AA JM81E TE_VAXELN_4.1_Runtime_Facilites_Guide_Mar90 TE VAXELN 4.1 Runtime Facilites Guide Mar90
AA-JM81E-TE_VAXELN_4.1_Runtime_Facilites_Guide_Mar90 AA-JM81E-TE_VAXELN_4.1_Runtime_Facilites_Guide_Mar90
User Manual: AA-JM81E-TE_VAXELN_4.1_Runtime_Facilites_Guide_Mar90
Open the PDF directly: View PDF .
Page Count: 790
Download | |
Open PDF In Browser | View PDF |
VAXELN Runtime Facilities Guide Order Number: AA-JM81 E-TE This manual is a guide to using the VAXELN runtime facilities. Revision/Update Information: This manual supersedes the VAXELN Runtime Facilities Guide, AA-JM81 D-TE. Operating System and Version: VMS, Version 4.7 or higher Software Version: digital equipment corporation maynard, massachusetts VAXELN, Version 4.1 Revised, March 1990 The information in this document is subject to change without notice and should not be construed as a commitment by Digital Equipment Corporation. Digital Equipment Corporation assumes no responsibility for any errors that may appear in this document. Any software described in this document is furnished under a license and may be used or copied only in accordance with the terms of such license. No responsibility is assumed for the use or reliability of software or equipment that is not supplied by Digital Equipment Corporation or its affiliated companies. Restricted Rights: Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1 )(ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013. © Digital Equipment Corporation 1986, 1987, 1988, 1989, 1990 All rights reserved. Printed in U.S.A. The Reader's Comments form at the end of this document requests your critical evaluation to assist in preparing future documentation. The following are trademarks of Digital Equipment Corporation: DATATRIEVE DDCMP DEC DECnet DECnet-VAX. DECwindows DELUA DEQNA DEUNA DHB32 DRB32 DRQ DSSI Industrial VAX IVAX KA KDA50 KDB50 Local Area VAXcl uster MASSBUS MicroVAX MS P/OS Q-bus Q22-bus RA RD RRD40 RSTS RSX RT rtVAX RX ThinWire TK TU UDA ULTRIX ULTRIX-32m UNIBUS VAX VAXBI VAXC VAXcluster VAXconsole VAXDEC/CMS VAXDECIMMS VAX DECtrest Manager VAX DOCUMENT VAXELN VAX FORTRAN VAX RdblELN VAX RdblVMS VAX Realtime Accelerator VAXRMS VAXstation VMS VT XMI XUI UNIX® is a registered trademark of American Telephone & Telegraph Company. X Window System, Version 11 and its derivations (X, X11, X Version 11, X Window System) are trademarks of the Massachusetts Institute of Technology. This document was prepared with VAX DOCUMENT, Version 1.2. S1339 Contents PREFACE xxv RUNTIME FACILITIES OVERVIEW 1-1 1.1 VAXELN RUNTIME ENVIRONMENT 1-2 1.2 VAXELN PROGRAMMING CONCEPTS 1.2.1 Processes: Execution Agents for Programs and Program Parts Jobs: Families of Processes 1.2.2 Concurrency: Processes Sharing Processor 1.2.3 Resources 1.2.3.1 Multitasking • 1-10 1.2.3.2 Multiprogramming • 1-10 1.2.3.3 Multiprocessing • 1-10 1-7 CHAPTER 1 1.3 CHAPTER 2 2.1 VAXELN RUNTIME FACILITIES 1.3.1 Kernel 1.3.2 Network Services 1.3.3 LAT Host Services 1.3.4 Authorization Service 1.3.5 File Service 1.3.6 Device Drivers 1.3.7 DECwindows Support THE VAXELN KERNEL KERNEL OBJECTS 2.1.1 AREA Objects 2.1.2 DEVICE Objects 2.1.3 EVENT Objects 1-8 1-8 1-9 1-14 1-14 1-15 1-15 1-16 1-16 1-17 1-17 2-1 2-2 2-4 2-6 2-7 iii 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2 CHAPTER 3 MESSAGE Objects NAME Objects PORT Objects PROCESS Objects SEMAPHORE Objects Kernel Object Implementation 2-8 2-9 2-10 2-12 2-13 2-14 OPTIMIZED DATA STRUCTURES 2.2.1 AREA_LOCK_VARIABLE Data Structure 2.2.2 MUTEX Data Structure 2-15 2-16 2-17 JOB, PROCESS, AND MEMORY MANAGEMENT 3-1 3.1 JOB ACTIVATION AND TERMINATION 3-3 3.2 SUBPROCESS ACTIVATION AND TERMINATION 3-4 3.3 SCHEDULING 3.3.1 Processes and Process States 3.3.2 Job and Process Scheduling 3.3.3 Initialization Programs and System Start-Up 3.3.4 Loading Programs 3.3.5 Scheduling in Multiprocessing Configurations 3-6 3-6 3-9 3-12 3-13 3-14 KERNEL SERVICES FOR PROCESSES AND JOBS CREATE_JOB Procedure CREATE_PROCESS Procedure CURRENT_PROCESS Procedure DELETE Procedure DISABLE_SWITCH Procedure ENABLE_SWITCH Procedure EXIT Procedure KER$GET_JCB Pr()cedure KER$GET_USER Procedure INITIALIZATION_DONE Procedure KER$NAME_OBJECT Procedure KER$RAISE_PROCESS_EXCEPTION Procedure 3-14 3-15 3-15 3-16 3-16 3-16 3-17 3-17 3-17 3-18 3-18 3-18 3-19 3.4 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.4.10 3.4.11 3.4.12 Iv 3.4.13 3.4.14 3.4.15 3.4.16 3.4.17 3.4.18 3.4.19 3.4.20 3.5 RESUME Procedure Setting a Job's Processor Eligibility SET_JOB_PRIORITY Procedure SET_PROCESS_PRIORITY Procedure KER$SET_USER Procedure SIGNAL Procedure SUSPEND Procedure WAIT_ANY and WAIT_ALL Procedures MEMORY MANAGEMENT 3.5.1 Managing Stack Usage 3.5.2 Allocating Memory 3.5.2.1 3.5.2.2 3.5.2.3 3.5.2.4 3.5.2.5 3.5.3 CHAPTER 4 3-19 3-19 3-20 3-21 3-22 3-22 3-22 3-23 3-23 3-27 3-29 ALLOCATE_MEMORY Procedure • 3-29 KER$ALLOCATE_SYSTEM_REGION Procedure • 3-30 FREE_MEMORY Procedure • 3-31 KER$FREE_SYSTEM_REGION Procedure • 3-31 KER$MEMORY_SIZE Procedure • 3-31 Loading VAXELN System Images onto KA800 Processors SYNCHRONIZATION 3-32 4-1 4.1 SYNCHRONIZING PROCESS EXECUTION 4-2 4.2 USING TIME VALUES TO SYNCHRONIZE PROCESS EXECUTION 4.2.1 Waiting on Time Retrieving and Setting the System Time 4.2.2 4-6 4-6 4.3 4.4 4-8 SYNCHRONIZING PROCESS EXECUTION BASED ON PROCESS COMPLETION 4-9 USING SEMAPHORES TO SYNCHRONIZE PROCESS EXECUTION 4.4.1 Creating Semaphores 4.4.2 Waiting On and Signaling Semaphores 4.4.3 Deleting Semaphores 4-10 4-11 4-12 4-14 v 4.4.4 4.5 Using Mutexes to Optimize Waiting and Signaling Operations USING EVENTS TO SYNCHRONIZE PROCESS EXECUTION Creating Events Waiting On, Signaling, and Clearing Events Deleting Events 4.5.1 4.5.2 4.5.3 CHAPTER 5 COMMUNICATION 4-15 4-16 4-16 4-18 5-1 5.1 SHARING MODULE-LEVEL DATA 5-1 5.2 SHARING PACKETS OF DATA USING QUEUES 5-4 5.3 PASSING MESSAGES Messages Message Ports Named Message Ports Message Transmission 5.3.4.1 Expedited Messages • 5-15 5.3.5 Datagrams and Circuits 5.3.6 Programming with Circuits 5.3.7 Port Limits and Flow Control 5.3.7.1 Flow Control with Unconnected Ports • 5-21 5.3.7.2 Flow Control with Circuits • 5-22 5.3.8 Programming Considerations for Message Communication 5.3.9 Kernel Services for Message Transmission 5.3.9.1 ACCEPT_CIRCUIT Procedure • 5-23 5.3.9.2 CONNECT_CIRCUIT Procedure • 5-24 5.3.9.3 CREATE_MESSAGE Procedure • 5-25 5.3.9.4 CREATE_NAME Procedure • 5-25 5.3.9.5 CREATE_PORT Procedure • 5-25 5.3.9.6 DELETE Procedure • 5-26 5.3.9.7 DISCONNECT_CIRCUIT Procedure • 5-26 5.3.9.8 JOB_PORT Procedure • 5-26 5.3.9.9 RECEIVE Procedure • 5-26 5.3.9.10 SEND Procedure • 5-27 5.3.9.11 TRANSLATE_NAME Procedure • 5-27 5.3.1 5.3.2 5.3.3 5.3.4 vi 4-14 5-10 5-11 5-12 5-13 5-14 5-16 5-17 5-21 5-22 5-23 5.3.9.12 5.4 SHARING 5.4.1 5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 CHAPTER 6 WAIT_ANY and WAITy.LL Procedures • 5-27 MEMORY AREAS Creating Areas Synchronizing Access to Areas with Events Synchronizing Access to Areas with Semaphores Using Area Lock Variables to Optimize Waiting and Signaling Operations Using Areas to Synchronize Job Execution Deleting Areas DEVICE HANDLING 5-28 5-30 5-33 5-39 5-40 5-41 5-46 6-1 6.1 CREATING AND DELETING DEVICE OBJECTS 6-3 6.2 HANDLING DEVICE INTERRUPTS 6.2.1 Waiting for an ISR to Service a Device Interrupt 6.2.2 Signaling the DEVICE Object After Service Completion 6-5 6-5 6-5 6.3 SYNCHRONIZING ACCESS TO THE DEVICE COMMUNICATION REGION 6-6 6.4 SETTING A DRIVER JOB'S PROCESSOR ELIGIBILITY 6-8 6.5 READING AND WRITING REGISTER DATA 6-9 6.6 CONTROLLING DMA DEVICES 6.6.1 Allocating, Loading, and Freeing Map Registers 6.6.2 Allocating and Freeing Buffered Data Paths 6.6.3 Mapping and Unmapplng Memory Buffers Returning a Variable's Physical Address 6.6.4 6-10 6-10 6-11 6-12 6-13 6.7 CODING VAXBI BUS DEVICE DRIVERS 6-13 6.8 EXECUTING ROUTINES IN KERNEL MODE 6-14 vii 6.9 HANDLING POWER-FAILURE RECOVERY CHAPTER 7 EXCEPTION HANDLING 7.1 7.2 7-1 VAX STACK ARCHITECTURE 7-1 7-4 7.2.1 7.2.2 7.2.3 7.2.4 EXCEPTIONS IN VAXELN SYSTEMS Exception-Handier Arguments Continue and Reslgnal Operations Unwind Operation Multiple Concurrent Exceptions 7-11 7.3.1 7.3.2 RAISING EXCEPTIONS Kernel Procedure Failure Exceptions Asynchronous Exceptions 7-11 7-11 7-11 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 EXCEPTION-HANDLING PROCEDURES DISABLE_ASYNCH_EXCEPTION Procedure ENABLE_ASYNCH_EXCEPTION Procedure RAISE_EXCEPTION Procedure KER$RAISE_PROCESS_EXCEPTION Procedure KER$UNWIND Procedure 7-12 7-12 7-12 7-13 7-13 7-13 7.5 STATUS CODES 7-13 7.6 USING RUNTIME MESSAGES IN APPLICATION PROGRAMS 7.6.1 VAXELN Message Flies 7.6.2 Constructing Messages 7.6.3 Using Message Files with Application Programs 7.6.4 Retrieving Message Text 7.6.5 Displaying VAXELN Message Text on VMS Systems 7-14 7-15 7-18 7-19 7-21 7-23 7.3 7.4 vIII 6-17 7-5 7-7 7-8 CHAPTER 8 ETHERNET/IEEE 802 DATALINK DRIVERS 8-1 8.1 ETHERNET/IEEE 802 DATAGRAM SERVICE 8-4 8.2 RETRIEVING A CSMAlCD LAN CONFIGURATION 8.2.1 Ethernet Controller Device Types 8.2.2 Ethernet Controller Device Names 8.2.3 Ethernet Controller Control Ports 8.2.4 Ethernet Controller Data Ports 8-7 8-8 8-9 8-9 8-9 8.3 RETRIEVING ETHERNET CONTROLLER ATTRIBUTES 8.3.1 Ethernet Controller Physical Addresses 8.3.2 Ethernet Controller Hardware Addresses 8-10 8-11 8-12 8.4 CONNECTING AND DISCONNECTING AN ETHERNET/IEEE 802 PROTOCOL 8.4.1 Portals 8.4.2 Dispatch Ports 8.4.3 Message Format and Multiplexing User Data 8.4.4 8.4.5 Promiscuous Mode 8.4.6 Multicast Addresses 8.4.7 Group SAPs 8.4.8 LLC Classes 8.4.9 Padded Ethernet Protocols 8-12 8-14 8-15 8-15 8-17 8-17 8-18 8-18 8-18 8-19 8.5 TRANSMITTING AND RECEIVING MESSAGES 8.5.1 Allocating a Message Buffer 8.5.2 Transmitting Messages 8.5.3 Retrieving Transmitted Messages 8.5.4 Receiving Messages 8-19 8-20 8-21 8-23 8-25 8.6 SETTING UP AN ETHERNET/IEEE 802 DATAGRAM SERVICE ENVIRONMENT 8-27 Ix CHAPTER 9 DECNET NETWORK SERVICES 9.1 NETWORK SERVICE PROTOCOLS 9-2 9.2 MESSAGE TRANSMISSION SERVICES 9-3 NAME SERVICE Name Server Kernel and Name Service Interaction Name Server Election 9-5 9-6 9-6 NETWORK MANAGEMENT SERVICES Managing VAXELN DECnet Systems from a VMS Host 9.4.1 System Testing the Network Service 9.4.2 Using the Network Management Service 9.4.3 Initializing DECnet Node Addresses at 9.4.3.1 Runtime • 9-13 9.4.3.2 Stopping and Starting DECnet Software to Reduce Network Overhead • 9-14 Switching DECnet Software Between Ethernet 9.4.3.3 Controllers • 9-16 9.4.4 Using the Down-Line Load Service Establishing Circuits for Down-Line Load 9.4.4.1 Service Communication • 9-20 Managing and Monitoring Data Base Node 9.4.4.2 Entries • 9-21 9.4.4.3 Managing and Monitoring Data Base Line Entries • 9-28 Managing Target-Initiated Down-Line Load 9.4.4.4 Requests • 9-35 9.4.4.5 Trigger Booting a VAXELN Target Node • 9-36 9.4.4.6 Down-Line Loading VAXELN Systems • 9-40 9-8 9.3 9.3.1 9.3.2 9.3.3 9.4 9.5 x 9-1 SERVICES FOR COMMUNICATING WITH VMS NODES Specifying Nodes 9.5.1 Using Node Names and Node Numbers in 9.5.1.1 VMS • 9-46 9.5.1.2 Using Node Numbers in VAXELN • 9-47 Requesting Connections from VAXELN Systems 9.5.2 9-7 9-9 9-10 9-11 9-18 9-44 9-45 9-47 9.5.3 9.5.4 9.5.5 9.5.6 9.6 Accepting Connections on VMS Systems Requesting Connections from VMS Systems Accepting Connections on VAXELN Systems Using DECnet Object Numbers in Connection Requests REMOTE TERMINAL UTILITY CHAPTER 10 INTERNET SERVICES 9-48 9-48 9-48 9-49 9-49 10-1 INTERNET SERVICE CONCEPTS 10.1.1 Client-Server Model 10.1.2 Internet Architecture 10.1.2.1 Internet Protocol • 10-5 10.1.2.2 User Datagram Protocol • 10--6 10.1.2.3 Transmission Control Protocol • 10-7 10.1.3 Internet Addresses 10.1 .3.1 Network Classes • 10-9 10.1.3.2 Network Mask • 10-12 10.1 .3.3 Broadcast Mask • 10-13 10.1.4 Ports as Internet Communication Endpoints 10.1.5 Sockets 10.1.5.1 Connection Socket Communication • 10-16 10.1.5.2 Connectionless Socket Communication • 10-17 10.1.6 Routing 10.1.7 Fragmentation 10-18 10-23 10.2 CONFIGURING INTERNET SERVICES 10-23 10.3 CONTROLLING INTERNET SERVICES 10.3.1 Managing the ARP Cache 10.3.1.1 Adding and Deleting ARP Cache Entries • 10-26 10.3.1.2 Retrieving Ethernet Addresses from the ARP Cache • 10-27 10.3.1 .3 Retrieving ARP Cache Entries • 10-28 10-25 10-25 10.1 10-2 10-3 10-3 10-9 10-14 10-15 xi 10.3.2 10.3.3 10.3.4 10.3.5 10-31 10-40 10-44 10-48 CONVERTING THE BYTE ORDER OF NETWORK AND HOST BINARY DATA 10-53 10.5 MANIPULATING INTERNET ADDRESSES 10-54 10.6 PROGRAMMING INTERNET COMMUNICATION Creating Sockets 10.6.1 Binding Names to Sockets 10.6.2 Controlling Socket Characteristics 10.6.3 Establishing Connections for Socket Communication 10.6.4 10.6.4.1 Initiating Socket Connections • 10-62 Creating a Queue for Pending Connection 10.6.4.2 Requests • 10-64 10.6.4.3 Accepting Socket Connections • 10-65 10.6.5 Transferring Data 10.6.5.1 Sending Data to Sockets • 10-66 10.6.5.2 Receiving Data from Sockets • 10-70 10.6.5.3 Polling Sockets for I/O Activity • 10-73 Shutting Down Sockets 10.6.6 10.6.7 Closing Sockets Programming Socket Communication for a UDP 10.6.8 Application Programming Socket Communication for a TCPIIP 10.6.9 Application 10-55 10-57 10-58 10-60 10-62 RETRIEVING AND SETTING SOCKET CHARACTERISTICS 10.7.1 Retrieving Socket Names 10-91 10-91 10.4 10.7 xII Managing the Internet Routing Table Adding and Deleting Routing Table 10.3.2.1 Entries • 10-31 Checking the Status of Routing Table 10.3.2.2 Entries • 10-34 10.3.2.3 Retrieving Routing Table Entries • 10-37 Managing Internet Network Interfaces 10.3.3.1 Setting Internet Network Interfaces • 10-40 Retrieving Internet Network Interface 10.3.3.2 Characteristics • 10-42 Retrieving Internet Performance and Error Data Retrieving TCP Connection Data 10-66 10-75 10-76 10-77 10-84 10.7.2 10.7.3 CHAPTER 11 Setting Socket Characteristics Retrieving Socket Options 10-92 10-93 LAT HOST SERVICES 11-1 11.1 LAT HOST SERVICES OVERVIEW 11-1 11.2 ESTABLISHING CIRCUITS FOR LAT COMMUNICATION 11.2.1 Connecting to a LAT Control Port 11.2.2 Creating a VAXELN LAT Port 11.2.3 Connecting to a DDA Port 11-4 11-5 11-7 11-9 11.3 MANAGING VAXELN SERVICE NODES 11.3.1 Retrieving and Setting Service Node Characteristics 11.3.1.1 Node Names • 11-14 11.3.1.2 Node Identification Strings • ·11-15 11.3.1.3 LAT Network Groups • 11-15 11.3.1.4 Multicast Timer • 11-16 11.3.1.5 Service Node States • 11-16 11.3.2 Managing Service Node Services 11.3.2.1 Creating and Deleting Services • 11-17 11.3.2.2 Changing Service Characteristics • 11-20 11.3.2.3 Advertising Services • 11-21 11.3.3 Retrieving LAT Port Characteristics 11.3.3.1 LAT Port Names • 11-24 11.3.3.2 Queue Statuses • 11-25 11.3.3.3 Remote Server Names • 11-25 11.3.3.4 Remote Port Names • 11-25 11.3.4 Retrieving Terminal Server Characteristics 11.3.5 Monitoring LAT Network Performance and Error Statistics 11-27 11.4 SETTING UP A DEDICATED SERVICE ENVIRONMENT 11-29 11.5 SETTING UP AN APPLICATION DEVICE ENVIRONMENT 11-36 11.6 RETRIEVING AND SETTING TERMINAL CHARACTERISTICS 11-43 11-12 11-12 11-17 11-23 11-25 xiii CHAPTER 12 SYSTEM SECURITY 12.1 SECURITY FEATURES OVERVIEW 12-1 12.2 USER NAMES AND IDENTIFICATION CODES 12-2 12.3 AUTHORIZATION SERVICE 12.3.1 Including the Authorization Service 12.3.2 Authorization Service Utility Procedures 12.3.3 Establishing Circuits for Authorization Service Communication 12.3.4 Adding Users to the Authorization Data Base 12.3.5 Modifying Records In the Authorization Data Base Removing User Records from the Authorization Data 12.3.6 Base 12.3.7 Retrieving Authorization Data Base Information 12-3 12-6 12-7 12-13 12-14 12.4 USER IDENTITIES 12-16 12.5 FILE SERVICE SECURITY 12-19 CHAPTER 13 12-8 12-9 12-11 FILE SERVICE 13-1 13.1 DEVICE SPECIFICATIONS 13-2 13.2 VOLUME NAMES 13-3 13.3 FILE SPECIFICATIONS 13-5 13.4 PROCEDURE FOR MOUNTING MULTIPLE VOLUMES WITH IDENTICAL VOLUME LABELS 13-6 DISK$DEFAULT_VOLUME DEVICE NAME 13-8 13.5 xiv 12-1 13.6 FILE ACCESS LISTENER 13.7 FILE SERVICE VOLUMES FROM VMS 13-10 13.8 FILE SERVICE OPERATIONS 13-10 13.9 FILE UTILITY PROCEDURES 13.9.1 ELN$COPY_FILE Procedure 13.9.2 ELN$CREATE_DIRECTORY Procedure 13.9.3 ELN$DELETE_FILE Procedure 13.9.4 ELN$DIRECTORY_CLOSE Procedure 13.9.5 ELN$DIRECTORY_LIST Procedure 13.9.6 ELN$DIRECTORY_OPEN Procedure 13.9.7 ELN$PROTECT_FILE Procedure 13.9.8 ELN$RENAME_FILE Procedure 13.9.9 ELN$SET_DEFAULT_FILESPEC Procedure 13-11 13-11 13-12 13-12 13-13 13-13 13-13 13-14 13-15 13-15 13.10.1 13.10.2 13.10.3 DISK UTILITY PROCEDURES ELN$DISMOUNT_VOLUME Procedure ELN$INIT_VOLUME Procedure ELN$MOUNT_VOLUME Procedure 13-15 13-16 13-16 13-17 13..11 TAPE UTILITY PROCEDURES 13.11.1 ELN$DISMOUNT_TAPE_VOLUME Procedure 13.11.2 ELN$INIT_ TAPE_VOLUME Procedure 13.11.3 ELN$MOUNT_ TAPE_VOLUME Procedure 13-17 13-18 13-18 13-18 13.12 FILE SERVICE INTERFACE FOR DISK AND TAPE DRIVERS 13-19 DATA ACCESS PROTOCOL DAP General Principles Action Routines and DAP$SERVER DAP Data Types DAP Constants DAP Wildcard Functions 13-21 13-24 13-25 13-26 13-26 13-27 13.10 13.13 13.13.1 13.13.2 13.13.3 13.13.4 13.13.5 13-9 xv CHAPTER 14 VAXELN DEVICE DRIVERS 14-1 14-3 14-3 14-6 14-7 14-7 DISK DRIVERS 14.1.1 Logical 1/0 Disk Specifications 14.1.2 Disk Driver Interface to the File Service 14.1.3 Recovery from Power Failure 14.1.4 Direct Device Access for Disk Devices 14.1.5 14.1.5.1 Establishing Circuits for the DDA Disk Interface • 14-8 Reading Data from and Writing Data to a 14.1.5.2 Local Disk • 14-9 Reading Logical Blocks from an Unmounted 14.1.5.3 Disk • 14-12 Reading Logical Blocks from a Mounted 14.1.5.4 Disk • 14-15 14.1.5.5 Transferring Data to a System Region • 14-20 14.1.6 Virtual-Memory Disk Driver 14-24 14.2 TAPE DRIVER 14.2.1 Logical 1/0 14.2.2 Tape SpeCifications 14.2.3 Tape Driver Interface to the File Service 14.2.4 Recovery from Power Fall ure 14.2.5 Recovery from Errors 14-27 14-27 14-28 14-28 14-29 14-29 14.3 PRINTER DRIVERS 14.3.1 Accessing Printer Devices 14.3.2 Printer Driver Characteristics 14-29 14-30 14-31 14.4 TERMINAL DRIVERS 14.4.1 Terminal 1/0 14.4.2 Type-Ahead and Synchronization 14.4.3 Terminating Lines of Input 14.4.4 Setting Up Polnt-to-Point DDCMP Communication 14-32 14-35 14-35 14-36 14-36 14~1 xvi 14-1 14.4.5 14.4.6 14.4.7 14.4.8 14.4.9 14.5 Direct Device Access for Serial-Line Devices Establishing Circuits for Serial-Line 14.4.5.1 Communication • 14-41 14.4.5.2 Retrieving and Setting Terminal Characteristics • 14-41 14.4.5.3 Reading Data from and Writing Data to a Serial Line • 14-48 14.4.5.4 Setting a Serial Line to the Spacing State • 14-57 14.4.5.5 Monitoring the Use of Out-of-Band Characters • 14--59 Using Control Characters USing Escape and Control Sequences 14.4.7.1 Using VT52-Type Escape Sequences • 14-66 Using Modem Control 14.4.8.1 Retrieving and Setting Modem Characteristics • 14--68 14.4.8.2 Monitoring Modem Events • 14--69 Performing Parallel 1/0 SMALL COMPUTER SYSTEM INTERFACE DRIVER 14.5.1 Using the VAXELN SCSI Disk Class Driver 14.5.2 Using the VAXELN SCSI Generic Class Driver 14.5.2.1 Connecting to the Generic Class Driver • 14-78 Requesting SCSI Bus Configuration 14.5.2.2 Data • 14-80 14.5.2.3 Connecting to SCSI Devices • 14-83 14.5.2.4 Issuing SCSI Commands • 14-85 14.5.2.5 Programming a Generic Class Driver Message Interface Application • 14-91 14.5.3 Developing User-Defined SCSI Class Drivers 14.5.3.1 Modifying the SCSI Driver Start-Up Module • 14-114 14.5.3.2 Programming SCSI Class Drivers • 14-116 14.5.3.2.1 Defining Device Locks • 14-119 14.5.3.2.2 Setting Up an Entry Point • 14-120 14.5.3.2.3 Checking for Devices to Service • 14-121 14.5.3.2.4 Setting the Current Connection Flag • 14-121 14.5.3.2.5 Allocating 110 Request Packets for Devices • 14-122 14-39 14-62 14-64 14-66 14-73 14-73 14-76 14-n 14-110 xvii Mapping Data Buffers for I/O Requests • 14-123 Issuing SCSI Commands • 14-125 14.5.3.2.7 14.5.3.2.8 Initializing a SCSI Device Controller • 14-127 14.5.3.3 Compiling and Linking the SCSI Driver Modules • 14-128 14.5.3.2.6 14.6 REALTIME DEVICE DRIVERS 14.6.1 ADQ32 DMA Analog-to-Digital Converter 14.6.2 ADV11-C/AXV11-C Analog-to-Digital Converter 14.6.3 ADV11-D DMA Analog-to-Digital Converter 14.6.4 DLVJ1 Asynchronous Serial-line Controller 14.6.5 DRB32 DMA Parallel-Line Interface 14.6.6 DRQ3B DMA Parallel-Line Interface 14.6.7 DRV11-J Parallel-Line Interface 14.6.8 DRV11-W DMA Parallel-Line Interface 14.6.9 IEQ11-A and IEU11-A Dual IEC/IEEE Instrument Bus Interfaces 14.6.10 KWV11-C Realtime Clock 14-128 14-130 14-131 14-133 14-134 14-136 14-140 14-142 14-144 14-146 14-150 APPENDIX A STATUS VALUES/EXCEPTION NAMES A-1 APPENDIX B MACHINE·CHECK STACK FRAMES B-1 B.1 OBTAINING A MACHINE-CHECK STACK FRAME B-2 B.2 MACHINE-CHECK STACK FRAME FOR MICROVAX I PROCESSORS B-4 B.3 MACHINE-CHECK STACK FRAME FOR MICROVAX II AND 2000, VAXSTATION II AND 2000, AND KA800 PROCESSORS B-6 MACHINE-CHECK STACK FRAME FOR RTVAX 300, MICROVAX 3NNN SERIES, VAXSTATION 3100, 3200, AND 3500, AND VAX 6000-2NN AND 6000-3NN SERIES PROCESSORS B-7 B.4 xviii B.5 MACHINE-CHECK STACK FRAME FOR VAX 6000-4NN SERIES PROCESSORS B-10 MACHINE-CHECK STACK FRAME FOR VAX 8200· AND 8250 PROCESSORS B-12 MACHINE-CHECK STACK FRAME FOR VAX 8500, 8550, 8700, 8800, AND 8810 PROCESSORS B-13 B.8 MACHINE-CHECK STACK FRAME FOR VAX-11rl30 PROCESSORS B-15 B.9 MACHINE-CHECK STACK FRAME FOR VAX-11rl50 PROCESSORS B-17 B.6 B.7 APPENDIX C VMS EMULATION ROUTINES C-1 C.1 VMS EMULATION ROUTINE SUMMARY C-1 C.2 CALLING VMS EMULATION ROUTINES C-4 C.3 VMS SYSTEM SERVICE EMULATION ROUTINE DESCRIPTIONS C-7 C.4 L1B$ EMULATION ROUTINE DESCRIPTIONS C-9 C.5 STR$ EMULATION ROUTINE DESCRIPTION C-25 APPENDIX D SCSI PORT DRIVER INTERFACE ROUTINES PORT$ALLOCATE_DEVICE PORT$EXIT_HANDLER PORT$FREE_DEVICE PORT$INITIALlZE_CONTROLLER PORT$ISSUE_COMMAND PORT$MAP_BUFFER PORT$UNMAP_BUFFER D-1 D-3 D-7 D-10 D-13 D-16 D-20 D-24 xix Index-1 INDEX EXAMPLES 5-1 5-2 5-3 Using Queues for Process Communication Disconnecting the Partner Port After a Disconnect Operation Synchronizing Access to Areas with Events 5-4 Synchronizing Job Execution with Semaphores 6-1 7-1 8-1 Using the KER$ENTER_KERNEL_CONTEXT Procedure Using Message Flies Sample Network Interface Application 9-1 Managing and Monitoring Down-Line Load Data Base Node Entries Managing and Monitoring Down-Line Load Data Base Line Entries Trigger Booting a VAXELN Target Node Down-Line Loading a VAXELN System Image 9-2 9-3 9-4 10-1 10-2 10-3 10-4 11-1 11-2 14-1 14-2 14-3 14-4 14-5 14-6 14-7 14-8 14-9 14-10 xx 5-6 5-20 5-34 5-42 6-16 7-20 8-29 9-24 9-31 9-39 Sample TCP/IP Client LAT Dedicated Service 9-43 10-78 10-82 10-85 10-88 11-31 LAT Application Service Reading Logical Blocks from an Unmounted Disk Reading Logical Blocks from a Mounted Disk 11-38 14-12 14-15 Transferring Data to a System Region Using the Virtual-Memory Driver Reading and Writing Serial-Line Data Reading and Writing Serial-Line Data Using a User-Defined Message Monitoring the Use of Out-of-Band Characters Monitoring Modem Events Programming a SCSI Generic Class Driver Message Interface Application Modifying the SCSI Driver Start-Up Module 14-21 14-25 14-52 Sample UDP Server Sample UDP Client Sample TCP/IP Server 14-54 14-61 14-71 14-92 14-115 FIGURES 1-1 1-2 1-3 1-4 1-5 1-6 1-7 1-8 2-1 3-1 3-2 3-3 3-4 3-5 3-6 3-7 7-1 7-2 7-3 7-4 7-5 8-1 9-1 9-2 9-3 9-4 10-1 10-2 10-3 10-4 11-1 11-2 A VAXELN Application VAXELN System Software Runtime Environment Process Family Loosely Coupled Multiprocessing Configuration Tightly Coupled Symmetric Multiprocessing Configuration Closely Coupled Symmetric Multiprocessing Configuration with VAXELN Primary System Closely Coupled Symmetric Multiprocessing Configuration with VMS Primary System PORT Value Representation Valid Process State Transitions Job and Process Priorities Combined Priority Representation Memory Allocation System Region Program Region Control Region A Procedure's Stack Frame A Frame Structure After a Procedure Call Call Frame Block Signal Arguments Mechanism Arguments A Two-Node VAXELN Network Using the Datagram Service A Two-Node VAXELN Network Using the Network Service Target-Initiated Down-Line Load Request Trigger Boot Request Down-Line Load Request Client-Server Model Internet Layers Routing Table Routing Algorithm Sample VAXELN LAT Configuration VAXELN LAT Port 1-2 1-4 1-5 1-9 1-11 1-12 1-13 1-13 2-11 3-8 3-10 3-11 3-24 3-25 3-25 3-27 7-3 7-3 7-4 7-6 7-7 8-5 9-4 9-35 9-37 9-40 10-3 10-4 10-19 10-20 11-3 11-9 xxi 11-3 11-4 11-30 Dedicated Service Environment Application Device Environment 11-37 12-1 Authorization Service Example 12-2 Protection Mask 13-1 14-1 DAP Message Transmission (Read Request) 13-22 A VAXELN Serial DDCMP Link 14-37 14-2 SCSI Class/Port Driver Architecture 14-3 SCSI Device Markers 12-4 12-20 14-75 14-114 B-1 Machine-Check Stack Frame for MlcroVAX I Processors B-4 B-2 Machine-Check Stack Frame for MicroVAX II and 2000, VAXstation II and 2000, and KA800 Processors B-6 B-3 B-4 Machine-Check Stack Frame for rtVAX 300, MicroVAX 3nnn Series, VAXstatlon 3100,3200, and 3500, and VAX 6000-2nn and 6000-3nn Series Processors Machine-Check Stack Frame for VAX 6000-4nn Series Processors B-8 B-10 B-5 Machine-Check Stack Frame for VAX 8200 and 8250 Processors B-12 B-6 B-13 B-7 Machine-Check Stack Frame for VAX 8500, 8550, 8700, 8800, and 8810 Processors Machine-Check Stack Frame for VAX-111730 Processors B-8 Machine-Check Stack Frame for VAX-111750 Processors B-17 - B-15 TABLES xxii 1-1 Runtime System Components 1-6 2-1 Kernel Objects 2-4 2-16 2-2 Optimized Data Structures 3-1 6-1 Process States Interrupt Priority Levels 3-7 6-6 7-1 8-1 VAXELN Message Files 7-16 Ethernet/IEEE 802 Datalink Drivers 8-2 8-2 Ethernet Controller Device Types 8-8 8-3 8-4 9-1 9-2 10-1 10-2 Portal Message Formats 8-15 Portal Multiplexing Fields 8-17 Down-Line Load Data Base Node Characteristics 9-21 Down-Line Load Data Base' Line Characteristics UDP Characteristics 9-29 10-6 TCP Characteristics 10-8 Network Class Number Ranges 10-11 10-4 Broadcast Addresses 10-14 10-5 Socket Protocol Types 10-16 10-6 Calling Sequence for Socket Communication 10-56 10-7 Socket-Level Socket Options 10-92 13-1 Storage Device Types 10-3 13-3 14-1 Disk Drivers 14-1 14-2 Disk Devices 14-3 14-3 Tape Specifications 14-28 14-4 Printer Drivers 14-29 14-5 Printer Driver Characteristics 14-31 14-6 Terminal Drivers 14-32 14-7 Terminal Driver Characteristics 14-41 14-8 Control Characters 14-63 14-9 Modem Control Signals 14-67 14-10 Modem Characteristics 14-68 14-80 14-11 SCSI Device Characteristics 14-12 VAXELN SCSI Driver Components 14-13 SCSI Bus Configuration Data 14-112 14-14 Realtime Devices 14-128 A-1 Status Values/Exception Names A-1 B-1 Machine-Check Type Codes for MicroVAX I Processors B-5 B-2 Machine-Check Type Codes for MicroVAX II and 2000, VAXstation II and 2000, and KA800 Processors B-7 Machine-Check Type Codes for rtVAX 300, MicroVAX 3nnn Series, VAXstation 3100,3200, and 3500, and VAX 6000-2nn and 6000-3nn Series Processors B-9 B-3 14-111 8-11 B-4 Machine-Check Type Codes for VAX 6000-4nn Series Processors B-5 Machine-Check Stack Frame Contents for VAX 8500, 8550, 8700, 8800, and 8810 Processors B-14 B-6 Machine-Check Error Type Codes for VAX-111730 Processors 8-15 8-18 - B-7 Machine-Check Error Codes for VAX-11n50 Processors C-1 VMS System Service Emulation Routines 0-2 C-2 VMS Runtime Library Emulation Routines 0-2 xxiii Preface The VAXELN Runtime Facilities Guide describes the VAXELN runtime software and explains how to use it to produce dedicated, realtime VAXELN systems. The manual provides a language-independent discussion of the VAXELN Toolkit's runtime facilities. It explains VAXELN programming concepts and describes runtime features that you program and build into VAXELN systems. For information about developing and monitoring VAXELN systems, see the VAXELN Development Utilities Guide. Intended Audience This manual is for programmers and students who have a working knowledge ofPascal,C, or FORTRAN. Knowledge of the VMS operating system and a cursory understanding of the Digital command language (DCL) is recommended. Some information in this manual requires a more extensive understanding of the VMS operating system. In such cases, this manual directs you to appropriate documentation for additional information. xxv Document Structure This manual consists of 14 chapters and 4 appendixes, organized as follows: . • • • • • • • • • xxvi Chapter 1, Runtime Facilities Overview, provides general information about the runtime facilities and their role in an executing application. Chapter 2, The VAXELN Kernel, introduces the VAXELN Kernel and describes the kernel data structures. Qhapter 3, Job, Process, and Memory Management, explains how VAXELN application programs can manage processes, jobs, and memory. The kernel's roles in scheduling and memory allocation are discussed in this chapter. Chapter 4, Synchronization, explains how to use kernel objects, optimized structures, and related procedures to synchronize processes. Chapter 5, Communication, explains how to use kernel objects and related procedures to program interprocess and inteIjob communication. Chapter 6, Device Handling, explains how to use the kernel DEVICE object, related kernel procedures, and interrupt service routines in programs that handle device interrupts. This chapter also discusses recovery from power failure and direct memory access UNIBUS and Q-bus device handling. Chapter 7, Exception Handling, explains how to handle exceptions from your VAXELN programs. This chapter also discusses status codes and message-processing features that handle the conversion of status codes into message text. Chapter 8, EthernetlIEEE 802 Datalink Drivers, describes the EthernetlIEEE 802 datalink drivers and Datagram Service and explains how to use the Datagram Service. Chapter 9, DECnet Network Services, describes the VAXELN Network Service. • • • • • • • • • Chapter 10, Internet Services, explains how to use the VAXELN Internet Services. Chapter 11, LAT Host Services, explains how to establish virtual circuits for local area transport communication, manage VAXELN service nodes, and set up dedicated service and application device environments. Chapter 12, System Security, explains how to include security features in your VAXELN systems for protecting resources and data. Chapter 13, File Service, describes the VAXELN File Service and explains how to use file, disk, and tape utility procedures in your application programs. Chapter 14, VAXELN Device Drivers, describes the disk, virtual memory, tape, printer, terminal, and realtime device drivers that VAXELN supplies. Appendix A, Status ValueslException Names, lists the status values/exception names that VAXELN defines. Appendix B, Machine-Check Stack Frames, explains how to manually obtain and interpret a machine-check stack frame, in case a machine check occurs on a VAXELN target processor in an application that does not include the error-logging service. Appendix C, VMS Emulation Routines, identifies the VMS runtime library and system service emulation routines that the VAXELN Toolkit supports. Appendix D, SCSI Port Driver Interface Routines, describes the VAXELN SCSI port driver interface routines that you can use to program user-written SCSI class drivers for third-party SCSI devices. Conventions The following conventions are used in this manual: Convention Meaning UPPERCASE characters VMS, VAXELN, and language-specific reserved words and identifiers are printed in uppercase characters. xxvii Convention Meaning italic characters The following items are printed in italic characters: • Elements for which you supply a value. For example: • User-defined elements in code examples when these elements are used in text. For example: The geCattributes argument ... System Builder menu entry values when they appear in text. For example: Select Yes for the Console entry on the System Characteristics Menu. First occurrence of a new term. nodename::"TAS~portname" • • bold characters The following items are printed in bold characters: • • red characters System Builder menu entries when they appear in text. For example: Select Yes for the Console entry on the System Characteristics Menu. Case-sensitive C language elements, such as keywords, macros, modules, and procedures, when they appear in text. For example: The definition module $vaxelnc ... In interactive examples, elements for which you must supply input. For example: $ SHOW NETWORK [ ] Square brackets enclose optional items. For example: SHOW NODE node-id [SUMMARY] [COUNTERS] Square brackets are also used in the syntax of a directory name in a VMS file specification and in user identification code (UIC) specifications. When an item is followed by horizontal ellipsis points, you can repeat the item one or more times. Vertical ellipsis points in a figure or example indicate that not all the information the system displays is shown or that not all the information a user is to supply is shown. xxviii Convention Meaning /Ctrllx / indicates a control key sequence. Press the key la- beled Ctrl while you simultaneously press another key. For example: /CtrI/C/ n and x When used in items such as names, the variables n and x represent numeric and nonnumeric characters, respectively. For example: VAX 6000-2nn series systems Associated Documents The following documents are relevant to programming VAXELN applications using the VAXELN runtime facilities: VAXELN Documents: • • • • • • • • • • • • • • • VAXELN Release Notes VAXELN Installation Guide Introduction to VAXELN VAXELN Development Utilities Guide VAXELN Runtime Facilities Guide VAXELN Application Design Guide VAXELN Pascal Language Reference Manual VAXELN Pascal Runtime Library Reference Manual VAXELN C Reference Manual VAXELN C Runtime Library Reference Manual VAXELN FORTRAN Runtime Library Reference Manual VAXELN Pocket Reference VAXELN Messages Manual VAXELN Guide to DECwindows VAXELN Master Index and Glossary xxix VAX Documents: • • • VAX Architecture Reference Manual VAX Hardware Handbook Guide to VAX Language-Sensitive Editor and VAX Source Code Analyzer VMS Documents: • • • • • • • • • • • • • • • • • • • • Guide to Creating VMS Modular Procedures Guide to Maintaining a VMS System Introduction to VMS Introduction to the VMS Run-Time Library Introduction to VMS System Management Introduction to VMS System Services VMS Authorize Utility Manual VMS DCL Dictionary VMS Error Log Utility Manual VMS I/O User's Reference Volume VMS Librarian Utility Manual VMS License Management Utility Reference Manual VMS Linker Utility Manual VMS Message Utility Manual VMS Network Control Program Reference Manual VMS Networking Manual VMS RTL Library (LIB$) Manual VMS RTL String Manipulation (STR$) Manual VMS Run-Time Library Routines Volume VMS System Services Reference Manual DECnet Documents: • • • • xxx DECnet DIGITAL Network Architecture General Description DECnet-VAX System Manager's Guide DECnet-VAX User's Guide Guide to DECnet-VAX Networking Hardware Documents: • • • • • • • • • • • • • • • • • • ADQ32 A/D Converter Module User's Guide DLVll-J User's Guide DRB32 Hardware Manual DRB32 Technical Manual DRQ3B Parallel DMA I/O Module User's Guide DRll-W Direct Memory Access Interface User's Guide IEUll-A/IEQll-A User's Guide IEXll-A IEC/IEEE Bus Interface KFQSA Installation Guide Micro VAX I O·wner's Manual Micro VAX II Owner's Manual LSI-ll Analog System User's Guide Q-bus DMA Analog System User's Guide American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) Small Computer System Interface: An Overview Small Computer System Interface: A Developer's Guide VAX 8800 Console Manual VAX 8nnn Console Manual VAX RTA Documents: • • VAX Real-Time Accelerator Hardware/Software Installation Guide VAX Real-Time Accelerator Software User's Guide The VAXELN Internals and Data Structures manual is also available as a separate document. This manual describes the internal data structures and operations of the VAXELN Kernel and its associated subsystems. xxxi Chapter 1 Runtime Facilities Overview The VAXELN Toolkit is a VMS layered product that provides software for developing dedicated, realtime software applications that run on VAX processors. A dedicated application uses a computer to solve a specific problem or set of related problems. A typical dedicated .application takes advantage of VAXELN realtime capabilities, which give prompt, predictable responses to time-critical events. The VAXELN Toolkit's low-overhead design caters to these application needs by applying the VAX processor's speed and responsiveness. Typical examples of dedicated, realtime applications include the following: • • • • • • • Computer integrated manufacturing Process control Simulations Data acquisition and analysis File and print servers Communication switching systems Multifaceted professional workstations VAXELN systems.are only as complex as they need to be; they are statically defined and include only those services necessary to support the functions required by your application. You develop a VAXELN application on a VAX host processor using VMS software and VAXELN development tools. The resulting VAXELN system includes user and Digital program images that reside in the memory of and run independently on a supported VAX target processor. Figure 1-1 shows a typical VAXELN application. Runtime Facilities Overview 1-1 Figure 1-1: A VAXELN Application VAX Target Processor User Devices Ethemet MLO-004265 This chapter provides information about the following: • • • The VAXELN runtime environment, Section 1.1 Basic VAXELN programming concepts, Section 1.2 Facilities provided by VAXELN runtime software, Section 1.3 For information about the VAXELN development and utility features, see the VAXELN Development Utilities Guide. 1.1 VAXELN Runtime Environment A VAXELN runtime environment consists of one or more VAX target processors running a VAXELN system image. The system image executes on the target processor as a dedicated application under the control of the kernel (see Section 1.3.1) and supplied services. The runtime hardware requirements include the following: • At least one of the target processors that the VAXELN Toolkit supports. For a list of supported target processors, see the help text for the System Builder's Target Processor Menu, or the latest VAXELN Toolkit System Support Addendum (SSA) or Software Product Description (SPD). 1-2 Runtime Facilities Overview • • Ethernet hardware if an application requires down-line loading, remote debugging, remote error logging, VAXELN Performance Utility, or remote VAXELN Command Language Utility support. Application-specific peripheral devices, such as disks, terminals, communications hardware, and special interfaces that Digital, a third party, or the programmer supplies. The target processor can exist as a standalone system or can be distributed on a local area network. A VAXELN system image includes user application program images and program images that Digital supplies. Typical user application programs, which you write in high-level languages, include data acquisition and reduction programs, process control supervisors, and user-written device drivers. The program images that Digital supplies include the VAXELN Toolkit's highly optimized kernel executives and images of the following: • • • • • • Runtime libraries Device drivers Services A server Runtime utilities A local debugger component Using the toolkit's System Builder, you combine the application program images and the program images that Digital supplies into a VAXELN system. When building the system, you can specify the programs that are to start executing as soon as you load and boot the system. Figure 1-2 presents the system image components in a hierarchical diagram. The diagram shows that the kernel executive is the heart of a VAXELN system; it schedules and controls an application's execution and access to system resources. The second tier of the diagram represents optional user and Digital software that provides kernel extensions. You tailor your VAXELN system by including only those services and utilities that Runtime Facilities Overview 1-3 Figure 1-2: VAXELN Sysiem Software your application requires. The outermost tier represents a VAXELN system's highest level of code: your application program images. After building your VAXELN system image, you can load and boot it onto the target processor from disk, tape, or read-only memory (ROM). If you have an optional DECnet-VAXlicense and the appropriate Ethernet hardware, you can down-line load the system image from the host processor to the target processor. The system image executes on the target processor independently under the control of the VAXELN Kernel and runtime services. Figure 1-3 shows a typical VAXELN runtime environment, and Table 1-1 briefly describes the system components that Digital supplies. 1-4 Runtime Facilities Overview Figure 1-3: Runtime Environment Target VAX Processor Kernel* User-Supplied Drivers Runtime Libraries User Module 1 Drivers Supplied by Digital User Module 2 System Image Network Service File Service Display Utility Local Debugger Component** VAXELN Toolkit Components * Required component **Usua/ly not included in final system User-Written Components MLO-004267 Runtime Facilities Overview 1-5 Table 1-1: Runtime System Components Component Description Kernell Controls the sharing of the target processor's resources. The System Builder includes the appropriate kernel for your target processor. Runtime Libraries Contain object modules and shareable images that support realtime, 110, math, DECwindows, and other routines called from VAXELN Pascal, VAX C, and VAX FORTRAN programs. Drivers Control communication between application programs and external devices. Network Service Controls data transmission between network nodes, manages a network name table, and provides a runtime interface for managing a DECnet network. EthernetlIEEE 802 Datagram Service Provides network interface routines that VAXELN application programs can use to communicate over a Carrier Sense Multiple Access/Collision Detect (CSMAlCD) LAN. Internet Services Provide an Ethernet network interface that VAXELN applications can use to communicate with other applications in an Internet network. File Service Provides support for file-oriented disk and tape 110 operations and remote file access. Error Logging Service Writes data that identifies hardware errors, volume changes, and system events to an error log file that exists on the local target system or on a remote system over the Ethernet. LAT Host Services Provide an interface that application programs can use to communicate with devices attached to terminal servers. DECwindows Server Provides a common means for DECwindows applications to interact with graphics workstations. 1A required component 1-6 Runtime Facilities Overview Table 1-1 (Cont.): Runtime System Components Component Description DECwindows User-Environment Provide Window Manager and terminal Components emulator support. Command Language Utility (ECL) Provides an interactive interface you can use to maintain files, execute programs, and control the runtime system environment. Display Utility (EDISPLAY) Displays system-level and job-specific resource information on a target system video terminal. Performance Utility Collector Collects application program performance data. Remote Terminal Utility Lets you connect to a remote computer system from a terminal on another computer system by using a SET HOST command LAT Control Program Utility (LATCP) Provides an interactive interface you can use to manage and monitor local area transport (LAT) service node characteristics and activities Local Debugger Component2 Lets you debug a VAXELN application from the target processor's console terminal. 2Usually not included in final system 1.2 VAXELN Programming Concepts A VAXELN application's design and development are based on the concept of concurrency, the simultaneous execution of multiple programs and parts of programs. Concurrency is a proven approach for applications that require cooperation among programs to solve specific problems quickly and efficiently. VAXELN programs execute as jobs. A typical VAXELN application consists of multiple jobs that each have functionally independent components called processes. Runtime Facilities Overview 1-7 1.2.1 Processes: Execution Agents for Programs and Program Parts A process is a functionally independent entity that provides the execution context for a program image or part of a program image. Each process in a VAXELN system represents a specialized task. The main section of program code (the program block for VAXELN Pascal programs, the main routine for C programs, and the main program for FORTRAN programs) executes as the master process. The kernel creates this process implicitly when the program starts executing. 1.2.2 Jobs: families of Processes Collectively, the processes associated with a running program constitute a job. A job consists of a master process and zero or more subprocesses that can execute concurrently. A job can be thought of as a family of processes. A job's master process and subprocesses create other subprocesses dynamically. Once created, a process stays active until it exits, another process deletes it, its master process terminates, it encounters an error from which it cannot recover, or it finishes executing the associated code segment. A programmed exit (see Section 3.2) is the most controlled means of forcing process termination. Figure 1-4 illustrates the creation and dependency paths for a process family consisting of a master process and five subprocesses. When a master process terminates under any circumstances, the kernel removes the corresponding job, its master process and associated subprocesses, and shared data from the system and replenishes the system's memory resources. 1-8 Runtime Facilities Overview Figure 1-4: Process Family Subprocess 2 Subprocess 4 Job Master Process 1 Subprocess 3 Subprocess 5 Subprocess 6 ----... Creation Path ------.. Dependency Path MLO-004268 1.2.3 Concurrency: Processes Sharing Processor Resources To take advantage of the VAXELN Toolkit's realtime efficiency, you design applications with the concept of concurrency in mind. Concurrency is built into the VAXELN software so that cooperating processes can share processor resources. While some processes wait for an event to occur or a resource to become available, other processes can execute. The kernel manages system resources so that all jobs and processes appear to execute simultaneously, although only one process actually executes on a processor at a time. You determine whether jobs and processes should execute concurrently when designing your application. Concurrent programming has numerous system design advantages, including improved performance. The VAXELN Kernel supports three levels of concurrency - multitasking, multiprogramming, and multiprocessing - which are described in Sections 1.2.3.1, 1.2.3.2, and 1.2.3.3, respectively. Runtime Facilities Overview 1-9 1.2.3.1 Multitasking Multitasking lets you divide an application program's functionality into a set of smaller, focused tasks that can execute concurrently. Each task executes as a separate dedicated process. For example, a program controlling a wing in an aircraft flight simulation application might consist of processes that specialize in tasks such as surface control and engine fire-up. 1.2.3.2 Multiprogramming Multiprogramming is the concurrent execution of entire programs, including multitasking programs. The programs execute as jobs that mayor may not run cooperatively; that is, Job A mayor may not depend on Job B. However, the jobs of most VAXELN systems work together to accomplish mutual goals. For example, in an aircraft flight simulation application, a collection of cooperating jobs might emulate major components of an airplane, such as cockpit controls and instrumentation, navigation equipment, and left and right wings. 1.2.3.3 Multiprocessing A VAXELN application's jobs can reside on one processor or they can be distributed among multiple processors. The concurrent execution of a VAXELN application's parts on multiple processors is called multiprocessing. The VAXELN Kernel supports the following multiprocessing configurations: • • • Loosely coupled symmetric multip~ocessing Tightly coupled symmetric multiprocessing Closely coupled symmetric multiprocessing In a loosely coupled symmetric configuration, an Ethernet device links the processors, as shown in Figure 1-5. Each processor runs its own system image with its own jobs. 1-10 Runtime Facilities Overview Figure 1-5: Loosely Coupled Multiprocessing Configuration Processor 1 Processor 2 Job A Job B Job E Job 0 Job F JobC VAXELN Processor 3 VAXELN VAXELN MLO-004269 In a tightly coupled symmetric configuration, the hardware supports multiple processors on the same CPU bus, as shown in Figure 1-6. VAXELN supports tightly coupled symmetric multiprocessing on VAX 6000 series and VAX 8800 multiprocessor configurations. All processors share a copy of the VAXELN runtime components and application images. A job can execute on any processor (the default) or you can limit it to a specific subset of processors. A closely coupled symmetric configuration consists of a VAX 6000 series, 8500, 8530, 8550, 8700, or 8800 primary system and one or more KA800 single-board computers (SBCs). The primary system can be a single processor or a tightly coulpled symmetric multiprocessing configuration. Each KA800 system is connected to the primary system's VAXBI bus and has its own copy of the VAXELN runtime components and application images. Closely coupled configurations provide limited data sharing capabilities. Data in the primary system's memory is shareable and can be accessed by the attached KA800 systems. However, the primary system cannot gain access to data that is in the memory of the KABOO systems. Runtime Facilities Overview 1-11 Figure 1-6: Tightly Coupled Symmetric Multiprocessing Configuration Processor 1 Job A Shared Memory Processor 2 Application Images JobS VAXELN MLO-004270 As shown in Figures 1-7 and 1-8, the primary processor in a closely coupled environment can run a VAXELN or VMS system. When the primary processor is running a VAXELN system, you down-line load VAXELN systems into the KA800 processors by using a configuration file, a runtime procedure call, or an EeL command. When the primary processor is running a VMS system, you use VAX Real-time Accelerator (RTA) software to load, control, and communicate with VAX RTA KA800 processors. For information about VAX RTA, see the VAX Real-Time Accelerator Hardware/Software Installation Guide and VAX Real-Time Accelerator Software User's Guide. A common application for closely coupled multiprocessing is to distribute realtime 1/0 functions. You can achieve superior performance by offloading interrupt-intensive tasks to KA800 processors, freeing the primary processor for other functions. The KA800 processors can directly control the DRB32 direct memory access (DMA) parallel port device to distribute 1/0 control for high-speed data transfers and fast, predictable interrupt response time. 1-12 Runtime Facilities Overview Figure 1-7: Closely Coupled Symmetric Multiprocessing Configuration with VAXELN Primary System User Device VAX 8800 KA800 Application Images Job A Job D KA800 Loader JobC VAXELN VAXELN Global Memory Shared Data DMA Buffers KA800 KA800 JobG JobB Job E VAXELN HighSpeed Parallel Interface JobF JobH VAXELN MLO-004271 Figure 1-8: Closely Coupled Symmetric Multiprocessing Configuration with VMS Primary System User Device VAX 8800 KA800 Application Images Job A Job D VAXATA VMS JobC VAXELN Global Memory Shared Data DMA Buffers KA800 KA800 JobG Job B Job E VAXELN HighSpeed Parallel Interface JobF JobH VAXELN MLO-004272 Runtime Facilities Overview 1-13 1.3 VAXELN Runtime Facilities The VAXELN runtime components provide a rich software environment for programming dedicated realtime applications. These components consist of a kernel executive and a variety of runtime services that provide support for: • • • • • • 1.3.1 Networking, Section 1.3.2 Local area transport (LAT) communication, Section 1.3.3 System security, Section 1.3.4 File oriented disk and tape I/O, Section 1.3.5 Device drivers, Section 1.3.6 DECwindows, Section 1.3.7 Kernel The VAXELN Kernel defines a set of objects that it uses to control the sharing of resources and to synchronize communication between the jobs in a system. The kernel manipulates these objects in response to procedure calls that are issued from application programs. In addition, the kernel provides the following types of facilities to both user and system programs: • • • • • Process, job, and memory management Process synchronization Communication Device and interrupt handling Exception handling Chapter 2 describes the kernel data structures and the operations in which they can be used. Chapter 3 explains how the kernel manages processes, jobs, and memory. Chapters 4 to 7 discuss synchronization, communication, device handling, and exception handling, respectively. 1-14 Runtime Facilities Overview 1.3.2 Network Services The VAXELN Toolkit includes EthernetlIEEE 802 datalink drivers for supported network devices. Each of the datalink drivers supports the VAXELN EthernetlIEEE 802 Datagram Service, VAXELN Network Service, and VAXELN Internet Services. The Datagram Service provides network interface routines that VAXELN systems can use to communicate with other types of systems using system-independent communications protocols. The Network Service is a supplied program image that controls message transmission between network nodes, manages a network name table, and provides a runtime interface for managing a DECnet network. You configure a Network Service for each target node used in a multinode application. The Network Service preserves the methods for sending and receiving messages, whether jobs communicate on the same node or between nodes; data transmission across network nodes is transparent to your programs. The VAXELN Internet Services support Internet networking protocols over an Ethernet medium. The services consist of runtime routines that applications can use to control the Internet Services,convert byte order of Internet and host physical addresses, manipulate Internet addresses, communicate over the Internet using sockets, and retrieve and set socket characteristics. Chapter 8 describes the datalink drivers and explains how to use the Datagram Service. Chapters 9 and 10 describe VAXELN DECnet and Internet Services, respectively. 1.3.3 LAT Host Services The local area transport (LAT) host services enable VAXELN system nodes running LAT host services to communicate with devices attached to dedicated terminal server nodes running LAT server. services. Using these services, VAXELN applications can perform terminal I/O operations and can use control interfaces to manage and monitor LAT environments. In addition, the LAT host services support a utility that you can use to manage and monitor a VAXELN LAT environment interactively. See Chapter 11 for more information. Runtime Facilities Overview 1-15 1.3.4 Authorization Service The VAXELN Toolkit includes an optional Authorization Service that provides system security for network applications. The Authorization Service protects system resources and data by maintaining a data base of a system's authorized users and identifying users who issue network requests. The Network Service and File Service use the Authorization Service to protect the resources and data that they control. The Network Service running on a particular node accepts circuit connections only from users who are listed in the Authorization Service's data base. The File Service provides read, write, and delete protection for files on disks that it controls. Likewise, your application programs can use the service to protect their resources and data. See Chapter 12 for more information. 1.3.5 File Service The File Service is a set of system disk and tape driver services that enable VAXELN application programs to perform file-oriented disk and tape I/O operations. The File Service consists of a disk File Service and a tape File Service and provides for remote file access. The disk File Service uses FILES-II On-Disk Structure Level 2 services and is compatible with the VMS, Version 4.4, file system and the VMS record management services (RMS). Files are sequentially organized. Programs can use sequential or random access for creating, reading, and writing sequential disk files. The tape File Service is based on Version 3 of the ANSI-standard magnetic tapes and is compatible with the VMS, Version 4.4, tape file system. You can use this service to transport files to and from VMS systems. See Chapter 13 for more information. 1-16 Runtime Facilities Overview 1.3.6 Device Drivers The VAXELN Toolkit simplifies VAX device support by providing pregenerated device drivers that you can include in your VAXELN systems. These drivers provide support for a variety of disk, tape, printer, terminal, Ethernet, and realtime devices. See Chapter 14 for more information. 1.3.7 DECwindows Support The VAXELN Toolkit provides DECwindows support for creating network transparent distributed applications that perform twodimensional, integer coordinate drawing and windowing operations. The toolkit includes the following DECwindows software: • • • A DECwindows server image that you can build into VAXELN systems that run on the following workstations: VAXstation IIIGPX VAXstation 2000 VAXstation 3100 series (color video option) VAXstation 3200 (color video option) VAXstation 3500 The DECwindows runtime libraries and tools you need to develop VAXELN DECwindows client applications A Window Manager and terminal emulators that enhance the user environment for VAXELN DECwindows client applications See VAXELN Guide to DECwindows for more information. Runtime Facilities Overview 1-17 Chapter 2 The VAXELN Kernel The VAXELN Kernel is a small, realtime executive that controls target hardware resources and the execution of VAXELN system software. VAXELN applications typically require fast, predictable responses to intelTupts. To meet this crucial need, the highly optimized kernel takes advantage of the VAX architecture and imposes minimal overhead between the application code and the hardware. The kernel recognizes and operates on a set of realtime programming data structures, which it uses to control the sharing of resources and to synchronize communication between the jobs in a system. These structures include a set of kernel objects and two specialized structures called mutexes and area lock variables. The objects represent ongoing activities, such as process execution, and hardware and software resources, such as devices, memory regions, events, and messages. Mutexes and area lock variables are optimizations of kernel objects. Table 2-1 describes the kernel objects, and Table 2-2 describes the optimized structures. Each VAXELN Kernel data structure is associated with a corresponding set of operations that are implemented as procedure calls. The kernel manipulates the structures and the resources associated with them in response to procedure calls that you issue from your application programs. Your high-level language programs call the kernel procedures directly to synchronize processes, to communicate between jobs Qr processes, and to handle device interrupts. The kernel also handles system scheduling and memory allocation and maintains information about the entire VAXELN system and each system component - that is, the context for the system image and each program image. The VAXELN Kernel 2-1 This chapter describes and summarizes the kernel operations for the following: • • Kernel objects, Section 2.1 Optimized data structures, Section 2.2 Chapters 3 to 6 describe the operations that the kernel performs in more detail. 2.1 Kernel Objects The VAXELN Kernel objects represent ongoing activities, such as process execution, and hardware and· software resources, such as devices, memory regions, events, and messages. To guarantee the integrity of a kernel object, its fields are not directly accessible to a program. Instead, when the program calls the kernel to create a new object, the· kernel dynamically allocates a block of memory for the object and returns an identifying value for it. You then refer to the object by specifying the identifying value in subsequent calls to kernel procedures. When you no longer need the object, you specify the identifying value in a call to the DELETE procedure. In the VAXELN Pascal language, predeclared data types represent the kernel objects' identifying values. These predeclared types are AREA, DEVICE, EVENT, MESSAGE, NAME, PORT, PROCESS, and SEMAPHORE. To create and use an object, a program declares a variable of the object's type, calls the appropriate CREATE_object_type kernel procedure, and saves the returned, object value in the variable. The variable then assumes the object's identifying value, which you can use throughout the program to name the object. For example, the following lines of code declare a variable of type SEMAPHORE, create a SEMAPHORE object, and save the returned identifying value in the variable main_lock: 2-2 The VAXELN Kernel VAR main lock SEMAPHORE; BEGJ:N END. You can then wait on or signal the semaphore anywhere in the program by using the variable to reference the object as follows: SJ:GNAL(main_lock); When the program no longer needs the object, you can delete it with a call to the DELETE procedure as follows: DELETE(maifi_lock); The VAXELN Toolkit also provides kernel interfaces for VAX C and VAX FORTRAN programming. The data type definitions for the two languages are provided in the following definition modules: Language Module C $vaxelnc in VAXELNC.TLB FORTRAN 'ELN$:FORTRAN_DEFS.FOR' NOTE Except for PORT values and AREA values for jobs on the same node, an object's identifying value is valid only within a job, even when the object is known in more than one job. Table 2-1 summarizes the kernel objects. Sections 2.1.1 to 2.1.8 describe the objects in detail. TheVAXELN Kernel 2-3 Table 2-1: Kernel Objects Object Description AREA Represents a region of physical memory accessible to all jobs executing on the same node in a local area network. DEVICE Represents a channel to an 110 device and associates an interrupt service routine (ISR) with the device's interrupt. DEVICE objects synchronize ISR and device driver process execution. EVENT Represents a flag that identifies the occurrence of a realtime event. Events synchronize process execution and access to shared data. MESSAGE Represents data that is transmitted between processes. Messages can be sent between two processes, two jobs, or two nodes in a local area network. NAME Represents an entry in a name table that associates a character string name with a message port or process. Port names can be local (known only on its own node) or universal (known on any node in the local area network). PORT Represents a system-maintained store for messages being sent or waiting to be received. Only the processes in the job that creates the port can receive messages from that port. However, any process in any job can send a message to the port. A program can connect two ports in the same or different jobs to form a circuit, which simplifies and increases the reliability of communication between jobs. PROCESS Represents a functionally independent entity that provides the execution context for a program image or part of a program image. The main program executes as a master process, which can control zero or more subprocesses. Collectively, a master process and its subprocesses constitute a job. SEMAPHORE Represents a synchronization gate that controls access to a shared resource. Binary semaphores enforce exclusive access to a resource. Counting semaphores permit metered access, allowing a specified number of processes simultaneous access to units of a resource. 2.1.1 AREA' Objects An AREA object represents a region of memory or another type of shared resource that can' be shared among jobs on a single node in a VAXELN network. An AREA object contains an event or semaphore that can be used by the sharing jobs to synchronize access to the area's 2-4 The VAXELN Kernel data. Areas with a size of 0 are valid and represent only the event or semaphore. An AREA object has the following properties: • • • • • • A character string name of up to 31 characters that supplies a name for the area A signaled or cleared state if the area is associated with an event A count of the number of processes that can gain access to the area (or resource) without waiting for some other process to signal the area if the area is associated with a semaphore The maximum allowed value for the count, which is the maximum number of processes that can gain access to the area (or resource) simultaneously, if the area is associated with a semaphore A list of processes waiting for access to the area The associated region of memory Chapter 5 discusses these properties and the kernel procedures that affect AREA objects. AREA values are represented internally as 32-bit longwords. The kernel uses the longwords to locate AREA objects and their properties. An AREA object occupies one block (128 bytes) of kernel pool. The kernel allocate~ the region of memory associated with an area from physically contiguous 512-byte pages of physical memory and maps the region into the creating job's PO virtual address space. The region occupies an integral number of memory pages and is aligned on a page boundary. The following table lists the operations for which you can use AREA values and the procedures an application calls to perform the operations: Operation Procedure Create an area or map an existing area, return an identifying AREA value and pointer to the area, and associate the area with an event or semaphore. CREATE_AREA CREATE_AREA_EVENT CREATE_AREA_SE~HORE Gain exclusive access to an area by waiting for that area to be signaled. The VAXELN Kernel 2-5 2.1.2 Operation Procedure Signal the event or semaphore that is associated with an area. SIGNAL Clear an event associated with an area. CLEAR_EVENT Delete an area. DELETE DEVICE Objects A DEVICE object represents a channel to an I/O device and associates an interrupt service routine (ISR) with the device's interrupt. When the device issues an interrupt, the kernel calls the device's ISR to service the device. A DEVICE object has the following properties: • • • A set of device characteristics established with the System Builder A communication region that lets a device driver and its ISR share data An ISR, which the kernel invokes when an appropriate interrupt occurs and to which the kernel passes the DEVICE value and communication region Chapter 6 discusses these properties and the kernel procedures that affect DEVICE objects. DEVICE values are represented internally as 32-bit longwords. The kernel uses the longwords to locate the·DEVICE objects and their properties, such as the address of its communication region. DEVICE values are valid only within their own job. A DEVICE object occupies one block (128 bytes) of kernel pool. If an ISR is connected, it also requires one block of pool or a page of communication region for its dispatcher. The following table lists the operations for which you can use DEVICE values and the procedures an application calls to perform the operations: 2-6 The VAXELN Kernel Operation Procedure Create a DEVICE object and return an identifying DEVICE value. Wait for an ISR to signal a DEVICE object. Signal a DEVICE object from an ISR. Delete a DEVICE object. 2.1.3 WAIT_ALL WAIT.ANY SIGNAL_DEVICE DELETE EVENT Objects An EVENT object represents a flag that identifies the occurrence of a realtime event. Events synchronize process execution and access to shared data. An EVENT object records events in real time and stores that information until explicitly cleared by a program. An EVENT object has the following properties: • • Either a signaled or a cleared state A list of processes waiting for the event to be signaled Chapter 4 discusses these properties and the kernel services that affect EVENT objects. EVENT values are represented internally as 32-bit longwords. The kernel uses the longwords to locate EVENT objects and their properties, such as the object state. An EVENT value is valid only within its own job unless the value is associated with an area (see Section 2.1.1). An EVENT object occupies one block (128 bytes) of system pool. The following table lists the operations for which you can use EVENT values and the procedures an application calls to perform the operations: Operation Procedure Create an event and return an identifying EVENT value. Wait for the signaling of an event. The VAXELN Kernel 2-7 2.1.4 Operation Procedure Signal an event. SIGNAL Clear an event. CLEAR_EVENT Delete an event. DELETE MESSAGE Objects A MESSAGE object represents data that is transmitted between processes. Messages can be sent between two processes, two jobs, or two nodes in a local area network. A MESSAGE object has the following properties: • • Message data Message length Chapter 5 discusses these properties and the kernel procedures that affect MESSAGE objects. MESSAGE values are represented internally as 32-bit longwords. The kernel uses the longwords to locate MESSAGE objects and their properties. MESSAGE objects are valid only within their own job. The associated message data is allocated in contiguous 512-byte pages of physical memory and is mapped by the creating or receiving job's PO virtual address space. Therefore, the data always occupies an integral number of memory pages and is aligned on a page boundary. (These characteristics suit the message data well for a VAX DMA-device liD buffer.) Since PO address space is used, all processes in a job can share the message data. The following table lists the operations for which you can use MESSAGE values and the procedures an application calls to perform the operations: Operation Procedure Create a message, map its data into the job's PO address space, and return an identifying MESSAGE value and a pointer to the data. CREATE_MESSAGE 2-8 The VAXELN Kernel 2.1.5 Operation Procedure Send a message to a message port and remove the message data from the sending job's address space. SEND Remove a message from a message port, map the message data into the receiving job's PO address space, and return an identifying MESSAGE value and a pointer to the message data. RECEIVE Delete a message. DELETE NAME Objects A NAME object represents an entry in a name table that associates a character string name with a message port or process. Name objects have the following properties: • • • A character string of up to 31 characters that names an existing message port or process The value of the message port or process being named For port name objects, the property local or universal Port name objects and their associated character strings are stored in either a local or a universal name table. The kernel maintains the local name table for name objects used within a node. The Network Service helps to maintain the universal name table; it contains valid name objects for nodes in the local area network. NOTE The processors in a closely coupled symmetric multiprocessing configuration constitute one Ethernet node and share the same local name table. Therefore, the images running on the processors must create unique local names. A NAME object for a process is not kept in a name table; it is associated with a PROCESS object. Chapter 5 discusses these properties and the kernel procedures that affect NAME objects for processes and message ports, respectively. The VAXELN Kernel 2-9 Identifying NAME values are 32-bit longwords that are valid only within their own job. A NAME object occupies one block (128 bytes) of kernel pool. A universal name also requires 64 bytes of dynamic memory in the local Network Service and 64 bytes in the system acting as the network's current name server. (See Chapter 9 for more information.) The following table lists the operations for which you can use NAME values and the procedures an application calls to perform the operations: Operation Procedure Create a name and an identifying NAME value. Return the PORT value associated with a name (not valid for process names). 2.1.6 Name a process by creating a unique NAME object that associates a character string with a process. KER$NAME_OBJECT (Pascal only) Delete a name. DELETE PORT Objects A PORT object represents a system-maintained store for messages being sent and waiting to be received. Only processes in the job that creates a port can receive messages from that port. However, any process in any job can send messages to a port. Each executing job in a system has a unique message port, or job port, created when the first process in the job is started. A job can use its job port to receive messages from other jobs. Programs can create additional message ports dynamically with the CREATE_PORT procedure. A PORT object has the following properties: • • • The maximum number of queued messages A list of queued messages, to be removed from the port by the RECEIVE procedure The state of the port's circuit: unconnected, connected, or in a special state during the establishment of a connection 2-10 The VAXELN Kernel • If connected, the PORT value identifying the port to which the port object is connected Chapter 5 discusses these properties and the kernel procedures that affect the state of PORT objects. PORT values are 128-bit values that identify a message port as shown in Figure 2-1. Figure 2-1: PORT Value Representation o 31 Port Table Index Network: Number Ethernet Node Reserved I Address 127 MLO-004273 Each PORT object occupies one block (128 bytes) ofkemel pool and requires one entry in the kernel's port address table. The following table lists the operations for which you can use PORT values and the procedures an application calls to perform the operations: Operation Procedure Create a port and return an identifying PORT value. CREATE_PORT Return a unique PORT value for the calling job for communicating between jobs. JOB_PORT The VAXELN Kernel 2-11 Operation Procedure Wait to receive a message. WAIT_ALL WAIT_ANY CONNECT_CIRCUIT DISCONNECT_CIRCUIT ACCEPT_CIRCUIT Connect and disconnect circuit ports. Let the calling process wait for a circuit connect request on a port. Delete a port. DELETE When a message arrives at a port, any process waiting on that port can continue if its wait conditions are satisfied. The receiver process calls the RECEIVE procedure to get the message. Only processes in the job that creates a port can receive messages from that port with RECEIVE. 2.1.7 PROCESS Objects A PROCESS object represents a functionally independent entity that provides the execution context for a program image or a part of a program image. The main program executes as a master process, which can control zero or more subprocesses. Collectively, a master process and its subprocesses constitute a job. A job can contain any number of processes within a limit of 4096 objects for each job. A PROCESS object has the following properties: • • • One of 16 levels of process priority One of the process states running, ready, waiting, or suspended A user name and a user identification code (UIC) Chapter 4 discusses these properties and the kernel services that affect PROCESS objects. PROCESS values are represented internally as 32-bit longwords. They are valid only within their own job. The following table lists the operations for which you can use PROCESS values and the procedures an application calls to perform the operations: 2-12 The VAXELN Kernel Operation Procedure Create a process and return an identifying PROCESS value. Get the PROCESS value of the calling process. CURRENT_PROCESS Set a process's priority. SET_PROCESS_PRIORITY Suspend a process's execution. SUSPEND Resume execution of a process. RESUME Wait for another process to terminate. WAIT_ALL WAIT_ANY Force another process into an exception condition. SIGNAL Exit from a process. EXIT Delete a process. DELETE 2.1.8 SEMAPHORE Objects A SEMAPHORE object represents a synchronization gate that controls access to a shared resource. Binary semaphores enforce exclusive access to a resource. Counting semaphores permit metered access, allowing a specified number of processes simultaneous access to units of a resource. A SEMAPHORE object has the following properties: • • • A count of the number of processes that can gain access to the resource without waiting for some other process to signal the semaphore The maximum allowed value for the count, which is the maximum number of processes that can gain access to the resource simultaneously A list of processes waiting for the semaphore to be signaled Chapter 4 discusses these properties and the kernel procedures that affect SEMAPHORE objects. A SEMAPHORE object occupies one block (128 bytes) of system pool. The VAXELN Kernel 2-13 SEMAPHORE values are represented internally as 32-bit longwords. The kernel uses the longwords to locate SEMAPHORE objects and their properties, such as its CUITent count. A SEMAPHORE value is valid only within its own job unless the value is associated with an area (see Section 2.1.1). The following table lists the operations for which you can use SEMAPHORE values and the procedures an application calls to perform the operations: 2.1.9 Operation Procedure Create a semaphore and return an identifying SEMAPHORE value. CREATE_SEMAPHORE Wait for the signaling of a semaphore. WAIT_ALL WAIT_ANY Signal a semaphore. SIGNAL Delete a semaphore. DELETE Kernel Object Implementation Although it is usually not necessary for a VAXELN programmer to know the details of the kernel's implementation of objects, the following points are useful in answering system configuration questions: • • The kernel allocates all objects, except PROCESS objects, from a pool of fixed-length blocks of memory.. The number of blocks in the pool is set with the System Builder. When the system is booted, the kernel initializes the pool, maps the blocks into system space, and links the blocks into a list of free blocks. The fixed size of the blocks makes allocating and deallocating objects efficient. The identifying value returned by the kernel for a newly created object is not the virtual address of the object. Instead, it is a 32-bit value consisting of two indexes. The indexes are used to look up the address of the object ina two-level table maintained by the kernel for each job. These values are thus unique for each job in the system. 2-14 The VAXELN Kernel • The object table grows dynamically as the job creates more objects. The kernel allocates the table from system memory and pool blocks. The top-level table is allocated in a 512-byte page of memory that can hold pointers to 128 second-level tables. Each second-level table occupies one 128-byte pool block that can hold up to 32 object addresses. Thus, you can create up to 4096 objects for a job. The preceding description applies to all objects except ports. Because a PORT value is valid anywhere in the network, it also includes the DECnet or Ethernet node address and additional fields reserved for future use. Thus, a PORT value is 128 bits long. Also, the indexes in a PORT value are used for a table that describes all the ports in the system, rather than just the ports in a job. The size of the port table is also set with the System Builder, and the table is allocated by the kernel when the system is booted. Although the kernel's method for representing identifying values might seem complicated, it allows you to validate identifying values in a few VAX instructions. Furthermore, the method of representation is not important for VAXELN programming. 2.2 Optimized Data Structures The kernel also recognizes and operates on two specialized data structures: mutexes and area lock variables. These structures are optimizations of kernel objects; locking a mutex can be faster than waiting on a mutual exclusion semaphore, and locking an area synchronization variable can be faster than waiting on a shareable memory area. The locations of the MUTEX and AREA_LOCK_VARIABLE data type definitions are as follows: Language Module VAXELN Pascal $MUTEX in the RTLOBJECT.OLB C $mutex in the VAXELNC. TLB FORTRAN 'ELN$:FORTRAN_DEFS.FOR' Table 2--2 summarizes the optimized structures. Sections 2.2.1 and 2.2.2 describe the structures in detail. The VAXELN Kernel 2-15 Table 2-2: 2.2.1 Optimized Data Structures Structure Description AREA_LOCK_VARIABLE Represents a variable that resides in an area object for synchronizing job access to the associated area. Using this variable, a process can lock an area to gain exclusive access. When the process locks the area, the process does not have to issue a wait before accessing the associated area unless the area is already locked. MUTEX Represents an optimized binary semaphore. A process can lock a mutex to gain exclusive access to a shared resource. When the process locks the mutex, the process does not have to issue a wait before accessing the resource unless the mutex is already locked. AREA_LOCK_VARIABLE Data Structure The AREA_LOCK_VARIABLE data structure provides an alternative means for synchronizing access to areas between jobs. Area lock operations can be used to improve the performance of AREA wait and signal operations. Area-locking operations enable jobs to synchronize access to an area by using a synchronization variable of type AREA_LOCK_VARiABLE in the area's data portion. You can use an area lock variable only if the area is created with an associated binary semaphore that is properly initialized. You can do this with CREATE_AREA, and its implied binary semaphore, or with CREATE_AREA_SEMAPHORE with initial and maximum counts of 1. No error status is returned if you use an AREA_LOCK_VARIABLE with an area that is not associated with a binary semaphore. Area-locking operations can be more efficient than calling the WAIT_ ANY and SIGNAL procedures with areas. When a process locks an area to gain exclusive access, the process does not have to call a WAIT_ ANY procedure unless some other process has already locked the area. The following table lists the operations for which you can use area lock variables and the procedures an application calls to perform the operations: 2-16 The VAXELN Kernel Operation Procedure Initialize (unlock) a synchronization variable (of type AREA_LOCK_VARIABLE) in the data portion of an area. ELN$INITIALIZE_AREA_LOCK Lock (wait on) an area. ELN$LOCK_AREA Unlock (signal) an area. ELN$UNLOCK_AREA An area lock variable is represented internally as a I6-bit counter. The variable must be within an area's data portion. A single process in the application calls ELN$INITIALIZE_AREA_LOCK to initialize the counter to -l. Once an area lock variable is initialized, subsequent calls to the ELN$LOCK_AREA and ELN$UNLOCK_AREA procedures increment and decrement the counter, respectively. • • 2.2.2 When ELN$LOCK_AREA increments the counter and the result is greater than 0, the area has already been locked by another process. Thus, the procedure calls the WAIT_ANY procedure to wait for the area to be unlocked. When ELN$UNLOCK_AREA decrements the counter and if the result is greater than or equal to 0, another process is waiting for the area. To satisfy that wait, ELN$UNLOCK_AREA calls the SIGNAL procedure to unlock the area. MUTEX Data Structure The MUTEX data structure is an optimization of a binary semaphore. The meanings of mutex operations are similar to the comparable operations on binary semaphores. The difference is that when a process locks a mutex to gain access to a shared resource, the process does not have to call the WAIT_ANY procedure unless some other process has already locked the mutex. The result is significantly more efficient than that obtained using WAIT_ANY and SIGNAL procedures on binary semaphores. The following table lists the operations for which you can usemutexes and the procedures an application calls to perform the operations: The VAXELN Kernel 2-17 Operation Procedure Initialize (unlock) a mutex and create an associated semaphore. ELN$CREATE_NnlTEX Lock (wait on) a mutex. ELN$LOCK_NnlTEX ELN$UNLOCK_MUTEX ELN$DELETE_N.nlTEX Unlock (signal) a mutex. Delete the semaphore created for a mutex. A mutex is represented internally as a 6-byte record containing a 16-bit counter and a SEMAPHORE value. A call to ELN$CREATE_MUTEX initializes the counter to -1 and the SEMAPHORE value to a binary semaphore with an initial count of 0. Once a mutex is initialized, subsequent calls to the ELN$LOCK_ MUTEX and ELN$UNLOCK_MUTEX procedures increment and decrement the counter, respectively. • • When ELN$LOCK_MUTEX increments the counter and the result is greater than 0, the mutex has already been locked by another process. Thus, the procedure.calls the WAIT_ANY procedure to wait for the mutex to be unlocked. When ELN$UNLOCK_MUTEX decrements the counter and the result is greater than or equal to 0, another process is waiting for the mutex. To satisfy the wait, ELN$UNLOCK_MUTEX calls the SIGNAL procedure to unlock the mutex. Deleting a mutex with the ELN$DELETE_MUTEX procedure sets the counter to 0, indicating that the mutex is locked. If you try to lock or unlock a mutex after it has been deleted, the internal call to WAIT_ ANY fails and returns the status value KER$_BAD_VALUE. 2-18 The VAXELN Kernel Chapter 3 Job, Process, and Memory Management The VAXELN Kernel manages jobs, processes, and system memory. The programs that comprise a VAXELN application execute as jobs. When you build a VAXELN system, the kernel creates a job for each program image that you specify; the images execute automatically when the system starts on the target hardware. The kernel also creates jobs in response to calls to the CREATE_JOB procedure and when you issue appropriate VAXELN debugger or ECL commands. An application can use the CREATE_JOB procedure to create a job dynamically or to create a job after dynamically loading a program image with the dynamic program loader (see Section 3.3.4). A program image is a copy of all the code and initial data necessary to run the program. A job consists of one master process that executes the program's main routine (program block, main function, or main program, depending on the language) and zero or more subprocesses that execute concurrently with the master process and with each other. The master process and subprocesses synchronize their activities by using the kernel objects, mutexes, and area lock variables and the associated procedures that manipulate them. The procedures create, delete, or otherwise affect the state of the structures represented by the data types AREA, AREA_ LOCK_VARIABLE, DEVICE, EVENT, MESSAGE, MUTEX, NAME, PORT, PROCESS, and SEMAPHORE. Job, Process, and Memory Management 3-1 A program creates subprocesses by calling the CREATE_PROCESS procedure. Each subprocess executes a routine that defines the executable code and data available to one or more dynamically created processes. In VAXELN Pascal, C, and FORTRAN, these routines are called process blocks, functions, and integer functions, respectively. Ajob can be thought of as a process family. The way processes are created implies a hierarchy: the CREATE_JOB procedure or the System Builder creates a job and a corresponding master process that runs a program; that program then can call the CREATE_PROCESS procedure to create subprocesses to execute the program's process blocks and functions. The subprocesses can also call CREATE_PROCESS to create subprocesses. Execution of the master process holds the object values of all subprocesses; thus, if the master process exits, all subprocesses and the memory and objects created by the job are deleted. The processes in a job can share data that is declared externally (outerlevel data). Jobs on a single node in a VAXELN network can share data by using AREA objects. You can combine any number of jobs with the VAXELN runtime software to form a VAXELN system image. The VAXELN Kernel keeps track of the current jobs in a system. Therefore, if a program calls CREATE_JOB and then exits, the created job continues executing. With this procedure, a VAXELN program can create a new process family, in which the main program can be any program that was originally configured into the system or loaded with the dynamic program loader. The new job is independent of other jobs and has its own data and code. Similarly, multiple proceses within a job can execute the same code segment. When you build a system, you can specify any number of programs to execute when you load the system onto the target processor. A running VAXELN application can contain any combination of multitasking, multiprogramming, and multiprocessing job configurations. A job remains active until the master process finishes executing its main routine code. A process remains active until it exits, another process deletes it, its master process terminates, it encounters an error from which it cannot recover, or it finishes executing the associated code segment. The exit operation provides the most controlled means of forcing process termination. A process can delete itself or any other process within the same job. You cannot restart a deleted process; in general, you should use SIGNAL or EXIT to force a process to terminate. 3-2 Job, Process, and Memory Management When a job or master process terminates, the kernel deletes all the job's subprocesses and shared data from the system. This chapter provides information about programming job, process, and memory management. The topics discussed include the following: • • • • • 3.1 Job activation and termination, Section 3.1 Subprocess activation and termination, Section 3.2 Scheduling, Section 3.3 Kernel procedures for processes and jobs, Section 3.4 Memory management, Section 3.5 Job Activation and Termination The VAXELN Kernel creates a job implicitly when you select the Run option for a program image that you specify in the System Builder's Program Description Menu. The image executes automatically when the system starts on the target hardware. If you do not select the Run option, you can load a program and create jobs dynamically. You can load a program image by using one of the following: • • • • System Builder ELN$LOAD_PROGRAM procedure LOAD PROGRAM debugger command LOADIPROGRAM or RUN ECL command (RUN also creates the job) Mter the program image is loaded, you can: • • • • Use the CREATE_JOB procedure to create a job dynamically, using a program that was loaded with the System Builder Use the CREATE_JOB procedure after dynamically loading a program image with the ELN$LOAD_PROGRAM procedure Use the CREATE JOB debugger command to create ajob Use the EXECUTEIWAIT ECL command to create a job The LOAD PROGRAM and CREATE JOB debugger commands and the LOADIPROGRAM, EXECUTEIWAIT, and RUN ECL commands are described in the VAXELN Development Utilities Guide. Job, Process, and Memory Management 3-3 When a job is created, the kernel establishes the job's PO address space and the PI address space (stack) for the job's master process (the program block). The processes in a job, including the master process and subprocesses, share the PO space. Program arguments are stored in PO space so that the PROGRAM_ARGUMENT function and the 1/0 runtime routines (for opening files) can access them. The System Builder and Program Loader detect oversized jobs and issue appropriate warning messages. If you receive such a message, make sure you have allocated enough PO virtual address space for each job in your system. The kernel will delete a job if not enough PO space is available to create the job. No files are open initially. However, you can implicitly open an input file, an output file, or a file named in the program block's header with the first 1/0 operation on that file. The kernel activates the program block's routine body. It initializes data, using the program block's declaration section; then it executes the block's compound statement (BEGIN ... END). A job terminates when the main routine's code completes execution, when the job's master process is terminated by the DELETE or EXIT procedure, or when an unhandled exception occurs (such as an unhandIed QUIT exception caused when another process signals this process). When a job terminates, its existing subprocesses terminate, open files are closed, and the job's resources are returned to the kernel. If files are closed due to job termination, data in buffers can be lost. If you want the kernel to send a termination message to a specified port, use the NOTIFY parameter with the CREATE_JOB procedure. You can use VAXELN utility procedures to establish an exit handler to perform cleanup operations following the termination of a job with the EXIT procedure (see Chapter 7). 3.2 Subprocess Activation and Termination When a process in a job calls CREATE_PROCESS, the kernel creates a subprocess, establishes a new stack (PI virtual address space) for the process, and prepares it for execution, beginning at the first statement in a process's routine code. The new process is in the ready state; it begins actual execution immediately or later, depending on its priority and the scheduling algorithms. (For information about process states and scheduling, see Section 3.3.) 3-4 Job, Process, and Memory Management A subprocess terminates when one of the following occurs: • • • • • Execution of the main routine code terminates. The process calls the EXIT procedure. The process is deleted by a call to the DELETE procedure. An unhandled exception occurs in the process. (For example, an unhandled QUIT exception can occur when another process signals this process.) The job's master process terminates. When a subprocess terminates, the kernel frees its Pl virtual address space (stack space) and the kernel pool space associated with the subprocess's activation. Objects it created and did not delete remain active, since the kernel cannot detect whether the object is in use by more than one process in the job. These objects are acquired by the job's processes that are deleted only when the job's master process is deleted. NOTE Be careful when using the DELETE procedure to delete a process. Processes terminated by DELETE are not terminated in an orderly way and cannot be restarted. Deletion of a process is intended as an emergency method to stop a process; ordinarily, you should use SIGNAL or EXIT to terminate a process in an orderly way. When terminating a process, the kernel also takes action so that: • • If another process of the job is currently waiting for the process to terminate, the wait is satisfied. If the call to CREATE_PROCESS that activated the process specified an exiCstatus argument, the exit status of the terminated process is stored in the designated data item. These actions are not taken if the subprocess terminates because the master process terminated. Processes are terminated in an orderly way with the SIGNAL or EXIT procedure or when they return from the outermost procedure block. (See Chapter 7 for a discussion of VAX. stack architecture and call frames.) Job, Process, and Memory Management 3-5 The orderly termination of a process has two special consequences: • • The debugger notifies the user that the process is going away, if the debugger is active in the process. If the process is a master process (that is, if the job is terminating), the kernel activates an exit handler feature so that resources can be cleaned up by the code that allocated them. When a process signals another process to quit, the quitting process can handle the raised exception KER$_QUIT_SIGNAL (see Section 3.4.18). The exception handler can perform special operations for the process, such as cleaning up resources, before the process exits. A program can set up an exit handler by using the toolkit's exit utility procedures, ELN$DECLARE_EXIT_HANDLER and ELN$_CANCEL_ EXIT_HANDLER. The ELN$DECLARE_EXIT_HANDLER procedure causes a program-defined exit handler routine to be called when the job terminates. When the exit handler routine is no longer needed, the program can delete it with a call to ELN$_CANCEL_EXIT_HANDLER. 3.3 Scheduling The VAXELN Kernel schedules an application's execution based on a preemptive priority scheduling scheme that is driven by states and priorities of a system's jobs and processes. This scheduling scheme is described in Sections 3.3.1 to 3.3.5. 3.3.1 Processes and Process States A process is a code segment that the kernel can schedule and execute independently as part of a VAXELN job. A process is created statically when you build your system or dynamically at runtime and remains active until it terminates. While active, a process is always in one of four process states: run, ready, wait, or suspend. Table 3-1 describes these states, and Figure 3-1 illustrates valid state transitions. 3-6 Job, Process, and Memory Management Table 3-1 : Process States State Description Run The process has control of the processor and is currently executing. Ready The process is not executing but is ready to execute as soon as the scheduler allows. When an application creates a process, the process enters the ready state. Wait The process is waiting for a specified set of conditions to be satisfied, such as an amount of time to elapse, an event or series of events to occur, or the receipt of a message. A process enters the wait state by calling one of the following procedures: • • • Suspend WAIT_ANY - Wait for any of the listed conditions to be satisfied. WAIT_ALL - Wait for all the listed conditions to be satisfied. RESUME - Reenter the wait state if the process was waiting prior to being suspended with a call to the SUSPEND procedure. Another process must issue the call to RESUME. The process cannot reenter the ready state until another process in the same job reactivates the suspended process with a call to the RESUME procedure. A process can put itself or any other process in the same job into the suspend state with a call to the SUSPEND procedure. The rules for process state transitions are as follows: • • • • • Ready is the initial state for a process. When a process's wait conditions are satisfied, it enters the ready state. If the scheduling state of the system is such that the process should run immediately, the process enters the run state. The scheduler selects a ready process to enter the run state based on the system's jobs and process priorities. A process in the run state enters the ready state when the process is preempted by a higher priority process. A process in the run state enters the wait state when the process issues a call to WAIT_ANY or WAIT_ALL that blocks due to the wait conditions not being satisfied. Job, Process, and Memory Management ~7 Figure 3-1: Valid Process State Transitions MLO-004274 • • • If a process is in the run or ready state when it is suspended, it enters the ready state when it is resumed. If the scheduling state of the system is such that the process should run immediately, the process enters the run state when it is resumed. If a process is in the wait state when it is suspended and not all the wait conditions are satisfied when the process is resumed, it reenters the wait state. If the scheduling state of the system is such that the process should run immediately, the process enters the run state when it is resumed. If a process was in the wait state when it was suspended and all the wait conditions are satisfied when the process is resumed, it enters the ready state. 3-8 Job, Process, and Memory Management 3.3.2 Job and Process Scheduling The order in which processes enter the run state depends on job and process scheduling. The VAXELN Kernel selects a process to run based on a preemptive, priority scheduling scheme; round-robin and time-sliced scheduling are not available. To accommodate preemptive priority scheduling, you must assign a priority to each job and process in a VAXELN system. You can assign the priorities when you build the system, or you can change them dynamically with the procedures SET_JaB_PRIORITY and SET_ PROCESS_PRIORITY. Job priorities can range from 0 to 31 (0 is the highest and 16 is the default). Process priorities can range from 0 to 15 (0 is the highest and 8 is the default). Therefore, within a job, processes can have 16 levels of priority independent of the job's priority. Figure 3-2 illustrates the structure of job and process scheduling priorities. The VAXELN driver jobs run at higher priorities. For example, the datalink driver normally runs at job priority 1, the console driver runs at job priority 2, and the disk and tape drivers run at job priority 5. If an application includes one or more jobs that need to run at a job priority higher than that of the datalink driver and the jobs can run at the same job priority, you can set their job priorities to 0 and vary the process priorities. The kernel scheduler considers a job ready to execute if one or more processes in that job are in the ready state. The kernel scheduler gives preference to the ready jobs and processes that have the highest priorities. The scheduler identifies the job with the highest priority and then selects that job's highest priority process for execution. The jobs in a system, whether they are executing or idle, are rescheduled when one or more of a job's processes enters the ready state. Job rescheduling is illustrated by the following example, in which JOB1 has a higher priority than JOB2: 1. JOB1 has only one process, the master process; at a certain point, it executes WAIT_ANY to wait for a message to arrive at its job port. Job, Process, and Memory Management 3-9 Figure 3-2: Job and Process Priorities Job 1 (Priority 0-31) Process 1 (Priority 0-15) Process 2 (Priority 0-15) Process 3 (Priority 0-15) Job2 (Priority 0-31) Process 1 (Priority 0-15) Process 2 (Priority 0-15) Process 3 (Priority 0-15) MLO-004275 2. JOBl now has no processes in the ready state, so JOB2 is given control (assuming that at least one of its processes is ready). 3. When a message arrives at JOBl's port, the wait condition is satisfied, and JOB1's master process becomes ready again. Since JOB1's priority is higher, it is given control of the CPU again, preempting JOB2. When two or more jobs have equal priority, the scheduler gives control to the ready process that has the highest priority among those jobs, preempting lower-priority processes. When a job is preempted and one or more jobs in the ready queue have the. same job priority and the same highest priority ready process as· that of the preempted job, the scheduler's action depends on the job preemption algorithm in effect. The default algorithm rotates the preempted job by placing it in the ready queue behind the jobs of equal job and process priority. However, if you selected No for the Rotating job preempt entry on the System Builder's System Characteristics 3-10 Job, Process, and Memory Management Menu when you built your system, the scheduler places the preempted job in the ready queue ahead of the jobs of equal job and process priority. The scheduler's use of 32 job priorities and 16 process priorities might imply that the job and process priorities are unified to form one of 512 possible combined priority values and that the processes are scheduled against each other using this combined value. Rather, jobs are scheduled first followed by processes; the overall priority of a process, therefore, is limited by the priority of its job. Figure 3-3 illustrates the internal representation of the combined job and process priority values. Figure 3-3: Combined Priority Representation o 8 7 15 Job Priority I Process Priori1y MLO-004276 Process rescheduling, or switching, within a job can be enabled and disabled with the procedures ENABLE_SWITCH and DISABLE_ SWITCH. When switching is disabled, no other process in the current job can run. This feature provides a mechanism by which, for example, a process can control the access to a data set. (A finer mechanism is the use of semaphores, discussed in Chapter 4.) Since process rescheduling is automatic and predictable, you can design systems that execute without noticeable delays - even though programs sit idle while others execute. In principle, the execution speed of an application is the speed of the slowest thread of execution. The definition of important delay is essentially the definition of realtime performance for your application. It is impossible to exactly synchronize a computer or computer program with external phenomena. Instead, to satisfy the practical definition of realtime, the system must contain processes, which - given control of the CPU - can respond Job, Process, and Memory Management 3-11 to external events in an acceptable amount of time. Furthermore, the processes should have high enough priority to ensure that they are not preempted while they are reacting to important external events. Generally, realtime systems work best if the processes .in charge of specific events are properly designed for, and synchronized with, those events. Only then should process priorities enter in, as a fine-tuning mechanism; priorities are not a means of synchronization. Chapter 4 summarizes issues related to synchronizing processes with each other or with external events. For information about scheduling in multiprocessing configurations, see Section 3.3.5. 3.3.3 Initialization Programs and System Start-Up When you use the System Builder to configure your program images, you can specify Yes for the Init required entry (see the VAXELN Development Utilities Guide). This characteristic means that the program is an initializing program that will be created and made eligible to run - along with other initializing programs, in order of job priority - when the system is started. Start-up of initializing programs precedes that of noninitializing programs. While an initializing program runs, no jobs of lower priority are started until the program either calls the INITIALIZATION_DONE procedure or terminates. The INITIALIZATION_DONE procedure informs the kernel that the calling program has completed an initialization sequence, and other programs can be created and made eligible to run. (The calling program continues to run until some other occurrence . causes it to block.) The INITIALIZATION_DONE procedure makes it possible to synchronize the start of several programs in a system. For example, suppose a system has descriptions of the following programs: programl Run, Init required, Priority 5 program2 Run program3 Run, Init required, Priority 6 program4 Norun 3-12 Job, Process, and Memory Management When the resulting system is started, the initializing programs are created and made eligible to run, one at a time, in the order of their job priorities, followed by the noninitializing programs. Here, programl is started first. (Remember that with job priorities, low numbers mean high priorities.) When programl calls INITIALIZATION_DONE, other initializing programs, beginning with program3, can be created and made eligible to run; meanwhile, programl continues running until some other occurrence causes it to block. If programl does not call INITIALIZATION_DONE, it must run to completion before program3 or any other program is started. Program2 is not started until both initializing programs have run or called INITIALIZATION_DONE. Program4 is not started automatically; it must be activated by a CREATE_JOB call from one of the other programs, a debugger CREATE JOB command, or an ECL EXECUTE or RUN command. 3.3.4 Loading Programs Normally, the programs that are available to run using the CREATE_ JOB procedure are specified with the System Builder. To allow the system to react to new situations without being rebooted, however, VAXELN provides utility procedures that can be used to dynamically load and unload program images after the initial system is built. Mter a program image is dynamically loaded, CREATE_JOB is used to execute the program image. The $LOADER_UTILITY module provides the following procedures: • • ELN$LOAD_PROGRAM, which loads a specified image file into a running system. The file is opened in the context of the caller, so the file name must be specified in enough detail to correctly identify the file. The file can reside on the system or on a remote node; you do not need to have a file system on the node to which the program is being loaded. Arguments specify the initial stack size, job and process priority, and whether or not the debugger should be given control when the program starts. ELN$UNLOAD_PROGRAM, which unloads the specified program from the system. Job, Process, and Memory Management 3-13 One restriction is that shareable images that the dynamically loaded program references must be included in the system at system build time. The Guaranteed image list entry on the Edit System Characteristics Menu allows you to specify the images that are needed by the dynamically loaded programs. These specified images are merged with those needed by other programs, and the System Builder resolves any interdependencies. Another entry on the same menu, Dynamic program space, specifies the number of memory pages that can be used by dynamically loaded programs. The number is a quota and does not cause the pages to be allocated until the program is actually loaded. (For more information, see the VAXELN Development Utilities Guide.) 3.3.5 Scheduling in Multiprocessing Configurations Each processor involved in a loosely or closely coupled multiprocessing configuration (see Figures 1-5, 1-7, and 1-8) executes its own copy of a VAXELN system image. Thus, the kernel uses the single-processor scheduling rules to schedule the jobs and processes on each processor participating in these configurations. However, in a tightly coupled symmetric multiprocessing configuration (see Figure 1-6), application components running on different processors share a single copy of the VAXELN system image, including the kernel. In this case, the kernel can select a ready job to run on any available processor. Once a job begins to run on a processor, all its subprocesses run on that processor also. If the job is not eligible to run on the selected processor, the kernel reschedules the job for execution on a valid processor. The scheduling of a job for a particular processor may preempt the processor's execution of a lower-priority job. 3.4 Kernel Services for Processes and Jobs The kernel services affecting the state of PROCESS objects are summarized in Sections 3.4.1 to 3.4.20. 3-14 Job, Process, and Memory Management 3.4.1 CREATE_JOB Procedure The CREATE_JOB procedure creates a new job that executes a specified program image. The procedure returns the new job port value. The caller can use this value to send messages to the new job. The same value can be obtained within the new job by the JOB_PORT procedure. For program images that require arguments, you can specify the arguments as strings in an optional argument list. The argument list must specify all required argument values for the specified program image. An optional argument identifies a port to be notified of the created job's termination. If this argument is present, a termination message is sent to the port when the new job terminates. The termination message is the integer completion status of the created job's master process. If the argument is omitted, no message is sent. The job's master process can return an explicit status with the EXIT procedure; if it specifies no status and completes successfully, the default status returned in the termination message is 1 (success). An unhandled exception condition causes the value of the exception to be returned. CREATE_JOB runs a program image already built into the system (with the System Builder), or it executes program images that are loaded dynamically with the ELN$LOAD_PROGRAM procedure after the initial system is built. 3.4.2 CREATE_PROCESS Procedure The CREATE_PROCESS procedure creates a new subprocess running the specified process block or function, returning the new PROCESS value that identifies the process. An optional list of up to 31 arguments can be passed to the created process. An optional integer variable receives the final (exit) status of the created process. The variable must be in shared space. Such a value can be returned by the created process with the EXIT procedure. If the argument is omitted, no such status is returned. An unhandled exception condition causes the value of the exception to be returned. Job, Process, and Memory Management 3-15 3.4.3 CURRENT_PROCESS Procedure The CURRENT_PROCESS procedure returns a PROCESS value that identifies the calling process. 3.4.4 DELETE Procedure The DELETE procedure removes the PROCESS object from the system. When a process is deleted, if another process is waiting for its termination, that aspect of its wait condition is satisfied permanently. When a master process is deleted, all subprocesses in the same job are deleted, along with the data and kernel objects created by processes in the job. The exit status of a deleted process is KER$_NO_STATUS. 3.4.5 DISABLE_SWITCH Procedure The DISABLE_SWITCH procedure disables process switching for the job from which it is called. The calling process continues executing, regardless of the priorities of other processes in the job, until switching is reenabled with ENABLE_SWITCH. If the process that calls DISABLE_SWITCH blocks and requires action from another process in the same job before it can resume, deadlock resul ts - that is, the blocked process cannot unblock. NOTE Process switching is reenabled automatically if the process calls EXIT or deletes itself. DISABLE_SWITCH is necessary only when a process must perform an operation with assurance that it will not be preempted by other processes in the job. 3-16 Job, Process, and Memory Management 3.4.6 ENABLE_SWITCH Procedure The ENABLE_SWITCH procedure restores preemptive process scheduling, or switching, for the calling job. When process switching is enabled, the control of the CPU is given to the highest-priority process in the job that is ready to run. The procedures ENABLE_SWITCH and DISABLE_SWITCH count the number of times they are called; switching is enabled only if the number of calls to ENABLE_SWITCH is equal to the number of calls to DISABLE_SWITCH for a particular process. 3.4.7 EXIT Procedure The EXIT procedure causes an immediate exit from the calling process. The procedure is similar to deleting the current process, except that it can optionally return an exit status to the process that created it. Process switching, if disabled by the process, is reenabled automatically, so control goes to the highest-priority process in the job that is ready to run. If the calling process is the master process, all the objects it owns, including subprocesses, are deleted; all open files are closed. 3.4.8 KER$GET_JCB Procedure The KER$GET_JCB procedure returns a job control block (JCB) address. In a tightly coupled symmetric multiprocessing configuration for example, the VAX 8800 multiprocessor - the procedure saves the current interrupt priority level (IPL), raises the IPL to 4 so that the job will not be switched to run on another processor, gets the JCB address, and restores the initial IPL. (In a single-processor configuration, the procedure accesses the JCB address without raising the IPL.) The returned address can then be used to read fields in the JCB. User-mode programs in a tightly coupled multiprocessing configuration must use this procedure to access fields of the JCB. Kernel-mode programs in the same configuration can either use this procedure or perform the equivalent set of operations, including raising the IPL to 4. The ability to use this procedure in single-processor configurations, where it is not necessary to protect against a job being switched to a different processor, is provided so that the same source code can be used in all configurations without modification. Job, Process, and Memory Management 3-17 3.4.9 KER$GET_USER Procedure The KER$GET_USER procedure returns the user identity of either the calling process or the partner process connected by a circuit to the caller's port. An optional argument specifies a port connected in a circuit; if this argument is supplied, the port must be connected in a circuit that the caller has accepted with the ACCEPT_CIRCUIT procedure. Valid information is not returned if the caller initiated the connection with CONNECT_CIRCUIT; that is, KER$GET_USER can provide information only about the object of a connection, not the subject. Other optional arguments return the user name string and the UIC of either the calling process or the partner process. If the circuit is from a remote user, but there is no Authorization Service available in the system - that is, the Authorization required entry on the System Builder's Edit Network Node Characteristics Menu is NoKER$GET_USER returns 0 for the UIC parameter. 3.4.10 INITIALIZATION_DONE Procedure The INITIALIZATION_DONE procedure informs the kernel that the calling program has completed an initialization sequence and that other programs can be created and made eligible to run. This procedure does not cause the calling job to block. The calling job continues to run until some other occurrence causes it to block. The INITIALIZATION_DONE procedure is exclusively for programs that have the System Builder Init required program attribute. NOTE Context switching is disabled during initialization. 3.4.11 KER$NAME_OBJECT Procedure The KER$NAME_OBJECT procedure names a specified process by creating a unique NAME object that associates a character string with the process. The procedure helps you identify the process when you use the remote debugger and 'other VAXELN development utilities. 3-18 Job, Process, and Memory Management This procedure is similar to the CREATE_NAME procedure that creates names for message ports (see Chapter 5), except that process names do not have the local or universal attribute that is associated with port names. NOTE KER$NAME_ OBJECT is used only in Pascal programs; to get the equivalent process-naming feature in C, you call KER$CREATE_NAME with a special set of arguments. See the VAXELN C Runtime Library Reference Manual for details. 3.4.12 KER$RAISE_PROCESS_EXCEPTION Procedure The KER$RAISE_PROCESS_EXCEPTION procedure raises the asynchronous exception KER$_PROCESS_ATTENTION in the specified process. 3.4.13 RESUME Procedure The RESUME procedure resumes the execution of a suspended process. A resumed process is ready to run but is not necessarily running. If the process was waiting when it was suspended, the wait is repeated when it is resumed. Asynchronous exceptions that occurred during the suspension are raised when the process runs, including the exception KER$_QUIT_SIGNAL that results from signaling the process itself. 3.4.14 Setting a Job's Processor Eligibility A job's processor eligibility is determined when the job is ready to run based on information in the job's job control block (JCB). An application program can alter this eligibility information while executing by calling the KER$SET_JOB_ELIGIBILITY procedure. An argument supplies Boolean values that indicate job eligibility for each processor in your target configuration. TRUE means a job is eligible to run on a processor; FALSE means a job is not eligible to run on a processor. Whether the master process or a subprocess calls the procedure, the call changes the processor eligibility for the entire job. If a job's new eligibility makes the job ineligible to run on its current processor, the Job, Process, and Memory Management 3-19 kernel reschedules the job for execution on a valid processor; otherwise, no rescheduling takes place. The KER$SET_JOB_ELIGIBILITY procedure is most useful for programs that run in multiprocessor configurations. However, code that includes the procedure can run on both single-processor and multiprocessor configurations. On a single-processor system, the procedure changes the job's eligibility mask but has no other effect, even if the user argument specifies ineligibility for the single processor. In multiprocessor configurations, jobs are initially eligible to run on any available processor. If the configuration includes a VAX 8800 multiprocessor and a device driver job calls the CREATE_DEVICE procedure, the kernel ties the job to the processor that handles the device's interrupts. This lets the driver raise the processor's IPL with a call to DISABLE_INTERRUPT to synchronize access to the device communication region. Synchronization using an elevated IPL is not possible if interrupts are being handled by the other processor. For multiprocessor configurations that let devices interrupt any processor (such as the VAX 62nn multiprocessor), you can use the KER$SET_ JOB_ELIGIBILITY procedure to make a user-created job eligible on a specified set of processors. (This is also true for a driver running on a VAX 8800 multiprocessor, as long as the driver does not use an elevated IPL to synchronize access to the device communication region.) However, the procedure affects only the job for which the call is made; it does not keep other jobs, including system jobs such as the debugger and drivers that Digital supplies, from running on the specified processors. In a tightly coupled multiprocessor configuration, at least one available processor must be eligible to run the job. If the job cannot run on any of the processors that are up and running as part of the configuration, the kernel returns the status value KER$BAD_VALUE. 3.4.15 SET_JOB_PRIORITY Procedure The SET_JOB_PRIORITY procedure resets the scheduling priority of the current job to an integer in the range 0 to 31. Priority 0 is the highest. The initial priority for a job can be set by the System Builder as part of a program description or by the ELN$LOAD_PROGRAM procedure; the default is 16. Raising job priority causes the calling job to continue execution at the higher job priority. Lowering job priority allows a ready job with higher (or equal) combined job and process 3-20 Job, Process, and Memory Management priority, if there is one, to gain control of the processor; otherwise, the calling job continues execution at the lower job priority. Jobs and processes in a VAXELN system are scheduled on a preemptive priority basis. When scheduling an idle processor or arbitrating possible job preemption, the scheduler allocates the processor to the ready job with the highest combined job and process priority. That is, the scheduler selects the job with the highest job priority or, among jobs of equally high job priority, the job with the highest-priority ready process. Preemption occurs when a process entering the ready state becomes the highest-priority ready process in its job, such that the ready job then has a higher combined job and process priority than the running job. The scheduling scheme can be extended to allow a running job to give up control to a ready job of equal combined job and process priority, without lowering its own priority. If running job a issues a call to SET_ JOB_PRIORITY that specifies its current priority, one of the following occurs: • • If another job, b, of the same combined priority is ready, job b is placed in the running state. The voluntarily preempted job a is placed in the ready queue behind remaining jobs of equal combined priority. If no other job of the same combined priority is ready, the running job continues in the running state. The SET_PROCESS_PRIORITY procedure resets the scheduling priority of a process to an integer in the range 0 to 15. Priority 0 is the highest. The initial priority for the processes in a job can be set by the System Builder as part of a program description or by the ELN$LOAD_ PROGRAM procedure; the default is 8. When arbitrating possible process preemption within a job, the scheduler selects the process with the highest process priority. Preemption occurs within a job when a process becomes ready with higher priority than the job's current process. The scheduling scheme can be extended to allow a running process to give up control to a ready process of equal priority within the same job, without lowering its own priority. Job, Process, and Memory Management 3-21 If process switching is enabled and process a issues a a call to SET_ PROCESS_PRIORITY that specifies its own process value and its current priority, one of the following occurs: • • 3.4.17 If another process, b, of the same priority within the same job is ready, process b is placed in the running state. The voluntarily preempted process a is placed in the ready queue behind remaining processes of equal priority within the same job. If no other process of the same priority within the same job is ready, the running process continues in the running state. KER$SET_USER Procedure The KER$SET_USER procedure sets the user identity of the current process. A string of up to 20 characters specifies the user name to be associated with the process. An integer supplies the user identification code (UIC) to be associated with the process. 3.4.18 SIGNAL Procedure Signaling a process with a call to SIGNAL raises the exception KER$_ QUIT_SIGNAL for that process. If the process needs to perform special operations, such as deallocating resources, before exiting, it must have established an exception handler to handle the KER$_ QillT_SIGNAL exception. If the process does not have an established exception handler or if the exception handler resignals the exception, the kernel forces the process to exit. The exception handler should resignal the exception if the job is to exit after the special operations are completed. 3.4.19 SUSPEND Procedure The SUSPEND procedure suspends the execution of a process. If the process is waiting, as a result of a WAIT_ANY or WAIT_ALL call, it is removed immediately from the waiting state and then suspended. If the process is resumed later, the wait is repeated. 3-22 Job, Process, and Memory Management 3.4.20 WAIT_ANY and WAIT_ALL Procedures The WAIT procedures make a process wait for 0 to 250 wait conditions (conditions pertaining to the state of objects) to be satisfied. WAIT_ ANY allows the invoking process to continue if a wait condition is satisfied; WAIT_ALL requires that all the conditions be satisfied simultaneously. A wait for a PROCESS object is satisfied when the process terminates. Waiting causes no modification to a PROCESS object, and all waiting processes continue if their wait conditions are otherwise satisfied. Both procedures can specify a timeout argument, which defines either a time interval or absolute time after which the waiting process proceeds regardless of the states of the objects. 3.5 Memory Management VAXELN uses the VAX memory management hardware to map jobs in a virtual address space. Although knowledge of VAX memory management is not essential for understanding this section, you may find it more useful if you are already familiar with VAX memory management terminology. Figure 3-4 illustrates a typical mapping. Each job created by VAXELN executes a program image. You build program images into the system image with the System Builder or load them dynamically with the program loader. The shareable runtime library modules and kernel are not included as part of a program image but are images themselves. When a VAXELN system is booted, the kernel maps the system image (kernel, program, and shareable runtime images) into the SO virtual address space (the system region). The system region maps the system image and kernel data, as shown in Figure 3-5. Job, Process, and Memory Management 3-23 Figure 3-4: Memory Allocation f"_ Master Process Code P~~M{ PO SYSTEM REGION Global Data Program Image -------, Subprocess 1 Code ~< Dynamic Memory Kernel Image Subprocess n Code Program 1 Image Job Context Page -< Program 2 Image I SO Program n Image Shareable Runtime Image Subprocess 2 Code Subprocess n Job Heap Data Job Message Buffer User Stack No Access Page P1 Kernel Stack Dynamic Memory Process Context Page CONTROL REGION Master Process Local Data MLO-004277 When the kernel creates a job, it generates a PO page table and maps the job's program image, data, and message buffers into PO virtual address space (the program region) as shown in Figure 3-6. If multiple jobs in a system use the same program image, the kernel makes a copy of the image's read/write data for each job and lets all jobs share the same read-only code and data. 3-24 Job, Process, and Memory Management Figure 3-5: System Region Kernel Image :80000000 Program 1 Image Program 2 Image Program n Image Shareable Runtime Images Kernel Pool and Data Unmapped :BFFFFFFC MLO-004278 Figure 3-6: Program Region Program Image :00000000 Job Context Page Job Dynamic Memory Job Heap Data Job Message Buffers Unmapped :3FFFFFFC MLO-004279 Job, Process, and Memory Management 3-25 The kernel uses PO virtual address space for static variables and message text. The kernel makes a copy of the read/write data, although no copy is made of read-only code and data. If multiple jobs in a system run the same program, only one copy of the read-only code and data exists, with as many copies of the read/write data, message data, and heap data as jobs running the program. Since the runtime library uses heap data for many of its data structures, the kernel also maps the context of open file variables into PO address space so the runtime libraries can use the variables for their data structures. A job's processes share its PO page table and PO address space. Thus, the processes can access the same job-level data. The processes can coordinate their access to this data by using synchronization techniques. A pointer to a data item in the PO address space can be passed to any process in the job. A pointer cannot be passed to a process in another job, since the pointer refers to a different data item in that job's PO region. In addition to setting up static memory mapping, the kernel manages the data associated with dynamically created processes. When the kernel creates a process, it generates a PI page table and maps a kernel and user stack into Pl virtual address space (the control region). Each process in a job, including the master process, has its own pair of stacks, which store process-specific data, such as local variables and procedure call frames. The kernel uses PI virtual address space exclusively for dynamic memory; it does not map any of the program image. Kernel procedures and kernel mode programs use the fixed-sized kernel stack. The kernel expands the user stack as necessary, enabling programs to start out with minimal stack space. This feature saves space that can be wasted when memory is preallocated. The kernel stack for a user-mode process occupies two pages. The stack is used by the VAXELN Kernel when executing kernel procedures and dispatching exceptions. Kernel-mode processes have only a fixed-size kernel stack that is used by both the process and the VAXELN Kernel procedures. If the kernelmode stack overflows, the fatal exception KER$_KERNEL_STACK is returned. When this exception is delivered, the kernel stack pointer is reset to the base of the original stack, and the previous contents of the stack are lost. The size of the kernel-mode stack is specified as a program attribute. 3-26 Job, Process, and Memory Management In addition to the stacks, the PI address space contains process context data. This data represents context information that is used by the VAXELN Kernel, debugger, and runtime library routines. Figure 3-7 shows the PI region of the VAX virtual address space. Figure 3-7: Control Region Unmapped :40000000 User Stack No Access Page Kernel Stack Process Context Data :7FFFFFFC MLO-004280 3.5.1 Managing Stack Usage When the kernel creates a process, it generates a PI page table and maps a kernel and user stack into PI virtual address space (the control region). Each process in a job (including the master process) has its own pair stacks, which store process-specific data, such as local variables and procedure call frames. For most programs, VAXELN manages stack usage sufficiently. Kernel procedures and kernel-mode programs use the fixed-size kernel stack. The kernel expands the user stack as necessary, enabling programs to start out with minimal stack space. This feature saves space that can be wasted when memory is preallocated. Job, Process, and Memory Management 3-27 You may need to control stack usage in the following cases: • • • When stack usage varies widely during process execution. The kernel extends user stacks as. necessary. However, since the kernel knows nothing about a program's behavior, it does not trim stacks. Thus, if the stack space allocated for a process significantly exceeds the amount of space that the process requires at a certain point during execution, space is wasted. When the stack size that you specify for a kernel-mode program causes stack space to be wasted. The kernel allocates the size that you specify to each process in the program's job. Again, if the stack usage for each process varies significantly, stack space may be wasted. When kernel stack overflows occur. Kernel stack overflows may occur because kernel stacks are not dynamically extended as are user stacks. Your programs can control these conditions by calling the ELN$DEALLOCATE_STACK and ELN$ALLOCATE_STACK procedures. These procedures extend and contract the stacks during program execution. Use the ELN$DEALLOCATE_STACK procedure to trim a stack by a specified number of bytes, without trimming beyond the page containing the current stack pointer (SP). If the stack does not contain the specified space, the kernel trims the stack to the page in which the procedure is running. Thus, you can trim the stack to the currently needed size by specifying an overly large number. Use the ELN$ALLOCATE_STACK procedure to verify the availability of an amount of stack space. If the stack space is not available, the procedure allocates the additional space needed to satisfy the request. This procedure is most useful for allocating stack space for kernel-mode programs that demand more stack space than was allocated when the system was built. This procedure is not as useful for user-mode programs because the kernel automatically extends the stack as needed by the process. If a program produces an exception that i;ndicates an invalid kernel stack; you should suspect inadequate stack size (kernel stack overflow) as a possible cause. For an example of how a kernel stack overflow can occur, consider the following situation. When a program running in kernel mode issues a call to WRITELN, the procedure's arguments (and other information) are pushed onto the kernel stack allocated for that program. The WRITELN procedure in tum calls a routine in the runtime library, which pushes yet more information onto the stack. Since kernel stacks are not automatically extended at runtime, this 3-28 Job, Process, and Memory Management single call to WRITELN can cause the stack to overrun its allotted size and result in system failure. Any kernel-mode program that calls nested subroutines can encounter kernel stack overflows. To prevent such overflows, you must allocate adequate kernel stack space for kernel-mode programs. If you suspect that kernel stack overflows are occurring, specify a larger kernel stack size in the program's description; then rebuild the system. To avoid or correct the problem at runtime, call the ELN$ALLOCATE_STACK procedure from the offending program. 3.5.2 Allocating Memory The procedures summarized in Sections 3.5.2.1 to 3.5.2.5 allocate and free memory. 3.5.2.1 ALLOCATE_MEMORY Procedure The ALLOCATE_MEMORY procedure allocates physical memory pages (not necessarily contiguous) into contiguous virtual address space of the job that calls it. The allocated memory can be placed at a specified virtual address or at a virtual address selected by the kernel. The procedure returns the address at which the memory is allocated. The caller specifies the size of the needed memory in bytes, but allocation is done in units of memory pages (512-byte pages). The size is rounded up to page-sized units before the allocation. Allocation always begins on a page boundary. If the allocation virtual address was selected by the kernel, the address will be in the PO or shared region of the job's virtual memory. The caller can specify any virtual address, so it is possible to allocate memory in the P1 or stack region, as well as at a particular memory location in PO. Most high-level languages provide a higher level and more controlled means of allocating and freeing dynamic memory - for instance, the Pascal NEW procedure and the C calloc or malloc functions. Use these procedures if you do not need to allocate memory at a specific location, or if you need to allocate memory in different units than a page (512 bytes). The smallest unit you can allocate with NEW is 8 bytes. Job, Process, and Memory Management 3-29 Use the ALLOCATE_MEMORY procedure for large temporary memory allocations or to allocate memory at a specific virtual or physical address. ALLOCATE_MEMORY is a low-level operation that is used by programs that need direct control of memory allocation or is used as a building block to provide a higher-level service. The ALLOCATE_MEMORY procedure also allows a kernel-mode caller to specify the exact physical address at which to start the allocation. If you specify a physical starting address, the memory allocated is physically contiguous. This feature is intended for specialized applications, for example, multiported memory or video bitmap memory. The kernel does not restrict the use of this parameter and does not check that the value is consistent with the state of the system. Therefore, it is possible to accidentally double map pages of memory that are already in use. 3.5.2.2 KER$ALLOCATE_SVSTEM_REGION Procedure The KER$ALLOCATE_SYSTEM_REGION procedure allocates memory in system (SO) address space. The memory allocated is virtually and physically contiguous, and the virtual addresses come from the system region you specify on the System Builder's System Characteristics Menu. This procedure can be called only by programs running in kernel mode. You might use KER$ALLOCATE_SYSTEM_REGION to map a device's 1/0 space control status registers (CSRs) into SO virtual address space. Typically, the kernel maps the 1/0 space for a system's device CSRs into SO address space at initialization time, and calls to CREATE_DEVICE return a pointer to the first CSR for a device. The kernel does not do this mapping for all devices. For example, the mapping is not done for devices on systems that use an integral bus. Device drivers for such devices can map the registers into SO address space by specifying the appropriate physical address and size in a call to KER$ALLOCATE_ SYSTEM_REGION. When you finish using an area of SO space, use KER$FREE_SYSTEM_ REGION to free it; deleting a process or job does not free SO space. 3-30 Job, Process, and Memory Management 3.5.2.3 FREE_MEMORY Procedure The FREE_MEMORY procedure frees the physical memory pages that are mapped to particular virtual addresses in the caller's address space. The caller specifies a base virtual address and a size in bytes. The procedure frees memory pages in the inclusive range from the base to the top. NOTE Be careful when you free memory that was not explicitly allocated by the caller, since it is difficult to determine the use of the virtual address range. For instance, deleting the process's stack can have unpredictable results. Dynamically allocated memory is normally freed with the languagespecific runtime library procedures provided by Pascal and C, that is, the Pascal DISPOSE procedure and the C free or cfree functions. Pointers to the freed memory become invalid. 3.5.2.4 KER$FREE_SYSTEM_REGION Procedure The KER$FREE_SYSTEM_REGION procedure frees memory in SO address space that was previously allocated with the KER$ALLOCATE_ SYSTEM_REGION procedure. The memory is freed from the system region you specify on the System Builder's System Characteristics Menu. This procedure can be called only by programs running in kernel mode. When you are finished using an area of SO space, use KER$FREE_ SYSTEM_REGION to free it; deleting a process or job does not free SO space. 3.5.2.5 KER$MEMORY_SIZE Procedure The KER$MEMORY_SIZE procedure scans the kernel memory data base and returns the initial main memory, the current free memory, and the current largest free memory block size (in 512-byte pages). The largest free block size is the size of the largest physically contiguous block of free memory. This value is useful if you need to create large MESSAGE or AREA objects, because these objects require contiguous memory for their data buffers. Job, Process, and Memory Management 3-31 While the KER$MEMORY_SIZE procedure performs the memory scan, other kernel operations are stopped; therefore, call this procedure only when necessary. 3.5.3 Loading VAXELN System Images onto KA800 Processors One way of setting up a closely coupled symmetric multiprocessing environment is to use the ELN$LOAD_KABOO_PROCESSOR procedure. By calling this procedure, a VAXELN application program can dynamically load VAXELN system images from a VAX Bnnn primary processor into the memory of KABOO processors attached to the primary processor's VAXBI bus. The ELN$LOAD_KABOO_PROCESSOR procedure provides a runtime interface to the KABOO loader, ELN:KABOO_ LOADER.EXE. At runtime, the loader waits on a port for load requests. To use the ELN$LOAD_KABOO_PROCESSOR procedure, you must build the KA800 loader's program image into the system that is to run on the primary processor. You must also include modules from the runtime libraries, as appropriate for the programming language you are using. A call to the ELN$LOAD_KABOO_PROCESSOR procedure must specify the VAXBI number and adapter number of the processor into which the system is to be loaded, the file specification of the system image to be loaded, and a variable that receives the load status. An optional argument lets you specify whether the kernel debugger is to be invoked when the system image is loaded. If you specify TRUE for the debugger argument, you must build the local debugger into the system image from which the ELN$LOAD_KA800_PROCESSOR call is made. The system image that is being loaded into a KA800 processor can reside on the primary processor or on a remote node. If you specify a system image file that resides on a remote node, you must identify the node in the specification as follows: area.node_number The following program calls ELN$LOAD_KABOO_PROCESSOR to load the remote system image 1.10::RTDISK:[CCSMP_APP]CCSMP.SYS into the memory of a KA800 processor with local debugging enabled. 3-32 Job, Process, and Memory Management MODULE load_ka800i INCLUDE $KASOO_LOAD_UTILITY; PROGRAM load_sys(INPUT,OUTPUT)i VAR load_stat : KA800_CODEi BEGIN ELN$LOAD KA800 PROCESSOR(BI NUMBER := 0, ADAPTER NUMBER := 7, FILE SPEC := '1.10: :RTDISK: [CCSMP APP]CCSMP.SYS' LOAD-STATUS := load stat, KDEBUG := TRUE); END; END. You can use the ELN$LOAD_KA800_PROCESSOR procedure to reboot a previously booted KA800 processor. You can also load a system image into the memory of a KA800 processor by entering a configuration file for the Argument(s) entry on the KA800 loader's Program Description Menu. VAXELN Development Utilities Guide explains the configuration file and how to load and boot a KA800 processor in a closely coupled symmetric multiprocessing configuration. Job, Process, and Memory Management 3-33 Chapter 4 Synchronization In addition to performing scheduling and memory management tasks, the kernel coordinates the operations on kernel data structures. One category of such operations is process synchronization. Process synchronization is a mechanism for coordinating the concurrent execution of two or more processes. Using kernel procedures you can synchronize processes in the same job or processes in different jobs. You must synchronize processes when they share a resource, depend on the completion of another process's execution, or wait for an external event to occur. The ability of a process to gain exclusive access to a shared resource is called mutual exclusion. The ability of a process to coordinate its activities with other processes is called event response. To attain controlled access to limited resource units or coordinate event response, processes wait for one or more conditions to exist by calling the WAIT_ALL or WAIT_ANY kernel procedure. These procedures provide a method by which processes wait and define the condition under which processes can proceed again. Section 4.1 provides a general overview of how to synchronize process execution. The rest of this chapter explains how to use VAXELN Kernel procedures to synchronize processes based on the following: • • • • A specified time, Section 4.2 Process completion, Section 4.3 Signaling of a semaphore or mutex, Section 4.4 The occurrence of an event, Section 4.5 Synchronization 4-1 4.1 Synchronizing Process Execution You synchronize execution of an application's processes by doing the following: • • • Creating AREA, DEVICE, EVENT, PORT, PROCESS, and SEMAPHORE kernel objects for which the processes can wait Using the WAIT_ANY or WAIT_ALL kernel procedure to make processes wait for the kernel objects Defining the way processes are to resume after waiting The WAIT_ANY and WAIT_ALL procedures accept a list of up to 250 AREA, DEVICE, EVENT, PORT, PROCESS, or SEMAPHORE values (including various combinations of object types). When using the WAIT_ANY procedure, the calling process waits until anyone of the specified objects is signaled. When using the WAIT_ALL procedure, the calling process waits until all the specified conditions are satisfied simultaneously. When an object is signaled and all other specified conditions are satisfied, the wait is otherwise satisfied. Once a wait is satisfied (or otherwise satisfied), the process returns to the ready state and can continue executing. An optional result argument receives the number of the argument that satisfied the wait for a call to WAIT_ANY. You can also supply a timeout argument, which defines either a time interval or absolute time after which the waiting process can proceed, regardless of the states of specified objects. NOTE When you specify more than four objects in calls to WAIT_ ALL and WAIT_ANY, you should account for the following additional overhead that is incurred: • 4-2 Synchronization Additional pool blocks are required to wait for the specified objects. When creating a process, the kernel allocates one pool block for the control structures that allow the process to wait for four objects. For example, if you specify five to eight objects, the kernel allocates an additional pool block to support the wait. If you specify nine objects, the kernel permanently allocates two additional pool blocks to the process. The second pool block could support waits for nine to twelve objects. • Additional time needed to process waits. As the number of objects increases, the time required to process, test, and satisfy a wait increases. Specifying a large number of objects may also affect the process latency of driver processes that run at high job priorities. Such processes require quick response time to device interrupts. For more information, see Chapter 6. Each call to WAIT_ANY or WAIT_ALL causes the calling process to wait for a resource or event as follows: • • • • Waiting on an AREA, EVENT, or SEMAPHORE object means waiting for the object to be signaled. Waiting on a DEVICE object means waiting for the connected interrupt to be signaled by an interrupt service routine (ISR). Waiting on a PORT object means waiting for a message to arrive at that port. Waiting on a PROCESS object means waiting for the identified process to terminate. Wait operations affect the kernel objects and the processes waiting on those objects in the following ways: • • • • Satisfying a wait on a SEMAPHORE object causes the kernel to decrement the semaphore count. At most, one process continues when a semaphore is signaled. Satisfying a wait on an EVENT, PORT, or PROCESS object causes no modification to the object, and all waiting processes continue if their wait conditions are satisfied. Satisfying a wait on an AREA object depends on whether the area is associated with an event or semaphore. If the area is associated with an event, the object is not modified and all waiting processes continue if their wait conditions are satisfied. If the area is associated with a semaphore, the kernel decrements the semaphore count and at most, one process continues. Areas associated with events provide a mechanism for inteIjob event synchronization. Satisfying a wait on a DEVICE object causes the object to be cleared if the wait is satisfied by an ISR signaling the object. Only one process continues as a result of the action of an ISR. Synchronization 4-3 The WAIT procedures return immediately with an error if one of the argument objects does not exist or is deleted. Both procedures also return immediately if the necessary conditions were satisfied before the call was made. Since the WAIT_ALL procedure waits for a number of conditions to be simultaneously satisfied, deadlock cannot occur. Deadlock occurs when two or more processes wait for the same set of resources, each holding onto some resources while waiting for others to become available, such that no process can get all the resources it needs to continue. Since WAIT_ALL does not lock up some resources while waiting for others to become available, deadlock is not a problem, provided that all the conditions (events, semaphores, and so forth) are known and are listed in a single call. WAIT_ALL is also a more efficient way to wait for two or more objects, which need to be satisfied simultaneously, than using multiple calls to WAIT_ANY. To program process synchronization, you can use the WAIT_ALL and WAIT_ANY procedures along with the following routines: Routine Description Sets the state of an event or an area's event to EVENT$CLEARED. Creates a new area or maps an existing area of memory into the calling job's PO virtual address space and associates the area with a binary semaphore. Creates a new area or maps an existing area of memory into the calling job's PO virtual address space and associates the area with an event. Creates a new area or maps an existing area of memory into the calling job's PO virtual address space and associates the area with a semaphore. CREATE_EVENT Creates an event. CREATE_MUTEX Creates a mutex. CREATE_PROCESS Creates a process. CREATE_SEMAPHORE Creates a semaphore. 4-4 Synchronization Routine Description Gets the identifier for the current process. DELETE Deletes an area, event, semaphore, or process. DELETE_MUTEX Deletes a mutex. GET_TIME Returns a processor's system time. KER$GET_UPTIME Returns a time interval indicating the time that has elapsed since system initialization. LOCK_MUTEX Locks a mutex. SET_TIME Sets a processor's system time. SIGNAL Signals an event, a semaphore, or an area's associated event or semaphore. Unlocks a mutex. The rest of this chapter explains how to use the preceding routines and WAIT_ALL and WAIT_ANY to synchronize process execution using the following: • • • • Time values, Section 4.2 Process completion, Section 4.3 Semaphores, Section 4.4 Events, Section 4.5 For descriptions of the routines, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. AREA, MESSAGE, and PORT objects are used for programming process and job communication, and DEVICE objects are used for programming application device handling. For information about using areas, ports, and the wait procedures to program process and job communication, see Chapter 5. Chapter 6 explains how to use device objects and the wait procedures to program VAXELN device handlers. Synchronization 4-5 4.2 Using Time Values to Synchronize Process Execution You can synchronize process execution by waiting for a specified date and time to occur or for a time interval to elapse. An application can wait on a time value in addition to or instead of kernel objects. If you synchronize processes using time values, you may need to get and set the system time. Section 4.2.1 explains how to synchronize processes by waiting on time and Section 4.2.2 explains how to retrieve and set the system time. 4.2.1 Waiting on Time To wait on time, a process must issue a call to WAIT-ALL or WAIT_ ANY that specifies a signed, 64-bit time value. A time value can be an absolute time (a specific date and time) that indicates when the process can continue or a time interval relative to the current system time that indicates how long the process must wait before continuing. You specify an absolute time in the following format: 'dd-mmm-yyyy hh :mm:ss .cc' The following table defines the absolute time value components: Component Meaning Value Range dd Day of the month 1 to 31 mmm Month JAN to DEC yyyy Year 1858 to 9999 hh Hours o to 23 mm Minutes Oto 59 ss Seconds o to 59 cc Hundredths of a second o to 99 You specify a time interval as follows: 'dddd hh:mm:ss.cc' 4-6 Synchronization The following table defines the time interval value components: Component Meaning Value Range dddd Days hh Hours o to 9999 o to 23 mm Minutes Oto 59 ss Seconds cc Hundredths of a second o to 59 o to 99 By convention, positive time values represent absolute time; negative time values represent time intervals. If you do not specify a time value, the calling process unblocks only when the specified wait object conditions are otherwise satisned. You can issue a conditional wait that will not block, by specifying a timeout value of O. Specifying 0 ensures that the WAIT procedures check for satisfied conditions and then return immediately. If the returned wait result is 0, the wait condition specified by the objects was not satisfied. The kernel expects and returns time values in 64-bit time value format. Thus, applications must convert absolute time and time interval format strings to and from 64-bit time value format, as appropriate. Runtime routines for converting time value formats are available in Pascal, C, and FORTRAN. See the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual for more information. The VAXELN Pascal, C, and FORTRAN language runtime libraries provide routines for dealing with time values conveniently. For example, you can use the routines to convert a time value to an ASCII string for printing, or an ASCII string in an absolute or interval time format to a time value for time value operations. Synchronization 4-7 4.2.2 Retrieving and Setting the System Time Before specifying an absolute time value in a call to WAIT_ANY or WAIT_ALL, you should set the system time. The system time is absolute and is maintained by the VAXELN Kernel as a 64-bit binary number. The system time is interpreted as the number of 100-nanosecond intervals since the base time, 00:00:00.00, November 17, 1858. The kernel uses the system's interval timer to maintain the system time. Thus, the system time is in effect for all jobs running on that system. You can set and get a system's time by using the SET_TIME, GET_ TIME, and KER$GET_ UPTIME procedures. A processor's system time is not necessarily preserved across power failures and is not set to a default value by the kernel or other system software. Thus, you should use SET_TIME to initialize the system time in an initialization job (see the VAXELN Development Utilities Guide) and in a handler for the KER$_POWER_SIGNAL exception. For example: SET_TIME(TIME_VALUE('10-MAR-1990 00:00:60')); You can also set the system time with the debugger and EeL command SET TIME. You can display the system time using the debugger and EeL command SHOW TIME. For information about the SET TIME and SHOW TIME commands, see the VAXELN Development Utilities Guide. If you set the system time while a wait that specifies an absolute timeout value is pending, one of the following effects occurs: • • • If you set the system time back, the timeout period is increased by the amount you set the time back. If you set the system time forward to a time that does not exceed the absolute timeout value, the waiting time is reduced to the difference between the new system time and the original timeout value. If you set the system time forward to a time that exceeds the absolute timeout value, the timeout occurs immediately. If a wait with an interval timeout value is pending, resetting the system time does not change the remaining timeout period. 4-8 Synchronization To retrieve the system time, use the GET_TIME or KER$GET_ UPTIME procedure. GET_TIME returns the current system time. KER$GET_UPTIME returns a time interval indicating the time that has elapsed since system initialization. The negative value representing the time interval decreases continuously regardless of system time resets. The following example illustrates the use of SET_TIME, GET_TIME, and KER$GET_UPTIME: MODULE time; INCLUDE $KERNEL; PROGRAM time; VAR set time value, get-time-value, uptime_v~lue : LARGE_INTEGER; time_str VARYING_STRING(23); BEGIN WRITE('Enter date and time (dd-mmm-yyyy hh:mm:ss.cc): '); READLN(time str); set time value := TIME VALUE (time str); SET=TIME(Set_time_value); { set the system time. GET TIME (get time value); { Get the current system time. time str := TIME STRING (get time value); WRITELN('The time is now ',-time=str); KER$GET UPTIME(,uptime value); { Get the elapsed system time. } time str := TIME STRING(uptime value); WRITELN('The system uptime i s ' time_str); END; END. 4.3 Synchronizing Process Execution Based on Process Completion Waiting for a process means waiting until the process has terminated. When one process waits for another, the second process is usually created by the waiting process, which needs it to complete some task before the waiting process can continue. Synchronization 4-9 The actions of the two processes are synchronized in the following way: 1. The first process (Process A) creates the process it must wait for (Process B). 2. Process A then calls WAIT_ALL or WAIT_ANY to wait for Process B. 3. Process B executes its process block until it terminates. 4. The termination of Process B satisfies the wait condition for Process A. 5. Process A continues its execution with the line of code following its call to WAIT_ALL or WAIT_ANY. To wait for a process, the process that wishes to wait (Process A) must specify the PROCESS variable associated with the process to be waited for (Process B) in a call to the WAIT_ALL or WAIT_ANY procedure. When Process A creates Process B and then waits for it, the same PROCESS variable is used in both the CREATE_PROCESS and the WAIT calls. When Process A does not create Process B, Process B's PROCESS variable must be globally accessible or must have been passed to Process A as an argument when Process A was created or in a message. The CREATE_PROCESS procedure has an optional EXIT parameter that allows the creating process to receive an exit status from the created process when the latter exits, if it terminates its execution with the EXIT procedure. The created process can supply the EXIT_STATUS value to indicate whether it has accomplished its task successfully. This EXIT_STATUS value is returned to the creating process in the variable passed as the EXIT argument to CREATE_PROCESS. When its wait has been satisfied by the termination of the created process, the creating process can check the EXIT status and take the appropriate action, based on the success or failure of the process it created. 4.4 Using Semaphores to Synchronize Process Execution Semaphores act as gates that control access to resources such as global variables, hardware resources, or the CPU. A semaphore maintains a count of the available units of a resource, such as the number of disk drives available, the number of gates available at an airport, or, for a railroad semaphore, the number of tracks (0 or 1) available to a train going in a particular direction. 4-10 Synchronization A semaphore's count value changes as processes wait on and signal the semaphore or area. As the value changes, it controls the execution of waiting processes, letting at most one process enter the ready state when a semaphore or area associated with a semaphore is signaled. When a process signals a semaphore or area associated with a semaphore, the semaphore count is incremented. When a process waits on a semaphore or an area associated with a semaphore, the process waits until the semaphore count is greater than O. When the count exceeds 0 (and, for WAIT_ALL, if all other wait conditions are satisfied) the process unblocks. When the kernel selects the process to execute, the procedure call returns and the process proceeds. If a wait is satisfied when the semaphore is signaled, the kernel decrements the semaphore count. The following sections explain how to do' the following: • • • • 4.4.1 Create semaphores, Section 4.4.1 Wait on and signal semaphores, Section 4.4.2 Delete semaphores, Section 4.4.3 Use mutexes, Section 4.4.4 Creating Semaphores An application creates and initializes a semaphore with a call to CREATE_SEMAPHORE. A call to'CREATE_SEMAPHORE must specify initial and maximum count integer values. The kernel also creates a semaphore when an application calls CREATE_AREA or CREATE_AREA_SEMAPHORE. When an application calls one of these procedures, the kernel creates an area and an associated semaphore. Like calls to CREATE_SEMAPHORE, calls to CREATE_AREA_SEMAPHORE must specify initial and maximum count integer values. In the case of CREATE_AREA, the kernel automatically initializes the initial and maximum count values to 1. Depending on the maximum count value that you specify, semaphores are either binary or counting. A binary semaphore has a maximum count of 1. You use a binary semaphore to guard a single item - often, a shared variable - from access by more than one process. The binary semaphore acts as a gate, letting only one process at a time get through to the resource behind it. When you signal a binary semaphore, the gate opens for one process and then closes. Synchronization 4-11 A semaphore that has a maximum count greater than 1 is a counting semaphore. A counting semaphore is like a gate that lets multiple processes through or a meter that keeps count of a finite resource's available units. In both cases, the initial semaphore count determines the initial· disposition of processes that issue a wait for the semaphore or area, independent of any signaling processes. A SEMAPHORE value created by a call to CREATE_SEMAPHORE can be used only within the job that creates it. The value identifies the same semaphore throughout the job. Multiple processes in the job can use the semaphore by sharing a variable or by passing the SEMAPHORE value as a process argument. SEMAPHORE values that the kernel associates with areas are valid in different jobs running on the same node. Thus, an application can use such an area to synchronize job execution. For information about using areas associated with semaphores, see Section 5.4. 4.4.2 Waiting On and Signaling Semaphores A process that wants to use a controlled resource waits on the semaphore or area by calling WAIT_ALL or WAIT_ANY. If the semaphore count is greater than 0, the count is decremented, ~d the process enters the ready state. If the count is 0, the process waits until another process signals the semaphore or area. If several processes wait for the same semaphore, the kernel places them in a queue in the order in which they call WAIT_ANY or WAIT_ALL. A process signals a semaphore or area when it no longer requires a resource. The SIGNAL procedure increments the semaphore count and, at most, one process unblocks if the wait is otherwise satisfied. If a process unblocks, the count is decremented. Thus, a semaphore's maximum count represents the available units of the resource being controlled. An application that needs to meter access to a 10-unit disk driver is an example of an application that might use a counting semaphore. The following Pascal example creates such a semaphore, initializes the semaphore such that all units are available initially, and places the SEMAPHORE value in the variable uniCavailable: 4-12 Synchronization VAR UNIT AVAILABLE: SEMAPHORE; BEGIN CREATE_SEMAPHORE(UNIT_AVAILABLE,lO,lO); Mter a process creates the semaphore, other processes needing disk drives wait on the semaphore by specifying unit_available in a call to WAIT_ANY or WAIT_ALL. Because the initial count is 10, the first 10 processes that wait on the semaphore continue immediately, and each time a process continues, the kernel decrements the count. When the count reaches 0 (assuming no process has released its drive in the meantime), the kernel places all processes that wait on the semaphore in the waiting state. These processes remain in the waiting state until a process releases its drive. The semaphore uses its count to meter disk drive availability. When a process is through using its drive, it can return the drive to the pool of available drives by signaling unit_available. The process at the head of the semaphore's queue can then access a drive and continue .... If the queue is empty, the next process to wait on the semaphore accesses the free drive. The following scenario illustrates the use of a binary semaphore to guard a shared data base: • • • A central data base is shared by a family of transaction-processing processes. When the master process begins execution, it creates a semaphore with maximum and initial counts equal to 1. The master process then creates worker subprocesses, as the need arises, to handle incoming data base inquiries. Each subprocess waits on the semaphore before accessing the shared data base and signals the semaphore when it is finished. Since the maximum value of the binary semaphore is 1, only one process can access the data base at a given time. Other processes must wait until the current worker signals the semaphore. When the semaphore is signaled, the next process can access the data base. Synchronization 4-13 4.4.3 Deleting Semaphores A process can delete a semaphore by specifying its value in a call to the DELETE procedure. When a process deletes a semaphore, the kernel unblocks all processes that are waiting on that semaphore and returns the completion status KER$_BAD_VALUE. When a process deletes an area that has an associated semaphore, the kernel removes all processes waiting on the area in the same job from the waiting state and returns KER$_BAD_VALUE. 4.4.4 Using Mutexes to Optimize Waiting and Signaling Operations You can improve the performance of binary semaphore waiting and signaling operations by using a mutex. (Mutex is an abbreviation for mutual exclusion semaphore.) Mutexes allow you to achieve the same effect as a binary semaphore without calling a kernel service unless contention exists. You can create, delete, lock, and unlock mutexes by using mutex procedures. To use these procedures, you must include one of the following modules: Language Module VAXELN Pascal C FORTRAN $mutex from VAXELNC.TLB $MUTEX from RTLOBJECT.OLB "ELN$:FORTRAN_DEFS.FOR" You create and initialize a mutex by specifying a variable of type MUTEX in a call to the ELN$CREATE_MUTEX procedure. The procedure initializes the mutex counter to -1, creates a SEMAPHORE object with an initial count of 0 and maximum count of 1, and stores the semaphore's identifying value in one of the mutex variable's fields. In addition to specifying a variable for the mutex, you can specify a variable that receives the completion status. Once you create a mutex, you can use the ELN$LOCICMUTEX and ELN$UNLOCK_MUTEX procedures to lock and unlock the mutex. ELN$LOCK_MUTEX provides the calling process with exclusive access to a shared resource. Generally, when a process locks a mutex, the process does not need to issue a wait before accessing the resource. The kernel issues a wait only if the mutex is aiready iocked. 4-14 Synchronization A process can relinquish exclusive access to a shared resource by calling ELN$UNLOCK_MUTEX. This procedure signals the semaphore if a process is waiting for access. If a binary semaphore is open (count = 1) and the semaphore is signaled, a count overflow error occurs. In contrast, the locking and unlocking of mutexes is not protected by this exception-raising mechanism. Under certain circumstances, in which two or more processes contend for a mutex, unlocking an already unlocked mutex can cause the calling process to block indefinitely. Therefore, when using mutexes, you should adhere to the following guidelines: • • You must make sure the first operation on an initialized mutex is a lock operation. You must pair lock and unlock operations within the code of the processes using the mutex. When a process is finished using a mutex, it can delete it by calling ELN$DELETE_MUTEX. This procedure deletes the mutex and the semaphore associated with it. A call to ELN$DELETE_MUTEX must specify the mutex you are deleting. You can also specify a variable to receive the completion status. 4.5 Using Events to Synchronize Process Execution An EVENT object represents the occurrence of an application-defined, realtime event. An event can be in one of two states: signaled or cleared. You can specify an event's initial state when you create the event. The following sections explain how to do the following: • • • Create events, Section 4.5.1 Wait on, signal, and clear events, Section 4.5.2 Delete events, Section 4.5.3 Synchronization 4-15 4.5.1 Creating Events An application creates and initializes an event with a call to CREATE_ EVENT. A call to CREATE_EVENT must specify the event's initial state: EVENT$CLEARED or EVENT$SIGNALED. The kernel also creates an event when an application calls CREATE_ AREA_EVENT. When an application calls this procedure, the kernel creates an area and an associated event. Like calls to CREATE_ EVENT, calls to CREATE_AREA_EVENT must specify the event's initial state - EVENT$CLEARED or EVENT$SIGNALED. 4.5.2 Waiting On, Signaling, and Clearing Events An event's state changes as processes clear and signal the event or area. Processes wait on an event by specifying the event's value in calls to WAIT_ANY or WAIT_ALL. If the event is in a signaled state, the processes continue immediately. Otherwise, the processes wait for another process to signal the event or area. Once the event is signaled, all waiting processes unblock if their wait conditions are otherwise satisfied. An EVENT value created by a call to CREATE_EVENT is valid only within the job that creates it. The value identifies the same event throughout the job. Multiple processes in the job can use the event by sharing a variable or by passing the EVENT value as a process argument. EVENT values that the kernel associates with areas are valid in different jobs running on the same node. Thus, an application can use such an area to synchronize job execution. For information about using areas that are associated with events, see Section 5.4. The particular realtime event represented by an EVENT object is application-specific. The conditions under which the EVENT object is signaled define its relationship to a realtime, real-world event. To the VAXELN Kernel, however, the EVENT object has only the properties signaled and cleared; nothing intrinsic in the EVENT object determines which process can signal it or what the signal means to waiting processes. The application designer must ensure that event signal and wait operations occur in a manner appropriate to the event's real-world meaning. For 'example, the following Pascal code fragment creates the EVENT object lights_on, and after determining that the 4-16 Synchronization lights are on, signals the event for processes that may be waiting for it. VAR lights_on: EVENT; BEGIN CREATE_EVENT (lights_on, EVENT$CLEARED); /* Check whether lights are on. */ SIGNAL(lights_on); The satisfied wait condition has no effect on the event's state. Once an event is signaled, it remains signaled until a process clears it with a call to the CLEAR_EVENT procedure. Processes waiting on the event have that part of their wait condition satisfied immediately. The CLEAR_EVENT procedure sets the state of an event or an area's event to EVENT$CLEARED. The following scenario illustrates the use of events: • • • • • A family of processes executes a series of steps that controls the operation of a chemical plant. One master process controls the sequencing of several other worker subprocesses. Each subprocess executes independently until it completes a step, at which time it must synchronize its execution with the master process. The master process is the first to execute, and it creates two events with initial states of cleared, that is, not signaled. The master process then creates each subprocess and gives it a control step to perform. The subprocesses race each other to complete their assigned work, and as each one finishes, it executes a WAIT procedure, specifying the first of the two events. When the master process determines it is time to perform the next control step, the master process signals the first event, which causes all the waiting subprocesses to continue. As the subprocesses finish the second control step, they again execute a WAIT procedure, but this time they specify the second event. Synchronization 4-17 • 4.5.3 Mter the appropriate amount of time, the master process clears the first event and then signals the second event. The worker subprocesses again continue, and so it goes until the work is finished. Deleting Events A process can delete an event by specifying its value in a call to the DELETE procedure. When a process deletes an event, the kernel unblocks all processes that are waiting on that event and returns the completion status KER$_BAD_VALUE. When a process deletes an area that has an associated event, the kernel unblocks all processes waiting on the area in the same job and returns KER$_BAD_VALUE. 4-18 Synchronization Chapter 5 Communication Processes and jobs exchange information by applying interprocess and inteIjob communication techniques. Processes in the same job communicate by using module-level variables and queues. Jobs communicate by passing messages and sharing areas of memory. Message-passing allows jobs to communicate whether or not they execute on the same node; sharing memory areas restricts communication to jobs executing on the same node. This chapter explains how to do the following: • • • • Share module-level data, Section 5.1 Share packets of data using queues, Section 5.2 Pass messages, Section 5.3 Share memory areas, Section 5.4 5.1 Sharing Module-Level Data A job's processes can communicate by sharing data. Most data is potentially shareable. However, a routine's local variables and value parameters are not shareable; the kernel stores this data in processspecific P1 virtual address space. Thus, the addresses of such data are meaningful only within the process allocating the data. The processes in a job can share module-level data that you declare outside routines: constants, variables, procedures, functions, and process blocks. The kernel makes this data available to all processes in a job by storing the data in the job's PO virtual address space. Since concurrently executing processes compete for the global data, you control access by using semaphores and mutexes. Communication 5-1 Processes can share the following entities by name (more than one process can refer to the variable by its name): • • • Pascal outer-level variables C variables declared with the attribute extern, globaldef, globalref, or static FORTRAN global commons Sharing can also be accomplished with pointers and, in Pascal, with process block variable parameters. Sharing constant data, including variables declared with the Pascal attributes READONLY or VALUE or the C attribute readonly, presents no programming problems. However, the sharing of data that is modified by one or more processes must be carefully managed to prevent unpredictable program behavior. In Pascal, you can use the following constructs to process data shared by processes within a job: • • • The READ~EGISTER and WRITE_REGISTER routines. (They are not restricted to operations on actual device registers.) The procedures INSERT_ENTRY and REMOVE_ENTRY, when used on the head and tail entries of a queue. The ADD_INTERLOCKED function. In C, the add_interlocked function is the only atomic (indivisible) function you can use safely to process data shared by a job's processes. (For information about sharing packets of data in C, see Section 5.2.) If you perform more complicated operations on shared data, you must synchronize access to the data. While one process is executing code that can modify the data, no other process can execute code that has access to the data. The synchronization must be done with kernel procedures or with the mutex routines (which call the kernel procedures when necessary). NOTE Failure to synchronize access to shared data results in unpredictable program behavior. A program that works on one processor model can fail on another; a change to the VAXELN system might cause program failure. 5-2 Communication Additional guidelines regarding shared data follow: • • • • • • Dynamic variables. Data allocated by the Pascal NEW procedure or the C calloc, ma1loc, or realloc function can be shared. The Pascal NEW and DISPOSE procedures and the C calloc, malloc, realloc, free, and cfree functions operate on single data items. File variables and file pointer variables. Pascal file variables and C file pointer variables (and the associated internal-file data structures) are subject to the same rules as other data. Most operations that use these variables are modify operations. Failure to synchronize access to a file can result in scrambled input or output data or in a runtime error (in Pascal if the runtime routines detect simultaneous access). Initialization of shared data. You should initialize shared Pascal outer-level variables, C external variables, and FORTRAN global commons in the master process before creating subprocesses. Otherwise, you might forget that the initialization operation must be synchronized. For example, you must initialize a mutex variable with a call to ELN$CREATE_MUTEX before you lock or unlock the mutex. Record locking. Programs that use shared data often must protect data that is more complicated than single variables.· For example, if multiple processes are updating records in a File Service file, they must synchronize access to the shared data and protect (or lock) records in the file. Otherwise, two read/write sequences on the same record can become interleaved. Shared messages. A message and its associated pointer can be manipulated by more than one process in a job, but the operations must be properly synchronized. For example, if process A deletes a message while process B is preparing to send it, ·the program may produce unpredictable results, such as the following: • Process B might receive the status KER$_BAD_VALUE from the SEND procedure because the message value is no longer valid. • Process B might incur an exception when it tries to access the message's buffer. • Process B might access new, unrelated data by using the address of the original message buffer. Communication regions. The communication region of an interrupt service routine (ISR) is shared between the ISR and the device driver processes. The program logic of the device driver must ensure that nonatomic operations are synchronized. Communication &-3 • Device registers. Device registers are not shared data in the sense used in the preceding guidelines. However; an ISR and device driver processes may need to synchronize access to the registers. In some cases, the registers symbolize the responses of a device to events that occur on a bus, such as read and write requests. The only routines you can use to ensure predictable operations on device registers are the Pascal READ_REGISTER and WRITE_REGISTER routines, the C read_register and write_register routines, or the FORTRAN ELN$READ_REGISTER and ELN$WRITE_REGISTER routines. 5.2 Sharing Packets of Data Using Queues In addition to sharing global data, a job's processes can communicate by using queues. Queues provide an efficient, highly structured means for a job's processes to exchange large packets of information. This section discusses the use of absolute queues - queues that use links that contain the absolute address of an entry to which it points. If you are programming in C, you have the option of using self-relative queues - queues that use links that contain a displacement from the present queue entry. Self-relative queues let two separate processes address the same queue, with each process able to treat the queue as residing at a different location in its virtual address space. For information about using self-relative queues, see the VAXELN C Runtime Library Reference Manual. VAXELN provides the predeclared data types and procedures you need to create and maintain queue structures. The procedures for inserting and removing queue entries use VAX machine instructions specifically designed to synchronize queue operations automatically. Thus, two processes can access a queue simultaneously: one can insert an entry while the other removes an entry. Use the queue data types (QUEUE_ENTRY and QUEUE_POSITION) and procedures (START_QUEUE, INSERT_ENTRY, and REMOVE_ ENTRY) to pass data messages between two or more processes within a job. Using queues this way is more efficient within ajob than using the SEND and RECEIVE procedures. Although you can use SEND and RECEIVE to send messages between processes in the same job, they are better suited to passing messages between jobs on the same or different systems in a network (see Section 5.3). 5-4 Communication Typically, you use a semaphore with each queue to signal the transition of the queue from an empty state to a nonempty state. The INSERT_ ENTRY procedure and the INSQUE instruction give information that allows you to synchronize queue operations. Therefore, the queue and the semaphore can work together to maintain lists and synchronize and schedule processes. Example 5-1 shows how you can use queues as a structured and efficient means of communicating between processes. The module consists of an initialization procedure and two process blocks. The procedure initializes the queues free_list and done_list; creates the semaphores free_lisChas_entry and done_list_has_entry for metering the content of each queue; and fills the free_list queue with entries. The process blocks, producer and consumer, communicate by inserting entries onto and removing entries from the two queues. The processes producer-process_l and producer-process_2 share the producer process block, which removes available entries from the free_list queue, fills the entries with data, and inserts the filled entries onto the done_list queue. Mter a producer process inserts the first entry onto the done_ list queue, the process signals the done_list_has_entry semaphore to let the consumer process know that a done_list queue entry is available. The consumer process block removes available entries from the done_ list queue, writes the entry's buffer data, and inserts the empty entries onto the free_list queue. Mter the consumer process inserts the first entry onto the free_list queue, the process signals the free_list_has_ entry semaphore to let the producer processes know that a free_list queue entry is available. Communication 5-5 Example 5-1: Using Queues for Process Communication MODULE producer_consumer; This module uses queues with semaphores to communicate between processes. } TYPE entry = RECORD links ident buffer END; CONST producer_max consumer max QUEUE_ENTRY; INTEGER; LARGE_INTEGER; A record type that represents } a queue entry. } The entry's flink and blink. Producer identifier. } A user data buffer. } 25; 50; VAR QUEUE_ENTRY; SEMAPHORE; SEMAPHORE; free list, done list free-list has e~try done=list=has=entry { Decl.are queue headers. { Declare semaphor~s. } PROCEDURE initialize; This procedure initializes the free list and done list queues, creates the semaphores free list has entry and done list has entry, and fills the free_list queue with entries. } CONST initial free count = 10; Declare a maximum of 10 free entries. } VAR entry-ptr Aentry; first entry BOOLEAN; entry=counter : INTEGER; Declare a pointer to an entry. } Declare the first entry flag. } Declare an entry counter. } Example 5-1 Cont'd on next page 5-6 Communication Example 5-1 (Cont.): Using Queues for Process Communication BEGIN WRITELN('Initializing queues ... '); START QUEUE(free list); { Initialize queues. } START-QUEUE(done-list); WRITELN('Creating semaphores ... '); CREATE SEMAPHORE(free list has entry, 0, 1); CREATE-SEMAPHORE (done-list-has-entry, 0, 1); WRITELN('Filling the free list-queue with entries ... '); FOR entry_counter := 1 TO initial_free_count DO BEGIN NEW (entryytr) ; INSERT ENTRY(free list, entrYytrA.links, first entry, QUEUE$TAIL) ; { If this is the first entry, } IF first entry THEN { let the producer process } SIGNAL"(free_list _has_entry) ; } { know that an entry is { available. } END; WRITELN('Initialization done ... '); WRITELN; END; { initialize } PROCESS_BLOCK producer (producer_number : INTEGER); This process block removes entries from the free list queue, fills the entries with data, and inserts them on the done_list queue for the consumer process block. } VAR entryytr : Aentry; first_entry, empty : BOOLEAN; Declare a pointer to an entry. Declare first entry and empty flags. } producer_loop_counter : INTEGER := 0; { Declare a loop counter. } BEGIN empty : = TRUE; REPEAT IF empty THEN WAIT_ANY(free_list_has_entry); { Is the free list queue empty? { If it's empty, wait for an { entry and let the consumer { continue. Example 5-1 Cont'd on next page Communication 5-7 Example 5-1 (Cont.): Using Queues for Process Communication REMOVE ENTRY(free list, entry~tr: :~QUEUE_ENTRY, empty, QUEUE$HEAD) ; GET_TIME(entry-ptr~.buffer); entry-ptrA.ident := producer_number; INSERT ENTRY(done list, entry~tr~.links, first entry, QUEUE$TAIL) ; IF first entry THEN { If this is the first entry, } } { let the consumer process SIGNAL(done_1ist_has_entry); } { know that an entry is } { available. producer loop counter := producer loop counter + 1; UNTIL producer loop counter = producer max; END; {producer-} PROCESS_BLOCK consumer; This process block removes entries from the. done list queue, operates on the data, and inserts the entries on-the free list queue for the producer process block. } VAR entry-ptr : Aentry; first_entry, empty : BOOLEAN; Declare a pointer to an entry. Declare first entry and empty flags. } consumer_loop_counter : INTEGER := 0; {.Dec1are a loop counter. Example 5-1 Co.nt'd on next page 5-8 Communication Example 5-1 (Cont.): Using Queues for Process Communication BEGIN empty := TRUE; REPEAT IF empty THEN WAIT_ANY(done_list_has_entry); { Is the done list queue empty? { If it's empty, wait for an { entry and let the producer { process continue. REMOVE ENTRY (done list, entry-ptr::AQUEUE_ENTRY, empty, QUEUE$HEAD); WRITELN('Data received from Producer' entry-ptrA.ident:1, , --- buffer value = " entry-ptrA.buffer: :INTEGER); INSERT ENTRY(free list, entrY-ptrA.links, first entry, QUEUE$TAIL) ; { If this is the first entry, IF first entry THEN { let the producer process SIGNAL(free_list_has_entry); { know that an entry is { available. consumer loop counter := consumer loop counter + 1; UNTIL consumer loop counter = consumer max; END; {consumer-} - } } } } PROGRAM queue_communication(OUTPUT)i VAR main : PROCESS; producer-process_1, producer-process_2 consumer-process : PROCESS; PROCESS; BEGIN {main} initialize; CREATE_PROCESS (producer-process_1, producer, 1); CREATE_PROCESS (producer-process_2, producer, 2); CREATE_PROCESS (consumer-process, consumer); WAIT_ALL (producer-process_1, producer-process_2, consumer-process); WRITELN (' Finished producing and consuming ... ' ) ; WRITELN('Program exiting ... '); EXIT; END; { main } END; { producer_consumer Communication 5-9 } } } } 5.3 Passing Messages A message is a block of contiguous bytes of memory that is transmitted between processes in the same or different jobs. The kernel maps message data into a job's unique, protected PO virtual address space, making the data available to all processes in that job. Within a single processor, the kernel uses VAX. memory management hardware to distinguish the virtual address space for each job. Within a local area network, the virtual address space for each job resides in the memory of a different target processor. By passing messages, the jobs in a VAXELN system can use the same mechanism to share data efficiently and transparently in both single-processor and network configurations. Processes send messages to and receive messages from systemmaintained queues called ports. The ports in·8, system store messages that are waiting to be sent or received. Calls to the CREATE_PORT procedure create ports dynamically and associate them with unique PORT values that can be used throughout the application: within the creating job, within other jobs on the same node, or within jobs on other network nodes. One of the principal reasons for dividing an application into separate jobs is to distribute an application's jobs across a local area network (LAN). To allow inteIjob communication and to make the distribution of applications across LANs transparent, you can use the CREATE_ NAME procedure to associate port values with port names. When ports are associated with names, a process can call the TRANSLATE_NAME procedure to look up a name in a table and use the returned port value to communicate with other processes and jobs. Port names can be up to 31 characters long and can be either local or universal. Local names are known only to processes and jobs on the node on which they are created. Universal names are known to processes and jobs on all VAXELN nodes in the local area network. VAXELN systems can pass messages by using datagrams or virtual circuits. The datagram method, which uses the DECnet-VAX. datagram, requires no explicit connection sequence and provides fast communication with low overhead. However, this method cannot guarantee message delivery or sequence (although the probability of received messages being correct is extremely high). Using datagrams, a process can obtain the value of any named port in the system, whether the port is on the same node or on a different node on the Ethernet. 5-10 Communication The virtual circuit method, which uses the network services protocol within the VAXELN Network Service, is the preferred method for VAXELN systems to pass messages. Virtual circuits require two ports, usually in different jobs, to be connected as a pair. Despite the overhead of setting up and handling a virtual circuit connection, circui ts offer the following advantages: • • • Guaranteed delivery and sequence Flow control Message size is not limited by the underlying physical media characteristics due to automatic message segmentation and reconstruction When a job sends a message to another job on the same node, the kernel unmaps the message buffer's address from the sending job's virtual address space and maps the address to the receiving job's address space. If the jobs are on different Ethernet nodes, the VAXELN Network Service transports the data across the network and places it in the receiving job's virtual address space. (Network configurations limit message size to the maximum imposed by relevant network devices.) In addition to moving data, applications can use message-passing to synchronize and coordinate multiple processes and jobs. Most of the VAXELN services use message-passing to organize their work. 5.3.1 Messages A message, as recognized by most network devices, is a block of contiguous bytes of memory. Usually, network devices, particularly Ethernet devices, impose a maximum size on a message. A network message also typically requires a number of bytes at the beginning of the message (a protocol header) to identify the rest of the message. The kernel provides a MESSAGE object to describe a block of memory that can be moved from one job's virtual address space to another's. The block of memory is called the message data and is allocated dynamically by the kernel. A MESSAGE object and its data are created by calling the CREATE_MESSAGE procedure. Message data is allocated by the kernel from physically contiguous, page-aligned blocks of memory, which allows the kernel to store the complete description of a message· of reasonable length in a single MESSAGE object. Message data is mapped into a job's PO virtual Communication 5-11 address region, so it is potentially accessible to all the processes in the job. 5.3.2 Message Ports A PORT object represents a system-maintained message queue. A port is unique in that its identifying value is valid within all application jobs, not just within a particular job or jobs on a particular node. In other words, PORT values can be passed as arguments, sent in messages, or obtained from the RECEIVE procedure with certainty that they identify a unique destination for messages, somewhere in the application network. PORT values can be used with WAIT_ANY and WAIT_ALL to synchronize programs with the receipt of messages. A message port can hold a maximum number of messages, specified when the port is created (the default is four). Messages are removed from a port by the RECEIVE procedure in first-inlfirst-out (FIFO) order. If more messages than the maximum are sent, they may be lost. (For exceptions, see Section 5.3.7.) A large message limit requires no more overhead than a small limit. Only the messages themselves determine the amount of memory consumed. PORT values are assigned dynamically by the kernel to identify a particular message port. New values are returned by the CREATE_ PORT procedure and are valid until used with the DELETE procedure to explicitly delete the port. For example, the following Pascal code fragment creates a new message port, limited to 10 messages, and puts the PORT value in the variable newport. The identifier newport is then used in later SEND, RECEIVE, and other message operations that require a PORT value. VAR newport: PORT; BEGIN CREATE_PORT (newport, LIMIT := 10); 5-12 Communication 5.3.3 Named Message Ports To facilitate communication between jobs, the kernel provides a NAME object, a name table entry that associates character string names with message ports. Names are represented as separate objects to allow a port to have multiple names, if desired. A process in the application that expects to communicate with processes outside its job can broadcast the necessary information about one or more of its message ports by creating names for them. If the process needs to communicate with a process on a different network node, it creates a universal name; if all communication occurs within a single node, a local name suffices. A local name is guaranteed to be unique within the local node. Universal names are guaranteed to be unique throughout the local area network. The translation and other maintenance of universal names is a function of the Network Service, as described in Chapter 9. NOTE The processors in a closely coupled symmetric multiprocessing configuration constitute one Ethernet node and share the same local name table. Therefore, the images running on the processors must create unique local names. These names are created with the CREATE_NAME procedure and can be deleted with DELETE. A NAME value specifies a name string of 1 to 31 characters for an associated port. The name string is used to obtain the PORT value of the associated port with the TRANSLATE_NAME procedure. That is, a program can look up a name in the name table and use the resulting PORT value to communicate with other jobs or processes. Applicationwide services, such as disk drivers, commonly use such names. The disk driver makes names available for its message ports (for example, DUAO) so that another job or process can quickly translate the name into a PORT value for use in sending messages. In the case of a disk, program 110 is typically done with language-specific liD procedures, whose runtime software performs the necessary name translation and message transmission for you. When designing a system and writing the programs for it, you decide which processes are the communicators and create names appropriately. You then develop the programs and test the communication to your satisfaction. If you later decide to reconfigure the application - for example, by moving all the programs onto a single network Comm unication 5-13 node or, conversely, distributing programs among several newly added nodes - only the final program development step, system building, must be repeated, to describe the· new hardware/software configuration. No changes to the programs themselves are necessary, because calls to TRANSLATE_NAME in the new application will obtain port information based on the new configuration. Name strings can also be used directly (for example, as a parameter to the CONNECT_CIRCUIT procedure), in which case the translation is done by the procedure. 5.3.4 Message Transmission To send a message, you must declare a pointer to the type of data you want to send, specify the size of the message buffer (C and FORTRAN), supply the pointer to CREATE_MESSAGE, use the pointer to fill in the message data, and supply the MESSAGE value to the SEND procedure. The following Pascal code example sends a message: VAR mtext: AVARYING STRING(80); command: MESSAGE;destination: PORT; BEGIN CREATE MESSAGE(command,mtext); mtext A-:= 'START'; SEND(command,destination); END. An application can send a message as it was created or can send part of a message. To send part of a message, the call to SEND must specify a message size, indicating the length in bytes of the message data to be sent. The SEND procedure removes the message data from your job's address space and places the MESSAGE object in the destination port. The SEND procedure also provides the following information to the receiver: • • The value of the sending process's job port or optionally, a different reply port specified by the sender The value of the destination port 5-14 Communication • The size of the message sent The receiver process waits for a message to arrive on its port and then uses the RECEIVE procedure to obtain it. The RECEIVE procedure automatically maps the message data into the receiver's address space, returns a MESSAGE value for the receiver's use, and optionally returns the identification of the reply port and destination port. To reply to the message's originating job, the receiver uses the value of the reply port from RECEIVE, formulates an answer, and sends a reply to the reply port. (The receiver can use the same message data to form the reply; it need not create a new message.) The receiver process must know beforehand the formats of the messages it can receive. That is, the sender and receiver must have established a message protocol. Defining a protocol is the basic design task in intetjob communication. For example, if the receiver is a server, it must know a set of predefined commands to which it will respond; it can return an error message to the sender (in most cases, an operator's terminal) if it receives a message that does not contain a valid command. 5.3.4.1 Expedited Messages A distinct form of message, called an expedited message, is recognized by the kernel and the Network Service. An expedited message can bypass the normal, sequential flow control provided by the system. For example, a transmitting process may have sent many messages to a receiving process, but before all the messages are received by the receiver, the transmitter may decide that the previous messages should be ignored, if possible. In this case, the transmitter can send an expedited message telling the receiver to halt. Most applications do not need to use expedited data messages, because expedited data messages are restrictive, and there is no guarantee that an expedited message will be received before normal data messages. However, remote expedited data messages provide an interface to the DECnet Network Services Protocol interrupt message service, which is used by established protocols, such as the Data Access Protocol. The following facilities and restrictions apply to expedited data messages: • An expedited data message is sent by specifying a Boolean value to the EXPEDITE parameter of the SEND procedure. Communication 5-15 • • • • 5.3.5 An expedited data message can contain a maximum of 16 bytes of data. Only one unreceived expedited message is allowed in a port. If a second expedited message is sent before the first is received, it has the same effect as a normal data message when the port is at its message limit; that is, either an error status is returned or an exception is raised, or the sending process waits until the first message has been received, depending upon the setting of the FULL_ERROR parameter when the circuit is connected or accepted. An expedited data message is received using the normal RECEIVE procedure but returns the alternate success status value, KER$_ EXPEDITED. Therefore, if a receiver process needs to know if a message is an expedited or a normal message, and the protocol being used does not indicate which it is, the receiving process can compare the status to KER$_EXPEDITED. Expedited data messages queued to a port are received by the RECEIVE procedure before any normal data messages are received. Datagrams and Circuits Ports and messages can be used in two ways to transmit data: • • In the datagram method, one process can obtain the value of a port anywhere in the local area network, and can send the port a message with the SEND procedure. In the circuit method, any two ports can be bound into pairs called circuits. Mter establishing the circuit, the sending process has one port of its own bound to another port, which usually is in a different job or on a different network node. The sender sends the message to its own port, and the message is routed automatically to the other port in the circuit. Processes can both send to and receive from a circuit port. In either method, a process can use the WAIT_ALL or WAIT_ANY procedure to wait for the receipt of a message on a port. The datagram method requires no connection sequence, but correct delivery of datagrams to the destination is not guaranteed. (However, the datagram method guarantees with high probability that received messages are correct.) Also, datagram transmissions cannot be sent 5-16 Communication and received in a guaranteed order; that is, two messages sent to the same destination port can arrive in a different order. Although circuits incur setup and handling costs, they offer the following advantages over the basic datagram method: • • • • Guaranteed delivery and sequence. Messages sent through circuits are guaranteed with high probability to be delivered - if the physical connection is intact - and to be delivered in the same sequence in which they are sent. The circuit method guarantees that the message arrives at the destination port regardless of its location or, if the message fails to arrive, that the sender is notified that the message could not be delivered. Flow control. Options of the procedures ACCEPI'_CIRCUIT and CONNECT_CIRCUIT allow you to control the flow of messages through a circuit. That is, you can prevent a sending process from sending too many messages to a slower receiving process. Segmentation. Messages can have any length, and, if the transmission is across the network, the network services will divide the message into segments, transmit the segments in sequence, and reassemble them at the destination node. A user interface through Pascal I/O routines. The OPEN procedure permits you to open a circuit as if it were a file and to use the I/O routines, such as READ and WRITE, to transmit messages. No performance penalty is incurred with the circuit method for messages transmitted on the same network node and only a small penalty is incurred over the network. For full generality, programs should assume that the sending and receiving jobs may be distributed on different nodes in a network. The circuit method is preferred for sending messages in almost every instance. 5.3.6 Programming with Circuits You establish circuits between two ports by using the CONNECT_ CIRCUIT and ACCEPI'_CIRCUIT procedures. Options let you control the flow of messages through a circuit. For example, you can prevent a sending process from sending too many messages to a slower receiving process. Communication 5-17 A process aimed to establish a circuit calls CONNECT_CIRCUIT and designates a destination port in another process. A connection-request message is sent to the designated port. Consider the following Pascal example: CONNECT_CIRCUIT (myport, DESTINATION_NAME := 'request_server'); The variable myport is an existing port in the calling process that forms its half of the circuit. The string 'requesCserver' specifies the destination name. CONNECT_CIRCUIT translates this name to designate the destination port. The call to CONNECT_CIRCUIT causes a process to wait for the connection request to be accepted. The interval between the time the connection request is initiated for a port and the time the circuit is accepted should be no greater than the interval specified for the Connect time entry on the System Builder's System Characteristics Menu. For example, if the connect time is 45 seconds, the circuit should be accepted no later than 45 seconds after the call to CONNECT_ CIRCUIT initiates the connection request. A longer delay may cause the circuit to go into a bad state. Elsewhere, the accepting process calls the ACCEPT_CIRCUIT procedure to wait for a connection-request message on the designated port. For example: VAR server : NAME; receiver-port PORT; CREATE~ORT(receiver-port, LIMIT := 10); CREATE_NAME (server, 'request_server' ,receiver-port); { { Wait for a connection request. When the wait is satisfied, a { circuit is established between the requestor and receiver-port. {} ACCEPT_CIRCUIT(receiver-port); You can request multiple connections on the same port, but you must distribute connections to other ports as they are received. 5-18 Communication Consider the following Pascal example: VAR. server : NAME; receiver-port, connect-port : PORT; BEGIN CREATE_PORT (receiver-port, LIMIT := 10); CREATE_PORT(connect-port); CREATE_NAME (server, 'request_server', receiver-port); ACCEPT_CIRCUIT (receiver-port, CONNECT := connect-port); { wait for a connection request. When the wait is satisfied, a circuit is established between the requestor and connect-port. At this point, the acceptor can take a variety of actions to communicate with the requestor. For example, the acceptor can create a subprocess to continue the dialog and pass the subprocess the port value (connect_ port) identifying its half of the circuit. The ACCEPT_CIRCUIT procedure can notify you of error conditions, such as an unreceived message in receiver-port or another connection request for which acceptance is pending. When a process issues a call to ACCEPT_CIRCUIT, the kernel issues a call to the WAIT_ANY procedure for that process. When a message arrives at the port, the port is signaled and the kernel issues a call to RECEIVE, assuming that a connection request message is in the port. If the message is not a connection request, the kernel reissues the wait. For this reason, you cannot use the SIGNAL or KER$RAISE_ PROCESS_EXCEPTION procedure to signal a process waiting for a circui t to be accepted; nor can you use the debugger to halt the process. To avoid this behavior, wait on the port and accept the circuit after the wait is satisfied. Circuits are broken when either partner calls the DISCONNECT_ CIRCmT procedure. The SEND and RECEIVE procedures notify their callers if the designated port was disconnected by returning the status value KER$_DISCONNECT. As part of the corrective action for this condition, an application program must call the DISCONNECT_ CIRCmT procedure to disconnect the partner port. If appropriate, the program can then try to reestablish the circuit connection. Consider Example 5-2. Communication 5-19 Example 5-2: Disconnecting the Partner Port After a Disconnect Operation MODULE msg_symbol_ex; INCLUDE $KERNELMSG; PROGRAM use_msg_symbol(INPUT, OUTPUT); VAR one second : LARGE INTEGER; data-port : PORT; dest-port_name : VARYING_STRING(8); msg : MESSAGE; stat : INTEGER; BEGIN CREATE_PORT(data-port); REPEAT WAIT ANY(TIME := one second); CONNECT_CIRCUIT(data~ort, DESTINATION NAME := dest-port_name, STATUS : = stat); UNTIL stat := KER$_SUCCESS; SEND (msg, data-port, STATUS := stat), If the send operation fails because the circuit was disconnected by the partner process, the sender process must clean up by disconnecting the port on its end of the circuit. Once both ports are disconnected, reestablish the circuit connection and try { to send the message again. {} IF stat BEGIN = KER$_DISCONNECT THEN { Disconnect the port before trying to reestablish the { connection. {} DISCONNECT_CIRCUIT(data-port); Example 5-2 Cont'd on next page 5-20 Comm unication Example 5-2 (Cont.): Disconnecting the Partner Port After a Disconnect Operation CONNECT_CIRCUIT (data-port, DESTINATION NAME := dest-port_name, STATOS : = stat); SEND (msg, data-port, STATUS := stat), END; END. END; If the disconnect condition exists, the call to DISCONNECT_CIRCUIT cleans up and prepares data.J)ort for another connection. 5.3.7 Port Limits and Flow Control An advantage of using a circuit for a message exchange is that the kernel and Network Service provide a function called flow control. Under flow control, the flow of messages from a transmitting process to a receiving process is controlled to ensure that unreceived messages do not consume excessive memory in the system. When a process sends a message with· SEND, the message is queued in a specified destination port. If the transmitting process can produce messages faster than the receiving process can consume them and if no limit is placed on the number of messages that can be queued, the messages might use all the available memory. To avoid that situation, ports have a limit on the number of unreceived messages that can be queued at a time; the limit is specified when the port is created. 5.3.7.1 Flow Control with Unconnected Ports If a port that is not connected in a circuit is full and an application sends a message to the port, the call to SEND returns a failure status or exception. If the port is not on the same node, the message can be lost. Communication 5-21 5.3.7.2 Flow Control with Circuits If a circuit-connected port is full, the sender is, by default, put into the waiting state until the port is no longer full. The transmission is then successfully completed. The implicit waiting performed by the SEND procedure evens the flow of messages between the transmitting process and receiving process without having to explicitly program for the condition. Since some applications may not need implicit waiting, an argument to the ACCEPT_CIRCUIT and CONNECT_CIRCUIT procedures allows the calling process to specify that it wants a SEND call to return an error status or exception rather than to wait. 5.3.8 Programming Considerations for Message Communication When programming message communication, consider the following: • • • When programs use circuits to communicate, you must ensure that the programs cooperate. One program is to call the CONNECT_ CIRCUIT procedure, and the other program is to call the ACCEPT_ CIRCUIT procedure. If the programs do not cooperate, various results are possible, including loss of pool blocks used for the connect request, return of the KER$_CONNECT_TIMEOUT status value, unexpected satisfied waits, or the circuit entering a bad state. When a program issues a call to CONNECT_CIRCUIT for a port, an ACCEPT_CIRCUIT for that port must be pending, or the interval between the time the connection request is initiated and the time the circuit is accepted should be no greater than the interval specified for the Connect time entry on the System Builder's System Characteristics Menu. A longer delay may cause the circuit to go into a bad state. A program cannot operate on a port while the port is being used in an ACCEPT_CIRCUIT or CONNECT_CIRCUIT operation. When a program calls the ACCEPl'_CIRCUIT and CONNECT_ CIRCUIT procedures to establish a circuit connection, the kernel and Network Services perform a sequence of operations. This sequence may satisfy a wait request issued by another process in the job unexpectedly. 5-22 Communication • 5.3.9 Once a program establishes a circuit connection, multiple processes can perform simultaneous SEND and WAITIRECEIVE operations. In this situation, the WAIT can be satisfied even if the call to RECEIVE returns the status value KER$_NO_MESSAGE. The combination of the wait being satisfied and the status value being returned results when a program uses multiple receivers or when the SEND procedure resumes after a flow control suspension. In the multiple receiver case, another receiver process may have received the message. In the flow control case, internal flow control mechanisms may have unblocked all processes waiting on the port. If a process receives a KER$_NO_MESSAGE status from a call to RECEIVE after a WAIT is satisfied, it should WAIT on the port again. Kernel Services for Message Transmission The kernel services affecting the state of MESSAGE, PORT, and NAME objects are summarized in Sections 5.3.9.1 to 5.3.9.12. 5.3.9.1 ACCEPT_CIRCUIT Procedure The ACCEPT_CIRCillT procedure causes the invoking process to wait for a circuit connection. On successful completion, the circuit is established between two ports. The invoker's half of the circuit can be the port used to wait for the connection request or, optionally, a different port. This optional parameter allows a program, such as a resource service, to create a name for its connection-request port but to use a different·port for the connection itself; in this way, the server could create a name for the first port to establish simultaneous circuits with several different processes or jobs. The only valid message that can be received at the connection-request port is the kernel's internal connection request; other messages are discarded by the system. By default, when a process sends a message on a circuit with SEND, the operation waits if the partner port is full, a method called flow control. When you accept a circuit connection, you have the option of specifying that you want an error status or the corresponding exception instead of the implicit wait. Communication 5-23 An optional argument supplies a data value that is received by the process requesting the circuit connection in its CONNECT_CIRCUIT call. Another optional argument receives data passed by the requesting process in its CONNECT_CIRCUIT call. These data values are called connect data and accept data, respectively, and are strings of up to 16 bytes. 5.3.9.2 CONNECT_CIRCUIT Procedure The CONNECT_CIRCUIT procedure connects a port to a specified destination port and causes the invoking process to wait for the connection request to be accepted. If a process calls ACCEPT_CIRCUIT with the destination port, the two ports are bound in a circuit. The destination port can be specified by using a name string established by the CREATE_NAME procedure or by using a PORT value giving the destination for the connection request. By default, when a process sends a message on a circuit, the SEND procedure performs an implicit wait if the partner port is full - that is, contains its limit of unreceived messages; this type of flow control is usually used with circuits. With CONNECT_CIRCUIT, you have the option of disabling the implicit wait, causing SEND to receive an error status or raise an exception if the partner port is full. An optional argument supplies data to the process receiving the connection request. Another optional argument receives data supplied by the accepting process in its ACCEPT_CIRCUIT call. NOTE The interval between the time a connection request is initiated for a port and the time the circuit is accepted should be no greater than the interval specified for the Connect time entry on the System Builder's System Characteristics Menu. For example, if the connect time is 45 seconds, the circuit should be accepted no later than 45 seconds after the call to CONNECT_CIRCUIT initiates the connection request. A longer delay may cause the circuit to go into a bad state. >-24 Communication 5.3.9.3 CREATE_MESSAGE Procedure The CREATE_MESSAGE procedure creates a MESSAGE object and allocates and maps its message data into the job's PO address space for use by the SEND and RECEIVE procedures, returning the MESSAGE value that identifies the message and a pointer to the allocated message data. A program can use the pointer to the message data to store data that is to be moved to another job's address space. 5.3.9.4 CREATE_NAME Procedure The CREATE_NAME procedure creates a name string of 1 to 31 characters for a specified port as an entry in a name table and returns the NAME value that identifies that name. An optional argument specifies that the new name is local (known only on its own node), universal (known on any node in the local area network), or both; local is the default. If the Name Service is not present in the system, all names are placed in the local name table, even if you specify universal or both. (For information about the Name Service, see Chapter 9.) Names created by this procedure are guaranteed to be unique within the specified name space: local or universal. If you try to create a name that is not unique, the procedure does not create a NAME object and returns an error status. When you create a universal name in a local area network configuration, the Name Service on each node in the local area network can translate universal names created by other nodes in the local area network. 5.3.9.5 CREATE_PORT Procedure The CREATE_PORT procedure creates a message port, returning the PORT value that identifies the port. An optional integer expression supplies the maximum number of messages that can be queued to the port at one time. If the maximum is exceeded, the sender is notified; the default value is 4. Communication 5-25 5.3.9.6 DELETE Procedure The DELETE procedure removes the MESSAGE, PORT, or NAME object from the system. When a message is deleted, it is unavailable for sending or receiving, and pointers to the message data become invalid. When a port in a circuit is deleted, the connected port is disconnected, messages at the port are deleted, and the wait conditions of any waiting processes are satisfied with the completion status KER$_BAD_VALUE. When a universal name is deleted, the Network Service on each node ensW'es that the deletion is reflected in the list of universal names. The deletion of local names is performed by the kernel on the local node and does not involve the Network Service. 5.3.9. 7 DISCONNECT_CIRCUIT Procedure The DISCONNECT_CIRCUIT procedW'e breaks the circuit connection between two ports. If a process is waiting for either port in the circuit, its wait condition is satisfied. A request for connection can be rejected by first calling ACCEPT_CIRCUIT and then calling DISCONNECT_ CIRCUIT. 5.3.9.8 JOB_PORT Procedure The JOB_PORT procedure returns a PORT object value identifying the caller's job port. A unique job port is created whenever a job is started. 5.3.9.9 RECEIVE Procedure The RECEIVE procedW'e removes a message from a message port. The procedure maps the message data into the receiver job's virtual address space, retW'ns a MESSAGE value identifying the message, and optionally returns PORT values identifying the reply port and destination port. The value is normally the same value supplied by the sender for the receiver's port. An integer argument, optional for Pascal, receives the size in bytes of the message data. 5-26 Communication 5.3.9.10 SEND Procedure The SEND procedure removes a message buffer from the sender's address space and then places the MESSAGE object describing the buffer in the destination message port. If the message is being sent through a circuit, the destination message port you specify is the sender's port, and the message arrives at the receiver's port. By default, when a process sends a message on a circuit, the SEND procedure performs an implicit wait if the partner port is full, a method called flow control. When you accept a circuit connection, you have the option of specifying that you want an error status or the corresponding exception instead of the implicit wait. Other SEND arguments, optional for Pascal, specify the length in bytes of the message data to be sent, specify a reply PORT value, and specify whether to expedite the message. The size of an expedited message must not exceed 16 bytes. 5.3.9.11 TRANSLATE_NAME Procedure The TRANSLATE_NAME procedure returns a value identifying a named port. The specified name string is used to search for a NAME object with a matching string. If the NAME object is found, a value for the named port is returned. You can specify that a name is to be looked up in the local name table, the universal name table, or both; the local name table is searched first if both are specified. The Name Service provides the universal name table. Therefore, to translate universal names, the Name Service must be present in the system. An attempt to translate a universal name without the Name Service present causes the service to try to translate the name using the local name table. For more information about the Name Service, see Chapter 9. 5.3.9.12 WAIT_ANY and WAIT_ALL Procedures A wait for a port, including a port in a circuit, is satisfied when it has a message in it. Waiting for a port causes no modification to the port, and all waiting processes continue if their wait conditions are otherwise satisfied. Both procedures can specify a timeout argument, which defines a time interval or absolute time after which the waiting process proceeds regardless of the states of the objects. Communication 5-27 Normally, a process must call a WAIT procedure, then call RECEIVE. Calling RECEIVE without first calling a WAIT procedure may return a no-message status. If a process needs to accept a circuit connection and wait for one or more other objects at the same time, it can call a WAIT procedure specifying the port and the other objects. When the wait is satisfied because a message is received (the PORT object is returned as the wait result), the process can call ACCEPT_CIRCUIT. 5.4 Sharing Memory Areas Jobs executing on the same node can communicate by sharing an area, a common region of physically contiguous memory. Each job that shares an area must create it. When a job creates an area, the kernel maps the physical memory associated with the area to the job's PO virtual address space. The first time an application creates an area, the kernel also associates the area with an event or semaphore. Jobs can use the event or semaphore to synchronize access to the area. Once an application creates an area, the area remains available until all jobs sharing the area terminate or delete their references to the area. VAXELN applications can use the following procedures to create and use areas: Procedure Description Sets the state of an area's event to EVENT$CLEARED. Creates a new area or maps an existing area of memory into the creating job's PO virtual address space and associates the area with a binary semaphore. Creates a new area or maps an existing area of memory into the creating job's PO virtual address space and associates the area with an event. 5-28 Communication Procedure Description Creates a new area or maps an existing area of memory into the creating job's PO virtual address space and associates the area with a semaphore. DELETE Deletes an area. ELN$INITIALIZE_AREA_LOCK Initializes an area lock variable. ELN$LOCK_AREA Locks an area for exclusive access. SIGNAL Signals an area. If the area is associated with an event, the kernel sets the event to a signaled state. If the area is associated with a semaphore, the kernel increments the semaphore's count. ELN$UNLOCK_AREA Unlocks an area. WAIT_ALL and WAIT..ANY Waits on an area. If the area is associated with an event, the kernel lets the calling job access the area or causes the job to wait, depending on whether the event is signaled or cleared. If the area is associated with a semaphore, the kernel checks the semaphore's count, and based on the count value lets the calling job access the area or causes the job to wait. If the count is greater than zero, the kernel decrements the count and lets the calling job access the area. Otherwise, the job waits. The following sections explain how applications can use these procedures to do the following: • • • • • Create areas, Section 5.4.1 Synchronize access to areas using events, Section 5.4.2 Synchronize access to areas using semaphores, Section 5.4.3 Use area lock variables to optimize waiting and signaling operations, Section 5.4.4 Use areas to synchronize job execution, Section 5.4.5 Communication ~29 • Delete areas, Section 5.4.6 NOTE The systems in a closely coupled symmetric multiprocessing configuration cannot use areas as a means of sharing memory. To share memory, such systems must use the ALLOCATE_MEMORY routine to allocate memory at a physical address on the primary system; which is accessible to all processors. 5.4.1 Creati ng Areas An application can create a new area or map an existing area of memory into a job's PO virtual address space by calling the CREATE_ AREA, CREATE_AREA_EVENT, or CREATE_AREA_SEMAPHORE procedure. A procedure call that creates a new area associates the area with an event or semaphore as follows: Procedure Object Type CREATE_AREA CREATE_AREA_EVENT Binary semaphore Event CREATE_AREA_SE~HORE Binary or counting semaphore The event or semaphore controls access to the area. An application that uses one job to write to an area and lets several jobs read from that area might use an event to control area access. A counting semaphore lets an application specify a maximum number of jobs (maximum count value) that can access an area at a given time. A binary semaphore provides exclusive access to an area. An application uses an area's event or semaphore to control access by changing the event or semaphore's state. The state of an event changes when the application signals or clears an area. The state of a semaphore changes when an application signals or waits on an area. Sections 5.4.2 and 5.4.3 explain how to synchronize area access. Calls to the CREATE_AREA, CREATE_AREA_EVENT, and CREATE_ AREA_SEMAPHORE procedures must specify an area variable, a data pointer, the size of the area (C and FORTRAN), and an area name. The area variable receives a value that identifies the area. You use 5-30 Communication this variable to identify the area in calls to other routines, such as CLEAR_EVENT, SIGNAL, WAIT_ALL, and WAIT_ANY. The data pointer receives the area's base virtual address. A VAXELN Pascal data pointer also implicitly defines the area's size. The data pointer can be of any type except AANYTYPE and the procedure uses the size of that argument's type to determine the area's size. For C and FORTRAN applications, you must specify the area size in bytes. The value you specify is increased to the next multiple of 512. Specify a size of 0 to use an area only as a mechanism for synchronizing job execution (see Section 5.4.5). A string of 1 to 31 characters specifies an area's name. The name must be unique within the application. Calls to the CREATE_AREA_EVENT and CREATE_AREA_ SEMAPHORE procedures also must specify arguments that initialize the event or semaphore that the procedure creates. You can initialize the state of an area's event to EVENT$CLEARED or EVENT$SIGNALED. You must specify initial count and maximum count values for a semaphore that CREATE_AREA_SEMAPHORE creates. (The CREATE_AREA procedure automatically initializes the initial and maximum count values to 1.) Procedure calls that create an existing area only map the area to the calling job's PO virtual address space. The use of a shared area, whether it is associated with an event or semaphore, must remain consistent throughout an application. When you create an area that is associated with an event, subsequent create area procedure calls specifying that area must be CREATE_AREA_EVENT calls and they must specify the same initial event state. Likewise, if you create an area that is associated with a semaphore, subsequent create area procedure calls specifying that area must be CREATE_AREA or CREATE_ AREA_SEMAPHORE calls and they must specify the same initial and maximum count values. For example, if a call to CREATE_AREA_ SEMAPHORE creates a new area named common_area and specifies 0 and 3 as the semaphore's initial and maximum counts, all subsequent calls to CREATE_AREA_SEMAPHORE that specify common_area must also specify 0 and 3 as the semaphore count values. An optional virtual address argument lets you specify the starting job PO virtual address at which the specified area is to be mapped. You can specify this argument in calls to CREATE_AREA, GREATE_AREA_ EVENT, or CREATE_AREA_SEMAPHORE. If you do not specify an address, the kernel allocates a free range of PO virtual addresses. Communication 5-31 The following C example creates a 5000-byte area that has an associated semaphore with an initial value of 1 and a maximum count of 2: #module cr area semaphore #include $;axelnc main () { int completion status, size, init_count, max_count; AREA area1char * area1-ptr static $DESCRIPTOR(name_string1, "AREA_1"); init_count = 1; max count = 2; size = 5000; ker$creat area semaphore(&completion status, &area1,&area1-prt, size, &name string1, init_count, max count, NULL) ; Once you have created an area, subsequent calls to CREATE_AREA, CREATE_AREA_EVENT, or CREATE_AREA_SEMAPHORE that specify the area you created map that area to the PO virtual address space of each calling job. If you specified a virtual address in the procedure call that initially created an area, subsequent calls that specify that area must specify the same virtual address. • • When a shared area is mapped to the same virtual address for each sharing job, the area is position-dependent and pointer values are equivalent in each job's address space. Thus, the sharing jobs can place absolute and relative pointers in the area. When a shared area is mapped to different virtual addresses by different jobs because no virtual address was specified, the area is position-independent and the sharing jobs can place only relative pointers in the area. 5-32 Communication In all cases absolute and relative pointers within an area must point to other addresses within the area if they are to be used by different jobs. Jobs that share an area can map none, some, or all of the area's memory, depending on the area size that you specify. If a job shares part of an area, the shared part begins at the start of the area. 5.4.2 Synchronizing Access to Areas with Events Jobs can synchronize access to a shared area that is associated with an event by waiting on, signaling, and clearing the area. Jobs can access the area so long as the event is in a signaled state. To wait on an area, you must specify its AREA variable in the object value list of a call to the WAIT_ALL or WAIT_ANY procedure. A wait operation for an area that is associated with an event causes the calling job to wait for the area to be signaled. If the area's event is already in the signaled state, jobs calling the WAIT_ALL or WAIT_ANY procedure can access the area immediately. If an area's event is in the cleared state, calling jobs block and wait for another job to signal the area with a call to the SIGNAL procedure. The call to SIGNAL changes the state of the area's event to EVENT$SIGNALED and unblocks all waiting jobs. An area's event remains in the signaled state until a job clears the event with a call to CLEAR_EVENT. The call to CLEAR_EVENT must specify the AREA object with which the event is associated. Example 5-3 shows two modules that use an area associated with an event. The first module, area_writer, contains a job that writes data to the area. The area_writer module also creates two jobs, using the second module, areaJeader. The reader jobs read data from the area, using the area's associated event as a synchronization mechanism. Messages synchronize the writer's ability to gain access to the area. Communication 5-33 Example 5-3: Synchronizing Access to Areas with Events /********************************************************************/ /* Writer Module */ /********************************************************************/ tmodule writer-prog tinclude $vaxelnc tinclude descrip /* * Declare external variables. */ static int main () { /* * Declare master process local variables. */ int char char * AREA static PORT NAME static static static completion_status, area_size, i; *n, a_ch, ch[10]; area-ptr; area with event; $DESCRIPTOR(area name string, "Shared Area ll ); job-port1, job-port2, job-port3, another-port2, another-port3; port name2, port name3; $DESCRIPTOR(port name string2, "Port_FOr_Job2"); $DESCRIPTOR(port-name-string3, "Port For Job3"); $DESCRIPTOR(reader-program_name, "readeryrogll); printf(IIThis is from Job 1."); area size = 50; /* * * Create an area of size 50 bytes and associate that area with a cleared event. */ ker$create_area event (NULL, -&area_with_event, &area-ptr, area size, &area name string, EVENT$CLEARED, NULL) ; /* /* /* /* /* /* Longword containing area ID */ Data pointer */ Area size */ String - name of area */ Initial state - clear */ Virtual address */ printf(II\n Area created of size %d bytes", area_size); Example 5-3 Cont'd on next page 5-34 Communication Example S-3 (Cont.): Synchronizing Access to Areas with Events ker$create-port(NULL, &another-port2, NULL) ; ker$create_name(NULL, &port name2, &port-name string2, &another-port2, NAME$LOCAL) ; ker$create-port(NULL, &another-port3, NULL); ker$create_name(NULL, &port_name3, &port name string3, &another-port 3, NAME$LOCAL) ; printf(II\n\n Now create Job 2. \n\n"); ker$create job (NULL, &job-p ort2 , &reader-program_name, NULL, , 2' ) ; printf(II\n\n Now create Job 3.\n\n"); ker$create job (NULL, &job-p ort3 , &reader-program_name, NULL, , 3' ) ; /* * Initialize the area to all 'A's. */ for (n area-ptr; n < &area-ptr[area_size);) { *n++ '\A' ; /* * Print out the area contents. */ Example S-3 Cont'd on next page Communication 5-35 Example 5-3 (Cont.): Synchronizing Access to Areas with Events area-ptr; n < &area-ptr[area_size1];) for (n { a ch *n++; printf("\n ch /* * * * Signal area with event to let the reader jobs use the data. Once the area is-signaled, all reader jobs can gain access to the area. */ ker$signal(NULL, area_with_event); for (i = 1; i <= 4; i++ ) { /* * Use a mechanism to synchronize the two reader jobs finishing with the area. * * Wait for messages from the two reader jobs. The messages indicate that the reader jobs are finished using the area. * * */ /* * * Lock the area for exclusive access by clearing the area's event. The writer job can then modify the data. */ ker$clear_event(NULL, area with event); /* * * * Send messages to the two reader jobs. The messages indicate that the reader jobs are finished using the area and that the area is locked by this job. */ /* * Modify the area's contents. */ Example 5-3 Cont'd on next page 5-36 Communication Example 5-3 (Cont.): Synchronizing Access to Areas with Events for (n = area-ptr; n < &area-ptrl[area_size1);) { *n++= *n + 1; /* * Print the new contents */ for (n = area-ptr; n < &area-ptr[area_size1);) { a ch = *n++; printf("\n\n ch %c \n\n", a_ch); /* * Signal the area so the reader jobs can read the new data. */ ker$signal (NULL, area "with_event) ; /* * * Mark the area and its associated event for deletion when it is no longer needed. */ ker$delete(NULL,my_areal); /********************************************************************/ /* */ Reader Module /********************************************************************/ tmodule reader-prog tinclude $vaxelnc tinclude descrip main() { int char char completion status, area_size, i; *n, ch(50); * area-ptr; AREA area with event; void subprocess code(); static $DESCRIPTOR(area_name_string, "Sharedyrea"); area size = 50; Example 5-3 Cont'd on next page Communication 5-37 Example 5-3 (Cont.): Synchronizing Access to Areas with Events /* Map area with event to the PO virtual address space for the reader jobs. -The call must specify the same argument data as was specified in the call that initially created the area. * * * */ ker$create_area event (NULL, -&area_with_event, &areaytr, area size, &area name string, EVENT$CLEARED, NULL) ; for (i /*Longword containing area ID */ /* Data pointer */ /* Area size */ /* String - name of area */ /* Initial state - clear */ /* virtual address */ 1; i <= 5 ; i++) { /* * Wait for the writer job to signal the area. */ ker$wait_any(NULL, NULL, NULL, area_with_event); /* * * * * Use the data in the area, send a message to the writer job indicating that we are finished using the area, and wait for a message from the writer job, indicating that all reader jobs are finished. */ /* * * Mark the area and its associated event for deletion when it is no longer needed. */ ker$delete(NULL, area_with_event); 5-38 Communication 5.4.3 Synchronizing Access to Areas with Semaphores Jobs can synchronize access to a shared area that is associated with a semaphore by waiting on and signaling the area. A job gains access to the area by waiting on it. When the job no longer needs access, it should signal the area, allowing other sharing jobs to gain accesS. To wait on an area,·you must specify the area's value in the object value list of a call to the WAIT_ALL or WAIT_ANY procedure. A wait operation for an area that is associated with a binary semaphore gives the calling job exclusive access to the area. If an area is associated with a counting semaphore, the semaphore's maximum count indicates the number of jobs that can wait on, and thus access, an area for read operations simultaneously. For example, if the maximum count value is 3, up to three jobs can access the area simultaneously. The kernel decrements the semaphore's count value by one for each satisfied wait on the area. When the semaphore's count value equals 0, subsequent calls to WAIT_ALL or WAIT_ANY that specify the area cause the calling jobs to block and wait for the area to be signaled. The kernel places the waiting jobs in a queue in the order in which they issued the calls to WAIT_ALL or WAIT_ANY. NOTE If multiple jobs can gain simultaneous access to an area, the application should ensure the integrity of the shared data by allowing the jobs to only read the data. A job that writes to a shared area must have exclusive access. Primarily, areas associated with counting semaphores are for synchronizing access to available units of a shared resource. In such a case, the area has a size of O. For more information about using areas in this way, see Section 5.4.5. When a job no longer needs to access an area that is associated with a semaphore, it can inform the kernel by specifying the area in a call to the SIGNAL procedure. The call to SIGNAL increments the semaphore's count value by one. If one or more jobs are waiting to access the area, the kernel lets the first waiting job in the semaphore's queue access the area and then decrements the semaphore's count by one. The next job in the queue waits for the next signal operation. Communication 5-39 5.4.4 Using Area Lock Variables to Optimize Waiting and Signaling Operations You can improve the performance of area access synchronization by using an area lock variable. An application can use an area lock variable only if the area is created with an associated binary semaphore that is properly initialized. Area lock variables allow you to achieve the same effect as an area with an associated binary semaphore (with initial and maximum counts of 1) without calling a kernel service unless contention exists. Generally, when a process locks an area to gain access to a shared resource, the process does not have to call the WAIT_ALL or WAIT_ANY procedure. The kernel issues a wait only if area is already locked. To use an area lock variable, you must declare a variable of type AREA_LOCK_VARIABLE and place that variable in the data portion of the area. You then initialize the variable using a call to the ELN$INITIALIZE_AREA_LOCK procedure and then synchronize access to the area with calls to ELN$LOCK_AREA (instead of WAIT_ANY or WAIT_ALL) and ELN$VNLOCK_AREA (instead of SIGNAL). To use the area-locking procedures in Pascal applications, you must include the module $MUTEX from the RTLOBJECT library. To use them in C programs, you must include the module $mutex from VAXELNC.TLB. The ELN$INITIALIZE_AREA_LOCK procedure waits on the AREA object. When the wait is satisfied, the kernel places the area's semaphore in a closed state for subsequent lock and unlock operations, and then the procedure sets the area lock variable's initial state to unlocked. (The area semaphore's state changes only when lock contention exists.) An area lock variable should be initialized only once by one process; no error status is returned if the variable is initialized more than once. A job locks an area for exclusive access by calling the ELN$LOCK_ AREA procedure. A call to this procedure must specify the area to be locked and the lock variable that con troIs access to the area. If the area is already locked, the calling job waits on the area. Generally, when a job locks an area, the job does not need to issue a wait before accessing the area. The kernel issues a wait only if the area is already locked. A job can unlock an area by calling the ELN$VNLOCK_AREA procedure. This procedure releases an area and signals processes that are waiting to access it. A call to this procedure must specify the area to be unlocked and the lock variable that controls access to the area. 5-40 Communication If a binary semaphore is open (count = 1) and the semaphore is signaled, a count overflow error occurs. In contrast, the locking and unlocking of areas is not protected by this exception-raising mechanism. Under certain circumstances (in which two or more jobs contend for an area) unlocking an already unlocked area can cause the calling job to block indefinitely. Therefore, when using area lock variables, you should adhere to the following guidelines: • • 5.4.5 The first operation on an initialized area lock variable must be a lock operation. You must pair lock and unlock operations within the code of the jobs using the area. Using Areas to Synchronize Job Execution You can use an area of size 0 to synchronize job execution. In such cases, the AREA object represents an inteIjob event or semaphore or a user-defined resource. As an inteIjob synchronizing mechanism, an area functions the same as events and semaphores used to synchronize processes in the same job. Instead of synchronizing processes that execute as parts of the same job, you synchronize processes that execute as parts of different jobs. For more information about using semaphores and events to synchronize processes, see Sections 4.4 and 4.5. An area can also represent the available units of a shared user-defined resource that is application-specific. The printers available on a system are an example of such a resource. The event or semaphore associated with the area serves as a resource access control mechanism. Example 5-4 shows two modules that use an area associated with a counting semaphore to control the ability of three jobs to gain access to two shared resources. The first module does the following: • • • • • Creates the area with an initial count of 1 and a maximum count of 2 Waits on the area to gain access to a resource lni tializes the two resources Signals the area twice to let two jobs gain access to the resource Creates two other jobs Communication 5-41 • Allows the three jobs to use the two resources five times each, with only two of the jobs using the resources at a time. The second module, which is executed by the two created jobs, maps the area to its PO space, waits until the resource is available, uses the resource, and signals the area when the resource is no longer needed. All three jobs use the area's semaphore to synchronize access to the shared resources. Example 5-4: Synchronizing Job Execution with Semaphores {*********************************************************************} Module 1 {* *} {*********************************************************************} MODULE cr_area_sema_l; PROGRAM cr_area_sema-progl(INPUT,OUTPUT); CONST area size 0; TYPE area_type = string(area_size); VAR i : INTEGER; completion_status : INTEGER; resource : AREA; resource-ptr : Aarea_type; job2-port, job3-port : PORT; BEGIN writeln(fCreate resource area .. . f); { { { { { Create an area of size 0 and associate that area with a counting semaphore that has initial and maximum count values of 1 and 2. As many as two jobs can gain access to the resource without waiting. {} Example 5-4 Cont'd on next page 5-42 Communication Example 5-4 (Cont.): Synchronizing Job Execution with Semaphores CREATE_AREA_SEMAPHORE( resource, resource-.ptr, , Shared_Area' , 1, 2, completion_status); Longword containing area ID } Data pointer } String - name of area } Initial count } Maximum count } } Status { { { Wait on the area. Since the initial count was 1, this job gains access immediately. {} WAIT_ANY(resource); Set up the shared resource. } { { { { { Signal the area's semaphore. When the area is signaled, the kernel increments the semaphore count so that another job can use the area. We signal the area twice to make the resource available to two jobs. {} SIGNAL(resource); SIGNAL(resource); { Create the other two jobs. } { Create the second job and pass it the program argument '2'. } CREATE_JOB (job2-'port, 'cr_area_sema-'prog2', " , " , '2'); { Create the third job and pass it the program argument '3'. } create_job (job3-'port, 'cr_area_sema-'prog2', " , " , '3'); FOR i := 1 TO 5 DO BEGIN { { { { Wait on the area until the resource is available. If the semaphore count is greater than 0, the job gains access to the area. If the count is 0, the job waits. {} Example 5-4 Cont'd on next page Communication 5-43 Example 5-4 (Cont.): Synchronizing Job Execution with Semaphores WAIT_ANY(resource); Determine which resource is available and use it. } { { { { { Signal the area's semaphore to indicate that the resource is no longer in use. When the area is signaled, the kernel increments the semaphore count so that another job can use the area. {} SIGNAL(resource); END; WRITELN('Job 1 has used a resource 5 times.'); { { { Mark the area and its associated semaphore for deletion when they are no longer needed. {} DELETE(resource); END. END; {*********************************************************************} Module 2 {* *} {*********************************************************************} MODULE cr_area_sema_2; PROGRAM cr_area_sema-prog2(INPUT,OUTPUT); CONST area size TYPE area_type 0; = STRING(area_size)i VAR i, j : INTEGER; completion status : INTEGER; job_number-: STRING(l); resource : AREA; resource-ptr : Aarea_type; Example 5-4 Cont'd on next page 5-44 Communication Example 5-4 (Cont.): Synchronizing Job Execution with Semaphores BEGIN job_number := PROGRAM_ARGUMENT(3); { { Map the area of size n ° for {Get the job number. the cr_area_sema-prog2 job. CREATE_AREA_SEMAPHORE( resource, resourceytr, 'Shared_Resource' , 1, 2, completion_status); Longword containing area ID } Data pointer } String - name of area } Initial count } } Maximum count } Status FOR j := 1 TO 5 DO BEGIN { { { { Wait on the area until the area is signaled. If the semaphore count is greater than 0, the job gains access to the resource. If the count is 0, the job waits. {} WAIT_ANY(resource); Determine which resource is available and use it. } { { { { { Signal the area's semaphore to indicate that the resource is no longer in use. When the area is signaled, the kernel increments the semaphore count so that another job can use the area. {} SIGNAL(resource); END; WRITELN('Job " job_number, ' has used a resource 5 times'); { { { Mark the area and its associated semaphore for deletion when it is no longer needed. {} Example 5-4 Cont'd on next page Communication 5-45 Example!>-4 (Cont.): Synchronizing Job Execution with Semaphores DELETE(resource); END. END; 5.4.6 Deleting Areas You can delete an area by specifying the area's identifier in a call to the DELETE procedure. When you specify an area identifier with this procedure, it removes the calling job's reference to the area and unmaps the data from its PO virtual address space. Any process in the job that created or mapped the area can delete it. The AREA object is not actually deleted until the last job that uses the area deletes its reference to the area. 5-46 Communication Chapter 6 Device Handling Device drivers are programs that control communication between application programs and external devices. In the case of realtime applications, most external devices are interrupt-driven - they communicate with the application only when they need service. A device requests service by sending an interrupt signal to the processor. The processor recognizes the signal, stops what it is doing, and services the request by executing a block of driver code called an interrupt service routine (ISR). Once you decide on your application's device requirements, you build the relevant devices and drivers into your VAXELN system by specifying device characteristics on the System Builder's Device Description Menu (see the VAXELN Development Utilities Guide). The VAXELN Toolkit provides a highly productive environment for developing application-specific device drivers. Using high-level languages, you can implement drivers for devices that have one or more units per controller. In addition, the toolkit supplies prototype driver code that you can study, and perhaps use, while programming device drivers. You can design a device driver so that it executes as a job or as a callable routine. As a job, a device driver is a shareable resource available to all program images in a system. If a driver does not need to be shareable, you can code it as a callable routine. As a routine, a driver reduces overhead by eliminating job context switching. Typically, a device driver job executes in kernel mode at a higher priority than jobs running other application programs and executes concurrently with the other jobs that use the related device. Device Handling 6-1 A driver's activity depends on the characteristics and actions of the device it controls. However, you program a driver's general interface by declaring a variable of type DEVICE (which represents the hardware device) and an ISR. You then call VAXELN procedures that perform the following types of operations: • • • • • Set up communication for 1/0 requests Associate a device with an ISR and a driver program Handle device interrupts Synchronize access to a device communication region Read data from and write data to a device's control status register (CSR) or data buffer A driver's ISR provides an interface for handling device interrupts and power-failure recovery. When an interrupt occurs, the kernel executes the necessary machine instructions, and then calls the ISR to service the device. While servicing the device, the ISR communicates with the driver code by sharing an area of memory called the communication region. For example, an ISR might use this region to return device register data to the driver program. A driver establishes a communication region when it creates a DEVICE object with a call to CREATE_DEVICE. All communication regions are potentially accessible to all ISRs. For example, for handling multivector devices, you can create two communication regions (with two CREATE_DEVICE calls) and then store a pointer to one region in the other's region. (For an example, see the VAXELN source module YCDRlVER.PAS.) You synchronize a driver job's processes with an ISR by identifying a DEVICE object in calls to the WAIT and SIGNAL_DEVICE procedures. Driver processes wait on the DEVICE object while the ISR services a device interrupt. If multiple processes wait on the same object, the kernel queues them in the order in which the WAIT_ALL or WAIT_ ANY procedure calls executed. Once the interrupt is serviced, the ISR satisfies the wait of the first process in the queue by signaling the DEVICE object with SIGNAL_DEVICE. This priority-based process scheduling eliminates the need for fork processing. This chapter provides information about writing 110 device driver programs for handling device interrupts and power recovery. Specifically, the chapter explains how to do the following: • • Create and delete DEVICE objects, Section 6.1 Handle device interrupts, Section 6.2 6-2 Device Handling • • • • • • • 6.1 Synchronize access to the device communication region, Section 6.3 Set a driver job's processor eligibility, Section 6.4 Read and write register data, Section 6.5 Control DMA devices, Section 6.6 Code VAXBI bus device drivers, Section 6.7 Execute routines in kernel mode, Section 6.8 Handle power-failure recovery, Section 6.9 Creating and Deleting DEVICE Objects A device driver program, running in kernel mode, can create DEVICE objects by calling the CREATE_DEVICE procedure. The procedure associates a physical device with a driver program and an ISR. Once you create a DEVICE object, you can use its value as a binary semaphore to synchronize execution of the driver's ISR with the execution of other driver processes. A call to CREATE_DEVICE must specify the device's name and a variable of type DEVICE that is to receive the DEVICE object's identifier. The device name must be one of the 1- to· 30-character names established with the System Builder. The procedure uses the name to retrieve the device's characteristics. The DEVICE variable can be a single variable or an array of 1 to 64 DEVICE elements. If you specify an array, the procedure creates an array of DEVICE objects and places the corresponding identifiers in the appropriate array elements. Use an array if an ISR needs to communicate with multiple-unit devices, such as a 32-bit parallel port or dual-drive disk controller. In the case of a 32-bit parallel port, an ISR might use an array of 32 DEVICE elements to process the data that it receives on each port. Based on condition or bit information that the ISR receives, it can signal appropriate objects and make the associated driver processes eligible for execution. A call to CREATE_DEVICE also can specify the name of the ISR that is to be associated with the DEVICE object or array of DEVICE objects. If you omit the argument, you drive the device by polling rather than with interrupts. Device Handling 6-3 An optional relative vector argument specifies which vector of a multiple-interrupt-vector device should be connected to the ISR. (The base vector address appears on the System Builder's Device Characteristics Menu.) If you omit this argument, it defaults to 1 (the first vector). If you specify this argument in multiple calls to CREATE_ DEVICE within a program, the vector value for each call must be unique; specifying the same value a second time causes the subsequent call to CREATE_DEVICE to return the status value KER$_DEVICE_ CONNECTED. For example: CREATE_DEVICE ('DUAO' , first_device, VECTOR NUMBER := 1); CREATE_DEVICE ('DUAl' , second_device, VECTOR NUMBER := 2); CREATE_DEVICE ('DUA2' , third_device, VECTOR NUMBER := 3); Other arguments that you can specify receive pointers to the device communication region, the first device control status register (CSR), the first adapter control register, and the interrupt vector in the system control block. In C and FORTRAN, you can also specify the size of the communication region. You can also specify arguments that receive the device's interrupt priority level (IPL) and the name of a power-failure recovery routine. The recovery routine is called before any process or ISR is restarted if the processor enters a power-fail recovery sequence. If your target configuration includes a VAX 8800 multiprocessor, a call to CREATE_DEVICE forces a driver job to run on the processor that handles the device's interrupts. It forces driver jobs for devices on VAXBI buses 2 and 3 to run on the primary processor and forces driver jobs for devices on VAXBI buses 0 and 1 to run on the secondary processor. If necessary, you can declare the job eligible to run on either processor with a call to KER$SET_JOB_ELIGIBILITY (see Section 6.4). 6-4 Device Handling When a program is finished using a DEVICE object, it can delete the object with a call to the DELETE procedure. The kernel frees the memory used for the DEVICE object's communication region (invalidates pointers to that memory) and disconnects the ISR from the interrupt vector. Waiting processes are removed from their wait states immediately and receive the status value KER$_BAD_VALUE. 6.2 Handling Device Interrupts Mter the CREATE_DEVICE procedure associates a device with an ISR, the kernel calls the ISR each time the device interrupts the processor. The ISR services the interrupt, using the device register pointer to gain access to the device registers. Typically, with devices that interrupt for several reasons, the ISR can examine the device's CSR to determine the reason for the interrupt. An ISR uses the device communication region to supply a program with values that it receives from device registers. Only the data placed in the communication region is available to an ISR. An ISR and the driver program synchronize their execution by waiting on and signaling a DEVICE object. 6.2.1 Waiting for an ISR to Service a Device Interrupt Driver processes wait to be signaled while an ISR services a device interrupt. To initiate the wait, a process specifies the appropriate DEVICE identifier in a call to WAIT_ALL or WAIT_ANY. The ISR satisifies the wait when it finishes servicing the interrupt. If multiple processes are waiting on the same DEVICE object, the kernel queues them in the order in which the WAIT procedure calls execute. Once the interrupt is serviced, the ISR satisfies the wait of the first process in the queue. 6.2.2 Signaling the DEVICE Object After Service Completion When an ISR finishes servicing a device interrupt, it signals the appropriate driver processes by specifying the appropriate DEVICE identifier in calls to SIGNAL_DEVICE. These calls unblock the processes that are waiting on the specified DEVICE object. An optional argument lets you identify an element in a DEVICE array. Device Handling 6-5 6.3 Synchronizing Access to the Device Communication Region While servicing a device, a driver program and an ISR communicate by sharing the device communication region. Since the communication region is a shared resource, access to the region must be synchronized. The driver program can synchronize access to the region by setting the processor's interrupt priority level (IPL). VAX processors define 32 IPLs. IPL 0 is the lowest priority; IPL 31 is the highest. Table 6-1 lists the IPLs at which various system events occur. Table 6-1 : Interrupt Priority Levels Events IPL (decimal) Hardware: 31 Machine check; kernel stack not valid 30 Power failure 25-29 Processor, memory, or bus error 24 Clock (except MicroVAX, which is IPL 22) 16-23 Device IPLs, with 20-23 corresponding to UNIBUS or Q22-bus request levels 4-7, respectively Software: 9-15 6-6 Unused 8 DEVICE signal 7 Timer process 6 Closely coupled symmetric multiprocessing interrupt 5 Kernel debugger 4 Job scheduler 3 Process scheduler 2 Deliver asynchronous exception 1 Unused o User process level Device Handling You should consider a device's interrupt priority and job priority when synchronizing device driver programs. The default interrupt priority for the supplied device drivers is 5. You can change the interrupt priority for the supplied drivers and set the priority for user-written drivers by editing the value for the Interrupt priority entry on the System Builder's Device Description Menu. The priority values range from 4 to 7, with 4 being the highest priority. These values correspond to the VAX interrupt priority levels 14 (hexadecimal) to 17 (hexadecimal). You can get the resulting interrupt priority by specifying a priority argument in the call to CREATE_DEVICE. When synchronizing a device driver program, you should also consider the program's job priority. The default job priority for most supplied device drivers is 4. The default for supplied terminal drivers is 2. You can adjust the job priority for supplied drivers and set the priority for user-written drivers by calling the SET_JOB_PRIORITY procedure. However, you can use this mechanism only if you select No for the Autoload driver entry when you edit the System Builder's Device Description Menu. For more information about setting job priorities, see Section 3.3.2. Setting the processor IPL provides synchronization because when the processor IPL is set to a certain level, interrupts assigned to that level and below (and their corresponding service routines) are disabled. This form of synchronization, though somewhat difficult to use, is efficient. Depending on your target configuration, a driver program can use either the DISABLE_INTERRUPr and ENABLE_INTERRUPT procedures or the KER$LOCK_DEVICE and KER$UNLOCK_DEVICE procedures to raise and lower the processor's IPL. To use these procedures, the program must be running in kernel mode. Use DISABLE_INTERRUPT and ENABLE_INTERRUPT if your target is a single processor or a VAX 8800 multiprocessor. DISABLE_ INTERRUPT prevents entry to an ISR when a device interrupt occurs by raising the processor's IPL to the IPL of the device. While interrupts are disabled, no kernel procedures can be called; doing so causes unpredictable results. For a driver job to use DISABLE_INTERRUPT on a VAX 8800 multiprocessor, the job must be running on the processor that handles the device's interrupts. If necessary, you can request specific processor eligibility while the driver job is executing by issuing a call to the KER$SET_JOB_ELIGIBILITY procedure (see Section 6.4). Device Handling 6-7 To reenable device interrupts, lower the processor's IPL by calling ENABLE_INTERRUPT. Use KER$LOCK_DEVICE and KER$UNLOCK_DEVICE if your target configuration includes a multiprocessor that lets devices interrupt any processor (such as a VAX 6000-3nn multiprocessor). KER$LOCK_ DEVICE prevents entry to an ISR when a device interrupt occurs by raising the processor's IPL to the IPL of the device and setting a spin lock. The procedure locks out the ISR. If an interrupt for the device comes in on another processor while the spin lock is set, that processor spins on the lock until the driver clears it with a call to KER$UNLOCK_DEVICE. NOTE If your target configuration may include a VAX multiprocessor that lets devices interrupt any processor, you should use the KER$LOCK_DEVICE and KER$UNLOCK_DEVICE procedures instead of DISABLE_INTERRUPT and ENABLE_ INTERRUPT to synchronize the device communication region. A VAX processor's current IPL is part of its processorwide state. Disabling interrupts of a certain priority also disables other system activities that occur at or below that priority level. If a process raises the processor's IPL to block device interrupts, that process is the only activity (other than ISRs) that can execute on that processor until the process lowers the priority by calling ENABLE_INTERRUPT or KER$UNLOCK_DEVICE. If the power fails while interrupts are disabled, the kernel sets the IPL to 0 before it raises the exception KER$_POWER_SIGNAL. This exception is handled like other asynchronous exceptions; however, continuing from the exception with interrupts enabled may produce unpredictable results. 6.4 Setting a Driver Job's Processor Eligibility When a device driver job executes on a VAX 8800 tightly coupled multiprocessing system, calls to the CREATE_DEVICE procedure force the driver job to run on the processor that handles the device's interrupts. This binding lets the driver job raise the processor's IPL with a call to DISABLE_INTERRUPr to synchronize access to the device communication region. If necessary, the driver job can undo this binding by calling the KER$SET_JOB_ELIGIBILITY procedure. Using a call 6-8 Device Handling to this procedure, a driver job can dynamically change its processor eligibility and make itself eligible to run on either processor. However, keep in mind that you cannot use an elevated IPL to synchronize access to the device communication region if the driver job is not executing on the processor that handles the device's interrupts. When calling the KER$SET_JOB_ELIGIBILITY procedure, specify the job's new eligibility mask. The procedure replaces the eligibility mask in the job's job control block (JCB) with the mask you specify. The mask supplies Boolean values that indicate job eligibility for each processor in your target configuration. TRUE means the job is eligible to run on a processor, and FALSE means the job is not eligible to run on a processor. Whether the master process or a subprocess calls the procedure, the call changes the processor eligibility for the entire job. At least one available processor must be eligible to run the driver job. If the job cannot run on any available processor, the kernel returns the status value KER$BAD_VALUE. For information about synchronizing access to the device communication region, see Section 6.3. 6.5 Reading and Writing Register Data Driver programs and ISRs can read data from and write data to device and processor registers by calling the READ_REGISTER, WRITE_ REGISTER, MFPR, and MTPR routines. The READ_REGISTER and WRITE_REGISTER routines operate on device registers. The READ_REGISTER function returns the value of a variable reference, and the WRITE_REGISTER procedure loads a value or group of values into a specified target variable reference. These read and write operations are performed by single machine instructions and are not affected by compiler optimizations. The READ_REGISTER and WRITE_REGISTER routines are the only safe methods for reading data from and writing data to a device register. These routines also can be used safely to read and write a shared variable. READ_REGISTER and WRITE_REGISTER should always be used, instead of direct assignments, to read and write the fields in a device register. This is required because the VAX architecture does not allow the use of variable-length bit-field instructions to read or write device registers. Using READ_REGISTER and WRITE_REGISTER ensures that the compiler generates only valid instructions. Device Handling 6-9 The MFPR and MTPR routines operate on processor registers. The MFPR function returns the contents of a VAX processor register. The MTPR procedure moves a specified value into a specified VAX internal processor register. To call these routines, a program must be running in kernel mode. NOTE Processor registers are a privileged system resource. Changing the contents of processor registers while a system is running may cause an unhandled exception. 6.6 Controlling DMA Devices The VAXELN Toolkit provides utility procedures that device ·driver programs can use to perform the following direct memory access (DMA) device operations: • • • • 6.6.1 Allocate, load, and free map registers, Section 6.6.1 Allocate and free UNIBUS buffered data paths, Section 6.6.2 Map and unmap memory buffers, Section 6.6.3 Return a variable's physical address, Section 6.6.4 Allocating, Loading, and Freeing Map Registers Device driver programs can allocate, load, and free UNIBUS or Q22bus map registers. The KER$ALLOCATE_MAP procedure allocates a contiguous block of UNIBUS or Q22-bus map registers for use by a program to map VAX memory to UNIBUS or Q22-bus memory addresses, respectively. The procedure returns a pointer to the first register allocated and returns the starting map register number (0 to 495 for a UNIBUS, 0 to 8175 for a Q22-bus). Optionally, the procedure returns a pointer to the base address of the system page table (SPT). Arguments supply the number of registers to allocate and the DEVICE value that identifies the device for which the registers are to be used. . Once a driver has allocated the appropriate map registers, it can call the ELN$LOAD_UNIBUS_MAP procedure to load the registers for use by a DMA UNIBUS or Q22-bus device. 6-10 Device Handling The ELN$LOAD_VNIBUS_MAP procedure is an alternative to the more commonly used ELN$UNIBUS_MAP procedure. The procedure assumes that the calling program has called the KER$ALLOCATE_MAP procedure to allocate sufficient map registers. ELN$UNIBUS_MAP allocates them for the caller. ELN$LOAD_ UNIBUS_MAP also assumes that an additional map register, beyond the number actually necessary to map the buffer, has been allocated for use as an invalid wild-transfer-stopper. Arguments supply a pointer to the first UNIBUS or Q22-bus map register allocated by KER$ALLOCATE_MAP, the I/O buffer, and the buffer size. An optional argument is a pointer to the SPT; if this argument is not specified, a device communication region (or any system space buffer) cannot be mapped. Another optional argument supplies a UNIBUS data path for the transfer. If that argument is not supplied, data path 0, the direct data path, is used. When the map registers are no longer needed, the driver program can free them by calling the ELN$FREE_MAP procedure. Pointers to the freed registers become invalid. Arguments supply the number of contiguous .map registers to be freed, the number of the first register, such as the one returned by KER$ALLOCATE_MAP, and the DEVICE value that identifies the device for which the registers are freed. The KER$ALLOCATE_MAP and KER$FREE_MAP procedures can be called only from programs running in kernel mode. 6.6.2 Allocating and Freeing Buffered Data Paths A driver program can allocate and free UNIBUS adapter buffered data paths by calling the KER$ALLOCATE_PATH and KER$FREE_ PATH procedures. The KER$ALLOCATE_PATH procedure allocates a UNIBUS adapter buffered data path for use by a DMA UNIBUS device. The procedure returns a pointer to the allocated data path register and the allocated data path register number. An argument supplies the DEVICE value that identifies the device for which the data path is allocated. Device Handling 6-11 A buffered data path can optimize the use of memory by a DMA device that performs strictly sequential address transfers. (For additional information on buffered data paths, see the VAX Hardware Handbook.) The VAX-II/750, and VAX 8800, 8700, 8550, 8530, and 8500 processors that are configured with UNIBUS adapters, support UNIBUS buffered data paths. For the VAX-II/750, each UNIBUS adapter has three buffered data paths. For the VAX 8nnn processors, each UNIBUS adapter has five buffered data paths. To use a buffered data path for a DMA transfer, the allocated data path number must be loaded into the UNIBUS map registers being used for the transfer. The ELN$UNIBUS_MAP and ELN$LOAD_UNIBUS_ MAP procedures accept an optional data path number for loading into the UNIBUS map registers. When a UNIBUS buffered data path is used for a DMA transfer, the data path must be purged when the transfer has completed. You purge by writing a value of I to the data path register, identified by the returned register pointer. The driver program can free allocated data paths by calling the KER$FREE_PATH procedure. Arguments supply the data path register number, such as the one returned by KER$ALLOCATE_PATH, and the DEVICE value that identifies the device for which the data path is freed. The KER$ALLOCATE_PATH and KER$FREE_PATH procedures can be called only from programs running in kernel mode. 6.6.3 Mapping and Unmapping Memory Buffers Device driver programs can map and free memory buffers for DMA operations on UNIBUS and Q22-bus devices by calling the ELN$UNIBUS_MAP and ELN$UNIBUS_VNMAP procedures, respectively. The ELN$UNIBUS_MAP procedure maps a specified buffer into UNIBUS or Q22-bus address space and returns the 18-bit UNIBUS address or the 22-bit Q22-bus address of the mapped buffer. Arguments supply the DEVICE value identifying the device that will use the mapped memory, the I/O buffer, and the buffer size. An optional argument specifies the UNIBUS data path to use; the default is 0, specifying the direct data path. ~ 12 Device Handling NOTE The procedure allocates the correct number of map registers by calling KER$ALLOCATE_MAP. The procedure then converts the virtual address of each page of the buffer to a physical address and stores and validates the physical page numbers in the allocated map registers. If a data path other than 0 is specified, it is stored in the map registers as well. Although the map registers are allocated by ELN$UNIBUS_ MAP before use, a nonzero data path number is assumed not to be in use by any other device. When the driver program no longer needs the memory buffers, it can free them by calling ELN$UNIBUS_UNMAP. This procedure unmaps previously mapped memory buffers. The procedure deallocates the correct number of map registers by calling KER$FREE_MAP. Arguments supply the DEVICE value identifying the device that was using the mapped memory, the I/O buffer and the buffer size, and the l8-bit UNIBUS address or the 22-bit Q22-bus address of the mapped buffer. 6.6.4 Returning a Variable's Physical Address A device driver program can use the ELN$PHYSICAL_ADDRESS function for DMA devices on MicroVAX processors to return the physical address of an identified variable. Programs using this function must include the module $PHYSICAL_ADDRESS. 6.7 Coding VAXBI Bus Device Drivers The VAXELN Toolkit provides the utility procedures ELN$BI_NODE_ MASK and ELN$BI_STOP for coding device drivers that interface with a VAXBI bus. A VAXBI device driver must call the ELN$BI_NODE_ MASK procedure to get the mask identifying the VAXBI node number to which the device should direct its inputs. The driver must load the returned identification into the device's INTR Destination Register. (The alternative, hard-coding the mask, limits the driver's portability.) For example, in a VAX 8800 or VAX 6000-2nn system, the returned mask has a bit set for the VAXBI node number of the NBIBIXBIB bus adapter. In a KA800 system, the mask has a bit set for the processor's VAXBI node number. Device Handling 6-13 The ELN$BI_STOP procedure issues a VAXBI STOP bus transaction to place a device in a stopped node state. The procedure's meaning and usefulness for a device depends on the device. Pascal and C programs that use these procedures must include the modules $VAXBI and $vaxelnc, respectively. 6.8 Executing Routines in Kernel Mode A number of VAXELN routines must execute in kernel mode. If a program includes a call to one of these routines or a user-declared routine that requires kernel mode, you have two options. You can execute the entire program in kernel mode, or you can use the KER$ENTER_ KERNEL_CONTEXT procedure to execute only that routine in kernel mode. To execute an entire program in kernel mode, select kernel mode when you build the program into your VAXELN system or when you load the program image. Device driver programs are typical examples of entire programs that run in kernel mode. If it is not desirable to execute an entire program in kernel mode, use calls to KER$ENTER_KERNEL_ CONTEXT to execute specific routines in kernel mode; the rest of the program runs in user mode. You specify the KER$ENTER_KERNEL_CONTEXT procedure with the address of the routine that is to be called in kernel mode. You can also specify a status argument and the address of a VAX argument list to be passed to the called routine. The argument list is a block of longwords in standard VAX format: the first byte of the first longword supplies the argument count, and the block contains an additionallongword for each of the arguments. VAXELN routines that require kernel mode include most of the VAXELN driver utility procedures and the following: ALLOCATE_MEMORY (with the physical_address argument) CREATE_DEVICE DISABLE INTERRUPT ELN$LOAn_UNIBUS_MAP ENABLE_INTERRUPl' KER$ALLOCATE_MAP KER$ALLOCATE_SYSTEM_REGION KER$FREE_MAP KER$FREE_SYSTEM_REGION KER$LOCK_DEVICE 6-14 Device Handling KER$UNLOCK_DEVICE MFPR MTPR Example 6-1 uses KER$ENTER_KERNEL_CONTEXT to execute a fWlCtion that calls DISABLE_INTERRUPT and ENABLE_ INTERRUPT. The call to KER$ENTER_KERNEL_CONTEXT in Example 6-1 establishes the kernel context needed to execute calls to DISABLE_ INTERRUPT and ENABLE_INTERRUPT. It replaces a function call that might otherwise appear as follows: return_status := raise_ipl(4); Each argument in the call to KER$ENTER_KERNEL_CONTEXT corresponds to the components of the preceding function call. The first argument in the call to KER$ENTER_KERNEL_CONTEXT, return_ status, receives the function's completion status, assuming the function is returning an integer status value. (If the KER$ENTER_KERNEL_ CONTEXT procedure cannot access a specified argument, the procedure returns the status KER$_NO_ACCESS to return_status.) The second and third arguments identify the function and its arguments, respectively. NOTE When you call KER$ENTER_KERNEL_CONTEXT, the kernel checks for a completion status. Therefore, you must specify the KER$ENTER_KERNEL_CONTEXT procedure's status argument. If the specified routine is a function, alternatively, that function can explicitly return a status value. If you do not specify the status argument in the call to KER$ENTER_KERNEL_CONTEXT or a function that returns a status value, the call to KER$ENTER_KERNEL_ CONTEXT may produce unpredictable results. Device Handling 6-15 Example 6-1: Using the KER$ENTER_KERNEL_CONTEXT Procedure MODULEkernel_context_example; INCLUDE $KERNEL; TYPE argument_block_type = RECORD argument_count : INTEGER; priority : INTEGER; END; VAR argument block : argument_block_type; return status INTEGER; PROGRAM change_context (INPUT, OUTPUT); BEGIN argument_block. argument_count := 1; priority } argument block.priority := 4; WRITELN('Entering kernel context ... '); KER$ENTER KERNEL CONTEXT (return status, Routine return status ADDRESS(raise ipl), {Routine to execute} ADDRESS(argument block»; {Routine args } WRITELN('Exiting kernel context ... '); - END. FUNCTION raise_ipl(priority : INTEGER) : INTEGER; { While in kernel mode, raise the processor's IPL to value of priority. } BEGIN WRITELN('In kernel context ... '); DISABLE_INTERRUPT(priority); ENABLE_INTERRUPT; raise_ipl := 1; END; END; {MODULE kernel_context_example} 6-16 Device Handling Raise the IPL } Lower IPL to 0 } Returned in return_status} 6.9 Handling Power-Failure Recovery Devices normally need special attention following a power failure. When the necessary speed and synchronization requirements cannot be met by the general power-recovery exception (KER$_POWER_ SIGNAL), you can specify; in a CREATE_DEVICE call, the name of an ISR that is to be called when the processor enters its power-failure recovery sequence. Such a routine is called before any other process or ordinary ISR is restarted. Typically; for a processor to recover from a power failure, an application must perform the following sequence of operations: 1. Reinitialize the device controller to a known state. 2. Ensure that no partially completed I/O operations are started, since the device has been reinitialized. 3. Signal processes that are waiting for device interrupts, since no interrupts will occur now that the device has been reinitialized. These operations can be performed by a power-failure recovery routine. Since power-failure recovery occurs at unpredictable times, the ISR and main program must synchronize themselves with the action of the power-failure recovery routine to retry operations that were in progress. The VAX architecture defines a power-failure interrupt at IPL 30 (see Table 6-1). Therefore, a process can set the processor's IPL to 30 and block the interrupt, allowing the process to synchronize itself with the power-failure recovery routine. Once a power-failure interrupt has been posted, the processor has approximately 4 milliseconds before power is shut down. So the interrupt should not be disabled for more than a few instructions. Device Handling 6-17 Chapter 7 Exception Handling This chapter discusses VAXELN exceptions. and exception-handling procedures. The chapter discusses the following topics: • • • • • • VAX. stack architecture, Section 7.1 Exceptions in VAXELN systems, Section 7.2 Raising exceptions, Section 7.3 Exception-handling procedures, Section 7.4 Status codes, Section 7.5 Using runtime messages in application programs, Section 7.6 For language-specific information concerning exception handling, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 7.1 VAX Stack Architecture This section contains a brief review of the VAX. stack architecture. Whenever a program is executing on a VAX. processor, the stack pointer (SP) and frame pointer (FP) hardware registers describe an active stack environment. The syste~ software always sets up the initial stack environment for a process. Usually the memory for the stack is in the high virtual addresses of the process's memory, the. PI region. (See Chapter 3 for a discussion of VAX. memory management and the definition of the PI region.) .. Exception Handling 7-1 Stacks are good structures to record items in a defined order and then play the items back in the reverse order. Stacks are helpful in performing recursive operations, but in many cases they are best used as a record of the implicit state of a program. The call history of the procedures activated up to a point in the program is a typical application of this stack feature. The VAX. architecture uses the stack environment in the processing of many VAX. instructions. The simple cases are instructions such as PUSHAL, which pushes an address on the stack. The action of pushing is a 2-step process: subtract a constant from the SP register, then use the new SP value as the address at which to place the data. Popping the stack is the reverse: use the value of SP to address the data, then add a constant to the stack. The constant is dependent upon the operation. For PUSHAL, a longword is placed on the stack. In other contexts, different-sized objects are pushed or popped from the stack. VAX. stacks grow downward in address as they expand. Nothing can be assumed regarding the alignment of SP on a particular memory-length boundary, although some instructions, such as CALL, implicitly align the stack. Most high-level languages manage the stack environment for the programmer; it is not necessary to manipulate the SP value explicitly. At any given time, the value in the FP register contains the address of the active stack call frame, a small data structure, defined by the VAX. hardware, that contains information about the current procedure invocation and the state of the procedure that called it. At the same time, the value of the SP register is equal to or less than (that is, below) the FP value. The memory between the SP and FP values is referred to as the local storage of the procedure activation; together, the SP and FP values are referred to as the procedure's stack frame, as illustrated in Figure 7-1. Pascal and C use this space to store procedure temporaries or variables. The VAX. CALLS, CALLG, and RET instructions affect the values of SP and FP to dynamically create and destroy the frame structure. For instance, with the stack in the state pictured in Figure 7-1, if a procedure call is performed, the stack would look like Figure 7-2. 7-2 Exception Handling Figure 7-1: A Procedure's Stack Frame Procedure Local Storage :(SP) Active Call Frame :(FP) MLO-004281 Figure 7-2: A Frame Structure After a Procedure Call Stack Frame Procedure Local Storage :(SP) Active Call Frame :(FP) Stack Frame Procedure Local Storage Previous Call Frame MLO-OO4282 Internally, the call frame block looks like Figure 7-3. In Figure 7-3, Return PC contains the address of the first instruction after the CALL instruction that called this currently active procedure. Previous FP contains the address of the previously active frame: The Handler Address location is either Oor the address of an established condition handler procedure. (For a more detailed description of the frame contents, see the VAX Architecture Reference Manual.) By examining the current frame at the FP address, the history of the call sequence can be extracted by following the Previous FP values until the top of the stack is reached. This trail of frames is the key to understanding what happens when an exception occurs. Exception Handling 7-3 Figure 7-3: Call Frame Block Handler Address Register Mask I Previous PSW :(FP) :(FP) + 4 PreviousAP :(FP) + 8 Previous FP :(FP) + 12 Retum PC :(FP) + 16 Saved Registers :(FP) + 20 MLO-004283 7.2 Exceptions in VAXELN Systems The term exception describes programming events that occur during the execution of a program. Exceptions can be either synchronous or asynchronous: • • Synchronous exceptions occur at the same place in the program given a set of circumstances, for example, dividing by o. Asynchronous exceptions are triggered by an event outside the control of the program, for example, power failure. Some exceptions are generated by hardware events, and some are solely the result of a software event. VAXELN programs can experience these types of exceptions: • • • • • 7-4 Hardware-detected arithmetic problems, for instance, division by 0 or integer overflow Hardware-detected access problems, for instance, nonexistent memory Hardware-detected events, for instance, power failure Software-detected events, for instance, a signal of a process Software-detected conditions, for instance, a Pascal range violation Exception Handling • • Software-detected conditions in the runtime library, for instance, a problem with opening a file Software-detected conditions in the VAXELN Kernel when a program has requested a kernel service that must return an error status but the program did not specify a status parameter When an exception occurs, you have two options: ignore it or handle it. An exception might or might not be important for a program and it might or might not be expected. You must decide if a particular problem or exception condition is important or fatal to the program execution. The VAXELN Kernel exception-processing software notifies a running program of an exception by temporarily stopping the normal execution of the program and calling a specially defined exception handler routine defined by the program. Exception handlers are procedures that are established during the execution of a program to handle one or more of the potential exception conditions that can occur. For example, a programmer might know that an integer overflow could occur during a particular section of code and establish a special handler for that region. All of the VAX programming languages allow the programmer to dynamically establish exception or condition handlers. For transportability, the VAXELN exception mechanism is almost identical to the VMS exception mechanism. 7.2.1 Exception-Handler Arguments When an exception occurs, the VAXELN Kernel exception logic builds an argument list that describes the exception. The kernel then searches the current list of stack frames to find a frame that contains a nonzero condition handler address. When one is found, the handler procedure is called. If no handler is found, the kernel takes a default action. If the debugger is present in the system, a special debugger handler is called. The debugger handler acts as the condition handler, giving the programmer a chance to look at the state of the program. If no handler is found and the debugger is not present, the kernel deletes the process. Exception Handling 7-5 The argument list for an exception handler routine contains two values. The first argument value is the address of another data block that contains information about the exception that occurred. This block is the signal argument block. The signal arguments are illustrated in Figure 7-4. Figure 7-4: Signal Arguments Number of Longwords Following Name of the Exception :Signal Arguments :Signal Arguments + 4 Additional Exception-Dependent Information PC of the Exception PSL at the Exception Point MLO-004284 Each exception has a distinct argument list that provides information about the exception. Sometimes, as in the case of division by 0, no additional information is needed or present. Such exceptions have the same names as the corresponding status values, as described in Appendix A, Status ValueslException Names. The second argument value is the address of a data block that contains information needed to recover from the exception. This block is called the mechanism argument block. The mechanism arguments are illustrated in Figure 7-5. The frame depth value is the number of frames searched while the system is looking for the exception handler address. 7-6 Exception Handling Figure 7-5: Mechanism Arguments 4 :Mechanism Arguments FP of Established Handler :Mechanism Arguments + 4 Frame Depth :Mechanism Arguments + 8 RO at Exception :Mechanism Arguments + 12 R1 at Exception :Mechanism Arguments + 16 MLO-004285 7.2.2 Continue and Resignal Operations When the exception handler routine is called, it has the responsibility of looking at the exception name value and deciding what to do. The routine then returns a Boolean value to the kernel exception handler logic. If the Boolean value is TRUE (low bit of RO = 1) the kernel resumes execution of the program at the point of the exception; the condition is handled. If the Boolean value is FALSE (low bit of RO = 0) the kernel continues to search the stack frame list for another handler to call; the condition is not handled. These two actions are referred to as continuing and resignaling. Many high-level languages provide an explicit method for exiting a routine, such as an up-level GOTO in Pascal and the longjmp function in C, which you should use to exit an exception handler. When you use a Pascal up-level GOTO or a C longjmp, the language runtime library does an implicit continue on behalf of the program. As explained previously, if no handler is found that handles the exception, the kernel deletes the process and returns the exception name as the status. Each potential exception has an individual status code defined for it (see Section 7.5). The exception name value can be used to associate a descriptive text message with the status code, as explained in Section 7.6. Exception Handling 7-7 An exception handler may handle one or more individual exception conditions. Some programs have handlers that handle all exceptions and display a message if something unexpected occurs. Since the stack frame is searched backward in the call history, a handler established in the program's main routine would be the last to be called in the event of an exception and could act as the catch-all handler. In addition to the typical continue or resignal options, the program can also modify the exception state information and continue under different conditions. For instance, if an integer overflow occurs on a statement, the handler can modify the variables involved and continue. As another example, changing the value of the saved PC in the signal argument list has the effect of continuing the program at a different place. Remember, though, that the program continues with the stack state as it was at the exception. This means that the new PC must be in the routine that experienced the exception. 7.2.3 Unwind Operation As mentioned previously, some languages provide an explicit method for exiting the condition handler. Using such a method has the effect of continuing at a different location and possibly in a different stack environment. The act of exiting cleanly from one stack environment and reestablishing another stack environment is called unwinding. Because the stack discipline and modification are complex, a VAXELN Kernel procedure performs the unwinding operation. Normally, the unwind occurs automatically when an application exits an exception handler. If you use the KER$UNWIND procedure directly, it provides several options. You can specify KER$UNWIND with two parameters: a new frame pointer (FP) and an optional new program counter (PC) . The new FP argument specifies the target FP to which the stack will be unwound, or a value in the range 0 to 32767 that specifies the number of stack frames to be unwound (the frame depth). You can use a frame depth value only if you call KER$UNWIND from an exception handler or a routine called by an exception handler. Otherwise, the status value/exception SS$_NOSIGNAL is returned. When specified as frame depths, the values 0 and -1 have special meanings. The value 0 causes KER$DNWIND to unwind to the frame of the caller of the routine that established the handler. If you specify -1 for the frame depth, KER$UNWIND does not unwind any call frames. 7-8 Exception Handling The PC argument specifies the new PC at which execution should resume within the call frame specified by the new FP argument. If you do not specify a new PC, the kernel uses the return PC that is already established for the target call frame. The KER$UNWIND procedure has the effect of returning back through some number of subroutines without executing any code in the subroutines that are skipped. Unwinding allows a program to handle the exception by skipping back to a particular call point in the stack history, for instance, the caller of the routine that got the exception. As an unwind operation takes place, if a frame has a handler established, the handler is called with a special unwind exception condition. This exception is to notify the handler that the active frame is being skipped and that any necessary cleanup should be performed. The unwind handler is assumed to complete, returning the Boolean TRUE value that specifies continue. One final feature can be used when an unwind is performed. Most procedures that return a simple value return that value in RO and Rl. Most VAX languages adhere to this standard. You can, therefore, change the value of the saved RO and Rl in the mechanism argument block and then unwind. The effect is to set the value of a function and return. The following program calls procedures to a frame depth of three. The procedure at level three establishes an exception handler that unwinds the call stack two frames to the main procedure level. MODULE handler_test; INCLUDE $KERNEL, $SSMSG; PROGRAM handler_test; FUNCTION cond handler OF TYPE EXCEPTION_HANDLER; VAR status : INTEGER; unwind_depth : AANYTYPE; Exception Handling 7-9 BEGIN IF SIGNAL ARGS.NAME <> SS$_UNWIND THEN BEGIN WRITELN ('Inside condition handler.'); WRITELN ('Unwinding " mech args.depth:1, , fr~es'); WRITELN ('to return to the ;ain procedure.'); unwind depth::INTEGER := mech args.depth; KER$UNWIND(status, NEW FP := unwind_depth); cond handler := TRUE END ELSE cond handler := FALSE END; PROCEDURE level_3; VAR i, j, k : INTEGER; BEGIN WRITELN ('Process is in level-3.'); WRITELN ('Now raising an exception to test KER$UNWIND.'); RAISE EXCEPTION (1); WRITELN ('Should not execute this statement.'); END; PROCEDURE level_2; BEGIN WRITELN ('Process is in level-2.'); WRITELN ('Now calling level-3.' ); level_3; WRITELN ('Should not execute this statement.' ); END; BEGIN WRITELN ('This is the main program -- level 1.'); WRITELN ('Establishing a condition handler.'); ESTABLISH (cond_handler); WRITELN ('Now calling level-2.' ); level 2; WRITELN ('Control is back in level 1 after the unwind.' ); WRITELN ('Main routine is done.'); END. END; In the preceding example, active handlers are called during the unwind operation. Thus, the handler in the example checks whether an unwind operation is already in progress. If not, the handler calls KER$UNWIND. If an unwind operation is in progress, the handler resignals. When the unwind operation is complete, control returns to the main routine. 7-10 Exception Handling 7.2.4 Multiple Concurrent Exceptions When an exception signal is in progress, other exceptions can still occur. These exceptions also cause the stack to be searched for an active handler, but a special action takes place. Any frames that were previously tested for having an exception handler are not tested again. That is, when the exception occurs, the frames from the exception frame through the original condition handler are tested, then the frames between the handler's frame and the frame that activated the handler are skipped. The search resumes with the frame preceding the one that established the handler. This prevents handlers from being recursively entered; once active, a handler cannot be reactivated. 7.3 Raising Exceptions VAXELN provides the RAISE_EXCEPTION kernel procedure, which can be used to generate exceptions. The result is much like an exception caused by a hardware condition. Sections 7.3.1 and 7.3.2 provide information about kernel procedure failure exceptions and asynchronous exceptions, respectively. 7.3.1 Kernel Procedure Failure Exceptions Each VAXELN Kernel procedure accepts an optional status variable. The final status of the operation is placed in the variable as one of the last things done by the kernel procedure. If the program does not specify a status variable and the status is some sort of failure, an exception is generated, with the status as the exception name. This feature provides a means of handling unexpected failures for the programmer who expects kernel procedures to succeed. 7.3.2 Asynchronous Exceptions Asynchronous exceptions do not occur as a result of a program action but as a result of an external event that cannot be predicted. The resul t of an asynchronous exception is identical to that of any other exception, with one notable difference. While one of these exceptions is signaled, other asynchronous exceptions are prevented from occurring Exception Handling 7-11 until a handler returns the BOOLEAN TRUE value that specifies continue. However, other synchronous exceptions can still occur. In addition, VAXELN provides two kernel procedures for controlling the occurrence of these exceptions. Normally the exceptions are enabled, but calling DISABLE_ASYNCH_EXCEPTION prevents the delivery of the exceptions to the calling process until ENABLE_ASYNCH_ EXCEPTION is called. These procedures mimic the action of having an asynchronous exception signal in progress. Several types of asynchronous exceptions are generated by VAXELN: • • • KER$_POWER_SIGNAL. If a job is specified during system build as desiring power-recovery signals, the kernel generates an exception when the power recovery takes place. KER$_QUIT_SIGNAL. Signaling a process object causes the target process to receive this exception. KE R$_PROCESS_ATTENTI ON. This exception occurs when a process calls the kernel procedure KER$RAISE_PROCESS_ EXCEPTION. 7.4 Exception-Handling Procedures The kernel procedures relating to exception handling are summarized in Sections 7.4.1 to 7.4.5. 7.4.1 DISABLE_ASYNCH_EXCEPTION Procedure DISABLE_ASYNCH_EXCEPTION prevents the delivery of asynchronous exceptions to the calling process. 7.4.2 ENABLE_ASYNCH_EXCEPTION Procedure ENABLE_ASYNCH_EXCEPTION allows the delivery of asynchronous exceptions to the calling process. Asynchronous exceptions are enabled by default and must be reenabled only after being explicitly disabled. They also are disabled while an asynchronous exception is being handled. 7-12 Exception Handling 7.4.3 RAISE_EXCEPTION Procedure RAISE_EXCEPTION causes a particular software exception in the calling process. You can specify a list of 0 or more additional exception arguments, which will be made available to the exception handler in the array of additional arguments. NOTE Some exception names, such as SS$_ACCVIO, are used to identify specific system or hardware events (in this case, a virtual memory access violation); do not raise one of these exceptions. 7.4.4 KER$RAISE_PROCESS_EXCEPTION Procedure KER$RAISE_PROCESS_EXCEPTION raises the asynchronous exception KER$_PROCESS_ATTENTION in the specified process. 7.4.5 KER$UNWIND Procedure The KER$UNWIND procedure unwinds the call stack to a new location. Arguments supply the target frame pointer (FP) and the new program counter (PC) at the new FP. 7.5 Status Codes Status codes returned by VAXELN routines follow the VAX convention in which odd-numbered integers signify success and even values failure, though not necessarily fatal. The details of the convention are as follows: • • Bits 0 to 2 define the severity: 0 means warning, 1 means success, 2 means error, 3 means informational, and 4 means severe or fatal error. Bits 3 to 31 of the integer form a status ID. Exception Handling 7-13 Typically, an informational status is similar to success but is qualified in some way. For example, a command interpreter might use it to inform a user that although a delete command was understood and processed successfully, no objects were deleted. Similarly, warning and, sometimes, error severity imply that operation of a system is still possible, whereas fatal severity implies that it is not. NOTE For the exit status of a process, you can return any integer, although Digital recommends that you follow the convention just explained. The creator of a job has the option of receiving a special termination message when the created job completes. This message contains an integer making up the completion, or exit, status of the created job's master process. If the master process specifies no status of its own and completes successfully, the default status code is 1. NOTE The successful completion of a process can be represented by more than one exit status, for example, status code 1 or 3. Therefore, to check for success in your programs, you should check for an odd value (bits 0 to 2 equal 1 for success, or 3 for success with an informational message). 7.6 Using Runtime Messages in Application Programs The VMS system contains message-processing features that application programs can use to perform error checking and to handle the conversion of status codes into meaningful message text. These features are supported by the VMS Message Utility and the VMS system service $GETMSG. Using the Message Utility, you can construct messages for use with your application programs. The$GETMSG system service extracts message text from system and user-created message data bases generated by the Message Utility. The VAXELN Toolkit includes message files generated from the VMS Message Utility. You can use the contents of these files in your application programs to check and handle errors. Additionally, the toolkit provides two runtime routines that return message text associated with a status code: the system service SYS$GETMSG, which is similar 7-14 Exception Handling to the VMS $GETMSG routine, and a high-level language equivalent named ELN$GET_STATUS_TEXT. Sections 7.6.1 to 7.6.4 identify the VAXELN message files and explain how to create application-specific messages, use message files in application programs, and retrieve message text associated with status codes. 7.6.1 VAXELN Message Files The VAXELN Toolkit provides message source files and object modules used by the VAXELN software components for error checking and handling. The message source files reside in the general VAXELN runtime library. They consist of message definition statements and directives that define message text, status codes, and message symbols. You may want to examine them before or use them as templates while you create your own message files. Message object modules reside in the RTLOBJECT.OLB and RTL.OLB object module libraries. These modules are compiled message files. The RTLOBJECT message modules contain message symbols. Message symbols are global symbols that provide a convenient way for programs to refer to status codes (see Section 7.6.4). A message symbol consists of a prefix that identifies the facility and a symbol name that is defined in the message definition. An example of a message symbol defined for the VAXELN Kernel is KER$_NO_SUCH_PORT. The prefix is KER$_, and the message symbol is NO_SUCH_PORT. The RTL.OLB library contains two sets of message modules that are named facility$MSGDEF_TEXT and facility$MSGDEF. The facility$MSGDEF_TEXT modules contain message text. You link these modules with application programs that call the ELN$GET_STATUS_ TEXT procedure to access message text at runtime. The facility$MSGDEF modules in the RTL.OLB library define message symbols as linker global values for use with programs written in languages other than VAXELN Pascal. Table 7-1 summarizes the VAXELN message files. Exception Handling 7-15 Table 7-1: VAXELN Message Flies Source File RTLOBJECT Module CMSG.MSG $CMSG RTL Modules Description C$MSGDEF_TEXT C$MSGDEF Messages generated by the VAXELN C runtime library ELNDECW_DWTMSG.MSG ELNDECW_DWT$MSGDEF_ TEXT ELNDECW_DWT$MSGDEF Messages generated by the VAXELN DECwindows XUI Toolkit routines ELNDECW_XLIBMSG.MSG ELNDECW_XLIB$MSGDEF_ TEXT ELNDECW_XLIB$MSGDEF Messages generated by the VAXELN DECwindows Xlib routines ELNMSG.MSG $ELNMSG ELN$MSGDEF_TEXT ELN$MSGDEF Messages generated by the VAXELN Pascal compiler and other runtime components FORMSG.MSG $FORMSG FOR$MSGDEF_TEXT FOR$MSGDEF FORTRANspecific messages generated by the VAXELN FORTRAN runtime library KERNELMSG.MSG $KERNELMSG KER$MSGDEF_TEXT KER$MSGDEF Messages generated by the VAXELN Kernel LIBMSG.MSG $LIBMSG 7-16 Exception Handling LIB$MSGDEF_TEXT LIB$MSGDEF General runtime library messages generated by the VAXELN FORTRAN runtime library Table 7-1 (Cont.): VAXELN Message Files Source File RTLOBJECT Module MTHMSG.MSG RTL Modules Description $MTHMSG MTH$MSGDEF_TEXT MTH$MSGDEF Math runtime library messages generated by the VAXELN and VAXELN FORTRAN runtime libraries OTSMSG.MSG $OTSMSG OTS$MSGDEF_TEXT OTS$MSGDEF Languageindependent runtime library messages generated by the VAXELN and VAXELN FORTRAN runtime libraries PASCALMSG.MSG $PASCALMSG PAS$MSGDEF_TEXT PAS$MSGDEF Messages generated by the VAXELN Pascal runtime library SSMSG.MSG $SSMSG SS$MSGDEF_TEXT SYS$SSDEF System Service runtime messages generated by the VMS emulation routines and other VAXELN routines STRMSG.MSG $STRMSG STR$MSGDEF_TEXT STR$MSGDEF String runtime library messages generated by the VAXELN FORTRAN runtime library In addition to the modules listed in the preceding table, the VAXELN Toolkit includes the message image files ELNDECW_DWTMSG.EXE, ELNDECW_XLIBMSG.EXE, ELNCMSG.EXE, and ELNMSG.EXE and VAXELN Pascal compiler messages. The VAXELN installation procedure places the images ELNDECW_DWTMSG.EXE, ELNDECW_ XLIBMSG.EXE, and ELNCMSG.EXE in the VAXELN directory ELN$. Exception Handling 7-17 The ELNDECW_DWTMSG.EXE and ELNDECW_XLIBMSG.EXE images provide message text for the VAXELN DECwindows XUI Toolkit and Xlib runtime routines. The ELNCMSG.EXE image file provides message text for the VAXELN C runtime routines. The image file ELNMSG.EXE and the VAXELN Pascal compiler messages are used by software that runs on a VMS system. The VAXELN installation procedure places the image ELNMSG.EXE in the VMS directory SYS$MESSAGE. 7.6.2 Constructing Messages To construct application-specific messages, do the following: 1. Create a message source. 2. Compile the source file using the VMS Message Utility. 3. Include the resulting message object module when you link your application program. A sample message source file follows: . FACILITY . SEVERITY SYNTAX ERRORS . END RTAPPLICATION,l /PREFIX=RTAPP$_ ERROR/FAO=l Consult the message source files that reside in the general runtime library for more elaborate examples. After you create the source file, use the MESSAGE command to compile it. Specify the command in the following format: $ MESSAGE file-spec[, ... ] The default file type for message source files is MSG. The following example compiles the message source file RTAPPMSG.MSG and produces the message object module RTAPPMSG.OBJ: $ MESSAGE RTAPPMSG You can then link the message object file with your application program. For example: $ 7-18 LINK/NOSYSSHR RTAPPLICATION+RTAPPMSG+ELN$:RTLSHARE/LIB+RTL/LIB Exception Handling For more information about the VMS Message Utility, see the VMS Message Utility Manual. 7.6.3 Using Message Files with Application Programs You can use VAXELN and application-specific message symbols in your application programs to check for and handle various conditions at runtime. A program can compare a message symbol with a status value returned by a routine call to check whether an operation completed successfully or whether a particular error occurred. To use message symbols, a program must import them with a languagedependent include statement. Alternatively, you can include message symbols by specifying a message module, such as KER$MSGDEF_ TEXT, from RTL.OLB when you link the application. You can include the same set of object modules for each application program or you can set up the application such that all jobs share the message text shareable image ELN$:SHARED_STATUS_TEXT.EXE. This shareable image contains the status text for the following toolkit components: • • • • • • • • Kernel VAXELN runtime library C runtime library VAXELN Pascal runtime library FORTRAN runtime library General runtime library (LIB) Language-independent runtime library (OTS) String runtime library (STR) For information about building the message text shareable image into a VAXELN system or tailoring the shareable image, see the VAXELN Development Utilities Guide. Example 7-1 imports the message. symbols from the message module $KERNELMSG. The program then uses the symbols KER$_SUCCESS and KER$_DISCONNECT to check for success and error conditions. Exception Handling 7-19 Example 7-1: Using Message Flies MODULE msg_symbol_ex; INCLUDE $I tr; fileJ>tr=fopen("10::SYS$LIBRARY:DIGITAL.DAT","r"); The FORTRAN equivalent would look like the following: OPEN(FILE = 'lO::SYS$LIBRARY:DIGITAL.DAT', TYPE = 'NEW', UNIT = 100); 9.5.2 Requesting Connections from VAXELN Systems You can use the CONNECT_CIRCUIT procedure to request a connection with a VMS program on the same DECnet network by specifying the destination_name argument in the following format: 'nodenumber::objectname' The nodenumber is a network node number (as described in Section 9.5.1), and objectname is the name of the object on the VMS system that will handle the connection. Set up a command procedure that runs the desired VMS program image, name the procedure objectname.COM, and place it in the default DECnet directory on the VMS system. The command procedure executes when the DECnet-VAX. software gets a request for a connection to the specified object. The VMS image then handles the connection. DECnet Network Services 9-47 9.5.3 Accepting Connections on VMS Systems A VMS program image has two ways of waiting for and accepting a connection from a VAXELN system: • • You can use an operation that is comparable to using the VAXELN ACCEPT_CIRCUIT procedure. You can specify the name SYS$NET in a high-level language OPEN procedure (or equivalent). (In a VAX MACRO program, you can use the $ASSIGN system service.) You can break the connection by calling the DISCONNECT_CIRCUIT procedure from your VAXELN program or by performing a close operation in the VMS program. 9.5.4 Requesting Connections from VMS Systems A VMS program can request a connection with a VAXELN program by using a high-level language OPEN procedure or the $ASSIGN system service with a name of the form: nodename::"TASK=portname" The node name is the name of the VAXELN network node, and the portname is the character string name of the port created by the VAXELN program; 9.5.5 Accepting Connections on VAXELN Systems The VAXELN program does nothing special to accept a connection from a remote VMS program. The VAXELN program needs only to create a PORT object and a NAME object for the port and then call the ACCEPT_CIRCUIT procedure to await the connection request. 9-48 DECnet Network Services 9.5.6 Using OECnet Object Numbers in Connection Requests A VAXELN program can connect and accept connections using requests that specify DECnet object numbers instead of names. This feature is useful only for compatibility with existing DECnet applications. To connect to a port or object by number, specify a string with this format for the DESTINATION_NAME parameter of CONNECT_ CIRCUIT: 'nodenumber::objectnumber' To accept a connection for an object by number, create a port name of the form: 'NET$OBJECT_objectnumber' Here, objectnumber is the object number in ASCII. Once the name is created, connections can be accepted as usual. 9.6 Remote Terminal Utility The Network Service provides a Remote Terminal Utility that lets you connect to a remote computer system from a terminal on another computer system by using a SET HOST command. For example, you can connect to a VAXELN system from a VMS system terminal by using the DCL SET HOST command, or you can connect to a VMS system from a VAXELN system terminal by using the ECL SET HOST command. Once connected to a remote system, you can log in, use operating system commands (such as DCL and ECL commands), receive messages, and interact with programs that run on that system. To use the Remote Terminal Utility, you must build it into your VAXELN system with the outbound, inbound, or outbound/inbound capability. The outbound capability lets you connect to computer systems from your VAXELN system. The inbound capability lets you connect to your VAXELN system from other systems. For more information about the Remote Terminal Utility and the ECL SET HOST command, see the VAXELN Development Utilities Guide. DECnet Network Services 9-49 Chapter 10 Internet Services You can use the VAXELN Internet Services for VAXELN applications that need to communicate between two computer hosts that reside on the same or on different networks. The hosts are the sources and destinations ,of transferred data. The Internet Services provide the protocols necessary for VAXELN applications to transfer data over an Internet. An Internet is a set of connected networks. Higher-level software hides the underlying Internet architecture and makes a collection of networks appear as a single large network. The hosts on a network are physically connected and networks on the Internet are physically connected. Applications can communicate across intermediate networks even though the networks are not connected to the source or destination host. The hosts that connect and transfer messages between networks are called gateways. NOTE Although VAXELN systems can use gateways for Internet communication, they cannot function as gateways. The VAXELN Internet Services provide the following: • • • • Connectionless or end-to-end connection-oriented packet delivery service Packet delivery service that is independent of the communications medium over which data is transmitted Communications environment that supports a variety of computer platforms Communications protocol standards Internet Services 10-1 This chapter explains Internet Service concepts in Section 10.1, how to configure a VAXELN system that uses the Internet Services in Section 10.2, and how an application can use runtime routines to do the following: • • • • • Control the Internet Services, Section 10.3 Convert the byte order of Internet and host physical addresses, Section 10.4 Manipulate Internet addresses, Section 10.5 Communicate over the Internet, Section 10.6 Retrieve and set socket characteristics, Section 10.7 NOTE The VAXELN Intern,et Services cUlTently support a C language runtime interface only. 10.1 Internet Service Concepts Before using the VAXELN Internet Services, you should understand the following Internet Service concepts: • • • • • • • Client-server model Internet architecture Internet addresses Ports as Internet communication endpoints Sockets Routing Fragmentation Sections 10.1.1 to 10.1.7 explain these concepts. 10-2 Internet Services 10.1.1 Client-Server Model The hosts in a network environment communicate through processes. A process that offers a service over the network to another process is known as a server. Servers accept requests from other processes known as clients. A client sends requests and waits for the results from the server. Figure 10-1 represents a client-server model. Figure 10-1: Client-Server Model A process name on a host cannot be used as the destination for message communication for the following reasons: • • • Heterogeneous operating systems define processes differently. Not all processes that send data have enough information to identify a process on another host. Process IDs can change. Therefore, the hosts on the Internet identify communication endpoints using ports (see Section 10.1.4). Internet protocols that comprise the Internet architecture allow communication between the client and server endpoints. 10.1.2 Internet Architecture The Internet architecture consists of four layers of protocol that allow two-way interprocess data flow between hosts, gateways, and networks. The architecture includes an application layer, host-to-host protocol layer, Internet Protocol (IP) layer, and network protocol layer. Figure 10-2 illustrates the Internet layers. Internet Services 10-3 The host-to-host layer supports two protocols: the User Datagram Protocol (UDP) and the Transmission Control Protocol (TCP). Figure 10-2: Internet Layers Application Layer Application Code Host-to-Host Protocol Layer Internet Protocol Layer IP Network Protocol Layer Datalink Driver ... Communications Medium - - - - - - I.. ~ MLO-004160 Processes on a host transmit data by passing it to the lower protocol layers. A process at the application layer passes the data to the hostto-host protocol layer. The host-to-host protocol layer then packages the data according to protocol functions. For example, TCP adds a header that ensures reliable communication. Then the protocol sends the packaged data to the IP layer. The IP also adds a header and sends the data to the local datalink driver. Sections 10.1.2.1, 10.1.2.2, and 10.1.2.3 describe IP, UDP, and TCp, respectively. 10-4 Internet Services 10.1.2.1 Internet Protocol The Internet Protocol (IP) is a protocol that is used for data communication in a packet-switched computer network. IP implements mechanisms for connecting networks and gateways into a system that can deliver network packets from source to destination. IP saves applications from addressing network specifics by doing the following: • • • Routing packets to destinations through networks Keeping track of routes for hosts and networks Accounting for incompatibilities The protocol packages message data and a header in blocks called datagrams. The header provides fixed-length source and destination Internet addresses, a protocol number that identifies the host-tohost protocol being used, and a checksum value. The datagrams are encapsulated in the network packets that are delivered between the source and destination hosts. IP can fragment and reassemble datagrams if necessary to accommodate requirements of smaller packet networks. IP is specifically limited to delivering datagrams, without provisions for reliability, flow control, sequencing, or other services found in host-to-host protocols. In addition to handling datagram fragmentation, IP implements address mapping, and transmits control and error messages by using the following protocols: • • Address Resolution Protocol (ARP). Dynamically maps Internet addresses to physical Ethernet addresses and stores the address pairs in an ARP cache. Using this protocol, an application can determine a target host's physical (built-in) Ethernet address. Section 10.1.3 provides more information about Internet addresses. For more information about managing the ARP cache, see Section 10.3.l. Internet Control Message Protocol (ICMP). Transmits error and control messages to a destination host's IP when an IP datagram delivery fails. ICMP provides routing information and notifies hosts when a datagram cannot reach its destination or when a datagram's keep-alive time reaches zero. Internet Services 10-5 • 10.1.2.2 Reverse Address Resolution Protocol (RARP). Determines a diskless host's Internet address at start-up so that the host can operate in an Internet network. A host can broadcast a message that specifies its physical Ethernet address to all hosts in a local area network (LAN). A host running an RARP server searches its address data base and responds by returning the appropriate Internet address. See Section 10.1.3 for more information about Internet addresses. User Datagram Protocol The User Datagram Protocol (UDP) is layered on IP and provides host-to-host datagram communication for applications that do not require streamed communication. UDP adds multiplexing to IP, letting multiple processes use the protocol to send and receive data independently. The protocol achieves mutliplexing by using ports to identify the processes executing on a host. UDP lets application programs send messages to programs running on other hosts in a network using minimal protocol. The protocol is transaction oriented, and it does not guarantee delivery or duplicate protection. UDP accepts a message from an application, places the message in a datagram, and tries to deliver the datagram. The datagrams may not arrive at the destination or may arrive out of order. Because UDP does not provide a reliable service, applications generally add reliability by incl uding error and sequence control. Table 10--1 summarizes UDP characteristics: Table 10-1 : 10-6 UDP Characteristics Protocol Characteristic UDP Specifics Initial setup Not required Transmission path Datagram Error handling Done by application Remote address Remote address may be specified on each transmission End-to-end flow control Not provided Data sequencing Passed in order of arrival Internet Services Table 10-1 (Cont.): UDP Characteristics UDP Specifics Protocol Characteristic Checksum computation Provided The VAXELN Toolkit provides a Boot Protocol (BOOTP) that is based on UDP. Like RARp, BOOTP determines a diskless host's Internet address at start-up so that the host can operate in an Internet network. A host can broadcast a message that specifies its physical address to all hosts in a LAN. A host running a BOOTP server searches its address data base and responds by returning the appropriate Internet address. 10.1.2.3 Transmission Control Protocol The Transmission Control Protocol (TCP) is layered on IP and provides host-to-host, connection-oriented communication in a network environment. TCP adds multiplexing, checksum computations, connectivity, and reliability to IP. TCP provides for reliable interprocess communication between pairs of processes executing on host computers attached to distinct but interconnected networks. Although TCP is layered on IP, TCP does not require reliability of the underlying IP and datalink driver. TCP uses virtual circuits for data transmission. The virtual circuits provide automatic sequencing, error control, and flow control. Applications that use TCP must establish a virtual circuit connection before transferring data. Once an application establishes the connection, the application can use data transfer calls to send data to a destination without specifying a destination address. When the connection is no longer needed, the application must explicitly shut it down. TCP provides the following functions: • Transfers a continuous stream of bytes in each direction between a source and destination. TCP breaks up a message into bytes, packages the bytes into segments for transmission through the Internet, and reassembles the message at the destination. TCP ensures that all data is transferred. Internet Services 10-7 • • • • Recovers lost, duplicated, or out-of-order data by assigning a sequence number to each octet (eight bits) transmitted, and requiring a positive acknowledgment (ACK) from the receiving TCP. If the ACK is not received within a timeout interval, the data is retransmitted. The receiver's TCP uses the sequence numbers to reorder segments that are received out of order and to eliminate duplicates. TCP handles damaged data by adding a checksum to each transmitted segment, checking it at the receiver end, and discarding damaged segments. Handles flow control. TCP controls data flow by returning a sliding window (message buffer size) with every ACK indicating a range of acceptable sequence numbers beyond the last segment successfully received. The window identifies the number of octets that the sender can transmit before receiving an ACK. Provides for multiplexing. Using ports, multiple processes rtmning on a host can use TCP simultaneously. Establishes connections using unique device interfaces that specify connection-related information, such as status information, sequence numbers, and window sizes. TCP establishes a connection by using a handshaking mechanism with initial sequence numbers to avoid connection initialization errors. An application should terminate a connection and free resources when the connection is no longer needed. Table 10-2 summarizes TCP characteristics: Table 10-2: TCP Characteristics Protocol Characteristic TCP Specifics Initial setup Required Transmission path Virtual circuit Error handling Transparent to application Remote address Remote address is required at setup End-to-end flow control Provided Data sequencing Passed in order sent Checksum computation Provided 10-8 Internet Services 10.1.3 Internet Addresses For a source host to communicate with a destination host, it must know the Internet address of the destination host. An Internet address is a 32-bit (four octets) address that identifies a network and a host. o 32 I Network Identifier Host Identifier MLO-004161 The network identifier must be the same for all hosts connected to the same network, and no two networks can have the same network identifier if they are connected in any way. No two hosts on the same network can have the same host identifier. The notation used to represent a 32-bit Internet address consists of four decimal integer fields separated by periods. The value in each field can range from 0 to 255. A sample Internet address might be represented as 5.0.2.10. An Internet address can fall into one of three network classes and can identify subnetworks (see Section 10.1.6). A network mask informs a system which bits of an Internet address to interpret as the network, subnetwork, and host addresses. A broadcast mask interprets an Internet address as a broadcast address. Sections 10.1.3.1, 10.1.3.2, and 10.1.3.3 provide more information about network classes, network masks, and broadcast masks, respectively. 10.1.3.1 Network Classes In addition to providing a network identifier, the network part of an Internet address identifies a network class. The Internet supports three network classes: Class A, Class B, and Class C. The network configuration determines a network's class type. The four Internet address fields are used in different ways to specify the network class, network number, and host number. The high-order bits in an Internet address designate the network class of the address. The first high-order bits for each class are defined as follows: Internet Services 10-9 Class High-Order Bits A o B 10 110 C For a Class A network, the first field specifies the network number and class and the remaining three fields specify a subnet number, if subnetworks are being used (see Section 10.1.6), and the host number. The following figure shows such an Internet address: 32 24 16 o 8 MLO-004162 The value in the first field can range from 1 to 126, inclusive. By convention, 127 is reserved as the loopback address. Loopback is used for testing the connectivity to a specific host in the network. NOTE Currently, the VAXELN Internet Services do not use 127 as the loopback address. For a Class B network, the first two fields specify the network number and class, and the remaining two fields specify a sub net number, if subnetworks are being used, and the host number. The value in the first field can range from 128 to 191 and the value in the second field can range from 1 to 254. The following figure shows the Internet address format for a Class B network: MLO-004163 10-10 Internet Services For a Class C network, the first three fields specify the network number and class, and the remaining ;field specifies the host number, as shown in the following figure: MLO-004164 The value in the first field can range from 192 to 223, the value in the second field can range from 0 to 255, and the value in the third field can range from 1 to 254. Subnet routing is not generally used with a Class C network because there are only eight bits in the host field. Table 10-3 lists the ranges of the network numbers for the three network classes. Table 10-3: Network Class Number Ranges Class Number A 1.-126. B 128.1-191.254 C 192.0.1-223.255.254 To determine which network class to use, you must consider the number of network hosts and the number of Internet networks. The Class A network is best suited for sites with a few networks but numerous hosts, because it has 24 bits in the host part of its Internet address. The 24 bits allow for the most host-number combinations. In this case, the network part of the Internet address consists of seven usable bits, leaving 126 usable network-number combinations (0 and 127 are reserved). The Class B network is best suited for sites where the number of networks is about equal to the number of hosts, because the 32 bits of the Internet address are evenly divided between the network and the host part of the address. The network part uses 16 bits and the host part uses 16 bits. Internet Services 10-11 The Class C network is best suited for sites with numerous networks but few hosts, because the network part of the Internet address has 21 usable bits. The 21 bits allow up to 2,097,152 network-number combinations, while the eight bits of the host part of the Internet address can have only up to 254 host-number combinations. If you are planning to set up a LAN, you should obtain a registered Internet address. This way, if you choose to connect your network with another network, you will not have to change your Internet addresses. You can obtain a registered Internet address by calling the Network Information Center at 1--800-235-3155 from inside the United States. 10.1.3.2 Network Mask A network mask is a 32-bit number that informs the system which bits of the Internet address to interpret as the network, subnetwork, and host addresses. A one-to-one correspondence exists between the 32 bits in the network mask and the 32 bits in the Internet address. For each bit in the network mask that is set (binary 1), the corresponding bit position in the Internet address is interpreted as part of the network and subnetwork address. The decimal number 255 is 11111111 in binary notation. The value 255 means that an entire 8-bit field is set because each bit position is a 1. Generally, an 8-bit field is either set (255) or cleared (0). Values other than 255 and 0 can be used, but by using 255 or 0 you make it easier to differentiate between the network, subnetwork, and host fields. If the network mask bit position is part of the host field and is set, the corresponding bit in the Internet address is interpreted as part of the subnetwork address. If the network mask bit position is part of the host field and is cleared, the corresponding bit in the Internet address is interpreted as part of the host address. Each bit in the first (leftmost) field of the network mask must be set (decimal value of 255, binary value of 11111111), because the first field of the Internet address must always be interpreted as the network address regardless of whether subnetworks exist. If a bit in the first field of the network mask is cleared, part of the network field of the Internet address is interpreted as part of the host address. This may cause errors. The second and third fields are usually 255 or 0, depending on how the Internet address is to be interpreted. The fourth field is usually 0, indicating that it represents the host address. 10-12 Internet Services A Class A network mask is usually 255.255.0.0 or 255.255.255.0. When the network mask is 255.255.0.0, the first octet is the network address, the second octet is the subnet address, and the third and fourth octets are the host address. If the network mask is 255.255.255.0, the first octet is the network address, the second and third octets are the subnet address, and the fourth octet is the host address. If a Class B network uses 255.255.255.0 for a network mask, the first and second octets are the network address, the third octet is the subnet address, and the fourth octet is the host address. Normally, Class C networks do not have subnetworks, because only eight bits are allocated for the host part of the Internet address. Eight bits may not be enough to divide between a subnetwork address and a host address. The default network masks for each class are as follows: 10.1.3.3 Class Default Network Mask A 255.0.0.0 B 255.255.0.0 C 255.255.255.0 Broadcast Mask A broadcast mask interprets an Internet address as a broadcast address. Using the broadcast address, a process can send messages to all hosts on the network that have the same Internet broadcast address at the same time. The format of the broadcast address consists of the network number followed by all ones ( 1 ). NOTE Some operating systems, such as UNIX BSD 4.2 and ULTRIX-32 prior to Version 1.2, require that the Internet broadcast address be the network number followed by all zeros (0). Currently, the VAXELN Internet Services support only the default format. The network number includes the subnet, if there is one. Internet Services 10-13 If you know the Internet address and the network mask for a particular host, you can calculate the broadcast mask by using the following formula: (NOT networkmask) OR (internetaddress) For example, if a host has an Internet address of 128.50.100.100 and the network mask 255.255.0.0 (the default), the host's broadcast mask is 128.50.255.255. The NOT of the host's network mask is 0.0.255.255. You then substitute the first two fields of the Internet address for the two zeros to get the broadcast mask. Table 10-4 lists examples of broadcast addresses. Table 10-4: Broadcast Addresses Host Number Network Class Network Number Network Mask (Subnet Mask) Broadcast Address 3.0.0.10 10 A 3. 255.0.0.0 3.255.255.255 11.1.0.12 12 A 11.1. 255.255.0.0 11.1.255.255 129.39.0.15 15 129.39. 255.255.0.0 129.39.255.255 128.45.2.8 8 B B 128.45.2. 255.255.255.0 128.45.2.255 192.0.1.8 8 C 192.0.1. 255.255.255.0 192.0.1.255 192.0.1.223 223 C 192.0.1. 255.255.255.0 192.0.1.255 Host Internet Address 10.1.4 Ports as Internet Communication Endpoints While Internet addresses identify source and destination hosts, ports represent the endpoints of a communications link between two processes. Like the messages sent to a VAXELN port, Internet messages sent to a port are queued until another process extracts them. Processes that are waiting for messages are blocked until a message arrives. To send data to a port on another host, a process uses a destination host's Internet address and a port number. The Internet address identifies a network and a host. The port number identifies a particular destination on the host. A process also specifies a source port when it sends a message. The process that receives the message can use the source port to return a reply. 10-14 Internet Services Integers identify the communications ports. The source and destination ports are not necessarily identified with the same port number. TCPIIP and UDPIIP use port numbers that range from 1 to 65535. Port numbers ranging from 1 to 1023 identify privileged ports. Privilege means something different for each operating system. In general, when a host receives a message from a privileged port, you can assume that the destination host has done some level of checking against the application using the port. The port numbers ranging from 1 to 255 are reserved to provide a service contact point to known callers. Digital honors these assigned ports as implemented in the Department of Defense (DoD) and Defense Advanced Research Projects Agency (DARPA) Internet communities. Before an application can use UDPIIP or TCP/IP for communication, a process must be bound to a port. An application binds a process to a port by specifying an Internet address and port number in a call to the bind function (see Section 10.6.2). NOTE To bind a process to a privileged port, the calling program must be authorized with a system group UIC (that is, a UIC less than or equal to %X0008FFFF or [10, 177777]). 10.1.5 Sockets A socket is a communication endpoint abstraction that allows two peers to communicate. The peers can be entities such as two programs, two processes within a program, or a program itself. Sockets have the following properties: • • • Communication domain Protocol type Protocols A communication domain is the collective common properties of processes communicating through sockets. One such property would be the naming scheme of the sockets. The VAXELN Internet Services support the Internet (AF_INET) domain. Internet Services 10-15 Protocol types are the communication properties that are visible to the user. Normally, processes communicate only between sockets of the same protocol type. Three protocol types are available as defined in Table 10-5. Table 10-5: Socket Protocol Types Protocol Type Description Stream Provides bidirectional, reliable, sequenced, and unduplicated data flow without record boundaries. The receiving processes are guaranteed to receive messages, in order, without duplication. Datagram Provides bidirectional data flow that does not guarantee that messages will be received in sequence, without duplication, or at all. The record boundaries of the data are preserved. Raw Provides access to underlying communicati.ons protocols that support sockets. Raw sockets are not intended for the general user; they are mainly available for developing new communications protocols. The stream, datagram, and raw protocol types map to the protocols TCP, UDP, and IP, respectively. These protocols are described in Section 10.1.2. Before a process can use a socket, the process must bind a name (Internet destination) to the socket. A socket name consists of an Internet address (network and host) and port number (process on the host). Once a socket has a name, an application can use the socket for connection or connectionless communication. Sections 10.1.5.1 and 10.1.5.2 provide more information about these two modes of communication. 10.1.5.1 Connection Socket Communication After a process binds a name to a socket, the process can use that socket to establish a connection and communicate with another process over the Internet. One process can function as a client and the other as a server. Once a socket is created, the server listens to its socket for service requests. The client requests services from the server by initiating a connection request. 10-16 Internet Services If the client process's socket is unnamed at the time of a connection request, the Internet software assigns a name to the socket. If the connection is successful, the socket is associated with the server and data can be transmitted. If the connection is unsuccessful, an error is returned (the name that the system binds to the socket remains). A connection may be unsuccessful for one of the following reasons: • • A lack of resources on the source or destination host An application problem such as: Conventions not being followed The incorrect port number being specified A privileged port number being required Mter binding the socket, the server can receive a client's connection request if the following conditions exist: • • Server is listening for the connection request Maximum number of outstanding connections that can be queued to the server's port has not been reached If a client requests a connection when the queue is full, the messages that comprise the request are ignored and the client retries the request. Once a connection is established, data can be exchanged between the two sockets. For communication to take place between the source and destination hosts, the socket at each endpoint must be bound to a name. The application program on the source host must provide its Internet address and the destination socket name. The source port number is optional. If the application program omits the port number, the Internet software on the source host selects a port number. 10.1.5.2 Connectlonless Socket Communication Sockets can also support connectionless communication typical of datagram facilities found in packet-switched networks. While processes are still likely to have a client-server relationship, applications do not need to establish connections. Instead, each message includes a destination address. You create datagram sockets the same way that you create sockets for connection-oriented communication. However, you must bind a name to each datagram socket to identify the message sender and receiver. Internet Services 10-17 For source and destination hosts to communicate, applications must specify the source and destination socket names. The application program on the source host must provide its Internet address and the destination socket name. The source port number is optional. If the application program omits the port number, the Internet software on the source host selects a port number. 10.1.6 Routing A route is the path over the Internet that information takes to get from one host to another. A route can be a path to either a host or a network. IP uses routes to hosts for sending packets to a remote host and uses routes to networks for sending packets to any host in a remote network. A subnetwork is a set of hosts within a network that are organized into a logical group. A network can be made up of several subnetworks. A host on another network can access a host on a subnetwork if a gateway connects the networks. The data from the host on the other network is routed through the gateway to the network and onto the appropriate subnetwork, where the destination host ultimately receives the data. A subnet mask identifies the bits in an Internet address to be used for the network and subnet addressing. The VAXELN Internet Services support static routing. This method of routing employs a table that pairs destination Internet addresses with Internet addresses that specify routes. Each table entry also contains flags that specify the following: • • • 10-18 Whether IP should use only the network portion of an Internet address or an entire Internet address when searching for a matching destination Internet address in the routing table Whether the route for a destination Internet address is to a host on the local network or to a gateway on the local network Whether the route is locked to prevent ICMP from updating the route with redirect messages Internet Services The destination Internet address identifies a host or network. The Internet address that specifies a route can identify a host or gateway on the local network. The Internet address for a gateway is an intermediate destination for datagrams being sent to the network identified in the table entry. Figure 10-3 shows the routing table format. Figure 10-3: Routing Table Flags Destination Route Network or Local? Locked? Destination Internet Address Gateway or Local Internet Address MLO-004165 IP uses the routing table to determine the appropriate path for a datagram. The protocol extracts the destination Internet address from the datagram and searches for a matching destination Internet address in the routing table, extracting the network portion of the address as necessary. Figure 10-4 provides an overview of the routing algorithm. Internet Services 10-19 Figure 10-4: Routing Algorithm Extract Internet address from datagram Broadcast datagram over the Ethernet using the address FF--FF--FF--FF--FF--FF Loop datagram back to port on local host Transmit on the local network Search routing table for destination Internet address MLO-004166 Figure 10-4 Cont'd on next page 10-20 Internet Services Figure 10-4 (Cont.): Routing Algorithm Search for match using network portion of destination Intemet address Search for match using entire destination Internet address Use destination Internet address to transmit datagram Use gateway Intemet address to transmit datagram Use default gateway address to transmit datagram Discard datagram MLO-004167 Internet Services 10-21 IP first checks whether the destination Internet address equals a broadcast address, or the local host's Internet address. If the address is a broadcast address, IP broadcasts the datagram over the Ethernet using the FF-FF-FF-FF-FF-FF Ethernet address. A destination Internet address is considered a broadcast address if one of the following conditions applies: • • • The address is 255.255.255.255 The network part of the address matches the network part of the local host's Internet address and the logical OR of the destination address and the network mask equals 255.255.255.255 The address is local and the logical OR of the address and the subnet mask equals 255.255.255.255 NOTE IP cannot check for a broadcast address if it has not yet determined the local Internet address. If the destination Internet address is equal to the local host's Internet address, IP loops the datagram back to a port on the local host. If the destination Internet address is not a broadcast address or the local host's Internet address, IP checks whether the address is local and if so, sends the datagram to a node on the local network. The destination Internet address is local if one of the following applies: • • The subnet mask isO The logical AND of the destination Internet address and the subnet mask equals the logical AND of the local host's Internet address and the subnet mask If the destination Internet address is not local, IP searches the routing table for a matching address. If the network flag is set, IP uses only the network portion of the address when checking for a match. Otherwise, IP uses the entire address for the search. If IP finds an entry for the address, the protocol checks the state of the local flag. If the flag is set, IP uses the destination Internet address to route the datagram to a host on the local network. Otherwise, IP uses the gateway address in the table entry to route the datagram to a gateway on the local network. If IP does not find an entry in the routing table for the destination address, IP checks the table for a default gateway. If IP does not find a default, the protocol discards the datagram. 10-22 Internet Services An application can manage a routing table at runtime by using Internet service routines. For more information, see Section 10.3.2. 10.1.7 Fragmentation IP fragments a datagram when a datagram originates in a local network that allows a large packet size and must traverse a local network that limits packets to a smaller size to reach its destination, IP may also fragment a datagram when no gateway exists and applications send messages that are greater in length than the network layer supports. A gateway can fragment an Internet datagram into smaller Internet datagrams. The gateway produces a set of Internet datagrams, each carrying a fragment. If necessary, subsequent gateways can break down the fragments into smaller fragments. The fragment format is designed so that the destination IP can reassemble fragments into datagrams. 10.2 Configuring Internet Services To use the Internet Services, you must build the appropriate datalink driver and the Internet Services into your VAXELN system. You configure the Internet Services for a system by selecting the Edit Internet Service Characteristics entry on the System Builder's Main Menu. When you select this entry, the System Builder displays two menu options: Edit Internet Characteristics and Edit Internet Network Description. The Internet Characteristics Menu lets you define systemwide Internet characteristics. You must use the Internet Network Description Menu to provide an Internet network description for the Ethernet controller that is to use the Internet Services. You include the Internet Services in a VAXELN system by selecting Yes for the Internet Services entry on the Internet Characteristics Menu. This menu defines the following general systemwide Internet characteristics: • • • Maximum number of ARP cache entries Maximum number of routing table entries Maximum number of bytes in an Internet datagram Internet Services 1~23 • Default gateway You also can use the Internet Characteristics Menu to define the following systemwide TCP characteristics: • • • • • • • • Maximum number of octets in a segment Default number of octets in the sliding window Maximum number of octets in the sliding window Number of seconds to wait for a connection Number of seconds a connection should linger after it is closed Number of seconds to wait for a connection acknowledgment Number of seconds to wait for message acknowledgments Maximum number of message resends You provide an Internet network interface description for an Ethernet controller in your system by editing the Internet Network Description Menu. Using this menu, you specify the following controller information: • • • • • • • • Name Internet address Internet network mask Broadcast mask Address resolution method Whether the Internet Services are to determine the network mask Number of seconds to wait for the Internet address before timing out (0 indicates no timeout) Number of seconds to wait for the Internet network mask before timing out (0 indicates no timeout) If you include the Internet Services in a VAXELN system, an application program can use runtime routines to control the Internet Services, convert byte order Internet and host physical addresses, communicate over the Internet, and retrieve and set socket characteristics. For descriptions of the Internet Service routines, see the VAXELN C Reference Manual and VAXELN C Runtime Library Reference Manual. For more information about building the Internet Services into VAXELN systems, see the VAXELN Development Utilities Guide. 10-24 Internet Services 10.3 Controlling Internet Services A VAXELN application can use Internet Service control routines to manage the ARP cache, routing table, and Internet network interfaces dynamically at runtime. Control routines also provide a means for retrieving IP, UDP, and TCP statistics and connection information. 10.3.1 Managing the ARP Cache ARP maps Internet addresses to Ethernet addresses and stores the address pairs in an ARP cache. A host searches its ARP cache for an Internet address binding. If the host does not find the binding, the host broadcasts the target host's Internet address to all hosts on the network. The target host recognizes its Internet address and responds by returning its physical address to the requesting host. The VAXELN Internet Services provide the following Internet network control routines for managing a host's ARP cache: Routine Description Deletes an entry from the ARP cache. Returns an Ethernet address from the ARP cache. ELN$INET_SET_ARP_ENTRY Adds an entry to the ARP cache. ELN$INET_SHOW_ARP_ENTRIES Returns the entries currently stored in the ARP cache. For information about Internet addresses, see Section 10.1.3. Sections 10.3.1.1 to 10.3.1.3 explain how to use the Internet control routines to do the following: • • • Add and delete ARP cache entries Retrieve Ethernet addresses from the ARP cache Retrieve ARP cache entries Internet Services 10-25 10.3.1.1 Adding and Deleting ARP Cache Entries An application can add entries to and delete entries from a host's ARP cache by calling the ELN$INET_SET_ARP_ENTRY and ELN$INET_ DELETE_ARP_ENTRY routines. A call to ELN$INET_SET_ARP_ENTRY maps an Internet address to an Ethernet address and places the mapping in the cache. The call must specify an Internet address, Ethernet address, and an ARP option. The Internet address must be the Internet address of the host on which the Internet interface resides. The Ethernet address is the target interface address that the routine maps to the Internet address. The Ethernet address cannot be a multicast address. The option argument specifies whether an entry is permanent. A permanent entry can be deleted only with a call to the ELN$INET_ DELETE_ARP_ENTRY routine. However, ARP requests can continue to update entries marked with this option. You can set or clear the permanent option using a Boolean or bit mask value. If you choose the Boolean method, set the permanent field of the INET$SET_ROUTE_OPTIONS aggregate to TRUE. When using the bit mask method, specify the mask name INET$ARP_PERMANENT_ MASK for the aggregate's mask value field. You should delete an ARP cache entry when the entry is no longer needed. 1b delete an entry from the ARP cache, specify the host Internet address of the entry to be deleted in a call to the ELN$INET_ DELETE_ARP_ENTRY routine. If ARP does not find a cache entry for the specified Internet address, the routine returns an error. NOTE The Internet address that you specify in a call to ELN$INET_SET_ARP_ENTRY or ELN$INET_DELETE_ ARP_ENTRY cannot be the Internet address of a network interface. 10-26 .Internet Services The following function adds and deletes an ARP cache entry: tinclude $vaxelnc tinclude $internet_utility void add_and_delete_arp_entry() { long int status; INET$INTERNET ADDRESS internet_address; INET$ETHERNET=ADDRESS ethernet address; INET$SET_ARP_OPTIONS options; 1* Get an Internet address, Ethernet address, and options. *1 internet address.S un.S addr = get ia(IIInternet address: "); get epa("Ethernet ~ddre-;s: ", ðernet address); optlons.mask_value = get_ulong("Options- (l=NODELETE): "); 1* Add the input to the ARE cache. *1 eln$inet set arp entry(&status, &internet address, ðernet=address, &options); if (! (status & 1» disp_status(status); 1* When the entry is no longer needed, delete it. *1 eln$inet delete arp entry(&status, &internet_address); if (! (status & 1» disp_status(status); 10.3.1.2 Retrieving Ethernet Addresses from the ARP Cache An application can retrieve the Ethernet address that corresponds to an Internet address by calling the ELN$INET_FIND_ARP_ENTRY routine. A call to this routine must specify an Internet address and the variable that is to receive the corresponding Ethernet address. If ARP does not find a cache entry for the specified Internet address, the routine returns an error. The following function retrieves the Ethernet address that corresponds to a specified Internet address: Internet Services 10-27 #include $vaxelnc #include $internet_utility void find_arp_entry() { long int status; INET$INTERNET ADDRESS internet address; NET$ETHERNET_ADDRESS ethernet=address; /* Get an Internet address. */ internet_address.s_un.s_addr = get_ia("Internet address: "); /* Find the entry for the specified address. */ eln$inet_find_arp_entry(&status, &internet address, ðernet=address); if (! (status & 1)) disp status(status); else { printf ("\nArp entry for %s", format ia(internet address)); printf (" is %s\n\n", format_epa (ðernet_address)); 10.3.1.3 Retrieving ARP Cache Entries An application can retrieve all the cache entries currently stored in a host's ARP cache by calling the ELN$INET_SHOW_ARP_ENTRIES routine. A call to this routine must specify the name of a user-defined routine that returns ARP entry information. ELN$INET_SHOW_ARP_ ENTRIES invokes the user-defined routine once for each entry in the cache. If the ARP cache is empty, ELN$INET_SHOW_ARP_ENTRIES returns an error. The user-defined routine returns the cache data to an aggregate called INET$ARP_ENTRY. A program can then extract the following information: • • • 1~28 Internet address Ethernet address ARP status information Internet Services The ARP status information is returned to a flag field of bits that indicate whether the entry is permanent, in use, and complete. An application can set the permanent bit in calls to ELN$INET_SET_ ARP_ENTRY. ARP sets the in use bit when the host broadcasts an entry's Internet address. When a target host returns its physical address to the requesting host, ARP sets the complete bit. Once the ARP entry data is returned, a program can examine and manipulate the data using the field names interneCaddress, ethernet_ address, and arp_status. You can examine the ARP status hits individually using Boolean values, or collectively, using bit mask values. If you choose the Boolean method, examine the hits using aggregate field names. When using the bit mask method, specify one or more mask values. The status fields and mask values are defined as follows: Status Field Name Mask Name Mask Value Pennanent permanent.field ARP_PERMANENT_MASK 1 In use inuseJield ARP_INUSE_MASK 2 Complete completeJield ARP_COMPLETE_MASK 4 You can also manipulate groups of status values by specifying the sum of the appropriate mask values for the mask_value field. The following code shows an example of how an application might use ELN$INET_SHOW_ARP_ENTRIES: #include $vaxelnc #include $internet_utility void show arp entries() { -- char ch; long int status; FUNCTION DESCRIPTOR fn desc; void sho;_arp_entry();version_displayed = FALSE; /* Show the entries that are in the ARP cache. */ eln$inet show arp entries (&status, -ELN$PASS=FUNCTI ON_DE SCRIP TOR (fn_desc, show_arp_entry)); Internet Services 10-29 if (! (status & 1» disp status(status); else ch = get_char ("\nPress to continue.\n"); INET$SHOW ARP ENTRY(show arp entry) - { - -- BOOLEAN parenthesis_displayed = FALSE; if (!version displayed) - { version displayed = TRUE; printf (iiARP Information version number is: %d\n\n", version); printf ("%S", format ia (entry->internet address»; printf (" => %S", format_epa (&entry->ethernet_address»; i.f (entry->arp_status . mask_value) { if (entry->arp status.fields.permanent field) { parenthesis displayed = TRUE; printf(" (PERM"); if (entry->arp status.fields.inuse field) { - - if (parenthesis_displayed) printf(",INUSE"); else parenthesis displayed printf(" (INUSE"); TRUE; if (entry->arp_status.fields.complete_field) { if (parenthesis displayed) print £(11 , COMPL ") ; else { parenthesis displayed printf (" (COMPL"); printf (")"); printf ("\n"); 10-30 Internet Services TRUE; 10.3.2 Managing the Internet Routing Table IP maps Internet routes (addresses) to host and network addresses and stores the address pairs in a routing table. The VAXELN Internet Services provide the following Internet network control routines for managing the Internet routing table: Routine Description S~arches for a route to a specified Internet address. Deletes an entry from the routing table. ELN$INET_SET_ROUTE Adds an entry to the routing table. ELN$INET_SHOW_ROUTES Returns the entries currently stored in the routing table. For more information about routing, see Section 10.1.6. Sections 10.3.2.1 to 10.3.2.3 explain how to use the Internet control routines to do the following: • • • 10.3.2.1 Add and delete routing table entries Checking the status of routing table entries Retrieve routing table entries Adding and Deleting Routing Table Entries An application can add entries to and delete entries from an Internet routing table by calling the ELN$INET_SET_ROUTE and ELN$INET_ DELETE_ROUTE routines. A call to ELN$INET_SET_ROUTE maps a routing path to a host or network and places the mapping in the table. The call must specify an Internet address, gateway address, and route options. The Internet address must be the host or network destination address. The gateway address is the Internet address of the gateway host. The options argument is an aggregate of bit fields that specify the following: • • Whether the entry is for a network or host route Whether the route is to a host or gateway Internet Services 10-31 • Whether the route is locked (can be updated by ICMP redirect messages) You can set or clear the route entry options individually, using Boolean values, or collectively, using bit mask values. If you choose the Boolean method, you set the Boolean value for the appropriate aggregate fields to TRUE or FALSE, as appropriate. When using the bit mask method, specify the sum of the appropriate mask values in the mask field. The option fields and mask values are defined as follows: Mask Value Option Field Name Mask Name Search for network address networkJield INET$ROUTE_NETWORK_ MASK 1 Local route local..field INET$ROUTE_LOCAL_MASK 2 Lock route lock..field lNET$ROUTE_LOCK_MASK 4 If you do not specify options, the entry identifies a host route. You can specify multiple route options by specifying the sum of the mask values for the desired options in the mask_value field. For example, to specify a network route that cannot be updated by ICMP redirect messages, use a mask value of 5 (the sum of mask values INET$ROUTE_NETWORK_MASK and INET$ROUTE_LOCK_MASK). NOTE You cannot add a route to the static routing table until the Internet address and Internet network mask are known. You should mark a routing table entry for deletion when the entry is no longer needed. Once an entry is marked, the Internet software can delete the entry when it is no longer in use. The Internet software uses a reference count to determine whether an entry is being used. A reference count is maintained for each entry in the routing table. To mark an entry for deletion, specify the Internet address of the entry to be deleted in a call to the ELN$INET_DELETE_ROUTE routine. If the Internet software does not find an entry for the specified Internet address, the routine returns an error. You must also specify an option argument in calls to ELN$INET_ DELETE_ROUTE. The route option indicates whether the Internet software is to delete a network or host route. 10-32 Internet Services The following function adds a route to the routing table and then deletes the route when it is no longer needed: #include $vaxelnc #include $internet_utility void set_route () { long int INET$INTERNET ADDRESS INET$INTERNET-ADDRESS INET$SET ROUTE OPTIONS INET$DELETE_ROUTE_OPTIONS status; internet address; gateway address; set options; del=options; /* Get an Internet address, gateway address, and the options to */ /* be set. */ internet address.S un.S addr = get ia("Internet address: "); gateway address.S un.s addr = get ia("Gateway address: "); set_options.mask_value-= get_ulong("Options BITMASK (l=NETWRK, 2=LOCAL, 4=LOCK): "); /* Add the input to the routing table. */ eln$inet_set_route(&status, &internet address, &gateway address, &set_options) ; /* When the routing table entry is no longer needed, mark it for */ /* deletion. */ del_options.mask_value = get_ulong("Options BITMASK (l=NETWRK): "); eln$inet delete route(&status, &internet address, &del_options) ; Internet Services 10-33 10.3.2.2 Checking the Status of, Routing Table Entries An application can check the status of a routing table entry by calling the ELN$INET_CHECK_ROUTE routine. Using this routine an application can check whether an entry contains a network or local route, can be updated by ICMP redirect messages, or is marked for deletion but is still in use. A call to ELN$INET_CHECK_ROUTE must specify an Internet address, a credit value, a routing table entry returned by a previous call to ELN$INET_CHECK_ROUTE, and variables that are to receive the gateway address and the routing table entry status value. The Internet address identifies the entry for which the Internet software is to return the status information. If the Internet software does not find an entry for the specified Internet address, the routine returns an error. The Internet software uses reference counts for the table entries to prevent a route from being deleted while it is being used. The credit argument specifies whether or not the table entry's reference count is to be updated. You must specify one of the following credit values: Credit Value Effect o Reference count remains unchanged. 1 Increments reference count. -1 Decrements reference count. If you specify a credit value of -1, ELN$INET_CHECK_ROUTE uses the routing table entry argument. This argument specifies an entry returned by a previous call to ELN$INET_CHECK_ROUTE and receives the table entry number for the specified Internet address's route upon successful completion. The gateway address and route status arguments receive the destination Internet address and the route status, respectively. The route status indicates whether the entry is for a network route, whether the route is to a host, whether I CMP redirect messages can update the entry, and whether the entry is marked for deletion. The status information is returned as an aggregate of bits. You can examine and manipulate the status bits individually, using aggregate field names, or collectively, using one or more mask values. The status fields and mask values are defined as follows: 10-34 Internet Services Mask Value Status Field Name Mask Name Searched for network address networkJield INET$ROUTE_NETWORK_ MASK 1 U sed host route localJield INET$ROUTE_LOCAL_MASK 2 Route is locked lock..field INET$ROUTE_LOCK_MASK 4 Route is marked for deletion deleted..field INET$ROUTE_DELETED_ MASK 8 If multiple status values apply to an entry, the Internet software adds the mask values of the appropriate status values and returns the sum. The following function checks the status of a routing table entry and displays the status information: #include $vaxelnc #include $internet_utility void check_route() { long int status; INET$INTERNET ADDRESS internet address; INET$INTERNET-ADDRESS gateway_address; INET$ROUTE_STATUS route_status; short int credit; unsigned long int rte; BOOLEAN parenthesis_displayed = FALSE; credit = 0; rte = 0; /* Get an Internet address. */ internet_address.S_un.S addr = get_ia(IIInternet address: "); /* Search the routing table for an entry for the specified address. */ eln$inet check route(&status, &internet address, credit, &rte, &gateway_address, &route_status) ; Internet Services 10-35 /* If an entry is found, display the data. */ if (! (status & 1» disp_status(status); else printf (IIRoute for %S", format_ia(internet_address»; printf (" is %S", format_ia(gateway address»; if (route status.mask value) - {- if (route status.fields.network_field) parenthesis displayed printf (" (NETWRK") = TRUE; if (route status. fields. local_field) if (parenthesis displayed) printf (", LOCAL") ; else parenthesis displayed = TRUE; printf (" (LOCAL"); if (route status.fields.lock_field) T if ( parenthesis displayed print f (", LOCKED II ) ; else parenthesis displayed printf(" (LOCKED"); TRUE; if (route_status.fields.deleted_field) if (parenthesis displayed) printf(",DELETED"); else parenthesis displayed printf(" (DELETED"); printf (")"); printf (II\n"); 10-36 Internet Services TRUE; 10.3.2.3 Retrieving Routing Table Entries An application can retrieve all the entries in the Internet routing table by calling the ELN$INET_SHOW_ROUTES routine. A call to this routine must specify the name of a user-defined routine that returns routing table entry information. ELN$INET_SHOW_ROUTES invokes the user-defined routine once for each entry in the table. If the table is empty, ELN$INET_SHOW_ROUTES returns an error. The user-defined routine returns the routing data to an aggregate called INET$ROUTE_ENTRY. A program can then extract the following information: • • • • • Destination Internet address Gateway address Route status Reference count Usage count The route status information is returned to a flag field of bits that indicate whether IP is to search for a match using only the network portion of the destination Internet address, the route is to a host, the route is locked, and the route is marked for deletion. An application can set the deleted bit in calls to ELN$INET_SET_ROUTE. IP sets the deleted bit when an application calls ELN$INET_DELETE_ROUTE. Once the route entry data is returned, a program can examine and manipulate the data using the field names destination_address, gateway_ address, route_status, reference_count, and use_count. You can examine the route status bits individually, using Boolean values, or collectively, using bit mask values. If you choose the Boolean method, examine the bits using aggregate field names. When using the bit mask method, specify one or more mask values. The status fields and mask values are defined as follows: Mask Value Status Field Name Mask Name Searched for network address networkJield INET$ROUTE_NETWORK_ :MASK 1 U sed host route localJield INET$ROUTE_LOCAL_:MASK 2 Internet Services 10-37 Status Field Name Mask Name Mask Value Route is locked lockJield lNET$ROUTE_LOCK_MASK 4 Route is marked for deletion deletedJield lNET$ROUTE_DELETED_ MASK 8 You can also manipulate groups of status values by specifying the sum of the appropriate mask values for the mask_value field. The following function shows the contents of the routing table: #include $vaxelnc #include $internet_utility void show_routes() { char Chi long int status; FUNCTION DESCRIPTOR fn desc; void show route entry(); version_dIsplayed = FALSE; /* Show the routing table entries. */ eln$inet show routes (&status, ELN$PASS FUNCTION DESCRIPTOR(fn dese, show_route_entry»; if (! (status & 1» disp status (status); else ch = get_char("\nPress to eontinue.\n"); INET$SHOW ROUTE ENTRY(show route entry) - { - -- BOOLEAN parenthesis_displayed = FALSE; if (!version displayed) - { version_displayed = TRUE; printf("Route information version number is: %d\n\n", version); printf ("%S", format ia(entry->destination address»; printf (tl => %S", format ia (entry->gateway address»; printf (" REFCNT: %d USECNT: %d", entry->referenee_count, entry->use_count); 10-38 Internet Services if (entry->route_status.rnask_value) { if (entry->route status.fields.network field) - { - parenthesis displayed = TRUE; printf (" (NETWRK"); if (entry->route status.fields.local field) - { - if (parenthesis_displayed) printf (", LOCAL") ; else { parenthesis_displayed printf(" (LOCAL"); TRUE; if (entry->route status.fields.lock field) - { - if (parenthesis displayed) printf (" ,LOCKED"); else { parenthesis_displayed printf(" (LOCKED"); TRUE; if (entry->route status.fields.deleted field) - { - if (parenthesis_displayed) printf (", DELETED"); else { parenthesis displayed printf (" (DELETED"); TRUE; printf (")"); printf ("\n"); Internet Services 10-39 10.3.3 Managing Internet Network Interfaces The VAXELN Internet Services provide the following Internet network control routines for managing Internet network interfaces: Routine Description Associates an Internet address with the name of an Internet network interface that resides on the VAXELN target system. Returns the Internet network characteristics for Internet interfaces. For more information about setting up Internet network interfaces for VAXELN systems, see the. VAXELN Development Utilities Guide. Sections 10.3.3.1 and 10.3.3.2 explain how to use the Internet control routines to do the following: • • 10.3.3.1 Set an Internet network interface dynamically at runtime Retrieve Internet network interface characteristics Setting Internet Network Interfaces If you did not specify an Internet address for an Internet network interface when you built your system, you can do so at runtime by calling the ELN$INET_SET_INTERFACE routine. You can also use this routine to set an interface's broadcast and network masks once. A call to ELN$INET_SET_INTERFACE must specify the name of the communication interface that is to be associated with an Internet address. You must also specify a new fields argument and values for the Internet address, broadcast mask, and network mask arguments. The new fields argument is an aggregate that identifies characteristics that you intend to set. You set characteristics by setting the appropriate bits in the aggregate. You can specify the aggregate fields to be set individually, using Boolean values, or collectively, using a bit mask value. If you choose the Boolean method, you set the Boolean value for aggregate fields to TRUE, as appropriate. If you choose the bit mask method, you specify the sum of the appropriate mask values in the mask value field. The interface characteristics fields and mask values are defined as follows: 10-40 Internet Services Characteristic Field Name Mask Name Mask Value Internet address interneCaddress_ field INET$INTERNET_ADDR_ MASK 1 Broadcast address broadcast_address_ field INET$BROADCAST_MASK 2 Network mask network_maskJield INET$NETWORK_MASK 4 You can set fields without changing other fields in the aggregate. However, for each field that you set, you must specify a value for a corresponding argument. For example, to set the Internet address, you must set the bit for the Internet address field in the fields argument and specify the Internet address for the Internet address argument. For the fields that you choose not to set, you can specify a null string for the corresponding argument. The following section of code shows how an application might use ELN$INET_SET_INTERFACE: iinclude $vaxelnc iinclude $internet_utility show~interface() void { char Chi int status; VARYING STRING(32) interface_name; INET$SET INTERFACE FIELDS new fields; INET$INTERNET ADDRESS internet address; INET$INTERNET-ADDRESS network mask; INET$INTERNET-ADDRESS broadcast mask; INET$SET_INTERFACE_OPTIONS options; /* Get interface input. */ new fields.mask value = 0; get:=varying_str'ing("Interface to set: ", 32, &interface_name); ch = get_char("Set Interface address? Y or N: if (toupper(ch) == 'Y') [N] "); { new fields.mask value += INET$INTERNET ADDR MASK; internet_address.s_un.S_addr = get_ia ("Internet address: "); Internet Services 10-41 ch = get char ("Set Address (subnet) mask address? Y or N: if (toupper(ch) == 'Y') [NJ "); { new fields.mask value += INET$NETWORK MASK; network_mask.s_un.s_addr = get_ia ("Address mask: "); ch = get char ("Set Broadcast mask address? Y or N: if (toupper(ch) == 'Y') [NJ "); { new fields.mask value += INET$BROADCAST MASK; broadcast_mask. S_un. S_ addr = get _ ia ("Broadcast mask: "); options.mask_value = get_ulong("Interface options (reserved) : "); /* Set the interface. */ eln$inet set interface(&status, &interface name, &new fields, &internet address, &network mask, &broadcast_mask, &options); if (! (status &1» disp_status (status); You must also specify an interface options argument. This argument is reserved for future use. 10.3.3.2 Retrieving Internet Network Interface Characteristics An application can retrieve the characteristics for all Internet network interfaces on a VAXELN system by calling the ELN$INET_SHOW_ INTERFACES routine. A call to this routine must specify the name of a communication interface and the name of a user-defined routine. The interface name identifies the interface for which information is to be returned. To return information about all network interfaces, specify an asterisk (*). If you specify a name that has not been defined, the routine returns an error. The user-defined routine returns the network interface information. ELN$INET_SHOW_INTERFACES invokes the user-defined routine for the specified interface. If you specify an asterisk, ELN$INET_SHOW_ INTERFACES invokes the routine once for each interface defined for the system. If no interfaces are defined, ELN$INET_SHOW_ROUTES returns an error. 10-42 Internet Services Once the program retrieves the interface data, it can extract the following information: • • • • • • • • • • • • • • • • Interface name Interface state Internet address Ethernet address Network mask Broadcast mask Number of IP datagrams received Number of IP data grams transmitted Number of trailer datagrams received Number of trailer datagrams transmitted Number of ARP datagrams received Number of ARP datagrams transmitted Number of ICMP datagrams received Number oflCMP datagrams transmitted Number of receive errors Number of transmit errors The following code shows the characteristics for a specified interface: finclude $vaxelnc finclude $internet_utility void show_interface() { char ch; int status; FUNCTION DESCRIPTOR fn desc; void show_interface_entry(); VARYING_STRING (32) interface_name; /* Get the name of an interface. */ get_varying_string(ltInterface name: [* for all] 32, &interface_name); It, eln$inet_show_interface(&status, &interface name, ELN$PAS S_FUNCTI ON_DE SCRIP TOR (fn_desc, show_interface_entry»; Internet Services 10-43 if (! (status & 1» disp_status (status); lNET$SHOW INTERFACE ENTRY(show interface entry) - { - - - char Chi printf("\nlnterface: %.*s\n", entry->interface name. string length, &entry->interface name. string text); printf("Interface state:- %d\n", entry->interface state.mask value); printf("Internet Address-;- %s\n", format ia(entry->internet address»; printf ("Ether~et Address: %s\n",format epa (&entry->ethernet address»; printf("Address Mask: %s\n",format ia(entry->network mask»; printf("Broadcast Mask: %s\n"; format ia(entry->broadcast mask»; printf("\n\n Counters: (version %d):\n\n", version); printf(" RECEIVED TRANSMITTED\n"); printf ("IP Packets %10u %lOu\n", entry->ip rcvd,entry->ip xmit); printf("IP Trailer 1 %10u --\n", entry->trailer1 rcvd); printf("IP Trailer 2 %lOu --\n", entry->trailer2-rcvd); printf ("ARP Packets %lOu %lOu\n", entry->arp rcvd, entry->arp xmit); printf("ICMP Packets %10u %lOu\n", entry->icmp rcvd, entry->icmp xmit); printf ("Errors %10u %lOu\n", entry->errors rcvd, entry->xmit_errors); ch = get_char ("\nPress to continue. \n"); 10.3.4 Retrieving Internet Performance and Error Data The VAXELN Internet Services provide the following Internet network control routines for retrieving data concerning performance and errors: Routine Description Returns perfonnance and error statistics for IP. Returns perfonnance and error statistics for Tel'. Returns perfonnance and error statistics for UDP. 10-44 Internet Services The ELN$INET_SHOW_IP_STATISTICS, ELN$INET_SHOW_UDP_ STATISTICS, and ELN$INET_SHOW_TCP_STATISTICS routines return performance and error statistics for IP, UDp, andTCP, respectively. /These routines allocate a statistics aggregate for the appropriate protocol. The application program can then extract the following information from the aggregate: IP UDP TCP Transmission time in seconds Transmission time in seconds Transmission time in seconds Number of packets received Datagrams transmitted Connection requests forwarded IP datagram received Datagrams received Connections accepted Received IP datagram has bad size Invalid transmit Connection requests issued Received IP datagram has bad checksum Invalid receive Open connections Received IP datagram has bad destination address Datagrams received but not delivered Connections reset Received IP datagram includes disabled IP protocol Segments transmitted Received IP datagram fragmented Segments retransmitted Received IP datagram fragments dropped Segments received Received fragmented IP datagram reassembled Invalid segments received ICMP datagram received Out-of-sequence segments received Received ICMP datagram has bad size Concatenated record descriptor buffers Received ICMP datagram has bad checksum ARP datagram received Received ARP datagram replies Received ARP datagram requests Internet Services 10-45 IP UDP TCP Trailers received Trailers received invalid Packets transmitted Packet trasmissions that failed Transmitted IP datagram invalid Transmitted IP datagram has bad destination address IP datagram transmitted Transmitted IP datagram fragmented Transmitted IP datagram fragments ICMP datagram transmitted ARP datagram transmitted Transmitted ARP datagram replies Transmitted ARP datagram requests A call to ELN$INET_SHOW_IP_STATISTICS, ELN$INET_SHOW_ UDP_STATISTICS, or ELN$INET_SHOW_TCP_STATISTICS must specify a Boolean flag that indicates whether counters are to be cleared after they are read and variables that receive a version number and a pointer to the appropriate protocol statistics aggregate. The version number identifies the version of the statistics aggregate that the routine returns to the statistics argument. When you finish accessing a statistics record, you must use the free function to deallocate it. The following code shows how an application might retrieve TCP statistics: 10-46 Internet Services tinclude $vaxelnc tinclude $internet_utility void show_tcp_statistics() { int status; int version; char chi BOOLEAN clear counters = FALSE; INET$TCP_STATISTICS *statistics; /* Check whether counters should be cleared. */ ch = get char ("Clear Counters? Y or N: if (toupper(ch) == 'Y') clear_counters = TRUE; [N] "); /* Show all TCP statistics. */ eln$inet show tcp statistics(&status, clear_counters, &version, &statistics) ; if (status & 1) { printf ("TCP Statistics Version %10u\n", version) ; printf ("Seconds %10u\n", statistics->seconds); printf ("Connections forwarded: %10u\n", statistics->connects forwarded); printf ("Connections accepted: %10u\n", statistics->connects accepted); printf ("Connections issued:%10u\n", statistics->connects issued); printf ("Connections opened:%10u\n", statistics->connects opened); printf ("Connections reset: %10u\n", statistics->connects reset); printf ("Segments transmitted: %10u\n", statistics->segments xmit); printf ("Segments retransmitted: %10u\n", statistics->segments rexmit); printf ("Segments received: %10u\n", statistics->segments rcvd); printf ("Invalid segments received: %10u\n", statistics->invalid rcvd); printf ("Out of sequence received: %10u\n", statistics->out of sequence rcvd); printf ("Concatenated m;ss-;ges: -%10u\n", statistics->concatenated_rdbs); Internet Services 10-47 free(statistics); ch = get_char ("\nPress to continue\n"); else disp_status(status); 10.3.5 Retrieving TCP Connection Data An application can retrieve data concerning active TCP connections by calling the ELN$INET_SHOW_CONNECTIONS routine. This routine does not report information about listening servers (applications waiting on a connection). A call to ELN$INET_SHOW_TCP_CONNECTIONS must specify the name of a user-defined routine to be invoked by ELN$INET_SHOW_ TCP_CONNECTIONS once for each active TCP connection. The userdefined routine returns the connection information. If no connections exist, ELN$INET_SHOW_TCP_CONNECTIONS returns an error. Once the program retrieves the connection data, it can extract the following information: • • • • • • • • • • • • • • • • Local Internet address Local port number Remote Internet address Remote port number Connection state Connection options Number of messages in the receive queue Number of messages in the send queue Number of urgent messages received Number of urgent messages sent Number of messages in the receive window Number of messages in the send window Send sequence number Acknowledgment sequence number Retransmit timer value Persist timer value 10-48 Internet Services • • • Keep-alive timer value Maximum linger timer value Number of retransmissions The connection state and connection options information is returned to flag bit fields. For the connection state, the bits indicate whether: • • • • • • • • • • • The connection is open The connection is listening The connection is waiting for a matching connection request The connection is waiting for a connection request ACK message after having received and transmitted a connection request The connection is established The connection is waiting for a connection termination request from a remote peer or an ACK message for the connection termination request previously sent The connection is waiting for a connection termination request from a remote peer The wait is closed The connection is being closed The last ACK has been sent The wait time expired For the connection options, the bits indicate whether the connection is to have a linger time and keep-alive time. A program can examine and manipulate the connection data using field names. You can examine or manipulate the state and option bits individually using Boolean values, or collectively, using bit mask values. If you choose the Boolean method, examine the bits using aggregate field names. When using the bit mask method, specify one or more mask values. The state fields and mask values are defined as follows: Internet Services 10-49 Mask Value State Field Name Mask Name Connection is closed closed..field INET$TCP_STATE_CLOSED_ MASK 1 Connection is listening for requests listen..field INET$TCP_STATE_LISTEN_ MASK 2 Waiting for matching connection request syn_sen..field INET$TCP_STATE_SYN_SENT_ MASK 4 Waiting for ACK message after receive and transmit syn_rcvd..field INET$TCP_STATE_SYN_ RCVD_MASK 8 Connection is established established..field INET$TCP_STATE_ ESTABLISHED_MASK 16 Waiting for connection termination request from remote peer fin_waiCl..field INET$TCP_STATE_FIN_WAIT_ I_MASK 32 Waiting for connection termination request from remote peer fin_waiC2.Jield INET$TCP_STATE_FIN_WAIT_ 2_MASK 64 Wait is closed close_wait.Jield INET$TCP_STATE_CLOSE_ WAIT_MASK 128 Connection is being closed closing.Jield INET$TCP_STATE_CLOSING_ MASK 256 Last ACK has been received lasCack..field INET$TCP_STATE_LAST_ACK_ MASK 512 Time to wait for connection expired lasCackJield INET$TCP_STATE_TIME_ WAIT_MASK 1024 The option fields and mask values are defined as follows: Mask Value Option Field Name Mask Name No linger time nolingerJield INET$TCP_ OPT_NOLINGER_ MASK 1 Linger time linger..field INET$TCP_OPT_LINGER_ MASK 2 10-50 Internet Services Mask Value Option Field Name Mask Name No keep alive time nokeepalive..field lNET$TCP_OPT_ NOKEEPALIVE_MASK 4 Keep alive time keep alive..field lNET$TCP_STATE_ KEEPALIVE_MASK S You can also examine groups of status values by specifying the sum of the appropriate mask values for the mask_value field. The following function shows how an application might use ELN$INET_SHOW_TCP_CONNECTIONS to retrieve information about active TCP connections: #include $vaxelnc #include $internet_utility void show_tcp_connections() { char ch; int status; FUNCTION DESCRIPTOR fn desc; void show_tcp_connection_entry(); 1* Clear error in version displayed flag. con_ver_err_dspld = *1 FALSE; eln$inet show tcp connections(&status, ELN$PASS FUNCTION DESCRIPTOR(fn desc, show_tcp_connection_entry»; if (! (status & 1» disp status(status); else ch = get_char (lI\nPress to continue.\n"); Internet Services 10-51 INET$SHOW TCP CONNECTION ENTRY(show tcp connection entry) - { - - - - - if (version != INET$TCP CONNECTION VERSION -- { if (! (con ver err dspld» - { - - printf("TCP connection entry version number is unrecognized. \n"); con_ver_err_dspld = TRUE; return; else { printf ("TCP Connection version: %10u\n", version); printf("Local IA: %s Local PN: %u\n", format ia (entry->local internet address), entry->local-F0rt_number); printf("Remote IA: %s Remote PN: %u CCB ID: %X (hex)\n", format ia (entry->remote internet address), entry->remote-Fort_number, entry->ccb id); printf(ftTCP state:-%s, Options: %s\n", format_tcp_state (entry->state), format options (entry->options»; printf(ftReceive: Q: %8u, Urg: %8u, Window: %6u\n", entry->recv queue, entry->recv-urgent, entry->recv-window); printf(nSend: Q~ %8u, Urg: %8u, Window: %6u\n", entry->send queue, entry->send=urgent, entry->send window); printf(nTimers: RexIDit: %u, Prst: %u, Keep: %u, MSL: %u\n", entry->rexmit_tmr, entry->persist tmr, entry->keep tmr, entry->msl tmr); printf (nRexmit value: %u, Snd seq: %12u, Ack seq: %12u\n", entry->rexmit value, entry->snd seq, entry->ack=seq); 10-52 Internet Services 10.4 Converting the Byte Order of Network and Host Binary Data Not all hosts store bits the same way. To enable different types of hosts to communicate, regardless of how bits are represented, the Internet Services define a standard byte order for Internet packet binary fields. The standard network byte order places the byte with the most significant bits at the lower addresses. All hosts must use this format when sending data. The VAXELN Internet Services provide the following routines for converting the byte order of network and host binary data: Routine Description htonl Converts a 32-bit unsigned integer from host byte order to network byte order. htons Converts a short integer from host byte order to network byte order. ntohl Converts a 32-bit unsigned integer from network byte order to host byte order. ntons Converts s short integer from network byte order to host byte order. Before sending a message, a host must convert the byte order of binary data from its local representation to the standard network representation. An application can convert data to network byte order by calling htonl or htons. You specify htonl and htons with a longword or short integer, as appropriate, in host byte order. The functions return a longword or short integer in network byte order. You cannot use integers in network byte order for arithmetic computations on VAX systems. When a host receives a message, it must convert the byte order of the message data to its byte-order representation. To convert data to the host's representation, call ntohl and ntons. Specify these functions with a longword or short integer, as appropriate, in network byte order. The functions return a longword or short integer in host byte order. For descriptions of the conversion routines, see the VAXELN C Reference Manual. Internet Services 10-53 10.5 Manipulating Internet Addresses The VAXELN Internet Services provide a set of routines for manipulating Internet addresses. An application might use these routines while managing an ARP cache or for programming socket communication. The routines are as follows: Routine Description Converts an Internet address in the standard text Internet "." notation to a numeric (binary) Internet address in network byte order. Returns the local network (subnet) portion of an Internet address. Returns an Internet address given a network address and local (subnet and host) address on that network. inet_netof Returns the network portion of an Internet address. inet_network Converts an Internet address in the standard text Internet "." notation to a numeric (binary) Internet address in host byte order. Converts an Internet address to a text string representing the addess in the standard Internet "." notation. The inet_makeaddr and inet_addr functions provide a means for deriving an Internet address in network byte format given appropriate Internet address information. In the case of inet_makeaddr, you specify the network and local portions of an Internet address in host byte order. You specify inet_addr with a pointer to an ASCIZ NULLterminated text string that identifies an Internet address in standard Internet ce." notation. If the argument does not point to a valid Internet address, the function returns -1. If you have an Internet address in network byte order, you can use the inet_netof, inet_Inaof, or inet_ntoa function to get the network portion, local portion, or string representation of an Internet address. The inet_netof and inet_lnaof functions return the network and local portions of the specified Internet address in byte host order. To get a pointer to a text string that identifies an Internet address in standard Internet "." notation, specify the network byte order Internet address in a call to inet_ntoa. 10-54 Internet Services To convert the string representation of an Internet address to a numeric (binary) Internet address in host byte order, use the inet_network function. Specify a pointer to an ASCIZ NUL-terminated text string that identifies an Internet address in standard Internet "." notation. If the argument does not point to a valid Internet address, the function returns -1. For descriptions of the Internet address manipulation routines, see the VAXELN C Reference Manual. 10.6 Programming Internet Communication You program Internet communication using socket interface routines. You can use the routines to program connectionless communication, sending datagrams to specified destinations, or you can use them to program connection-oriented communication. The VAXELN Toolkit provides the following socket interface routines: Routine Description accept Accepts a connection on a socket. bind Binds a name to a socket. close Closes a socket. connect Initiates a connection on a socket. listen Sets the maximum limit of outstanding connection requests for a connection-oriented socket. read Reads bytes from a file or connected socket and places them in a buffer. recv Receives bytes from a connected socket and places them in a buffer. recvfrom Receives bytes for a socket from any source. recvmsg Receives bytes from a socket and places them in scattered buffers. select Polls and checks a group of sockets for 110 activity. send Sends bytes through a socket to its connected peer. sendmsg Sends gathered bytes through a socket to any other socket. sendto Sends bytes. through a socket to any other socket. Internet Services 10-55 Routine Description shutdown Shuts down a socket. socket Creates a socket and returns the socket's descriptor. vaxc$get_ sdc Returns a socket device descriptor. vaxc$socket_ Sets socket characteristics. control write Writes bytes from a buffer to a file or connected socket. Table 10-6 lists the calling sequence for programming connectionoriented and connectionless socket communication. Table 10-6: Calling Sequence for Socket Communication Task Connectionless (IP and UPDIIP) ConnectionOriented (TCPIIP) Create a socket. socket socket Bind a name to. the socket. bind bind Define the socket as a listener. listen Client: Send a connection request. connect Server: Accept a connection request. accept Send data. sendto sendmsg write send sendto sendmsg Receive data. recvfrom recvmsg read recv recvfrom recvmsg Shut down the socket. shutdown shutdown Close (delete) the socket. close close Sections 10.6.1 to 10.6.7 explain how to use the socket communication routines. Sections 10.6.1 and 10.6.2 explain how to create and bind names to sockets. Section 10.6.4 explains how to establish connections for TCPIIP communication. Section 10.6.5 explains how applications 10-56 Internet Services can use sockets to transfer data. Sections 10.6.6 and 10.6.7 explain how to shut down and close sockets, respectively. . For descriptions of the socket communication routines, see the VAXELN C Reference Manual. 10.6.1 Creating Sockets An application creates sockets by calling the socket function. A call to socket must specify an address format, type, and protocol. The address format argument defines the address format to be used in subsequent operations that use the socket. The VAXELN socket routines support Internet (AF_INET) addresses. A socket's type and protocol affect the way the socket operates and how an application uses it. The type argument specifies whether the socket operates as a stream, datagram, or raw data transmission mechanism. Sockets of type SOCK_STREAM are for reliable, sequenced, two-way connection-based communication that can handle out-of-band data. Sockets of type SOCK_DGRAM are for connectionless communication. Sockets of type SOCK_RAW provide access to internal network interfaces, and are available only to programs authorized with a system group UIC (that is, a mc less than or equal to %X0008FFFF or [10,177777]). The protocol argument specifies the protocol to be used with the socket. Normally, only one protocol supports a particular socket type using a given address format. Generally, the stream, datagram, and raw socket types map to the protocols TCP, UDP, and IP, respectively. However, multiple protocols can exist for a socket type. If so, you must specify a protocol. The protocol number you need to specify depends on the communication domain in which the socket is to be used. The following call to socket creates a stream socket and returns a socket descriptor to socket_2: Internet Services 10-57 tinclude types . tinclude socket tinclude in main (argc, argv) int argc; char **argv; { socket 2 = socket(AF_INET, SOCK_STREAM, 0) You can gain more control over how a socket operates by using the setsockopt function to set the following socket options: • • • • • Let local addresses be reused Keep connections alive Do not apply routing on outgoing messages Linger on close operations if data is present Let broadcast messages be sent For more information about setting socket options, see Section 10.7.2. 10.6.2 Binding Names to Sockets When an application creates a socket, the socket exists in an address family's name space but has no name (direct address) assigned. To use the socket, the application must bind a name to it, using a call to the bind function. A call to bind must specify a socket descriptor returned by socket, a name, and the length of the name. The name argument specifies the address of a structure that defines a name for the socket. The structure must define the name using the socket's address format. The VAXELN socket interface defines two such structures: sockaddr and sockaddr_in. The sockaddr structure defines names for sockets that use a general address format. Members of this structure identify the socket's address family and a data string of up to 14 bytes of direct address. The sockaddr_in structure defines 10-58 Internet Services names for sockets that use the Internet address format. This structure defines a name that includes the socket's address family (AF_INET), a port number in network byte order, an Internet address in network byte order, and an 8-byte field that contains all zeros. The name length argument must specify the size of the name structure in bytes. The following code binds an Internet address name socket_2_name to the socket socket-.2: :hnclude types :fI:include socket :fI:include in main (argc, argv) int argc; char **argv; { int socket_2; static struct sockaddr in socket_2_name; /* * Fill in the name structure. */ socket_2_name.sin_family = AF_INET; socket_2_name.sinyort = htons(atoi(argv[l]»; socket_2_name.sin_addr.s_un.S_addr inet_addr("5.0.0.1"); /* * Bind the name to the socket. */ Once a socket has a name, an application can use the socket for either connection-oriented or connectionless communication. Internet Services 10-59 10.6.3 Controlling Socket Characteristics The VAXELN Internet software provides the routines vaxc$get_sdc and vaxc$socket_control for controlling certain socket characteristics. The vaxc$get_sdc routine returns the socket device descriptor associated with a specified socket descriptor. Once an application has the socket device descriptor, it can specify that descriptor in calls to vaxc$socket_control to do the following: • • Set the socket to a blocking or nonblocking state Determine whether the socket's read pointer is pointing at the out-of-band data marker A blocking socket waits for the current operation to complete, while a nonblocking socket does not block if the requested operation takes a considerable amount of time. Calls to the vaxc$socket_control must specify a socket device descriptor returned by vaxc$get_sdc, a request, and an argument pointer. The request argument specifies the characteristic to be set or returned. The argument pointer specifies the address of a buffer that supplies information to or receives characteristics from the routine. To set a socket to the blocking or nonblocking state, you must specify FIONBIO as the request. If you specify FIONBIO and the specified buffer contains 0, the socket is set to the blocking state. Otherwise, it is set to the nonblocking state. To determine whether a socket's read pointer is pointing at the out-ofband data marker in the data stream, specify SIOCATMARK as the request. When you specify this request, the routine returns the value 1 to the specified buffer if the next read is to return data after the mark. The following example shows how you might use vaxc$get_sdc and vaxc$socket_control to create an 1/0 control function that is similar to the UNIX ioctl function. /* ** */ Include files iinclude inetdef 10-60 Internet Services /** * * * * * * * I/O control functions have the command encoded in the lower word and the size of the input and output parameters in the upper word. The high two bits of the upper word are used to encode the parameter's I/O status. For now, we restrict parameters to at most 128 bytes. The IOC VOID field of Ox20000000 is defined so that new I/O control functions can be distinguished from old I/O control functions. */ tl=ifndef tl=define tl=define tl=define tl=define tl=define tl=define tl=define tl=define tl=define tl=endif IO IOCPARM MASK IOC VOID IOC OUT IOC IN IOC INOUT IO(x,y) :=IOR(x,y,t) IOW(x,y,t) :=IOWR(x,y,t) IO tl=define ODD (s) Ox7f /* Parameters are < 128 bytes */ (int)Ox20000000 /* No parameters */ (int)Ox40000000 /* Copy output parameters */ (int)OxSOOOOOOO /* Copy input parameters */ (int) (IOC INIIOC OUT) (int) (IOC-VOIDI ('x'«8) Iy) (int) (IOC-OUTI «sizeof(t) &IOCPARM MASK) «16) I ('x'«8) Iy) (int) (IOC-INI «sizeof(t)&IOCPARM MASK) «16) I ('x'«8) Iy) (int) (IOC:=INOUTI «sizeof(t) &IOCPARM_MASK) «16) I ('x'«S) Iy) (s & 01) /*---------------------------------------------------------------------*/ int ioctl(d, request, argp) int d, request; char *argp; /* Arguments: ** d - Specifies the socket descriptor ** request - Specifies the characteristics; either FIONBIO or ** SIOCATMARK argp - Points to the buffer that specifies input to or ** receives output from the routine ** */ { int int sdd; retval; /* Socket device descriptor */ /* Return value */ /* ** Get the socket device descriptor. ** If failure, then errno will contain error number. */ sdd vaxc$get_sdc(d); /* ** Do socket control. ** If failure, then errno will contain error number. */ Internet Services 10-61 if (sdd) { ret val = vaxc$socket_control(sdd, request, argp) ; return(retval); else return (-1); /* Return failure */ For descriptions of the vaxc$get_sdc and vaxc$socket_control, see the VAXELN C Reference Manual. 10.6.4 Establishing Connections for Socket Communication To use sockets for TCP communication, an application must establish a connection between client and server sockets. A client initiates a connection by sending a connection request to a server's socket. A server waits for connection requests, and depending on the state and characteristics of its socket, receives the requests, places the requests in a queue, or rejects the requests. The following sections explain how to establish socket connections. Sections 10.6.4.1 and 10.6.4.3 explain how to send and accept socket connection requests. Section 10.6.4.2 explains how to associate a socket with a queue for pending connection requests. 10.6.4.1 Initiating Socket Connections A client initiates a~ connection on a socket by calling the connect function. The function call must specify a socket descriptor returned by socket, the name of a remote socket, and the length of the name. The socket descriptor can be of type SOCK_DGRAM or SOCK_ STREAM. If the socket is of type SOCK_DGRAM, the call permanently specifies the peer to which data is to be sent. If the socket is of type SOCK_STREAM, the function sends a connection request to another socket. The name argument specifies the address of a structure that names the remote socket to which the specified socket is to connect. The structure must define the name using the remote socket's address format. Section 10.6.2 provides information about the VAXELN socket address structures and binding names to sockets. 10-62 Internet Services NOTE If an application does not bind an Internet address (name) to a socket before calling the connect function, the function uses the local Internet address. If the Internet address is not defined when the application calls connect, the function blocks until the Internet address is set. The name length argument must specify the size of the name structure in bytes. The following code fragment connects the socket socket_l to the remote socket named socket~_name: #include types #include socket #include in main (argc, argv) int argc; char **argv; { int socket_l; static struct sockaddr in socket_2_name; /* * Fill in the name structure for the remote socket. */ socket 2 name. sin family = AF INET; socket=2=name.sin:port = hton;(atoi(argv[2]»; socket_2_name.sin_addr.S_un.S_addr = inet_addr("5.0.0.5"); /* * */ connect socket 1 to socket 2 name. - -- Internet Services 10-63 10,6.4.2 Creating a Queue for Pending Connection Requests Before a server can accept a connection on a socket, it must create and associate the socket with a queue that stores pending connection requests. The socket uses the queue to listen for requests. If the server is busy when a request arrives, the request is queued. If the queue is empty when the server is ready to service a request, the server waits on the queue for a new request. To create a queue for a socket, call the listen function. The function call must specify a socket descriptor of type SOCK_STREAM returned by socket and an integer in the range 1 to 5 that specifies the maximum number of pending connections that may be queued for the socket at any given time. If a connection request arrives when the queue is full, the client receives an error. The call to listen in the following example creates a connection request queue for socket_2. The queue entry limit is set to 5. #include types #include socket #include in main (argc, argv) int argc; char **argv; { int socket _2; /* * Listen on socket 2 for connection requests. */ return val 10-64 Internet Services = listen(socket_2, 5); 10.6.4.3 Accepting Socket Connections A server accepts a connection on a socket by calling the accept function. A call to accept must specify a socket descriptor of type SOCK_ STREAM returned by socket, a variable that receives the address of the connecting entity, and an argument that specifies and receives the length of the connecting entity's address in bytes. The socket descriptor that you specify must be bound to a name and listening for connection requests. The address of the connecting entity is filled in as it is known to the communication layer. The format of the structure to which the address points is determined by the communication domain. The VAXELN Internet Services support the Internet (AF_INET) domain. The address length argument should specify the size of the structure to which the address argument points. When the function returns, the argument contains the actual length of the structure that the communication layer places in the address argument. The accept function completes the first connection on the socket's connection pending queue, creates a new socket with the same properties as the specified socket, and allocates and returns a new descriptor for the socket. If no connections are pending and the socket is not marked as nonblocking, the function blocks the calling process until a connection request is present. If the socket is marked as nonblocking and no connections are pending, the function returns an error. The original socket continues to listen for other connection requests. The following code accepts a connection from socket_2 and places the accepted connection on socket_3: Internet Services 10-65 iinclude types tinclude socket tinclude in main (argc, argv) int argc; char **argv; { int socket 2, socket 3; static struct sockaddr in socket 2 name; int socket_2:namelen; - - /* * * Accept connection request from socket 2. Accepted connection will be on socket:3. */ socket 2 namelen = sizeof (socket 2 name); socket:3-= accept(socket_2, &socket_2_name, &socket_2_namelen); 10.6.5 Transferring Data A variety of socket communication routines are available for transferring data between sockets. Sections 10.6.5.1 and 10.6.5.2 explain how to use the routines to send and receive data, respectively. Section 10.6.5.3 explains how to poll sockets for I/O activity while programming data transfers between sockets. 10.6.5.1 Sending Data to Sockets Internet applications can send data from sockets by calling the write, send, sendto, or sendmsg function. You can use any of these functions to send data in connection-oriented communication. You must use sendto or sendmsg to send data in a connectionless environment. The write function writes a buffer of data to a connected socket or file. You specify write with a destination socket or file descriptor, the address of contiguous storage from which the output data is to be taken, and the maximum number of bytes to be written. 10-66 Internet Services The send function provides an alternative method of sending data between connected sockets. A call to send must specify a socket descriptor, the address of the buffer containing the data to be sent, the length (in bytes) of the data being sent, and an out-of-band character flag. In the case of send, the socket descriptor specifies a source socket - the socket from which data is sent - that is connected to another socket. The function sends bytes of data through the specified socket to its connected peer and returns an integer indicating the number of bytes of data that were sent. The out-of-band character flag that you specify with send can be 0 or MSG_OOB. If you specify MSG_OOB, data can be received before other pending data on the receiving socket if the receiver also specifies MSG_OOB. The following code uses a call to send to send a message to socket_2: #include types #include socket #include in main (argc, argv) int argc; char **argv; int socket 1; static struct sockaddr_in socket 2 name; int socket_2_namelen; /* * Fill in the name structure for the remote socket. */ socket 2 name. sin family = AF lNET; socket=2=name.sin~ort = htons(atoi(argv[2]»; socket_2_name.sin_addr.s_un.s_addr = inet_addr("5.0.0.5"); /* * */ socket 2 namelen = sizeof(socket 2 name); return=val = connect(socket_l, &socket_2_name, &socket_2_namelen); /* * Send message to socket 2. */ Internet Services 10-67 flag = 0; return val send (socket_l, message, sizeof(message), flag); If your application uses connectionless socket communication, you can send data by calling the sendto or sendmsg function. These functions send data to any other socket. The sendto function sends bytes of data through a socket to any other socket. The sendmsg function sends gathered bytes of data through a socket to any other socket. Like calls to send, calls to sendto must specify a socket descriptor, the address of the buffer containing the data to be sent, the length (in bytes) of the data being sent, and an out-of-band character flag. In addition, you must supply the destination socket by specifying the address of the destination socket's address structure and the length of that structure. The call to sendto in the following code fragment sends data between unconnected sockets: :fI:include types :fI:include socket :fI:include in main (argc, argv) int argc; char **argv; int static char int int static struct sendlength, tolength; sendbuf [] = "Hi."; flag; return val; sockaddr in socket _2_name; /* * Fill in the address structure for socket 2. */ socket 2 name. sin family = AF INET; socket=2=name.sin~ort = htons(atoi(argv[2]»; socket_2_name.sin_addr.S_un.S_addr = inet_addr("5.0.0.5"); /* * Initialize send block. */ 10-68 Internet Services sendlength = sizeof(sendhuf); tolength = sizeof(socket 2 name); flag =0; - - /* * Send message from socket_l to socket_2. */ return_val sendto(socket_l, sendhuf, sendlength, flag, &socket_2_name, tolength) ; When you use the sendmsg function, you must specify a socket descriptor created by socket, a message argument, and an out-of-band character flag. The message argument specifies the address of a message header structure of type msghdr that contains the message to be sent. The message header structure lets the sendmsg function gather data from several user transmit buffers before sending a message. Members of the msghdr structure identify the following: • • • • • • The address of the destination socket if the source socket is not connected. The length of the message name field. An array of I/O buffer pointers of the iovec structure form. Each of the buffer pointers specifies the address of a buffer and that buffer's length. The number of buffers in the message array. The address of a buffer containing access rights sent with the message. The length of the access rights buffer. The sendmsg function sends the data in the mSlL,iovec field of the msghdr structure to the socket whose address is specified in the msg_ name field of msghdr. The receiving socket can then receive the data. If the array specifies multiple buffers, sendmsg gathers the data from all specified buffers before sending the message. If blocking is enabled for a socket, send, sendto, and sendmsg will block if the receiving end of a socket connection does not have enough space to buffer the data being sent. However, if the sending socket is defined as nonblocking, an error results and the send operation fails. Internet Services 10-69 The send operation will fail also if the sending socket is of type SOCK_ DGRAM and the message is too large to be sent in one piece. 10.6.5.2 Receiving Data from Sockets Internet applications can receive data from sockets by calling the read, recv, recvfrom, or recvmsg function. You can use any of these functions for receiving data in connection-oriented communication. You must use recvfrom or recvmsg to receive data in a connectionless environment. The read function reads data from a connected socket or file and places the data in a buffer. You specify read with the descriptor of a socket or file opened for reading, address of contiguous storage in which the input data is to be placed, and the maximum number of bytes to be read. The function returns the number of bytes actually read and placed in the buffer. The recv function provides an alternative means of receiving data between connected sockets. A call to recv must specify a socket descriptor, the address of the buffer into which received data is to be placed, the length (in bytes) of the specified buffer, and a flags argument. In the case of read, the socket descriptor specifies a destination socket - the socket from which data is received - that is connected to another socket. The function receives bytes of data through the specified socket from its connected peer and returns an integer indicating the number of bytes of data received and placed in the buffer. The flags argument is a bit mask that specifies whether the function should receive out-of-band characters and be allowed to peek at data before it is read. The out-of-band character flag can be 0 or MSG_OOB. If you specify MSG_OOB, available out-of-band data will be read before any other available data. The peek flag can be 0 or MSG_PEEK The following code uses a call to recv to receive a message from socket_ 2: 10-70 Internet Services :f/:include types :f/:include socket :f/:include in main (argc, argv) int argc; char **argv; { int static char static struct int int socket 2, socket 3; message[BUFSIZ]; sockaddr in socket 2 name; socket 2-namelen; - flag; - - /* * * Accept connection request from socket 2. Accepted connection will be on socket=3. */ socket 2 namelen = sizeof(socket 2 name); socket=3-= accept(socket_2, &socket_2_name, &socket_2_namelen); /* * Receive message from socket 1. */ flag = 0; ret val recv(socket_3, message, sizeof(message), flag); If your application uses connectionless socket communication, you can receive data by calling the recvfrom or recvmsg function. These functions receive data from another source. The recvfrom function receives bytes of data on a socket from any source. The recvmsg function receives bytes of data on a socket and places them in scattered buffers. Like calls to recv, calls to recvfrom must specify a socket descriptor, the address of the buffer into which received data is to be placed, the size of the buffer, and a flags argument. In addition, you must supply a source and source length. The source argument can be zero or nonzero. If nonzero, the argument points to the buffer into which recvfrom is to place the address structure of the socket from which data is received. If you specify zero, the address is not returned. The source length argument points to an integer that indicates the buffer's size. When Internet Services 10-71 the function returns, the size is modified such that it contains the actual length of the socket address returned. The call to recvfrom in the following code fragment receives data from an unconnected socket: tinclude types iinclude socket tinclude in main (argc, argv) int argc; char **argv; { int static char int int static struct buflength, fromlength; recvbuf[] = "Hi."; flag; return val; sockaddr in socket_2_name; /* * Receive data from socket 1 on socket_2. */ buflength = sizeof(recvbuf); fromlength = sizeof(socket 1 name); flag = 0; - return val recvfrom(socket 2, recvbuf, buflen, flag, &socket_l_name, &fromlength) ; When you use the recvmsg function, you must specify a socket descriptor created by socket, a message argument, and a flags argument. The message argument specifies the address of a message header structure of type msghdr into which the received message is to be placed. The message header structure lets the recvmsg function scatter data to several user transmit buffers after a message is received. Members of the msghdr structure identify the following: • • 10-72 The address of the destination socket if the source socket is not connected. The length of the message name field. Internet Services • • • • An array of I/O buffer pointers of the iovec structure form. Each of the buffer pointers specifies the address of a buffer and that buffer's length. The number of buffers in the message array. The address of a buffer containing access rights sent with the message. The length of the access rights buffer. The recvmsg function scatters a message into several user buffers if such buffers are available. The data is scattered into the message array buffers as specified by the iovec structure. When recvmsg receives a message, the message is split among buffers by filling the first buffer in the list, then the second, and so on, until all the buffers are full or no more data is available. If blocking is enabled for a socket, recv and recvto block and wait for data to arrive if no data is available at the time of the function call. However, if the sending socket is defined as nonblocking, an error results and the receive operation fails. 10.6.5.3 Polling Sockets for 1/0 Activity While programming data transfers to and from sockets, you may want to poll the sockets for I/O activity. By polling the sockets, you can check which sockets are ready to receive or send data, or which sockets have a pending exception. To poll sockets for I/O activity, use the select function. This function determines the I/O status of the sockets. specified in various mask arguments. The function returns when a socket is ready to receive or send data, or when a timeout value expires. A call to select must specify the highest numbered socket descriptor for which the function must search; pointers to arrays of bits that indicate which sockets should be checked for read or write readiness or for exceptions; and a timeout value. The first argument improves efficiency by specifying the highest numbered bit + 1 to be checked. A descriptor is represented by 1«8 (1 shifted to the left 8 times). If you are not sure what the highest numbered descriptor is, you can safely specify a number less than 64. Internet Services 10-73 The read, write, and exception fields arguments are pointers to arrays of bits, organized as integers (each integer describes 32 descriptors) that you can examine. If bit n of a bit array is set, the function checks to see if socket descriptor n is ready to be read from, is ready to be written to, or has any pending exceptions. All bits in the bit masks must correspond to socket descriptors. On return, the bit array to which each of the fields arguments points contains a bit mask of sockets that are ready for reading, are ready for writing, or have exceptions pending. Only bits that are set on entry to select can be set on exit. The timeout argument is a timeval structure that specifies the maximum interval to wait for a selection to be completed. The timeval structure consists of members that specify the number of seconds and number of microseconds to wait. If one of the sockets specified in the bit masks is ready for liD, the function returns before the timeout expires. The following code fragment selects a socket to receive a message: :fI:include types :fI:include socket :fI:include in main (argc, argv) int argc; char **argv; { unsigned long rmask, wmask, emask; int socket 2; int return=val; static struct sockaddr in socket_2_name; struct timeval timeout; /* * Select socket to receive message. */ emask = wmask = 0; rmask = (l«socket 2); timeout.tv_sec = 30; timeout.tv_usec ~ 0; return val = select(32, 10-74 Internet Services /* Set read mask */ &~mask, &wmask, &emask, &timeout); switch(return val) - { case -1: perror("select error"); break; case 0: printf("Select timed out with status O.\n"); break; default: if «rmask& (l«socket 2)) == 0) printf("Select not reading on socket_2. \n"); break; /* switch */ If a call to select blocks a process while waiting for input from a socket and the sending process closes the socket, select notes this as an event and unblocks the process. The descriptors are modified on return if select returns because of a timeout. 10.6.6 Shutting Down Sockets When an application no longer needs a socket, it should use the shutdown function to shut down the socket. An application can shut down a socket completely or shut down the socket's ability to receive or send data. You might use this function to program a more controlled shutdown. The shutdown function is also useful for setting up one-way (half-duplex) communication rather than normal two-way (full-duplex) communication. A call to shutdown must specify a socket descriptor and an integer in the range 0 to 2 that indicates how the socket is to be shut down. If you specify 0, the socket can no longer receive data. If you specify 1, the socket can no longer send data. The value 2 prevents the socket from receiving or sending data. In the following example, shutdown shuts down socket_l completely: Internet Services 10--75 :f/:include types :f/:include socket :f/:include in main(argc, argv) int argc; char **argv; { int int socket 1; return=val; /* * Shut down socket 1. */ return val } - select (socket_1, 2); 10.6.7 Closing Sockets When a socket is no longer being used, the application should close it. To close a socket, call the close function. If the socket is a connected socket, the function breaks the connection and then deletes the socket's descriptor from the appropriate reference table. Otherwise, the function just deletes the descriptor. If the close operation is the last reference to the socket, the socket is deactivated. The following code fragment shuts down and closes the socket socket_I: :f/:include types :f/:include socket :f/:include in main (argc, argv) int argc; char **argv; int int socket 1; return=val; /* * Shut down and close socket 1. */ 1e-76 Internet Services return_val = shutdown(socket_l, 2); return_val = close(socket_l); 10.6.8 Programming Socket Communication for a UDP Application This section shows an example of how you might use the socket communication routines to program a UDP application. The example consists of a UDP server (see Example 10-1) and a UDP client (see Example 10-2). The server creates a socket of type SOCK_DGRAM (UDP), binds it, and selects to receive a message on the socket. The server program expects the number of the port where it is waiting for requests. The client creates a socket of type SOCK_DGRAM (UDP), binds it, and sends a message to a specified destination address. The client program expects the name of a remote host and the port number where the remote host is waiting. To run the sample application you must do the following: • • • Pass 7 as the fourth program argument for both the server and client programs. The first argument (program name) is not supported by the VAXELN Toolkit, and the stdin, stdout, and stderr arguments are not used. Set the priority of the server to a higher priority than that of the client if the server and· client are to run on the same node. The Internet address in the example code must match the Internet address that you specify for the Internet address entry on the System Builder's Internet Network Description menu. Internet Services 10-77 Example 10-1: Sample UDP Server /* * Include Files */ #include #inc1ude #inc1ude #inc1ude #inc1ude #inc1ude #inc1ude $vaxe1nc errno types stdio socket in inet main (argc, argv) int argc; char **argv; static static unsigned long read mask, write mask, exception mask; int socket 2; /* Socket 2" descriptor. */ int buf1en; from1en; char recvbuf[BUFSIZ]; struct sockaddr in socket 1 name; /* Address structure for Socket 1. */ struct sockaddr-in socket:2:name; /* Address structure for Socket 2. */ int name1ength; int retva1; int flag; struct timeva1 timeout; /* * Check input parameters. */ if (argc ! = 2) { printf("Usage: server port number. \n"); exit (); } /* * Create a datagram socket (SOCK DGRAM) that is to use Internet addresses. Return the socket descriptor to socket_2. * */ if ((socket 2 { - = socket(AF INET, SOCK_DGRAM, 0» perror( "socket error"); exit () ; Example 10-1 Cont'd on next page 10-78 Internet Services -1) Example 10-1 (Cont.): Sample UDP Server /* * Build the address structure for socket 2. */ socket 2 name. sin family = AF lNET; socket=2=name.sin:p0rt = hton;(atoi(argv[l]»; socket_2_name.sin_addr.S_un.S_addr = inet_addr("5.0.0.5"); /* * Bind socket 2 to the name structure socket 2 name. */ retval bind (socket_2, &socket_2_name, sizeof(socket_2_name»; if (retval) { perror ("bind error"); cleanup(socket_2); /* * * set the read mask and poll socket 2 for read requests. a timeout value of 30 seconds. - Use */ exception mask = write mask = 0; read mask-= (1«socket-2); /* set read mask */ timeout.tv sec = 30; timeout.tv-usec = 0; Example 10-1 Cont'd on next page Internet Services 10-79 Example 10-1 (Cont.): ret val Sample UDP Server = select(32, &read mask, &write mask, &exception_mask, &timeout); switch (retval) { case -1: { perror("select error"); cleanup(socket_2); break; case 0: { printf("Select timed out with status cleanup(socket_2); break; default: if «read mask & (l«socket 2» - { == o. \n"); 0) printf("Select not reading on socket_2.\n"); cleanup(socket_2); } /*switch*/ /* * Initialize the receive buffer. */ buflen sizeof(recvbuf); fromlen = sizeof(socket 1 name); flag = 0; /* Flag can-be MSG_OOB or MSG PEEK */ /* * * Receive data from a socket named socket 1 name, using socket_2, and place the data in the buffer recvbuf. */ retval = recvfrom(socket 2, recvbuf, buflen, flag, &socket_1_name, &fromlen); if (retval == -1) perror (" recvfrom error II ) ; else printf (" %s\n", recvbuf); Example 10-1 Cont'd on next page 1 ~80 Internet Services Example 10-1 (Cont.): Sample UDP Server /* * Call cleanup to shut down and close socket_2. */ cleanup(socket_2); } 1* end main */ 1*-----------------------------------------------------------*/ cleanup (aocket) int socket; int 1** *1 retval; shut down socket completely. retval - shutdown(socket,2); if (retval -- -1) perror ("udp_server shutdown error"); 1** Close the socket. */ retval = close(socket); if (retval) perror ("close error"); exit (); } /* end cleanup *1 Internet Services 10-81 Example 10-2: Sample UDP Client /* * Include Files */ $vaxelnc errno types stdio socket in inet tinclude tinclude tinclude tinclude tinclude tinclude tinclude main (argc, argv) int argc; char **argv; { int int static char static struct int int int socket 1; /* Socket descriptor for Socket 1 */ sendle~, tolen; sendhuf [] = "Have a nice day."; sockaddr in socket_2_name; /* Address structure for Socket 2 */ namelength; flag; retval; /* * Check input parameters. */ if (argc != 2) { printf(ttUsage: port number. \n"); exit () ; } /* * * Create a datagram socket (SOCK DGRAM) that is to use Internet addresses. Return the socket descriptor to socket_1. */ if «socket_1 = socket(AF_INET, SOCK_DGRAM, 0» == -1) perror(ttsocket error"); exit () ; /* * * Build an address structure for socket 2 for receiving the message. */ Example 10-2 Cont'd on next page 10-82 Internet Services Example 10-2 (Cont.): Sample UDP Client socket 2 name. sin family = AF INET; socket=2=name.sin~ort = htons(atoi(argv[1]»; socket_2_name.sin_addr.S_un.S_addr inet_addr("5.0.0.5"); /* * Initialize the send buffer. */ sendlen = sizeof(sendhuf); tolen = sizeof(socket 2 name); flag = 0; /* Flag may-be MSG_OOB */ /* * * Send data from the buffer sendhuf using socket 1 to a socket named socket 2 name. */ ret val = sendto(socket 1, sendhuf, sendlen, flag, &socket 2 name, tolen); if (retval == -1) - { perror("sendto error"); cleanup(socket_1); /* * Call cleanup to shut down and close socket 1. */ cleanup(socket_1); } /* end main */ /*-----------------------------------------------------------*/ cleanup (socket) int socket; int retval; /* * Shut down socket completely. */ retval = shutdown(socket, 2); if (retval == -1) perror ("udp_client shutdown error"); Example 10-2 Cont'd on next page Internet Services 10-83 Example 10-2 (Cont.): Sample UDP Client /* * Close the socket. */ retval = close(socket}; if (retval) perror("close error"); exit (); /* end cleanup */ 10.6.9 Programming Socket Communication for a TCP/IP Application This section shows an example of how you might use the socket communication routines to program a TCPIIP application. The example consists of a TCPIIP server (see Example 10-3) and a TCPIIP client (see Example 10-4). The server creates a socket of type SOCK_STREAM (TCP), binds it, listens on it, receives a message, and closes it. The server program expects the number of the port where it is listening. The client creates a socket of type SOCK_STREAM (TCP), initiates a connection to the remote host, sends a message to the remote host, and closes the connection. The client program expects the name of the remote host port where the remote host (server) is listening.. To run the sample application you must do the following: • • • 10-84 Pass 7 as the fourth program argument for both the server and client programs. The first argument (program name) is not supported by the VAXELN Toolkit, and the stdin, stdout, and stderr argumen ts are not used. Set the priority of the server to a higher priority than that of the client if the server and client are to run on the same node. The Internet address in the example code must match the Internet address that you specify· for the Internet address entry o·n the System Builder's Internet Network Description menu. Internet Services Example 10-3: Sample TCP/IP Server /* * Include Files */ $vaxelnc errno types stdio socket in inet :/J:include :/J:include :/J:include :/J:include :/J:include :/J:include :/J:include main (argc, argv) int argc; char **argv; { /* Socket descriptors for /* Socket 2 and Socket 3. int static char static struct static struct int int int */ */ message[BUFSIZ]; sockaddr in socket 2 name; /* Address structure for socket 2 */ sockaddr-in retsocket_2_name; /* Address structure for socket 2 */ flag; retval; namelength; /* * Check input parameters. */ if (argc != 2) { printf(flUsage:- server port number. \n"); exit () ; /* * * Create a stream socket (SOCK STREAM) that is to use Internet addresses. Return the socket descriptor to socket_2. */ if «socket 2 = socket(AF INET, SOCK_STREAM, 0» { perror(flsocket error fl ); exit () ; - -1) Example 10-3 Cont'd on next page Internet Services 10-85 Example 10-3 (Cont.): Sample TCP/IP Server /* * Build an address structure for socket 2. */ socket 2 name. sin family = AF INET; socket=2=name.sin:p0rt = htons(atoi(argv[l]»; socket_2_name.sin_addr.s_un.s_addr = inet_addr("5.0.0.5"); /* * Bind socket 2 to the name structure socket 2 name. */ retval bind (socket_2, &socket_2_name, sizeof(socket_2_name»; if (retval) { perror("bind error"); cleanup (1, socket_2, 0); /* * * create and associate socket 2 with a queue for pending connection requests. The socket uses the queue to listen for requests. */ retval = listen(socket_2, 5); if (retval) { perror("listen error"); cleanup (1, socket_2, 0); /* Accept a connection request from socket 2. requests on socket 3. * * Place accepted */ namelength sizeof(socket 2 name); socket 3 = accept (socket_2; &socket_2_name, &namelength); if (socket 3 == -1) { - perror ("accept error"); cleanup (2, socket_2, socket_3); Example 10-3 Cont'd on next page 10-86 Internet Services Example 10-3 (Cont.): /* Sample TCP/IP Server Receive data from socket 1, using socket_3, and place the data in the buffer message. * * */ flag = 0; /* Can be 0, MSG_OOB, or MSG_PEEK. */ retval = recv(socket 3, message, sizeof(message), flag); if (retval == -1) { perror("receive error"); cleanup (2, socket_2, socket_3); else printf (" %s\n", message); /* * Call cleanup to shut down and close the sockets. */ cleanup (2, socket_2,. socket_3); } /* end main */ /*-----------------------------------------------------------*/ cleanup(how many, socket 1, socket 2) int how many; int socket_1, socket_2; int retval; /* * Shut down and close socket 1 completely. */ retval = shutdown(socket 1, 2); if (retval == -1) perror("tcp_server shutdown error, socket_1"); retval = close(socket 1); if (retval) perror("close error"); Example 10-3 Cont'd on next page Internet Services 10-87 Example 10-3 (Cont.): Sample TCP/IP Server /* * If given, shut down and close socket 2. */ if (how many - { == 2) retval = shutdown(socket 2, 2); if (retval == -1) perror("tcp_server shutdown error, socket_2"); retval = close(socket 2); if (retval) perror("close error"); exit (); } /* end cleanup*/ Example 10-4: Sample TCP/IP Client /* * Include Files */ #include # include #include #include :jj:include #include # include $vaxelnc errno types stdio socket in inet main (argc, argv) int argc; char **argv; { static static int char struct int int int socket 1; /* Socket descriptor for Socket 1 */ message[] "Have a nice day. "; sockaddr_in socket _2_name; /* Address structure for Socket 2 */ flag; retval; shut = FALSE; /* Flag to cleanup */ Example 10-4 Cont'd on next page 10-88 Internet Services Example 10-4 (Cont.): Sample TCP/IP Client /* * Check input parameters. */ if (argc != 2 ) { printf("Usage: port number. \n"); exit (); /* * * Create a stream socket (SOCK STREAM) that is to use Internet addresses. Return the socket descriptor to socket_l. */ if «socket_l = socket(AF INET, SOCK_STREAM, 0» == -1) { perror ( "socket error"); exit (); /* * Build an address structure for socket 2. */ socket 2 name. sin family = AF INET; socket:2:name.sin:port = htons(atoi(argv[l]»; socket_2_name.sin_addr.S_un.S_addr = inet_addr("5.0.0.5"); /* Connect socket_1 to the remote socket named socket_2_name. * */ retval connect(socket 1, &socket_2_name, sizeof(socket_2_name»; if (retval) { perror ("connect error"); cleanup (shut, socket_1); Example 10-4 Cont'd on next page Internet Services 10-89 Example 10-4 (Cont.): /* Sample TCP/IP Client send data from the message buffer, using socket_l, to the connected socket. * * */ flag = 0; /* Can be 0 or MSG OOB. */ ret val = send(socket 1, message, sizeof(message), flag); if (retval < 0) { perror ("send error"); shut = TRUE; /* * Call cleanup to shut down and close the socket. */ cleanup (shut, socket_1); } /* end main */ /*-----------------------------------------------------------*/ cleanup (shut, socket) int shut; int socket; int retval; /* Shut down socket completely if it was connected. * */ if (shut) { retval = shutdown(socket, 2); if (retval == -1) perror ("tcp_client shutdown error"); Example 10-4 Cont'd on next page 10-90 Internet Services Example 10-4 (Cont.): Sample TCP/IP Client /* * Close the socket. */ retval = close(socket); if (retval) perror("close error"); exit () ; /* end main */ 10.7 Retrieving and Setting Socket Characteristics The VAXELN Toolkit also provides routines for retrieving and setting socket characteristics. These routines include the following: Routine Description getpeername Returns the name of a socket's connected peer. getsockname Returns the name associated with a socket. getsockopt Returns the options set for a socket. setsockopt Sets options for a socket. Sections 10.7.1 and 10.7.3 explain how to retrieve socket names and options. Section 10.7.2 explains how to set socket options. 10.7.1 Retrieving Socket Names An application can retrieve a socket name by calling the getsockname or getpeername routine. The getsockname routine returns the name associated with a socket. The getpeername routine returns the name of a socket's connected peer. You must specify these routines with a socket descriptor that was previously created with socket, a pointer to a buffer in which the name is to be returned, and the size of the name buffer. The socket descriptor that you specify in a call to getsockname must be bound to a name. Internet Services 10-91 The routines return the socket name and update the name length argument with the name's actual size. 10.7.2 Setting Socket Characteristics To set options on a socket, an application must call the setsockopt routine. A call to setsockopt must specify a socket descriptor, the protocol level for which the options are to be modified, the options to be set, the address of a buffer that contains option parameters, and the size of the option parameter buffer. Options can exist at multiple protocol levels. However, options are always present at the uppermost socket level. To set options at the socket level, you specify the level SOL_SOCKET. To set options at any other level, specify the number of the protocol that controls the option. For example, to specify that an option be interpreted by the TCP protocol, specify the TCP protocol number (IPPROTO_TCP). See the module in.h for a list of the protocol values. The interpretation of the options you specify is based on the protocol level. Table 10-7 lists the options that are available at the socket level: Table 10-7: SOCket-Level Socket Options Option Description SO_BROADCAST Lets the socket broadcast messages. SO_DONTROUTE Specifies that messages sent through the socket are to bypass the routing facilities. Messages are directed to the appropriate network interface' according to the network portion of the destination address. Lets a connected socket transmit messages periodically. If a connected peer fails to respond to the messages, the connection is considered broken and the processes using the socket receive an error. Specifies that reused local addresses can be supplied in calls to bind. Delays the deletion of transmitted data when a socket is closed until the data is transmitted or the device times out (approximately eight minutes). 10-92 Internet Services You must specify all socket-level options except SO_LINGER with an integer parameter. Specify a nonzero value if the option is to be enabled. Specify zero to disable the option. When you use the SO_LINGER option, you must specify the address of a linger structure that indicates the state of the option (on or off) and the linger interval. The linger interval indicates the number of seconds to linger. If the linger interval is zero, the value specified for the linger time when the system was built is used. The linger structure is defined as follows: struct linger int int 1 onoff; l=linger; /* option on/off */ /* linger time */ }; If the value of l_onoffis nonzero, the system does not delete the socket until the socket is able to transmit the data or until the socket times out. If the value of l_onoffis zero, the system processes a close operation as quickly as possible. 10.7.3 Retrievi ng Socket Options An application can check which options are set for a socket by calling the getsockopt routine. A call to getsockopt must specify a socket descriptor, the protocol level for which the options are to be returned, the option to be returned, the address of a buffer into which the option val ue is to be placed, and the size of the option value buffer. To retrieve options at the socket level, specify the level SOL_SOCKET. To retrieve options at any other level, specify the number of the protocol that controls the option. For example, to specify that an option or the TCP protocol be returned, specify the TCP protocol number (IPPROTO_ TCP). See the module in.h for a list of the protocol values. The interpretation of the .options you specify is based on the protocol level. See Table 10-7 for a list of the socket level options. Internet Services 10-93 Chapter 11 LAT Host Services The VAXELN Toolkit includes local area transport (LAT) host services that VAXELN systems can use to communicate with devices attached to terminal servers, such as the DECserver 500. This chapter provides an overview of theLAT host services (see Section 11.1) and explains how to use the services to do the following: • • • • • 11.1 Establish circuits for LAT communication, Section 11.2 Manage VAXELN service nodes, Section 11.3 Set up a dedicated service environment, Section 11.4 Set up an application device environment, Section 11.5 Retrieve and set terminal characteristics, Section 11.6 LAT Host Services Overview LAT is a communications protocol that lets system nodes running LAT host services communicate with dedicated terminal server nodes running LAT server services. The collection of system nodes and terminal server nodes in a local area network (LAN) constitutes a LAT network. The VAXELN LAT host services support the following: • • • Terminal server communication Terminal I/O A control interface that LAT application programs can use to manage and monitor the LAT environment on a VAXELN system LAT Host Services 11-1 • An interactive utility you can use to manage and monitor the LAT environment on a VAXELN system A VAXELN system that includes the LAT host services is a VAXELN service node. A service node can offer services to or request access to services offered by a terminal server. By default, a service node offers VAXELN Command Language Utility (EeL) as a service. You can access that service from an interactive terminal attached to a terminal server. The LAT host services let application programs: • • • Manage and monitor a VAXELN service node's characteristics and activities by calling VAXELN LAT utility procedures Set up dedicated service environments Set up application device environments You can initiate communication between a service node and terminal server from an interactive terminal attached to the terminal server or from an application program running on the service node. From an interactive terminal, you establish a session with a service offered by the service node. The service can be ECL or a user-created dedicated service that is built into your VAXELN system and that executes as a job. An application program running on a service node can establish a session with a remote application device or service attached to a terminal server. An application device offers a service to VAXELN service nodes in a LAT network. For example, a printer would offer printing services; a terminal device might offer display services. Figure 11-1 shows a sample VAXELN LAT configuration. 11-2 LAT Host Services Figure 11-1: Sample VAXELN LAT Configuration V AXElN Service Nodes VAXElN VAXElN LAT LAT Host Services Host Services D lili~ililililijl o Interactive terminal accessing Eel Interactive terminal accessing a dedicated service Application device MLO-004288 To include the LAT host services, you build the VAXELN LAT driver (LTDRIVER) into your VAXELN system by selecting ACTNE or INACTNE for the LAT host services option on the System Builder's Network Node Characteristics Menu. If you specify ACTNE, the driver's LAT protocol becomes active when your system starts executing. When the LAT protocol is active, the driver periodically multicasts a message to the terminal servers in the LAN, advertising the services that it offers. If a terminal server user tries to. connect to one of the services, the service node accepts the connection request. LAT Host Services 11-3 When the LAT protocol is inactive, the LAT driver does not multicast advertising messages to or accept connection requests from terminal servers. However, you can activate the protocol at run time with a utility command or a runtime procedure call. By using an initial inactive state, an application program can set up a LAT service node environment before the driver establishes connections with terminal servers. For example, you can set the service node's characteristics, or you can create ports for establishing connections with dedicated services or application devices. A VAXELN application program can manage and monitor a LAT service node environment by calling LAT utility procedures. For descriptions of the utility procedures, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. The LAT driver also supports a LAT Control Program (LATCP) Utility that lets you manage and monitor LAT service node characteristics and activities interactively by entering LATCP commands. For more information about the LATCP Utility, see the VAXELN Development Utilities Guide. The rest of this chapter explains how to do the following: • • • • • Establish circuits for LAT communication, Section 11.2 Manage VAXELN service nodes, Section 11.3 Set up a dedicated service environment, Section 11.4 Set up an application device environment, Section 11.5 Retrieve and set terminal characteristics, Section 11.6 11.2 Establishing Circuits for LAT Communication The LAT driver relies on VAXELN virtual circuits for communicating with application programs. Therefore, an application program must establish the appropriate circuit connections before it can call the VAXELN LAT utility procedures. Sections 11.2.1, 11.2.2, and 11.2.3 explain how to establish these connections. 11-4 LAT Host Services 11.2.1 Connecting to a LAT Control Port LAT host service utility procedures manage the LAT environment on a VAXELN service node. Before an application program can call these procedures, it must create a VAXELN message port and connect that port in a circuit to a LAT control port. When the LAT driver starts executing, it creates two control ports and two corresponding port names: the local port name $LAT_CONTROL and a universal PORT name of the form node_name$LAT_CONTROL. For example, if the LAT driver starts executing on the service node RTNODE, the driver names the control ports $LAT_CONTROL and RTNODE$LAT_CONTROL. The $LAT_CONTROL port makes the host service utility procedures available to application programs running on the local node; the node_name$LAT_CONTROL port makes the procedures available to programs running on remote nodes. The following example shows how you might connect to the local LAT control port: MODULE create_a_lat-port; INCLUDE $LAT_UTILITY; PROGRAM create_lat-port; VAR lat_ctrl-port : PORT; BEGIN { Create a VAXELN message port. { Connect that message port in a circuit to the local LAT control port. } CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION_NAME := '$LAT_CONTROL'); { Now call a LAT host service utility procedure. ELN$LAT_CREATE_PORT(CIRCUIT := lat_ctrl-port, PORT NAME : = ' LTAO' , PORT=TYPE := LAT$APPLICATION); END. END; LAT Host Services 11-5 Once a program connects to a control port, the program specifies the port on its end of the connection in calls to the LAT host service utility procedures. In the preceding example, the port lat_ctrCport connects to the local control port $LAT_CONTROL. Thus, lat_ctrtport can be used in the subsequent call to ELN$LAT_CREATE_PORT. You must specify a LAT control port in calls to the following LAT host service utility procedures. Routine Description Clears a VAXELN service node's counters. Creates a VAXELN LAT port on a VAXELN service node. Creates a service to be offered by a VAXELN service node. ELN$LAT_DELETE_PORT Deletes a VAXELN LAT port. ELN$LAT_DELETE_SERVlCE Deletes a service that is offered by a VAXELN service node. Sets a VAXELN service node's characteristics. Associates a dedicated LAT port with application service; or associates an application LAT port on a VAXELN service node with a remote port on a terminal server. Sets the characteristics of a service being offered by a VAXELN service node. Returns a VAXELN service node's characteristics. Returns performance and error statistics for a VAXELN service node or for all terminal servers connected to a VAXELN service node. Returns the characteristics of a VAXELN service node's LAT ports. 11-6 LAT Host Services Routine Description Returns the characteristics of terminal servers known to a VAXELN service node. Activates the LAT protocol on a VAXELN service node. Stops the LAT protocol on a VAXELN service node. To use these procedures, you must also include the appropriate modules from the VAXELN runtime libraries. Language Module VAXELN Pascal $LAT_UTILITY C $vaxelnc and $lat_utility FORTRAN 'ELN$FORTRAN_DEFS.FOR' NOTE The LAT utility procedures are in the shareable image LATSHR.EXE. If you dynamically load programs that use LAT utility procedures into a VAXELN system, you should specify ELN$:LATSHR.EXE in the Guaranteed image list entry on the System Builder's System Characteristics Menu when you build that system. For descriptions of the LAT utility routines, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 11.2.2 Creating a VAXELN LAT Port A VAXELN LAT port is a service node structure for terminal 110 operations. The VAXELN LAT driver supports three types of LAT ports: interactive, dedicated, and application. The driver dynamically creates interactive LAT ports that offer the ECL service to terminal server users. A dedicated LAT port offers an application service (a service other than ECL) to terminal server users. An application LAT port lets application programs running on the service node gain access LAT Host Services 11-7 to a remote terminal's dedicated or application LAT port by using the LATCP command CREATE PORT or a call to the ELN$LAT_CREATE_ PORT procedure. A call to ELN$LAT_CREATE_PORT must specify the port connected in a circuit to a LAT control port, a LAT port name, and a LAT port type. The following call to ELN$LAT_CREATE_PORT creates an application LAT port named LTAO: MODULE create_a_lat-port; INCLUDE $LAT_UTILITY; PROGRAM create_lat-port; VAR lat_ctrl-port : PORT; BEGIN { Create a VAXELN message port. CREATE_PORT(lat_ctrl-port); { Connect that message port in a circuit to the local LAT control port. CONNECT_CIRCUIT(lat_ctrl-port, DESTINATION_NAME:= '$LAT_CONTROL'); { Create an application LAT port named LTAO. } ELN$LAT_CREATE_PORT(CIRCUIT := lat_ctrl-port, PORT NAME := 'LTAO', PORT-TYPE := LAT$APPLICATION); END. END; The LAT driver associates two VAXELN message ports with each LAT port that it creates: a DAP port for file- and record-oriented I/O and a DDA port for accessing serial line devices and managing connections between VAXELN LAT ports and remote terminal server ports. In the case of interactive LAT ports, the driver associates the DAP port with the name LTAn and associates the DDA port with the name LTAn$ACCESS, where n identifies a unique port name. When you create a dedicated or application LAT port, the driver associates the DAP port with the port name you specify with the CREATE PORT command or ELN$LAT_CREATE_PORT procedure. The driver also associates the DDA port with a port name of the form port-name$ACCESS, where port-name is the name of the DAP port. 11-8 LAT Host Services Figure 11-2 distinguishes a VAXELN LAT port from its DAP and DDA VAXELN message ports. Figure 11-2: VAXELN LAT Port VAXELN LAT Port DAP Port DAP Port Name Kernel Objects DDA Port DDA Port Name MLO-004289 The LAT host services include a set of port utility procedures for managing a connection between a VAXELN LAT port and a remote port or service on a terminal server. To use these procedures, an application program must connect to a LAT port's DDA port (see Section 11.2.3). 11.2.3 Connecting to a DDA Port To use the VAXELN LAT port utility procedures, an application must create a port and connect that port in a circuit to a VAXELN LAT port's DDA port. The DDA port provides an interface for accessing serial line devices. The following example builds upon the example in Section 11.2.1 by showing how you might connect to a DDA port: LAT Host Services 11-9 MODULE map_a_dda-port; INCLUDE $LAT_UTILITY; PROGRAM map_dda-port; VAR lat_ctrl-port, dda_interface-port PORT; BEGIN { Create a VAXELN message port. CREATE_PORT(lat_ctrl-port); { Connect that port in a circuit to the local LAT control port. } CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION_NAME := '$LAT_CONTROL'); { Create VAXELN LAT port named LTAO. Driver creates DAP and DDA } { ports named LTAO and LTAO$ACCESS, respectively. } ELN$LAT_CREATE_PORT(CIRCUIT := lat_ctrl-port, PORT NAME := 'LTAO', PORT=TYPE := LAT$APPLICATION); { Create a VAXELN message port for connecting to the DDA port. } CREATE_PORT(dda_interface-port); { Connect that port in a circuit to the LAT port's DDA port. } CONNECT_CIRCUIT (dda_interface-port, DESTINATION NAME := 'LTAO$ACCESS') { Now call a port utility procedure. } ELN$LAT_MAP_PORT(CIRCUIT := dda_interface-port, NEW FIELDS := [LAT$SET NODE, LAT$SET QUEUED STATUS, LAT$SET=PORT1, QUEUED STATUS := TRUE, REMOTE-SERVER NAME := 'LAT100', REMOTE= PORT_NAME : = , PORT_2' , SERVICE NAME := " ) ; END. END; Once a program connects a circuit to the LAT port's DDA port, the program specifies the port on its end of the connection in calls to the port utility procedures. The preceding example connects the port dda_interface..port to the DDA port named LTAO$ACCESS. Thus, the subsequent call to the ELN$LAT_MAP_PORT procedure can associate the LAT port LTAO with the remote port named PORT_2 on the terminal server named LATIOO. 11-10 LAT Host Services You must specify a LAT port's DDA port in calls to the following port utility procedures: Description Routine Connects an application LAT port on a VAXELN service node to a remote port or service offered by a terminal server. ELN$LAT_DISCONNECT Disconnects a VAXELN LAT port from a remote port offered by a terminal server. Associates (maps)· a dedicated LAT port with a service offered by a VAXELN service node; or associates an application LAT port on a VAXELN service node with a remote port or service offered by a terminal server. Returns mapping information for a LAT port on a VAXELN service node. Waits for a connection to be established between a dedicated LAT port on a VAXELN service node and a remote device port or service offered by a terminal server. To use these procedures, you must also include the appropriate modules from the VAXELN runtime .libraries. Language Module VAXELN Pascal $LAT_UTILITY C $vaxelnc and $lat_utility FORTRAN 'ELN$FORTRAN_DEFS.FOR' NOTE The LAT utility procedures are in the shareable image LATSHR.EXE. If you dynamically load programs that use LAT utility procedures into a VAXELN system, you should LAT Host Services 11-11 specify ELN$:LATSHR.EXE in the Guaranteed image list entry on the System Builder's System Characteristics Menu when you build that system. For descriptions of these routines, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. For more information about DDA or establishing a circuit with a DDA port, see Section 14.4.5. 11.3 Managing VAXELN Service Nodes You can manage a VAXELN service node's characteristics and activities by calling LAT host service utility procedures from an application program. The procedures let you: • • • • • 11.3.1 Retrieve and set service node characteristics, Section 11.3.1 Manage service node services, Section 11.3.2 Retrieve port characteristics, Section 11.3.3 Retrieve terminal server characteristics, Section 11.3.4 Monitor a LAT environment's performance and error statistics, Section 11.3.5 Retrieving and Setting Service Node Characteristics The LAT driver stores a service node's characteristics in a characteristics record. The values in this record identify the following node characteristics: • • • • • • 11-12 Name Identification string Enabled LAT network groups Service announcement message time interval LAT driver state (active or inactive) LAT protocol version LAT Host Services An application program can retrieve a service node's characteristics by calling the ELN$LAT_SHOW_CHAR procedure. and ELN$TTY_GET_ CHARACTERISTICS procedures This procedure allocates a characteristics record that the application program can access to retrieve service node characteristics. A call to ELN$LAT_SHOW_CHAR must specify the port connected in a circuit to a LAT control port, an argument that receives the version number of the characteristics record, and a pointer that points to the service node's characteristics record. For example: VAR lat_ctrl-port : PORT; char record version, status INTEGER; char-record-:. "'LAT$NODE CHAR; one_~hown : BOOLEAN := FALSE; BEGIN CREATE~ORT(lat_ctrl-port); CONNECT_CIRCUIT(lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_SHOW_CHAR(CIRCUIT := lat_ctrl-port, VERSION := char_record_version, CHARACTERISTICS := char_record); WITH char record'" DO BEGIN WRITELN('Node name = I NAME); WRITELN('Groups enabled = )'; FOR i := LAT$GROUPO TO LAT$GROUP255 DO IF i IN GROUPS THEN BEGIN IF one shown THEN WRITE(' ,'); WRITE(i:l); one shown := TRUE; END; WRITELN(')'); END; DISPOSE(char_record); END. This section of code allocates a service node's characteristics record and then accesses the fields containing the service node's name and enabled LAT network groups. Deallocate the characteristics record when the record is no longer needed. LAT Host Services 11-13 An application program can also change a service node's characteristics by calling the ELN$LAT_SET_NODE procedure. You can use this procedure to change all characteristics but the LAT driver's state and the LAT protocol version. The call to ELN$LAT_SET_NODE in the following section of code changes a service node's name, identification string, and enabled groups: VAR lat_ctrl-port : PORT; msg_interval : LAT$MULTICAST; disable grps : LAT$GROUPS; status 7 INTEGER; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_SET_NODE(CIRCUIT := lat_ctrl-port, NEW FIELDS := [LAT$SET NODE, LAT$SET IDENT, LAT$ENABLE_GROUPS] , NODE NAME := 'RTNODE', NODE-IDENT := 'VAXELN Service Node -- RTNODE', SECONDS := msg_interval, ENABLE GROUPS := [0,4,7], DISABLE_GROUPS := disable_grps); END. Sections 11.3.1.1 to 11.3.1.5 provide more information about VAXELN service node names, identification strings, network groups, multicast timers, and LAT driver states. 11.3.1.1 Node Names A LAT service node must have a node name that consists of 1 to 16 ASCII characters and is unique within the LAT network. If a service node is part of a DECnet network, the LAT service node name should be the same as the DECnet node name. The DECnet node name must be unique within the same logical Ethernet and must be unique within the entire DECnet network. If a node name is not defined for a service node, the LAT driver uses a node name of the form LAT-nnnnnnnnnnnn, where nnnnnnnnnnnn represents the hexadecimal string for the Ethernet controller's address. 11-14 LAT Host Services 11.3.1.2 Node Identification Strings A node identification string is a string of up to 64 ASCII characters that describes a LAT service node. When the LAT driver is active, it advertises the string by including it in periodic service announcement messages it sends to terminal servers. If you do not specify a node identification string, the default is the VAXELN system identification string. 11.3.1.3 LAT Network Groups You can distribute a LAT network among LAT network groups. Groups help manage the size of terminal server data bases by limiting the number of service nodes for which the server maintains information. By controlling groups, you can restrict message traffic between the terminal servers and service nodes in a LAT network. For a terminal server to establish a connection with a service node, the server must share at least one group with that service node. A terminal server ignores the messages it receives from service nodes that are not in one of the server's groups. For example, suppose a LAT configuration consists of two terminal servers, TSl and TS2, and the service node RTNODE. Assume that the following groups are enabled for each: Device Groups Enabled TSI 1,7 TS2 0,6 RTNODE 0 Initially, terminal server TS2 can communicate with service node RTNODE because the group 0 is enabled for both devices. If you use the LATCP command SET NODE or the ELN$LAT_SET_NODE procedure to enable group 7 for RTNODE, both terminal servers can communicate with that service node. Group 0 is enabled by default -for all service nodes and terminal servers. If you do not want group 0 enabled, you must disable it. LAT Host Services 11-15 11.3.1.4 Multicast Timer The multicast timer determines the time between a service node's service announcement messages. Service nodes send announcement messages to terminal servers to advertise the services that they offer. The messages include the following information: • • • • • • Node name Identification string Group designations Service names Service identification strings Service ratings By default, the LAT driver sends the announcement messages every 60 seconds. However, the time interval can range from 10 to 255 seconds. If you specify a larger value for the multicast timer, the LAT driver sends service announcement messages less frequently. Thus, a larger value minimizes network overhead but causes terminal server users to wait longer for services to become available after a server reboot, or after recovering from a network problem. Infrequent message announcements can also affect a server's load balancing. Smaller multicast time values cause the LAT driver to consume more network resources because it sends service announcement messages more frequently. Multicast service announcement messages broadcast service node characteristic changes. When you change a service node's characteristics, the LAT driver notifies the servers in the LAN by including the changed information in the service node's announcement messages. 11.3.1.5 Service Node States A service node can be active or inactive. When active, the service node periodically sends service announcement messages to terminal servers in the LAT network. An active service node can also accept connection requests from terminal servers. For example, you can issue a connect request from an interactive terminal. 11-16 LAT Host Services When inactive, a service node driver does not send service announcement messages to or accept connection requests from terminal servers until you start the LAT protocol with the LATCP command START NODE or a call to the ELN$LAT_START_NODE procedure. By using an initial inactive state, an application program can set up a service node before the LAT driver establishes connections with terminal servers. For example, an application program can set the service node's characteristics or create ports for establishing connections with dedicated services or application devices. 11.3.2 Managing Service Node Services A service is a resource offered by a VAXELN service node or a terminal server on the LAT network. A VAXELN service node can offer up to eight uniquely named services, with each service offering all of the node's resources. You can manage a service node's services by calling LAT host service utility procedures from an application program. The procedures let you: • • • 11.3.2.1 Create and delete services Change service characteristics Advertise services Creating and Deleting Services To add services to and delete services from a service node's list of offerings, use the ELN$LAT_CREATE_SERVICE and ELN$LAT_ DELETE_SERVICE procedures, respectively. Each service offered by a service node has a name, identification string, and rating. The terminal server uses the service rating to balance the loads of service nodes in a LAT network. When you create a service, you must specify the port connected in a circuit to aLAT control port, a service name, a service identification string, and a Boolean value indicating whether you want the driver to use a service rating that you specify or the service rating that it generates. You must also specify a link argument; however, this argument is reserved for future use. LAT Host Services 11-17 The following call to ELN$LAT_CREATE_SERVICE creates a service named RT_SERVICE: VAR lat_ctrl-port : PORT; service rating : LAT$SERVICE RATING; link count, status : INTEGER; link-names LAT$LINK_NAME_LIST; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_CREATE_SERVICE(CIRCUIT := lat_ctrl-port, SERVICE NAME := 'RTSERVICE', SERVICE-IDENT := 'Real Time Service -- RTSERVICE', STATIC SERVICE RATING := FALSE, SERVICE RATING-:= service rating, LINK COUNT := link count,LINK-NAMES := link=names); END. The value FALSE specified for the static service rating tells the driver to use a dynamically determined service rating and to ignore any user-specified service rating. When you delete a service, you only need to specify the port connected in a circuit to the LAT control port and the name of the service you want to delete. The following sections provide more information about VAXELN service names, identification strings, and ratings. Service Names Service names are strings that can consist of up to 16 of the following ASCII characters: • • Alphanumeric characters - A to Z, a to z, and 0 to 9 A subset of the international character set - decimal character values 192(10) to 253(10) 11-18 LAT Host Services • Punctuation characters - dollar sign ($), hyphen (-), period (.), and underscore CJ The names of services that a service node offers must be unique. However, multiple service nodes in a LAT network can share a service name. Having multiple service nodes in a LAT network offer the same service provides for fa ilover . Failover is a terminal server service that takes over if a session is disrupted because a service node becomes unavailable. When a session is disrupted, the terminal server uses the automatic failover service to search for other nodes that offer the service that was being used by the disrupted session. If the server finds one or more such nodes, it tries to connect to the service on the node that is least busy. When the LAT driver executes, it creates a default service representing the name of the VAXELN service node. If no name is defined for the service node, the driver uses a node name and service name of the form LAT-nnnnnnnnnnnn, where nnnnnnnnnnnn represents the hexadecimal string for the Ethernet controller's address. Service Identification Strings A service identification string is a string of up to 64 ASCII characters that describes a service offered by a service node. The service node incl udes service identification strings in its service announcement messages. If you do not specify a service identification string, the default is the VAXELN system identification string. Service Ratings Service ratings provide a system load balancing feature. The LAT driver running on each service node that offers a particular service can dynamically calculate a service rating for that service. If a service's rating is calculated dynamically, the driver recalculates the rating every time the multicast timer expires. Thus, the rating reflects the availability of resources on the service node. A service rating can range from 0 to 255, where 0 indicates that a service is not available and 255 indicates that a service is highly available. Dynamic service ratings are based on a service node's activity and processor type. Generally, services offered by nodes experiencing high levels of activity receive low ratings to inhibit new connections. LAT Host Services 11-19 Terminal servers use service ratings to balance the load among service nodes that offer the same service; servers establish connections with a service on the least busy service node that offers that service. 11.3.2.2 Changing Service Characteristics An application program can change a service's characteristics by calling the ELN$LAT_SET_SERVICE procedure. A call to this procedure must specify the port connected in a circuit to the LAT control port, a value for a new fields argument, and values for characteristics you want to change: name, identification string, and rating. The new fields argument identifies the characteristics you will be changing. You must also specify two link arguments. However, these arguments are reserved for future use. Normally, the LAT driver generates adequate service ratings. However, you can override the driver's rating by assigning a static service rating to a service. For example, suppose a service needs to run on a service node that is not busy. An application program could let the LAT driver set up the service's initial service rating and then adjust the rating to inhibit new connections. The following call to ELN$LAT_SET_ SERVICE changes a service's service rating: VAR lat_ctrl-port : PORT; service ident : LAT$IDENT STRING; link count, status : INTEGER; link=names LAT$LINK_NAME_LIST; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); { Lower service rating to inhibit new connections. } 11-20 LAT Host Services ELN$LAT_SET_SERVICE(CIRCUIT := lat_ctrl-port, NEW FIELDS := [LAT$SET STATIC RATING], SERVICE NAME := 'RTSERVICE', SERVICE-IDENT := service ident, SERVICE=RATING := 10, LINK COUNT : = 0, LINK NAMES := link_names); END. When you specify a static service rating, you disable a dynamic service rating. 11.3.2.3 Advertising Services All of the service nodes in a LAT network advertise their services by multicasting service announcement messages to all terminal servers in the LAN. A service node starts multicasting these messages as soon as it becomes active. You can activate a service node from an application program by calling the ELN$LAT_START_NODE procedure as follows: VAR lat_ctrl-port : PORT; link_names : LAT$LINK_NAME_LIST; status : INTEGER; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT(lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_START NODE(CIRCUIT := lat_ctrl-port, LINK COUNT := 0, LINK-NAMES := link_names); END. A call to ELN$LAT_START_NODE must specify the port connected in a circuit to a LAT control port and two link arguments. The link arguments are reserved for future use. LAT Host Services 11-21 As a terminal server receives service announcement messages, it checks whether the service nodes sending the messages share one of its enabled LAT network groups. If a service node and a terminal server share a group, the server accepts the message and adds the name of the service node and the names of the services the node offers to its services data base. To shut down a VAXELN service node, call the ELN$LAT_STOP_NODE procedure. You should precede the call with a call to ELN$LAT_SET_ NODE and identify the reason for the shut-down in its node_ident argument. For example: VAR lat_ctrl-port : PORT; seconds : LAT$MULTICAST disable grps, enable grps : LAT$GROUPS; link_names : LAT$LINK_NAME_LIST; status : INTEGER; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_SET_NODE(CIRCUIT := lat_ctrl-port, NEW FIELDS := [LAT$SET IDENT], NODE_NAME := 'RTNODE',NODE IDENT := 'RTNODE shutting down for PM ... ', SECONDS := seconds, ENABLE GROUPS := endable grps, DISABLE_GROUPS := disable_grps); ELN$LAT_STOP_NODE(CIRCUIT := lat_ctrl-port, LINK COUNT := 0, LINK NAMES := LAT$LINK_NAME_LIST); END. 11-22 LAT Host Services 11.3.3 Retrieving LAT Port Characteristics A VAXELN LAT port has the following characteristics: • • • • • • • • Port name Port type Queue status Remote server name Remote port name Service name Actual remote server name Actual remote port name An application program can retrieve a LAT port's characteristics by calling the ELN$LAT_SHOW_PORT procedure. This procedure allocates a characteristics record from which the application program can retrieve the characteristics. A call to ELN$LAT_SHOW_PORT must specify the port connected in a circuit to a LAT control port, the name of the LAT port whose characteristics record is to be accessed, a LAT port type, and the name of a user-specified procedure to be invoked by ELN$LAT_SHOW_PORT. For example: VAR 1 at_ctrlyort PORT; BEGIN CREATE_PORT(lat_ctrlyort); CONNECT_CIRCUIT (lat_ctrlyort, DESTINATION NAME := '$LAT_CONTROL')i ELN$LAT_SHOW_PORT(CIRCUIT := lat_ctrlyort, PORT NAME := 'LTAO', PORT-TYPES := [LAT$APPLICATION, LAT$DEDICATED, LAT$INTERACTIVE], SHOW PORT := show_latyort); END. PROCEDURE show_latyort OF TYPE LAT$SHOW_PORT_ROUTINEi LAT Host Services 11-23 BEGIN WITH port_characteristics A DO BEGIN WRITELN('Port name = " name); WRITE('Port type = '); CASE port type OF LAT$RESERVED PORT: WRITELN('Reserved'); LAT$APPLICATION : WRITELN('Application'); LAT$DEDICATED : WRITELN('Dedicated'); LAT$INTERACTIVE : WRITELN('Interactive'); OTHERWISE WRITELN('Unknown')i END; END; END; The ELN$LAT_SHOW_PORT procedure invokes the user-specified procedure only if the driver finds a characteristics record for the specified LAT port. When the call to ELN$LAT_SHOW_PORT in the preceding example executes, the driver searches for a characteristics record for the LAT port named LTAO. If it finds one, the user-defined procedure show _la(JJort is invoked. You can also access a LAT port's mapping information by calling the port utility procedure ELN$LAT_SHOW_PORT_MAPPING. A call to this procedure specifies a. port connected in a circuit to the LAT port's DDA port. Other arguments receive the LAT port's name, type, and queue status, and depending on the port's mapping, a remote terminal server name, a remote port name, and a service name. The following sections give more information about LAT port names, queue statuses, remote server names, and remote port names. For information about service names, see Section 11.3.2.1. 11.3.3.1 LAT Port Names VAXELN LAT port names are strings that can consist of up to 16 of the following ASCII characters: • • • Alphanumeric characters - A to Z, a to z, and 0 to 9 A subset of the international character set - decimal character values 192 to 253 Punctuation characters - dollar sign ($), hyphen (-), period (.), and underscore (_) A service node's LAT port names must be unique. 11-24 LAT Host Services 11.3.3.2 Queue Statuses A LAT port's queue status indicates whether connection requests to a remote device port or service are to be queued. If the remote port is busy and queuing is enabled on the terminal server and the VAXELN service node, the remote request is queued. If queuing is disabled, the terminal server rejects connection requests when the device or service is busy. 11.3.3.3 Remote Server Names A remote server name is a string of up to 255 characters that identifies a terminal server that supports an application device or service. You get a remote server name from the terminal server manager. 11.3.3.4 Remote Port Names A remote port name is a string of up to 255 characters that identifies a terminal server port that supports an application device or service. You get a remote port name from the terminal server manager. 11.3.4 Retrieving Terminal Server Characteristics When an application program establishes a virtual circuit with a remote terminal server, the server becomes known to the service node. The LAT driver creates a terminal server characteristics record for each known terminal server. A terminal server characteristics record stores the following characteristics: • • • • • Name State (active or inactive) Address Number of active users Link name An active terminal server is connected to a VAXELN service node. Inactive servers are known to the service node, but are not connected to the node. LAT Host Services 11-25 An application program can retrieve the characteristics of terminal servers known to a service node by calling the ELN$LAT_SHOW_ SERVERS procedure. This procedure allocates a characteristics record from which the application program can retrieve the characteristics. A call to ELN$LAT_SHOW_SERVERS must specify the port connected in a circuit to a LAT control port, a Boolean value that indicates whether the driver is to return characteristics for active and inactive servers, and the name of a user-specified procedure to be invoked by ELN$LAT_SHOW_SERVERS. For example: VAR lat_ctrl-port : PORT; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT(lat_ctrl-port~ DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_SHOW_SERVERS(CIRCUIT := lat_ctrl-port, INACTIVE := TRUE, SHOW_SERVER := show_lat_server); END. PROCEDURE show_lat_server OF TYPE LAT$SHOW_PORT_ROUTINE; BEGIN WITH server_characteristics A DO BEGIN WRITELN (' Server name = " SERVER_NAME); WRITE('Server is '); IF active THEN WRITELN('active') ELSE WRITELN('inactive'); END; END; The ELN$LAT_SHOW_SERVERS procedure invokes the user-specified procedure for all known servers or only active servers, depending on the value of the inactive argument. When the call to ELN$LAT_ SHOW_SERVERS in the preceding example executes, the driver uses 11-26 LAT Host Services the show_lat_server procedure to return server characteristic records for known terminal servers. 11.3.5 Monitoring LAT Network Performance and Error Statistics The LAT driver maintains performance and error counters for a service node and the terminal servers logically connected to a service node. The LAT driver stores the following counters in node, server, and device counter records: Node Counters Server Counters Device Counters Circuit timeouts Invalid messages Line name Discarded output bytes Invalid slots Seconds since last zeroed Last transmit failure Out-of-sequence frames Receive frames No transmit buffer Receive frames Receiv~ multicast frames Retransmissions Receive errors Protocol bit mask Server name Bytes received Receive frames Transmit frames Multicast bytes received Protocol errors Receive errors Data overruns Receive duplicates Local buffer errors Resource errors Transmit frames Retransmissions Transmit multicast frames Solicitation failures Frames sent, multiple collisions Transmit frames Frames sent, single collision Transmit errors Frames sent, initially deferred Unit timeouts Bytes sent Multicast bytes sent Transmit errors LAT Host Services 11-27 Node Counters Server Counters Device Counters Transmit collisions detect check failure Unrecognized frame destination User buffer unavailable Receive errors bit mask Transmit errors bit mask An application program can monitor these counters by calling the ELN$LAT_CLEAR_COUNTERS and ELN$LAT_SHOW_COUNTERS procedures. Use the ELN$LAT_CLEAR_COUNTERS procedure to initialize the node counters. You can then call ELN$LAT_SHOW_ COUNTERS at various points in the program to retrieve various counter values. The ELN$LAT_SHOW_COUNTERS procedure allocates a record for the type of counter the application program is to access. A call to the procedure must specify the port connected in a circuit to a LAT control port, a counter type, a Boolean value that indicates whether the driver is to return counters for active and inactive servers (if you specify the server counter type), and the name of a user-specified procedure to be invoked by ELN$LAT_SHOW_COUNTERS. For example: VAR lat_ctrl-port : PORT; link_name LAT$LINK_NAME; BEGIN CREATE_PORT(lat_ctrl-port); CONNECT_CIRCUIT (lat_ctrl-port, DESTINATION NAME := '$LAT_CONTROL'); ELN$LAT_SHOW_COUNTERS(CIRCUIT := lat_ctrl-port, COUNTER_TYPE := LAT$SERVER, INACTIVE := FALSE, LINK := link name, SHOW_COUNTER-:= show_server_counters); END. 11-28 LAT Host Services PROCEDURE show_server_counters OF TYPE LAT$SHOW_COUNTER_ROUTlNE; BEGIN WITH server counters A DO BEGIN WRITELN (' Server name =' SERVER_NAME); END; END; When the call to ELN$LAT_SHOW_COUNTERS in the preceding example executes, the driver uses the show_server_counters procedure to return server counter records for active terminal servers. If you specify the counter type LAT$NODE, the ELN$LAT_SHOW_ COUNTERS procedure invokes the user-declared procedure to return a service node counter record. Similarly, if you specify the counter type LAT$DEVICE, the procedure invokes the user-declared procedure to return device counter records. 11.4 Setting Up a Dedicated Service Environment The VAXELN LAT host services provide support that lets a VAXELN service node offer user-created dedicated services, such as data entry and on-line status programs, to terminal server users. When you create a service on a VAXELN service node, that service offers ECL by default. To offer a dedicated service instead of ECL, you must associate the service with a dedicated port. You initiate a connection to a dedicated service running on a VAXELN service node from a device attached to a terminal server, as shown in Figure 11-3. To make a service other than ECL available to a terminal attached to a terminal server, you must do the following: 1. Connect to a LAT control port 2. Create a service 3. Create a dedicated LAT port LAT Host Services 11-29 Figure 11-3: Dedicated Service Environment VAXELN Service Node VAXELN LAT Host Services ....._+-__ Dedicated LAT Port t Direction of I connection request Interactive terminal accessing a dedicated service MLO-004290 4. Associate the dedicated LAT port with the service 5. Access the dedicated LAT port from an application program 6. Request notification of a terminal server connection (optional) The rest of this section uses the sample application module sample_ lat_dedic_srvc and callout text to illustrate these steps. The module executes as one job of a two-job application that offers the VAXELN Display Utility as a dedicated service to terminal server users. The sample module creates a LAT service named EDISPLAY and the dedicated LAT port LTAO. The module then associates the LAT port with the service EDISPLAY. Once the port/service association is made, the module activates the LAT protocol. U sing the protocol, the LAT driver multicasts service announcement messages to terminal servers in the LAT network, advertising the EDISPLAY service. While the driver multicasts these messages, the application module waits for a terminal server user to 11-30 LAT Host Services connect to the service. When a connection is established, the application module creates the EDISPLAY job and then waits for that job to execute. When the terminal server user exits the Display Utility, the application module waits for another connection request. Example 11-1 assumes that the LAT driver is built into the VAXELN system with the LAT protocol inactive. It also assumes that the LAT application module sample_laCdedic_srvc is built into the system" with the initial state set to RUN and that EDISPLAY is built into the system with the initial state set to ...1VORUN. Example 11-1: LAT Dedicated Service MODULE sample_lat_dedic_srvc; INCLUDE $LAT_UTILITY, $KERNELMSG; PROGRAM example (INPUT, OUTPUT); VAR lat_control-port, dda_interface-port job-port, edisplay_exit-port : PORT; link names : LAT$LINK NAME LIST; stat-: INTEGER; -mid : MESSAGE; mptr : AINTEGER; PORT; BEGIN { Create a VAXELN message port, then connect that port in a circuit to { a LAT control port. o CREATE_PORT(lat_control-port ); CONNECT_CIRCUIT (lat.:...control-port, DESTINATION NAME:= o '$LAT_CONTROL'); { Create the LAT service that is to offer EDISPLAY. ELN$LAT_CREATE_SERVICE(CIRCUIT := lat_control-port, f) SERVICE_NAME := 'EDISPLAY', SERVICE_IDENT := 'VAXELN Display Utility', STATIC_SERVICE_RATING := FALSE, SERVICE_RATING := 0, LINK COUNT := 0, LINK NAMES := link_names); { Create a dedicated LAT port. } Example 11-1 Cont'd on next page LAT Host Services 11-31 Example 11-1 (Cont.): LAT Dedicated Service ELN$LAT_CREATE_PORT(CIRCUIT := lat_control-port, PORT TYPE := LAT$DEDICATED, PORT=NAME := 'LTAO'); { Associate the dedicated LAT port LTAO with the LAT service EDISPLAY. ELN$LAT_SET_PORT(CIRCUIT := lat_control-port, NEW FIELDS := [LAT$SET SERVICE], PORT_NAME : = 'LTAO', QUEUE := TRUE, REMOTE SERVER NAME : = " REMOTE-PORT NAME : = ", SERVICE NAME : = 'EDISPLAY', LINK_NAME := " ) ; { Activate the LAT protocol to advertise service. ELN$LAT_START_NODE(CIRCUIT := lat_control-port, LINK COUNT := 0, LINK NAMES := link_names); { Access the LAT port. } CREATE_PORT(dda_interface-port); CONNECT_CIRCUIT (dda_interface_port, DESTINATION_NAME := 'LTAO$ACCESS', STATUS : = stat); { Create a port to be notified when EDISPLAY exits. CREATE_PORT(edisplay_exit-port); WHILE TRUE DO BEGIN { Wait for a terminal server user to connect to the EDISPLAY service. ELN$LAT_WAIT_FOR_CONNECTION(CIRCUIT := dda_interface-port, STATUS : = stat); ~ { { { { If the wait fails because the terminal server user disconnected the session, reestablish a circuit connection with the LAT port's DDA port. o Example 11-1 Cont'd on next page 11-32 LAT Host Services Example 11-1 (Cont.): LAT Dedicated Service IF stat = KER$_DISCONNECT THEN BEGIN DISCONNECT_CIRCUIT(dda_interface-port); CONNECT_CIRCUIT (dda_interface-port, DESTINATION NAME := 'LTAO$ACCESS', STATUS : = stat); ELN$LAT WAIT_FOR_CONNECTION(CIRCUIT := dda_interface-port, STATUS : = stat); END; If an error occurs, terminate this job. IF NOT(ODD(stat» THEN BEGIN WRITELN('Exiting, status is: EXIT(EXIT_STATUS := stat); END; stat: 1); Run EDISPLAY on the VAXELN LAT port and wait for it to complete. IF ODD (stat) THEN CREATE_JOB (job-port, 'EDISPLAY' , 'LTAO:' , Program argument 1 'LTAO:' , Program argument 2 'LTAO:' , Program argument 3 NOTIFY := edisplay_exit-port, STATUS := stat); IF ODD (stat) THEN BEGIN { Wait for the EDISPLAY job to terminate. } WAIT_ANY(edisplay_exit-port); ~ RECEIVE (mid, mptr, edisplay_exit-port, STATUS := stat); DELETE (mid, STATUS := stat); { Disconnect the session with the terminal server user. } ELN$LAT_DISCONNECT_PORT(CIRCUIT := dda_interface-port, ~ STATUS : = stat); END; END; END. {P rogram END; {Module} LAT Host Services 11-33 o Connect to a LAT control port. Create a VAXELN message port and connect that port in a circuit to a LAT control port. The sample module creates the message port lat_controlJlort and connects that port in a circuit to the local control port $LAT_ CONTROL. For information about connecting to a LATcontrol port, see Section 11.2.1. @ Create a service. Create a service to be offered by the service node by calling the ELN$LAT_CREATE_SERVICE procedure. The sample module creates the service named EDISPLAY. The procedure call specifies FALSE for the static service rating argument. Thus, the LAT driver will calculate the service rating dynamically. For information about services, see Section 11.3.2. 6) Create a dedicated LAT port. Create a dedicated LAT port by calling the ELN$LAT_CREATE_PORT procedure with the port type LAT$DEDICATED. The sample module creates a dedicated LAT port named LTAO. The LAT driver creates a DAP message port and a DDA message port for the LAT port and associates the ports with the names LTAO and LTAO$ACCESS. For information about creating LAT ports, see Section 11.2.2. o Associate the dedicated LAT port with the service. Associate the dedicated LAT port with the service by calling the ELN$LAT_ MAP_PORT or ELN$LAT_SET_PORT procedure. Use ELN$LAT_ SET_PORT to make the association using the LAT control interface. Use ELN$LAT_MAP_PORT to associate the port and service using the DDA interface. A call to the ELN$LAT_SET_PORT procedure must specify the port connected in a circuit to a LAT control port, the name of a LAT port, and a value for a new fields argument. You can change the LAT port's queue status, remote server.name, remote port name, and service name. The new fields argument identifies the LAT port characteristics you will be changing. You must also specify a link argument. This argument is reserved for future use. The call to ELN$LAT_SET_PORT in the sample module associates the LAT port LTAO with the service EDISPLAY. A call to the ELN$LAT_MAP_PORT procedure must specify the port connected in a circuit to a LAT port's DDA port and a value for a new fields argument. You can also change the LAT port's queue status, remote server name, remote port name, and service name. The new fields argument identifies the LAT port characteristics you will be changing. 11-34 LAT Host Services The following procedure call makes the same association using the LAT port's DDA interface: ELN$LAT_MAP_PORT(CIRCUIT := dda_interface-port, NEW_FIELDS := [LAT$SET_SERVICE], QUEUED STATUS := TRUE, REMOTE- SERVER NAME : = ", REMOTE=PORT_NAME : = ", SERVICE_NAME := 'EDISPLAY'); o o Activate the LAT protocol. Advertise the service node's services by activating the LAT protocol with a call to ELN$LAT_START_ NODE. When you activate the protocol, the driver starts advertising services in announcement messages that it multicasts to the terminal servers in the LAT network. The call to ELN$LAT_ START_NODE in the sample module causes the LAT driver to activate the LAT protocol. The driver then starts advertising the service EDISPLAY. You can skip this step if the LAT protocol is already active. Access the dedicated LAT port from the application pro~ gram. An application program running on the service node can access a dedicated LAT port by using a call to a language-dependent open statement or a call to CONNECT_CIRCUIT. Use a call to an open statement to perform file- and record-oriented I/O operations. Your application program accesses the LAT port's DAP port to process these I/O requests. Use a call to CONNECT_CIRCUIT to connect to the LAT port's DDA port. You need to connect to the DDA port to perform operations that involve accessing serial line devices or managing a VAXELN LAT port connection to a remote terminal server port. The sample module uses a call to CONNECT_CIRCillT to establish a circuit connection with the DDA port LTAO$ACCESS. For information about connecting to a LAT port's DDA port, see Section 11.2.3. f) Request notification of a terminal server connection. A dedicated service application program can request notification of a terminal server connection by calling the ELN$WAIT_FOR_ CONNECTION port utility procedure. A call to this procedure causes your program to wait for a connection to be established between a dedicated LAT port and a terminal server port. The application program unblocks when the terminal server connects to the service node. LAT Host Services 11-35 e CD G> A call to ELN$LAT_WAIT_FOR_CONNECTION procedure must specify a port connected in a circuit to the LAT port's DDA port. Since the sample module established a circuit between the port dda_interfaceJJort and the DDA port LTAO$ACCESS, it can call ELN$WAIT_FOR_CONNECTION by specifying the port dda_ interfaceJJort. Create a job for the service. The sample module creates ajob for EDISPLAY, specifying the LAT port name as program arguments. Wait for the job to terminate. Wait for the job to terminate by specifying the service's exit port in a WAIT_ANY procedure call. The sample module waits on the exit port edisplay_exit..]Jort. Disconnect the session between the service~ode and terminal server. A session between a dedicated LAT port and a terminal server's device port terminates when one of the following occurs: • The terminal server user disconnects the session (for example, by logging out). • All open files to the dedicated LAT port are closed, and all DDA circuit connections to the dedicated LAT port are disconnected. • The application program forces a disconnection by calling the ELN$LAT_DISCONNECT_PORT port utility procedure. An application program can force a session to disconnect a dedicated LAT port from a remote terminal server port by calling the ELN$LAT_DISCONNECT_PORT port utility procedure. The procedure call must specify the port connected in a circuit to the LAT port's DDA port. When a session terminates, all open files are closed and all DDA circuit connections between application programs and the dedicated LAT port on the service node are terminated. 11.5 Setting Up an Application Device Environment The VAXELN LAT driver supports access to remote application devices attached to terminal servers. For example, application programs running on VAXELN service nodes in a LAT network can share a remote printer. 11-36 LAT Host Services To access an application device, an application program associates a remote terminal server port with an application LAT port. As shown in Figure 11-4, once a program running on a service node makes the port association, it can initiate a connection to the terminal server to which the application LAT port is associated. Figure 11-4: Application Device Environment VAXELN Service Node VAXELN LAT Host Services Application device I Direction of +connection request MLO-004291 To communicate with a remote application device, you must do the following: 1. Create an application LAT port 2. Access the application LAT port from the application program 3. Associate the application LAT port with a terminal server device port or service 4. Issue a connection request to establish a session with the remote terminal server port LAT Host Services 11-37 The rest of this section uses the sample application module sample_ lat_app_device and callout text to illustrate these steps. The module executes as one job of a two-job application. This application uses a terminal attached to a terminal server as a device that displays VAXELN Display Utility output. The sample module creates the application LAT port LTAO. The module then accesses the LAT port by connecting to the LAT port's DDA port. The module then associates the application LAT port with a port on a terminal server. Once the port/device association is made, the module activates the LAT protocol, allowing the service node and terminal server to communicate. Example 11-2 assumes that the LAT driver is built into the VAXELN system with the LAT protocol inactive. It also assumes that the LAT application module sample_lat_dedic_srvc is built into the system with the initial state set to RUN and that EDISPLAY is built into the system with the initial state set to NORUN. Example 11-2: LAT Application Service MODULE sample_lat_app_device; INCLUDE $LAT_UTILITY; PROGRAM example (INPUT, OUTPUT); VAR lat_control-port, dda_interface-port job-port, edisplay_exit-port : PORT; link names : LAT$LINK NAME LIST; stat~ reject reason :-INTEGER; mid : MESSAGE; mptr : AINTEGER; PORT; BEGIN { Create a VAXELN message port, then connect that port in a circuit { to a LAT control port. o CREATE_PORT(lat_control-port ); CONNECT_CIRCUIT (lat_control-port, DESTINATION NAME:= { Create an application LAT port. } Example 11-2 Cont'd on next page 11-38 LAT Host Services o '$LAT_CONTROL'); Example 11-2 (Cont.): LAT Application Service ELN$LAT_CREATE_PORT(CIRCUIT := lat_control-port, PORT TYPE := LAT$APPLICATION, PORT-NAME := 'LTAO'); { Activate the LAT protocol. } ELN$LAT_START_NODE(CIRCUIT := lat_control-port, LINK COUNT := 0, LINK NAMES := link_names); { Access the LAT port. } CREATE_PORT(dda_interface-port); CONNECT_CIRCUIT (dda_interface-port, DESTINATION NAME := 'LTAO$ACCESS', STATUS := stat); { Create a port to be notified when EDISPLAY exits. CREATE_PORT(edisplay_exit-port); { Associate the application LAT port LTAO with the remote terminal { server port PORT_2. {} ELN$LAT_MAP_PORT(CIRCUIT := dda_interface-port, ~ NEW_FIELDS := [LAT$SET_QUEUED_STATUS, LAT$SET_PORT], QUEUED STATUS := TRUE, REMOTE-SERVER NAME : = 'LAT100', REMOTE-PORT NAME : = 'PORT 2', SERVICE_NAME := " ) ; { Issue a connection request to connect the application LAT port { with a remote terminal server port. o ELN$LAT_CONNECT PORT (CIRCUIT := dda_interface-port, REJECT REASON := reject reason, STATUS-:= status); IF ODD (stat) THEN BEGIN { If the connection was established, execute the Display { Utility on the application LAT port. o Example 11-2 Cont'd on next page LAT Host Services 11-39 Example 11-2 (Cont.): LAT Application Service CREATE_JOB (job-port, 'EDISPLAY' , 'LTAO:', { Program argument 1 'LTAO:', { Program argument 2 'LTAO:', { Program argument 3 NOTIFY := edisplay_exit-port, STATUS : = stat); IF ODD (stat) THEN BEGIN { An EDISPLAY job was created successfully. { to complete. Wait for it {} WAIT_ANY(edisplay_exit-port); RECEIVE(mid, mptr, edisplay_exit-port, STATUS := stat); DELETE (mid, STATUS := stat); { Disconnect the session with the terminal server. } ELN$LAT_DISCONNECT_PORT(CIRCUIT := dda_interface-port, ~ STATUS : = stat); END; END. END; END; {Program} {Module} o Connect to a LAT control port. Create a VAXELN message port and connect that port in a circuit to a LAT control port. The sample module creates the message port lat_controtport and connects that port in a circuit to the local control port $LAT_ CONTROL. For information about connecting to a LAT control port, see Section 11.2.1. @ Create an application LAT port. Create an application LAT port by calling the ELN$LAT_CREATE_PORT procedure with the port type LAT$APPLI CATI ON. The sample module creates an application LAT port named LTAO. The LAT driver creates a DAP message port and a DDA message port for the LAT port and associates the ports with the names LTAO and LTAO$ACCESS. For information about creating LAT ports, see Section 11.2.2. 11-40 LAT Host Services 6) Activate the LAT protocol. Activate the LAT protocol with a call to ELN$LAT_START_NODE. When you activate the protocol, the driver starts advertising services in service announcement messages that it multicasts to the terminal servers in the LAT network. The call to ELN$LAT_START_NODE in the sample module causes the LAT driver to activate the LAT protocol. e o You can skip this step if the LAT protocol is already active. Access the application LAT port from the application program. Use a call to CONNECT_CIRCUIT to connect the VAXELN message port to the LAT port's DDA port. The DDA port provides an interface for operations that access serial line devices or manage a VAXELN LAT port. The sample module creates the VAXELN message port dda_ interfaceJ)ort, then uses a call to CONNECT_CIRCUIT to connect that port in a circuit to the DDA port LTAO$ACCESS. For information about connecting to a LAT port's DDA port, see Section 11.2.3. Associate the application LAT port with the remote device. Associate an application LAT port with a remote device port or service on a terminal server by calling the ELN$LAT_MAP_PORT or ELN$LAT_SET_PORT procedure. Use ELN$LAT_SET_PORT to make the association using the LAT control interface. Use ELN$LAT_MAP_PORT to associate the port and service using the DDA interface. A call to the ELN$LAT_MAP_PORT procedure must specify the port connected in a circuit to a LAT port's DDA port and a value for a new fields argument. You can also change the LAT port's queue status, remote server name, remote port name, and service name. The new fields argument identifies the LAT port characteristics you will be changing. The call to ELN$LAT_MAP_PORT in the sample module associates the LAT port LTAO with the remote device port named PORT_2 on the terminal server LAT100. A call to the ELN$LAT_SET_PORT procedure must specify the port connected in a circuit to a LAT control port, the name of a LAT port, and a value for a new fields argument. You can also change the LAT port's queue status, remote server name, remote port name, and service name. The new fields argument identifies the LAT port characteristics you will be changing. Get the names of the remote terminal server and remote port by using the terminal server manager. LAT Host Services 11-41 You must also specify a link argument. This argument is reserved for future use. The following procedure call makes the same association from the LAT control port: . ELN$LAT_SET_PORT(CIRCUIT := lat_control-port, NEW FIELDS := [LAT$SET QUEUE STATUS, LAT$SET_PORT], PORT_NAME := 'LTAO', QUEUE := TRUE, REMOTE SERVER NAME : = 'LATl 00' , REMOTE-PORT NAME : = 'PORT 2', SERVICE NAME := " , LINK_NAME: : = "); (:) Connect to the application device. You can issue a connection request from the application LAT port to the remote device port on a terminal server with a call to the ELN$LAT_CONNECT_PORT procedure. In the procedure call, you specify the port connected in a circuit to the LAT port's DDA port. The sample module connects the LAT port LTAO to the device port PORT_2. A call to ELN$LAT_CONNECT_PORT causes the LAT driver to send a request to a terminal server to establish a session between the service node and a terminal server device port or service. If the terminal server establishes a session, the LAT port is ready to be used for I/O and DDA operations. If the server rejects the connection request or if the request times out, the server returns an error code that identifies the reason for the connection failure. 8 The LAT driver initiates connection requests automatically when an application program performs read and write operations, if an application LAT port is associated with a terminal server and is not already connected in a session. However, if an automatic connection attempt fails, the 1/0 operation returns the status value ELN$DNR. It does not identify the reason for the connection failure. Disconnect the session between the service node and terminal server. An application program disconnects a session between an application LAT port and a terminal server's device port by calling the ELN$LAT_DISCONNECT_PORT port utility procedure. The procedure call must specify the port connected in a circuit to the LAT port's DDA port. When a session terminates, ·all open files are closed and all DDA circuit connections between application programs and the application LAT port on the service node are terminated. 11-42 LAT Host Services A session is also terminated if all open files are closed and all DDA circuit connections are disconnected. 11.6 Retrieving and Setting Terminal Characteristics The VAXELN LAT driver supports the DDA interface procedures ELN$TTY_GET_CHARACTERISTICS and ELN$TTY_SET_ CHARACTERISTICS. An application program can use a VAXELN LAT port's DDA port in a call to ELN$TTY_GET_CHARACTERISTICS to retrieve the following characteristics for that LAT port: • • • • • • • • • • • • • • Terminal type Speed Parity Parity type Display type Escape recognition Echo Passall Eight-bit Display type Character size Terminal synchronization Modem DDCMP Similarly, a program can use a VAXELN LAT port's DDA port in a call to ELN$TTY_SET_CHARACTERISTICS to set the following subset of these characteristics, which includes escape recognition, echo, passall, eight-bit, display type, and terminal synchronization. For more information about retrieving and setting terminal characteristics, see Section 14.4.5.2. LAT Host Services 11-43 Chapter 12 System Security The VAXELN Toolkit includes system security features that protect system resources and data from unauthorized use, examination, or modification. Since VAXELN is primarily for developing and running dedicated applications, the security features are disabled by default for programs running on a single system. You might use these features, however, to protect an application from inexperienced or malicious users. This chapter provides an overview of the security features that the VAXELN Toolkit supplies (see Section 12.1) and describes the following: • • • • User names and identification codes, Section 12.2 Authorization Service, Section 12.3 User identities, Section 12.4 File service security, Section 12.5 12.1 Security Features Overview The VAXELN Toolkit provides security features that application designers must explicitly include and enable. If, for example, a VAXELN system is to be included as part of a larger network of systems, the system would normally include the security features. Since VAXELN is not intended to provide a multiuser time-sharing environment, no protection is enforced among programs running on a single system. That is, although the VAX. memory management ensures that incorrectly coded programs cannot accidentally modify the memory allocated to other programs, the VAXELN kernel and runtime services do not attempt to dictate which programs can run in kernel mode, System Security 12-1 alter priorities, stop and start program execution, or, in general, fairly distribute the resources of the single-node system. The programs running on a system control the resources of the system. Therefore, if a VAXELN application is potentially vulnerable to inexperienced or even malicious users, you should ensure that the application and the system are protected. Also, if protection of system resources is required, users should not be allowed to run their own programs. Many VAXELN systems are part of a larger network. Programs must protect the resources of these systems from use or abuse by other users of the network. In particular, programs that accept requests from other network nodes need to somehow determine the identity of the requestor. An example of a program with this requirement is the File Service, which needs to provide protection for the disk files that it services. The most basic security feature of a VAXELN system, therefore, provides the capability for a program to determine the identity of a user issuing a network request. This feature is provided by an optional service called the Authorization Service. The Authorization Service maintains a data base of the users authorized to use a particular VAXELN system or network of systems. When an application program accepts a circuit connection to handle a request, the program can query the data base to determine the identity of the requestor. Other VAXELN facilities use the Authorization Service to protect the resources and data that they control. The Network Service running on a particular node accepts incoming circuit connections only from authorized users in the Authorization Service's data base. The File Service provides read, write, and delete protection for files on disk volumes that it controls. The Authorization Service itself uses the data base to protect the data base. Likewise, application programs can use the service to protect their resources and data. 12.2 User Names and Identification Codes Each process in a VAXELN system has an associated user name string and a user identification code (UIC). These two values are maintained by the kernel and are inherited by a process from the process or job that created it. A process can also set its own user name and UI C to desired values by calling the KER$SET_USER kernel procedure (see Section 12.4). 12-2 System Security The mes are integer values that provide a shorthand way of identifying a user or group of users. mes can then be used by application programs to protect their resources. For example, the File Service stores a me with each file that is created. The File Service then uses the stored me, called the owner UIC, to determine whether a requestor should be allowed to access the file. The VAXELN use of mes is compatible with the VMS use. On VAXELN and VMS, me values are 32-bit longwords, partitioned into two 16-bit words. The least significant word is called the member number, and the most significant word is called the group number. me values are normally displayed in octal, in the format [groupnumber,member-numberJ - for example, [1,4J, [11,32J, [200,200J. The partitioning of the value into group/member fields allows groups of values to be associated with each other for protection. Also, group numbers less than or equal to octal 10 are considered part of the system groups. The use of VIes is explained in Section 12.5. A process can determine its own user name and me by calling the KER$GET_VSER kernel procedure. Since, as just described, the security features in VAXELN are based upon validating network requests, a process can also determine the user name and me of the process from which it has accepted a circuit connection. This capability is also provided by calling KER$GET_VSER, although the port object connected in the circuit is then one of the arguments. 12.3 Authorization Service The Authorization Service is the key component of the VAXELN security facilities. It protects system resources and data by maintaining a data base of a system's authorized users and identifying users who issue network requests. A target system can include local or network authorization services. When a system includes the network authorization services, it handles authorization for the nodes in a local area network that do not have their own service. At least one node in a local area network must include this service. If multiple nodes include the network authorization service and all nodes in the local area network use the same data base file, one target system acts as an authorization server and manages the data base while the other nodes serve as backups. By designating multiple authorization servers, you can preserve the application's security if the acting server shuts down. System Security 12-3 The Authorization Service's primary task is to determine the identity of the requestor of a network connection request. The service gets the requestor's host system user name and node name and looks them up in the authorization data base. The service can also accept a specific user name and password, or access control string, and look them up in the data base. Figure 12-1 and the accompanying text illustrate and explain how the service works. Figure 12-1: User: FRED Authorization Service Example DEPOT1 DOCK2 Application Application Network and Authorization Services Network and Authorization Services I"FRED,DEPOT1"1 1 MLO-004292 In Figure 12-1, a user named FRED is executing a program on a VAXELN node named DEPOTl. FRED issues a request for a service on another node named DOCK2, so the Network Service on node DEPOT1 sends a connection request message that identifies FRED and DEPOT1 to DOCK2. The DOCK2 Network Service then sends a request to its Authorization Service to verify that user FRED on node DEPOT1 is authorized to use the services provided by node DOCK2. The Authorization Service replies to the Network Service with a Yes or No indication; if Yes, the Authorization Service returns the UIC with which the user is to be identified. 12-4 System Security This type of authorization is termed proxy access control. Since FRED is authorized to use the resources of node DEPOT!, his DEPOT! name is sent, by network proxy, to determine if he can use the resources of node DOCK2. The other type of authorization provided by the Authorization Service is called destination authorization. It is used when a connection request or open file operation specifies a user name and password, or access control string, with the connection request. Destination authorization provides a means of assuming a new identity on the remote system. Proxy access control and destination authorization are provided in a compatible manner by the VMS operating system. Other Digital operating systems support only the destination authorization provided with access control strings. The CONNECT_CIRCillT procedure allows you to specify a remote destination as a string by using the optional DESTINATION_NAME parameter. Like other DECnet systems, the node specification for CONNECT_CIRCUIT can include a user name and password, which can be optionally enclosed in quotes and separated from each other by a space. To specify the remote destination by object name, use a string of one of the following forms: 'nodenumber::objectname' 'nodenumber"username password" ::objectname' 'nodenumber"username" ::objectname' 'nodenumber"[ggg,mmm] password"::objectname' For example, the following call connects to object TESTOR on node number 3, using a user name of FRED and a password of SWIZZLE: CONNECT_CIRCUIT(p, DESTINATION_NAME := '3"FRED SWIZZLE"::TESTOR'); To specify the remote destination by object number, use a string of one of the following forms: 'nodenumber: :objectnumber' 'nodenumber"username password" ::objectnumber' 'nodenumber"username" ::objectnumber' 'nodenumber"[ggg ,mmm] password"::objectnumber' System Security 12-5 For example, the following call connects to object number 129 on node 4, using a user name of [10,150] and a password of QUAKE. This format is typically used only to connect to RSTS/E systems. CONNECT_CIRCUIT (p, DESTINATION_NAME := '4" [10,150] QUAKE":: 129'); To connect to a port in a VAXELN system, use a string of one of the following forms: 'nodename::objectname' 'nodename"username password": :objectname' 'nodename"username": :objectname' 'nodename"[ggg,mmm] password"::objectname' 'nodename: :objectnumber' 'nodename"username password" ::objectnumber' 'nodename"username" ::objectnumber' 'nodename"[ggg,mmm] password"::objectnumber' For example, the following call would connect to object TEST on node NODEA, using a user name of FRED and a password of ABC: CONNECT_CIRCUIT(p, DESTINATION_NAME := 'NODEA"FRED ABC"::TEST'); Since the OPEN routine uses CONNECT_CIRCUIT to access remote files on other DECnet nodes, its FILE_NAME parameter can also include a user name and password if a node number is specified. For example, the following call would open FILE99.DAT on node number 3, using a user name of FRED and a password of SWIZZLE: OPEN(f, FILE NAME := '3"FRED SWIZZLE"::FILE99.DAT'); 12.3.1 Including the Authorization Service The Authorization Service is supplied as a program image that can be included in a VAXELN system using the System Builder. To include this service in a system, do the following: 1. Select Yes for the Authorization required entry on the Network Node Characteristics Menu. When you select Yes, the Network 12-6 System Security Service monitors inbound circuit connections and honors a connection only if it can authorize the user through the Authorization Service. 2. Select Local or Network for the Authorization service entry on the Network Node Characteristics Menu. When you select Local, the service is included in the system image but handles authorization for only the local target system. When you select Network, the service is included, and it handles authorization for any node in the local area network that does not have its own Authorization Service. The network Authorization Service uses VAXELN universal names. Thus, at least one system in the network must include the Name Service. Only one of the nodes can run the network Authorization Service, even if multiple nodes include the Name Service. 3. Specify an authorization data file for the Authorization :file entry on the Network Node Characteristics Menu. The data file must exist on the same node as the Authorization Service or on a node that the service is authorized to access, for example, a node with its own local service. The default file is [O,O]AUTHORIZE.DAT on the local default disk. When the Authorization Service starts running, it opens and reads the specified data file. If the data file is not found, the Authorization Service creates a new one. The file should be modified only by using the maintenance procedures described in Section 12.3.2. Typically, the authorization data file is on a disk directly attached to the node running the Authorization Service. In such a case, when the file is first created by the service, it can be modified only by users running programs on the same node. That is, since the data file is empty, no remote users are authorized to access the node. Once other users are authorized, if they have UIes in the system group, they can remotely maintain the authorization data file. 12.3.2 Authorization Service Utility Procedures The Authorization Service provides the capability to maintain the authorization data base. Since the Authorization Service can run as a server in a local area network, it performs the maintenance functions, using messages and its own maintenance request protocol. To simplify the development of maintenance programs, the VAXELN System Security 12-7 Toolkit includes a set of utility procedures that handle the protocol, eliminating the need for user programs to code the protocol explicitly. The Authorization Service utility procedures are as follows: Routine Description Adds a new user record to the authorization data base. ELN$AUTH_MODIFY_USER Modifies a user record in the authorization data base. Removes a user record from the authorization data base. Returns the authorization data base information for the specified users. To use the Authorization Service utility procedures, your program must be authorized with a system group UIC - that is, a mc that is less than or equal to %X0008FFFF or [10,177777]. You must also include the $AUTHORIZE_UTILITY module in the compilation. For descriptions of these routines, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 12.3.3 Establishing Circuits for Authorization Service Communication An application program communicates with the Authorization Service using a VAXELN virtual circuit. The program must establish the circuit connection by creating a port and connecting that port to' Authorization Service's AUTH$MAINTENANCE port. Once the connection is made, the program can call the Authorization Service utility procedures to set up and access the authorization base. The following Pascal example connects the port authorization-port in a circuit to the AUTH$MAINTENANCE port. MODULE test_authorization; INCLUDE $AUTHORIZE_UTILITY; PROGRAM authorization_maintenance; 12-8 System Security VAR authorization-port PORT; BEGIN CREATE_PORT(authorization-port ); CONNECT_CIRCUIT (authorization-port, DESTINATION NAME := 'AUTH$MAINTENANCE'); END; END. Once the connection between authorization-port and the authorization maintenance port is established, the program can call the Authorization Service utility routines, specifying authorization-port as an argument. 12.3.4 Adding Users to the Authorization Data Base To add new user records to the authorization data base, call the ELN$AUTH_ADD_USER procedure. A call to ELN$AUTH_ ADD_USER must specify the port connected in a circuit to the AUTH$MAINTENANCE port, a user name, a node name, a password, a user identification code, and user data. The user name can specify a name, a null string, or the reserved word $ANY. If you specify $ANY, any user from the specified node that does not match one the explicit user names is authorized with the specified user identification code. The node name argument specifies the name or number of the node on which the new user is authorized. You can specify a node name, node number, a null string, or the reserved name $ANY. • • If you specify a node name or number, the data base record represents a proxy access control, and the Authorization Service does not use the password. If you specify a null string, the data base record represents a destination authorization. System Security 12-9 • If you specify $ANY, any user with the specified name from any node that does not match one of the explicit node names is authorized with the specified user identification code. You can specify a password or null string for the password argument. If you add a destination authorization record to the data base (that is, if you specify a null string for the node name), the Authorization Service stores the password in the record. The Authorization Service stores all passwords in scrambled form so they cannot be read once they are stored. You must specify a user identification code for each new user. A user data argument lets you store unmodified user-defined data in a user record. If you do not need to store such data, you can specify a null string. The following section of Pascal code adds a new record to the authorization data base for user FRED: VAR authorization-port node user uic node BEGIN PORT; AUTH$NODENAME; AUTH$USERNAME; INTEGER; AUTH$NODENAME; CREATE_PORT(authorization-port ); CONNECT_CIRCUIT (authorization-port, DESTINATION NAME := 'AUTH$MAINTENANCE'); user := 'FRED'; node := 'DEPOT1'; uic := %X00010002; ELN$AUTH_ADD_USER(CIRCUIT := authorization-port, USERNAME := user, NODENAME := node, PASSWORD := UIC := uic, USERDATA := 'f); END; END. 12-10 System Security The call to ELN$AUTH_ADD_USER adds user FRED to the data base with authorization on node DEPOT1 and the user identification code %X00010002. Since a node name is specified, the record represents a proxy access control. Thus, a null string is specified for the password argument. The call also omits user data by specifying a null string for that argument. For information about establishing a circuit with the AUTH$MAlNTENANCE port, see Section 12.3.3. For a description of the ELN$AUTH_ADD_USER procedure, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 12.3.5 Modifying Records in the Authorization Data Base To modify user records in the authorization data base, call the ELN$AUTH_MODIFY_USER procedure. A call to ELN$AUTH_ MODIFY_USER must specify the port connected in a circuit to the AUTH$MAlNTENANCE port, a user name, and a node name. You must also specify a new fields argument that identifies the record fields that you intend to modify and new values for the user name, node name, password, user identification code, and user data, as appropriate. The user name and node name arguments specify the name of the user whose record is to be modified and the name or number of the node on which that user is authorized. The new fields argument identifies the user record fields you will be changing: user name, node name, password, user identification code, or user data. You can modify fields without changing other fields in the record. To change a record, you must indicate the appropriate fields in the value you specify for this argument and specify values for the fields you are changing. The call to ELN$AUTH_MODIFY_USER in the following section of code changes the node for user FRED: System Security 12-11 VAR authorization-port node user uic new_node BEGIN PORT; AUTH$NODENAME; AUTH$USERNAME; INTEGER; AUTH$NODENAME; CREATE_PORT(authorization-port ); CONNECT_CIRCUIT (authorization-port, DESTINATION NAME := 'AUTH$MAINTENANCE'); user := 'FRED'; node := 'DEPOT1'; new node := 'DEPOT2'; uic-:= %X00010002; ELN$AUTH_MODIFY_USER(CIRCUIT := authorization-port, USERNAME := user, NODENAME := node, NEW_FIELDS := [AUTH$NODENAME_FIELD], NEW USERNAME : = " NEW NODENAME := new_node, NEW PASSWORD : = " NEW:=UIC := " , NEW USERDATA : = "); END; END. You can specify a new user name or the reserved name $ANY. If you specify $ANY, any user from the specified node that does not match one of the explicit user names is authorized with the specified user identification code. If you modify the user name, you must reset the password. The value for the new node name argument can be a node name, a node number, a null string, or the reserved name $ANY. If you specify a node name of number, the data base record represents a proxy access control and the Authorization Service does not use the password. If you specify a null string, the data base record represents a destination authorization. If you specify $ANY, any user with the specified name from any node that does not match one of the explicit node names is authorized with the specified user identification code. 12-12 System Security The hashing algorithm that the Authorization Service uses for passwords includes the user name. Thus, you must reset the password if you modify the user name. You can reset a password to another password or to a null string. If you add a destination authorization record to the data base (that is, if you specify a null string for the node name), the Authorization Service stores the password with the record. The Authorization Service stores all passwords in scrambled form so they cannot be read once they are stored. To establish a circuit with the AUTH$MAINTENANCE port, see Section 12.3.3. For a description of the ELN$AUTH_MODIFY_USER procedure, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 12.3.6 Removing User Records from the Authorization Data Base To remove user records from the authorization data base, call the ELN$AUTH_REMOVE_USER procedure. A call to ELN$AUTH_ REMOVE_USER must specify the port connected in a circuit to the AUTH$MAINTENANCE port, a user name, and a node name. The user name identifies the user record to be removed. The node name argument specifies the name or number of the node on which the user is no longer authorized. The call to ELN$AUTH_REMOVE_USER in the following section of Pascal code removes user FRED from the data base: VAR authorization-port node user uic node BEGIN PORT; AUTH$NODENAME; AUTH$USERNAME; INTEGER; AUTH$NODENAME; . CREATE_PORT(authorization-port ); System Security 12-13 CONNECT_CIRCUIT (authorization-port, DESTINATION NAME := 'AUTH$MAINTENANCE'); user : = , FRED' ; node := 'DEPOT1'; uic := %X00010002; ELN$AUTH_REMOVE_USER(CIRCUIT := authorization-port, USERNAME := user, NODENAME := node); END; END. To establish a circuit with the AUTH$MAINTENANCE port, see Section 12.3.3. For a description of the ELN$AUTH_REMOVE_USER procedure, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 12.3.7 Retrieving Authorization Data Base Information To retrieve information from the authorization data base, call the ELN$AUTH_SHOW_USER procedure. A call to ELN$AUTH_ SHOW_USER must specify the port connected in a circuit to the AUTH$MAINTENANCE port, a user name, a node name, and the name of a show user procedure. The user name specifies the name of the user for which data base information is to be accessed. If you specify the string '*', the procedure returns all the records in the data base. The node name argument specifies the name or number of the node on which the user is authorized. You must specify a nonnull string if the proxy information for the specified users is requested, in which case the Authorization Service returns the proxy information. The show user routine is a user-defined routine that the ELN$AUTH_ SHOW_USER procedure invokes. The procedure invokes your routine only if it finds the specified user entry in the authorization data base. If you specify the string ,*, for the user name, ELN$AUTH_SHOW_ USER calls your routine once for each record in the data base. 12-14 System Security The call to ELN$AUTH_SHOW_USERS in the following section of Pascal code instructs the Authorization Service to invoke the procedure show_all_users for all records in the authorization data base: VAR authorization-port uic node BEGIN PORT; INTEGER; AUTH$NODENAME; CREATE_PORT(authorization-port ); CONNECT_CIRCUIT (authorization-port, DESTINATION NAME := 'AUTH$MAINTENANCE'); node := 'DEPOT1'; uic := %X00010002; ELN$AUTH_SHOW_USER(CIRCUIT := authorization-port, USERNAME : = , *, , NODE NAME := node, SHOW_USER := show_alI_users); END. PROCEDURE show all users OF TYPE AUTH$SHOW_USER_ROUTINE; BEGIN WRITELN('User name =', username A ) ; WRITELN('Node name =', nodename A ) ; WRITELN('UIC =', uic A ) ; END; For information about establishing a circuit with the AUTH$MAINTENANCE port, see Section 12.3.3. For a description of the ELN$AUTH_SHOW_USER procedure, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. System Security 12-15 12.4 User Identities The Network Service ensures that inbound connection requests are from authorized users. However, application programs that accept such requests should use calls to KER$GET_USER to query the user's identity and use the information to protect program resources. Each process in a VAXELN system has a user identity that consists of a user name and a UIC. The user name can be a string of up to 20 characters, and the mc is an integer. Using the KER$GET_USER and KER$SET_USER procedures, you can retrieve and set these values for a calling process. The KER$GET_USER procedure returns the user identity of one of the following: • • The calling process A process connected in a circuit to a port owned by a process in the current job To retrieve the user identity of a process whose port is connected to the calling process, you must specify that port in an optional circuit port argument. The port that you specify must be connected in a circuit that was established as follows: • • The process in the current job whose port is to be specified in the call to KER$GET_USER initiated the connection with a call to the CONNECT_CIRCUIT procedure. The process calling KER$GET_USER accepted the connection with a call to the ACCEPT_CIRCUIT procedure. If the appropriate circuit connection is established, the kernel returns the user name and UIC associated with the process that initiated the connection to optional user name and UIC arguments. If the appropriate circuit connection is not established, KER$GET_USER returns invalid user information. If the process that initiates the circuit connection is a remote process, you should ensure that the Authorization Service is built into your system. That is, you should select Yes for the Authorization required entry and Network for the Authorization service entry on the System Builder's Network Node Characteristics Menu. If you do not build the Authorization Service into the system, KER$GET_USER returns 0 to the UIC argument. 12-16 System Security The Network Service ensures that inbound connection requests are from authorized users. However, application programs that accept such requests must use calls to KER$GET_USER to query the user's identity and use the information to protect program resources. The following example accepts an inbound connection request and checks that it is from a user in a system group, less than or equal to octal 10: VAR np, p: PORT; username: VARYING_STRING(20); uic: INTEGER; ACCEPT CIRCUIT(np, CONNECT := p); KER$GET_USER(CIRCUIT := p, USERNAME := username, UIC := uic); IF (uic div %X10000) > %010 THEN DISCONNECT_CIRCUIT(p) ELSE To set the user identity of the current process, call the KER$SET_ USER procedure. Specify the user name and UIC that are to be associated with the process. The mc that the KER$SET_USER procedure sets is valid only on the local system. When you specify a remote destination port in a call to CONNECT_CIRCUIT, only the calling process's user name is sent to the destination system. The Authorization Service on the destination system adds that name to the authorization data base and associates the name with a new UIC. Calls to KER$GET_USER on the destination system then return the user name and new UIC as they are defined on that system. If you include an access control string in the remote destination argument that you specify in a call to CONNECT_CIRCUIT, the user name specified in the argument is sent to the remote system rather than the user name set with KER$SET_USER. The argument in the following call to CONNECT_CIRCUIT authorizes the user name FRED and password ABC on the remote system NODEA: CONNECT_CIRCUIT(DESTINATION_NAME := 'NODEA"FRED ABC"::TEST'); Calls to KER$GET_USER on the destination system get the authorized by the destination system. mc System Security 12-17 You can use the KER$SET_USER procedure to authorize a process's access requests to a remote system. Consider the following entries in the Authorization Service data base on node DOCK2. Authorization Type Host Node UIC Proxy access control DEPOT1 [1,2] Destination authorization SAM [1,3] Password NOODLE The first entry is a proxy access control because it includes a host node name. The second entry is a destination authorization because it includes a password instead of a node name. Suppose program A on node DEPOT1 executes the following: KER$SET USER(username := 'FRED'); CONNECT:CIRCUIT(destination_name := 'DOCK2::TESTOR'); When program B executes the following code on node DOCK2, the Authorization Service on node DOCK2 uses the proxy access control entry to authorize the remote user: CREATE NAME(p, 'TESTOR'); ACCEPT-CIRCUIT(p); KER$GET USER(CIRCUIT := p, USERNAME:= partner user, UIC := partner_uic); Program B receives a user name value of FRED in variable partner_ user and a UIC value of [1,2] (%X00010002) in variable partner_uic. Suppose, instead, that program A on node DEPOT1 executes the following: CONNECT_CIRCUIT (DESTINATION_NAME: : = , DOCK2" SAM NOODLE": : TESTOR' ) ; When Program B executes the following code on node DOCK2, the Authorization Service on node DOCK2 uses the destination authorization entry to authorize the remote user. CREATE_NAME(p, 'TESTOR'); ACCEPT CIRCUIT(p); KER$GET_USER(CIRCUIT := p, USERNAME := partner_user, UIC := partner_uic); Program B receives a user name value of SAM in variable partner_user and a UIC value of [1,3] (%X00010003) in variable partner_uic. 12-18 System Security 12.5 File Service Security The File Service uses the VAXELN features explained in this chapter to protect the disk volumes and files that the File Service manages. Since the File Service uses the Files-II on-disk structure, it uses the standard Files-II protection facilities. Those facilities are compatible with the VMS operating sysetm. The standard Files-II protection facilities are as follows: • • When a new file is created, one of its attributes is the primary ule of the user requesting the creation. This mc is called the owner Ule of the file. If the File Service is unable to determine the me of the user creating a new file (for example, no Authorization Service is available) the file owner ule is set to the mc of the disk volume owner. A new file also gets, as one of its attributes, a protection mask that describes how the File Service protects the file·from the folloWing categories of users: Category Description System Users with mcs with a group number less than or equal to 8 Owner Users with UICs that match the owner mc Group Users with UICs with a group number that matches the owner UIC's group number World Users with UICs in none of the previous categories The protection mask is a 16-bit word composed of four fields. Each of the four fields corresponds to one of the four categories of users. Each of the four fields consists of I-bit indicators that specify the access allowed to the category: read, write, execute, and delete. Figure 12-2 shows the protection mask. If a bit is set in a category's field, users in that category are denied the corresponding access. For example, if bit 1 is set, then system users are denied write access. System Security 12-19 Figure 12-2: Protection Mask 15 11 I 01 1 E WI R World I °i 7 E 3 0 i wi R I 01 E i WI R I 01 E 1wi R I Group Owner System MLO-004293 • • • • The Pascal programmer can specify the protection mask fields defined by the $FILE_UTILITY module. The C programmer typically specifies unsigned octal values. (For compatibility with UNIX systems, the C creat and chmod functions do not use the same format for the protection mask.) The owner and protection for a new file can be specified as parameters to the Pascal OPEN procedure and the C creat function. The protection for an existing file can be changed by using the Pascal PROTECT_FILE procedure and the C chmod and chown functions. If a new file is created and no protection mask is specified, the File Service sets the protection to the disk volume's default file protection. The owner UIC and protection mask for a new disk volume can be specified as a parameter to the ELN$INIT_VOLUME procedure. The default protection mask for files on a new disk volume can be specified as a parameter to the ELN$INIT_VOLUME procedure. If the File Service is unable to determine the mc of a user requesting access to a file (for example, no Authorization Service is available) it allows unprotected access by the user. (See the description of the Authorization required Network Node Characteristic in Section 12.3.1, for a means of preventing this unprotected access.) 12-20 System Security Chapter 13 File Service The File Service is a set of services provided by the disk and tape drivers in a system that allows programs to perform file-oriented I/O on disks and tapes. The File Service is not used for terminal or printer I/O. The File Service consists of a disk File Service and a tape File Service: • • The disk File Service provides Files-11 On-Disk Structure Level 2 file services. The disk File Service is compatible with the VMS Version 4.4 file system and with the RMS-32 system routines. The tape File Service is based on Version 3 of the ANSI standard for magnetic tapes. The tape File Service provides users with a convenient means of transporting files to and from VMS systems, since it is compatible with the VMS Version 4.4 file system. For disk and tape devices supported by Digital, the File Service is already linked with the VAXELN drivers. If you are writing your own disk or tape drivers that will use the File Service, the appropriate shareable image must be linked, as explained in Section 13.12. When several VAXELN systems are running on nodes in a local area network, only one node needs to have disk or magnetic tape hardware. An appropriate hardware configuration, running a system containing the File Service, thus can act as a file server for other jobs on the same node or on other nodes, handling all file storage and retrieval for the local area network. With disks, for example, programs can identify files, regardless of their network locations, by using file specifications that give the File Service volume name for the storage device; node specifications are needed only when you use a file that is stored on an operating system other than a VAXELN system. Systems that support file access from remote File Service 13-1 nodes also include a separate job, the File Access Listener, to handle connection requests between nodes. This chapter discusses the following: • • • • • • • • • • • • • 13.1 Device specifications, Section 13.1 Volume names, Section 13.2 File specifications, Section 13.3 Mount procedure for multiple volumes with identical volume labels, Section 13.4 Use of the DISK$DEFAULT_VOLUME device name, Section 13.5 File Access Listener, Section 13.6 Use of file service volumes from VMS, Section 13.7 File service operations, Section 13.8 File utility procedures, Section 13.9 Disk utility procedures, Section 13.10 Tape utility procedures, Section 13.11 File Service interface for disk and tape drivers, Section 13.12 Data Access Protocol, Section 13.13 Device Specifications You must provide descriptions of the devices to be used by a VAXELN system when you build the system by editing the System Builder's Device Description Menu, as explained in the VAXELN Development Utilities Guide. Each device name identifies a specific unit on a specific controller. Typically, the controller is specified by a letter and the unit by a number. For example, the device specification DQAl identifies controller A, unit 1, for an RB02 or RB80 disk attached to the Integrated Disk Controller of a VAX-11/730 processor. Table 13-1 lists the storage device types used in VAXELN programming. 13-2 File Service Table 13-1: Storage Device TYpes Device Type Meaning DQ VAX-ll/730 Integrated Disk Controller (RB02 cartridge disks and RB80 :fixed disks) . DD TU58 cartridge drive in VAX console DU UDA50 UNIBUS interface to Storage Interconnect (SI) disks, RQDXn (MicroVAX) interface to RXnn diskettes and RDnn Winchester disks, RC25 fixed and removable disks, KDA50 Q-bus RAxx-series disk adapter BD KDB50 BI RAxx-series disk adapter MU TK50 streaming cartridge tape drive, TK70 streaming cartridge tape drive, or TU81 reel tape system The device types in Table 13-1 are conventional names for these devices; you can use any names that you like, provided the usage is consistent in the System Builder and in user programs. 13.2 Volume Names After you enter the device specifications for the drives used by the File Service, you can supply volume names, or volume labels, for disks or tapes that are to be mounted by the service when the system is started. Volume names are specified on the System Builder's Edit System Characteristics Menu (see the VAXELN Development Utilities Guide). The volume name is paired with a device specification; the following System Builder menu argument establishes two such pairings: "DUAl TEST1", "DUAO TEST2" TEST1 is established as the volume to be mounted on drive DUAl and TEST2 as the volume for DUAO. The first volume mounted in the system becomes the default volume for the File Service. That is, any file specification that lacks a volume name or device name refers to this volume. In systems with a single disk controller, the first volume specified in the list (here, TEST1) will be the first volume mounted. In systems with multiple disk controllers, volumes are mounted in the order in which the disk driver jobs controlling their disks are created and initialized at system start-up. The order in which the driver jobs are created is determined by their job priority; the driver with the highest job priority is created first. If two or more drivers with the File Service 13-3 same priority exist, their jobs are created in the order in which they appear in the System Builder's program list, as shown in a full System Builder map. In this case, the default volume will be the first volume in the disk/volume name list that is associated with the first driver job to be initialized. The controller name (here, DUA) is also supplied as an argument to the driver. The VAXELN Development Utilities Guide explains how the controller device is described to the System Builder and how the appropriate driver is built into the system. The specified volumes are mounted automatically if the VAXELN system is built with the File Service. If no volume name is supplied for a specified device, the File Service tries to mount the volume that exists in the drive. If the specified volume name is not the same as the name specified when the volume was initialized, the File Service mounts the volume anyway and displays an informational message on the target machine's console terminal. However, the specified name is overridden by the volume name of the volume mounted in the drive. For example, if you specify the volume name TEST1, but the volume in the drive was initialized with the name TEST3, you would have to refer to the mounted volume by the name DISK$TEST3, not DISK$TESTl. If no argument is supplied for a drive, no volume is mounted initially by the File Service, but a volume can be mounted dynamically with the ELN$MOUNT_VOLUME procedure or with the ELN$MOUNT_TAPE_ VOLUME procedure, as appropriate. If the drive is a disk, it can also be used directly (for nonfile, or logical, 1/0) by opening it for logical 1/0 with the Pascal OPEN procedure or corresponding C open functions. (Logical 110 treats the volume as if it were a single large file; logical 1/0 is explained in Chapter 14.) NOTE If you attempt to mount a VMS disk volume that was improperly dismounted - for exmaple, if the VMS system crashed - the File Service prints a warning message on the target machine's console. The volume should be remounted on VMS, which rebuilds it; then it can be mounted on the VAXELN system. You can successfully mount a VAXELN or VMS tape volume that was improperly dismounted and can read all of its files. If the tape structure was corrupted - for example, by a crash of the VAXELN system when a file was being written - additional files cannot be written to it. 13-4 File Service 13.3 File Specifications When used in programs, such as in a call to the Pascal OPEN procedure, file specifications with volume labels are interpreted by the File Service as referring to a particular mounted disk or tape on the target machine. The format for specifying a volume label is as follows: DISK$name or TAPE$name If you supplied volume names with the System Builder's Edit System Characteristics Menu, name must match a volume name you defined. If you did not define volume names through the System Builder or if a different volume is in the drive, name must match the actual volume name. The first time a volume is mounted - whether by the File Service or with the ELN$MOUNT_VOLUME or ELN$MOUNT_TAPE_VOLUME procedure - its DISK$ or TAPE$ name is established as a universal name by the File Service and uniquely identifies the volume to local area network nodes. If another process in the application mounts a volume with the same volume name, the volume's DISK$ or TAPE$ name is established as a local name for that process's node. The use of local names allows, for example, a VAXELN system to initialize, mount, and write duplicate copies of a volume, all with the same volume name. To illustrate the use of volume labels in file specifications, suppose that the following volume name definitions are entered on the Edit System Characteristics Menu: "DQAl TEST1", "DQAO TEST2" The volume specifications DISK$TESTI and DISK$TEST2 in programs now refer to disks mounted on drives DQAl and DQAO, respectively. Furthermore, DISK$TESTI (DQAl) is the default disk volume; if no volume or device is specified in a file specification, the File Service refers to the specified directory, file name, and so forth on TEST!. For example, the following Pascal procedure call creates a file on DISK$TEST2: OPEN (myfile, FILE NAME := 'DISK$TEST2: [data]analog.dat')i Rle Service 13-5 The corresponding example in C is as follows: :fI:include. stdio FILE *fileytr fileytr=fopen ("DISK$TEST2: [data] analog. datil , "r"); Here, the file analog.dat in directory data is created and is represented by the program variable myfile. NOTE If a volume is mounted, you can also refer to it with an explicit device name. For example, the following OPEN statement refers to the disk volume in drive DUAO: OPEN(f,FILE_NAME := 'DUAO: [TEST]TEST.DAT') The corresponding example in C is as follows: :fI:include stdio FILE *fileytr fileytr=fopen("DUAO: [TEST]TEST.DAT","r"); Device names are local to their network node. If you access a file on a remote node by using file specification syntax other than VMS syntax, you must enclose the specification in quotation marks. For example, the following file specification file reference contains a question mark, which is not valid under VMS. Therefore, you must enclose the file reference in quotation marks: 2.9: : "DATA? . DATil 13.4 Procedure for Mounting Multiple Volumes with Identical Volume Labels You can mount multiple disk volumes that have the same volume label. However, the presence or absence of the Network Service and Name Service can affect such an operation. If the system does not include the Network Service and Name Service and you try to mount a volume that has the same volume name as an already mounted volume, the mount fails. 13-6 File Service If the system includes the Network Service and Name Service (the System Builder defaults), and you try to mount a volume that includes the volume label of an already mounted volume, several outcomes are possible. Consider a situation in which two disk volumes are to be mounted in the system. The first volume has the name TEST and will be mounted in the physical device DUAO. The second volume, also named TEST, will be mounted in the physical device DUAL Suppose a mount request is made specifying the device DUAO. When you mount the volume, the following names are created: • • • DUAO. This is the first name created; it is placed in the local name table. If this name cannot be created, the mount operation fails. DISK$DEFAULT_VOLUME. This is the second name created; it is also placed in the local name table. If this name cannot be created, the system assumes that another disk volume is to be used as the default volume and has already been mounted in the system. DISK$TEST. The system tries to create this name in the universal name table. If this fails, the system tries to create the name in the local name table. For example, if the universal name DISK$TEST does not exist in the network, the name DISK$TEST is created in the universal name table. You can use these names to access the mounted volume. If you try to mount another volume that has the same volume label, assuming that the mount request is made to the DUAl device, the following events occur: 1. The name DUAl is created in the local name table. 2. The system's attempt to create the name DISK$DEFAULT_ VOLUME fails because the name already exists. 3. The system's attempt to create the name DISK$TEST in the universal name table fails, so the name is created in the local name table. When the second mount operation is completed, the system knows the following names: File Service 13-7 Name Name Table Device Represented DUAO Local DUAO DISK$TEST Universal DUAO DISK$DEFAULT_VOLUME Local DUAO DUAl Local DUAl DISK$TEST Local DUAl The preceding operations have the following consequences for use of volume labels: • • If you try to access a file by using the device specification DISK$TEST:, you get access to device DUAl because local names are· used first. If you call the ELN$DIRECTORY_OPEN procedure, it returns a volume name string that does not correctly refer to the volume accessed. For example, if you specify DUAO:[OOOOOO]*. *;* for the search_name argument in a call to ELN$DIRECTORY_OPEN, the procedure returns DISK$TEST as the volume name. If you include this volume name in the file name you specify with a file utility routine, such as ELN$DELETE_FILE, you access the volume DUAl, not DUAO. Therefore, you should use the device that you specify for the search_ name argument, not the device that you specify for volume_name, in subsequent file operations. 13.5 DISK$DEFAULT_VOLUME Device Name The name DISK$DEFAULT_VOLUME is used as the device name when a file is accessed without the device name specification. When you mount a volume, the system tries to create the name DISK$DEFAULT_VOLUME. If the name does not exist, it is created. If another volume is already mounted, the name already exists, and the second attempt to create the name fails. If you dismount the volume that corresponds to DISK$DEFAULT_ VOLUME, the name is deleted. A subsequent attempt to access files on DISK$DEFAULT_VOLUME fails. The next mount request recreates the name DISK$DEFAULT_VOLUME. The system does not check to see whether other volumes 'are already mounted in the system. The following sequence of ECL commands illustrates this behavior: 13-8 File Service ECL> ECL> MOUNT DUAO: DIRECTORY DISK$DEFAULT_VOLUME: Directory DISK$VOLUME1: [000000] OOOOOO.DIR CONTIN.SYS VOLUME1.DAT BACKUP.SYS CORMIG.SYS BADBLK.SYS INDEXF.SYS BITMAP.SYS VOLSET.SYS Total of 9 files. ECL> MOUNT DUAl: ECL> DISMOUNT DUAO: ECL> DIRECTORY DISK$DEFAULT VOLUME: $DIRECT-E-OPENIN, error opening DISK$DEFAULT_VOLUME: [000000]*.*; * as input -ELN-F-DEV, error in device name or inappropriate device type for operation ECL> ECL> ECL> DISMOUNT DUAl: MOUNT DUAl: DIRECTORY DISK$DEFAULT_VOLUME: Directory DISK$VOLUME2: [000000] OOOOOO.DIR CONTIN.SYS VOLUME2.DAT BACKUP.SYS CORMIG.SYS VOLUME2.DAT BADBLK.SYS INDEXF.SYS BITMAP.SYS VOLSET.SYS Total of 10 files. 13.6 File Access Listener The file access listener (FAL) is built into VAXELN systems that support file access from remote nodes. You include the FAL in a VAXELN system by selecting Yes for the File access listener entry on the System Builder's Network Node Characteristics Menu, as explained in the VAXELN Development Utilities Guide. The FAL handles connection requests, such as file openings, that involve different network nodes, including incoming requests from VMS nodes. Accordingly, the inclusion of the FAL in a VAXELN system also presumes that the Network Service is present. Inclusion of the FAL does not necessarily mean that the File Service must be present. For example, a VAXELN network could use a system that includes a line printer, a line printer device driver, and the FAL as a print server. The FAL would accept I/O connection requests directed at the printer and establish the connection with the printer driver's message ports. File Service 13-9 13.7 File Service Volumes from VMS The File Service uses the same on-disk and tape file structure as the VMS operating system, and supports most VMS file-handling operations, such as COPY, DIFFERENCES, DIRECTORY, EDIT, and so forth. For example, assume that node MILDEW is a VAX system with two disks, DQAO and DQAl, and that MILDEW is running a VAXELN system with the File Service, Network Service, and FAL. Assume also that the following volume name definitions were entered on the System Builder's Edit System Characteristics Menu: "DQAl 'I'ES'I'l", "DQAO 'I'ES'I'2" You can copy a file from MILDEW with the following VMS command, which refers by default to DQAl on MILDEW: $ COpy MILDEW:: [directory] filename. type *.* Or, you can copy with the following command, which refers to DQAO on MILDEW: $ COpy MILDEW: :DISK$'I'ES'I'2: [directory]filename.type *.* You can also use the device specification directly, as in the following command: $ COpy MILDEW: :DQAO: [directory] filename. type *.* 13.8 File Service Operations The File Service performs the following disk file and record 1/0 operations: • • • • 13-10 File Service Creating a new file or opening an existing file - for example, using the Pascal OPEN procedure or the C open function Retrieving information from the file - for example, using the Pascal READLN procedure or the C gets function Adding information to the file - for example, using the Pascal WRITELN procedure or the C puts function Closing a file - for example, using the Pascal CLOSE procedure or the C close function When you are familiar with Pascal or CliO, all you need to know about the File Service is how to initialize, mount, and dismount volumes and how to create directories. The call formats and detailed argument descriptions for all file 110 routines, as well as for the file utility, disk utility, and tape utility procedures summarized in the following sections, are contained in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 13.9 File Utility Procedures The file utility procedures provided by the File Service are summarized in this section. To use these procedures, you must include the $FILE_ UTILITY module appropriate to the language you are using in the compilation of your program. (For more information, see the VAXELN Development Utilities Guide. NOTE The VAXELN File Service supports all of the file utility procedures for disk and tape volumes. However, the ELN$CREATE_DIRECTORY, ELN$DELETE_FILE, ELN$RENAME_FILE, and ELN$PROTECT_FILE procedures are invalid for tapes. An error message is returned if you attempt to apply them to tape volumes. 13.9.1 ELN$COPY_FILE Procedure The ELN$COPY_FILE procedure makes a duplicate of a specified file. A string of 1 to 255 characters gives the :file specification of the source file. A second string of 1 to 2Q5 characters gives the file specification of the destination file. You can supply file specification defaults for both the source and destination files. Optional parameters return the resultant file name strings of both files, the mode (block or record) and the number of blocks or records copied. If an error exists in one of the files, an optional Boolean expression is returned, indicating which file contains the error. File Service 13-11 NOTE The ELN$COPY_FILE procedure provides the only means of creating an ISAM or RELATIVE organization file in a VAXELN system, by copying an existing file of the organization. 13.9.2 ELN$CREATE_DIRECTORY Procedure The ELN$CREATE_DIRECTORY procedure creates a directory on the specified file service disk volume. This procedure is invalid for tape volumes. A string of 1 to 255 characters gives the file specification for the directory or subfile directory to be created. You can supply a file specification default for the directory. A file owner user identification code (mC) can also be specified. An optional parameter returns the resultant file name string of the directory file created. For example, the following Pascal command creates the directory DATA.DIR in the master file directory of the volume: CREATE_DIRECTORY ('DISK$TEST: [DATA]'); The directory must be created on a VAXELN disk volume; the procedure cannot create a directory on a volume that is not part of a VAXELN system. Also, the procedure creates only the last directory in the specification; any intermediate directories must already exist. When you create a directory and do not specify an owner, the directory is assigned the same owner as the directory under which it is created. Furthermore, all files created under a directory are assigned the owner of that directory's owner, unless you specify otherwise in the call to OPEN. Unless you desire the default owner, you should specify an owner when creating directories and files. (Specifying 0 has the same effect as not specifying a value.) 13.9.3 ELN$DELETE_FILE Procedure The ELN$DELETE_FILE procedure deletes a file from a mounted disk volume. This procedure is invalid for tape volumes. 13-12 File Service A string of 1 to 255 characters gives the file specification, with either an explicit version number or a semicolon or period to indicate the most recent version. For example, test.dat;23 designates version 23 is to be deleted; test.dat; and test.dat. designate the most recent version of the file. You can supply a file specification default for the file to be deleted. Another optional parameter stores the resultant file name string of the deleted file. 13.9.4 ELN$DIRECTORY_CLOSE Procedure The ELN$DIRECTORY_CLOSE procedure closes a directory on a mounted disk volume. A variable supplies a pointer to the directory file variable. The preferred method for obtaining directory listings is to use the ELN$DIRECTORY_OPEN procedure to open the directory, then loop, calling the ELN$DIRECTORY_LlST procedure until no more files are found. You should call ELN$DIRECTORY_CLOSE only if you db not want the program to continue the directory list loop until all the files are exhausted. 13.9.5 ELN$DIRECTORY_LIST Procedure The ELN$DIRECTORY_LIST procedure obtains the next file name from a mounted disk directory. A variable supplies a pointer to the directory file. If more than one directory is traversed by ELN$DIRECTORY_LIST, the directory name will change. An optional variable supplies a pointer to a file attributes record that receives the file's attributes; if you specify this argument, you must supply the pointer that was returned by a previous call to ELN$DIRECTORY_ OPEN. 13.9.6 ELN$DIRECTORY_OPEN Procedure The ELN$DIRECTORY_OPEN procedure opens a directory on a mounted disk volume in preparation for a ELN$DIRECTORY_LIST operation, returning the volume name and directory name if the procedure is successful. A variable supplies a pointer to the directory file variable. File Service 13-13 A string of 1 to 255 characters supplies the file specification of a directory for which to search. The general form of the character string is as follows: node::disk:[directory Jlilename.type;version The file name, type, and version can use the wildcard characters, percent sign (%) and askerisk (*), as in VMS file specifications. The % character matches any single character in the corresponding position; the * character matches any character or string in the indicated positions, including null strings. For example, the following string matches any specification with a file name of at least four characters, the last being C and the fourth-fromlast being A, and any file type or version. DISK$TEST: [testdata]*A%%C.*;* Wildcards are not allowed in volume names or, for VAXELN disks, in directory specifications. If the directory is not on a VAXELN disk - for example, it is serviced by a VMS system - the asterisk (*), percent sign (%), and ellipsis ( ... ) can be used in the directory specification. The ellipsis following a directory name matches all subdirectories contained in and including the named directory. In addition, an optional string of 1 to 64 characters receives the resultant node specification or server process port name. An optional variable receives a pointer to the file attributes record allocated by ELN$DIRECTORY_OPEN; you can use this pointer in subsequent calls to ELN$DIRECTORY_LIST to receive a file's attributes. 13.9.7 ELN$PROTECT_FILE Procedure The ELN$PROTECT_FILE procedure changes the protection of a disk file. This procedure is invalid for tape volumes. A string of 1 to 255 characters gives the file specification. The procedure sets the file ownership user identification code (UIC), the protection code, or both for the specified file. You can supply a file specification default for the file. Another optional parameter returns the resultant file name string of the file. 13-14 File Service 13.9.8 ELN$RENAME_FILE Procedure The ELN$RENAME_FILE procedure renames a disk file. This procedure is invalid for tape volumes. A string of 1 to 255 characters gives the current file specification; no wildcard characters are permitted. (To rename several related files, use ELN$DIRECTORY_LIST to find them and ELN$RENAME_FILE to rename each one.) A second string of 1 to 255 characters gives the new file specification. You can supply file specification defaults for both the current file and the new file. Optional parameters return the resultant file name strings of both files. The new volume name must be the same as the old one; that is, if the old specification includes a volume name, the new one must supply the same name or no name. Any parts of the current specification that are not supplied in this argument are obtained from the old file name. 13.9.9 ELN$SET_DEFAULT_FILESPEC Procedure The ELN$SET_DEFAULT_FILESPEC procedure establishes a defaultfile specification to be used within the current job. The default is applied to procedures that take a file specification as an input parameter. For example, if you set the default to DISK$YAHOO:[TEST]FILE1.DAT and if you call the OPEN procedure with the file name TEST, the resulting file reference for the OPEN is DISK$YAHOO:[TEST]TEST.DAT. A string of 1 to 255 characters gives the default file specification for the current job. The string replaces the previous default specification each time you call ELN$SET_DEFAULT_FILESPEC within a job. You cannot use wildcards in the file specification. 13.10 Disk Utility Procedures The disk utility procedures provided by the disk File Service are summarized in this section. To use these procedures, you must include in the compilation of your program the $DISK_UTILITY module appropriate for the language you are using (see the VAXELN Development Utilities Guide). File Service 13-15 13.10.1 ELN$DISMOUNT_ VOLUME Procedure The ELN$DISMOUNT_VOLUME procedure dismounts a file service disk volume on the specified device. The procedure must be called on the same node that has the File Service. A dismounted disk can be opened and used for nonfile, or logical block, 110. A string of 1 to 30 characters names the device, for example, DQAl for drive 1 on disk controller DQA. The user must have read, write, execute, and delete (RWED) privileges to dismount a volume. 13.10.2 ELN$INIT_VOLUME Procedure The ELN$INIT_VOLUME procedure initializes a disk for use as a Files-II file-structured volume. Disks must be initialized once before they are used. You can initialize any volume on any node running a VAXELN system, provided the volume is not mounted or already open. The procedure must be called on the same node that has the File Service. A string of 1 to 30 characters gives the device specification of the disk drive, for example, DQAl for drive 1 on disk controller DQA. The node must be specified explicitly for a drive on another node. A string of 1 to 12 characters gives the volume label for the disk. An optional argument supplies the default extension quantity in blocks for the files on the disk volume. The extension quantity is applied when the size of a file is increased beyond its initial allocation by writing more records to the file. Optional arguments supply a user name to be recorded on the volume and an integer identifying the UIC of the volume owner. The volume, file, and record protection for the volume are also specified by optional arguments. (See Chapter 12 for more information on protection.) Other optional arguments designate the following: • • • • 13-16 File Service The number of directories that can be cached by the File Service by default The maximum number of files that can exist on a disk The number of entries that are preallocated for user directories The number of file headers allocated initially for the index file (the file for the volume's file structure) • • • • • • • • The number of mapping pointers to be allocated for file windows, which are used to describe the logical segments of the file for access The cluster size (the minimum allocation unit for the volume) The position of the index file (beginning, middle, or end) Whether data checking on read or write operations is enabled or disabled Whether the volume is shareable Whether the volume is a group volume Whether the volume is a system volume Whether the volume has information about where bad blocks are located A required argument supplies a list of bad blocks. Bad blocks are areas on the volume that are known to be faulty and are marked by the procedure so that no data will be written on them. The bad-block list specifies a range of either logical or physical block numbers. You: can specify a null list. 13.10.3 ELN$MOUNT_ VOLUME Procedure The ELN$MO'ONT_VOLUME procedure mounts a disk for use as a file-structured volume. The procedure requires the device, its driver, and the File Service to be present in the same system from which it is called. The procedure does not return until the disk is mounted. A string of 1 to 30 characters names the disk drive on which the volume is to be mounted, for example, DQAl for drive Ion disk controller DQA. An optional argument of 1 to 12 characters supplies the volume label. If the argument is omitted, the procedure mounts whichever volume is loaded in the indicated drive. 13.11 Tape Utility Procedures The tape utility procedures provided by the tape File Service are summarized in this section. To use these procedures, you must include the $TAPE~UTILITY module appropriate for the language you are using in the compilation of your program (see the VAXELN Development Utilities Guide). File Service 13-17 13.11.1 ELN$DISMOUNT_TAPE_VOLUME Procedure The ELN$DISMOUNT_TAPE_VOLUME procedure dismounts a file service magnetic tape volume on the specified device. The procedure must be called on the same node that has the File Service. A string of 1 to 30 characters names the device - for example, MUAO for drive 0 on tape controller MUA. An optional argument designates whether the tape will be unloaded by the device. 13.11.2 ELN$INIT_TAPE_VOLUME Procedure The ELN$INIT_TAPE_VOLDME procedure initializes a file service magnetic tape as a tape volume that conforms to American National Standards Institute (ANSI) standard X3.27-1978. Tapes must be initialized before they are used. The procedure requires the device, its driver, and the tape File Service to be present in the same system from which it is called. The procedure does not return until the tape is ini tialized. A string of 1 to 30 characters gives the device specification of the tape drive, for example, MUAO for drive 0 on tape controller MUA. The node must be specified explicitly for a drive on another node. A string of 1 to 6 characters gives the volume label for the tape. An optional argument designates the density of data recorded on the tape. 13.11.3 ELN$MOUNT_TAPE_VOLUME Procedure The ELN$MOUNT_TAPE_VOLUME procedure mounts a file service magnetic tape as a tape volume that conforms to American National Standards Institute (ANSI) standard X3.27-1978. The procedure requires the device, its driver, and the tape File Service to be present in the same system from which it is called. The procedure does not return until the tape is mounted. A string of 1 to 30 characters names the tape drive on which the volume is to be mounted, for example, MUAO for drive 0 on tape controller MUA. An optional argument of 1 to 6 characters supplies the volume label. If the argument is omitted, the procedure mounts whichever volume is loaded in the indicated drive. Optional arguments designate the block size of new files and whether the tape volume can be written to. 13-18 File Service 13.12 File Service Interface for Disk and Tape Drivers This section is provided for anyone who is writing new disk or tape drivers that will use the File Service or who wants to study the drivers supplied with the development toolkit. You do not need this information for normal use of the VAXELN Toolkit. The File Service consists of two separate shareable images: FILE.EXE, which is the disk File Service shareable image, and TAPE.EXE, which is the tape File Service shareable image. The appropriate shareable image is linked to each disk and tape driver installed in a VAXELN system and is activated by calling routines from the respective driver. The following File Service initialization routines are available: • • The function ELN$FILE_INITIALIZE defines the actions open, close, get, and put for the specific disk device being driven. The function ELN$TAPE_INITIALIZE defines the actions open, close, get, put, reposition, tapemark, erase, and return for the specific tape device being driven. Normally, one of these functions is called by the driver's master process as part of its initialization sequence. The arguments are functions, or action routines, that define the operations for the device. The function returns a file context variable that is used by the File Service. Since most controllers support multiple units, typical drivers are multitasking programs that create a process to handle each drive. Therefore, after defining the action routines with ELN$FILE_INITIALIZE or ELN$TAPE_INITIALIZE, as appropriate, the driver creates a process for each attached drive. The drive process is usually passed some kind of argument identifying the drive, such as a unit number. The initializing process then waits for a start-up event to be signaled, meaning that one drive is initialized and the initializing process can proceed with creating other drive processes. (Depending on the driver, the event value can be passed explicitly to the process or obtained in the drive process with an up-level reference.) When all the drive processes have been started, the initializing process calls INITIALIZATION_DONE and proceeds with its other work. Each drive process calls one of the following file service routines: • The procedure ELN$FILE_SERVICE for disk device drivers File Service 13-19 • The procedure ELN$TAPE_SERVICE for tape device drivers In either case, the procedure's arguments are as follows: • • • • The start-up event value (startup_event) The file context (file_context) A string naming the drive (drive_name) (typical drivers take the controller name as a program argument and concatenate a digit to it to form the drive name) A drive context pointer, where the drive context (drive_context) is a structure defining the state of an individual drive and is usually initialized by the drive process Forming these arguments and calling the procedure are the only actions required of the drive processes. From this point on, the File Service is in effective control of the drive and performs all 1/0 operations on it, including handling protocol messages. The File Service signals the start-up event after performing its own initialization, allowing the master process to proceed with the creation of the other driver processes. The source modules for user-written drivers are as follows: • • ELN$:DAP.PAS. This module contains the Pascal language declarations of the two disk routines described in this section and the declarations of the function types you can use to declare action routines for ELN$FILE_INITIALIZE. The two tape routines described in this section and the Pascal language declarations of the function types for the action routines of ELN$TAPE_INITIALIZE are in ELN$:TAPE.PAS. The action routines' types are prefixed with DISK$ or TAPE$, as appropriate. DISK$PUT_ACTION, for example, is the function type used to declare put actions for disk devices. The precompiled version of DAP.PAS is the module $DAP and the precompiled version of TAPE.PAS is $TAPE. If you are writing a disk or tape driver for use with the File Service, be sure to include the appropriate module in its compilation. $DAP in ELN$:VAXELNC.TLB. This module contains the definitions for disk drivers written in C. You include this module when you compile your driver source module by issuing a command of the following form: #include $DAl? 13-20 File Service After including the appropriate Pascal or C module in your compilation, link the compiled driver with ELN$:RTLSHARE.OLB, which contains the shareable image of the File Service. NOTE A user-written driver should be capable of having any of its functions called in the context of any process, and its data base should, therefore, either be statically allocated or be allocated on the heap. 13.13 Data Access Protocol The data access protocol (DAP) is a method for exchanging data between processes in your system and record-oriented device driver programs or services. DAP is used by the Pascal and C runtime libraries to exchange 1/0 requests and results between the user's program and device drivers. This section explains the use of the development system's DAP facilities for anyone who is writing file- or record-oriented device drivers, or for anyone who is studying the drivers that Digital supplies. You will not need this information for normal use of the VAXELN Toolkit or for writing disk or tape drivers that will not use the File Service. A typical occasion for using the DAP is to add support for a new type of disk controller. Writing drivers with the DAP is usually simple because you have only to write definitions of a set of preestablished functions called action routines. Typically, you write definitions of open, close, get data, and put data that are appropriate for the device in question. The definition of each action routine in your program is accomplished with predeclared constants, data types, and functions, which are discussed in this section. For practical information on the use of the DAP in driver writing, study the driver and definition sources supplied with your development system. Figure 13-1 illustrates the message flow in a typical 1/0 operation. File Service 13-21 Figure 13-1: DAP Message Transmission (Read Request) Target VAX 1 User Program: ,Call ~ GET(f); Target VAX 2 Pascal Runtime Library Disk Driver: DAP$SERVER ............ Message .- .. --- ----- .. -. _.. _...... -_ DAP ...................... _.. --- .. _...... .. -... _.. --- -_ .. _.......... . _ 1-?,!,:~-1 _ g:=E~::~ File Access Listener [:_:_ _ ~~:_~~:~~~iVQr: File Server/Disk Driver: DAP$SERVER • . . . . . . . . . . . .1 ...........• ~~~~.~.J Network Service DataJink Driver Datalink Driver Ethemet ~ f---\ \,...-------~J---{ MLO-004294 In the example illustrated by Figure 13-1, a user program makes a read request, the Pascal GET procedure. When the runtime library is called, it generates a DAP message formulating the read request. There are then five cases that describe the destination and processing of the message, depending on the way the file was originally opened: 13-22 File Service Case 1 The program has opened a local terminal for logical I/O, as in: OPEN(f,FILE_NAME := 'TTAO:') The message is sent directly to the terminal driver by translating the local name TTAO, which has called the function DAP$SERVER to define the actions for servicing DAP requests directed at its device. (Action routines are discussed in Section 13.13.2.) Case 2 The program has opened a file on a mounted disk volume, as in: OPEN(f, FILE_NAME := 'DISK$VDATA: [mydir]file.dat') In this case, DISK$VDATA is a universal name established by the File Service, naming the port that receives DAP requests for the disk volume of the given name. The DAP request is thus received and processed by the File Service and the associated disk driver for that volume. CaseS The OPEN call is as in Case 2, but the volume name does not have a local translation. The Network Service receives the message and encloses it in an NSP message for transmission by the datalink drivers over the Ethernet to the node (here, VAX2) that has the named message port. The DAP message reemerges from node B's Network Service with the NSP envelope removed. The named port is defined in the job running node B's disk driver, and the read request is handled there. Case 4 The OPEN call used an explicit node name to access a file on a mounted disk (DUAl), as in: OPEN(f, FILE_NAME := 'VAX2: :DUA1: [mydir] file.dat') After transmission to node VAX2, the message is intercepted by that node's FAL and sent on to the File Service on that node. (In most respects, this case also applies if node VAX2 is a VMS node, although the node is then specified by number instead of by name; similarly, it could occur if node VAX1 is a VMS node at which a comparable OPEN call was made from a VMS program.) Case 5 The OPEN call specified a node explicitly, to open a remote terminal, as in: OPEN(f,FILE_NAME := 'VAX2::TTAO:') This is the network version of Case 1; the terminal TTAO on node VAX2 was opened for logical I/O. In all cases, the device driver manipulates the device registers to perform the input or output. The device driver or File Service uses the function DAP$SERVER to handle the message. Figure 13-1 shows the flow of the read-request message; the requested record, in each case, flows back to the requesting program on the same path. File Service 13-23 When the driver uses the data access protocol, the driver must be on the same network node as the device it controls, but the driver - and thus, the device - can be used by programs located anywhere in the local area network. The DAP is supported by a set of precompiled modules (for Pascal only) and a set of declarations, including types, constants, and function types (action routines). The Pascal declarations are used in programs by including the module $DAP from RTLOBJECT.OLB in the compilation. The corresponding definitions for C are contained in the module $DAP in ELN$:VAXELNC.TLB. 13.13.1 CAP General Principles In data communication, a protocol is a definition of a set of messages and, usually, the means of exchanging the messages. The data access protocol defines two things: • • A set of messages. Each message has a predefined format and meaning, and definitions are provided in the DAP for messages of every kind likely to be relevant to talking to record-oriented devices: specifying a file and the kind of access requested, sending control information (commands to read, write, and so on) defining the characteristics of files and devices, and so forth. A method of starting a message exchange (action routines). The DAP assumes that a communications path already exists for the messages, which, in VAXELN programming, is a circuit. (See Section 5.3.B.) The low-level operations of locating the communicating processes and formatting, interpreting, and transmitting messages are done by runtime library routines. When writing a device driver, you can regard these routines as black boxes, since you do not have to call any of them explicitly, except DAP$SERVER. In writing device drivers, the use of the DAP requires three steps: 1. Define a set of action routines appropriate to the device. 2. Establish circuits with any user processes that want to do something with the device. 13-24 File Service 3. Call the library function DAP$SERVER with parameters that supply the circuit - that is, the communication path between the device and the user process - and the set of action routines you have defined in the driver. The management of messages and other low-level operations is then done implicitly by DAP$SERVER. Almost all other code in DAP device drivers is concerned with servicing device interrupts. 13.13.2 Action Routines and DAP$SERVER An action routine defines your choice of DAP information that should be transmitted to perform a particular operation, such as reading a data record. The information is represented by a set of predeclared data types and constants. DAP$SERVER is a predeclared function. The following Pascal declaration is included with module $DAP. (See also the source file DAP.PAS.) FUNCTION dap$server(VAR circuit-port: port; FUNCTION open action OF TYPE dap$open action; [OPTIONAL] FUNCTION rename action OF TYPE dap$rename action; [OPTIONAL] FUNCTION dir op;n OF TYPE dap$dir open; [OPTIONAL] FUNCTION dir-list OF TYPE dap$dir-list; [OPTIONAL] FUNCTION erase action OF TYPE dap$erase action; [OPTIONAL] FUNCTION get action OF TYPE dap$get action; [OPTIONAL] FUNCTION put-action OF TYPE dap$put-action; [OPTIONAL] FUNCTION find action OF TYPE dap$fi~d action; [OPTIONAL] FUNCTION update action OF TYPE dap$update action; [OPTIONAL] FUNCTION rewind:action OF TYPE dap$rewind:action; [OPTIONAL] FUNCTION truncate action OF TYPE dap$truncate action; [OPTIONAL] FUNCTION flush action OF TYPE dap$flush actio~; [OPTIONAL] FUNCTION extend action OF TYPE dap$exte~d action; [OPTIONAL] FUNCTION display action OF TYPE dap$display action; [OPTIONAL] FUNCTION close action OF TYPE dap$close action; dap_buffer_size: integer 0; context: integer := 0 ): integer; := SEPARATE; The action routines, in tum, are represented by function types, for example: File Service 13-25 FUNCTION dap$put action ( record access 7 dap$b rac; record-number: INTEGER; record=options : dap$l_rop; buffer: ASTRING(32767); buffer_length : INTEGER; context: integer; var record file address: dap$r_rfai next record: BOOLEAN) : dap$l_statusi FUNCTION_TYPE; For the definitions of all DAP function types - that is, the action routines' parameters - and DAP$SERVER's parameters, see the file DAP.PAS. NOTE The preceding discussion applies to Pascal programs only. The equivalent interface is available to C programmers using the $DAP include module contained in ELN$:VAXELNC.TLB. 13.13.3 DAP Data Types Each kind of action routine is associated with a set of data types representing the routine's parameters. In addition, the result type dap$l_status, shown in Section 13.13.2, represents the success/failure status of each action-routine call. For the definitions of the types of action-routine parameters and the result type dap$l_status, see the source file DAP.PAS, supplied with your development system. 13.13.4 DAP Constants A large set of named constants are declared for use in DAP device drivers. For example, the named constant dap$k_seq_acc can be used as an open-file argument to indicate sequential access. For the list of names and their definitions, see the source file DAP.PAS, supplied with your development system. This same file defines the named constants representing action routine completion status, error status, control functions, and so forth. 13-26 File Service Many of the status constants are defined in DAP.PAS with reference to other, lower-level named constants. The definitions of these constants are in the file DAPSTATUS.PAS. 13.13.5 DAP Wildcard Functions The DAP$SERVER, upon receiving a retrieval, rename, or delete access function, checks the file specification parameter for any wildcard characters. If there are any, it recursively invokes itself to perform the function. File Service 13-27 Chapter 14 VAXELN Device Drivers The VAXELN Toolkit supplies drivers for a variety of devices. The supplied drivers include the following: • • • • • • Disk drivers, Section 14.1 Tape driver, Section 14.2 Printer drivers, Section 14.3 Terminal drivers, Section 14.4 Small Computer System Interface (SCSI) bus driver, Section 14.5 Realtime device drivers, Section 14.6 This chapter discusses the features of the supplied drivers and explains how VAXELN applications can perform parallel 110. 14.1 Disk Drivers The VAXELN Toolkit includes device drivers for a number of mass storage devices. Table 14-1 lists these drivers with the devices they support. Table 14-1: Disk Drivers Driver Supported Mass Storage Devices BDDRIVER Disk devices that use the VAXBI bus through a KDB50 VAXBI bus disk adapter, including the RAnn disks VAXELN Device Drivers 14-1 Table 14-1 (Cont.): Disk Drivers Driver Supported Mass Storage Devices DDDRIVER TU58 (VAX-ll/730 and VAX-111750) console tape cartridges, which, operationally, resemble disk devices DIDRIVER RFnn disks attached to the MicroVAX 3300 and 3400 Integrated Disk Controller DQDRIVER RB02 and RB80 disks attached to the VAX-111730 Integrated Disk Controller DUDRIVER Disk devices that use the UNIBUS through a UDA50 UNIBUS disk adapter, including the RAnn disk drives Disk devices that use the RQDXn interfaces on the MicroVAX, including RXnn diskettes and RDnn Winchester disks The RC25 controller for the Q-bus and UNIBUS Disk devices that use the KDA50 interface on the MicroVAX, incl uding the RAnn disks Disk devices that use the KFQSA Q-bus controller, including the RFnn disks DVSDRIVER RX33, RD53, and RD54 disk devices attached to the MicroVAX 2000 disk subsystem SCDRIVER RZnn Winchester disks, RX23 SCSI diskettes, RRD40 compact discs, and third-party Small Computer System Interface (SCSI) devices attached to a SCSI bus on MicroVAX, VAXstation, and rtVAXstation 3100 series systems. To use the disk interfaces and drives on a VAXELN target processor, you must build the appropriate driver into the VAXELN system that is to run on that processor. If you use the supported disk types and drivers as supplied, you can regard the drivers, and the File Service, as self-contained programs that perform I/O for you. All you need to know in such cases is how to build the drivers into your systems. This information is provided in the VAXELN Development Utilities Guide. NOTE If you build DID RIVER into a VAXELN system, you must specify an additional 256 pages for the system's system region size. 14-2 VAXELN Device Drivers 14.1.1 Logical 1/0 When a disk is not mounted, you can access it directly by using language-specific I/O routines or statements. You open a disk for logical I/O (nonfile I/O) by specifying the disk's device name instead of a file name in a call to the Pascal OPEN procedure, C open functions, or FORTRAN OPEN statement. Operations that you perform on the open file variable apply to the disk volume itself, as if it were a single, large file with the first record (record number 1) starting at block 0 on the disk. Logical I/O lets a program maintain and use its own information about the logical structure of records in a file. It is up to the program to interpret the structure of individual records, read from the disk, record the placement of records relative to one another, and perform other operations that the File Service normally handles. NOTE When you open a disk for logical 110, no other job can access the disk. You can write your own disk drivers that are compatible with this method and with the File Service. For information on writing disk drivers that are compatible with the File Service, and for general information on the Data Access Protocol (DAP) used by the languagespecific I/O routines and statements, see Sections 13.12 and 13.13. 14.1.2 Disk Specifications Table 14-2 lists specifications for the devices that the VAXELN disk drivers support. Table 14-2: Drive Disk Devices Device Code Media Type ByteslDisk Disks! Drive Drives! Controller Driver Image RA60 DU BD Cartridge 205 Mbyte 1 4 DUDRlVER.EXE BDDRIVER.EXE RA70 DU BD Fixed disk 280 Mbyte 1 4 DUDRlVER.EXE BDDRIVER.EXE VAXELN Device Drivers 14-3 Table 14-2 (Cont.): Device Code Drive Disk Devices Media Type ByteslDisk Disks! Drive Drives! Controller Driver Image RA80 DU BD Fixed disk 121 Mbyte 1 4 DUDRIVER.EXE BDDRIVER.EXE RA81 DU BD Fixed disk 456 Mbyte 1 4 DUDRIVER.EXE BDDRIVER.EXE RA82 DU BD Fixed disk 622 Mbyte 1 4 DUDRIVER.EXE BD DRIVER. EXE RA90 DU BD Fixed disk 1.2 Gbyte 1 4 DUDRIVER.EXE BDDRIVER.EXE RB02 DQ Cartridge 10 Mbyte 1 4 DQDRIVER.EXE RB80 DQ Fixed disk 119 Mbyte 1 1 DQDRIVER.EXE RD31 DU Fixed disk 20 Mbyte 1 2 DUDRIVER.EXE RD32 DU Fixed disk 42 Mbyte 1 2 DUDRIVER.EXE DVSDRIVER.EXE RD51 DU Fixed disk 10 Mbyte 1 2 DUDRlVER.EXE RD52 DU Fixed disk 31 Mbyte 1 2 DUDRIVER.EXE RD53 DU Fixed disk 71 Mbyte 1 2 DUDRIVER.EXE DVSDRIVER.EXE RD54 DU Fixed disk 150 Mbyte 1 2 DUDRIVER.EXE DVSDRIVER.EXE RF30 DI Fixed disk 150 Mbyte 1 1 6 1 DIDRIVER.EXE DUDRlVER.EXEl RF71 DI Fixed disk 400 Mbyte 1 1 6 1 DIDRIVER.EXE DUDRlVER.EXEl RRD402 DU Compact disc 577 Mbyte 1 1 SCDRIVER.EXE RX23 DU Diskette 1.4 Mbyte 1 1 SCDRIVER.EXE RX33 DU RX33 diskette3 1.2 Mbyte 1 1 2 1 DUDRIVER.EXE DVSDRIVER.EXE RX50 DU Diskette 400 Kbyte 2 4 DUDRIVER.EXE RZ22 DU Fixed disk 52 Mbyte 1 1 SCDRIVER.EXE 1 When used with the KFQSA Q-bus controller 2Read-only device 3The RX33 drive also supports RX50 diskettes. 14-4 VAXELN Device Drivers Table 14-2 (Cont.): Disk Devices Drive Device Code Media Type ByteslDisk Disks! Drive Drives! Controller Driver Image RZ23 DU Fixed disk 104 Mbyte 1 1 SCDRIVER.EXE RZ55 DU Fixed disk 332 Mbyte 1 1 SCDRIVER.EXE RZ56 DU Fixed disk 665 Mbyte 1 1 SCDRIVER.EXE TU58 DD Tape cartridge 256 Kbyte 2 2 DDDRIVER.EXE The RB02 and RB80 devices use the VAX-111730 Integrated Disk Controller (RB730). You can attach a total of four drives to the controller and only one of them can be an RB80. RB02 cartridges are identical to RL02 cartridges, and the cartridges can be interchanged between these two drive types. The TU58 cartridge is the console medium on VAX-111730 and VAX111750 processors. The cartridge is treated as if it were a randomaccess disk with one cylinder, four tracks per cylinder, 128 512-byte blocks per track. It is controlled by processor registers. RQDXn controllers interface up to four disk drives to the MicroVAX Q22-bus; up to two of these drives can be Winchester RDnn disks. The RD32, RD53, RD54, and RX33 devices can use the MicroVAX 2000 Integrated Disk Controller. This controller interfaces up to three disk drives; up to two of these drives can be Winchester RDnn disks, and one can be an RX33 drive. Devices that use this controller use the driver image DVSDRIVER.EXE. The RF30 and RF71 disks are integrated storage elements (ISEs) that can interface with the MicroVAX 3300 and MicroVAX. 3400 Integrated Disk Controller or the KFQSA Q-bus controller. The disks use the DIDRIVER.EXE image to interface with the integrated disk controller. This controller communicates with up to six disks using the Digital Storage System Interconnect (DSS!) bus. The RF30 and RF71 disks use the DUDRIVER.EXE image when interfacing with the KFQSA Q-bus controller. This controller also supports up to six RFnn disks. However, only one disk is supported per driver image. Th support multiple RFnn disks, you must include a copy of the DUDRIVER.EXE image in your system for each disk. VAXELN Device Drivers 14-5 Bad blocks are handled on disks and diskettes according to the device. RDnn disk devices support controller-initiated bad block replacement; that is, the RQDXn controller automatically handles bad blocks. However, the DVSDRlVER handles bad block replacement and vectoring for RDnn disks used with the MicroVAX 2000 Integrated Controller. An RAnn disk interfaces to a VAX bus by using a disk adapter or controller. • • • The UDA50 disk adapter interfaces RAnn disks to the VAX UNIBUS. The KDA50 disk controller interfaces the RAnn disks to the MicroVAX Q-bus. The KDB50 disk adapter interfaces the RAnn disks to the VAXBI bus. The disk adapter or disk controller you use for an RAnn disk determines the driver image you should use. The driver image DUDRIVER.EXE is for UDA50 and KDA50 I/O; the image BDDRIVER.EXE is for KDB50 I/O. RAnn and RC25 devices support host-initiated bad block replacement; that is, the driver automatically revectors bad blocks as they occur on the disks. 14.1.3 Disk Driver Interface to the File Service The VAXELN disk drivers include the disk File Service, which supports the Files-ll on-disk structure that the VMS systems use. Therefore, you can move disk volumes to a VMS system and use them with VMS software. Also, most VMS file-handling commands can use disks mounted on VAXELN systems when the systems are part of a network that includes VMS systems. A disk driver uses the File Service to perform the following operations on a disk: 14-6 VAXELN Device Drivers Operation Description Open Prepares a device and its driver for program I/O. The File Service performs this operation when you mount a disk volume or when the first user program accessing the disk for logical I/O calls the Pascal OPEN procedure, Copen functions, or FORTRAN OPEN statement. Get Reads data from a disk. The File Service performs this operation when language-specific input routines or statements retrieve information from a disk volume. Put Writes data on a disk. The File Service performs this operation when language-specific output routines or statements add information to a disk volume. Close Terminates I/O exchange with a user program. The File Service performs this operation when you dismount a disk volume or when the last user program accessing the disk for logical I/O calls the Pascal CLOSE procedure, C close functions, or FORTRAN CLOSE statement. 14.1.4 Recovery from Power Failure When disks are on line and mounted, they are brought back on line and remounted automatically following a power failure. The device driver reinitializes the disk controller. The File Service operations that were in progress when the power failed are retried, and the disks can be used again without manual intervention. Spinning down an RC25 controller and later spinning it back up is equivalent to a power-failure recovery. The actions just described apply in this case. 14.1.5 Direct Device Access for Disk Devices Direct device access (DDA) provides an interface that VAXELN applications can use to read data from and write data to local disks directly, avoiding the overhead incurred by the data access protocol (DAP). The DDA disk interface also provides for physical memory transfers by allowing applications to transfer data to and from an allocated system region. The interface consists of the runtime routines ELN$DISK_ READ and ELN$DISK_WRITE, which read blocks of data from and write blocks of data to a local disk drive using the DDA protocol. VAXELN Device Drivers 14-7 When the kernel initializes a disk driver, it creates a DDA port and a corresponding local port name of the form drive-name$ACCESS for each drive. For example, if DUDRIVER controls the drive named DUAl, the kernel creates the local name DUA1$ACCESS. To use the DDA disk interface routines, an application must first open the appropriate file or device (to gain access to an unmounted disk) and establish a VAXELN virtual circuit with a disk driver. The application uses the circuit to communicate with the driver. To establish the circuit connection, the application must create a port and connect that port to the disk drive's DDA port. Once the connection is made, the program can call ELN$DISK_READ and ELN$DISK_WRITE to read and write data. For descriptions of the ELN$DISK_READ and ELN$DISK_WRITE routines, see VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. Section 14.1.5.1 explains how to establish a circuit for the DDA disk interface. Sections 14.1.5.2 to 14.1.5.5 explain how to use the interface to do the following: • • • • 14.1.5.1 Perform direct read and write operations, Section 14.1.5.2 Read logical blocks from an unmounted disk, Section 14.1.5.3 Read logical blocks from a mounted disk, Section 14.1.5.4 Transfer data to physical addresses, Section 14.1.5.5 Establishing Circuits for the DDA Disk Interface An application program communicates with a disk driver using a VAXELN virtual circuit. The program must establish the circuit connection by creating a port and connecting that port to a disk drive's DDA port. Once the connection is made, the program can call the ELN$DISK_READ and ELN$DISK_WRITE routines to read and write data. The following example connects the port drivelJ10rt in a circuit to the DDA port named DUA1$ACCESS: MODULE test_drive; INCLUDE $DDA_UTILITY; PROGRAM test_read_write; 14-8 VAXELN Device Drivers VAR drivel-port, dda-port PORTi BEGIN CREATE_PORT (drivel-port) i CONNECT_CIRCUIT (drivel-port, DESTINATION NAME := 'DUA1$ACCESS')i END. ENDi Once the connection between drivel-port and the DDA port is established, the program can call ELN$DISK_READ and ELN$DISK_ WRITE, specifying drivelJJort as an argument. 14.1.5.2 Reading Data from and Writing Data to a Local Disk An application program can read data from and write data to a local mounted or unmounted disk by calling the ELN$DISK_READ and ELN$DISK_WRITE routines. These routines communicate with a disk driver by using a user-defined message. They send the message to the disk driver and wait for and receive a response. In the case of read operations, the message sent contains a read request and the message returned contains the data being read. In the case of write operations, the message sent contains the data to be written and the message returned contains the status of the write operation. Alternatively, an application can transfer data to an allocated system region. An application must use this method if it needs to lock the data buffer at a specific physical address. If an application specifies a physical address, ELN$DISK_READ and ELN$DISK_WRITE transfer the data directly to or from the system region at that address. The message sent or received contains a DDA header. Before calling ELN$DISK_READ or ELN$DISK_WRITE, you must create a message to be used for the data transfers. The message must be large enough to handle the largest possible transfer request and accommodate a DDA header of size DDA$_HEADER_SIZE. The following figure shows such a message: VAXELN Device Drivers 14-9 DDA Header Message Data MLO-004168 If the application is to transfer data to and from an allocated system region, the message must be large enough to accommodate just the header. Calls to ELN$DISK_READ and ELN$DISK_WRITE must specify the port connected in a circuit to the disk drive's DDA port, the number of bytes of data to be read or written (read or write size), and the starting logical block number on the disk where the read or write operation is to begin. A bytes transferred argument receives the number of bytes of data actually read or written. You must also specify the identifier and pointer for the previously created message. These input/output arguments represent the message sent to and received from the driver. ELN$DISK_READ uses the specified message to send a read request to the driver and to receive the data read. ELN$DISK_WRITE uses the message to send the data being written and to receive the completion status of the write operation. If you specify an allocated system region, the routines use the message to transfer only the DDA header. If an application uses the message arguments - for example, to gain access to the message data, it must ensure that it uses the current values, and if necessary, points to the message data. The message arguments are input/output arguments and the kernel may not map the sent and received messages to the same PO virtual address space. For example, this might happen if another process in the job runs and either uses some memory or returns memory to the system while the read or write operation is in progress. If this occurs, the message pointer value that the kernel returns might differ from the pointer value of the message that was sent. Similarly, the value of the message identifier might change. To read data from or write data to the message data buffer, an application must also set up a pointer to the data portion of the message. An application can do this by doing one of the following: 14-10 VAXELN Device Drivers Declaring a 2-field aggregate to represent the message and declaring a pointer to that aggregate Setting up a pointer to the message data directly • • An example of how an application might use an aggregate to represent a DDA message that has a data buffer of size 4096 bytes (eight disk blocks) follows: TYPE RECORD = dda message; dda-header : BYTE DATE(DDA$ HEADER SIZE); data_buffer: ARRAY[l .. 1024] OF INTEGER; END; VAR msg-ptr : Adda_message; Mter declaring the pointer to the aggregate, the application can specify the message pointer in the calls to CREATE_MESSAGE, ELN$DISK_ READ, and ELN$DISK_WRITE. The application can also use the pointer value to gain access to data read or to fill in data to be written. The following code shows how an application might gain access to the data buffer after a read operation. The assignment statement adjusts the pointer such that it points to the twelfth array element in the data buffer. ELN$DISK_READ(status, access-port, READ SIZE := bytes to read, BLOCK NUMBER := starting Ibn, BYTES=TRANSFERRED := bytes_read, MSG OBJ := msg object, MSG=PTR : = msgytr); data-ptr := msg-ptrA.data_buffer[12] If you prefer not to use the an aggregate representation, you might set up a pointer to the message data buffer before a write operation or after a read operation as follows: data-ptr: : INTEGER := msg-ptr: : INTEGER + DDA$_HEADER_SIZE; For information about transferring data to an allocated system region see Section 14.1.5.5. VAXELN Device Drivers 14-11 14.1.5.3 Reading Logical Blocks from an Unmounted Disk You can use the DDA disk interface to transfer data to and from a mounted or unmounted local disk. Example 14-1 shows an example of how you might use the interface to read logical blocks of data from an unmounted disk. Example 14-1: Reading Logical Blocks from an Unmounted Disk MODULE disk_read_unmounted; INCLUDE $dda_utility; PROGRAM disk_read_unmounted(INPUT, OUTPUT); TYPE byte = -128 .. 127; block = PACKED ARRAY [1 .. 512] OF BYTE; VAR total blocks : INTEGER; device file : FILE OF block; msg obj : MESSAGE; msg:ptr : AANYTYPE; bytes to read, starting Ibn INTEGER; data~tr-: AANYTYFE; access-port : PORT; drive_name, remote-port_name, file name VARYING STRING (32); status, bytes read : INTEGER; s_time, e_time, d_time : LARGE_INTEGER; s_time_asc, e_time_asc, d time asc VARYING_STRING(23); BEGIN { Main program } CREATE_PORT(access-port); o WRITE ('Enter the drive name [DUAl]: '); READLN(drive name); IF drive name = " THEN drive name := 'DUAl'; remote-p;rt_name := drive_name + '$ACCESS'; file name := drive name + ' :'; OPEN(device_file, FILE NAME := file name, HISTORY := HISTORY$READONLY); CONNECT_CIRCUIT(access-port, DESTINATION NAME := remote-port_name); Example 14-1 Cont'd on next page 14-12 VAXELN Device Drivers Example 14-1 (Cont.): Reading Logical Blocks from an Unmounted Disk REPEAT WRITE ('How many blocks are to be read: '); READLN(total blocks); bytes to read := total blocks * 512; starting-Ibn := 0; bytes_reid := 0; fl CREATE MESSAGE (msg obj, msg-ptr~:ABYTE_DATA(DDA$_HEADER_SIZE + bytes_to_read) ) ; GET_TIME(s_time); ELN$DISK_READ(status, access-port, READ SIZE := bytes to read, BLOCK_NUMBER := stirting_lbn, BYTES_TRANSFERRED := bytes_read, MSG_OBJ := msg_obj, MSG_PTR := msg-ptr); GET TIME(e time); WRITELN('ELN$DISK READ status: " status); d time := e time ~ s time; d-time asc ~= TIME STRING(-(d time»; wRITELN('Time for " bytes read, ' byte transfer -- , d time asc); WRITELN ('Transfer Rate = " bytes_read DIV (d_time::INTEGER DIV 10000), ' Kb/s'); data-ptr::INTEGER := msg-ptr: : INTEGER + DDA$_HEADER_SIZE; C) { { Use the data read. {} DELETE(msg_obj); UNTIL total blocks 1; { Clean up } DISCONNECT_CIRCUIT(access-port); DELETE(access-port); CLOSE(device_file); Example 14-1 Cont'd on next page VAXELN Device Drivers 14-13 Example 14-1 (Cont.): END; END. Reading Logical Blocks from an Unmounted Disk of main program } o Create a port, open the device, and connect to the drive's DDA port. Create a VAXELN message port and connect it in a circuit to the drive's DDA port. The sample module creates the message port access,JJort and connects it in circuit to the DDA port remote,JJort_name, where remote,JJort_name is a specified drive name and the string $ACCESS. The sample module also uses the specified drive name to open the device. The call to OPEN ensures that the device driver sets up the appropriate structures for the data transfer. @ Create a message object. Call CREATE_MESSAGE to create the message that is to be sent to the DDA port. The sample module creates the message msg_obj. The message's size is calculated based on the number of blocks that the user specifies. 6) Read data from the disk drive. Call ELN$DISK_READ to read data from the disk drive. You must specify the port connected in a circuit to the drive's DDA port, the read size, the starting logical block number, a variable that is to receive the number of bytes read, the message identifier, and the message pointer. The call to ELN$DISK_READ in the sample module reads data of size bytes_ toyead, starting at block starting_lbn, using port access,JJort. The number of bytes read is returned to bytes_read. The message is transferred using the message msg_obj. Set up a pointer to the message data. Set up a pointer to the data portion of the message and use the data read. o Clean up resources for the read operation. Clean up resources for this read operation by deleting the message and its associated data buffer. eD Clean up resources and exit. When the user enters 1 for the number of blocks to read, clean up resources by disconnecting the access port from the drive's DDA port, deleting the access port, and closing the device file. When the cleanup is complete, exit. e 14-14 VAXELN Device Drivers 14.1.5.4 Reading Logical Blocks from a Mounted Disk You can use the DDA disk interface to transfer data to and from a mounted local disk. Example 14-2 shows an example of how you might use the interface to read a contiguous file from or write a contiguous file to a mounted disk. Example 14-2: Reading Logical Blocks from a Mounted Disk MODULE disk_read_rnounted; INCLUDE $kernelrnsg, $elnrnsg, $dda_utility, $file_utilitYi PROGRAM disk_read_mounted(INPUT, OUTPUT); TYPE byte = -128 .. 127; block = PACKED ARRAY [1 .. 512] OF BYTE; VAR dda file FILE OF block; filesize INTEGER; attr rec AFILE$ATTRIBUTES RECORD; rnsg obj : MESSAGE; msg:ptr : AANYTYPE; total bytes, starting Ibn : INTEGER; dataytr : AANYTYPE; access-port : PORT; drive_name, remote-port_name, file_name VARYING STRING (32); status, bytes_xfr : INTEGER; s time, e time, d time : LARGE INTEGER; s=tirne_asc, e_time_asc, d_time=asc : VARYING_STRING(23)i [INLINE] PROCEDURE populate_data_buffer(flag : INTEGER); {++ { This procedure writes and checks an easily recognizable pattern on { each block. {--} VAR vbn, offset : INTEGER; pointer : AINTEGER; Example 14-2 Co nt' d on next page VAXELN Device Drivers 14-15 Example 14-2 (Cont.): Reading Logical Blocks from a Mounted Disk BEGIN FOR vbn := 1 TO filesize DO BEGIN FOR offset := 1 TO 128 DO BEGIN pointer::INTEGER := data-ptr: : INTEGER + «vbn - 1) * 512 ) + (offset - 1) * 4; CASE flag OF 0: pointer A := 0; 1: pointer A := vbn; 2: IF pointer A <> vbn THEN BEGIN WRITELN('Verify failed @ VBN, offset' vbn, offset); RAISE_EXCEPTION(KER$_BAD_VALUE); END; END; { CASE } END; { for offset } {for vbn } END; END; { procedure } BEGIN { Main program } CREATE_PORT(access-port); WRITE('Enter the drive name [DUAl]: '); READLN(drive_name); WRITE('Enter file READLN(filesize); size in blocks: '); IF drive name = I I THEN drive name := 'DUAl'; remote-port_name := drive_name + I $ACCESS ' ; file_name := drive_name + ':' + ' [OOOOOO]dda_file,img/; OPEN(dda file, FILE NAME := file name, HISTORY := HISTORY$NEW, RECORD LENGTH := 512, RECORD-TYPE := RECORD$FIXED, ACCESS:METHOD := ACCESS$DIRECT, CONTIGUOUS := TRUE, FILESIZE := filesize); IF filesize > 0 THEN BEGIN LOCATE(dda file, filesize); PUT (dda_file) ; END; Example 14-2 Cont'd on next page 14-16 VAXELN Device Drivers o Example 14-2 (Cont.): Reading Logical Blocks from a Mounted Disk CLOSE(dda_file); OPEN (dda_file, FILE NAME := file name, HISTORY := HISTORY$OLD, FILE_ATTRIBUTES := attr_rec); IF attr rec = NIL THEN RAISE-EXCEPTION(KER$ BAD STATE) ELSE IF-attr recA.starting-block number RAISE_EXCEPTION (KER$_BAD=STATE); o THEN ~ CONNECT_CIRCUIT (access-port, DESTINATION NAME := remote-port_name); total bytes := files·ize * 512; startIng lbn := attr recA.starting block number; bytes_xfr := 0; -create message (msg obj, msg~tr::Abyte_data(dda$_header_size + tt total_bytes»; data-ptr::INTEGER := msg-ptr::INTEGER + DDA$_HEADER_SIZE; { Initialize the message data buffer for a write operation. populate_data_buffer(l); GET_TIME(s_time); ELN$DISK_WRITE(status, access.-port , WRITE SIZE := total bytes, BLOCK-NUMBER := starting lbn, BYTES=TRANSFERRED := bytes_xfr, MSG OBJ := msg_obj, MSG_PTR := msg-ptr); GET TIME(e time); WRITELN('ELN$DISK WRITE status: " status); d time := e time ~ s time; d-time asc 7= TIME STRING(-(d time»; WRITELN('Time for T, bytes xfr, , byte transfer - - ' d_time_asc); WRITELN('Write Transfer Rate = " bytes_xfr DIV (d_time::INTEGER DIV 10000), , Kb/s'); data-ptr::INTEGER := msg-ptr::INTEGER + DDA$_HEADER_SIZEi { Clear message data buffer before read operation. } populate_data_buffer(O); Example 14-2 Cont'd on next page VAXELN Device Drivers 14-17 Example 14-2 (Cont.): Reading Logical Blocks from a Mounted Disk GET_TIME(s_time); ELN$DISK_READ(status, ~ accessyort, READ SIZE := total bytes, BLOCK NUMBER := starting Ibn, BYTES-TRANSFERRED := bytes xfr, MSG OBJ := msg obj, MSG=PTR := msg~tr); GET TIME(e time); WRITELN('ELN$DISK READ status: " status); d time := e time ~ s time; d-time asc 7= TIME STRING(-(d time)); WRITELN('Time for f, bytes xfr, , byte transfer d_time_asc); WRITELN('Read Transfer Rate = " bytes_xfr DIV (d_time::INTEGER DIV 10000), , Kb/s'); dataytr::INTEGER := msg-ptr: : INTEGER + DDA$_HEADE~SIZE; { Check the message data read. populate_data_buffer(2); DELETE(msg_obj)i DISCONNECT_CIRCUIT(access-port)i CLOSE(dda file); DELETE(accessyort)i ENDi { of main program END. o Create a port to be connected to the drive's DDA port. Use a call to CREATE_PORT to create a VAXELN message port. This port is to be connected to the drive's DDA port. The sample module creates the message port access-port. @ Get the name of the drive's DDA port. Get the name of the drive's DDA port. The name of the DDA port in the sample module is remote-port_name, where remote-port_name is a specified drive name and the string $ACCESS. 6) Create a file. Use a call to OPEN to create a file. The sample module creates an empty contiguous file defined as having 512-byte, fixed-length records. Extend the file to the correct size. Extend the file to the correct size by locating the last block and writing to it. The sample module uses the LOCATE routine to write to the last record. The file is then closed to ensure that the correct EOF marker is set. o 14-18 VAXELN Device Drivers o o 8 Reopen the file and get the starting block number. Reopen the file so that data can be written to it. The sample module reopens the file and retrieves its file attributes record to get the starting logical block number and the file's size. The sample checks for the correct starting block number to prevent the disk from being destroyed. If the file is not contiguous, the starting block will be zero. In this case the application should stop immediately. Connect to the drive's DDA port. Use a call to CONNECT_ CIRCUIT to connect the previously created message port to the drive's DDA port. The sample module connects the port access-port in a circuit to the DDA port remote-port_name, where remote-port_ name is a specified drive name and the string $ACCESS. Create a message object. Call CREATE_MESSAGE to create the message that is to be sent to the DDA port. The sample module creates the message msg_obj. The message's size is calculated based on a specified number of blocks. The module calls the routine populate_data_buffer with the argument 1. The routine writes the value 1 to each location in block 1, the value 2 to each location in block 2, and so forth. €) Write data to the disk drive. Call ELN$DISK_WRITE to write data to the disk drive by calling ELN$DISK_WRITE. You must specify the port connected in a circuit to the drive's DDA port, the write size, the starting logical block number, a variable that is to receive the number of bytes written, the message identifier, and the message pointer. The call to ELN$DISK_WRITE in the sample module writes data of size total_bytes, starting at block starting_Ibn, using port access-port. The number of bytes written is returned to bytes_xfr. The message is transferred using the message object msg_obj. When the routine returns, msg_obj receives the message identifier and msg-ptr receives a pointer to the message that is returned by the driver. The sample module uses the returned pointer to set up a pointer to the message data. o The module then calls the routine populate_data_buffer with an argument of O. This routine call initializes all locations in the message data buffer to o. Read data from the disk drive. Call ELN$DISK_READ to read data from the disk drive. You must specify the port connected in a circuit to the drive's DDA port, the read size, the starting logical block number, a variable that is to receive the number of bytes read, the message identifier, and the message pointer. The VAXELN Device Drivers 14-19 call to ELN$DISK_READ in the sample module reads data of size totaCbytes, starting at block starting_lbn, using port access-port. The number of bytes read is returned to bytes_xrf. The message is transferred using the message msg_obj. Note that the message that was used for the write operation is also used for the read operation. When the routine returns, msg_obj receives the message identifier and msg-ptr receives a pointer to the message that is returned by the driver. The sample module uses the returned pointer to set up a pointer to the message data. The module then calls the routine populate_data_buffer with an argument of 2. This routine call checks the data read against the data that was written. ~ Clean up resources. Clean up resources by deleting the message object and its associated buffer, disconnecting the access port from the drive's DDA port, closing the data file, and deleting the access port. 14.1.5.5 Transferring Data to a System Region You can transfer data to a region of memory at a specified physical address by specifying a system region address in the call to ELN$DISK_READ or ELN$DISK_WRITE. The address you specify must be aligned on a page boundary and must point to the starting location of a system region buffer that was previously allocated by a call to KER$ALLOCATE_SYSTEM_REGION. When you specify a system region address, the data is transferred directly to or from the system region at that address; the message associated with the specified message object is used only for the DDA header. Example 14-3 shows an example of how you might use the DDA disk interface to read logical blocks of data from an unmounted disk using system virtual address space. The sample module must run in kernel mode. 14-20 VAXELN Device Drivers Example 14-3: Transferring Data to a System Region MODULE xfr_to-physical_adr; INCLUDE $dda_utility, $KERNEL; PROGRAM xfr_to-physical_adr(INPUT, OUTPUT); CONST pages in ebuild = 6144; phy addr-= pages in ebuild * 512; free-pages_left 10240 - pages_in_ebuild; = TYPE byte = -128 .. 127; block = PACKED ARRAY [1 .. 512] OF BYTE; VAR sO addr : AANYTYPE; total blocks : INTEGER; device file : FILE OF BLOCK; mag obj : MESSAGE; msg~tr : AANYTYPE; bytes to read, starting Ibn INTEGER; data~tr-: AANYTYPE; access-port : PORT; drive_name, remote-port_name, file name VARYING STRING (32); status, bytes read : INTEGER; s time, e time, d time : LARGE INTEGER; s=time_as~, e_time_asc, d time-asc VARYING_STRING(23); BEGIN { Main program } o CREATE_PORT(access-port); WRITE('Enter the drive name [DUAl]: '); READLN(drive name); IF drive name = " THEN drive name := 'DUAl'; remote-p~rt_name := drive_name + '$ACCESS'; file name := drive name + ' :'; OPEN(device_file, FILE NAME := file name, HISTORY := HISTORY$READONLY); CONNECT_CIRCUIT (access-port, DESTINATION NAME := remote-port_name); CREATE MESSAGE (msg obj, msg-ptr::Abyte_data(DDA$_HEADER_SIZE»; REPEAT Example 14-3 Cont'd on next page VAXELN Device Drivers 14-21 Example 14-3 (Cont.): Transferring Data to a System Region WRITE('How many blocks are to be read: READLN(total_blocks); bytes to read := total blocks starting-lbn := 0; bytes_reid := 0; * '); 512; KER$ALLOCATE SYSTEM REGION(, sO_addr, bytes to read, PHYSICAL-:= phy_addr ); data-ptr := sO_addr; GET_TIME(s_time); ELN$DISK_READ(status, access-port, READ SIZE := bytes to read, BLOCK NUMBER := stirting lbn, BYTES=TRANSFERRED := bytes_read, MSG_OBJ := msg_obj, MSG_PTR := msg-ptr, SYS_REG~DR := sO_addr); GET TIME(e time); WRITELN('ELN$DISK READ status: " status); d time := e time ~ s time; d-time asc 7= TIME STRING(-(d time»; wRITELN('Time for I, bytes read, , byte transfer - - ' d_time_asc); WRITELN('Transfer Rate = ,~ bytes_read DIV (d_time::INTEGER DIV 10000), , Kb/s'); { { Use the data read from address sO addr. { { { {} KER$FREE_SYSTEM REGION(, bytes_to_read, sO_addr); UNTIL total blocks = 1; DELETE (msg obj); DISCONNECT=CIRCUIT(access-port); CLOSE(device file); DELETE(access-port); Example 14-3 Cont'd on next page 14-22 VAXELN Device Drivers ~ Example 14-3 (Cont.): Transferring Data to a System Region END; { of main program } END. o Create a port, open the device, and connect to the drive's DDA port. Create a VAXELN message port and connect that port in a circuit to the drive's DDA port. The sample module creates the message port access...Jlort and connects it in a circuit to the DDA port remote...Jlort_name, where remote...Jlort_name is a specified drive name and the string $ACCESS. The sample module also uses the specified drive name to open the device. The call to OPEN ensures that the device driver sets up the appropriate structures for the data transfer. fJ Create a message object. Create the message that is to be sent to the DDA port by calling CREATE_MESSAGE. The sample module creates the message msg_obj. The message's size is equal to the size of the DDA header. 6) Allocate necessary system region. Use a call to the KER$ALLOCATE_SYSTEM_REGION routine to allocate memory in system virtual address space. The memory allocated is physically and virtually contiguous and comes from the system region built into the system. A pointer to the first location of the allocated memory is returned to sO_addr. The region size is calculated based on the number of blocks specified in bytes_toJead. Read data from the disk drive. Read data from the disk drive by calling ELN$DISK_READ. You must specify the port connected in a circuit to the drive's DDA port, the read size, the starting logical block number, a variable that is to receive the number of bytes read, the message identifier, and the message pointer. The call to ELN$DISK_READ in the sample module reads data of size bytes_to_read, starting at block starting_lbn, using port access...Jlort. The number of bytes read is returned to bytes_read. The data is transferred to system region memory, starting at the address specified by sO_addr. The message object msg_obj is used for the DDA header. The routine returns the identifier and pointer values for the message returned by the driver. e VAXELN Device Drivers 14-23 o o Free the system region. Use a call to the KER$FREE_SYSTEM_ REGION routine to free memory that was previously allocated with the KER$ALLOCATE_SYSTEM_REGION routine. The call to KER$FREE_SYSTEM_REGION in the sample module frees the number of bytes read starting at the address specified by sO_addr. Clean up resources. Mter one block is read, clean up resources by deleting the message object and its associated buffer (from the last read operation), disconnecting the access port from the drive's DDA port, closing the device file, and deleting the access port. When the cleanup is complete, the module exits. 14.1.6 Virtual-Memory Disk Driver The VAXELN Toolkit includes a virtual-memory driver (VMDRIVER) that lets you create a virtual RAM disk structure in system memory and use the disk as you would an actual disk drive. You can use the VM disk as a scratch disk for the life of the system. Multiple readers and writers can share the disk and it can participate in network file operations. The VMDRIVER runs as a job in a VAXELN system. You build the driver into a system by entering the driver's characteristics on the System Builder's Program Description Menu. Once the VM disk is initialized, you cannot extend it. The memory pages used for the disk are allocated from contiguous addresses in system virtual address space. If insufficient virtual or physical memory is available for the disk, the driver raises the exception appropriate for the missing resource. If the debugger is present in the system, it gains control and shows the specific error message; otherwise, the driver is deleted from the system. The module in Example 14-4 initializes, mounts, and writes to the virtual-memory disk: 14-24 VAXELN Device Drivers Example 14-4: Using the Virtual-Memory Driver MODULE vrn_sample; INCLUDE $DISK_UTILITY, $FILE_UTILITY; PROGRAM Vffi_sample(INPUT, OUTPUT, data_file); CONST cluster size record size file size 1024; 1000; TYPE block record PACKED ARRAY[l .. record_size] OF CHAR; 1; Bytes } Blocks } VAR i, j, m : INTEGER; bad block l i s t : DSK$ BADLIST(O); dati file-: FILE OF block record; number records: INTEGER;buffer-size : INTEGER; more_dita : block_record; status : INTEGER; cstat : INTEGER; cerror : BOOLEAN; rdest : VARYING_STRING(255); rsource : VARYING STRING(255); file name: VARYING STRING(30); old file: VARYING STRING(255); target file VARYING STRING(255); volume=name : VARYING=STRING(12); BEGIN file name := 'DATA.DAT'; volume ,name :='VDISK'; number=records := 500; WRITELN(fInitializing virtual disk volume .. . f); Example 14-4 Cont'd on next page VAXELN Device Drivers 14-25 Example 14-4 (Cant.): Using the Virtual-Memory Driver ELN$INIT VOLUME(DEVICE := 'VM', VOLUME := volume_name, DEFAULT EXTENSION := 10, USERNAME := 'VAXELN', WINDOWS : = 7, CLUSTER SIZE := cluster size, INDEX POSITION := DSK$ BEGINNING, DATAYHECK : = DSK$ _ NOCHECK, SHARE : = FALSE, GROUP := FALSE, SYSTEM := FALSE, VERIFIED := FALSE, BAD LIST := bad block list::DSK$ BADLIST(O); STATUS := statu;); WRITELN('Mounting virtual disk volume ... '); ELN$MOUNT_VOLUME(DEVICE := 'VM', STATUS := status); buffer size := 4096; WRITELN('Opening file on virtual disk ... '); OPEN(data file, FILE-NAME := file name, HISTORY := HISTORY$NEW, RECORD_LENGTH := record_size, RECORD LOCKING := FALSE, ACCESS-METHOD := ACCESS$SEQUENTIAL, RECORD-TYPE := RECORD$FIXED, CARRIAGE CONTROL := CARRIAGE$NONE, DISPOSITION := DISPOSITION$SAVE, SHARING := SHARE$NONE, APPEND := TRUE, BUFFERING := TRUE, BUFFERSIZE := buffer_size, EXTENDSIZE := 0, FILESIZE := file_size, TRUNCATE := FALSE, STATUS := status); more data [1] : = 'A'; more:data[record_size] := 'Z'; Example 14-4 Cont'd on next page 14-26 VAXELN Device Drivers Example 14-4 (Cont.): Using the Virtual-Memory Driver FOR i := 1 TO number records DO WRITE(data file, m~re data); CLOSE (data file); target_file := 'll.lll"name passwd"::log$nam:data.dat'; old file := file name; ELN$COPY FILE(old file, target file,cstat, cerror, , , rsource, rdest);END; END. For information on how to build the virtual-memory driver into a VAXELN system, see the VAXELN Development Utilities Guide. 14.2 Tape Driver The VAXELN Toolkit includes the tape driver MUDRIVER for TK50 and TK70 magnetic streaming cartridge tape devices and the TUB1 reel tape system. This driver also supports all other byte-structured magnetic tape mass storage control protocol (TMSCP) tape drives. To use the tape interface and drive on a VAXELN target processor, you must include the driver in the VAXELN system that runs on that processor. If you use the supported tape types and driver as supplied, you can regard the driver, and the File Service, as a self-contained program that performs I/O for you. All you need to know in such cases is how to include the driver in your systems. This information is provided in the VAXELN Development Utilities Guide. 14.2.1 Logicall/O Tape file operations use the ANSI file structure. Since you cannot directly read from or write to this type of structure, you cannot use logical I/O with tapes as you can with disks. VAXELN Device Drivers 14-27 14.2.2 Tape Specifications Table 14-3 lists specifications for the devices that the VAXELN tape driver supports. Table 14-3: Tape Specifications Drive Device Type Driver Image TK50 MU Streaming cartridge MUDRIVER.EXE TK70 MU Streaming cartridge MUDRIVER.EXE TUB 1 MU Reel tape system MUDRIVER.EXE 14.2.3 Tape Driver Interface to the File Service The VAXELN tape driver, MUDRIVER, includes the tape File Service, which supports the ANSI tape file structure. ANSI is the tape file structure used by VMS. Therefore, you can move tape volumes to a VMS system and use them with VMS software. Also, tapes mounted on VAXELN systems can be used by most VMS file-handling commands when the VAXELN systems are part of a network with VMS systems. The tape driver uses the File Service to perform the following operations on a tape: Operation Description Open Prepares a device and its driver for program 110. The File Service performs this operation when you mount a tape volume or the first time a user program accesses the device. Get Asynchronously reads the next block from the tape and returns a context to the read operation. Put Asynchronously writes the next block to the tape and returns a context to the write operation. Reposition Asynchronously repositions the tape and returns a context to the reposition operation. The File Service performs this operation when a new file is accessed. 14-28 VAXELN Device Drivers Operation Description Tapemark Asynchronously writes a tape mark to the tape and returns a context to the tape mark operation. The File Service performs this operation when a file or the tape is closed. Return Provides the status of the completed action of the context given. 14.2.4 Recovery from Power Failure When a power failure occurs, tapes that are on line and mounted are automatically brought back on line, remounted, rewound to the beginning, and repositioned at the last known position. The device driver reinitializes the tape controller. The File Service operations that were in progress when the power failed are retried, and the tapes can be used again without manual intervention. 14.2.5 Recovery from Errors Tape mass storage control protocol (TMSCP) devices can detect errors and recover. The only data errors reported are unrecoverable errors, which the driver forwards to the File Service. 14.3 Printer Drivers The VAXELN Toolkit includes three device driver images that support LP11-type line printers. Table 14-4 lists these drivers with the devices they support. Table 14-4: Printer Drivers Driver Supported Printer Device LCD RIVER Printers attached to the parallel printer port of a DMF-32 board LIDRIVER Printers attached to the parallel printer port of a DMB32 communications adapter VAXELN Device Drivers 14-29 Table 14-4 (Cont.): Printer Drivers Driver Supported Printer Device LPVDRIVER Printers attached to an LPVl1 printer interface You can use the parallel port on a DMF-32 for a line printer or for parallel 110, but not both simultaneously (see Section 14.4.9). 14.3.1 Accessing Printer Devices You can open a printer device for output by specifying its device name instead of a file specification to the language-specific procedures that open files. Operations on the opened file then apply to the printer. To use line printer output on a VAXELN target system, you must build the appropriate driver in the VAXELN system that runs on that processor. Several systems in a network can use the printer configured for one node. For instructions on including a line printer driver in a VAXELN system, see the VAXELN Development Utilities Guide. A printer driver generally has one program parameter: the device controller name that you supply with the System Builder. The driver creates the printer unit's local name by appending 0 to the controller name. If you load the driver using a System Builder program description, you can specify a second program argument. The driver uses this argument to create the unit's universal name; again, the driver appends 0 to the argument. For example, if you specify LPA as the name of a printer controller when you build your system, you can use the local name LPAO: in place of a file specification when opening a file on that node. If you also supply a universal-name argument, such as PRINTER, you can use the name PRINTERO to access the printer from any node. Alternatively, you can access a printer on a remote node by supplying a node specification in the file specification .. However, the use of universal names is more transparent. If you are printing a file that was opened or created with FORTRAN carriage control, the driver interprets the first character of every line as a carriage control character. 14-30 VAXELN Device Drivers LCDRIVER also initializes theDMF-32 parallel interface for line printer operation, which means that the same DMF-32 cannot be used for parallel I/O. 14.3.2 Printer Driver Characteristics The source files LCDRlVER.PAS, LPVDRIVER.PAS, and LIDRIVER.PAS define the printer driver characteristics. These characteristics are defined as Pascal named constants. To change a driver's behavior, modify the appropriate constant definitions, recompile the source file, and relink to generate a new driver image. Table 14-5 summarizes the driver characteristics. Table 14-5: Printer Driver Characteristics Characteristic Description Maximum record length The maximum length of single records written to the line printer. The standard value is 512 bytes, or characters. Lines per page The number of consecutive lines written on a page before a page eject. The standard value is 66 lines. A usergenerated page eject resets the count. Form-feedlline-feed conversion A Boolean value that specifies whether the American Standard Code for Information Interchange (ASCII) character FF (form feed) is converted to an equivalent sequence of LFs (line feeds) in the output. The default is FALSE. Use TRUE for printers that do not have a mechanical form-feed feature. Page width The maximum number of characters on a printed line. The standard value is 132 characters. Line wrapping A Boolean value that specifies whether lines longer than the specified page width are wrapped automatically. The default is FALSE. VAXELN Device Drivers 14-31 Table 14-5 (Cont.): Printer Driver Characteristics Characteristic Description Lowercase-to-uppercase conversion A Boolean value that specifies whether lowercase characters are converted to uppercase when printed. The default is FALSE. To have all letters printed in uppercase, change. the value to TRUE. N onprinting character handling A Boolean value that specifies whether nonprinting characters are allowed in the output. The default is TRUE. Insertion of CR before LF A Boolean value that specifies whether the ASCII character CR (carriage return) is inserted before every occurrence of LF (line feed) in the output. (Some printers assume a CR when an LF is printed.) The default is FALSE. 14.4 Terminal Drivers The VAXELN Toolkit includes device drivers for performing program 1/0 with console terminals and terminals attached to asynchronous serial communication line interfaces. Table 14--6 lists these drivers with the devices they support. Table 14-6: Terminal Drivers Driver Supported Terminal Devices CONSOLE Target processor's console terminal CXDRIVER CXA16 and CXB 16 devices, which interface up to 16 asynchronous serial lines to a Q-bus on a VAX processor DECW$CONSOLE Console emulator for VAXELN DECwindows applications DECW$TE VT3nn terminal emulator for VAXELN DECwindows applications 14-32 VAXELN Device Drivers Table 14-6 (Cont.): Terminal Drivers Driver Supported Terminal Devices DHVDRIVER CXY08 device, which interfaces up to 8 asynchronous serial lines to an Industrial VAX processor DHQll and DHVll devices, which interface up to 8 asynchronous serial lines to a MicroVAX processor DHTDRIVER DHT32 device, which interfaces up to 8 asynchronous serial lines to a MicroVAX 2000 processor DSH32 device, which interfaces up to 8 asynchronous serial lines to MicroVAX 2000 and 3100 processors DZSDRIVER MicroVAX 2000 integrated serial-line controller, which interfaces up to 4 asynchronous serial lines to a MicroVAX 2000 processor DZVDRIVER DZQ11 and DZV11 devices, which interface up to 4 asynchronous serial lines to a MicroVAX processor DMBDRIVER DMB32 devices, which interface up to 8 asynchronous serial lines to a VAX processor LTDRIVER Serial-line devices attached to terminal servers RTDRIVER Remote Terminal Utility, which lets you access a VAXELN target from a remote host and enter commands as if you were connected to a local terminal SCNDRIVER User-implemented console or terminal device using the Signetics DUART chip in an rtVAX 300 configuration YCDRIVER DMF-32 device, which interfaces up to 8 asynchronous serial lines to a VAX. processor For information about the DECW$CONSOLE and DECW$TE drivers, see the VAXELN Guide to DECwindows. Chapter 11 discusses the LAT driver. For information about the Remote Terminal Facility, see Section 9.6. The VAXELN serial-line drivers are self-contained programs. To use the supported serial-line device types, build the corresponding driver program into your VAXELN system, using the System Builder's Terminal Description Menu or Console Characteristics Menu, as appropriate. If you include a terminal driver or the console driver in a VAXELN system, you may need to increase the pool size allocated for the system to at least 512 blocks. For more information about building terminal drivers and the console driver into VAXELN systems, see the VAXELN Development Utilities Guide. VAXELN Device Drivers 14-33 NOTE To use the DHVDRlVER for the CXY08 or DHQ11 controller, you must set the onboard mode switch to DHV mode. The factory-default setting for these controllers is DHU mode. If you use a CXY08 or DHQ11 controller for 110 operations while the device is in DHU mode, 110 inconsistencies may occur. All data transmissions involving terminals are full-duplex transmissions with the same speed, or baud rate, for sending and receiving. In addition, you can use all the supported serial-line interfaces to communicate between remote VAXELN and VMS systems, as discussed in Section 14.4.4. Other VAXELN drivers support the printer and parallel 110 features of the DMF-32 device. For information about these features, see Sections 14.3 and 14.4.9. The modules $TERMCLASS and $DDCMP_V2 in library RTLOBJECT.OLB contain several useful support routines for programming terminal drivers. You can use these declarations in your own terminal drivers by including the modules when you compile your driver programs. For details, see terminal driver source files such as DZVDRlVER.PAS, TERMCLASS.PAS, and YCDRlVER.PAS. Sections 14.4.1 to 14.4.9 discuss a variety of topics concerning the terminal drivers that Digital supplies. Specifically, they discuss terminal 110, the type-ahead buffer and output synchronization, and direct device access. They also explain how to do the following: • • • • • • • • • Terminate lines of input Set up point-to-point Digital Data Communications Message Protocol (DDCMP) communication Establish circuits for serial-line communication Retrieve and set terminal characteristics Read data from and write data to serial lines Set serial lines to the spacing state Use control characters Monitor the use of out-of-band characters Use modem control 14-34 VAXELN Device Drivers • • 14.4.1 Use escape and control sequences Perform parallel 110 Terminal 1/0 You read input from and write output to a terminal by sending messages to message ports that the Console Driver or other terminal driver creates. The Console Driver handles transmissions between the program and the console terminal; asynchronous line drivers handle transmissions between the program and one or more terminals attached to asynchronous serial interfaces. For instructions on including terminal drivers in your systems, see the VAXELN Development Utilities Guide. The runtime code for VAXELN procedures, such as the Pascal READ and WRITE procedures, formulates and transmits the necessary messages implicitly when you call these procedures with reference to a terminal. 14.4.2 Type-Ahead and Synchronization Input characters that you type before a read request are buffered in a type-ahead buffer. The type-ahead feature lets you, for example, answer a prompt without waiting for it to appear and usually prevents the loss of characters typed by a fast typist. Input characters remain in the type-ahead buffer until the drivers receive a read request from a program in the application. They are not echoed until then. If the type-ahead buffer fills up before the drivers get a read request, the drivers sound the bell on the terminal. The drivers synchronize their output with the terminal by using the XON and XOFF control characters. Therefore, for most applications, you should enable the terminal's AUTO XONIXOFF setting. VAXELN Device Drivers 14-35 14.4.3 Terminating Lines of Input You terminate lines of input by pressing the Return key or by typing Ctrl/Z or any other character with an ASCII code less than 32 (decimal), except those that have special interpretations as control characters (see Section 14.4.6). When escape recognition is enabled, an entire valid escape sequence is treated as a line terminator. The escape sequence is not echoed and is returned to the program writing the input. This is the only case in which a line terminator also constitutes program input. 14.4.4 Setting Up Point-to-Point OOCMP Communication You can use the following interfaces for error-free, though not transparent (as Ethernet is), communication between remote VAXELN and VMS systems: CXA16/CXB16 CXY08, DHQ11 DHT32 DHV11 DMB32 DMF-32 DZQ11 DZV11 You can establish a virtual circuit between jobs on remote machines over a serial line. To set up such a circuit, let each line act as a fullduplex asynchronous point-to-point Digital Data Communications Message Protocol (DDCMP) communications link. The DDCMP is a datalink control procedure that ensures a reliable data communications path between communications devices connected by data links. You specify the DDCMP option line-by-line when you build your system, using the System Builder. Figure 14-1 shows a typical VAXELN serial DDCMP link. 14-36 VAXELN Device Drivers Figure 14-1: A VAXELN Serial DDCMP Link Target VAX 1 I Job A H I t Kernel Target VAX 2 I Job B H Kernel I + I YCDR,V:R I DHV11 DMF-32 A job starts the DDCMP protocol on a line by connecting a circuit to the driver handling the line; the job stops the protocol by disconnecting from the circuit. In Figure 14-1, Job B receives messages sent by Job A and Job A receives messages sent by Job B. For example, if Job A uses line TTA2 on a DHV11 interface, part of the Pascal program would be the following: VAXELN Device Drivers 14-37 VAR data-port : PORT; msg MESSAGE; str : ASTRING(512); CREATE_PORT(data-port); CONNECT_CIRCUIT(data-port, DESTINATION_NAME := 'TTA2'); CREATE_MESSAGE (msg, str); SEND (msg, data-port); WAIT_ANY(data-port); RECEIVE (msg, str, data-port); On the other end, Job B's program for using line TTXl on a DMF-32 interface would look like the following: VAR data-port : PORT; msg MESSAGE; str : ASTRING(512); CREATE_PORT(data-port); CONNECT_CIRCUIT (data-port, DESTINATION NAME := 'TTX1'); CREATE~SSAGE(msg, str); SEND (msg, data-port); WAIT_ANY(data-port); RECEIVE (msg, str, data-port); The message data can be any data type and can have a length of 1 to 1024 bytes. The CONNECT_CIRCUIT procedure starts the DDCMP protocol running; the DISCONNECT_CIRCUIT procedure stops it. If the driver determines that the line is down due to excessive errors or retransmissions, it disconnects the circuit. Because this is a full-duplex communications line, both jobs can send messages simultaneously. The following limitations apply to DDCMP communication: • Messages received are guaranteed to be received in proper order and error-free. However, due to the nature of the DDCMP protocol, flow control is not as complete or as transparent as for normal circuits. For example, if a job sends enough messages to fill the 14-38 VAXELN Device Drivers • • 14.4.5 destination port before the receiving job can call the RECEIVE procedure to receive them, the driver refuses additional messages. If the receiver does not receive the messages within a timeout period of approximately 20 seconds (accounting for retransmissions and acknowledgments) the sending driver stops the protocol and disconnects the circuit. To prevent this, the two jobs should synchronize their transmissions so as not to exceed each other's port. The transmission lines are full-duplex, and messages can be overlapped for higher throughput. However, you should avoid prolonged uncontrolled sending of messages. Only one virtual circuit is allowed for each line. Direct Device Access for Serial-Line Devices Direct device access (DDA) provides an interface for controlling and monitoring serial-line device characteristics at runtime. The VAXELN terminal drivers use this interface. Likewise, user-written programs, including terminal drivers, can use this interface to retrieve and set serial-line characteristics. Additionally, programs in systems that include modem control- DHVDRIVER, DMBDRIVER, or YCDRIVER - can use the interface to monitor modem events. When the kernel initializes a serial-line terminal driver, it creates a port and a corresponding local port name of the form linename$ACCESS for each serial line. For example, if DHVDRlVER controls the line named TTAl, the kernel creates the local name TTAl$ACCESS. For systems that include an attached console, the kernel names the console port CONSOLE$ACCESS. The DDA serial-line device interface consists of a set of terminal utility procedures. To use these routines, a program must first connect a circuit to a serial line's DDA port named line-name$ACCESS. After the driver accepts the circuit, the program can call the procedures. A program can perform simultaneous DDA operations by connecting multiple circuits to the serial line's DDA port. A program can maintain multiple circuits with a terminal driver for each serial line. The terminal utility procedures are as follows: VAXELN Device Drivers 14-39 Routine Description Requests that a serial line be set to the spacing state. Cancels a request to be notified when a serial line's modem state changes. Cancels a request to be notified when a serial line receives an out-of-band character. ELN$'ITY_GET_CHARACTERISTICS Returns a serial line's characteristics. Requests that data be read from a serial line. Receives a datagram from the terminal driver containing information about a serial line's modem state changes. Receives a datagram from the terminal driver notifying you that the serial line has received an out-of-band character. Sets a serial line's characteristics. Sends a request to the terminal driver to be notified when a serial line's modem state changes. Sends a request to the terminal driver to be notified when a serial line receives an out-of-band character. Requests that data be written to a serial line. For descriptions of these procedures, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 14-40 VAXElN Device Drivers 14.4.5.1 Establishing Circuits for Serial-Line Communication An application program communicates with a terminal driver using a VAXELN virtual circuit. The program must establish the circuit connection by creating a port and connecting that port to a serial line's DDA port. Once the connection is made, the program can call the terminal utility procedures to get and set terminal characteristics, read and write data, and so forth. The following code fragment connects the port linel...]Jort in a circuit to the DDA port named TTA1$ACCESS: MODULE test_terminal; INCLUDE $DDA_UTILITY; PROGRAM test_term_characteristics; VAR linelyort, ddayort : PORT; BEGIN CREATE_PORT(linelyort); TRANSLATE_NAME (ddayort, 'TTA1$ACCESS', NAME$LOCAL); CONNECT_CIRCUIT (linelyort, DESTINATION PORT := ddayort); END. END; Once the connection between linel...]Jort and the DDA port is established, the program can call the terminal utility procedures, specifying linel...]Jort as an argument. 14.4.5.2 Retrieving and Setting Terminal Characteristics The VAXELN terminal drivers store a serial line's characteristics in a terminal characteristics record. The record fields define the characteristics listed in Table 14-7. Table 14-7: Terminal Driver Characteristics Characteristic Description Controller type The type of asynchronous serial-line controller in use. VAXELN Device Drivers 14-41 Table 14-7 (Cont.): Characteristic Speed Terminal Driver Characteristics Description For terminals other than the console, the baud rate for transmission and reception is on the indicated line. Valid baud rates include the following: 2000 19200 50 134 600 4800 75 150 1200 2400 7200 38400 110 300 3600 9600 1800 The default for the console and hard-copy terminals is 1200 baud. (The console is assumed to be a hard-copy terminal by default.) The default for CRT terminals is 9600 baud. You must set the terminal to the same speed by using its setup mode. Not all serial-line devices support the setting of this characteristic. Parity A Boolean value that specifies whether parity checking is enabled for the line. The default is FALSE. To enable parity checking, specify TRUE. You must set the terminal to the same value by using its set-up mode. Not all serial-line devices support the setting of this characteristic. Parity type For terminals other than the console, the value is DDA$_PARITY_SPACE, DDA$_PARITY_ODD, DDA$_PARITY_EVEN, DDA$_PARITY_MARK, or DDA$_PARITY_IGNORE, which specifies the type of parity checking used by the connected terminal. The default is DDA$_PARITY_EVEN. You must set the terminal to the same parity type by using its set-up mode. Not all serial-line devices support the setting of this characteristic. 14-42 VAXELN Device Drivers Table 14-7 (Cont.): Terminal Driver Characteristics Characteristic Description Display type The type of terminal in use. HARDCOPY specifies that the terminal is a hard-copy device, such as an LA120 printing terminal; this is the default for the console terminal. SCOPE specifies that the device is a video terminal; this is the default for terminals other than the console. SCOPE causes the DELETE key to backspace and rub out a deleted character; HARDCOPY makes it rewrite a deleted character enclosed in backslashes (\deleted-character\). DDCMP lines ignore this setting. Escape recognition A Boolean value that specifies whether the terminal driver is to check that the format of escape sequences conforms to the American National Standards Institute (ANSI) format. The default is TRUE. To disable escape recognition, specify FALSE. Section 14.4.7 describes the correct formats. In general, if you enable escape recognition for a terminal, you should set the terminal's escape-sequence format to ANSI by using the terminal's set-up mode. DDCMP lines ignore the escape recognition setting. Echo A Boolean value that specifies whether the terminal displays (echoes) input lines it receives. The default is TRUE. If the terminal is to display only characters that the software writes to it, specify FALSE. DDCMP lines ignore this setting. Passall A Boolean value that specifies whether the terminal driver passes all characters - including tabs, form feeds, control characters, and XONIXOFF directly from the terminal, without interpretation or translation. The default is FALSE, meaning that special interpretations apply to certain characters (see Section 14.4.6). DDCMP lines ignore this setting. VAXELN Device Drivers 14-43 Table 14-7 (Cont.): Terminal Driver Characteristics Characteristic Description Eight-bit A Boolean value that specifies whether the attached terminal uses 8-bit ASCII characters. The default is FALSE, in which case the high-order bits of all input characters are masked to o. To prevent the terminal driver from masking the high-order bit of an input character to 0, specify FALSE. This characteristic determines how software interprets input characters; the bitsper-character setting in a terminal's set-up mode governs the number of bits the terminal displays or prints. This setting is ignored for DDCMP lines. Character size The number of bits that comprise a character. Valid sizes are 5, 6, 7, and 8. Not all serial-line devices support the setting of this characteristic. TTYSYNC A Boolean value that specifies whether the terminal driver is to respond to XONIXOFF flow control (CtrllS and Ctr1lQ) sent from the device to synchronize output written by the system. TRUE is the default. To disable XON/OFF flow control, specify FALSE. Modem For terminals other than the console, a Boolean value that specifies whether a serial line is connected to a modem or cable that supplies standard (EIA) modem control signals. The default is FALSE; modem control signals are ignored. You can use modems only with CXY08, DHQ11, DHV11, DMB32, and DMF-32 devices. With the DMF-32 device, only the first two of its eight lines can be used for modems. (See Section 14.4.8.) Not all serial-line devices support the setting of this characteristic. DDCMP A Boolean value that specifies whether the line uses DDCMP for asynchronous communication with another system. The default is FALSE; the line acts as a regular terminal line. If the line is to act as a point-to-point full-duplex DDCMP line, specify TRUE. Not all serial-line devices support the setting of this characteristic. 14-44 VAXELN Device Drivers Table 14-7 (Cont.): Terminal Driver Characteristics Characteristic Description Passthru A Boolean value that specifies whether the terminal driver passes all characters except XONIXOFF directly from the terminal, without interpretation or translation. The default is FALSE, meaning that special interpretations apply to certain characters (see Section 14.4.6). DDCMP lines ignore this setting. NOTE If you change the escape recognition, echo, or display type terminal driver characteristic, the change does not take effect during the current read operation. However, the change will take effect for the next read operation. Unless you are using DECW$CONSOLE, DECW$TE, or RTDRIVER, all other terminal driver characteristics that you set by calling ELN$TTY_SET_CHARACTERISTICS take effect immediately, regardless of whether a read operation is in progress. You can retrieve a terminal's serial-line characteristics by: • • Issuing the ECL command SHOW TERMINAL Including a call to the ELN$TTY_GET_CHARACTERISTICS procedure in an application program Similarly, you can set all or a subset of the serial-line characteristics in the following situations: • • When you build your VAXELN system. If you include a terminal driver in your system, you can specify the characteristics of the terminal on each serial line by editing the System Builder's Terminal Characteristics Menu. You can specify the console terminal's characteristics on the Console Characteristics Menu. When using ECL. You can change the character size, echo, 8-bit, escape, parity, passall, speed, scope, and terminal synchronization characteristics by issuing the SET TERMINAL command with the appropriate qualifiers. VAXELN Device Drivers 14-45 • At runtime. You can modify a serial line's characteristics dynamically at runtime by including a call to the ELN$TTY_SET_ CHARACTERISTICS procedure in an application program. The ELN$TTY_GET_CHARACTERISTICS procedure allocates a terminal characteristics record that the application program can access to retrieve terminal characteristics. A call to ELN$TTY_GET_ CHARACTERISTICS must specify the port connected in a circuit to the serial line's DDA port and a pointer that points to the serial line's characteristics record. For example: VAR linel-port, dda-port char record PORT; ADDA$_TERMINAL CHARACTERISTICS; BEGIN { Establish a circuit connection with the serial line's DDA port. CREATE_PORT(linel-port); TRANSLATE_NAME (dda-port, 'TTA1$ACCESS', NAME$LOCAL); CONNECT_CIRCUIT (linel-port, DESTINATION_PORT := dda-port); ELN$TTY_GET CHARACTERISTICS(CIRCUIT := linel-port, LINE_CHAR_PTR := char_record); WITH char recordA DO BEGIN WRITELN('Device type = " DEV TYPE); WRITELN('Revision level = " REVISION); END; END. This section of code allocates a serial line's characteristics record and then accesses the fields containing the serial line's device type and the revision level of the characteristics record. An application program can change a serial line's characteristics by calling ELN$TTY_SET_CHARACTERISTICS. The call ELN$TTY_ SET_CHARACTERISTICS in the following section of code changes a serial line's passall characteristic to TRUE. 14-46 VAXELN Device Drivers VAR linel-port, dda-port char record PORT; ADDA$_TERMINAL CHARACTERISTICS; BEGIN { Establish a circuit connection with the serial line's DDA port. CREATE_PORT(linel-port); TRANSLATE_NAME (dda-port, 'TTA1$ACCESS', NAME$LOCAL); CONNECT_CIRCUIT(linel-port, DESTINATION_PORT := dda-port); ELN$TTY_GET_CHARACTERISTICS(CIRCUIT := linel-port, LINE CHAR PTR := char_record); char recordA.PASSALL := TRUE; ELN$TTY_SET_CHARACTERISTICS(CIRCUIT := linel-port, LINE CHAR PTR := char_record); END. Before the terminal driver sets a line's characteristics, it checks the values that you supply in the terminal characteristics record to ensure their compatibility with the driver. If you supply an incompatible value, the driver returns an error status and does not set any characteristics. You must then resubmit the request with compatible values. For example, if you specify a line speed that is not available to the driver, the driver returns the ELN$_INVALSPEED status and does not set any characteristics. In this case, you would resubmit the request with a valid line speed. You should determine whether a serial line's characteristics are set appropriately for your application before modifying the characteristics. You can also use the ELN$TTY_GET_CHARACTERISTICS and ELN$TTY_SET_CHARACTERISTICS procedures to retrieve and set a terminal's modem characteristics if your VAXELN system includes modem support. For information about using modem control, see Section 14.4.8.1. VAXELN Device Drivers 14-47 The following information sources might also be useful: • • • 14.4.5.3 For information about establishing a circuit with a serial line's DDA port, see Section 14.4.5.1. For information about specifying terminal characteristics at build time or about using the ECL commands SET TERMINAL and SHOW TERMINAL, see the VAXELN Development Utilities Guide. For descriptions of the ELN$TTY_SET_CHARACTERISTICS and ELN$TTY_GET_CHARACTERISTICS procedures, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. Reading Data from and Writing Data to a Serial Line Your application programs can read data from and write data to a serial-line device by calling the ELN$TTY_READ and ELN$TTY_ WRITE procedures. These procedures read and write characters without interpretation. ELN$TTY_READ honors input flow control. However, you can disable input flow control when you build your system or at runtime. You disable flow control at build time by selecting Yes for the Pass all entry on the System Builder's Terminal Description Menu. You disable it at runtime by using the ELN$TTY_SET_C:HARACTERISTICS procedure to change the values in the passall and TTYSYNC fields of the serial line's terminal characteristics record to TRUE and FALSE, respectively. Calls to the ELN$TTY_READ and ELN$TTY_WRITE procedures must specify the port connected in a circuit to the serial line's DDA port, a buffer, the transfer request size (in bytes), and a variable that receives the number of bytes of data transferred. The buffer receives the data to be read or contains the data to be written. In calls to ELN$TTY_READ, the buffer size can represent the maximum number of characters that can be read or the number of characters to be read. You can also specify the ELN$TTY_READ and ELN$TTY_WRITE procedures with arguments that specify a message object and its pointer. ELN$TTY_READ also provides an extended status argument that you can use for reporting character errors. 14-48 VAXELN Device Drivers The message object arguments are input/output arguments that simplify read and write requests. By default, ELN$TTY_READ and ELN$TTY_WRITE create messages, send the messages to the serialline driver, wait for and receive response messages, and delete the received messages. In the case of read operations, the messages are used to transfer data fragments that are copied to the specified buffer. In the case of write operations, the messages are used to transfer data fragments that are copied from the specified buffer. Rather than having the routines create and delete multiple messages to transfer data, you can create a message to be used in subsequent transfer requests. To use the message arguments, you must create a message that is large enough to handle the largest possible transfer request and accommodate a DDA header of size DDA$_HEADER_SIZE, prior to calling the ELN$TTY_READ or ELN$TTY_WRITE routine. The following figure shows such a message: DDA Header Message Data MLO-004168 You can then specify the message's identifier and pointer in the call to ELN$TTY_READ or ELN$TTY_WRITE. ELN$TTY_READ uses messages to send a read request to the driver and to receive the data read. ELN$TTY_WRITE uses messages to send the data being written and to receive the completion status of the write operation. If an application uses the message arguments - for example, to gain access to the message data, it must ensure that it uses the current values. The message arguments are input/output arguments and the kernel may not map the sent and received messages to the same PO virtual address space. For example, this might happen if another process in the job runs and either uses some memory or returns memory to the system while the read or write operation is in progress. If this occurs, the message pointer value that the kernel returns might differ from the pointer value of the message that was sent. Similarly, the value of the message identifier might change. When calling ELN$TTY_READ, you can also specify read options, the minimum number of characters required to complete a read request, a read terminator mask, and a timeout value. VAXELN Device Drivers 14-49 Read options specify a specific type of read operation. The read options are defined as follows: Option Description 1 Read a minimum number of characters up to the maximum value 2 Read until a specified timeout value expires 4 Read until a specified character is read If you do not specify a read option, the procedure reads characters without interpretation while honoring input flow control. If the default action for ELN$TTY_READ is not appropriate for your application, use the read options to tailor the procedure's action to your needs. You can define a minimum read size by specifying option 1 and an argument representing the minimum number of characters required to complete a read request. The minimum read size that you specify must be less than the buffer size. You can use the minimum read size option to flush a terminal driver's typeahead buffer. To do this, specify option 1 and a minimum read size of o. This combination will cause ELN$TrY_READ to read as many bytes as are available in the driver's typeahead buffer, up to a maximum equal to the specified buffer size. If necessary, repeat the read operation until the number of bytes read equals 0 and the status value is odd (success). You can define a terminator mask by specifying option 4 and an argument that specifies a read terminator mask array. Each element in the mask corresponds to a character in the DEC Multinational Character Set. Setting the value associated with an element to TRUE indicates that the character is to terminate the read operation. If you specify option 4 without specifying a value for the argument, the read terminates when the specified number of characters are read or a specified timeout value expires. NOTE When you specify option 4, a read operation may terminate due to two conditions: success (ELN$_SUCCESS) and the receipt of a terminating character (ELN$_TERM_RECV). In this case, the ELN$TrY_READ procedure returns the status value ELN$_TERM_RECV. 14-50 VAXELN Device Drivers If you specify option 2 and a timeout value argument, the ELN$TTY_ READ procedure reads data until a time interval expires. You specify the time interval as a time value as shown in the following example: tmo := TIME_VALUE('O 00:02:00.00'); If you specify option 2 without specifying a timeout value, the read terminates immediately with as many characters as are available (from the type-ahead buffer) up to the buffer size or a specified terminating character. You can specify multiple read options by supplying a read option value that is the sum of the desired options. For example, to initiate a read operation that is to use a terminator mask and a timeout value, specify 6 (the sum of options 2 and 4) for the read option. If an elTor occurs on a serial-line device during a read operation, the driver terminates the operation and does the following: • • Checks whether the elTor condition is ELN$_PARITY, ELN$_ BREAK_DETECTED, or ELN$_FRAME_ERROR. These conditions are associated with elTor characters. If one of these conditions occurs, the cOlTesponding elTor character is stored in the first (low-order) byte of the optional extended status argument. Stores the number of good characters read in the number of bytes read argument. If the elTor occurs while the first character is being read, the value of the number of bytes read argument is 0 even if the specified minimum read size is greater than O. Thus, you should check for elTor conditions and check the value of the number of bytes argument before using data that the ELN$TTY_READ procedure reads. The program in Example 14-5 reads data from a serial line and writes the characters that are read using the default transfer mechanism. Example 14--6 shows how you might read data to and write data. from a serial-line device using the user-defined message transfer mechanism. The discussions that follow refer to the callouts in the examples. VAXELN Device Drivers 14-51 Example 14-5: Reading and Writing Serial-Line Data MODULE readit; INCLUDE $ELNMSG, $PASCALMSG, $KERNELMSG, $GET MESSAGE TEXT, $DDA_UTILITY, $DDA; VAR dda-packet : ADDA$_PACKET; { I/O packet } dda msg : MESSAGE; dda:port : PORT; app_job-port : PORT; status : INTEGER := ELN$ SUCCESS; stat : INTEGER := ELN$ SUCCESS; options : INTEGER := 0; buffer_size : INTEGER; buffer: STRING(80); nbr bytes read: INTEGER := 0; nbr-bytes-written : INTEGER := 0; ter;inato~ mask : DDA$ BREAK MASK; tmo value 7 LARGE INTEGER :=-0; min-read size : INTEGER := 0; error_status: DDA$_EXTENDED_READ_STATUS := ZERO; PROGRAM readit(INPUT,OUTPUT); VAR i : INTEGER := 0; BEGIN JOB_PORT(app_job-port ); CONNECT_CIRCUIT (app_job-port, DESTINATION NAME := 'TTAO$ACCESS'); WHILE TRUE DO BEGIN options := 0; buffer size := 50; ELN$TTY READ (status, app_job-p ort , buffer size, buffer~ nbr_bytes_read, options, terminator_mask, tmo_value, min_read_size, error_status) ; Example 14-5 Cont'd on next page 14-52 VAXELN Device Drivers o Example 14-5 (Cont.): Reading and Writing Serial-Line Data WRITELN('Status from first read is: " status:l); WRITELN('Nurnber of characters read is: " nbr bytes read:l}; WRITELN('Data read was: " buffer::string(nbr:bytes:read»; IF «status = ELN$ PARITY) OR (status = ELN$-FRAME ERROR) OR (status = ELN$:BREAK:DETECTED» THEN WRITELN('Error character is: " error_status.error_character); buffer size := nbr bytes read; ELN$TTY_WRITE(status, app_j obyort, buffer size, buffer; nbr_bytes_written); END; o {WHILE TRUE } DISCONNECT_CIRCUIT(app_jobyort); END; END. o o Connect to a DDA port. Get the application's job port and connect it in a circuit to a DDA port. The sample module gets the application job port appJob..,port and connects it in a circuit to the DDA port TTAO$ACCESS. @ Read the data. Use a call to ELN$TTY_READ to read the data. The call to ELN$TTY_READ must specify the port connected in a circuit to a serial line's DDA port, a buffer, the size of the buffer, and a variable that receives a value indicating the amount of data read. You can also specify options, terminator mask, timeout value, minimum read size, extended status size, message object, and message pointer arguments. The sample module indicates that no read options will be used, defines a buffer size of 50 bytes, and then issues a call to ELN$TTY_ READ. The call to ELN$TTY_READ reads data into a buffer of size 50 bytes and uses error_status to receive extended status information. Because no read options are specified, ELN$TTY_READ reads characters without interpretation while honoring input flow control. VAXELN Device Drivers 14-53 6) Check for a read operation error. Check for a parity error, frame error, or break. If one of these conditions occurs, the low byte of the extended status argument will contain the character in error. The sample module checks whether status receives ELN$_PARITY, ELN$_FRAME_ERROR, or ELN$_BREAK_DETECTED. If one of these conditions occurs, the sample uses extended status argument error_status to write the character in error. Write the data. Use a call to ELN$TrY_WRITE to read the data. The call to ELN$TTY_WRITE must specify the port connected in a circuit to a serial line's DDA port, a buffer, the size of the buffer, and a variable that receives a value indicating the amount of data that is written. You can also specify message object and message pointer arguments. The call to ELN$TTY_WRITE in the sample module writes the data that is in buffer to the serial-line device. Disconnect the circuit to the DDA port. Use a call to DISCONNECT CIRCUIT to disconnect the circuit to the DDA port. The sample module disconnects the circuit between app.Job_ port and the DDA port TTAO$ACCESS. o o The numbered callouts that follow refer to the callouts in Example 14-6. Example 14-6: Reading and Writing Serial-Line Data Using a User-Defined Message MODULE dda_read_with_msg; INCLUDE $dda_utility; PROGRAM dda_msg_read(INPUT, OUTPUT); CONST request_size = 5; {Read in 5 bytes with each read VAR line_buffer: STRING(request_size); myyort : PORT; size read, size=written, stat : INTEGER; message_obj MESSAGE; messageytr "'STRING(DDA$_HEADER SIZE + request_size); BEGIN Example 14-6 Cont'd on next page 14-54 VAXELN Device Drivers Example 14-6 (Cont.): Reading and Writing Serial-Line Data Using a User-Defined Message JOB_PORT(app_job-port ); CONNECT_CIRCUIT (my-port, DESTINATION_NAME := 'CONSOLE$ACCESS'); o CREATE_MESSAGE (message_obj, ~ message-ptr: : ASTRING(DDA$_HEADER_SIZE + request_size»; ELN$TTYREAD(STATUS := stat, -CIRCUIT:= app_job-port, BUFFER SIZE := request size, BUFFER-:= line buffer,NBR BYTES READ-:= size read, OPTIONS :~ 0, MIN READ SIZE := 0, MSG:OBJ 7= message_obj, MSG_PTR := message-ptr); IF (size read. >0) THEN ELN$TTY_WRITE(STATUS := stat, CIRCUIT := app_job-port, BUFFER SIZE:= size read, BUFFER-:= line buff;r, NBR BYTES WRITTEN := size written, MSG:OBJ message_obj, MSG_PTR := message-ptr)i := DELETE(message_obj)i DISCONNECT_CIRCUIT(app-port ); o o END. {program} END; {module} o Connect to a DDA port. Get the application's job port and connect it in a circuit to a DDA port. The sample module gets the application job port app.Job...]Jort and connects it in a circuit to the DDA port CONSOLE$ACCESS. ~ Create a message object. Create the first message that is to be used to transfer data between the application and the serial-line driver by calling CREATE_MESSAGE. The sample module creates the message message_obj. The message has a size of 5 bytes plus 512 bytes for the DDA header as indicated by the message pointer argument message...]Jtr. VAXELN Device Drivers 14-55 6) Read the data. Use a call to ELN$TTY_READ to read the data. The call to ELN$TTY_READ must specify the port connected in a circuit to a serial line's DDA port, a buffer, the size of the buffer, and a variable that receives a value indicating the amount of data read. You can also specify options, terminator mask, timeout value, minimum read size, extended status size, message object, and message pointer arguments. e o o The call to ELN$TTY_READ in the sample module reads data into a buffer of size 5 bytes (request_size), using the user-defined message for the data transfer. The message_ob) and message,JJtr arguments specify the user-defined message to be used. The routine returns the message identifier and message pointer values of the message returned by the driver. The call to ELN$TTY_WRITE in step 4 specifies these values to reuse the message. Because no read options are specified, ELN$TTY_READ reads characters without interpretation while honoring input flow control. Write the data. Use a call to ELN$TTY_WRITE to read the data. The call to ELN$TTY_WRITE must specify the port connected in a circuit to a serial line's DDA port, a buffer, the size of the buffer, and a variable that receives a value indicating the amount of data that is written. You can also specify message object and message pointer arguments. In the sample module, ELN$TTY_WRITE echoes the data that is read back to the serial line. ELN$TTY_WRITE writes the number of characters read (size_read) from the buffer line_buffer, using the user-defined message for the data transfer. The message_ob) and messageJJtr arguments specify the message that was returned by the call to ELN$TTY_READ in step 3. The ELN$TTY_WRITE routine returns the message identifier and message pointer values of the message returned by the driver. Delete the message. Use a call to the DELETE procedure to delete the last message received from the driver. Disconnect the circuit to the DDA port. Use a call to DISCONNECT_CIRCUIT to disconnect the circuit to the DDA port. The sample module disconnects the circuit between appJob_ port and the DDA port CONSOLE$ACCESS. For information about establishing a circuit with a serial line's DDA port, see Section 14.4.5.1. For descriptions of the ELN$TTY_READ and ELN$TTY_WRITE procedures, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 14-56 VAXELN Device Drivers 14.4.5.4 Setting a Serial Line to the Spacing State An application program that must get the attention of a device attached to a serial line can do so by calling the ELN$TTY_ASSERT_BREAK procedure. This procedure sets a device's serial line to the spacing state. While in the spacing state, the serial line waits for a default or user-specified period of time and asserts a break. The wait ensures that all characters are transmitted to the device. All VAXELN terminal drivers except CONSOLE, DECW$CONSOLE, DECW$TE, and RTDRIVER support the ELN$TTY_ASSERT_BREAK procedure. When you call the procedure, you must specify the port connected in a circuit to the serial line's DDA port. Optionally, you can specify break options, a break duration period, and a break delay period. Break options specify the type of break that the serial line is to transmit. The break options are defined as follows: Option Description 1 Short break (235 milliseconds) 2 Long break (3.5 seconds) 4 User-specified break duration 8 User-specified break delay If you do not specify a break option, the serial line transmits a short break after transmitting all current output characters. If the predefined short and long breaks are not appropriate for your application, you can define your own break. You can define a break duration by specifying option 4 and a break duration period. Likewise, you define a break delay by specifying option 8 and a break delay period. You specify the duration and delay periods as time intervals as shown in the following example: delay := TIME_VALUE('O 00:02:00.00'); You can specify multiple break options by supplying a break option value that is the sum of the desired options. For example, to define break duration and delay periods, specify the value 12 (the sum of options 4 and 8) for the break option, as shown in the following example: VAXELN Device Drivers 14-57 VAR linel-port, dda-port stat : INTEGER; PORT; BEGIN { Establish a circuit connection with the serial line's DDA port. CREATE_PORT(linel-port); TRANSLATE_NAME (dda-port, 'TTA1$ACCESS', NAME$LOCAL); CONNECT_CIRCUIT (line1-port, DESTINATION_PORT := dda-port); ELN$TTY ASSERT BREAK (STATUS := stat, CIRCUIT := linel-port, OPTIONS := 12, DURATION := TIME VALUE('O 00:02:00.00'), DELAY := TIME_VALUE{'O 00:00:00.00')); END. When you specify multiple break options, the terminal driver applies the following precedence to determine the type of break to use: 1. Short break 2. Long break 3. User-defined break NOTE When you specify break option 4 or 8, you should also specify a break duration or delay period, as appropriate. If you specify option 4 and omit or specify 0 for the break duration period, the duration period is unpredictable. If you specify break option 8 and omit or specify 0 for the break delay period, the terminal driver does not impose a delay. For information about establishing a circuit with a serial line's DDA port, see Section 14.4.5.1. For a description of the ELN$TTY_ASSERT_ BREAK procedure, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 14-58 VAXELN Device Drivers 14.4.5.5 Monitoring the Use of Out-of-Band Characters VAXELN application programs can use the following terminal utility procedures to monitor the receipt of out-of-band characters: • • • ELN$TTY_SIGNAL_OOB_CHARACTERS ELN$TTY_RECEIVE_OOB_CHARACTER ELN$TTY_CANCEL_OOB_CHARACTERS A program can instruct a terminal driver to perform special actions based on the use of a specified character in the DEC Multinational Character Set. Before an application program can call ELN$TTY_SIGNAL_OOB_ CHARACTERS,ELN$TTY_RECEIVE_OOB_CHARACTER, and ELN$TTY_CANCEL_OOB_CHARACTERS, the program must establish a circuit with the serial line's DDA port (see Section 14.4.5.1). Once you establish the circuit, the application program can call ELN$TTY_ SIGNAL_OOB_CHARACTERS to request that the terminal driver notify the program when a serial-line device receives an out-of-band character. In the routine call, you specify the port connected in a circuit to the DDA port, user data, the response port that is to receive the outof-band character, and the out-of-band characters for which notification is requested. The ELN$TTY_SIGNAL_OOB_CHARACTERS routine signals the receipt of an out-of-band on a serial line or the console only if the line is not in the PASSALL or PASSTHRU state; if the line is in one of these states, the routine ignores the out-of-band character. However, if the line is in a temporary PASSTHRU state, the routine will signal the receipt of an out-of-band character. You specify the out-of-band characters by setting values in an outof-band character mask. Each element in the mask corresponds to a character in the DEC Multinational Character Set. Setting the value associated with an element to TRUE indicates that the terminal driver is to notify the application when the driver receives that character. You can also specify out-of-band character options in a call to ELN$TTY_SIGNAL_OOB_CHARACTERS. The options provide more control over the terminal driver's actions and are defined as follows: VAXELN Device Drivers 14-59 Option Description 1 Signal only once. The request for out-of-band character notification is canceled after the first datagram is sent. 2 Inel ude the out-of-band character in the input stream. If you do not specify an option, your application program receives all characters that match the specified out-of-band characters and the characters are not placed in the input stream. 'lb specify both options, specify 3, the sum of the two options. Mter you call the ELN$TTY_SIGNAL_OOB_CHARACTERS, you must wait on the response port as shown in the following call to WAIT_ANY: WAIT_ANY (response-port A subsequent call to ELN$TTY_RECEIVE_OOB_CHARACTER can then receive an out-of-band character from the terminal driver when the driver receives such a character. The call to this procedure must specify the response port that you specified in the call to ELN$TTY_ SIGNAL_OOB_CHARACTERS, user data, and a variable that is to receive the out-of-band character. The terminal driver sends a notification, in the form of a datagram, to the response port each time it receives an out-of-band character for which notification was requested. If you specified out-of-band character option 1 in the call to ELN$TTY_S I GNAL_M OD EM_EVENTS , the driver sends one datagram. Otherwise, the driver sends a separate datagram to your program each time an out-of-band character is received until you cancel the request with a call to ELN$TTY_CANCEL_ OOB_CHARACTERS. A call to this procedure must specify the port connected in a circuit to the serial line's DDA port. A user data argument (in calls to ELN$TTY_SIGNAL_OOB_ CHARACTERS and ELN$TTY_RECElVE_OOB_CHARACTER) lets you pass unmodified user-defined data between your program and the terminal driver. You might use this argument to distinguish different serial lines reporting out-of-band characters to the specified response port. Example 14-7 shows how you might use the ELN$TTY_SIGNAL_ OOB_CHARACTERS, ELN$TTY_RECEIVE_OOB_CHARACTER, and ELN$TTY_CANCEL_OOB_GHARACTERS procedures to monitor the transmission of out-of-band characters over a serial line. 14-60 VAXELN Device Drivers Example 14-7: Monitoring the Use of Out-of-Band Characters MODULE oob; INCLUDE $elnmsg, $pascalmsg, $kernelmsg, $get message text, $dda_utility, $dda; VAR dda...,.packet dda_msg dda...,.port my...,.port status response...,.port user data oob char mask oob char received { I/O packet } MESSAGE; PORT; Port to connect to Port for circuit connection} PORT; INTEGER := ELN$_SUCCESS; PORT; INTEGER : = 0; DDA$_OOB_CHAR_MASK := ZERO; CHAR; PROGRAM oob (INPUT,OUTPUT); VAR i : INTEGER; BEGIN { Establish a circuit connection with the serial line's DDA port. TRANSLATE_NAME (dda...,.port, 'TTA1$ACCESS', NAME$LOCAL); JOB_PORT(my...,.p0rt); { DDA circuit connection ID } CREATE_PORT (response...,.port, limit := 20); { Response port} CONNECT_CIRCUIT (my...,.port, DESTINATION_PORT := dda...,.port); oob_char_mask[ord('3')] := TRUE; oob_char_mask[ord('4')] := TRUE; { Choose '3' and '4' as the } { characters for which we want to } } { be notified. { Make the request. } ELN$TTY_SIGNAL_OOB_CHARACTERS(status, my...,.port, user_data, response...,.port, oob_char_mask); { Wait for notification from the driver. } WHILE NOT (done) DO BEGIN WAIT_ANY(response""'port); { Get the out-of-band character. Example 14-7 Cont'd on next page VAXELN Device Drivers 14-61 Example 14-7 (Cont.): Monitoring the Use of Out-of-Band Characters ELN$TTY_RECElVE_OOB_CHARACTER(status, response...,port, user data, oob_char_received); { The received character will either be a 3 or a 4. WRITELN('The received character is: END; ' ,oob_char_received); ELN$TTY CANCEL OOB CHARACTERS (status, mYJort) ; RETURN: DISCONNECT_CIRCUIT(my...,p0rt); END; END. For information about establishing a circuit with a serial line's DDA port, see Section 14.4.5.1. For a description of the ELN$TTY_ CANCEL_OOB_CHARACTERS,ELN$TTY_RECEIVE_OOB_ CHARACTER, and ELN$TTY_SIGNAL_OOB_CHARACTERS procedures, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. 14.4.6 Using Control Characters Unless you enable the passall, passthru, or DDCMP terminal characteristic, control characters identify special actions to be performed by the driver rather than actual characters to be sent to a program. Control characters have ASCII codes from 0 to 31 or equal to 127 (DELETE). Table 14-8 lists the control characters with corresponding ASCII codes and action taken. You generate the characters designated Ctrl/x, where x is a letter, by holding down the Ctrl key while pressing key x. 14-62 VAXELN Device Drivers In some cases, when the echo characteristic is enabled, a CtrVx character is echoed as a circumflex followed by the letter x - for example, AU for CtrVU. Table 14-8: Control Characters Terminal Key or Name Code Action Bell 7 Sound the terminal's bell or buzzer. BACKSPACE 8 Back up the cursor one character. This does not delete the previous character from the input. TAB, CTRUI 9 Advance to the next horizontal tab stop. The terminal controls the tab placement. LINE FEED, CTRL/J 10 Advance to the next line, without a carriage return. CTRLIK 11 Advance to the next vertical tab stop. The terminal controls the tab placement. CTRLIL 12 Advance to next page or display (form feed) and terminate the current input line. NO SCROLL,! CTRL/Q 17 Resume transmitting output from the program. CTRLIR 18 Redisplay the current input line. NO SCROLL,! CTRL/S 19 Suspend transmitting output from the program. CTRLIU 21 Erase the current input line. CTRLIZ 26 Designate end-of-file to the program and terminate the current input line. DELETE 127 Delete the previous character or, if escape recognition is in effect, the partial escape sequence from the input. ESC 27 Begin escape sequence if the escape recognition characteristic is enabled. Otherwise, echo a dollar sign ($), perform a carriage return and line feed, and terminate the current input line. !The key NO SCROLL, on VT100 and similar terminals, alternates between CtrllS (for the first and other odd-numbered keystrokes) and CtrllQ. VAXELN Device Drivers 14-63 Table 14-8 (Cont.): Control Characters Terminal Key or Name ENTER,2 RETURN Code Action 13 Perform a carriage return and line feed and terminate the current input line. 2The key ENTER, on the keypad of VT100 and similar terminals, is normally the same as RETURN. 14.4.7 Using Escape and Control Sequences When the escape recognition characteristic is enabled and you are using a regular terminal line, you can read escape sequences from a terminal with terminal driver checking syntax. In all cases, whether or not escape recognition is enabled, you can write escape sequences to perform actions specific to the terminal. (For example, the VT100-, VT200-, and VT300-series terminals let you control the cursor's movement with escape sequences.) The driver checks the syntax of escape sequences only on input and only when escape recognition is enabled. Only ANSI-format escape sequences, such as those used with VT100-, VT200-, and VT300-series terminals, are recognized on input. See the hardware documentation for your terminal for the set of escape sequences used with that terminal. When escape recognition is enabled, the terminal driver checks any sequence of input characters beginning with the ESC character (ASCII code 27) to determine whether the syntax is correct. An invalid sequence, including the ESC character itself, is effectively removed from the input. Pressing the Delete key in the middle of an escape sequence deletes the entire sequence from the input. The valid syntax is determined by an ANSI standard as follows (no space should separate the syntax elements): ESC character-sequence final-character character-sequence A sequence of zero or more characters, each of which has an ASCII code in the range 32 to 47. This range consists of the space character and 15 punctuation marks. 14-64 VAXELN Device Drivers final-character A single character that has an ASCII code in the range 48 to 127, which includes uppercase and lowercase letters, digits, and an assortment of punctuation marks. The following alternative forms are permitted: ESC ; character-sequence final-character ESC ? character-sequence final-character ESC ° character-sequence final-character With ESC 0, the final character can have an ASCII code in the range 64 to 127. The character sequence is the same in all cases. (The 8-bit character SS3 [8F16 J can introduce an escape sequence in place of ESC 0.) ANSI control sequences are also valid. In these sequences, the character sequence and final character are preceded by a left bracket ( [) and a sequence of parameter specifiers (no space should separate the syntax elements): ESC [ param-sequence char-sequence final-char The 8-bit character CSI [9B16J can be used to introduce an escape sequence, in place of ESC [. param-sequence Zero or more parameter specifiers, each of which has an ASCII code in the range 48 to 63. For example, for some control sequences on VT100-, VT200-, and VT300-series terminals, this is a sequence of digit characters separated by semicolons. char-sequence A sequence of zero or more characters, each of which has an ASCII code in the range 32 to 47. final-char A single character, which has an ASCII code in the range 64 to 127. For example, the following control sequence erases from the current cursor position to the end of the line on a VT100 terminal: ESC[OK The 0 is a parameter and the K is the final character. VAXELN Device Drivers 14-65 The following sequence turns on the bold and reverse video character attributes on a VT100 terminal: ESC[1;7m The 1 and 7 are parameters separated by a semicolon, and m is the final character. 14.4.7.1 Using VTS2-Type Escape Sequences The VT52 terminal uses escape sequences that do not comply fully with the ANSI format. VT100-, VT200-, and VT300-series terminals let you designate, in the terminal's set-up mode, that they will use VT52 escape sequences instead of the larger ANSI set supported on that terminal type. You should use ANSI escape sequences whenever possible. However, most VT52 escape sequences are compatible with the ANSI syntax and can be recognized if the terminal is set up in VT52 mode. For example, the following valid sequence erases from the cursor to the end of the screen on a VT52 terminal: ESCJ In ANSI terms, J is the final-character and there is no charactersequence. In contrast, the following control sequence, for positioning the cursor to line 2, column 2, is invalid: ESC! ! Here, the sequence is invalid in ANSI syntax because the finalcharacter (1) does not have an ASCII code in the range 48 to 127. 14.4.8 Using Modem Control Modems let you connect telephone or other remote lines with the terminal interface to access the target computer from remote terminals. The terminal drivers DHVDRIVER, DMBDRIVER, and YCDRIVER support modem control for modems such as the DF03 and DF224 in full-duplex, autoanswer mode. Of the eight asynchronous lines on a DMF-32, only the first two lines can be connected to modems. 14-66 VAXELN Device Drivers You can include modem support in a VAXELN system by selecting Yes for the Modem entry on the System Builder's Terminal Description Menu when you build your system. For more information, see the VAXELN Development Utilities Guide. A modem is controlled by a set of signals it exchanges with a target computer. The terminal driver transmits and interprets these signals. To be usable, the modem must support all signals listed in Table 14-9. Table 14-9: Modem Control Signals Signal Name Source Action TxD (transmitted data) Computer Identifies data originated by the computer and transmitted through the modem to one or more remote terminals. RxD (received data) Modem Identifies data generated by the modem, in response to signals received from a remote terminal, and sent to the computer. RTS (request to send) Computer If present, RTS tells the modem to enter transmission mode; if absent, the modem leaves transmission mode after data transmission is complete. CTS (clear to send) Modem If present, CTS tells the computer that the modem is ready to transmit data; if absent, it tells the computer that the modem is not ready. DSR (data set ready) Modem If present, DSR tells the computer that the modem is ready to operate. That is, the modem is connected to the line properly and is ready to exchange more signals. If absent, it tells the computer that the modem is not ready. CARRIER Modem If present, CARRIER tells the computer that the signal received on the data channel line is within the limits specified for the modem. If absent, it tells the computer that the received signal is not within these limits. VAXELN Device Drivers 14-67 Table 14-9 (ConI.): Modem Control Signals Signal Name Source Action DTR (data terminal ready) Computer If present, DTR tells the modem that the computer is ready to operate, prepares the modem for connection to the telephone line, and maintains this connection after it is made. DTR can be present whenever the computer is ready to transmit or receive data; if it is absent, the modem disconnects itself from the line. RING Modem If present, RING tells the computer that a calling signal is being received by the modem (for example, a remote telephone user has dialed the computer's telephone number). When modem control is enabled for a terminal line, the line is monitored continually by the interface hardware for the RING signal. If the driver detects the CARRIER and DSR signals, the ring is answered whether or not a read request is pending for the line. If the line's CARRIER signal is lost, the driver waits 2 seconds for it to reappear. If it does not, the driver returns an error to any current or future read request. 14.4.8.1 Retrieving and Setting Modem Characteristics If you build terminal modem support into your VAXELN system, you can use the ELN$TTY_GET_CHARACTERISTICS and ELN$TTY_ SET_CHARACTERISTICS procedures to retrieve and set the modem characteristics listed in Table 14-10. Table 14-10: Modem Characteristics Characteristic Description Modem control The type of modem control in effect. The modem can be controlled by the terminal driver or the user. The driver controls the modem by default. Not all serial-line devices support the setting of this characteristic. 14-68 VAXELN Device Drivers Table 14-10 (Cont.): Modem Characteristics Characteristic Description RING A Boolean value that specifies whether the terminal's modem RING indicator is set. You cannot set this characteristic. CD (carrier detect) A Boolean value that specifies whether the tenninal's modem CD indicator is set. You cannot set this characteristic. CTS (clear to send) A Boolean value that specifies whether the tenninal's modem CTS indicator is set. You cannot set this characteristic. DSR (data set ready) A Boolean value that specifies whether the tenninal's modem DSR indicator is set. You cannot set this characteristic. DTR (data tenninal ready) A Boolean value that specifies whether the terminal's modem DTR indicator is set. To set this characteristic, the modem control characteristic must be set to DDA$_MODEM_CONTROL_USER, and the Modem entry on the System Builder's Tenninal Description Menu must be set to Yes. Not all serial-line devices support the setting of this characteristic. RTS (request to send) A Boolean value that specifies whether the tenninal's modem RTS indicator is set. For information about using the ELN$TTY_GET_CHARACTERISTICS and ELN$TTY_SET_CHARACTERISTICS procedures, see Section 14.4.5.2. 14.4.8.2 Monitoring Modem Events Programs in systems that support modem control (that is, systems that include the terminal driver DHVDRIVER, DMBDRIVER, or YCDRlVER and terminal· modem support) can use the terminal utility procedures ELN$TTY_SIGNAL_MODEM_EVENTS, ELN$TTY_ RECEIVE_MODEM_EVENTS, and ELN$TTY_CANCEL_MODEM_ EVENTS to monitor modem events. VAXELN Device Drivers 14-69 Before an application program can call these procedures, the program must establish a circuit with the serial line's DDA port (see Section 14.4.5.1). Once you establish the circuit, the application program can call ELN$TTY_SIGNAL_MODEM_EVENTS to request that the terminal driver notify the program when a serial line's modem state changes. In the routine call, you specify the port connected in circuit to the DDA port, user data, and the response port that is to receive the modem state change data. You must then wait on the response port as shown in the following call to WAIT_ANY: WAIT~NY(response_port) A subsequent call to ELN$TTY_RECEIVE_MODEM_EVENTS can then receive modem state change information from the terminal driver. The call to this routine must specify the response port that you specified in the call to ELN$TTY_SIGNAL_MODEM_EVENTS, user data, and a pointer that indicates the record that is to receive the modem state change information. The terminal driver sends a notification, in the form of a datagram, to the response port each time the modem's state changes. The modem state change information is then stored in a record that identifies the following: • • • • • • • • • The revision level of the modem event information record The type of modem control in effect (driver or user) If the driver is controlling the modem, the modem's current state (connected or disconnected) Whether the terminal's modem RING indicator is set Whether the terminal's modem CD indicator is set Whether the terminal's modem CTS indicator is set Whether the terminal's modem DSR indicator is set Whether the terminal's modem DTR indicator is set Whether the terminal's modem RTS indicator -is set The driver continues to send the modem event information to your program until you cancel the request with a call to ELN$TTY_CANCEL_ MODEM_EVENTS. A call to this procedure must specify the port connected in a circuit to the serial line's DDA port. 14-70 VAXELN Device Drivers A user data argument (in calls to ELN$TTY_SIGNAL_MODEM_ EVENTS and ELN$TTY_RECElVE_MODEM_EVENTS) lets you pass unmodified user-defined data between your program and the terminal driver. You might use this argument to distinguish between serial lines reporting modem state changes to the specified response port. Example 14-8 shows how you might use the ELN$TTY_SIGNAL_ MODEM_EVENTS, ELN$TTY_RECEIVE_MODEM_EVENTS, and ELN$TTY_CANCEL_MODEM_EVENTS to monitor a serial line's modem events. Example 14-8: Monitoring Modem Events INCLUDE $DDA_UTILITY; PROGRAM getmodem; VAR line1yort ddayort modem_eventsyort modem_eventytr user_data PORT; PORT; PORT; ADDA$_MODEM EVENT INFORMATION; INTEGER; BEGIN { Establish a circuit connection with the serial line's DDA port. } CREATE_PORT(line1yort); CREATE_PORT(modem_eventsyort); TRANSLATE_NAME (ddayort, 'TTA1$ACCESS', NAME$LOCAL); CONNECT_CIRCUIT (linelyort, DESTINATION PORT := ddayort); { Request to be signaled when modem events occur on line 1. } ELN$TTY_SIGNAL_MODEM_EVENTS(CIRCUIT := line1yort, USER DATA := user data, RESPONSE_PORT := mOdem_eventsyort); { Process all modem change events. } Example 14-8 Cont'd on next page VAXELN Device Drivers 14-71 Example 14-8 (Cont.): Monitoring Modem Events WHILE TRUE DO BEGIN { Wait for the driver to signal a mode status change occurrence. } WAIT_ANY(modem_events-port); { Get the modem status change information. } ELN$TTY~CEIVE_MODEM_EVENTS(RESPONSE_PORT := modem_events-port, USER DATA := user data, MODEM_EVENT_PTR modem_event-ptr); WITH modem_event-ptrA do BEGIN := Do something with the modem state information. For example, you might notify the user if the line was disconnected. } } } END; END; { Cancel notification request. } END. END; You can also monitor a serial line's modem characteristics, except the revision level and modem state, by calling ELN$TTY_GET_ CHARACTERISTICS. If the modem is user-controlled, you can use the ELN$TTY_SET_CHARACTERISTICS procedure to set the DTR and RTS characteristics. For more information about retrieving modem characteristics, see Sections 14.4.5.2 and 14.4.8.1. 14-72 VAXELN Device Drivers 14.4.9 Performing Parallel 1/0 You can use the parallel port on a DMF-32 device as a line printer port or to send and receive up to 16 bits of data on 16 parallel lines. The Pascal source file DR11C.PAS, included in the VAXELN Toolkit, contains declarations of the DMF-32 device registers suitable for using the device's parallel port for digital input and output. You can use the source file DR11C.PAS as a template to write programs that perform parallel I/O. Use the type and variable declarations as delivered and modify the rest of the code to fit your application needs. In some cases, you need to add just a PROGRAM block that uses the declarations the module provides. In addition to the register declarations, the module provides templates for the following: • • • An ISR and communication region An initialization procedure that creates DEVICE objects representing the device's request A and request B lines, as well as initializing the parallel port for digital 110 instead of for a line printer 110 procedures to read and write a 16-bit word of data from the device 14.5 Small Computer System Interface Driver The VAXELN Toolkit provides a driver image that supports the American National Standards Institute, Small Computer System Interface (SCSI) devices on MicroVAX, VAXstation, and rtVAXstation 3100 series systems. The image includes a disk class driver (SCSIDISK) and a generic class driver (SCSIGNRC). • • The disk class driver supports RZ22, RZ23, RZ55, and RZ56 Winchester disks, RX23 SCSI diskettes, and RRD40 compact discs. The generic class driver provides an interface for all other types of SCSI devices, including scanners, optical devices, test equipment, and medical devices. VAXELN application programs use a supplied message interface to communicate with the generic class driver. VAXELN Device Drivers 14-73 A system can support up to two SCSI buses and each bus can support up to eight devices: a SCSI host adapter and up to seven device controllers connected to the SCSI bus. An integer in the range 0 to 7 uniquely identifies each of the SCSI devices. Each device controller supports one device unit; that is, VAXELN systems support only logical unit number (LUN) O. Only two devices connected to a SCSI bus can communicate on the bus at any given time. On VAXELN systems, the host adapter initiates communication to another device. The target device then performs a task. SCSI devices usually have a fixed role as an initiator or target, although some devices can perform both roles. On VAXELN systems, the host adapter is always the initiator and the device controllers are targets; target devices cannot handle selection operations. The VAXELN SCSI driver image employs a class/port driver architecture for device communication. The architecture clearly defines class and port driver responsibilities. The class drivers are deviceindependent and provide standard interfaces to an underlying port driver (see Figure 14-2). The class drivers format commands, interpret status values, and manage user data. The port driver monitors and controls SCSI bus phase changes and sends and receives SCSI path control messages. Using this architecture, you can develop a class driver without regard to the underlying port software and hardware. You can use the VAXELN SCSI driver image for third-party SCSI devices that attach to MicroVAX, VAXstation, and rtVAXstation 3100 series systems. The disk class driver supports disk and compact disc devices, while the generic class driver supports all other devices. You can also combine a user-written SCSI class driver with the supplied VAXELN SCSI port driver to produce a vendor-specific VAXELN SCSI driver image. You can then build that image into a VAXELN system. NOTE The American National Standard for Information SystemsSmall Computer System Interface-2 (SCSI-2) specification allows flexibility for some device implementation details and omits other details. Thus, implementations of the SCSI standard may differ from manufacturer to manufacturer 14-74 VAXELN Device Drivers Figure 14-2: SCSI Class/Port Driver Architecture VAXELN System SCSI Host Adapter MLO-004169 and from device to device. Although you can use thirdparty devices with the VAXELN SCSI disk class driver, the VAXELN Toolkit does not necessarily support such devices. Digital does not guarantee that third-party devices that currently run with the supplied class driver will continue to run under subsequent releases of the VAXELN Toolkit. At this writing, the Small Computer System Interface is under development. The draft American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) specification (Revision lOb) should be the official guide to what a third-party device implements. To ensure that your third-party device will work properly in a VAXELN environment, Digital encourages the use of an established and supported VAXELN interface, such as those described in Sections 14.5.1 to 14.5.3. VAXELN Device Drivers 14-75 Sections 14.5.1, 14.5.2, and Section 14.5.3 explain how to build thirdparty SCSI device support into VAXELN systems using the following: • • • VAXELN SCSI disk class driver VAXELN SCSI generic class driver message interface A user-defined class driver The decision as to which method to use for a particular SCSI device application is left to the application designer. The designer should consider the SCSI device's capabilities, user needs, and available programming resources. For information about building the SCSI driver into a VAXELN system, see the VAXELN Development Utilities Guide. For more information about Digital's implementation of the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) specification and how to use the implementation to develop SCSI peripheral devices that are currently available through Digital, see Small Computer System Interface: An Overview and Small Computer System Interface: A Developer's Guide. 14.5.1 Using the VAXELN SCSI Disk Class Driver The device-independent design of the VAXELN SCSI disk class driver enables it to control most disk and compact disc device drives that conform to the American National Standard for Information SystemsSmall Computer System Interface-2 (SCSI-2) specification. If your third-party device conforms to the specification, you should consider using the supplied disk class driver for your system. If you use the supplied SCSI driver image for a third-party disk or compact disc device and your application does not need the generic SCSI device support, you should consider removing the generic device support from the SCSI driver. You can remove device support from the supplied driver by modifying the VAXELN SCSI driver start-up module. For information about modifying this module, see Section 14.5.3.1. 14-76 VAXELN Device Drivers 14.5.2 Using the VAXELN SCSI Generic Class Driver The VAXELN SCSI generic class driver provides support for third-party SCSI devices that do not require file system services. 1YPical generic SCSI devices include devices such as scanners, optical devices, test equipment, and medical devices. An application that uses a SCSI generic device communicates with the generic class driver, using a generic class driver message interface. The interface consists of the following runtime routines: Routine Description ELN$SCSCCONNECT_DEVICE Connects the application to a SCSI device process. ELN$SCSCDISCONNECT_DEVICE Disconnects the circuit between the application and a SCSI device process. ELN$SCSCFREE_CONFIG_DATA Deletes a message object containing SCSI bus configuration data from the system. ELN$SCSCFREE_CONTROL_PORT Deletes application's source control port from the system. ELN$SCSCGET_CONFIG_DATA Returns SCSI bus configuration data from the generic class driver. ELN$SCSCGET_CONTROL_PORTS Connects the application to the generic class driver and returns the source and destination control ports used to establish the connection. ELN$SC SCI SSUE_COMMAND Delivers a SCSI command to a target SCSI device. ELN$SCSCMAP_MESSAGE_BUFFER Creates a message for sending SCSI commands and data to a SCSI device. ELN$SCSCUNMAP_MESSAGE_BUFFER Deletes a message used to send SCSI commands and data to a SCSI device. Sections 14.5.2.1 to 14.5.2.4 explain how to use the interface routines to do the following: VAXELN Device Drivers 14-77 • • • • Connect to the generic class driver Get configuration data for devices attached to a SCSI bus from the generic class driver Connect to SCSI devices Issue SCSI commands To use the message interface routines, you must include the appropriate modules from the VAXELN runtime libraries. Language Module VAXELN Pascal $SCSCUTILITY C $scsi_utility FORTRAN ELN$:FORTRAN_DEFS.FOR For descriptions of the message interface routines, see the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, or VAXELN FORTRAN Runtime Library Reference Manual. Section 14.5.2.5 shows an example (see Example 14-9) of how you might use the message interface routines to program communication between a SCSI bus and a third-party SCSI generic device. In addition to programming communication to the generic device driver, you may want to tailor the SCSI driver to your application. That is, if you use the supplied SCSI driver image for a third-party generic device and your application does not need the SCSI disk device support, you should consider removing the disk device support from the SCSI driver. You can remove device support from the supplied driver by modifying the VAXELN SCSI driver start-up module. For information about modifying this module, see Section 14.5.3.1. 14.5.2.1 Connecting to the Generic Class Driver To use the SCSI generic class driver message interface, an application must first connect to the driver by calling the message interface routine ELN$SCSI_GET_CONTROL_PORTS. This routine creates two control ports - one for the calling job and one for the driver - and establishes a circuit connection between the ports. Once the circuit is established, the application can use it to issue requests for the following: • Configuration data about the devices attached to the SCSI bus 14-78 VAXELN Device Drivers • Connections to SCSI devices A call to ELN$SCSI_GET_CONTROL_PORTS must specify the name of a SCSI bus controller and two port variables. The controller name that you specify must match the device name that you specify when configuring the SCSI bus at build time. For example, if you specify the device name DUA, you must specify DUA when you configure the bus with the System Builder. Source and destination port variables receive the control port values. The source port variable receives the message port value for the calling job. The destination port variable receives the generic class driver port value for the specified device controller. If your application needs to communicate with devices on two SCSI buses, you might design the application such that communication for devices on each bus is handled by a separate process. In this case, each process would call ELN$SCSI_GET_CONTROL_PORTS to establish a circuit connection for each bus. When a connection to the generic class driver is no longer needed, the application should free the resources associated with source port by calling ELN$SCSI_FREE_CONTROL_PORT. The following section of C code shows how you might establish a circuit connection for the bus controller named DUA and free the source port when it is no longer needed: VARYING_STRING_CONSTANT(scsiyort_name, "DUA"); PORT PORT int source_controlyort; destination_controlyort; status; status = eln$scsi_get_controlyorts(&scsiyort_name, &source_controlyort, &destination_controlyort); VAXELN Device Drivers 14-79 14.5.2.2 Requesting SCSI Bus Configuration Data Once an application connects to the generic class driver, the application can use the circuit connection to request SCSI bus device configuration data from the driver. The VAXELN SCSI driver stores the configuration data for each SCSI bus in a table and sends that data to applications in a message upon request. The configuration data includes information that the application needs to connect to the devices on the bus. To retrieve the configuration data, an application must call the ELN$SCSI_GET_CONFIG_DATA routine. Specify the routine with the source and destination ports returned by ELN$SCSI_GET_CONTROL_ PORTS for a particular bus. You must also specify a variable that receives a pointer to the SCSI bus configuration table. The table that the application receives includes information about the message that was used to transfer the data and the data for each device attached to the bus. The message information includes an error code, the message identifier, the size of the message in bytes, and an array that identifies the devices on the bus for which information was returned. The error code indicates whether the request was successful (ELN$_SUCCESS) or unsupported (ELN$_UNSUPPORTED). Table 14-11 lists the characteristics returned for each device (the host adapter and device controllers). Table 14-11: SCSI Device Characteristics Characteristic Description Valid data A flag that indicates whether a device exists for the SCSI bus identifier. If the flag is set to 1, a device is physically attached and the data in the table entry is valid. If the flag is set to 0, the data in the entry is ignored. 14-80 VAXELN Device Drivers Table 14-11 (Cont.): SCSI Device Characteristics Characteristic Description Device type An integer that identifies the type of peripheral device that is attached to the SCSI bus. The value can be one of the following: Value Device Type 0 Direct-access device 1 Sequential-access device 2 Printer device 3 Processor device 4 Write-once, read-multiple device 5 CDROM device 6 Scanner device 7 Optical memory device 8 Medium changer device 9 Communications device 10 to 30 Reserved 31 Unknown or no device type You can get the value for a device by using the SCSI INQUIRY command (see the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2J specification). Class attached A flag that indicates whether a class driver is assigned to the device. If the flag is set to 1, the device is not available to other class drivers. If the flag is set to 0, the device is available to other class drivers. Current connection A flag that informs the generic class driver whether a class driver has made a connection to the device. If the flag is set to 1, the device is currently being used. If the flag is set to 0, the device is not currently being used. Removable media A flag that indicates whether the device is removable. If the flag is set to 1, the device is removable. If the flag is set to 0, the device is not removable. VAXELN Device Drivers 14-81 Table 14-11 (Cont.): SCSI Device Characteristics Characteristic Description Product identifier A 16-byte ASCII text string that identifies the device type. You can get the product identifier for a device by using the SCSI INQUIRY command (see the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI2) specification). To connect successfully to a SCSI device, an application must use the configuration data to determine whether the following conditions exist: • • • A device exists for the SCSI bus identifier (valid data is set to 1) A class driver is assigned to the device (class attached is set to 1) The driver is not connected (current connection is set to 0) Thus, the valid data and class attached attributes must be set and the current connection attribute must be cleared. When the configuration data is no longer needed, the application should free the resources used for the configuration data message by calling ELN$SCSI_FREE_CONFIG_DATA. The following section of C code shows how you might retrieve the configuration data for a SCSI bus, check the configuration data for a direct access device that is not currently connected, and free the configuration data message when it is no longer needed: VARYING_STRING_CONSTANT{scsiyort_name, "DUA"); PORT PORT struct scsi$config_msg int int source_controlyort; destination_control-port; *config_msgyrt; scsi device status; status = eln$scsi_get_controlyorts{&scsiyort_name, &source_control-port , &destination_controlyort); 14-82 VAXELN Device Drivers status = eln$scsi_get_config_data(&source_control-port, &destination_control-port &config_msg-ptr); for (scsi device = 0; scsi device < SCSI$K_MAX_UNITS; scsi_device++) if «config_msg-ptr -> (config info.config tbl[scsi device]. valid data) && (config_isg-ptr->config_info. config_tbl [scsi_device] . device type == 0) && (config_msg-ptr->config_info. config_tbl [scsi_device] . class attached) && (!config:msg-prt->config_info.config_tbl[scsi_device]. current_connection» break; 14.5.2.3 status = eln$scsi_free_config_data(&config_msg-ptr); status = eln$scsi~free_control-port(&source_control-port); Connecting to SCSI Devices If an application determines from the bus configuration data that the data for a device is valid, a class driver is assigned to the device, and the device is not already connected, the application can connect to it by calling ELN$SCSI_CONNECT_DEVICE. A call to this routine creates a driver process for handling communication for the device and connects that process to your application. When an application connects to a SCSI device, the call to ELN$SCSI_ CONNECT_DEVICE must specify the control ports returned by ELN$SCSI_GET_CONTROL_PORTS for a particular bus, a variable that receives a circuit port value, a process priority, and the SCSI ID for the device to which the application is connecting. The connection request is sent over the circuit connection between the control ports. When the driver receives the request, it creates a process for the specified SCSI device and assigns the specified priority to that process. The driver also creates a message port for the process and connects that port to the application's control port; the new port value is returned to the circuit port argument. VAXELN Device Drivers 14-83 The process priority must be an integer in the range 0 to 15. The highest priority is 0; Digital recommends a priority of 10. If you specify a value that is not in the valid range, the driver uses the default value of 10. A value other than 10 can adversely affect system performance. If your a.pplication needs to communicate with multiple SCSI devices, you might design the application such that communication for each device is handled by a separate application process. In this case, each process would call ELN$SCSI_CONNECT_DEVICE to establish a circuit connection for each device. When the circuit between the application and the driver's device process is no longer needed, the application should disconnect it by calling ELN$SCSI_DISCONNECT_DEVICE. You must specify the circuit port returned by ELN$SCSI_CONNECT_DEVICE. The routine disconnects the circuit port from the application's circuit port, deletes the device process, returns the PORT and PROCESS objects to the system's kernel object pool, and returns the device to the available list. The following section of C code connects to a device associated with SCSI ID 3 and disconnects the driver's device process when the connection is no longer needed: VARYING_STRING_CONSTANT(scsiyort_name, "DUA"); PORT PORT PORT struct scsi$config_msg int int source_controlJ>ort; destination_controlJ>ort; deviceyrocessyort; *config_msgyrt; scsi_device status; status = eln$scsi_get_controlyorts(&scsiyort_name, &source_controlJ>ort, &destination_controlyort); status = eln$scsi_get_config_data(&source_controlyort, &destination_controlJ>ort &config_msgytr); 14-84 VAXELN Device Drivers for (scsi device = 0; scsi device < SCSI$K MAX UNITS; scsi_device++) if «co;fig_msgytr -> (config info.config thl[scsi device]. valid_data) && (config_msgytr->config_info. config_thl [scsi_device] . device type == 0) && (config_msgytr->config_info.config_thl[scsi_device] . class attached) && (!config=msgyrt->config_info.config_tbl[scsi_device] . current_connection» break; status = eln$scsi_connect_device(&source_controlyort, &destination_controlyort, &deviceyrocess_port, 10, scsi_device) ; eln$scsi_disconnect_device(&deviceyrocessyort); 14.5.2.4 status eln$scsi_free_config_data(&config_msgytr); status eln$scsi_free_controlyort(&source_contro1yort); Issuing SCSI Commands Once an application is connected to a SCSI device, the application can use the connected circuit to issue SCSI commands. Commands are sent to a device in a message that the application creates with a call to ELN$SCSI_MAP_MESSAGE_BUFFER. After creating the message, the application can specify the message identifier in subsequent calls to ELN$SCSI_ISSUE_COMMAND. SCSI command messages include a header and a command buffer. Optionally, the message can include a buffer for read and write data. The following figure shows the SCSI command message format: VAXELN Device Drivers 14-85 Header I Command Buffer I Data Buffsr MLO-004171 An application must specify ELN$SCSI_MAP~MESSAGE_BUFFER with variables that are to receive the message object identifier and a pointer to the command buffer. The routine call must also specify the size of the command buffer in bytes. The buffer size cannot exceed 256 bytes. A call to ELN$SCSI_MAP_MESSAGE_BUFFER can also specify a variable that is to receive a pointer to the data buffer, the size of the data buffer, and a pad size. If you specify the data buffer argument, you must also specify a size for the buffer. The size of the data buffer can range from 1 to 65,536 bytes; 0 bytes is the default. The pad size argument is for SCSI device commands that require a transfer size that is larger than the size specified by the data buffer size argument. If the amount of data requested in a SCSI command exceeds the space allocated for the data buffer, the pad size accounts for the difference. For example, the SCSI READ command transfers data in logical blocks - 512-byte units. Suppose an application uses the READ command to read the first two bytes of a disk block. The call to ELN$SCSI_ MAP_MESSAGE_BUFFER will specify 2 for the data buffer size to accommodate the two bytes to be read. Since the READ command reads data a block at a time, the call must also specify a pad size of 510 to account for'the extra 510 bytes. Once the message is created, the application can use it to issue SCSI commands, such as INQUIRY, READ, and WRITE. To issue a command, the application must use the ELN$SCSI_ISSUE_COMMAND routine. A call to this routine must specify variables that are to receive the status byte returned by the target device (as defined by the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) specification) and the status value returned by a SCSI port driver. The status value that the port driver returns indicates whether the command was completed successfully or whether a controller or timeout error occurred. 14-86 VAXELN Device Drivers When issuing a SCSI command, the application must also specify the following: • • • • • • • • • • A port returned by a call to ELN$SCSI_CONNECT_DEVICE The SCSI ID for the device to which the application is issuing the command Whether data is being sent or received Whether the target device can disconnect during command execution Whether the initiator and target devices support synchronous mode for data transfers Whether the port driver should attempt to repeat a command that fails due to a timeout, bus parity, or invalid phase transition error A phase timeout value A disconnect timeout value The identifier for the message object created by a call to ELN$SCSI_MAP_MESSAGE_BUFFER The message command buffer pointer returned by the call to ELN$SCSI_MAP_MESSAGE_BUFFER Optionally, the routine call can specify the message data buffer pointer. The values you can specify for the direction, disconnect, synchronous, and port retry arguments are defined as follows: Values Descriptions Direction Target device enters a Data In phase to send data to the initiator. Target device enters a Data Out phase to receive data from the initiator. VAXELN Device Drivers 14-87 Values Descriptions Disconnect SCSI$K_DISCONNECT Target device can disconnect. SCSI$K_NODISCONNECT Target device cannot disconnect. Target devices that remain connected to a bus for long periods of time can adversely affect system performance. Synchronous Initiator and target devices support synchronous mode for data transfers. SCSI$K_NOSYNCH The initiator or a target device does not support synchronous mode for data transfers. Currently, the port driver does not support synchronous mode data transfers. There(ore, you must specify SCSI$K_NOSYNCH. Port Retry Port driver can retry a command that fails due to a timeout, bus parity, or invalid phase transition error up to three times. SCSI$K_NORETRY Port driver cannot retry a command that fails due to a timeout, bus parity, or invalid phase transition error. If you do not specify a size for the message data buffer in the call to ELN$SCSI_MAP_MESSAGE_BUFFER, the driver ignores the direction argument. The phase and disconnect timeout values an application specifies can range from 0 to 420 seconds. The phase timeout value specifies the amount of time a target device has to change to another SCSI bus phase or to complete a data transfer. The disconnect timeout value specifies the amount of time a target device has to reselect an initiator to proceed with a disconnected data transfer. If you specify 0 or an invalid value, the driver uses a timeout value of 20 seconds. 14-88 VAXELN Device Drivers You can use ELN$SCSI_ISSUE_COMMAND to issue commands that are in the Common Command Set (CCS) for direct access devices. For information about these commands, see the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) specification. When a SCSI command message is no longer needed, the application should delete the message by calling ELN$SCSI_UNMAP_MESSAGE_ BUFFER. You must specify the message identifier returned by the call to ELN$SCSI_MAP_MESSAGE_BUFFER. The routine deletes the message object and returns the resources to the system's kernel pool. The following section of C code calls a function that creates a SCSI command message and uses it to issue a SCSI INQUIRY command. When the function returns, the module uses the returned data and then deletes the command message. struct inquiry info { unsigned char device type:S; unsigned char perif_qual:3; unsigned char resvOl:7; unsigned char rmb:l; unsigned char ansi ver:3; unsigned char ecma-ver:3; unsigned char iso ver:2; unsigned char rd_format:4; unsigned char resv03:2; unsigned char trmiop:l; unsigned char aenc:l; unsigned char add length; unsigned char resv05; unsigned char resv06; unsigned char stfre:l; unsigned char cmdque:l; unsigned char resv07:1; unsigned char linked:l; unsigned char sync:l; unsigned char wbus16:1; unsigned char wbus32:1; unsigned char reladr:l; unsigned char vendor ideS]; unsigned char product id[16]; unsigned char product=rev[4]; {18,O,O,O,36,O}; VAXELN Device Drivers 14-89 PORT PORT PORT struct inquiry_info MESSAGE unsigned char int int int status source_control-port ; destination_control_port; device-process-port; *inquiry data; inquiry msg obj; scsi status-byte; scsi~ort_status; scsi device status; get_inquiry_info(&device-process-port, scsi device, &scsI status byte, &scsi~ort_status, &inquiry data, &inquiry=:msg_obj) ; /* * Use the inquiry data. */ status int get inquiry info(PORT *device-process-port, int scsi id, unsigned char *status byte, int *port status, char *inqj>rt, MESSAGE *inCLobj) int char status i, status; *scsi_cmd-prt; = eln$scsi_map_message_buffer(inCLobj, &scsi_cmd-ptr, sizeof(inquirycmd), inct....Ptr , sizeof(struct inquiry_info), NULL) ; for(i = 0; i < sizeof(inquiry cmd); i++) scsi_cmd-ptr[i] = inquiry_cmd[i]; 14-90 VAXELN Device Drivers eln$scsi issue command( status_byte, port status, circuit-port, scsi id, SCSI$K READ, SCSI $K=DISCONNECT , SCSI$K NOSYNC, SCSI$K=RETRY, 0, 0, in config_info.config_tbl[test_device]~valid_data) && (config_msg-ptr->config_info.config_tbl[test_device].device_type DIRECT ACCESS DEVICE) && (config_msg-ptr->config_info.config_tbl[test_device] . class_attached) && (!config_msg-ptr->config_info.config_tbl[test..;.device] . current_connection) break; /* * * Check whether a SCSI .device has been found. If not; exit because no devices are available for testing. */ if (test_device != SCSI$K MAX UNITS) /* * * Connect the application to the SCSI device found in the configuration data. Set the generic class driver process priority to 10. */ status = eln$scsi_connect_device(&src_dg-port, &dest_dgyort, &circuit-port, 10, test_device) ; status get_inquiry_info(&circuityort, test_device, &scsi status byte, &scsi:port_status , &inquiry_data, &inquiry_msg_obj); /* * * * Use the inquiry data. When the data is no longer needed, unmap the SCSI command message buffer to free system resources and memory. */ Example 14-9 Cont'd on next page 14-96 VAXELN Device Drivers Example 14-9 (Cont.): Programming a SCSI Generic Class Driver Message Interface Application status = eln$scsi_unmap_message_buffer(&inquiry_msg_obj); /* * Issue a START UNIT command to the specified device. *1 status = go_spinup_drive(&circuit-port, test_device); /* * I~sue a TEST UNIT READY command to wait for the drive to spin up. */ status = go_wait_for_unit_ready(&circuit-port, test_device); = xfer size 512; num of blocks = «xfer size+511) » 9); 1* Divide by 512. pad:size = (num_of_blo~ks * 512) - xfer_size; *1 1* * The following code assumes that the read buffer, write buffer, * and SCSI READ and WRITE commands are all of the same size. *1 /* * Map a buffer for the read request. *1 status = eln$scsi - map message buffer(&rd msg obj, &rd-crnd:sizeof(read cmd) , &rd buff, xfe-; size, pad_size) ; 1* * Map a buffer for the write request. *1 status eln$scsi map message buffer(&wrt msg obj, &wrt-cmd:sizeof(write cmd), &wrt buff, xfer-size, pad_size) ; 1* * Initialize the read buffer to all ones. *1 Example 14-9 Cont'd on next page VAXELN Device Drivers 14-97 Example 14-9 (Cont.): Programming a SCSI Generic Class Driver Message Interface Application for (i=O; i < xfer size; i++) rd_buff [i] = OY.FF; /* * Issue a READ command. */ status go_issue_read_write_cmd(&circuit-port, test device, &rd cmd, &rd-buff, &rd-msg obj, read cmd, sizeof(read cmd), num of blocks, block,SCSI$K_READ) ; /* * Write the complement of the data just read into the write buffer. */ for (i=O; i < xfer size; i++) wrt_buff[i] = -rd~buff[i]; /* * Issue a WRITE command, using the write buffer. */ status go_issue_read_write_cmd(&circuit-port, test device, &wrt-cmd, &wrt-buff, &wrt- msg obj, write cmd, sizeof(write cmd) , num_of_blocks, block, SCSI$K_WRITE ); /* * Initialize the write buffer. */ for (i=Oi i < xfer size; i++) wrt~uff[i] = OxFF; Example 14-9 Cont'd on next page 14-98 VAXELN Device Drivers It will be used for the next read. Example 14-9 (Cont.): programming a SCSI Generic Class Driver Message Interface Application /* * * Read the data just written to the device. The write buffer will be used for the return data this time. */ status gO_i s sue_re ad_writ e_cmd (&circuit-port, test device, &wrt-cmd, &wrt-buff, &wrt- msg obj, read-cmd~ sizeof(read cmd), num of blocks, block, SCSI$K_ READ ); /* * write the complement of the data just read. */ for (i=O; i < xfer size; i++) wrt_buff[i) = -wrt_buff[i); /* * * write the complemented data to the device. be the original data. This should */ status go_issue_read_write_cmd(&circuit-port, test_device, &wrt cmd, &wrt-buff, &wrt- msg obj, write cmCi, sizeof(write cmd), num_of_blocks, block, SCSI$K_WRITE ); /* * Initialize the write buffer. It will be used for the next read. */ for (i=O; i < xfer size; i++) wrt_buff[i) = OxFF; Example 14-9 Cont'd on next page VAXELN Device Drivers 14-99 Example 14-9 (Cont.): Programming a SCSI Generic Class Driver Message Interface Application /* * * Read the complemented data. read. The data should be the original data */ status = go_issue_read_write_cmd(&circuit-port, test device, &wrt-cmd, &wrt -buff, &wrt- msg obj, read-cmd; sizeof(read cmd) , num of blocks, block,SCSI$K_READ ); /* * Return the resources back to the system. */ status = eln$scsi unmap message buffer(&rd msg obj); status = eln$scsi:unmap:message:buffer(&wrt_msg_obj); /* * * Disconnect the circuit to the generic class driver and return the associated devices to the available list. */ status eln$scsi_disconnect_device(&circuit-port); /* End of if (test_device != SCSI$K_MAX_UNITS) */ /* * * Return memory resources and the MESSAGE object back to the pool associated with the configuration data. */ status - eln$scsi_free_config_data(&config_msg-ptr); /* * * */ Delete the PORT assigned to this job by the call to eln$scsi_get_control-ports . Example 14-9 Cont'd on next page 14-100 VAXELN Device Drivers Example 14-9 (Cont.): Programming a SCSI Generic Class .Drlver Message Interface Application int char char MESSAGE char int int int int int int int int int *circuityort, scsi id, **cmd, **buffer, *msg obj, * cmdytr, cmd_size, block count, starting block, direction) scsiyort_status; scsiyort_statusl; status; statusl; i; request_sense_data st~uct ~SSAGE unsigned char unsigned char union Ibn_type *request sense data; request_sense_obj; scsi status byte; scsi-status-bytel; Ibn; - /* * * Copy the READ or WRITE command into the SCSI command message buffer. */ for (i=O; i < cmd size; i++) (*cmd) [i] cmdytr[i]; /* * * Insert the logical block number and the number of blocks to transfer into the command. */ lbn.num starting block; lbn.bits.msb; (*cmd) [1] (*cmd) [2] lbn.bits.mid; (*cmd) [3] lbn.bits.lsb; (*cmd) [4] block_count; do { /* * * Issue the SCSI READ or WRITE command. The host requests the target to return read data or sends write data to the target. */ Example 14-9 Cont'd on next page VAXELN Device Drivers 14-101 Example 14-9 (Cont.): status Programming a SCSI Generic Class Driver Message Interface Application eln$scsi_issue_command( &scsi status byte, &scsi:port_status, circuityort, scsi id, direction, SCSI$K DISCONNECT, SCSI $K-NOSYNC , SCSI $K-RE TRY , 0, 0, msg obj, cmd:buffer) ; if «scsiyort_status (scsi_status_byte /* * * * == /* /* /* /* /* /* /* /* /* /* /* /* /* Receives SCSI bus status */ Receives port function status */ This job's half of circuit port*/ SCSI bus ID of target device */ Direction = read or write */ Allow disconnects */ Synchronous disallowed */ Port retries allowed */ Phase change timeout */ Disconnect timeout */ Get message object */ Get return pointer to command */ Get return pointer to buffer */ ELN$_SUCCESS) && CHECK_CONDITION) ) { On error, issue a SCSI REQUEST SENSE command to the specified device to determine the error condition. Refer to the ANSI SCSI specification for information about this command and its response. */ statusl /* * * * get_request_sense_info(circuityort, scsi id, &scsI status bytel, &scsi:p0rt_statusl, &request sense data, &request=sense=obj ); Return the request sense data to the system. Otherwise, we may use up system resources while waiting for the command to succeed. */ while ( (status != KER$ SUCCESS) I I (scsi status byte) (scsiyort_status != ELN$_SUCCESS); return (status) ; Example 14-9 Cont'd on next page 14-102 VAXELN Device Drivers II Example 14-9 (Cont.): Programming a SCSI Generic Class Driver Message Interface Application int get inquiry info(PORT int unsigned char int char MESSAGE int char *circuityort, scsi id, *status byte, *port status, **inutr , *inCLobj) i, status; * scsi_ cmdytr; /* * * Map buffers for the SCSI INQUIRY command and for storing data. */ status eln$scsi_map_message_buffer(inCLobj, &scsi_cmdytr, sizeof(inquiry_cmd), in tr, *reCLobj) II Example 14-9 (Cont.): Programming a SCSI Generic Class Driver Message Interface Application /* * * Map a buffer for the SCSI REQUEST SENSE command and a buffer for storing the data. */ status eln$scsi_map_message_buffer(re~obj, &scsi_cmdytr, sizeof(request_sense_cmd), re config_tbl[unit] .valid_data == 1) && (marker_array->rnatch[unit] == 1» 14.5.3.2.4 Setting the Current Connection Flag After a class driver checks for devices that it is to service and is ready to service a particular device, the driver should set the current connection flag for that device to 1. When this flag is set to 1, the device cannot be used by another class driver. For example, if unit represents SCSI device 2, the following line of C code sets the current connection flag for SCSI device 2: scsi$config_table-ptr->config_tbl[unit] . current_connection = 1; NOTE The current connection flag is the only data in the configuration table that a class driver should modify. When a class driver no longer needs to service a device, the driver should clear the current connection flag. This allows another class driver to connect to the device. VAXELN Device Drivers 14-121 14.5.3.2.5 Allocating 1/0 Request Packets for Devices A class driver communicates with a SCSI device using one of 16 available VO request packets. The request packet transfers command data to the port driver and returns command status information to the class driver. To allocate a request packet, the driver must call the PORT$ALLOCATE_DEVICE routine. This routine allocates a request packet for the calling driver and returns the packet's ID. When allocating a request packet, a driver must specify the pointer to the port driver's data structures (routine_addresses.ctx_a_context), a SCSI device ID, and a command buffer byte count. The routine call must also specify variables that receive pointers to the packet's SCSI command buffer and SCSI status buffer. The SCSI device ID identifies the device on the SCSI bus that is to handle the 110 request. The command buffer byte count specifies the number of bytes to be allocated for the packet's SCSI command buffer. The command buffer can store up to 256 bytes of command data. PORT$ALLOCATE_ DEVICE returns the address of the command buffer to the specified buffer argument. The driver must use the returned address to place a SCSI command in the request packet. PORT$ALLOCATE_DEVICE returns the address of the packet's SCSI status buffer to the specified status buffer argument. The I-byte status buffer receives a status code from the target device after the class driver issues a SCSI command. Using the returned status buffer address, the class driver can check the status code and respond appropriately. When a class driver no longer needs an 1/0 request packet, the driver should deallocate the packet by calling the PORT$FREE_DEVICE routine. This routine returns a packet to the list of free request packets. If another process is waiting for a request packet, PORT$FREE_DEVICE will signal that process. The call to PORT$FREE_DEVICE must specify the pointer to the port driver's data structure and the request packet ID returned by PORT$ALLOCATE_DEVICE. The following section of C code shows how a class driver might allocate and free an 1/0 request packet: 14-122 VAXELN Device Drivers globalref struct contxt routine_addresses; int unsigned char unsigned char scsi dev, cmd buf length, packet_id, status; *cmd=buf-ptr;*stat_buf-ptr; packet_id = (*routine addresses.ctx a alloc) (routine_addresses.ctx_a_context, scsi dev, cmd bUf length, &cmd_but-ptr, &stat_buf-ptr) ; status = (*routine_addresses.ctx_a_free) (routine addresses.ctx a context, packet_id); -- 14.5.3.2.6 Mapping Data Buffers for 1/0 Requests To issue a SCSI command that reads or writes data, a class driver must map a data buffer for the 1/0 request packet. A driver maps a data buffer by calling the PORT$MAP_BUFFER routine. This routine searches the 12B-Kbyte SCSI DMA RAM bit map for a specified amount of contiguous data bytes, updates the I/O request packet with the appropriate mapping information, and marks the bit map pages as unavailable. A call to PORT$MAP_BUFFER must specify the pointer to the port driver's data structures (routine_addresses.ctx_a_context), a packet request ID, a pointer to the buffer to be mapped, the length of the data buffer, a pad size, and the direction of the transfer. The packet request ID must be a request ID returned by a call to PORT$ALLOCATE_DEVICE. The buffer pointer identifies the address at which the data buffer is to be mapped. The buffer can store up to 65,536 bytes of read or write data. VAXELN Device Drivers 14-123 The pad size argument is for SCSI device commands that require a transfer size that is larger than the size specified by the data buffer size argument. If the amount of data requested in a SCSI command exceeds the space allocated for the data buffer, the pad size accounts for the difference. For example, the SCSI READ command transfers data in logical blocks - 512-byte units. Suppose a driver uses the READ command to read the first two bytes of a disk block. The call to PORT$MAP_BUFFER will specify 2 for the data buffer size to accommodate the two bytes to be read. Since the READ command reads data a block at a time, the call must also specify a pad size of 510 to account for the extra 510 bytes. The direction argument specifies whether the data transfer is a read or write operation. A value of SCSI$K_WRITE indicates a write operation; a value of SCSI$K_READ indicates a read operation~ When a class driver no longer needs an 1/0 request packet data buffer, the driver should unmap the buffer by calling the PORT$UNMAP_ BUFFER routine. This routine returns the memory used for a data buffer back to the 128-Kbyte DMA RAM bit map and marks the returned pages as available. If another process is waiting for DMA RAM memory, PORT$UNMAP_BUFFER signals that process. The call to PORT$UNMAP_BUFFER must specify the pointer to the port driver's data structures, a request packet ID, the address of the data buffer to be unmapped, the size of the buffer being unmapped, and the buffer's pad size. The following section of C code shows how a class driver might map and unmap an 1/0 request packet data buffer: 14-124 VAXELN Device Drivers extern struct contxt routine_addresses; int unsigned char 14.5.3.2.7 packet id, data buf size, data_buf-pad_size; *data_buf-ptr; - status (*routine addresses.ctx a map) (routine addresses.ctx-a context, packet_id, - data_buf-ptr, data buf size, data=buf~ad_size); status (*routine addresses.ctx a unmap) (routine_addresses.ctx_a_context, packet id, data_buf-ptr, data_buf_size, data_buf-pad_size); Issuing SCSI Commands Once a class driver has set up an 1/0 request packet, the driver can use it to issue SCSI commands, such as INQUIRY, READ, and WRITE. To issue a command, the application must use the PORT$ISSUE_ COMMAND routine. This routine arbitrates and selects a device on the SCSI bus, issues the SCSI command that is in the specified request packet, and performs the operations necessary to complete the operation. A call to the PORT$ISSUE_COMMAND routine must supply a pointer to the port driver's data structures, a request packet ID, and values that specify the following: • • • • Whether the target device can disconnect during command execution Whether the port driver should attempt to repeat a command that fails A phase timeout value A disconnect timeout value VAXELN Device Drivers 14-125 You specify constant values for the disconnect and port retry arguments. The value for the disconnect argument can be SCSI$K_ DISCONNECT or SCSI$K_NODISCONNECT. SCSI$K_DISCONNECT indicates that a target device can disconnect; SCSI$K_NODISCONNECT indicates that the target cannot disconnect. Target devices that remain connected to a bus for long periods of time can adversely affect system performance. The value for the port retry argument can be SCSI$K_RETRY or SCSI$K_NORETRY. If the value is SCSI$K_RETRY, the port driver can retry a command that fails due to a timeout, bus parity, or invalid phase transition error up to three times. If the value is SCSI$K_ NORETRY, the port driver cannot retry commands. The phase and disconnect timeout values a driver specifies can range from 0 to 420 seconds. The phase timeout value specifies the amount of time a target device has to change to another SCSI bus phase or to complete a data transfer. The disconnect timeout value specifies the amount of time a target device has to reselect an initiator to proceed with a disconnected data transfer. If you specify 0 or an invalid value, the driver uses a timeout value of 20 seconds. A driver can use PORT$ISSUE_COMMAND to issue commands that are in the Common Command Set (CCS). For information about these commands, see the American National Standard for Information Systems-Small Computer System Interface-2 (SCSI-2) specification. The following section of C code shows how a class driver might issue a SCSI command: 14-126 VAXELN Device Drivers extern struct contxt routine_addresses; int packet id, disconnect, disable_retry, phase_timeout disconnect_timeout; status 14.5.3.2.8 = (*routine addresses.ctx a issue) (routine addresses.ctx-a context, disconnect, - disable retry, phase timeout, disconnect_timeout); Initializing a SCSI Device Controller A class driver might want to initialize a SCSI bus controller when a SCSI bus is hung. To initialize a controller, a driver must call the PORT$INITIALIZE_CONTROLLER routine. This routine asserts the SCSI RST signal on the SCSI bus. This signal causes all devices on the SCSI bus to release all asserted signals and places the bus in a BUS FREE state. A call toPORT$INITIALIZE_CONTROLLER must specify the pointer to the port driver's data structures and the SCSI device ID for a working SCSI target device. For example: status = (*routine addresses.ctx a init) (routine addresses.ctx context, scsi_de~) ; - - a NOTE The sniffer module calls PORT$INITIALIZE_CONTROLLER once after starting the port driver. A class driver should not call this routine unless the bus is hung. VAXELN Device Drivers 14-127 14.5.3.3 Compiling and Linking the SCSI Driver Modules After you modify the SCSI driver start-up module and program your class driver, you must compile the modules and then link them into a new VAXELN SCSI driver image. Compile the start-up module (SCDRIVER.C) and a user-written C class driver as follows: $ $ CC SCDRIVER + ELN$:VAXELNC/LIBRARY cc SCSIUSER + ~LN$:VAXELNC/LIBRARY After compiling the modules, you must link them with the VAXELN SCSI driver components to produce a· new VAXELN SCSI driver image. For example: $ $ =$ LINK SCDRIVER + SCSISNIF + SCSIDISK + SCSIGNRC + + SCSIUSER + SCSI5380 + ELN$:CRTLSHARE/LIB + RTLSHARE/LIB + RTL/LIB . This LINK command links a user class driver with the start-up module, the sniffer module, the supplied disk and generic class drivers, and the port driver. If you modified the start-up module such that it does not include the supplied class drivers, omit those driver modules when linking the driver image as follows: $ LINK SCDRIVER + SCSISNIF + SCSIUSER + SCSI5380 _$ ELN$:CRTLSHARE/LIB + RTLSHARE/LIB + RTL/LIB + - After you compile and link the driver module, you can build the image into your VAXELN system. For information about building the SCSI driver into VAXELN systems, see the VAXELN Development Utilities Guide. 14.6 Realtime Device Drivers The VAXELN Toolkit includes device drivers for the realtime devices listed in Table 14-14. 14-128 Table 14-14: Realtime Devices Devices Description ADQ32 Analog-to-digital converter. The ADQ32 transfers data in DMA. mode. VAXELN Device Drivers Table 14-14 (Cont.): Realtime Devices Devices Description ADVll-C AXVII-C Analog-to-digital converter. The AXVll-C is an ADVII-C with two additional digital-to-analog output channels. ADVll-D Analog-to-digital converter. The ADV1I-D transfers data in programmed and DMA modes. DLVJI Asynchronous serial-line controller. The DLVJI (formerly DLVII-J) is a Q-bus interface that contains four asynchronous serial-line channels. It is intended for realtime applications that collect data and control realtime devices by using asynchronous serial lines. DRB32-E DRB32-M DRB32-W Parallel-line interface devices. The DRB32 is a 32-bit, halfduplex DMA parallel port for the VAXBI bus. The DRB32-W option is for users who have equipment currently designed to interface with DRII-W devices. DRQ3B Parallel-line interface device. The DRQ3B is a I6-bit parallel port for the Q-bus that can run in full-duplex or half-duplex mode. DRVI1-J Parallel-line interface device. The DRVll-J is a Q-bus interface that provides communication, in I6-bit word lengths, between a MicroVAX system and up to four user devices by using four I/O ports. DRVII-W Parallel-line interface device. The DRVll-W is a I6-bit halfduplex DMA parallel port for the Q-bus that supports 18- and 22-bit addressing. IEQII-A lEU II-A IECIIEEE-488 instrument bus interfaces. The IEQ II-A and IEUII-A interface a Q-bus system to two independent IECIIEEE instrument buses. KWVII-C Programmable, realtime clock. You can use the KWVI1-C to initiate action after a specified time interval (by using an interrupt or an external signal) or to time an event. The design of these drivers prohibits access to a given device from more than one job. However, you can gain access from different processes within the same job, provided the caller ensures that processes do not access the same device simultaneously. VAXELN Device Drivers 14-129 14.6.1 ADQ32 DMA Analog-to-Digital Converter The VAXELN Toolkit supplies a programming interface for applications that use ADQ32 modules. The ADQ32 module is a high-speed DMA analog input device for Q-bus systems. Up to 32 single-ended or 16 differential channels of input data are converted to 12-bit digital data. Both single-ended and differential input sampling can be used in a single application. An application can sample multiple channels in any order and can use the programmable gain amplifier at any gain for any sample. The application can sample channel 0 at unity gain and sample channel 1 at a gain of 8. You specify the gain to be used for each sample, independent of each channel. The interface lets the device's DMA mode logic use block mode data transfers. If you prefer, you can use the ADQ32 device in extended block mode, which provides even more use of Q-bus systems. The ADQ32 supports a variety of clock modes. The nature of an application determines the clock mode that you should use. Based on the clock mode used" you can also specify the following: • • • • • • • Base frequency for the sample clock Number of ticks to wait before a sample is taken Base frequency for the sweep clock Number of ticks to wait before a sweep is taken Number of conversions to be performed for each sweep Base frequency for the delay clock Number of ticks to delay before sampling is started You can access an ADQ32 module from only one job, which must be running in kernel mode. This job can be an ADQ32 server if desired, which allows other jobs to communicate with the device. More than one process in the same job can access the device. The ADQ32 interface consists of the following routines: 14-130 VAXELN Device Drivers Routine Description ELN$AD(LINITIALIZE Prepares an ADQ32 device for input and creates the necessary data structures. Places a DMA read request for an ADQ32 on a request queue. ELN$AD(LSTART Tells the ADQ32 to start processing data. ELN$AD(LTRANSFER_DONE Removes an ADQ32 read request from the done queue and returns the status of that request. An application can call the ADQ32 interface routines only from pro- grams running in kernel mode. To use the routines you must include the appropriate modules from the VAXELN runtime libraries. For Pascal programs, you must include the module $ADQ32_UTILITY. If you are programming in C, you must include the modules $vaxelnc and $adq32_utility. For FORTRAN programs, you must include the definition file ELN$FORTRAN_DEFS.FOR. The supplied modules can be linked as delivered with your calling programs to perfonn analog-to-digital conversion. The modules also define constants. and types used by the routines and status codes returned by the routines. The driver source can serve as a model for drivers for other realtime devices. Descriptions of the ADQ32 interface procedures are provided for Pascal, C, and FORTRAN programming in VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual, respectively. For more infonnation about the ADQ32, see the ADQ32 AID Converter Module User~s Guide. 14.6.2 ADV11-CIAXV11-C Analog-to-Dig ital Converter The Pascal module $AXV_UTILITY, supplied with your development system, defines the procedures provided to interface with the ADVll-C analog-to-digital converter and the AXVll-C. The AXVll-C provides all of the functionality of the ADVll-C and two digital-to-analog outputs as well. VAXELN Device Drivers 14-131 By using a hardware jumper, you can configure an ADVll-C device to have 8 or 16 input channels. With 8 channels, analog voltage is measured across 2 input channels; with 16 channels, voltage is measured with respect to ground. The device has a built-in multiplexer, which permits the sampling and conversion of one channel at a time to a 12-bit binary integer. You can also write a value to the device to be used as a gain in the conversion. (The LSl-11 Analog System User's Guide contains more information on the hardware.) An analog-to-digital conversion can be initiated by program control (setting a bit in the controVstatus register) by an external signal, or by overflow from the KWVll-C clock option (see Section 14.6.10). You can access an AXVll-C from only one job, which must be running in kernel mode. This job can be an AX.V11-C server if desired, which allows other jobs to communicate with the device. More than one process in the same job is permitted to access the device; however, the caller must ensure that no simultaneous accesses to the same device occur. The procedures provided in the $AXV_UTILITY module can be linked as delivered with your calling programs to perform analog-to-digi tal conversion. This module also defines status codes returned by the procedures and types needed by the routines. The driver can serve as a model for drivers for other realtime devices. Because the KWVll-C clock can be used in conjunction with an AXVll-C device, some types used in $AXV_UTILITY are defined in the module $KWV_UTILITY. The $AXV_UTILITY module provides the following procedures: Routine Description ELN$AXV_INITIALIZE Causes an ADVII-C or AXVll-C device to be readied for input, output, or both, and causes all needed data structures to be created. This procedure must be called at least once for each device; it may be called more than once for the same device to change the value of a parameter - for example, to enable the device to gather a larger number of values. 14-132 VAXELN Device Drivers Routine Description Causes analog data to be sampled from the specified channels, converted to binary form by the device, and stored in a data array. One read is performed for each specified channel. The process is repeated until all data has been collected. This procedure may be called for either an ADVll-C or AXVII-C device. Causes a binary number to be converted to an analog voltage on one of the digital-to-analog output channels. This procedure may be called only for an AXVII-C device. The procedures just described return optional status values. To ensure good realtime response, the procedures provide limited error checking; they report only errors detected by the device. No input parameters are verified, and kernel service calls made in the course of execution raise exceptions upon failure. Call formats and detailed argument descriptions for the AXV11-C support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.3 ADV11-D DMA Analog-to-Digital Converter The Pascal module $ADV_DMA_UTILITY, supplied with your development system, defines the procedures provided to interface with the ADV11-D DMA analog-to-digital converter. The ADV11-D is an analog-to-digital converter that can transfer data in programmed mode or DMA mode. Up to 16 channels of input data are converted to 12-bit digital data. In DMA mode, one command can transfer up to 32,768 words. (For more information about the ADV11-D device, see the Q-bus DMA Analog System User's Guide.) An analog-to-digital conversion can be initiated by program control, by an external signal, or by overflow from the KWV11-C clock option (see Section 14.6.10). To use the clock to trigger input, you should jump the clock-overflow tab to either pin 1 or pin 3 of the J2 connector on the ADV11-D device. VAXELN Device Drivers 14-133 You can access an ADVI1-D from only one job, which must be running in kernel mode. This job can be an ADVll-D server if desired, which allows other jobs to communicate with the device. More than one process in the same job is permitted to access the device; however, the caller must ensure that no simultaneous accesses to the same device occur. The procedures provided in the $ADV_DMA_UTILITY module can be linked as delivered with your calling programs to perform analog-todigital conversion. This module also defines status codes returned by the procedures and types needed by the routines. The driver source can serve as a model for drivers for other realtime devices. The $ADV_DMA_UTILITY module provides the following procedures: Routine Description ELN$ADV_INITIALIZE Prepares an ADVII-D device for input and creates the necessary data structures. Places a programmed or DMA read request on an ADVII-D request queue. Removes the entry of a completed request from the ADVII-D done queue and returns the status of that request. Call formats and detailed argument descriptions for the ADVII-D support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.4 DLVJ1 Asynchronous Serial-line Controller The Pascal module $DLV_VTILITY, supplied with your development system, defines the procedures provided to interface with the DLVJl (formerly DLVII-J) asynchronous serial-line controller. The DLVJl is a Q-bus interface that contains four asynchronous serial-line channels. The channels can be configured independently for EIA RS-422, RS-423 , or RS-232C signal compatibility. Provisions are also made for configuring the channels for 20 milliampere (rnA) current loop operation. 14-134 VAXELN Device Drivers Four independent serial-line interfaces exist with consecutive bus device address and vector assignments that can be user-configured by using wire-wrap jumpers on the module. Each serial line can also be configured independently for the following: • • • • Baud rates 150, 300, 600, 1200, 2400, 4800, 9600, 19200, or 38400 bi ts per second Number of data bits (7 or 8) Number of stop bits (lor 2) Parity (none, even, or odd) All of these configuration parameters are also set by using wire-wrap jumpers on the controller module. (The DLVll-J User's Guide contains more information on the hardware.) The $DLV_UTILITY procedures are intended to provide the most efficient method of controlling the DLVJ1. The procedures are intended for realtime applications that collect data and control realtime devices using asynchronous serial lines. This is in contrast to the support provided for CXY08, CXA16/CXB16, DHQ11, DHT32, DHV11, DMB32, DZV11, DZQ11, which is intended to provide a more functional interface for reading and writing using standard Pascal, C, and FORTRAN 1/0 routines to terminals connected over the serial lines. The procedures provided in the $DLV_UTILITY module can be linked with your calling program, which must be running in kernel mode. This module also defines status codes returned by the procedures and types needed by the routines. The driver source, contained DLVUTIL.PAS and DLVBODY.PAS, can also serve as a model for other drivers for realtime devices. The $DLV_UTILITY module also exports definitions of the DLVJl's device registers if it is desirable to directly read and write the registers. (See DLVUTIL.PAS for the Pascal definitions or extract the $DLV_UTILITY module from the VAXELNC.TLB library for the C definitions.) in The $DLV_UTILITY module provides the following procedures: VAXELN Device Drivers 14-135 Routine Description ELN$DLV_INITIALIZE Prepares a DLV device line for input and output and creates all needed data structures. This procedure must be called once for each DLV serial line used. Since each line is initialized and handled separately from other lines, each line should have its own device description specified in the target system's System Builder menus. Causes characters to be read from the serial line until the specified number of characters is read. This procedure should be called to read from the serial line if the string_mode argument was FALSE in the call to ELN$DLV_INITIALIZE. Causes characters to be read from the serial line until a carriage return character is encountered. This procedure should be called to read from the serial line if the string_mode argument was TRUE in the call to ELN$DLV_INITIALIZE. Causes the specified character string to be written to the serial line. The characters are not interpreted by this procedure; therefore, any variable-length string can be written. Call formats and detailed argument descriptions for the DLVJ1 support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.5 DRB32 DMA Parallel-Line Interface The Pascal module $DRB_UTILITY, supplied with your development system, defines the procedures provided to interface with the DRB32-E, DRB32-M, and DRB32-W DMA parallel-line controllers. The DRB32 is a VAXBI bus interface that provides communication through a half-duplex DMA parallel port at data widths of 8, 16, or 32 bits. In addition, the DRB32: • Uses page tables so that buffers do not need to be physically contiguous. 14-136 VAXELN Device Drivers • • • Uses two sets of control registers for hardware-supported double buffering. When the device finishes a transfer by using one set of registers and page tables, the device automatically starts a transfer from the second set of registers. Has 8-bit input and output control/status registers that correspond to control lines on the port and have a fixed meaning. You can set the DRB32 to interrupt when an input control line changes. Can check the parity on its data lines. The DRB32-W option is for users of equipment currently designed to interface with the DRII-W device. In closely coupled symmetric multiprocessing configurations, KA800 processors can use DRB32 devices to communicate with user devices. KA800 processors can directly control the DRB32 parallel port for high interrupt response time. The $DRB_UTILITY procedures are intended to provide the most efficient method of controlling the DRB32. The procedures are intended for realtime applications that collect data and control realtime devices using parallel lines. This is in contrast to the support provided for devices that are not used in a realtime environment and are intended to provide a more functional interface for reading and writing using standard Pascal and C I/O routines. The procedures provided in the $DRB_UTILITY module can be linked with your calling program, which must be running in kernel mode. This module also defines status codes returned by the procedures and types needed by the routines. The driver source, contained in DRB32UTIL.PAS and DRB32BODY.PAS, can also serve as a model for other drivers for realtime devices. The $DRB_UTILITY module also exports definitions of the DRB32's device registers if it is desirable to directly read and write the registers. (See DRB32UTIL.PAS for the Pascal definitions or extract the $DRB_UTILITY module from the VAXELNC.TLB library for the C definitions.) These procedures assume that the user device connected to the DRB32 asserts the SYNCH OUT, SYNCH IN, CONTROL SYNCH OUT, and CONTROL SYNCH IN lines when the device is to inform the DRB32 that data is available for the application program to read or that the application program wrote data to the device. See the DRB32 Hardware Manual for more information. VAXELN Device Drivers 14-137 The $DRB_UTILITY module provides the following procedures: Routine Description ELN$DRB_FINISHED_TRANSFER Dequeues a completed request from the device driver and returns its status and a pointer to its data buffer. If no completed request is available, the procedure can wait or return, at your option. ELN$DRB_INITIALIZE Initializes a DRB32 device for input and output, creates all needed data structures, starts the queues that handle requests, and aborts current or queued commands. This procedure must be called once for each DRB32 controller used. The procedure call specifies the data width. Two arguments are provided for use with a DRB32-W device. One argument identifies whether the device being initialized is a DRB32-W device. The other argument specifies whether a DRB32-W device is to operate in link mode, which typically means two DRB32-W devices are connected for data transfer. The default mode specifies that the DRB32-W is connected to a DRI1-W device. Queues a read request to the driver, starts the request if the queue is empty, and returns. The request causes data to be read into a buffer you specify. If you are using a DRB32-W device, you may have to use the ELN$DRB_ WRITE_CTRL procedure to set or clear appropriate function bits in the IOCTL register (FUNCT1, FUNCT2, FUNCT3) before calling ELN$DRB_QUEUE_ READ, or· to properly establish the direction of transfer. 14-138 VAXELN Device Drivers Routine Description Queues a write request to the driver, starts the request if the queue is empty, and returns. The request causes data to be written from a buffer you specify. If you are using a DRB32-W device, you may have to use the ELN$DRB_ WRITE_CTRL procedure to set or clear appropriate function bits in the IOCTL register (FUNCT1, FUNCT2, FUNCT3) before calling ELN$DRB_ QUEUE_WRITE to properly establish the direction of transfer. Writes an 8-bit pattern to a DRB32's 8-bit control register. An argument is provided for use with DRB32-W devices. This argument specifies which bits of the IOCTL register are to be returned: the upper bits 8 to 15 (output) or the lower bits 0 to 7 (input). Returns an 8-bit pattern from a DRB32's 8-bit control register. NOTE These routines assume that the user device is connected to the DRB32 device and asserts the SYNCH OUT, SYNCH IN, CONTROL SYNCH OUT, and CONTROL SYNCH IN lines to inform the device that data is available for the application program to read or that the application program wrote data to the device. See the DRB32 Hardware Manual for more information. To link two DRB32-W devices, the receiving end must post a read request (ELN$DRB_QUEUE_READ) before the sending end posts a write request (ELN$DRB_QUEUE_WRITE). Also, the receiving end must not post a subsequent read until the sending end has completed sending its data. For more information on links, refer to the DRll-W Direct Memory Access Interface User's Guide. VAXELN Device Drivers 14-139 Call formats and detailed argument descriptions for the DRB32 support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.6 DRQ38 DMA Parallel-Line Interface The Pascal module $DRQ3B_UTILITY, supplied with your development system, defines the procedures provided to interface with the DRQ3B DMA parallel-line controller. The DRQ3B module performs DMA data transfers to or from system memory through I6-bit parallel data ports. The module provides two distinct ports for connection to external devices: an input port that supports device-to-memory or memory-tomemory transfers and an output port that supports memory-to-device or memory-to-memory transfers. Each channel is unique, allowing a full-duplex mode. The DRQ3B device performs DMA operations in nonblock mode (singlecycle or burst-mode) or block mode. In nonblock mode, each data word to be transferred is accompanied by an address location when placed on the Q-bus. In block mode, only the first address asserted in each block (up to 16 words) of data is asserted on the bus to indicate the starting address. For nonblock mode, you can specify two types of DMA operations: single-cycle and burst-mode transfers. Single-cycle operations transfer one address and one data word per bus cycle, then release the bus. Burst-mode operations transfer one address word for each data word. However, up to four address/data word combinations are transferred before the bus is released. For block mode transfers, the address location of the first data word is placed on the bus, followed by up to 16 data words, before the DRQ3B device gives up the bus. For more information about the DRQ3B device, see the DRQ3B Parallel DMA I/O Module User's Guide. The $DRQ3B_UTILITY procedures are intended to provide the most efficient method of controlling the DRQ3B. The procedures are intended for realtime applications that collect data and control realtime devices using parallel lines. This is in contrast to the support provided for devices that are not used in a realtime environment and are intended to provide a more functional interface for reading and writing using standard Pascal and C I/O routines. 14-140 VAXELN Device Drivers You can access a DRQ3B from only one job, which must be running in kernel mode. More than one process in the same job is permitted to access the device; however, the caller must ensure that no simultaneous accesses to the same device occur. The procedures provided in the $DRQ3B_UTILITY module can be linked as delivered with your calling programs to perform DRQ3B 1/0. This module also defines status codes returned by the procedures and types needed by the routines. The driver source can serve as a model for drivers for other realtime devices. The $DRQ3B_UTILITY module provides the following procedures: Routine Description ELN$DRQ3B_INITIALIZE Initializes a DRQ3B device, creates necessary data structures, starts the internal request queues, and aborts current or queued commands. Queues a read request to the DRQ3B driver and returns. ELN$DRQ3B_QUEUE_WRITE Queues a write request to the DRQ3B driver and returns. ELN$DRQ3B_READ_FUNCTION Returns the DRQ3B general-purpose function bits. ELN$DRQ3B_TRANSFER_DONE_ READ Dequeues a completed DRQ3B read request and returns its status. ELN$DRQ3B_TRANSFER_DONE_ WRITE Dequeues a completed DRQ3B write request and returns its status. ELN$DRQ3B_WRITE_FUNCTION Writes to the DRQ3B general-purpose latched function bits. Call formats and detailed argument descriptions for the DRQ3B support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. VAXELN Device Drivers 14-141 14.6.7 DRV11-J Parallel-Line Interface The Pascal module $DRV_UTILITY, supplied with your development system, defines the procedures provided to interface with the DRVII-J parallel-line interface device. The DRVI1-J is a Q-bus interface that provides communication between a MicroVAX system and up to -four user devices in I6-bit word lengths through four 1/0 ports. Four control lines are associated with each of the four ports to ensure orderly information transfers. Word transfers are executed by programmed 1/0 bus operations using either polling or interrupt-driven routines. Write data is output by the DRVII-J to the 1/0 bus through three-state data latches, and read data is input through unlatched bus drivers. The $DRV_UTILITY procedures are intended to provide the most efficient method of controlling the DRVII-J. The procedures are intended for realtime applications that collect data and control realtime devices using parallel lines. This is in contrast to the support provided for devices that are not used in a realtime environment and are intended to provide a more functional interface for reading and writing using standard Pascal and CliO routines. The procedures provided in the $DRV_UTILITY module can be linked with your calling program, which must be running in kernel mode. This module also defines status codes returned by the procedures and types needed by the routines. The driver source, contained in the DRVUTIL.PAS and DRVBODY.PAS modules can also serve as a model for other drivers for realtime devices. The $DRV_UTILITY module also exports definitions of the DRVI1-J's device registers if it is desirable to directly read and write the registers. (See the DRVUTIL.PAS module for the Pascal definitions or extract the $DRV_UTILITY module from the VAXELNC.TLB library for the C definitions.) The procedures perform all 1/0 operations, using a dynamically allocated, 2-dimensional buffer array. The first array index specifies the parallel port number (0 to 3), and the second array index specifies a data word. The procedures internally utilize a separate DEVICE object for each parallel port. Therefore, a user program can have interruptdriven 1/0 in progress on each port simultaneously. For example, an application program can have a process writing data to ports 0 and 1 and another process reading data from ports 2 and 3. Due to the way the DRVII-J functions, though, only one port can have concurrent 1/0 if polling is used instead of interrupts. 14-142 VAXELN Device Drivers The procedures assume that the user device connected to the DRVII--J asserts the USER REPLY lines when the user device is to inform the DRVII-J either that data is available for reading by the application program or that data has been accepted (written by the application program). The $DRV_UTILITY module provides the following procedures: Routine Description ELN$DRV_INITIALIZE Prepares a DRV device controller for input and output and creates all needed data structures. This procedure must be called once for each DRV controller used. Causes data words to be read from the specified parallel port. The resulting data is stored in the buffer pointed to by the buffer parameter returned by ELN$DRV_INITIALIZE. Causes data words to be written to the specified parallel port. Before you call this procedure, the data words should be stored in the buffer pointed to by the buffer parameter returned by ELN$DRV_INITIALIZE. NOTE These procedures assume that the user device connected to the DRVII--J asserts the USER REPLY lines to inform the DRVII--J device either that data is available for reading by the application program or that data has been accepted (written by the application program). Call formats and detailed argument descriptions for the DRVII--J support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, VAXELN FORTRAN Runtime Library Reference Manual. VAXELN Device Drivers 14-143 14.6.8 DRV11-W DMA Parallel-Line Interface The Pascal module $DRV_DMA_UTILITY, supplied with your development system, defines the procedures provided to interface with the DRV11-W DMA parallel-line controller. The DRV11-W is a Q-bus interface that provides communication through a 16-bit, half-duplex DMA parallel port. The device supports 18- and 22-bit addressing but does not support page tables (data must be contiguous) or double buffering. The $DRV_DMA_UTILITY procedures are intended to provide the most efficient method of controlling the DRV11-W. The procedures are intended for realtime applications that collect data and control realtime devices using parallel lines. This type of support is in contrast to the support provided for devices that are not used in a realtime environment and are intended to provide a more functional interface for reading and writing using standard Pascal and C I/O routines. The procedures provided in the $DRV_DMA_UTILITY module can be linked with your calling program, which must be running in kernel mode. This module also defines status codes returned by the procedures and types needed by the routines. The driver source, contained in the DRV11 WAUTIL.PAS and DRV11 WABODY.PAS modules, can also serve as a model for other drivers for realtime devices. The $DRV_DMA_ UTILITY module also exports definitions of the DRV11-W's device registers if it is desirable to directly read and write the registers. (See the DRV11 WAUTIL.PAS module for the Pascal definitions or extract the $DRV11W_UTILITY module from the VAXELNC.TLB library for the C definitions.) These procedures assume that the user device connected to the DRV11W asserts the USER REPLY lines when the user device is to inform the DRVII-W that data is available for the program to read or that data written by the program was accepted. The $DRV_DMA_UTILITY module provides the following procedures: 14-144 VAXELN Device Drivers Routine Description Initializes a DRVll-W device controller for input and output, creates all needed data structures, and starts the queues that handle requests. This procedure must be called once for each DRVll-W controller used. Queues a read request to the driver, starts the request if the queue is empty, and returns. The request causes data to be read into the buffer you specify; you are responsible for creating your data area using messages to ensure physically contiguous data. Queues a write request to the driver, starts the request if the queue is empty, and returns. The request causes data to be written from the buffer you specify; again, you must create your data area using messages to ensure physically contiguous data. ELN$DRV_DMA_TRANSFER_ DONE Dequeues a completed request from the device driver and returns its status and a pointer to its data buffer. If no completed request is available, the procedure can wait or return, at your option. ELN$DRV_DMA_WRITE_ FUNCTION Modifies the function bits of the DRVII-W control status register (CSR). This procedure writes a 3-bit pattern to the 3-bit CSR function field. Returns the status bits (3-bit field) from the DRVII-W CSR. NOTE These procedures assume that the user device connected to the DRVII-W asserts the USER REPLY lines to inform the DRVII-W device either that data is available for reading by the application program or that data has been accepted (written by the application program), VAXELN Device Drivers 14-145 Call formats and detailed argument descriptions for the DRV11-W support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.9 IEQ11-A and IEU11-A DuallECIIEEE Instrument Bus Interfaces The Pascal module $GPIB_SUB supplied with your development system defines the procedures provided to interface with the IEQ11-A and IEUII-A devices. The IEQI1-A is a DMA controller that interfaces a Q-bus system to two independent IECIIEEE instrument buses. Similarly, the IEUII-A is a DMA controller that interfaces a UNIBUS system (not a VAXBI system with the DWBUA BI-to-UNIBUS adapter) to two independent IECIIEEE instrument buses. (Alternatively, the IEQII-A and IEQ11U-A devices can provide two ports to the same instrument bus.) Each instrument bus can have up to 15 devices, including the IEQ11-A or IEU11-A, in a sequential configuration. Each bus allows instruments on the same bus to communicate with each other. Each device on the bus has a unique address to which it responds. Information is transmitted in byte, serial-bit, or parallel format and may consist of either commands or data. The IECIIEEE instrument bus is a General Purpose Interface Bus (GPIB). ANSIIIEEE 488-1978, IEEE Standard Digital Interface for Programmable Instrumentation, specifies the characteristics of the bus and the functions it performs. The bus consists of 24 lines. Of these, 8 lines are ground wires, and 16 carry information. Of the 16 information lines, 3 are used for handshaking control, and 5 for bus management; 8 carry data between devices on the bus. You will generally not be concerned with the control lines (NRFD, DAV, and NDAC), since the hardware takes care of the handshaking. The five bus management lines are: Line Mnemonic Attention Service request ATN SRQ Interface clear IFC 14-146 VAXELN Device Drivers Line Mnemonic End or identify EOI Remote enable REN The eight data lines are used to transfer a byte of data at a time across the bus. At any time, only one device on the bus acts as bus controller. The bus controller issues the commands needed to perform data transfers. Each device on the bus has the potential to perform the following functions: • • • • • Act as bus controller Act as talker in a bus transfer Act as listener in a bus transfer Issue a service request to the bus controller Respond to polls by the bus controller The IEQII-A and IEUII-A provide two independent ports to the IECIIEEE bus. These ports can interface to two different buses or provide two ports into the same bus. The ports are treated as separate controllers. The functioning of these ports is controlled by eight hardware registers for each port. The registers are: Register Mnemonic Address IEEE Status Read: Address StatuslBus Status Write: Int Mask OlInt Mask 1 ISR 76XXXO IEEE Interrupt Read: Int Status OlInt Status 1 Write: -/Address IIR 76XXX2 IEEE Command Read: Cmd Pass ThrulWrite: Serial Poll/Auxiliary Cmd ICR 76XXX4 IEEE Data Read: -/Data In Write: Parallel PolllData Out IDR 76XXX6 VAXELN Device Drivers 14-147 Register Mnemonic Address Control/Status CSR 76XXIO Bus Address BAR 76XX12 Byte Count BCR 76XX14 Match Character MCR 76XX16 The corresponding registers for the two ports have identical addresses. The setting of a multiplexer bit in the CSR, based on a user-specified controller ID or unit number, determines which port's register is referenced. Aside from register sharing, however, the two instrument bus ports are functionally independent. As indicated by the Read and Write designations in the preceding table, the four IEEE register addresses reference different registers, depending on whether a reference is a read or a write. For more information about the IEQII-A or IEUII-A device, see the IEUII-A/ IEQII-A User's Guide and the IEXI1-A IEC / IEEE Bus Interface. To use the procedures provided in the $GPIB_SUB module, you must link your programs with RTLOBJECT.OLB, or in the case of C programs, with CTRLOBJECT.OLB. In addition to providing the procedures, the $GPIB_SUB module defines status codes returned by the procedures and the data types that the procedures use. The driver source can serve as a model for drivers for other realtime devices. The $GPIB_SUB module provides the following procedures: Routine Description ELN$GP_AUXILIARY_COMMAND Issues a specified auxiliary command to an IEQII-A or lEU ll-A unit's auxiliary command register. ELN$GP_CLEAR_EVENT Clears all events set previously by GP_SET_EVENT for an IEQII-A or IEUII-A unit. ELN$GP_CONFIGURE Configures an IECIIEEE instrument bus. 14-148 VAXELN Device Drivers Routine Description Defines the data paths between devices that can be talkers and listeners on an IECIIEEE instrument bus. Takes control of an IECIIEEE bus if the specified IEQll-A or lEU ll-A unit is the controller-in-charge. Issues the auxiliary command GTS (go to standby mode) to an IEQllA or IEUII-A unit if the unit is the controller-in-charge. ELN$GP_INITIALIZE Establishes communication with the IEQII-A or IEUII-A instrument-bus interface device. Loads an IEQII-A unit's parallel-poll hardware register with a specified value. Requests a parallel poll of devices on an IECIIEEE bus and returns a parallel-poll value. ELN$GP_PARALLEL_POLL_ CONFIG Configures a parallel poll for the specified devices on an IECIIEEE bus. ELN$GP_PASS_CONTROL Passes control from an IEQII-A or IEUII-A unit to another device on the IECIIEEE bus. Lets an IEQII-A or IEUII-A unit receive control from another device on the IECIIEEE bus. Issues a service request (SRQ) on behalf of a specified IEQII-A or IEUII-A unit. Sends the specified number of interface commands or data bytes to the IEQII-A or IEUII-A data output register. Returns the IECIIEEE bus status and the specified IEQII-A or IEUII-A unit's controller status. VAXELN Device Drivers 14-149 Routine Description Performs a serial poll of the specified devices on an IECIIEEE instrument bus while the service request (SRQ) bit is asserted, to determine which devices requested service. Specifies events to watch for on an IECIIEEE bus. ELN$GP_TRANSFER Transfers data between devices on an IECIIEEE instrument bus according to the data paths specified in a call to GP_DEFINE_PATH. Initializes a specified IEQII-A or IEUII-A port (unit). Call formats and detailed argument descriptions for the IEQII-A and IEUII-A support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14.6.10 KWV11-C Realtime Clock The Pascal module $KWV_UTILITY, supplied with your development system, defines the procedures provided to interface with the KWVI1-C realtime clock. The KWVl1_C is a programmable, realtime clock that can be used to initiate action after a specified time interval (through an interrupt or an external signal) or to time an event. In the first mode, it can be used with an ADVI1-C, AXV11-C, or ADV11-D device to initiate the collection of data. The device's clock counter has a resolution of 16 bits. The clock counter can be driven from any of five internal crystal-controlled frequencies, from a line frequency input, or from Schmitt Trigger #1, which is fired by an external input. Another Schmitt Trigger, #2, can be used to start the counter. (A Schmitt Trigger is a logic device that responds to voltage levels rather than to voltage transitions. The LSl-11 Analog System User's Guide contains more information on the hardware.) 14-150 VAXELN Device Drivers The driver interface provided for the KWVII-C is of the same style as that provided for the ADVII-C and ADVII-D, described previously. The VAXELN Toolkit supplies the KWVII-C driver to allow you to use all of the functionality of the ADVII-C and ADVII-D. The design of this driver precludes accessing a given KWVII-C device from more than one job, and that job must be running in kernel mode. More than one process in the same job is permitted to access the device; however, the caller must ensure that no simultaneous accesses to the same device occur. The procedures provided in the $KWV_UTILITY module can be linked as delivered with your calling programs to interface with the KWVII-C clock. This module also defines status codes returned by the procedures and types needed by the routines. The$KWV_UTILITY module provides the following procedures: Routine Description Causes a KWVII-C device to be readied for input and causes all needed data structures to be created. This procedure must be called at least once for each KWVII-C; it may be called more than once for the same device to change the value of a parameter - for example, to enable the device to gather a larger number of values. Causes time values to be read from the device and stored in a data array; these values· represent timings of external events. This procedure may also be used to gather the elapsed time that began with a call to ELN$KWV_ WRITE. Causes the device to be set up such that, when the given number of ticks has occurred, the clock overflow signal is generated. Overflow signals may be repeatedly generated, depending on how the device was initialized. This procedure can also be used to start the clock if the intent is to later stop and read it with ELN$KWV_READ. The procedures just described return optional status values. To ensure good realtime response, the procedures provide limited error checking; they report only errors detected by the device. No input parameters are VAXELN Device Drivers 14-151 verified, and kernel service calls made in the course of execution raise exceptions upon failure. Call fonnats and detailed argument descriptions for the KWVII-C support routines are provided in the VAXELN Pascal Runtime Library Reference Manual, VAXELN C Runtime Library Reference Manual, and VAXELN FORTRAN Runtime Library Reference Manual. 14-152 VAXELN Device Drivers Appendix A Status Values/Exception Names The VAXELN Kernel procedures and some utility procedures accept an optional status argument that receives the procedure's completion status. If you specify the status argument in a procedure call, you can check the status value after the call to determine whether the operation was successful. If you omit the status argument and a fatal error occurs, an exception condition results. Exceptions have the same names as the corresponding status values. For example, KER$_NO_SUCH_PROGRAM can be either a status value or exception name, depending on whether you specify the status argument. You can use these names in exception handlers. For information about checking status arguments and establishing exception handlers, see Chapter 7. Table A-llists the status values/exception names that VAXELN programs raise. For more details about a particular status value/exception name, see the corresponding message symbol in the VAXELN Messages Manual. Table A-1 : Status Values/Exception Names Name Description C Runtime Library C$_EACCES Permission denied C$_EADDRlNUSE Address already in use C$_EADDRNOTAVAIL Cannot assign requested address C$_EAFNO SUPPORT Address family not supported Status Values/Exception Names A-1 Table A-1 (Cont.): Status Values/exception Names Name Description C Runtime Library C$_EAGAIN No more processes C$_EALREADY Operation already in progress C$_EBADF Bad file number C$_E2BIG Argument list too long C$_EBUSY Mount device busy C$_ECHILD No children C$_ECONNABORTED Software caused connection to abort C$_ECONNREFUSED Connection refused C$_ECONNRESET Connection reset by peer C$_EDESTADDRREQ Destination address required C$_EDOM Math argument error C$_EEXIST File exists C$_EFAULT Bad address C$_EFBIG File too large C$_EHOSTDOWN Host is down C$_EHOSTUNREACH No route to host C$_EINPROGRESS Operation in progress C$_EINTR Interrupted system call C$_EINVAL Invalid argument C$_EIO I/O error C$_EISCONN Socket is already connected C$_EISDIR Is a directory C$_ELOOP Too many levels of symbolic links C$_EMSGSIZE Message too long C$_EMFILE Too many open files C$_EMLINK Too many links C$_ENAMETOOLONG File name too long A-2 Status Values/Exception Names Table A-1 (Cont.): Name Status Values/Exception Names Description C Runtime Library C$_ENETDOWN Network is down C$_ENETRESET Network dropped connection on reset C$_ENETUNREACH Network is unreachable C$_ENFILE File table overflow C$_ENOBUFS No buffer space available C$_ENODEV No such device C$_ENOENT No such file or directory C$_ENOEXEC Exec format error C$_ENOMEM Not enough core C$_ENOPROTOOPT Protocol not available C$_ENOSPC No space left on device C$_ENOTBLK Block device required C$_ENOTCONN Socket is not connected C$_ENOTDIR Not a directory C$_ENOTSOCK Not a socket; socket operation requires a socket C$_ENOTTY Not a typewriter C$_ENXIO No such device or address C$_EOPNOTSUPP Operation not supported on socket C$_EPERM Not owner; need appropriate privileges C$_EPFNOSUPPORT Protocol family not supported C$_EPIPE Broken pipe C$~EPROTONOSUPPORT -Protocol not supported C$_EPROTOTYPE Protocol wrong type for socket C$_ERANGE Result too large Status Values/Exception Names A-3 Table A-1 (Cont.): Name Status Values/Exception Names Description C Runtime Library C$_EROFS Read-only file system C$_ESHUTDOWN Cannot send after socket shutdown C$_ESOCKTNOSUPPORT Socket type not supported C$_ESPIPE Invalid seek C$_ESRCH No such process C$_ETIMEDOUT Connection timed out C$_ETOO~EFS Too many references; cannot splice C$_ETXTBSY Text file busy C$_EVMSERR VMS error code for non-translatable errors C$_EWOULDBLOCK I/O operation would block channel C$_EXDEV Cross-device link DEC windows XVI Toolkit Runtime Library X Toolkit fatal error VAXELN Runtime Library A-4 ELN$_ABORTED Connection attempt failed ELN$_ACC Files-II ACP access failed ELN$_ACS Error in access control string ELN$_ACT File activity precludes operation ELN$_ADAWI First argument in call to ADD_INTERLOCKED is out of range ELN$_ALLRDYRUN Device is already running ELN$_ALQ Invalid allocation quantity ELN$_AMBENUMSTR Ambiguous specification for enumerated type ELN$_ANI Not ANSI "D" format ELN$_ARGUMENT Nonexistent argument in call to ARGUMENT ELN$_ARRAYBOUND Corresponding array bounds are not equal Status Values/Exception Names Table A-1 (Cont.): Name Status Values/Exception Names Description VAXELN Runtime Library ELN$_ASSERT Failed assertion ELN$_AUTH_DUPLICATE_ USER Duplicate user ELN$_AUTH_INVALID_UIC Invalid UIC value ELN$.-AUTH_NO_ AUTHORIZATION No authorization for user ELN$_AUTH_NO_PRIVILEGE No privilege for request ELN$_AUTH_NO_SUCH_ USER No such user ELN$_AUTH_UNKNOWN_ REQUEST Unknown request ELN$_AXV_DEVICE_ERROR Device error; clock too fast for requests ELN$_BADIMGFMT Bad image format ELN$_BADSTATE Bad state exists ELN$_BADVALUE Bad parameter value ELN$_BES Bad escape sequence ELN$_BLKCHK_CRC_ERR Block check or CRC error ELN$_BOF Beginning-of-file detected ELN$_BOOTERROR Insufficient physical memory, insufficient contiguous physical memory, processor identification mismatch, unexpected interrupt or exception, or unexpected machine check ELN$_BUGDAP Internal network error condition detected ELN$_CASELAB No case label exists corresponding to the selector value ELN$_CHARASGN Assignment of a string not of length 1 to a character ELN$_CHR Operand to CHR is out of the range 0 to 255 ELN$_CONFLICTINGVAL Conflicting argument values specified ELN$_CRC Network DAP level CRC check failed Status Values/Exception Names A-5 Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library No current record; operation not preceded by $GET or $FIND A-6 ELN$_DATA_OVERRUN Data overrun ELN$_DEL RFA-accessed record was deleted ELN$_DEV Error in device name or inappropriate device type for operation ELN$_DEVACTIVE Device already active ELN$_DEVNOTREADY Device not ready ELN$_DEVOFFLINE Device is not on line ELN$_DIR Error in directory name ELN$_DIR_FNM Directory listing; error in reading volume-set name, directory name, or file name ELN$_DIR_FUL Directory full ELN$_DISK_ALLOCFAIL ELN$_DISK_BADRANGE Index file allocation failure Bad block address not on volume ELN$_DISK_BLKZERO Block zero is bad; volume not bootable ELN$_DISK_CLUSTER Unsuitable cluster factor ELN$_DISK_DEVMOUNT ELN$_DISK_DIAGPACK Device is already mounted Disk is a diagnostic pack ELN$_DISK_FACTBAD Cannot read factory bad block data ELN$_DISK_INVCHRVOL ELN$_DISK_LARGECNT Invalid character in volume label Disk too large to be supported ELN$_DISK_MAXBAD Bad block table overflow ELN$_DISK_NOBADDATA Bad block data not found on volume ELN$_DISK_NOTFILEDEV Device is not file structured ELN$_DME Dynamic memory exhausted ELN$_DNF Directory not found ELN$_DNR Device not ready or not mounted Status Values/Exception Names Table A-1 (Cont.): Name Status Values/Exception Names Description VAXELN Runtime Library ELN$_DPE Device positioning error ELN$_END_OF_TAPE End-of-tape detected ELN$_END_OF_VOLUME End-of-volume detected ELN$_ENTR~STS Entry already exists ELN$_EOF End-of-file detected ELN$_EOFNOTDEF EOF taken when undefined ELN$_EOLN EOLN taken when file at end-of-file ELN$_ERRDURLOA Error occurred during load operation ELN$_FAC Record operation not permitted by specified file access (FAC) ELN$_FATAL_HWE Fatal hardware error ELN$_FEX File already exists, not superseded ELN$_FILE_ALROPEN File already open ELN$_FILE_ALTHOMBLK Alternate home block used ELN$_FILE_ALTIDXFHD Alternate index file header used ELN$_FILE_BADIDXFHD No valid index file header found ELN$_FILE_BITMAPERR I/O error on storage bitmap; volume locked ELN$_FILE_DEVINUSE Another processor is using device ELN$_FILE_DEVNOTMNT No volume mounted on device ELN$_FILE_FILESTRUCT Unsupported file structure level or ODS feature ELN$_FILE_HDR_CHKSUM File header checksum. failure ELN$_FILE_HDR_FULL File header full ELN$_FILE_IDXMAPERR I/O error on index file bitmap; volume locked ELN$_FILE_INCVOLLABEL Incorrect volume label, volume mounted anyway ELN$_FILE_MAPHDRBAD Storage map header is bad; volume locked ELN$_FILE_MLTVOLABEL A volume with this name has already been mounted Status Values/Exception Names A-7 Table A-1 (Cont.): Name Status Values/Exception Names Description VAXELN Runtime Library ELN$_FILE_NOHOMEBLOCK ELN$_FILE_VOLALRMNT No valid home block found on volume ELN$MOUNT_VOLUME ELN$_FILE_VOLIMPDSM Volume was improperly dismounted; rebuild on VMS system ELN$.;..FINDFIRST ELN$_FLK Start index out-of-range in call to FIND_ FIRST_BIT_CLEAR or FIND_FIRST_BIT_ SET File currently locked by another user ELN$_FND Files-11 ACP file or directory lookup failed ELN$_FNF File not found ELN$_FNM Error in file name ELN$_FOP Invalid file options ELN$_FSZ Invalid fixed control header size ELN$_FTM Network file transfer mode precludes operation (SQO) set ELN$_FUL Device full; insufficient space for allocation ELN$_IDR Invalid directory rename operation ELN$_IDXF_FULL Index file full ELN$_IFA Invalid file attributes detected; file header corrupted ELN$_INTCONVERT ELN$_INVALADDR Expression out-of-range for conversion to type BOOLEAN or an enumerated type Invalid or missing address value ELN$_INVALBUFSIZ Invalid buffer size ELN$_INVALCHARSIZ Invalid character size ELN$_INVALDSKSIZ Bad parameter input for VM disk size ELN$_INVALFUNC Invalid function ELN$_INVALLINE Invalid line name ELN$_INVALNAM Invalid node, port, or service name A-8 Status Values/Exception Names Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library ELN$_INVALNODE Invalid node name or address ELN$_INVALPARITY Invalid parity type ELN$_INVALREC Invalid record definition ELN$_INVALSPEED Invalid terminal speed ELN$_INVALSUBFUNC Invalid subfunction ELN$_INVALTYP Invalid port type ELN$_INVDBLSTR Invalid specification for a number of type DOUBLE ELN$_INVENUMSTR Invalid enumerated type syntax ELN$_INVENUMVAL Invalid enumerated type value ELN$_INVREALSTR Invalid specification for a number of type REAL ELN$_INVTIMSTR Invalid time specification ELN$_INVTIMVAL Invalid time value ELN$_IOP Invalid operation for file organization or device Invalid record encountered; with sequential files only ELN$_KEY Invalid record number key or key value ELN$_~_DATA_OVERRUN Data overrun; external events occurring too fast ELN$_LATACTIVE LAT protocol already active ELN$_LATNOTACTIVE LAT protocol is not active ELN$_LBL Tape label is not ANSI format ELN$_LNE Logical name translation count exceeded ELN$_LOCKED Entry is locked ELN$_MAXLOADS Maximum number of concurrent loads reached Maximum number of services reached Status Values/Exception Names A-9 Table A-1 (Cont.): Name Status Values/exception Names Description VAXELN Runtime Library ELN$_MISLINNAM Missing line name ELN$_MISLOAFIL Missing load file ELN$_MISNODID Missing node name or address ELN$_MISPHYADR Missing physical address ELN$_MKD Files-II ACP could not mark file for deletion ELN$_MOVVEC Vector moved from shareable image ELN$_MRS Invalid maxim urn. record size ELN$_NEF Not positioned to EOF on $PUT; sequential organization only ELN$_NEGSIZE The size of a dynamic aggregate is negative ELN$_NEGSTRLEN Negative string length specified ELN$_NET Network operation failed at remote node ELN$_NCADDRNOTSET Physical address could not be set ELN$_NCBSHORT Buffer too short ELN$_NI_CARRIERLOSS Carrier loss during transmission ELN$_NI_EXCESSCOLL Excessive collisions; transmission stopped ELN$_NI_ILLEGALCMD Illegal command opcode ELN$_NI_INVALIDBUFF Invalid buffer specified ELN$_NCINVALIDCMD Invalid command parameters ELN$_NCINVALIDPTDB Invalid PTDB ELN$_NCINVALIDSAP Invalid SAP value; even group SAPJ or odd individual SAP ELN$_NCINVLLCCLASS Invalid LLC class specified for this user ELN$_NCLENGTH Invalid length ELN$_NCLONG Frame too long ELN$_NCNOTENABLED User not enabled in a connection request ELN$_NCNOTUNIQUE PTT, SAP, or PROTID not unique ELN$_NI_PROMENABLED Promiscuous mode already enabled A-10 Status Values/Exception Names Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library ELN$_NI_RCVFAIL802TR Receive failed; IEEE 802 packet truncated ELN$_NI_RCVFAILNRSN Receive failed; no reason given ELN$_NI_SHORT Frame too short ELN$_NI_TOOMANYADR Too many addresses defined ELN$_NI_TOOMANYFQ Too many FQs defined ELN$_NCTOOMANYPTDB Too many PTDBs defined ELN$_NI_TRANSFAlLED Transmission failed ELN$_NI_UNKNOWNPrDB Specified PTDB is unknown ELN$_NI_XMTFAILLCOL Transmit failed; late collision ELN$_NI_XMTFAILNRSN Transmit failed; no reason given ELN$_NCXMTFAILTIME Transmit failed; transmit timeout ELN$_NMF No more files found ELN$_NOBLOCKSPEC Device driver indicated zero blocks on device ELN$_NOD Error in node name ELN$_NOHANDLER Exit handler not in system ELN$_NOMODEM No modem support ELN$_NOMOREINFO No information in data base ELN$_NORESOURC No resources available ELN$_NORMAL Operation successful ELN$_NOSERVERS No terminal servers known to service node ELN$_NOSUCHENTRY No matching entry found ELN$_NOSUCHLINK No such link ELN$_NOSUCHOPrION Hardware option not present ELN$_NOSUCHPORT No such port ELN$_NOSUCHSERV No such service ELN$_NOTENUMSTR String is not of the enumerated type ELN$_OBSVEC Obsolete termclass vectored routine Status Values/Exception Names A-11 Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library ELN$_ORG Invalid file organization value ELN$_PAOC A packed array of type CHAR is too large to be used as a string Assignment of string of wrong length to packed array of type CHAR ELN$_PES Partial escape sequence ELN$_PORTEXISTS Port already exists ELN$_PRED Operand to PRED is too small ELN$_PROBESIZE Size of argument to PROBE_READ or PROBE_WRITE is greater than 65535 bytes DAP protocol error detected; message field contains invalid format DAP protocol error detected; message field is invalid Insufficient privilege or file protection violation ELN$_QUO Error in quoted string ELN$_RAC Invalid record access mode ELN$_RAT Invalid record attributes ELN$_RECEIVE Size of message received is different from the size of the associated type of the data pointer ELN$_RENAME_2 Rename; 2 different device names specified ELN$_REQMAX Maximum number of requests already queued ELN$_REQUEST_ OUTSTANDING Modem event signaling request already exists ELN$_RFA Invalid record's file address (RFA) ELN$_RFM Invalid record format ELN$_RLK Target record currently locked by another stream Files-II ACP remove function failed A-12 Status Values/Exception Names Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library ELN$_RNF Record not found ELN$_RNL Record not locked ELN$_ROP Invalid record options ELN$_RSZ Invalid record size ELN$_SEND_RECEIVE Send or receive failure ELN$_SERVEXlSTS Service already exists ELN$_SETASGN Members present in the set source are out of range specified by target ELN$_SETCONSTR An expression in a set constructor is out of range ELN$_SHR Invalid file sharing (SHR) options ELN$_SNE File sharing not enabled ELN$_STRLEN A string length exceeds 32767 ELN$_SUBRASGN The source value is out of the range of the target subrange ELN$_SUBSCR Array index value is out of range ELN$_SUBSTR Operand in a call to SUBSTR is out of range ELN$_SUC Operation successful ELN$_SUCC Operation in call to SUCC is too large ELN$_SUCCESS Operation completed successfully ELN$_SUCCESS_ERROR Error in DAP success message ELN$_SUP Network operation not supported ELN$_SYN File specification syntax error ELN$_TAPE_DEVERROR Device error occurred ELN$_TAPE_DEVINUSE Another process is using the device ELN$_TAPE_DEVMOUNT Device is already mounted ELN$_TAPE_DIFLBLMNT A volume with a different label was mounted ELN$_TAPE_VOLNAMMSK Specified volume's name is masked by another volume Status Values/Exception Names A-13 Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Runtime Library ELN$_TERM_RECV Tenninator received ELN$_TIMEOUT Timeout occurred ELN$_TMO Timeout occurred ELN$_TNS Tenninator not seen ELN$_TRANSLATE No translation exists for a character in the source specified with TRANSLATE ELN$_TUTL_BLKSIZ Invalid block size specified ELN$_TUTL_INVCHRVOL Invalid character in volume label ELN$_TYP Error in file type ELN$_TYPECAST Target type is larger than the variable being cast ELN$_TYPEEXTENT Corresponding type extents are not equal ELN$_UNSUPPORT Network operation not supported ELN$_UNSUPPORTED Driver received unsupported request ELN$_UPI UPI not set when sharing and BIO or BRO set ELN$_VER Error in version number ELN$_VOL No such volume ELN$_WCC Invalid wildcard context (WCC) value. ELN$_WLD Invalid wildcard operation ELN$_ZEROSIZE Size of the target specified with ZERO is greater than 65,535 bytes File Service A-14 FLS$K_ALLFHDNOTMAP Allocated file header not mapped FLS$K_BADBLOCK Bad block encountered; handling not implemented FLS$K_BADFILEID File number out of range for this volume FLS$K_BADFILENAME Bad file name for enter operation Status Val ues/Exception Names Table A-1 (Cont.): Name Status Values/Exception Names Description File Service FLS$K_BADFILEVER Bad version number for enter operation FLS$K_BADPARAM Bad input parameter FLS$K_BADSBMBLK Bad storage bitmap block specified in bitmap search FLS$K_ERRDURDMT Error during dismount; outstanding file open FLS$K_ERREXTIDX Error extending index file FLS$K_ERRRDIDX Error reading index file header FLS$K_ERRWRTIDX Error writing index file header FLS$K_FILBLKNOTMAP Attem pt to read from or write to block not mapped in file FLS$K_FILESTRUCT Unsupported file structure level or unsupported ODS2 feature FLS$K_ILLEGALEXT Illegal extent specified in bitmap deallocation FLS$K_ILLPTRCNT Illegal pointer count specified during retrieval pointer creation FLS$K_MAPCNTZERO Attempt to create map pointer with zero block count FLS$K_MOUNTED Actual volume name is name FORTRAN Runtime Library FOR$_ADJARRDIM Adjustable array dimension error FOR$_ATTACCNON Attempt to access nonexistent record FOR$_BACERR BACKSPACE error FOR$_CLOERR CLOSE error FOR$_DUPFILSPE Duplicate file specifications FOR$_ENDDURREA End-of-file during read FOR$_ENDFILERR ENDFILE error FOR$_ERRDURREA Error during read FOR$_ERRDURWRI Error during write Status Values/Exception Names A-15 Table A-1 (Cont.): Status Values/Exception Names Name Description FORTRAN Runtime Library A-16 FOR$_FILNAMSPE File name specification error FOR$_FILNOTFOU File not found FOR$_FINERR FIND error FOR$_FLOUNDEXC Floating underflow exception FOR$_FORVARMIS Format and variable type mismatch FOR$_INCFILORG Inconsistent file organization FOR$_INCOPECLO Inconsistent OPEN and CLOSE parameters FOR$_INCRECLEN Inconsistent record length FOR$_INCRECTYP FOR$_INFFORLOO Inconsistent record type Infinite format loop FOR$_INPCONERR Input conversion error FOR$_INPRECTOO Input record too long FOR$_INPSTAREQ Input statement requires too much data FOR$_INSVIRMEM Insufficient virtual memory FOR$_INVARGFOR Invalid argument ,FOR$_INVLOGUNI FOR$_INVREFVAR Invalid logical unit number Invalid reference to variable in NAMELIST input FOR$_KEYVALERR Keyword value error in OPEN statement FOR$_LISIO_SYN List-directed 110 syntax error FOR$_NO_CURREC No currrent record FOR$_NO_SUCDEV No such device FOR$_NOTFORSPE Not a FORTRAN-specific error FOR$_OPEFAI FOR$_OUTCONERR Open failure Output conversion error FOR$_OUTSTAOVE Output statement overflows record FOR$_RECIO_OPEN Recursive I/O operation FOR$_RECNUMOUT Record number outside range Status Values/Exception Names Table A-1 (Cont.): Name Status Values/exception Names Description FORTRAN Runtime Library FOR$_REWERR REWIND error FOR$_REWRITERR REWRITE error FOR$_SEGRECFOR Segmented record format error FOR$_SPERECLOC Specified record locked FOR$_SYNERRFOR Syntax error in format FOR$_SYNERRNAM Syntax error in NAMELIST input FOR$_TOOMANREC Too many records in I/O statement FOR$_TOOMANVAL Too many values for NAMELIST variable FOR$_UNIALROPE U nit already open FOR$_UNLERR UNLOCK error FOR$_vFEVALERR Variable format expression value error FOR$_WRIREAFIL Write to READONLY file VAXELN Kernel KER$_AREA_EXISTS Previous job created area KER$_BAD_ACCESS_ CONTROL Remote system rejected user name or password KER$_BAD_COUNT Bad parameter count KER$_BAD_CREATE Bad job or process creation KER$_BAD_IMAGE_FORMAT Unsupported program image format KER$_BAD_LENGTH Bad string parameter length KER$_BAD_MESSAGE_SIZE Bad message size KER$_BAD_MODE Bad access mode KER$_BAD_STACK Bad stack KER$_BAD_STATE Bad object state KER$_BAD_TYPE Bad object type KER$_BAD_VALUE Bad parameter value Status Values/Exception Names A-17 Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Kernel Not enough free memory process's kernel or user stack KER$_CONNECT_PENDING Connect circuit pending KER$_CONNECT_TIMEOUT Connect circuit timeout KER$_COUNT_OVERFLOW Count overflow KER$_COUNT_UNDERFLOW Count underflow KER$_DEVICE_CONNECTED Device already connected KER$_DISCONNECT Circuit disconnected by partner KER$_DUPLICATE Duplicate name KER$.:..EX.PEDITED Expedited message KER$_KERNEL_STACK Kernel stack not valid KER$_MACHINECHK Machine check KER$_NO_ACCESS No access to parameter KER$_NO_DESTINATION No destination port KER$_NO_INITIALIZATION No job initialization specified KER$_NO_MAP_REGISTER No I/O mapping register available KER$_NO_MEMORY No physical memory available KER$_NO_MESSAGE No message available KER$_NO_OBJECT No object table entry available KER$_NO_PAGE_TABLE No process page table available KER$_NO_PATH_REGISTER No data path register available KER$_NO_POOL No pool available KER$_NO_PORT No port available KER$_NO_STATUS No exit status value specified KER$_NO_SUCH_DEVICE No such device KER$_NO_SUCH_IMAGE No such image KER$_NO_SUCH_NAME No such name KER$_NO_SUCH_PORT No such port A-18 Status Values/Exception Names Table A-1 (Cont.): Status Values/Exception Names Name Description VAXELN Kernel KER$_NO_SUCH_PROGRAM No such program KER$_NO_SUCH_SERVICE No such service KER$_NO_SYSTEM_PAGE No system page table entries available KER$_NO_VIRTUAL No virtual address space available KER$_POWER_SIGNAL System power recovery is in progress KER$_PROCESS_ATTENTION Interprocess signal KER$_QUIT_SIGNAL Quit signal KER$_SUCCESS Operation completed successfully KER$_TIME_NOT_SET Time has not been set KER$_UNREACHABLE Remote system currently unreachable General Runtime Library LIB$_AMBKEY Ambiguous keyword LIB$_AMBSYMDEF Ambiguous symbol definition LIB$-ATTCONSTO Attempt to continue from stop LIB$_ATTREQREF LIB$_BADBLOADR Attach request refused LIB$_BADBLOSIZ Bad block size LIB$_BADCCC Invalid compilation code LIB$_BADSTA LIB$_BADTAGVAL Bad stack Bad boundary tag value LIB$_DECOVF Decimal overflow Bad block address LIB$_DESSTROVF Destination string overflow LIB$_EF_ALRFRE Event flag already free LIB$_EF_ALRRES Event flag already reserved LIB$_EF_RESSYS Event flag reserved to system LIB$_EOMERROR Compilation errors in module Status ValueS/Exception Names A-19 Table A-1 (Cont.): Status Values/exception Names Name Description General Runtime Library A-20 LIB$_EOMFATAL Fatal compilation errors in module LIB $_EO MWARN Compilation warnings in module LIB$_ERRROUCAL Error in routine call LIB$_FATERRLIB Fatal error in library LIB$_FLTOVF Floating overfiow LIB$_FLTUND Floating underflow LIB$_GSDTYP Invalid GSD record type in module LIB$_ILLFMLCNT Minimum argument count exceeds maximum for procedure in module LIB$_ILLMODNAM Invalid module name length for module LIB$_ILLPSCLEN Psect has invalid length in module LIB$_ILLRECLEN Invalid record length in module LIB$_ILLRECLN2 Invalid record length LIB$_ILLRECTYP Invalid record type in module LIB$_ILLRECTY2 Invalid record type LIB$_ILLSYMLEN Symbol has invalid length in module LIB$_INPSTRTRU Input string truncated LIB$_INSEF Insufficient event flags LIB$_INSLUN Insufficient logical unit numbers LIB$_INSVIRMEM Insufficient virtual memory LIB$_INTLOGERR Internal logic error LIB$_INTOVF Integer overfiow LIB$_INVARG Invalid arguments LIB$_INVARGORD Invalid argument order LIB$_INVCHA Invalid character LIB$_INVCLADSC Invalid class descriptor LIB$_INVCLADTY Invalid class data type combination in descriptor Status Values/Exception Names Table A-1 (Cont.): Status Values/exception Names Name Description General Runtime Library Invalid conversion LIB$..JNVCVT LIB$_INVDTYDSC Invalid data type in descriptor LIB$_INVFILSPE Invalid file specification LIB $_INVNB DS Invalid numeric byte data string LIB$_INVOPEZON Invalid operation for zone LIB$_INVSCRPOS Invalid screen position LIB$_INVSTRDES Invalid string descriptor LIB$_INVS~NAJd Invalid symbol name LIB$_INVTYPE Invalid LIB$TPARSE state table entry LIB$_IVTIME Invalid time passed in or computed LIB$_KEYALRINS Key already inserted in tree LIB$_KEYNOTFOU Key not found in tree LIB$_LUNALRFRE Logical unit number already free LIB$_LUNRESSYS Logical unit number reserved to system LIB$_NEGTIM Negative time was computed LIB$_NOEOM Module does not contain end-of-module record LIB$_NORMAL Operation completed successfully LIB$_NOSUCHSYM No such symbol LIB$_NOTFOU Not found LIB$_ONEDELTIM At least one delta time is required LIB$_ONEENTQUE One entry in queue LIB$_OUTSTRTRU Output string truncated LIB$_PAGLIMEXC Page limit exceeded for zone LIB$_PUSSTAOVE Pushdown stack overflow LIB$_QUEWASEMP Queue was empty LIB$_RECTOOSML Data overflows object record in module LIB$_ROPRAND Reserved operand Status Values/Exception Names A-21 Table A-1 (Cont.): Name Status Values/Exception Names Description General Runtime Library LIB$_SCRBUFOVF Screen buffer overflow LIB$_SECINTFAI Secondary interlock failure in queue LIB$_SEQUENCE Invalid record sequence in module LIB$_SEQUENCE2 Invalid record sequence LIB$_SIGNO_ARG Signal with no arguments LIB$_STRIS_INT String is interlocked LIB$_STRLVL Invalid object language structure level in module LIB$_STRTRU String truncated LIB$_SYNTAXERR String syntax error detected by LIB$TPARSE LIB$_UNRKEY Unrecognized keyword LIB$_USEFLORES Use of floating reserved operand LIB$_WRONUMARG Wrong number of arguments Math Runtime Library MTH$_FLOOVEMAT Floating-point overflow MTH$_FLOUNDMAT Floating-point underflow MTH$_INVARGMAT Invalid argument MTH$_LOGZERNEG Logarithm of zero or negative value MTH$_SQUROONEG Square root of negative value MTH$_UNDEXP Undefined exponentiation MTH$_WRONUMARG Wrong number of arguments Language Independent Runtime Library OTS$_FATINTERR Fatal internal error OTS$_INPCONERR Input conversion error OTS$_INSVIRMEM Insufficient virtual memory OTS$_INTDATCOR Internal data corrupted A-22 Status Values/Exception Names Table A-1 (Cont.): Name Status Values/Exception Names Description Language Independent Runtime Library OTS$_INVSTRDES Invalid string descriptor OTS$_IO_CONCLO I/O continued to closed file OTS$_OUTCONERR Output conversion error OTS$_STRIS_INT String is interlocked OTS$_USEFLORES Use of floating reserved operand OTS$_WRONUMARG Wrong number of arguments Pascal Runtime Library PAS$-ACCMETINC ACCESS_METHOD specified is incompatible with file PAS$_AMBVALENU Ambiguous value for enumerated type PAS$_BUGCHECK Internal consistency failure PAS$_ERRDURCLO Error during CLOSE PAS$_ERRDURDIS Error during DISPOSE PAS$_ERRDURFIN Error during FIND PAS$_ERRDURGET Error during GET PAS$_ERRDURNEW Error during NEW PAS$_ERRDUROPE Error during OPEN PAS$_ERRDURPRO Error during prompting PAS$_ERRDURPUT Error during PUT PAS$_ERRDURRES Error during RESET PAS$_ERRDURREW Error during REWRITE PAS$_ERRDURWRI Error during WRITELN PAS$_FAIGETLOC Failed to get locked component PAS$_FlLALRACT File already active PAS$_FlLALRCLO File already closed PAS$_FlLALROPE File already open Status Values/Exception Names A-23 Table A-1 (Cont.): Name Status Values/Exception Names Description Pascal Runtime Library File name required for this history or disposition PAS$_FILNOTDIR File not opened for direct access PAS$_FILNOTFOU File not found PAS$_FILNOTGEN File not in generation mode PAS$_FILNOTINS File not in inspection mode PAS$_FILNOTOPE File not open PAS$_FILNOTTEX File not a text file PAS$_GENNOTALL Generation mode not allowed for a READONLY file PAS$_GETAFTEOF GET attempted after end-of-file PAS$_GOTO Non-local GOTO requested PAS$_GOTOFAILED Non-local GOTO failed PAS$_HALT Program execution terminated PAS$_INSVIRMEM Insufficient virtual memory PAS$_INVARGPAS Invalid argument PAS$_INVFILSYN Invalid filename syntax PAS$_INVFIL"AR PAS$_INVRECLEN Invalid file variable PAS$_INVSYNENU Invalid syntax for an enumerated value PAS$_INVSYNINT Invalid syntax for an integer value PAS$_INVSYNREA Invalid syntax for a real value PAS$_INVSYNUNS Invalid syntax for an unsigned value PAS$_LINTOOLON Line too long Invalid record length PAS$_LINVALEXC LINELIMIT value exceeded PAS$_NEGDIGARG Negative digits argument to BIN, HEX, or OCT not allowed PAS$_NEGWIDDIG Negative width or digits specification not allowed A-24 Status Values/Exception Names Table A-1 (Cont.): Status Values/exception Names Name Description Pascal Runtime Library PAS$_NOTVALTYP Item not a value of specified type PAS$_RECLENINC RECORD_LENGTH specified is inconsistent with this file RECORD_TYPE specified is inconsistent with this file RESET not allowed on an unopened internal file PAS$_REWNOTALL REWRITE not allowed for a shared file PAS$_TEXREQSEQ Text files require sequential organization and access WRITE of an invalid enumerated value Runtime System SS$_ACCVIO Access violation SS$_BREAK Breakpoint fault SS$_CMODUSER Change mode to user trap SS$_COMPAT Compatibility mode fault SS$_DECOVF Arithmetic trap, decimal overflow SS$_FLTDIV Arithmetic trap, floating-point/decimal divide by zero SS$_FLTDIV_F Arithmetic trap, floating-point divide by zero SS$_FLTOVF Arithmetic trap, floating-point overflow SS$_FLTOVF_F Arithmetic trap, floating-point overflow SS$_FLTUND Arithmetic trap, floating-point underflow SS$_FLTUND_F Arithmetic trap, floating-point underflow SS$_INSFRAME Insufficient call frames to unwind SS$_INTDIV Arithmetic trap, integer divide by zero SS$_INTOVF Arithmetic trap, integer overflow SS$_IVTIME Invalid time 'Status Values/Exception Names A-25 Table A-1 (Cont.): Status Values/Exception Names Name Description Runtime System SS$_NORMAL Normal successful completion SS$_NOSIGNAL No signal currently active SS$_OPCCUS Opcode reserved to customer fault SS$_OPCDEC Opcode reserved to Digital fault SS$_RADRMOD Reserved addressing fault SS$_ROPRAND Reserved operand fault SS$_SUBRNG Arithmetic trap, subscript out of range SS$_TBIT T-bit pending trap SS$_UNWIND Unwind currently in progress SS$_UNWINDING Unwind already in progress String Runtime Library A-26 STR$_DIVBY_ZER Division by zero STR$_FATINTERR Fatal internal error STR$_ILLSTRCLA Invalid string class STR$_ILLSTRPOS Invalid string position STR$_ILLSTRSPE Invalid string specification STR$_INSVIRMEM Insufficient virtual memory STR$_MATCH Match found against input string STR$_NEGSTRLEN Negative string length STR$_NOMATCH No match found against input string STR$_STRIS_INT String interlocked STR$_STRTOOLON String too long STR$_TRU Truncation STR$_WRONUMARG Wrong number of arguments Status Values/Exception Names Table A-1 (Cont.): Name Status Values/exception Names Description DECwindows Xlib Runtime Library X$_ERROREVENT Error event received from server X$_INSFMEM Insufficient dynamic memory X$_IOERROR Xlib 110 error X$_LIBABORT Xlib fatal error X$_OBSOLETE Obsolete Xlib entry point referenced Status Values/Exception Names A-27 Appendix B Machine-Check Stack Frames The VAXELN software supports optional error logging in a VAXELN target application. If you select error logging at system build time, an error log file is produced that you can analyze by using the VMS Error Log Utility. The reports generated by the VMS utility are primarily intended to assist Digital Customer Services personnel. (See the VAXELN Development Utilities Guide for more information on VAXELN error logging.) Among the errors that can be logged when error logging is built into a VAXELN system are processor machine checks. A machine check is an exception that is reported when the processor or an external adapter detects an error. When a machine-check occurs, the processor pushes a machine-check stack frame onto an interrupt stack that consists of a count longword, an implementation-dependent number of error report longwords, a program counter (PC), and a process status longword (PSL). The count longword reports the number of bytes of error report pushed onto the stack. For example, if four longwords of error report are pushed onto the stack, the countlongword will contain 16. The initial processing of a machine check or interrupt is processorspecific. However, the VAXELN machine-check handler for all processor types determines the seriousness of a machine check, whether the machine check is fatal to a job or to the system, and how to respond based on the following: • • The nature of the machine check The access mode in which the machine check occurred Machine-Check Stack Frames B-1 If the job or system can recover from a machine check, the machinecheck handler places the machine-check stack frame in the error log file. If error logging is not enabled, you can locate and inspect the stack frame manually. When a machine check places a system in a state from which it cannot recover, the machine-check handler checks the access mode in which the machine check occurred. If it occurred in user mode or kernel mode - at interrupt priority level (IPL) 0 - the handler reports a machinecheck exception through the exception dispatching mechanism. (Unless the process has taken special action, process execution terminates.) If the machine check occurred in kernel mode at an elevated IPL, a fatal system bugcheck may occur, causing an orderly shut-down of the system. When machine-check stack frames are not logged, you can look for the stack frame in the interrupt stack. This appendix describes how to locate and interpret machine-check stack frames manually. This material is presented to assist Digital Customer Services personnel. NOTE In order for you to use the procedures described in this appendix, the VAXELN system on which the machine check occurred must have a system console. B.1 Obtaining a Machine-Check Stack Frame When a machine check occurs in kernel mode at an elevated IPL, a VAXELN system attempts to display the entire current stack on the system console terminal (if the system has no console) in a raw format (address and contents only). If the stack is successfully displayed, you can locate the start of the machine-check stack frame, which follows the count longword on the stack. The value of the count longword depends on the target processor type; these values are shown in the uppermost portions of Figures B-1 to B-8. For example, on a VAX111730 processor, the machine-check stack frame follows a length parameter of OOOOOOOC(hex) on the stack. B-2 Machine-Check Stack Frames If the failure is very serious, the attempt to display the current stack might not succeed. In that case, you must use console commands to manually examine the VAX computer's processor status longword (PSL), program counter (PC), stack pointer (SP), and in-memory stack. For example, on a VAX-ll/750 processor, you would use the following commands: »> »> »> »> »> E P E/G F E/G E ElL (SP) ElL Get Get Get Get Get PSL PC SP first (bottom) stack longword next stack longword, then repeat ElL For examine (E) commands subsequent to the last one shown, the address being examined will increment automatically, allowing you to progress toward the top of the stack. The object is to locate the start of the machine-check stack frame, which on a VAX.-111750 processor follows a length parameter of 00000028(hexadecimal) on the stack, ignoring the intervening locations, which contain parameters pushed by VAXELN bugcheck code and exceptions pushed on the stack after the machine check occurred. Once you locate the start of the machine-check stack frame, you examine the stack frame and interpret it according to the frame layout for the particular processor. The remaining sections in this appendix give the machine-check stack frame formats for each supported target VAX. processor. Machine-Check Stack Frames B-3 B.2 Machine-Check Stack Frame for MicroVAX I Processors Figure B-1 shows the information that is left on the stack when a machine check occurs on a MicroVAX I processor. Figure B-1: Machine-Check Stack Frame for MicroVAX I Processors Byte Count (OOOOOOOC hex) :(SP) Machine-Check Type Code First Parameter Second Parameter PC PSL MLO-004295 8-4 Machine-Check Stack Frames Table B-1 lists the possible values for the machine-check type code field. Table B-1: Machine-Check Type Codes for MicroVAX I Processors Code Meaning o Memory-controller bug checkl 1 Unrecoverable memory-read errorl 2 Nonexistent memoryl 3 Illegal I/O-space operation l 4 Unrecoverable PTE-read errorl 5 Unrecoverable PTE-write errorl 6 Control-store parity error 2 7 Micromachine bug check2 8 Q22-bus vector read erro~ 9 Write parameter errors lBits<29,21:0> of the first parameter contain the corresponding bits of the physical address of the last memory reference, and the second parameter contains the address presented to the memory controller. 2Both parameters are O. sThe first parameter contains the virtual address that was being written, and the second parameter is O. Machine-Check Stack Frames 8-5 B.3 Machine-Check Stack Frame for MicroVAX II and 2000, VAXstation II and 2000, and KA800 Processors Figure B-2 shows the information that is left on the stack when a machine check occurs on one of the following processors: • • • • • MicroVAX II VAXstation II MicroVAX 2000 VAXstation 2000 KABOO Figure B-2: Machine-Check Stack Frame for MicroVAX II and 2000, VAXstatlon II and 2000, and KA800 Processors Byte Count (OOOOOOOC hex) :(SP) Machine-Check Type Code Most Recent Virtual Address Internal State Information PC PSL MLO-004296 8-6 Machine-Check Stack Frames Table B-2 lists the possible values for the machine-check type code field. Table B-2: Machine-Check Type Codes for MicroVAX II and 2000, VAXstation II and 2000, and KA800 Processors Code Meaning 1 Impossible microcode state (FSD) 2 Impossible microcode state (SSD) 3 Undefined FPU error code 0 4 Undefined FPU error code 7 5 Undefined memory management status (TB miss) 6 Undefined memory management status (M = 0) 7 Process PrE in PO space 8 Process PrE in PI space 9 Undefined interrupt ID code 80 Read bus error, address parameter is virtual 81 Read bus error, address parameter is physical 82 Write bus error, address parameter is virtual 83 Write bus error, address parameter is physical 8.4 Machine-Check Stack Frame for rtVAX 300, MicroVAX 3nnnSeries, VAXstation 3100,3200, and 3500, and VAX 6000-2nn and 6000-3nn Series Processors Figure B-3 shows the information that is left on the stack when a machine check occurs on one of the following processors: • • • • rtVAX 300 MicroVAX 3nnn VAXstation 3100 VAXstation 3200 Machine-Check Stack Frames B-7 • • • VAXstation 3500 VAX 6000-2nn VAX 6000-3nn Figure B-3: Machine-Check Stack Frame for rtVAX 300, MlcroVAX 3nnn Series, VAXstation 3100, 3200, and 3500, and VAX 6000-2nn and 6000-3nn Series Processors Byte Count (00000010 hex) :(SP) Machine-Check Type Code Most Recent Virtual Address Intemal State Information 1 Intemal State Information 2 PC PSL MLO-004297 8-8 Machine-Check Stack Frames Table B-3 lists the possible values for the. machine-check type code field. Table B-3: Code Machine-Check Type Codes for rtVAX 300, MicroVAX 3nnn Series, VAXstation 3100, 3200, and 3500,and VAX 6000-2nn and 6000-3nn Series Processors Meaning 1 FPU detected protocol error 2 FPU detected reserved instruction 3 FPU error of unknown origin 4 FPU error of unknown origin 5 Process PrE address in PO space (TB miss) 6 Process PrE address in PI space (TB miss) 7 Process PrE address in PO space (M = 0) 8 Process PrE address in PI space (M = 0) 9 Undefined IPL A Impossible MOVe state detected 80 81 Read error 82 Write error 83 Write error Read error Machine-Check Stack Frames B-9 B.5 Machine.. Check Stack Frame for VAX 6000-4nn Series Processors Figure B-4 shows the information that is left on the stack when a machine check occurs on a VAX 6000-400 series processor. Figure 8-4: Machine-Check Stack Frame for VAX 6000-4nn Series Processors Byte Count (00000018 hex) VAX Result Bit I 0 I :(SP) Machine-Check Type Code Most Recent Virtual Address Prefetch Virtual Instruction-Buffer Address Interrupt State Information Internal State Information SC PC PSL MLO-004173 B-10 Machine-Check Stack Frames Table B-4 possible values for the machine-check type code field. Table 8-4: Code Machine-Check Type Codes for VAX 6000-4nn Series Processors Meaning 1 Protocol error during F-chip operand/result transfer 2 F -chip detected invalid opcode 3 F-chip detected operand parity error 4 F -chip returned unknown status 5 F-chip result parity error 8 TB miss status generated in ACVITNV microfiow 9 TB hit status generated in ACVfrNV microflow 10 Undefined INT.ID value during interrupt service 11 Undefined state bit combination in MOVCx 12 13 16 17 Undefined trap code produced by the IBOX 18 DAL bus error on write or clear write buffer Undefined control store address reached P-cache tag or data parity error during read DAL bus or data parity error during read 19 Undefined bus error microtrap 20 Vector unit error Machine-Check Stack Frames 8-11 8.6 Machine-Check Stack Frame for VAX 8200 and 8250 Processors Figure B-5 shows the information that is left on the stack when a machine check occurs on a VAX 8200 or 8250 processor. Figure 8-5: Machine-Check Stack Frame for VAX 8200 and 8250 Processors Byte Count (0000001 C hex) :(SP) First Parameter Virtual Address Register Contents Virtual Address Prime Register Contents Memory Address Register Contents Status Word PC at Failure Microcode PC at Failure PC PSL MLO-004298 8-12 Machine-Check Stack Frames B.7 Machine-Check Stack Frame for VAX 8500, 8550,8700, 8800, and 8810 Processors Figure B-6 shows the information that is left on the stack when a machine check occurs on a VAX 8500, 8550, 8700, 8800, or 8810 processor. Figure 8-6: Machine-Check Stack Frame for VAX 8500,8550,8700, 8800, and 8810 Processors Count of Bytes Pushed, Excluding PC, PSL, and Count. 10 hex. :(SP) MCSTS PC VANIBA IBER CBER EBER NMIFSR NMIEAR PC PSL MLO-004299 Machine-Check Stack Frames 8-13 Table B-5 lists the offset value and contents for each field in the stack frame. Table 8-5: Machine-Check Stack Frame Contents for VAX 8500, 8550, 8700, 8800, and 8810 Processors Mnemonic Offset Contents COUNT 00 04 08 OC 10 14 18 lC 20 24 28 MCSTS PC VAIVIBA IBER CBER EBER NMIFSR NMIEAR PC PSL B-14 Machine-Check Stack Frames Count of bytes pushed, excluding PC, PSL, and count Machine-check status Current PC Virtual address/virtual instruction-buffer address IBOX error CBOX error EBOX error NMI fault summary NMI error address PC offaulted opcode Processor status longword 8.8 Machine-Check Stack Frame for VAX-11n30 Processors Figure B-7 shows the information that is left on the stack when a machine check occurs on a VAX-11/730 processor. Figure B-7: Machine-Check Stack Frame for VAX-111730 Processors Byte Count (OOOOOOOC hex) :(SP) Machine-Check Type Code First Parameter Second Parameter PC PSL MLO-004295 Table B-6 lists the possible values for the machine-check error type code field. Table 8-6: Machine-Check Error Type Codes for VAX-11/730 Processors Code Meaning o Microcode should not be here. If the first parameter is 0, no other information is available. If the first parameter is 2, the problem was inability to write back a PTE bit. If the parameter is 3, the problem was a bad 8085 interrupt. The second parameter is always O. 1 Translation-buffer parity error. The first parameter is the bad value from the TB. PFN is in bits<23:0>. PTE , the protection code, and PTE are in bits<31:26>. TB valid bit is in bit<25>. The second parameter is the virtual address referenced. Machine-Check Stack Frames B-15 Table B-6 (Cont.): Machine-Check Error Type Codes for VAX-11n30 Processors Code Meaning 3 Impossible value in memory CSR. The first parameter is the virtual address referenced. The second parameter is the bad value of the CSR. 4 Fast interrupt without support. A fast interrupt was requested and no microcode was loaded to handle it. Both parameters are o. 5 FPA parity error. The FPA control store had a parity error. The first parameter has parity error summary in bit , group 0 parity in bit , group 1 parity in bit<2>, and is unpredictable in bits<31:3>. The second parameter is o. 6 Error on SPTE read. The first parameter is the physical address of the SPTE. The second parameter contains the error syndrome bits. 7 U ncorrectable ECC error. The first parameter is the physical address of the reference. The second parameter contains the error syndrome bits. 8 Nonexistent memory. The first parameter is the physical address referenced. The second parameter is o. 9 Unaligned or nonlongword reference to 1/0 space. The first parameter is the physical address referenced. The second parameter is o. 8-16 A Illegal I/O-space address. The first parameter is the physical address referenced. The second parameter is o. B Illegal UNIBUS reference. The first parameter is the physical address referenced. The second parameter is O. Machine-Check Stack Frames B.9 Machine-Check Stack Frame for VAX-11nSO Processors Figure B-8 shows the information that is left on the stack when a machine check occurs on a VAX-11/750 processor. Figure 8-8: Machine-Check Stack Frame for VAX-11I7S0 Processors Count of Bytes Pushed, Excluding PC, PSL, and Count. 28 hex. :(SP) Error Code VA Register PC at the Time of the Error MDR Saved Mode Register Read Lock Timeout TB Group Parity Error Register Cache Error Register Bus Error Register Machine-Check Error Summary Register PC PSL MLO-004300 Machine-Check Stack Frames 8-17 Table B-7lists the possible values for the machine-check error type code field. Table B-7: B-18 Machine-Check Error Codes for VAX-11/7S0 Processors Code Meaning 1 Control-store parity error 2 Translation-buffer parity error, bus error, or cache parity error 6 "Microcode should not be here" error 7 "Unused IRD ROM slot" error Machine-Check Stack Frames Appendix C VMS Emulation Routines The VAXELN Toolkit supports subsets of the VMS system services and Runtime Library routines to simplify the task of porting VMS programs to the VAXELN environment. System services are procedures that the VMS operating system uses to control resources that are available to processes, provide for communication among processes, and perform basic operating system functions, such as coordination of input/output operations. The Runtime Library routines are commonly used to perform a wide variety of operations. You can call the supported system services and Runtime Library routines from your VAXELN Pascal, VAX C, or FORTRAN programs using the standard VAX procedure-calling conventions. This appendix provides a summary of the supported emulation routines (see Section C.l), explains how to call the routines (see Section C.2), and describes the following: • • • C.1 VMS system service emulation routines, Section C.3 LIB$ emulation routines, Section C.4 STR$ emulation routines, Section C.5 VMS Emulation Routine Summary This section summarizes the VAXELN Toolkit's VMS emulation routine support. Table C-l summarizes the supported system services. Table C-2 provides a summary of the supported Runtime Library routines. VMS Emulation Routines C-1 Table C-1 : VMS System Service Emulation Routines Routine Function SYS$ASCTIM Convert binary time to ASCII string SYS$GETTIM Get the CUITent system time SYS$UNWIND Unwind the procedure call stack For brief descriptions of the supported system services, see Section C.3. For detailed descriptions, see the VMS System Services Reference Manual. The VMS Runtime Library routines are grouped as facilities according to the tasks they perfonn. The VAXELN Toolkit supports a subset of LIB$ facility routines and an STR$ facility routine. LIB$ facility routines provide access to VMS components such as system services and VAX machine instructions and perform such functions as the following: • • • • • • • Get records from devices Manipulate strings Convert data types for I/O Allocate resources Get system information Signal exceptions Enable detection of hardware exceptions The STR$ facility provides string manipulation routines that perform such tasks as searching for substrings, concatenating strings, and prefixing and appending strings. Table C-2: VMS Runtime Library Emulation Routines Routine Function Lm$ Facility Routines C-2 LIB$ADD_TlMES Add two quadword times LIB$ADDX Add two multiple-precision binary numbers VMS Emulation Routines Table C-2 (Cont.): Routine VMS Runtime Library Emulation Routines Function LIB$ Facility Routines LIB$ANALYZE_SDESC LIB$CREATE_USER_V]d_ZONE Analyze a string descriptor LIB$CREATE_~_ZONE Create a new storage zone LIB$CVT_DTB Convert ASCII decimal number to binary Create a user-defined storage zone Convert ASCII hexadecimal number to binary LIB$CVT_OTB Convert ASCII octal number to binary LIB$DELETE_~_ZONE Delete virtual memory zone LIB$EDIV Perform an extended-precision divide LIB$EMUL Perform an extended-precision mUltiply LIB$FLT_UNDER Enable or disable floating-point underflow detection LIB$FREE_~ Free virtual memory from the program region LIB$FREE_~_PAGE Free virtual memory page LIB$GET_INPUT Get a line from SYS$INPUT LIB$GET_~l Allocate virtual memory LIB$GET_~_PAGEI Get a virtual memory page LIB$INT_OVER Enable or disable integer overflow detection LIB$LEN Return the length of a string as a longword LIB$MATCH_COND Match condition values LIB$MULTF_DELTA_TIME Multiply delta time by scalar LIB$MULT_DELTA_TIME Multiply delta time by F_floating scalar LIB$PUT_OUTPUT Put a line in SYS$OUTPUT LIB$RESET_V]d_ZONE Reset virtual memory zone 1Differs from VMS routine. VMS Emulation Routines C-3 Table C-2 (Cont.): VMS Runtime Library Emulation Routines Routine Function LIB$ Facility Routines Copy source string by descriptor to destination Copy source string by reference to destination LIB$SIGNAL Signal exception condition LIB$SIG_TO_RET Convert signaled message to a return status LIB$STOP Stop execution and signal the condition LIB $ SUBX Perform multiple-precision binary subtraction LIB$SUB_TIMES Subtract two quadword times STR$ Facility Routines STR$ANALYZE_SDESC Analyze· a string descriptor For brief descriptions of the supported Runtime Library routines, see Sections C.4 and C.5. For detailed descriptions, see VMS RTL Library (LIB$) Manual and VMS RTL String Manipulation (STR$) Manual. C.2 Calling VMS Emulation Routines The VMS systems services and Runtime Library routines are external routines that accept arguments. The VAXELN Pascal, VAX C, and VAX FORTRAN languages each provide a mechanism for calling external procedures and for passing arguments to those procedures. The specific mechanisms and the associated terminology for the different languages vary. For example, FORTRAN programs invoke external routines with CALL statements or function references. The call formats for the supported system services and Runtime Library routines are summarized in Sections C.3 to C.5. The VMS System Services Reference Manual, VMS RTL Library (LIB$) Manual, and VMS RTL String Manipulation (STR$) Manual provide detailed routine descriptions that indicate how arguments are to be passed and describe routine-specific data structures. C-4 VMS Emulation Routines You must pass arguments to a routine in the order shown in the documented call formats. Each argument has four characteristics: VMS usage, data type, access type, and passing mechanism. These characteristics are described in the VMS System Services Reference Manual and the Introduction to the VMS Run-Time Library. Some arguments are optional and are indicated with square brackets ( [ ]). In VAXELN Pascal and FORTRAN programs, you can omit such arguments at the end of an argument list. If an optional argument is not at the end of the argument list, you must either pass a zero by value or use a comma as a place holder to indicate the position of the omitted argument. In C programs, you must specify all arguments. For optional arguments you choose not to specify, you must supply the value NULL. The following examples show how to call external routines from VAXELN Pascal, VAX C, and VAX FORTRAN programs. For languagespecific information about calling external routines, see the appropriate language documentation. VAXELN Pascal MODULE ernul; FUNCTION LIB$EMUL (VAR multiplier: INTEGER; VAR multiplicand: INTEGER; VAR addend: INTEGER; VAR product: LARGE_INTEGER): INTEGER; EXTERNAL; PROGRAM emul~rog( INPUT, OUTPUT ); VAR multiplier: INTEGER; multiplicand: INTEGER; addend: INTEGER; product: LARGE_INTEGER; status: INTEGER; VMS Emulation Routines C-5 BEGIN multiplier := 4096; multiplicand := 268435456; addend := 0; status := LIB$EMUL(multiplier, multiplicand, addend, product); IF ODD (status) THEN BEGIN END; ELSE WRITELN('Error calling LIB$EMUL'); END; END. VAXC finclude $vaxelnc main ( { int multiplier, multiplicand, addend, status; int lib$emul(); LARGE_INTEGER product; multiplier = 4096; multiplicand = 268435456; addend = 0; status = lib$emul(&multiplier, &multiplicand, &addend, &product); if (status == TRUE) else VAX FORTRAN c C This FORTRAN program demonstrates how to use LIB$EDIV. C INTEGER divisor,dividend(2),quotient,remainder C-6 VMS Emulation Routines c c c divisor = 4096 dividend (1) '12345678'x dividend (2) = 'OOOOOOOl'x C C C return = LIB$EDIV(divisor,dividend,quotient,remainder) TYPE *,'The longword integer quotient of 4600387192/4096 is:' TYPE *,' , ,quotient TYPE *,'The longword integer remainder of 4600387192/4096 is:' , , remainder TYPE * , , END C.3 VMS System Service Emulation Routine Descriptions This section briefly describes the VMS system services that the VAXELN Toolkit supports. For details, see the VMS System Services Reference Manual. SYS$ASCTIM - Convert Binary Time to ASCn String The SYS$ASCTIM system service converts an absolute or delta time from 64-bit system time to an ASCII string. Call Format SYS$ASCTIM [tim len] ,timbuf [,timadr] [,cvtjlg] Type Access Mechanism Word (unsigned) Character-coded text string Quadword (unsigned) Longword (unsigned) Write only Write only Read only Read only By reference By descriptor By reference By value The timbuf argument specifies the buffer into which the ASCII string is to be written. The optional argument timlen receives the length (in bytes) of the ASCII string that the system service returns. The optional arguments timadr and cvtflg specify the time value the system service is to convert and a conversion indicator that specifies the date and time fields the system service is to return, respectively. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By reference VMS Emulation Routines C-7 SYS$GE'ITIM - Get Time The SYS$GETIM system service returns the current system time in 64-bit format. Call Format Type Access Mechanism Quadword (unsigned) Write only By refere~ce SYS$GETTIM timadr The timadr argument receives the current time in 64-bit format. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value SYS$UNWIND - Unwind Procedure Call Stack The SYS$UNWIND system service removes a specified number of call frames from the procedure call stack. Optionally, it can return control to a new program counter (PC) after unwinding the stack. The SYS$UNWIND service is intended to be called from within a condition-handling routine. Call Format Type Access Mechanism Longword (unsigned) Longword (unsigned) Read only Read only By reference By reference SYS$UNWIND [depadr] [,newpc] The optional arguments depadr and newpc specify the depth to which the procedure call stack is to unwind and the new value for the PC, respectively. The new PC value replaces the current value of the PC in , the call frame of the procedure that receives control when the unwind operation is complete. Returns: Type: Longword (unsign~d) Access: Write only Mechanism: By value C-8 VMS Emulation Routines C.4 LIB$ Emulation Routine Descriptions This section briefly describes the LIB$ Runtime Library routines that the VAXELN Toolkit supports. 'For details, see the VMS RTL Library (LIB$) Manual. LIB$ADD_TIMES - Add Two Quadword Times The LIB$ADD_TIMES routine adds two time values in internal-time format. Call Format Type Access Mechanism Quadword (unsigned) Quadword (unsigned) Quadword (unsigned) Read only Read only Write only By reference By reference By reference Lm$ADD_TIMES timel ,time2 ,resultant.time The time1 and time2 arguments specify the times to be added. The resultant-time argument receives the sum. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$ADDX - Add Two Multiple-Precision Binary Numbers The LIB$ADDX routine adds two signed two's complement integers of arbitrary length. Call Format Type Access Mechanism Unspecified Unspecified Unspecified Longword integer (signed) Read only Read only Write only Read only By reference (array) By reference (array) By reference (array) By reference Lm$ADDX addend.array ,augend.arro.y ,resultant.array [,array.length] The addend-array and augend-array arguments specify the multiple-precision, signed two's complement integers to be added. The resultant-array argument receives the multiple-preci.sion, signed two's complement integer result of the addition. The optional argument array-length specifies the length of the arrays on which the routine is to operate. VMS Emulation Routines C-9 Returns: Type: Longword (unsigned) Access:· Write only Mechanism: By value LIB$ANALYZE_SDESC - Analyze String Descriptors The LIB$ANALYZE_SDESC routine extracts the length and the address at which the data starts for a variety of string descriptor classes. Call Format Type Access Mechanism Lm$ANALYZE_SDESC input-descriptor ,data-length ,data-address Character string Word (unsigned) Longword (unsigned) Read only Write only Write only By descriptor By reference By reference The input-descriptor argument specifies the input descriptor from which the routine is to extract the data's length and starting address. The data-length and data-address arguments specify the length and starting address of the data, respectively. The routine extracts the length and address from the input descriptor. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value Lm$CREATE_USER_VM_ZONE - Create User-Defined Storage Zone The LIB$CREATE_USER_VM_ZONE routine creates a new user-defined storage zone. Call Format Type Access Mechanism Longword (unsigned) Longword (unsigned) Procedure entry mask Procedure entry mask Procedure entry mask Procedure entry mask Character string Write only Read only Function call Function call Function call Function call Read only By reference By reference By value By value By value By value By descriptor Lm$CREATE_USER_~_ZONE zone-id [,user-argument] [,user-a.llocation-procedure] [,user-deallocation-procedure] [,user-reset-procedure] [,uBer-delete-procedure] [,zone-name] C-10 VMS Emulation Routines The zone-id argument specifies a zone identifier. The optional argument user-argument specifies a user argument. The optional arguments user-aLlocation-procedure, user-deallocation-procedure, user-reset-procedure, and user-delete-procedure specify user allocation, deallocation, reset zone, and delete zone routines, respectively. The optional zone-name argument specifies a name to be associated with the zone being created. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value Lm$CREATE_VM_ZONE - Create a New Zone The LIB$CREATE_VM_ZONE routine creates a new storage zone according to specified arguments. Call Format Lm$CREATE_VM_ZONE zone-id [,algorithm] [,algorithm-argument] [Jlags] [,extend-size] [,initial-size] [,block-size] [,alisnment] [,page-limit] [,smallest-block-size] [,zone-name] [,number-ot-areas] [,get-Pl18e] [Jree-Pl18e] Type Access Mechanism Longword (unsigned) Longword integer (signed) Longword integer (signed) Longword (unsigned) Longword integer (signed) Longword integer (signed) Longword integer (signed) Longword integer (signed) Longword integer (signed) Longword integer (signed) Character string Longword (signed) Procedure entry mask Procedure entry mask Write only Read only Read only Read only Read only Read only Read only Read only Read only Read only Read only Read only Read only Read only By reference By reference By reference By reference By reference By reference By reference By reference By reference By reference By descriptor By reference By value By value The zone-id argument specifies a zone identifier. The optional algorithm and algorithm-argument arguments specify the algorithm and algorithm arguments to be used to create the new zone. The optional flags argument specifies flag bits that control various options. The optional arguments extend-size, initial-size, block-size, alignment, page-limit, smallest-block-size, zone-name, and number-ot-areas specify the zone's extend size, initial size, block size, block alignment, maximum page limit, smallest block size, name, and number of memory areas, respectively. The optional get-page and free-page arguments specify routines that allocate and deallocate pages of memory. VMS Emulation Routines C-11 Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$Cvr_DTB - Convert Numeric Decimal Text to Binary The LIB$CVT_DTB routine returns a binary representation of the ASCII text string representation of a decimal number. Call Format Type Access Mechanism Lm$CVT_DTB byte. count ,numeric.8tring ,re8ult Longword integer (signed) Character string Longword integer (signed) Read only Read only Write only By value By reference By reference The byte-count argument specifies the byte count of the input ASCII text string. The numeric-string argument specifies the ASCII text string representation of a decimal number that the routine is to convert to binary representation. The result argument receives the binary representation of the input string. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$Cvr_HTB - Convert Numeric Hexadecimal Text to Binary The LIB$CVT_HTB routine returns a binary representation of the ASCII text string representation of a hexadecimal number. Call Format Type Access Mechanism Lm$CVT_HTB byte.count ,numeric'8tring ,re8ult Longword integer (signed) Character string Longword integer (signed) Read only Read only Write only By value By reference By reference The byte-count argument specifies the byte count of the input ASCII text string. The numeric-string argument specifies the ASCII text string representation of a hexadecimal number that the routine is to convert to binary representation. The result argument receives the binary representation of the input string. C-12 VMS Emulation Routines Returns: Type: Longword (unsigned) .Access: Write only Mechanism: By value LIB$CVT_OTB - Convert Numeric Octal Text to Binary The LIB$CVT_OTB routine returns a binary representation of the ASCII text string representation of an octal number. Call Format Type Access Mechanism Lm$CVT_OTB byte-count ,numeric-string ,result Longword integer (signed) Character string Longword integer (signed) Read only Read only By value By reference By reference Write only The byte-count argument specifies the byte count of the input ASCII text string. The numeric-string argument specifies the ASCII text string representation of a octal number that the routine is to convert to binary representation. The result argument receives the binary representation of the input string. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$DELETE_VM_ZONE - Delete Virtual Memory Zone The LIB$DELETE_VM_ZONE routine deletes a zone and returns all pages owned by the zone to the processwide page pool. Call Format Type Access Mechanism Lm$DELETE_VM_ZONE zone-UJ Longword (unsigned) Read only By reference The zone-id argument specifies a zone identifier. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value VMS Emulation Routines C-13 LIB$EDIV - Extend-Precision Divide The LIB$EDIV routine performs extended-precision division. This routine makes the VAX EDIV instruction available as a callable routine. Call Format Type .Access Mechanism Lm$EDIV longword.integer.dilJiBor ,quadword.integer-dilJidend ,longword.integer.quotient ,remainder Longword integer (signed) Quadword integer (signed) Longword integer (signed) Longword integer (signed) Read only Read only Write only Write only By reference By reference By reference By reference The longword-integer-divisor and quadword-integer-dividend arguments specify the divisor and dividend. The longword-integer-quotient and remainder arguments receive the quotient and remainder. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$EMUL - Extend-Precision Multiply The LIB$EMUL routine performs extended-precision multiplication. This routine makes the VAX EMUL instruction available as a callable routine. Call Format Type .Access Mechanism LIB$EMUL longword.integer.multiplier ,longword.integer.multiplicand ,addend ,product Longword integer (signed) Longword integer (signed) Longword integer (signed) Quadword integer (signed) Read only Read only Read only Write only By reference By reference By reference By reference The longword-integer-multiplier, longword-integer-multiplicand, and addend arguments specify the multiplier, multiplicand and addend, respectively. The product argument receives the product. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value C-14 VMS Emulation Routines LIB$FLT_UNDER - Floating-Point Underflow Detection The LIB$FLT_DNDER routine enables or disables floating-point underflow detection for the calling routine activation and returns the previous setting as a function value. Call Format Type .Access Mechanism Lm$FLT_UNDER new-setting Longword (unsigned) Read only By reference The new-setting argument specifies the new floating-point underflow enable setting. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$FREE_VM - Free Virtual Memory The LIB$FREE_VM routine deallocates an entire block of contiguous bytes in the program region that were allocated by a previous call to LIB$GET_VM. The arguments passed are the same as for LIB$GET_VM. Call Format Type Access Mechanism Lm$FREE_VM number-or-bytes ,base-address [,zone-idl Longword integer (signed) Longword (unsigned) Longword (unsigned) Read only Read only Read only By reference By reference By reference The number-of-bytes and base-address arguments specify the number of contiguous bytes to be deallocated and the address of the first byte to be deallocated, respectively. The optional argument zone-id specifies a zone identifier created by a previous call to LIB$CREATE_VM_ZONE or LIB$CREATE_USER_VM_ZONE. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$FREE_VM_PAGE - Free Virtual Memory Page VMS Emulation Routines C-15 The LIB$FREE_VM_PAGE routine deallocates a block of contiguous pages that were allocated by a previous call to LIB$GET_VM_PAGE. Call Format Type Access Mechanism Longword integer (signed) Longword (unsigned) Read only Read only By reference By reference LIB$FREE_V14_PAGE number-or-pages ,ba.se-address The number-of-pages argument specifies the number of contiguous pages to be deallocated. The base-address argument specifies the address of the first byte of the first page to be deallocated. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$GET_INPUT - Get Line from SYS$INPUT The LIB$GET_INPUT routine gets one record of ASCII text from the current controlling input device, specified by SYS$INPUT. Call Format Type Access Mechanism Character string Character string Word (unsigned) Write only Read only Write only By descriptor By descriptor By reference LIB$GET_INPUT resultant-string [,prompt-string] [,resultant-length] The resultant-string argument receives a string from the input device. The optional argument prompt-string specifies a prompt message that is to be displayed on the controlling terminal. The optional resultant-length argument receives a value indicating the number of bytes written into the resultant-string argument. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$GET_VM - Allocate Virtual Memory The LIB$GET_VM routine allocates a specified number of contiguous bytes in the program region and returns the virtual address of the :first byte allocated. C-16 VMS Emulation Routines When calling the LIB$GET_VM routine, you can specify the address of a longword that contains a zone identifier. If you do not specify this argument or if the longword contains the value 0, the default zone is used. The default zone has a set of attributes, two of which are the initial size and the area extension size. The values for these attributes differ for VAXELN systems. For VAXELN systems, the initial size is zero pages, and the area extension size is two pages. If you need to allocate over 1000 pages in a single request, you should call KER$ALLOCATE_MEMORY instead of LIB$GET_VM_PAGE. Call Format Type Access Mechanism LIB$GET_VM number-or-bytes ,bcue-address [,zone-id] Longword integer (signed) Longword (unsigned) Longword (unsigned) Read only Write only Read only By reference By reference By reference The number-oi-bytes argument specifies the number of contiguous bytes the routine is to allocate. The base-address argument receives the first virtual address of the contiguous block of bytes the routine allocates. The optional argument zone-id specifies the address of a longword that contains a zone identifier created by a previous call to LIB$CREATE_VM_ZONE or LIB$CREATE_USER_VM_ZONE. Returns~ Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$GET_VM_PAGE - Get Virtual Memory Page The LIB$GET_VM_PAGE routine allocates a specified number of contiguous pages of memory in the program region and returns the virtual memory address of the first page allocated. LIB$GET_VM_PAGE allocates blocks of contiguous (512-byte) pages in the program region. The LIB$GET_VM_PAGE routine is designed for memory allocation request sizes ranging from one page to a few hundred pages. If not enough contiguous free pages are available to satisfy a request, the system calls the kernel procedure KER$ALLOCATE_MEMORY (instead of the VMS system service SYS$EXPREG). If you need to allocate over 1000 pages in a single request, you should call KER$ALLOCATE_MEMORY instead of LIB$GET_VM_PAGE. VMS Emulation Routines C-17 Call Format Type Access Mechanism Lm$GET_VM;..PAGE number.or·page8 ,baBe-oddre88 Longword integer (signed) Longword (unsigned) Read only By reference By reference Write only The number-of-pages argument specifies the number of contiguous pages to be allocated. The base-address argument receives the address of the first byte of the allocated block of pages. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$INT_OVER - Integer Overflow Detection The LIB$INT_OVER routine enables or disables integer overflow detection for the calling routine activation and returns the previous in teger overflow enable setting. Call Format Type Access Mechanism Lm$INT_OVER neW.8etting Longword (unsigned) Read only By reference The new-setting argument specifies the new integer overflow enable setting. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$LEN - Length of String Returned The LIB$LEN routine returns the length of a string as a longword value. Call Format Type Access Mechanism Lm$LEN 80Urce.Btring Character string Read only By descriptor C-18 VMS Emulation Routines The source-string argument specifies the source string whose length the routine is to return. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$MATCH_COND - Match Condition Values The LIB$MATCH_COND routine checks to see if a given condition value matches a list of condition values that you supply. Call Format Type Access Mechanism LIB$MATCH.-COND match-condition-value ,compare-condition-ualue, ... Longword (unsigned) Longword (unsigned) Read only Read only By reference By reference The match-condition-value argument specifies the condition value to be matched. The compare-condition-value argument specifies the condition values to be compared to match-condition-value. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$MULT_DELTA_TIME - Multiply Delta Time by Scalar The LIB$MULT_DELTA_TIME routine multiplies a delta time by a longword integer scalar. Call Format Type Access Mechanism LIB$MULT_DELTA_TIME multiplier ,delta-time Longword (signed) Quadword (unsigned) Read only Modify By reference By reference The multiplier argument specifies the value by which the routine is to multiply the delta time. The delta-time argument specifies the delta time to be multiplied. VMS Emulation Routines C-19 Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$MULTF_DELTA_TIME - Multiply Delta Time by an F _Floating Scalar The LIB$MULTF_DELTA_TIME routine multiplies a delta time by an F_floating scalar. Call Format Type .Access Mechanism LIB$MULTF_DELTA_TIME mUltiplier ,delta-time F_floating Quadword (unsigned) Read only Modify By reference By reference The multiplier argument specifies the value by which the routine is to multiply the delta time. The delta-time argument specifies the delta time to be multiplied. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$PUT_OUTPUT - Put Line to SYS$OUTPUT The LIB$PUT_OUTPUT routine writes a record to the current controlling output device, specified by SYS$OUTPUT. Call Format Type .Access Mechanism LIB$PUT_OUTPUT message-string Character string Read only By descriptor The message-string specifies the message string that the routine is to write to the current controlling output device. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value C-20 VMS Emulation Routines LIB$RESET_VM_ZONE - Reset Virtual Memory Zone The LIB$RESET_VM_ZONE routine frees all blocks of memory that previously were allocated from the zone. Call Format Type Access Mechanism Longword (unsigned) Read only By reference LrB$RESET_V14S_Z0NE zone-jd The zone-id argument specifies the identifier of a zone created by a previous call to LIB$CREATE_VM_ZONE or LIB $ CREATE_USER_VM_ZONE. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$SCOPY_DXDX - Copy Source String Passed by Descriptor to Destination The LIB$SCOPY_DXDX routine copies a source string passed by descriptor to a destination string. Call Format Type Access Mechanism Character string Character string Read only Write only By descriptor By descriptor Lm$SCOPY_DXDX source-string ,destination-string The source-string argument specifies the source string to be copied to the destination string and the destination-string argument specifies the destination string to which the source string is to be copied. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$SCOPY_R_DX - Copy Source String Passed by Reference to Destination VMS Emulation Routines C-21 The LIB$SCOPY_R_DX routine copies a source string passed by reference to a destination string. Call Format Type Access Mechanism Lm$SCOPY_R_DX word-integer-source-length ,source-string-address ,destination-string Word (unsigned) Character string Character string Bead only Bead only Bead only By reference By reference By descriptor The word-integer-source-length argument specifies the length of the source string. The source-string-address and destination-string arguments specify the source string to be copied to the destination string and the destination string to which the source string is copied, respectively. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value Lm$SIGNAL - Signal Exception Condition The LIB$SIGNAL routine generates a signal that indicates that an exception condition has occurred in your program. If a condition handler does not take corrective action and the condition is severe, then your program will exit. Call Format Type Access Mechanism Lm$SIGNAL condition-valuel [,number-or-argumentsl] [,FAD-argumentl •.. ] [,condition-value2] [,number-of-arguments2] [,FAD-argument2 ••• ] Longword (unsigned) Longword integer (signed) Unspecified Longword (unsigned) Longword integer (signed) Unspecified Bead Bead Bead Bead Bead Bead By value By value By value By value By value By value only only only only only only The condition-valuel and condition-value2 arguments specify VAX 32-bit condition values. The optional arguments number-of-argumentsl and number-of-arguments2specify the number of formatted ASCII output (FAO) arguments associated with the first and second conditiol1 values. The optional arguments FAO-argumentl and FAO-argument-2 specify optional FAO arguments associated with the first and second condition value. Returns: None C-22 VMS Emulation Routines LIB$SIG_TO_RET - Signal Converted to a Return Status The LIB$SIG_TO_RET routine converts a signaled condition value to a value returned as a function. The signaled condition is returned to the caller of the user routine that established the handler that is calling LIB$SIG_TO_RET. This routine may be established as or called from a condition handler. Call Format Type Access Mechanism LIB$SIG_TO_RET signal-arguments ,mechanism-arguments Unspecified Unspecified Read only Read only By reference (array) By reference (array) The signal-arguments and mechanism_arguments arguments specify the addresses of arrays that are the signal argument and mechanism argument vector stacks, respectively. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value Lm$STOP - Stop Execution and Signal the Condition The LIB$STOP routine generates a signal that indicates that an exception condition has occurred in your program. Exception conditions signaled by LIB$STOP cannot be continued from the point of the signal. Call Format Type Access LIB$STOP condition-valueI [,number-of-argumentsl] [,FAO-ar.qumentl " . ] [,condition-value2] [,number-of-arguments2] [,FAO-argument2 .•. ] Longword (unsigned) Longword integer (signed) Unspecified Longword (unsigned) Longword integer (signed) Unspecified Read Read Read Read Read Read only only only only only only Mechanism By value By value Unspecified By value By value Unspecified The condition-valuel and condition-value2 arguments specify VAX 32-bit condition values. The optional arguments number-of-argumentsl and number-of-arguments2 specify the number of formatted ASCII output (FAO) arguments associated with the first and second condition values. The optional arguments FAO-argument1 and FAO-argument-2 specify optional FAO arguments associated with the first and second condition value. VMS Emulation Routines C-23 Returns: None LIB$SUB_TIMES - Subtract Two Quadword Times The LIB$SUB_TIMES routine subtracts two time values in internal-time format. Call Format Type .Access Mechanism LIB$SUB_TIMES timel ,time2 ,resultant-time Quadword (unsigned) Quadword (unsigned) Quadword (unsigned) Read only Read only Write only By reference By reference By reference The timel argument specifies the time from which the routine subtracts another time. The time2 argument specifies the time that the routine subtracts from the first time. The resultant-time argument receives the difference. Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value LIB$SUBX - Multiple.Precision Binary Subtraction The LIB$SUBX routine performs subtraction on signed two's complement integers of arbitrary length. Call Format Type .Access Mechanism LIB$SUBX minuend-array ,subtrahend-array ,difference-array [,array-length] Unspecified Unspecified Unspecified Longword integer (signed) Read only Read only Write only Read only By reference (array) By reference (array) By reference (array) By reference The minuend-array and subtrahend-array specify the minuend and subtrahend, multiple-precision, signed two's complement integers. The difference-array argument receives the difference, a multiple-precision, signed two's complement integer. The opitional argument array-length specifies the length of the arrays on which the routine is to operate. C-24 VMS Emulation Routines Returns: Type: Longword (unsigned) Access: Write only Mechanism: By value C.5 STR$ Emulation Routine Description This section briefly describes the STR$ Runtime Library routine STR$ANALYZE_SDESC. For details, see the VMS RTL String Manipulation (STR$) Manual. STR$ANALYZE_SDESC - Analyze String Descriptor The STR$ANALYZE_SDESC routine extracts the length and starting address of the data for a variety of string descriptor classes. Call Format Type .Access Mechanism STR$ANALY2E_SDESC input.descriptor ,word.integer.length ,data.address Character string Word (unsigned) Longword (unsigned) Read only Write only Write only By descriptor By reference By reference The input-descriptor argument specifies the input descriptor from which the routine is to extract the length of the data and the address at which the data starts. The word-integer-length and data-address arguments specify the length and address of the data. The routine extracts the length and address from the descriptor. Returns: None VMS Emulation Routines C-25 Appendix D SCSI Port Driver Interface Routines The VAXELN Toolkit provides a set of interface routines for programming communication between user-written SCSI class drivers and the VAXELN SCSI port driver. The port driver interface routines let you allocate and build a SCSI command request packet and send it to a device on a SCSI bus. The interface also provides routines for freeing resources after a SCSI command performs its operations. This appendix provides descriptions of the SCSI port driver interface routines. Each description provides an overview; call formats and argument information for Pascal, C, and FORTRAN; argument descriptions; a description of the routine's return value; and examples. The call formats for the Pascal interface show how to invoke the routines using the INVOKE function. A call to INVOKE specifies a pointer. to the routine's entry mask, the name of a function type declared for the routine, and the routine's arguments. Descriptions are provided for only the port interface routine arguments; the argument descriptions listed for each routine do not include the INVOKE function's entry mask pointer or function type arguments. Before a class driver written in Pascal can invoke the interface routines, the driver must declare the routine addresses as follows: TYPE PORT ROUTINES = RECORD ctx init issue alloc free map unmap exit END; AANYTYPE; AANYTYPE; AANYTYPE; AANYTYPE; AANYTYPE; AANYTYPE; AANYTYPE; AANYTYPE; SCSI Port Driver Interface Routines D-1 VAR routine addresses : [EXTERNAL] port_routines; Similarly, before a class driver written in FORTRAN can invoke the interface routines, the driver must declare the type definition for the routine addresses defined in $SCSIPORT.H as follows: STRUCTURE /PORT_ROUTINES/ INTEGER*4 ctx INTEGER*4 init INTEGER*4 issue INTEGER*4 alloc INTEGER*4 free INTEGER*4 map INTEGER*4 unmap INTEGER*4 exit END STRUCTURE RECORD /PORT_ROUTINES/ routine addresses Prior to the calling the routines, the FORTRAN class driver must also delcare the variables routine_addresses and lock_device as external data, using the EXTERNAL statement as follows: EXTERNAL routine addresses EXTERNAL lock device These statements ensure that the symbols are resolved such that they are the addresses for the SCSI port interface callback routines as declared by the VAX C global definition (globaldef) storage class. For more information, see Section 14.5.3.2. A SCSI class driver gains access to the interface routines by using their addresses. One way of doing this from a FORTRAN driver is to apply the usual method for dealing with pointers in FORTRAN. For example: • • Pass the external variable routine_addresses to a subroutine that declares the variable as a RECORD /PORT_ROUTINES/. This enables the driver to access the necessary fields of the routine_addresses. As appropriate, pass a routine address (for example, routine_addresses.alloc) by value to another subroutine that redeclares the address to be EXTERNAL. The driver can then call the routine by using the name of the dummy argument. For information about developing a user-written class driver, see Section 14.5.3. See SAMPLE_SCSIDRIVER.PAS, SAMPLE_SCSIDRIVER.C, and SAMPLE_SCSIDRIVER.FOR in the VAXELN ELN$ directory for sample user-written SCSI class drivers. D-2 SCSI Port Driver Interface Routines PORT$ALLOCATE_DEVICE PORT$ALLOCATE_DEVICE Allocates a virtual device (SCSI command request packet) for the calling SCSI class driver and returns the virtual device number. To invoke this routine from a class driver written in Pascal, the driver must first declare the following function type: FUNCTION scsiport$allocate device(ctx : AANYTYPE; scsi target : INTEGER; cmd_bcnt : INTEGER; cmd-ptr : AANYTYPE; sts-ptr : AANYTYPE): INTEGER; FUNCTION_TYPE; Pascal Format INCLUDE SCSIPORT INCLUDE $SCSI_UTILITY virtual device:= INVOKE (routine_addresses. a I/o c, scsiport$allocate_ device, routine_addresses.ctx, scsLtarget, cmd_bcnt, cmd_ptr, sts_ptr) argument information routine addresses.ctx: scsi target: INTEGER cmer bcnt: INTEGER cmaptr: "ANYTYPE stsyfr: "ANYTYPE "ANYTYPE SCSI Port Driver Interface Routines D-3 PORT$ALLOCATE_DEVICE C Format #include $scsiport #include $scsi_utility virtual_device (*routine_addresses.ctx_a_alloc) (routine_addresses.ctx, scsLtarget, cmd_bcnt, cmd_ptr, sts_ptr) = argument information char *routine addresses.ctx char scsi target int cmdocn1 unsignedchar **cmd_ptr unsigned char **stsyfr FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format virtual_device = alloc_routine (% val(routine_ addresses~ ctx), %val(scsLtarget), %val(cmd_bcnt), cmd_ptr, sts_ptr) argument information INTEGER*4 routine addresses.ctx INTEGER*4 scsi target INTEGER*4 cma bcnt INTEGER*4 cmaptr INTEGER*4 stsyfr 0-4 SCSI Port Driver Interface Routines PORT$ALLOCATE_DEVICE Arguments routine_addresses.ctx Specifies the pointer to the port driver's data structures. scsltarget Specifies the SCSI device ID for the device on the SCSI bus that is to handle the command request. cmd_bcnt Specifies the number of bytes to be allocated for the request packet's SCSI command buffer. The command buffer can store up to 256 bytes of command data. cmdJ'tr Receives a pointer to the request packet's command buffer. A driver must use the returned pointer to place a SCSI command in the request packet. stsJ'tr Receives a pointer to the request packet's SCSI status buffer. The status buffer receives a status code from the target device, as defined in the ANSI SCSI specification, after the completion of a SCSI command. Returns An integer in the range 0 to 15 that identifies the SCSI command request packet. Examples 1. virtual deviee := INVOKE(routine addresses.alloe, sesiport$alloeate_deviee, sesi target, emd bent, ADDRESS(emd-ptr), ADDRESS(sts-ptr»; Shows a call to PORT$ALLOCATE_DEVICE in VAXELN Pascal. SCSI Port Driver Interface Routines D-5 PO RT$AL LOCATE_D EVICE 2. virtual device = (*routine addresses.ctx a alloc) (routi~e addresses.ctx-a context, scsi target, - cmd_bcnt, & cmdytr, &stsytr) ; Shows a call to PORT$ALLOCATE_DEVICE in C. 3. call allloc - = alloe routine (%val (routine addresses.ctx), %val(scsi target), %val (emdj>ent), emdytr, stsytr) Shows a call to PORT$ALLOCATE_DEVICE in FORTRAN. The call_alloc identifier is the name of the function that is to handle the address of the PORT$ALLOCATE_DEVICE callback routine. D-6 SCSI Port Driver Interface Routines PORT$EXIT_HANDLER PORT$EXIT_HANDLER Terminates the SCSI port driver and returns all port driver resources back to the system. NOTE An application should call this function only if the port driver needs to be terminated. This function frees all resources associated with the port and disconnects the device from the interrupt service routine (ISR). Digital recommends that user-defined class drivers not invoke this function. To invoke this routine from a class driver written in Pascal, the driver must first declare the following function type: FUNCTION scsiport$exit_handler(ctx : AANYTYPE): INTEGER; FUNCTION_TYPE; Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITY status := INVOKE (routine_8ddresses.exit, scsiport$exiLhandler, routine_addresses. ctx) argument information routine addresses.ctx: AANYTYPE C Format #include $scsiport #include $scsi_utility result (*routine_addresses.ctx_a_exit) (ctx) = SCSI Port Driver Interface Routines D-7 PORTSEXIT_HANDLER argument information char *routine_addresses.ctx FORTRAN INCLUDE 'ELNS:FORTRAN_DEFS.FOR' Format result exit routine = (%val(routine_addresses.ctx)) argument information INTEGER*4 routine_addresses.ctx Arguments routine_sddresses.ctx Specifies the pointer to the port driver's data structures. Returns A status value returned by kernel routine calls. Examples 1. status := INVOKE(routine addresses. exit, scsiport$exit handler, routine_addre;ses.ctx); Shows a call to PORT$EXIT_HANDLER in VAXELN Pascal. 2. status = (*routine addresses.ctx a exit) (routine_addresses.ctx=a_context) Shows a call to PORT$EXIT_HANDLER in C. D-8 SCSI Port Driver Interface Routines PORT$EXIT_HANDLER 3. call_exit = exit_routine (%val (routine_addresses.ctx» Shows a call to PORT$EXIT_HANDLER in FORTRAN. The call exit identifier is the name of the function that is to handle the -;ddress of the PORT$EXIT_HANDLER callback routine. SCSI Port Driver Interface Routines 0-9 PORT$FREE_DEVICE PORT$FREE_DEVICE Returns a SCSI command request packet to the list of free SCSI command request packets. If another process is waiting for a request packet, PORT$FREE_DEVICE signals that process. To invoke this routine from a class driver written in Pascal, the driver must first declare the following function type: FUNCTION scsiport$deallocate device(ctx : AANYTYFEi virtual_device : INTEGER) FUNCTION_TYPE; Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITY status := INVOKE (routine_addresses. free, scsiport$deallocate_device, routine addresses.ctx, virtuaL de vice) argument information routine addresses.ctx: AANYTYPE virtuaLaevice: INTEGER C Format #include $scsiport #include $scsi_utility status = (*routine_addresses.ct~a_free) (routine_addresses.ctx, virtuaL de vice) 0-10 SCSI Port Driver Interface Routines : INTEGER; PORT$FREE_DEVICE argument information char *routine addresses.ctx int virtual device FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format status = free routine (% val(routine_addresses. ctx), %val(virtuaL device)) argument information INTEGER*4 routine addresses.ctx INTEGER*4 virtual aevice Arguments routine_sddresses.ctx Specifies the pointer to the port driver's data structures. virtusl device Specifies the packet ID for the SCSI command request packet to be returned to the request packet free list. You must specify a packet ID returned by PORT$ALLOCATE_DEVICE. Returns An integer status value of SS$_NORMAL. Examples 1. status:= INVOKE(routine addresses. free, scsiport$deallocate device, routine addresses.ctx, virtual:=device) Shows a call to PORT$FREE_DEVICE in VAXELN Pascal. SCSI Port Driver Interface Routines D-11 PORT$FREE_DEVICE 2. status = (*routine addresses.ctx a free) (routi~e addresses.ctx-a context, virtual=device); -- Shows a call to PORT$FREE_DEVICE in C. 3. call free - = free routine(%val(routine addresses.ctx), %val (virtual=device») Shows a call to PORT$FREE_DEVICE in FORTRAN. The callJree identifier is the name of the function that is to handle the address of the PORT$FREE_DEVICE callback routine. 0-12 SCSI Port Driver Interface Routines PORT$INITIALIZE_CONTROLLER PORT$INITIALIZE_CONTROLLER Asserts the SCSI RST signal on the SCSI bus. This signal causes all devices on the SCSI bus to release all asserted signals and places the bus in a BUS FREE state. NOTE A class driver should not call this routine unless the SCSI bus is hung. To invoke this routine from a class driver written in Pascal, the driver must first declare the following function type: FUNCTION scsiport$initialize controller(ctx : AANYTYFE; scsi_target : INTEGER): INTEGER; FUNCTION_TYPE; Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITY status := INVOKE (routine_ addresses.init, scsiport$initialize_ controller, routine addresses.ctx, scsLtarget) argument information routine addresses.ctx: scsLtarget: INTEGER AANYTYPE SCSI Port Driver Interface Routines D-13 PORT$INITIALIZE_CONTROLLER C Format #include $scsiport #include $scsi_utility status (*routine_addresses.ctx_a_init) = (routine_addresses.ctx, scsLtarget) argument information char *routine addresses.ctx char scsLtarget FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format status = init_routine (%val(routine_addresses.ctx), %val(scsLtarget)) argument information INTEGER*4 INTEGER*4 routine addresses.ctx scsLtarget Arguments routine_ addresses.ctx Specifies the pointer to the port driver's data structures. scsltarget Specifies the SCSI device ID for a working SCSI target device. Returns An integer status value of SS$_NORMAL. 0-14 SCSI Port Driver Interface Routines PORT$INITIALIZE_CONTROLLER Examples 1. status:- ZNVOKB(routine addresses.init, scsiport$initialize controller, routine addresses.ctx, scsi_target) ; Shows a call to PORT$INITIALIZE_CONTROLLER in VAXELN Pascal. 2. atatus _ (*routine addresses.ctx a init) (routine addresses.ctx-a context, scsi_target) - - Shows a call to PORT$INITIALIZE_CONTROLLER in C. S. call init - = init - routine(%val(routine addresses.ctx), %val(scsi_target» Shows a call to PORT$INITIALIZE_CONTROLLER in FORTRAN. The call init identifier is the name of the function that is to handle the address of the PORT$INITIALIZE_CONTROLLER callback routine. SCSI Port Driver Interface Routines D-15 PORT$ISSUE_COMMAND PORT$ISSUE_COMMAND Arbitrates and selects a device on the SCSI bus, issues the SCSI command that is in the specified SCSI command request packet, and performs the tasks necessary to complete the operation. To invoke this routine from a class driver written in Pascal, the driver must first declare the following constants and function type: CONST SCSI$K DISCONNECT = 0; SCSI$K-NODISCONNECT = 1; SCSI$K-RETRY = 0; SCSI$K=NORETRY = 1; FUNCTION scsiport$issue command(ctx : AANYTYPE; virtual_device : INTEGER; disconnect : INTEGER; disable retry : INTEGER; phase_timeout : INTEGER; disconnect_timeout : INTEGER) FUNCTION_TYPE; : INTEGER; The constants SCSI$K_DISCONNECT, SCSI$K_NODISCONNECT, SCSI$K_RETRY, and SCSI$K_NORETRY are declared in the modules $scsi_utility and ELN$:FORTRAN_DEFS.FOR for drivers written in C and FORTRAN, respectively. Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITY status := INVOKE (routine_addresses.issue, scsiport$issue_ command, routine addresses.ctx, virtual device, disconnect, disable_retry, phase_timeout, disconnecLtimeout) 0-16 SCSI Port Driver Interface Routines PORT$ISSUE_COMMAND argument information routine addresses.ctx: AANYTYPE virtual aevice: INTEGER disconnect: INTEGER disable retry: INTEGER p'hase timeout: INTEGER 'disconnecLtimeout: INTEGER C Format #include $scsiport #include $scsi_utility = status (*routine_addresses.ctx_a_issue) (routine_addresses.ctx, virtual device, disconnect, disable_retry, phase_timeout, disconnecLtimeout) argument information char *routine addresses.ctx int virtual device int disconnect int disable retry int p'hase timeout int'disconnect timeout FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format status = issue routine (%val(routine_addresses.ctx), %val(virtuaL device), %val(disconnect), % val(disable_retry), SCSI Port Driver Interface Routines D-17 PORT$ISSUE_COMMAND %val(phase_ timeout), % val(disconnecL timeout)) argument information INTEGER*4 INTEGER*4 INTEGER*4 INTEGER*4 INTEGER*4 INTEGER*4 routine addresses.ctx virtual aevice disconnect disable retry p'hase Timeout CiisconnecLtimeout Arguments routlne_addresses.ctx Specifies the pointer to the port driver's data structures. virtual device Specifies the packet ID for the SCSI command request packet that contains the command being issued. You must specify a packet ID returned by PORT$ALLOCATE_DEVICE. disconnect Specifies whether the target device can disconnect during command execution. Specify SCSI$K_DISCONNECT to allow the device to disconnect. Specify SCSI$K_NODISCONNECT to prevent the device from disconnecting. disable_retry Specifies whether the port driver should attempt to repeat a command that fails due to a timeout, bus parity, or invalid phase transition error. Specify SCSI$K_RETRY to allow the port driver to retry commands. When this characteristic is set, the port driver will attempt three retries. Specify SCSI$K_NORETRY to disable retries. phase_timeout Specifies the amount of time a target device has to change to another SCSI bus phase. You can specify from 0 to 420 seconds. If you specify o seconds or an invalid value, the driver uses a timeout value of 20 seconds. D-18 SCSI Port Driver Interface Routines PORT$ISSUE_COMMAND dlsconnecLtlmeout Specifies the amount of time a target device has to reselect an initiator to proceed with a disconnected data transfer. You can specify from 0 to 420 seconds. If you specify 0 seconds or an invalid value, the driver uses a timeout value of 20 seconds. Returns The status value SS$_CTRLERR, SS$_TIMEOUT, or SS$_NORMAL. Examples 1. status := INVOKE(routine addresses. issue, scsiport$issue_command, routine addresses.ctx, virtual-device, SCSI$K DISCONNECT, SCSI$K-RETRY, phase timeout, disconnect_timeout); Shows a call to PORT$ISSUE_COMMAND in VAXELN Pascal. 2. status = (*routine_addresses.ctx_a_issue) (routine addresses.ctx a context, virtual-device, - SCSI$K DISCONNECT, SCSI$K-RETRY, phase timeout, disconnect_timeout); Shows a call to PORT$ISSUE_COMMAND in C. 3. call issue = issue_routine(%val(routine_addresses.ctx), %val(virtual device), %val(SCSI$K DISCONNECT), %val(SCSI$K=RETRY), %val(phase timeout), %val(disconnect_timeout» Shows a call to PORT$ISSUE_COMMAND in FORTRAN. The call issue identifier is the name of the function that is to handle the address of the PORT$ISSUE_COMMAND callback routine. SCSI Port Driver Interface Routines D-19 PORT$MAP_BUFFER PORT$MAP_BUFFER Searches the 128-Kbyte SCSI DMA RAM bitmap for a specified amount of contiguous data bytes, updates the SCSI command request packet with the appropriate mapping information, and marks the bitmap pages as unavailable. To invoke this routine from a class driver written in Pascal, the driver must first declare the following constants and function type: CONST SCSI$K WRITE = 0; SCSI$K=READ = 1; FUNCTION scsiport$map_buffer(ctx : AANYTYPE; virtual device : INTEGER; buffer 7 AANYTYPE; buf len : INTEGER; pad=len : INTEGER; direction : INTEGER) : INTEGER; The constants SCSI$K_READ and SCSI$K_WRITE are declared in the modules $scsi_utility and ELN$:FORTRAN_DEFS.FOR for drivers written in C and FORTRAN, respectively. Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITV status := INVOKE (routine_addresses. map, scsiport$map_buffer, routine_addresses.ctx, virtual device, buffer,buLlen, pad_len, direction) 0-20 SCSI Port Driver Interface Routines PORT$MAP_BUFFER argument information routine addresses.ctx: AANYTYPE virtual aevice: INTEGER buffer: AANYTYPE but len: INTEGER p'aa len: INTEGER 'direction: INTEGER C Format #include $scsiport #include $scsi_utility = status (*routine_addresses.ctx_a_map) (routine_addresses.ctx, virtual device, *butter, buLlen, pad_len, direction) argument information char *routine addresses.ctx, int virtual device unsi.g'ned char *buffer int Dut len int p'aa len int 'direction FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format status map_routine = (%val(routine_addresses.ctx), % val(virtuaL device}, %ret(buffer}, %val(buLlen}, SCSI Port Driver Interface Routines 0-21 PORT$MAP_BUFFER %val(pad_len), %val(direction)) argument information routine addresses.ctx virtual aevice, CHARACTER*n buffer INTEGER*4 but len INTEGER*4 INTEGER*4 INTEGER*4 ~aa I~n INTEGER*4 'direction Arguments routine_addresses.ctx Specifies the pointer to the port driver's data structures. virtuaL device Specifies the packet ID for the SCSI command request packet for which a data buffer is to be mapped. You must specify a packet ID returned by PORT$ALLOCATE_DEVICE. buffer Specifies a pointer to the data buffer to be mapped. bu,-Ien Specifies the size of the data buffer to be mapped. Specify a value in the range 1 to 65536. pad_len Specifies the pad size needed for a SCSI command that requires a transfer size that is larger than the size specified by buf_len. If the amount of data requested in a SCSI command exceeds the space allocated for the data buffer, the pad size accounts for the difference. direction Specifies whether the data transfer is a read or write operation. Specify SCSI$K_WRITE for a write operation; specify SCSI$K_READ for a read operation. 0-22 SCSI Port Driver Interface Routines PORT$MAP_BUFFER Returns An integer status value of SS$_NORMAL. Examples 1. status := INVOKE(routine addresses.map, scsiport$map buffer, routine addresses.ctx, virtual-device, buffer, buf len, pad-len, SCSI$K_READ) ; Shows a call to PORT$MAP_BUFFER in VAXELN Pascal. 2. status (*routine_addresses.ctx_a_map) (routine addresses.ctx a context, virtual-device, - *buffer; buf len, pad-len, SCSI$K_READ); Shows a call to PORT$MAP_BUFFER in C. 3. call map = map routine (%val (routine addresses.ctx), %val(virtual-device) , %ref(buffer); %val (buf len), %val (pad-len), %val(SCSI$K_READ» Shows a call to PORT$MAP_BUFFER in FORTRAN. The call_map identifier is the name of the function that is to handle the address of the PORT$MAP_BUFFER callback routine. SCSI Port Driver Interface Routines 0-23 PORT$UNMAP_BUFFER PORT$UNMAP_BUFFER Returns the memory used for a SCSI command request packet data buffer back to the 128-Kbyte DMA RAM bitmap and marks the returned pages as available. If another process is waiting for DMA RAM memory, PORT$UNMAP_BUFFER signals that process. To invoke this routine from a class driver written in Pascal, the driver must first declare the following function type: FUNCTION scsiport$unmap buffer(ctx : AANYTYPE; virtual_device : INTEGER; buffer : AANYTYPE; buf len : INTEGER; pad=len : INTEGER): INTEGER; FUNCTION_TYPE; Pascal Format INCLUDE $SCSIPORT INCLUDE $SCSI_UTILITY status := INVOKE (routine_addresses.unmap, scsiport$unmap_ buffer, routine_addresses.ctx, virtual device, buffer,but len, pad len) argument information routine addresses.ctx: AANYTYPE virtual aevice: INTEGER buffer: AANYTYPE but len: INTEGER paetJen: INTEGER 0-24 SCSI Port Driver Interface Routines PORT$UNMAP_BUFFER C Format #include $scsiport #include $scsi_utility status = (*routine_addresses.ctx_a_unmap) (routine_addresses.ctx, virtuaL de vice, *bufter, but len, pad len) argument information char *routine addresses.ctx, int virtual device unsi,gned char *buffer int ouf len int palLlen FORTRAN INCLUDE 'ELN$:FORTRAN_DEFS.FOR' Format status = unmap_routine (%val(routine_addresses.ctx), % val(virtuaL device), %ret(buffer), %val(bul/en), %val(pad_len)) argument information INTEGER*4 routine addresses.ctx INTEGER*4 virtual aevice, CHARACTER*n buffer INTEGER*4 buf len INTEGER*4 pact len SCSI Port Driver Interface Routines D-25 PORT$UNMAP_BUFFER Arguments routlne_addresses.ctx Specifies the pointer to the port driver's data structures. virtual device Specifies the packet ID for the SCSI command request packet for which a data buffer is to be unmapped. You must specify a packet ID returned by PORT$ALLOCATE_DEVICE. buffer Specifies a pointer to the data buffer to be unmapped. bu,--Ien Specifies the size of the data buffer to be unmapped. Specify a value in the range 1 to 65536. pad_len Specifies the pad size of the data buffer to be unmapped. Returns An integer status value of SS$_NORMAL. Examples 1. status := INVOKE(routine addresses.unmap, scsiport$unmap buffer, routine_addresses.ctx, virtual device, buffer,buf_Ien, pad_len) ; Shows a call to PORT$UNMAP_BUFFER in VAXELN Pascal. D-26 SCSI Port Driver Interface Routines PORT$UNMAP_BUFFER 2. status (*routine_addresses.ctx_a_unmap) (routine addresses.ctx a context, virtual-device, - *buffer; buf len, pa()en) ; Shows a call to PORT$UNMAP_BUFFER in C. 3. call unmap - = unmap routine(%val(routine addresses.ctx), %val (virtual-device), %ref(buffer); %val (buf len), %val (pad:=len) ) Shows a call to PORT$UNMAP_BUFFER in FORTRAN. The call_unmap identifier is the name of the function that is to handle the address of the PORT$UNMAP_BUFFER callback routine. SCSI Port Driver Interface Routines 0-27 Index A Absolute pointers, in areas • 5-32 Absolute time • 4-2 waiting for an • 4-6 ACCEPT_CIRCUIT procedure accepting logical links with • 9-2 accepting messages from network nodes with· 9-3 accepting VMS connections with • 9-48 as PORT object operation· 2-12 controlling message flow with· 5-17 establishing circuits for authorization with • 12-16 establishing circuits with· 5-17 waiting for circuit connection with • 5-23 accept function· 10-55 accepting connection requests with • 10-65 Access control string • 12-5, 12-18 Access to shared resources • 4-1 0 to 4-18 See also Synchronization types of· 4-11 ACK (acknowledgement) receiving from TCP • 10-8 setting time to wait for • 10-24 Acknowledgement (ACK) See ACK (acknowledgement) Active service nodes • 11-16, 11-21 See also LAT (local area transport) ADD_INTERLOCKED function • 5-2 Addresses See also Ethernet addresses; Hardware addresses; Internet addresses; Physical addresses multicast· 8-18 Address notation, Internet See Internet addresses Address resolution method • 10-24 Address Resolution Protocol (ARP) See ARP (Address Resolution Protocol) AD032 device ·14-128,14-130 ADO device driver utility procedures· 14-130 ADO_INITIALIZE procedure· 14-131 ADO_OUEUE_READ procedure· 14-131 ADO_START procedure· 14-131 ADO_TRANSFER_DONE procedure ·14-131 ADV11-C device· 14-128, 14-131 ADV11-D device· 14-128, 14-133 ADV device driver utility procedures ·14-134 ADVJNITIALIZE procedure ·14-134 ADV_OUEUE_READ procedure· 14-134 ADV_TRANSFER_DONE procedure ·14-134 AF_IN ET communication domain • 10-15 specified in socket names • 10-59 Allocated system region • 3-30 freeing • 3-31 using to transfer data • 14-7, 14-1 0, 14-20 to 14-24 ALLOCATE_MAP procedure· 6-10 ALLOCATE_MEMORY procedure • 3-29 ALLOCATE_PATH procedure· 6-11 ALLOCATE_STACK procedure • 3-28 ALLOCATE_SYSTEM_REGION procedure • 3-30 Analog-to-digital converter AD032 ·14-130 ADV11-C/AXV11-C· 14-131 ADV11-D· 14-133 ANSI control sequences· 14-65 Application devices, LAT· 11-2 See also LAT (local area transport) Index-1 Application devices, LAT (Cont.) accessing • 11-36 associating with application LAT ports· 11-41 environment of (figure)· 11-37 example· 11-38 to 11-40 setting up • 11-36 to 11-43 Application-initiated load requests· 9-35, 9-36, 9-40 Application LAT port • 11-7, 11-40 See also LAT (local area transport) Application services See LAT (local area transport) Area-locking procedures ELN$INITIALIZE AREA LOCK· 5-29 initializing a~ea lockvariables with • 5-40 ELN$LOCK_AREA • 5-29 ELN$UNLOCK_AREA • 5-29 unlocking areas with· 5-40 AREA_LOCK_VARIABLE data type· 2-16,5-40 Area lock variables· 2-1, 2-16,5-40 See also AREA objects; Areas; Binary semaphores initializing • 5-40 using to lock and unlock areas· 5-40 AREA_LOCK_VARIABLE values· 2-16 Area name· 5-31 AREA objects • 2-4 See also Area lock variables; Areas creating • 4-16, 5-30 definition of· 2-4 deleting • 5-46 initializing state of synchronization object for • 5-31 operations on • 2-5 satisfying a wait on • 4-3 sharing data with • 5-28 to 5-46 signaling· 4-12, 5-33, 5-39 starting address of • 5-31 waiting on • 4-12, 5-33, 5-39 Areas See also AREA objects; Area lock variables creating· 4-11 initializing area lock variables for· 5-40 interjob communication using • 5-28 to 5-46 locking • 5-40 pointers in • 5-32 position-dependent • 5-32 position-independent • 5-32 2-lndex Areas (Cont.) synchronizing access to • 5-33 to 5-41 synchronizing access to with area lock variables • 5-40 synchronizing access to with events • 5-33 to 5-38 synchronizing access to with semaphores • 5-39 synchronizing job execution with· 5-41 example of· 5-42 to 5-46 unlocking· 5-40 Area size • 5-31 AREA values • 2-5 ARP (Address Resolution Protocol) See also ARP cache datagrams • 10-43 definition of· 10-5, 10-25 status information • 10-28 ARP cache • 10-5 See also ARP (Address Resolution Protocol) adding entries to· 10-26 deleting entries from • 10-26 entries, setting maximum number of • 10-23 entry characteristics· 10-29 managing • 10-25 to 10-30 retrieving entries from • 10-28 retrieving Ethernet addresses from • 10-27 Asynchronous exceptions· 7-4,7-11 disabling • 7-12 enabling· 7-12 KER$RAISE PROCESS EXCEPTION· 7-13 Asynchronous s;rial-line co~rollers • 14-134 AUTH_ADD_USER procedure ·12-8, 12-9 AUTH_MODIFY_USER procedure· 12-8, 12-11 Authorization data base· 12-4,12-7 adding users to· 12-9 modifying records in • 12-11 removing user records from • 12-13 returning information from ·12-14 Authorization procedures • 12-16 to 12-18 KER$GET_USER· 12-16 KER$SET_USER ·12-17 Authorization Service· 1-16, 12-3 to 12-15 Authorization Service utility procedures • 12-7 to 12-15 See also Authorization procedures ELN$AUTH_ADD_USER· 12-9 ELN$AUTH_MODIFY_USER ·12-11 Authorization Service utility procedures (Cont.) ELN$AUTH_REMOVE_USER 012-13 ELN$AUTH_SHOW_USER 012-14 AUTH_REMOVE_USER procedure -12-8, 12-13 AUTH_SHOW_USER procedure 012-8, 12-14 AXV11~ device -14-128,14-131 AXV device driver utility procedures -14-132 AXV_INITIALIZE procedure -14-132 AXV_READ procedure - 14-133 AXV_WRITE procedure - 14-133 B BDDRIVER disk driver - 14-1 Binary semaphores 04-11 See also Semaphores example of - 4-13 for controlling access to areas 0 5-30 optimizations of 04-14 bind function· 10-55 binding names to sockets with 0 10-58 BLNODE_MASK procedure· 6-13 BLSTOP procedure 06-14 Blocking sockets 010-60, 10-69, 10-73 Blocks of data reading from mounted disks • 14-15 to 14-20 reading from unmounted disks 014-12 to 14-14 BOOTP (Boot Protocol) 0 10-7 BOOTP servers • 10-7 Bootstrap loader, primary 09--36 Bootstrap ROM • 9--36 Broadcast addresses as Internet addresses· 10-9, 10-13 examples of 010-14 in Internet routing algorithm • 10-22 Broadcast masks for network interfaces 0 10-43 Internet address • 10-9 calculating • 10-14 default value of 010-13 definition of· 10-13 setting 0 10-24, 10-40 Broadcast messages, setting for sockets • 10-92 Buffered data path allocating 06-11 freeing • 6-12 Buffers Buffers (Cont.) command mapping for SCSI command request packets • 0-20 unmapping for SCSI command request packets· D-24 memory mapping· 6-12 unmapping - 6-13 SCSI command • 14-85 Byte order conversion functions • 10-53 converting· 10-53, 10-54 c Call frame • 7-2 calloe function 0 ~3 Call sequence, extracting· 7-3 Call stack See Stacks CANCEL_EXIT_HANDLER procedure 03-6 Carrier Sense Multiple Access/Collision Detect (CSMAlCD) LAN See CSMAlCD LAN Checksum values, Internet address • 10-5 Circuits·~11, ~16 characteristics of • 5-11, 9-5 connected to remote nodes • 9-2 connecting • ~17, 5-24 datalink· 9-9, 9-16 disconnecting. 5-19, ~26 flow control with • 5-17, ~22 for DDA disk interface • 14-8 for DDA serial-line interface· 14-41 for Down-Line Load Service· 9-20 for LAT communication· 11-4 in network applications 09-5 message segmentation with· ~17 programming· ~17 to ~21 programming considerations for • ~22 requesting multiple connections for • ~18 TCP ·10-7 used for I/O • 5-17 waiting for connections of· ~23 Class A Internet networks • 10-10 network masks for· 10-13 Index-3 Class A Internet networks (Cont.) when to use • 10-11 Class attached flag, SCSI device· 14-81, 14-112 Class B Internet networks • 10-1 0 network masks for· 1 0-13 when to use· 10-11 Class C Internet networks • 10-11 network masks for· 10-13 when to use· 10-12 Class drivers, SCSI· 14-111 associating with device types ·14-115 compiling and linking· 14-128 declaring • 14-115 defining device locks for • 14-119 device types for • 14-114 disk· 14-76 generic· 14-77 to 14-110 con necting to • 14-78 example • 14-91 to 14-11 0 message interface· 14-77 to 14-110 programming ·14-116 to 14-127 setting up entry point for • 14-120 starting • 14-116 user-defined ·14-110 to 14-128 Classes Internet network· 10-9 default network masks for· 1 0-13 number ranges for· 10-11 Classes, llC· 8-18,8-34 specifying • 8-35 CLEAR_EVENT procedure • 4-4, 5-28 as area event operation • 2-6 as EVENT object operation • 2-8 clearing EVENT objects with • 4-17 Clients • 10-3 See also Processes sample TCP • 10-88 to 10-91 sample UDP ·10-82 to 10-84 Client-server model • 10-3 close function • 10-55 closing sockets with • 10-76 Closely coupled symmetric multiprocessing. 1-11, 3-32 Ethernet node· 9-1 sharing memory areas during • 5-30 Command buffer, SCSI· 14-85 Command language commands See ECl commands 4-lndex Command language Utility • 1-7 as lAT host service· 11-2 Commands See DCl commands; ECl commands; NCP commands Common Command Set (CCS)· 14--89, 14-126 Commons, global· 5-2 Communication interjob· 1-15, 5-10 to 5--46 through areas • 5-28 to 5--46 through message passing • 5-10 to 5-28 Internet connectionless ·10-6, 10-17 connection-oriented • 10-7, 10-16 datagram-based • 10-6 half-duplex socket· 10-75 programming • 10-55 to 10-91 stream-based • 10-7 interprocess· 5-1, 5-1 to 5-9 through data sharing • 5-1 to 5--4 through queues • 5--4 to 5-9 LAT ·11-4 protocol • 5-15 with other operating systems • 9-44 Communication domain • 10-15 Communication region See Device communication region Communications environments See Datalink drivers; Ethernet/IEEE 802 Datagram Service; Internet Services; Network Service Communications ports Internet· 10-6, 10-14 privileged • 10-15 Concepts, VAXElN programming • 1-7 Concurrency· 1-7, 1-9 See also Concurrent programming scheduling for • 3-9 types of • 1-9 Concurrent processes See Concurrency; Concurrent programming Concurrent programming· 1-9, 4-1 multiprocessing in· 1-10 to 1-12 multiprogramming in· 1-10 multitasking in· 1-10 CONNECT_CIRCUIT procedure ·12-5 accessing lAT ports with ·11-35,11-41 CONNECT_CIRCUIT procedure (Cont.) as PORT object operation· 2-12 connecting to VMS with • 9-47 connect to a port with· 5-24 controlling message flow with· 5-17 creating logical links with • 9-2 establishing circuits for authorization with • 12-16 establishing circuits with· 5-17 establishing network node connections with • 9-3 named ports used with • 5-14 setting up DDCMP communication with • 14-38 specifying DECnet object numbers with • 9-49 connect function • 10-55 initiating socket connections with • 10-62 Connection data, retrieving TCp· 10-48 Connection options, TCP· 10-48 Connection requests DECnet, stopping· 9-14 LAT· 11-25 socket • 10-84 Connections socket accepting • 10-65 closing • 10-76 establishing • 10-8, 10-82 to 10-66 initiating • 10-82 requirements of • 10-17 shutting down • 10-75 state of· 10-49 VAXELN accepting on VMS systems • 9-48 requesting from VMS systems • 9-48 VMS accepting on VAXELN systems· 9-48 requesting from VAXELN systems· 9-47 Connection state, TCP· 10-48 Constants, shared • 5-2 Control characters • 14-82 Controllers Ethernet See Ethernet controllers SCSI device • 14-74 initializing • 14-127 Control messages, Internet protocol for returning • 10-5 Control ports • 14-78 Down-Line Load Service • 9-20 Control region • 3-26 Control sequences, ANSI • 14-85 COPY_FILE procedure ·13-11 Counting semaphores • 4-12 See also Semaphores example of • 4-12 for controlling access to areas • 5-30 CREATE_AREA_EVENT procedure • 4-4, 5-28 as area event operation • 2-5 creating area events with • 4-16 creating AREA objects with· 5-30 CREATE_AREA procedure • 4-4, 5-28 as AREA object operation • 2-5 creating AREA objects with • 5-30 creating area semaphores with • 4-11 CREATE-AREA_SEMAPHORE procedure • 4-4, 5-29 as area semaphore operation • 2-5 creating AREA objects with • 5-30 creating area semaphores with· 4-11 CREATE_DEVICE procedure as DEVICE object operation • 2-7 creating DEVICE objects with • 6-3 specifying a power-failure recovery routine with • 6-17 CREATE_DI RECTORY procedure • 13-12 CREATE_EVENT procedure • 4-4 as EVENT object operation· 2-7 creating EVENT objects with • 4-16 CREATE JOB command· 3-3 activating Down-Line Load Service with· 9-18 CREATE_JOB procedure· 3-15 activating Down-Line Load Service with • 9-18 creating jobs with • 3-1 , 3-3 CREATE_MESSAGE procedure as MESSAGE object operation· 2-8 creating MESSAGE objects with· 5-11,5-25 setting up message communication with· 5-14 CREATE_MUTEX procedure • 4-4 as mutex operation • 2-18 creating mutexes with • 4-14 CREATE_NAME procedure as NAME object operation· 2-10 creating NAME objects with· 5-13,5-25 creating universal port names with • 9-5 CREATE_PORT procedure as PORT object operation· 2-11 creating PORT objects with· 5-12,5-25 Index-5 CREATE_PROCESS procedure· 3-15,4-4 as PROCESS object operation • 2-13 creating processes with· 3-2 terminating subprocesses with • 3-5 using exit parameter with • 4-10 CREATE_SEMAPHORE procedure· 4-4 as SEMAPHORE object operation· 2-14 creating SEMAPHORE objects with· 4-11 Credit values· 10-34 C runtime library message files· 7-16,7-17,7-23 CSMAlCD LAN • 8-4 getting configuration of· 8-7,8-36 Current connection flag, SCSI device ·14-81,14-112 setting • 14-121 CURRENT_PROCESS procedure· 3-16,4-5 as PROCESS object operation· 2-13 D DAP (data acc.ess protocol) • 13-21, 14-3 action routines· 13-19, 13-20 to 13-26 constants· 13-26 data types • 13-26 general principles • 13-24 in communication tasks • 9-3 message transmission example· 13-21 port for LAT port· 11-8 wildcard functions • 13-27 DAP$SERVER function· 13-23 to 13-26, 13-27 Data access protocol (DAP) See DAP (data access protocol) Data base down-line load • 9-18 clearing node information from • 9-22, 9-29 line characteristics • 9-28 managing and monitoring line entries in • 9-28 managing and monitoring node entries in • 9-21 node characteristics· 9-21 overriding information in· 9-38, 9-41 returning node information from • 9-22, 9-24, 9-29,9-30 setting line information in • 9-29 setting node information in • 9-22 Internet address ·10-6,10-7 VMS network node· 9-9 6-lndex Data buffers mapping • 0-20 unmapping • 0-24 Data flow interprocess, Internet· 10-3 message controlling • 5-17, 5-27 controlling with circuits • 5-22 controlling with unconnected ports • 5-21 Datagram fragments • 10-23 Datagram protocol type • 10-16 Datagrams· 5-10,5-16 ARP ·10-43 characteristics of • 5-10, 9-5 fragmentation of • 10-5 ICMP ·10-43 in DECnet network applications - 9-5 Ip· 10-5, 10-43 maximum size of • 9-5, 10-23 multicasting to LAN nodes· 9-17 sending to remote ports • 9-5 trailer • 10-43 UDP ·10-6 Datagram Service See Ethernet/IEEE 802 Datagram Service Datagram sockets -10-16 Datalink circuits - 9-9, 9-16 Datalink drivers - 9-3 as Internet layer • 10-4 building into VAXELN systems • 8-2, 10-23 clOSing connections to - 9-16 establishing connections with • 9-16 interface with Network Service· 9-1 table of • 8-2 Data path, buffered allocating· 6-11 freeing· 6-12 Data sharing • 5-1 See also Communication; Synchronization interjob • 5-28 to 5-46 interprocess· 5-1 to 5-9 Data structures, realtime· 2-1 Data transfers using DDA disk interface· 14-7 to 14-24 using DDA serial-line interface • 14-48 using sockets for • 10-66 to 10-75 Data types Data types (Cont.) AREA_LOCK_VARIABLE· 2-16,5-40 MUTEX· 2-17 system· 2-2 DCL commands SET HOST • 9-49 SHOW NETWORK ·9-45, 9-46, 9-47 DDA (direct device access) • 9-3 for disk devices· 14-7 to 14-24 reading and writing data with • 14-9 reading data from mounted disks with • 14-15 to 14-20 reading data from unmounted disks with • 14-12 to 14-14 transferring data to system regions with • 14-20 to 14-24 for serial-line devices • 14-39 to 14-62 reading and writing data with· 14-48 DDA port connecting to for disk read and write DDA operations • 14-8 connecting to for LAT operations • 11-9 connecting to for serial-line DDA operations· 14-41 for LAT port· 11-8, 11-35 DDCMP communication • 14-36 DDDRIVER disk driver· 14-2 Deadlock prevention • 4-4 DEALLOCATE_STACK procedure • 3-28 Debugger· 1-7 creating jobs with • 3-3 including in KA800 systems· 3-32 loading jobs with • 3-3 Debugger commands CREATE JOB • 3-3 activating Down-Line Load Service with· 9-18 LOAD PROGRAM· 3-3 DECLARE_EXIT_HANDLER procedure • 3-6 DECnet addresses· 8-11 . in down-line load data base • 9-21 name server, display 0 9-6 DECnet networks ~1' See also DECnet nodes; DECnet software; Network Service circuit connections in 09-47 expedited messages for use in • 5-15 node identification in 0 9-45 0 DECnet Network Service See Network Service DECnet nodes addresses of, initializing at runtime· 9-13 identifiers for 0 9-22 modifying state of 9-11 multicasting datagrams to 09-17 remote, connecting to· 9-49 specifying· 9-45 stopping and starting DECnet software on· 9-14 VAXELN, managing from VMS systems 0 9-9 DECnet object numbers • 9-49 DECnet software connection requests, stopping 0 9-14 end-node routing announcement messages, stopping • 9-14 periodic network timer, stopping· 9-14 shutting down 0 9-14 starting for first time 09-12 stopping 0 9-12 stopping and starting • 9-11, 9-14 switching between Ethernet controllers • 9-16 universal name service operations, stopping • 0 9-14 DECwindows software message files 07-17,7-23 runtime libraries· 1-17 runtime library message files· 7-16 server 01-6 server image 0 1-17 support· 1-17 terminal emulators 01-17 user-environment components 0 1-7 Window Manager • 1-17 Dedicated applications 01-1 Dedicated LAT host services See LAT (local area transport) Dedicated LAT port· 11-7, 11-34 See also LAT (local area transport) DELETE_FILE procedure· 13-12 DELETE_MUTEX procedure 0 4-5 as mutex operation 0 2-18 deleting mutexes with, 4-15 DELETE procedure • 4-5, 5-29 as AREA object operation • 2-6 as DEVICE object operation 0 2-7 as EVENT object operation· 2-8 Index-7 DELETE procedure (Cont.) as MESSAGE object operation' 2-9 as NAM E object operation • 2-10 as PORT object operation' 2-12 as PROCESS object operation' 2-13 as SEMAPHORE object operation • 2-14 deleting AREA objects with • 5-46 deleting DEVICE objects with • 6-5 deleting EVENT objects with' 4-18 deleting kernel objects with • 2-2 deleting MESSAGE objects with, 5-26 deleting NAME objects with· 5-13,5-26 deleting PORT objects with • 5-12, 5-26 deleting PROCESS objects with· 3-16 deleting SEMAPHORE objects with, 4-14 deleting universal port names with • 9-5 terminating jobs with • 3-4 terminating processes with, 3-5 Destination authorization • 12-5, 12-18 Destination Internet addresses extracting from routing table entries • 10-37 in Internet routing algorithm • 10-22 Device communication region • 2-6, 6-2 synchronizing access to • 6-6 Device Description Menu • 8-2 Device drivers • 1-6, 6-1, 14-1 allocating buffered data paths for • 6-11 allocating map registers for • 6-10 controlling DMA devices with • 6-10 creating DEVICE objects for • 6-3 File Service interface for· 13-19 freeing buffered data paths for • 6-11 freeing map registers for • 6-10 LAT· 11-3 mapping memory buffers for • 6-12 mass storage • 14-1 to 14-27 parallel 1/0 support for· 14-73 printer' 14-29 to 14-32 reading and writing data with • 6-9 realtime ·14-128 to 14-152 serial-line ·14-32 to 14-73 setting priorities for· 6-7 setting processor eligibility in' 6-8 synchronizing access to communication region in· 6-6 tape· 14-27 to 14-29 unmapping memory buffers for· 6-12 Virtual-memory • 14-24 8-lndex Device drivers (Cont.) waiting on ISR in • 6-5 writing • 6-1 Device handling· 6-1 Device interrupts· 6-2, 13-25 disabling· 6-7,6-8 enabling • 6-8 handling • 6-5 waiting for an ISR to service' 6-5 Device locks, SCSI· 14-119 Device markers, SCSI· 14-113, 14-120 DEVICE objects • 2-6, 6-2 creating • 6-3 definition of • 2-4 deleting • 6-5 operations on • 2-6 satisfying a wait on' 4-3 signaling • 6-5 waiting for • 6-5 Device register routines • 6-9 Device registers • 6-9 using for interprocess data sharing • 5-4 Devices disk· 14-1 handling interrupts for· 6-1 interrupt priority of· 6-7 LAT application' 11-2 accessing • 11-36 associating with application LAT ports • 11-41 environment of (figure) • 11-37 example ·11-38 to 11-40 printer • 14-29 realtime • 14-128 SCSI· 14-73 tape· 14-27 terminal • 14-32 DEVICE values • 2-6 DIDRIVER disk driver· 14-2 Direct device access (DDA) • 9-3 See DDA (direct device access) DIRECTORY_CLOSE procedure· 13-13 DIRECTORY_LIST procedure '13-13 DIRECTORY_OPEN procedure '13-13 DISABLE-ASYNCH_EXCEPTION procedure • 7-12 DISABLE_INTERRUPT procedure • 6-7 DISABLE_SWITCH procedure' 3-11,3-16 DISCONNECT_CIRCUIT procedure switching DECnet software between controllers with· 9-16 DISCONNECT_CIRCUIT procedure as PORT object operation· 2-12 disconnecting circuits with • 5-19, 5-26 disconnecting network node connections with· 9-3 disconnecting VMS connections with· 9-48 terminating DDCMP communication with • 14-38 Disk class driver, SCSI • 14-73, 14-76 Disk data, transferring to system regions· 14-20 to 14-24 Disk devices • 14-3 local, reading data from· 14-7, 14-9 local, writing data to· 14-7, 14-9 Disk drivers • 14-1 as interface to File Service· 14-6 DDA interface for -14-7 to 14-24 reading and writing data with • 14-9 reading data from mounted disks with 14-15 to 14-20 reading data from unmounted disks with • 14-12 to 14-14 transferring data to system regions with • 14-20 to 14-24 disk specifications for - 14-3 features of • 14-6 power-failure recovery of· 14-7 Disk File Service - 1-16, 13-1 using to interface with disk drivers • 13-19 utility procedures provided by· 13-15 Disk utility procedures - 13-15 to 13-17 ELN$DISMOUNT_VOLUME ·13-16 ELN$INIT_VOLUME -12-20,13-16 ELN$MOUNT_VOLUME-13-4,13-17 Disk volumes dismounting· 13-16 initializing· 13-16 mounting· 13-17 DISMOUNT_TAPE_VOLUME procedure ·13-18 DISMOUNT_VOLUME procedure - 13-16 Dispatch ports - 8-13,8-15 creating • 8-34, 8-35 disconnecting - 8-36 establishing • 8-34, 8-36 waiting on • 8-36 Display Utility • 1-7 Distributed applications, universal port names for • 9-6 DLV device driver utility procedures· 14-135 DLV_INITIALIZE procedure - 14-136 DLVJ1 device· 14-128, 14-134 DLV_READ_BLOCK procedure -14-136 DLV_READ_STRING procedure ·14-136 DLV_WRITE_STRING procedure· 14-136 DMA (direct memory access) devices • 6-10, 14-129 DRB32· 14-136 DR03B· 14-140 DRV11-W· 14-144 DMA device-handling procedures· 6-10 ELN$LOAD_UNIBUS_MAP • 6-10 ELN$UNIBUS_MAP • 6-12 ELN$UNIBUS_UNMAp· 6-13 KER$ALLOCATE_MAP· 6-10 KER$ALLOCATE_PATH - 6-11 KER$FREE_MAP· 6-11 KER$FREE_PATH • 6-12 DMA parallel-line interface DRB32· 14-136 DR03B - 14-140 DRV11-W· 14-144 Down-line load data base - 9-18 clearing node information from • 9-22, 9-29 combining entries in • 9-24 line characteristics· 9-28 managing and monitoring line entries in· 9-28 example of • 9-31 to 9-34 , managing and monitoring' node entries in • 9-21 example of • 9-24 to ~28 node characteristics· 9-21 overriding information in • 9-38, 9-41 returning node information from - 9-22, ~24, ~29,~30 script file • 9-18 setting line information in • ~29 setting node information in· 9-22 Down-line loading· ~18, 9-40 to 9-44 enabling • 9-44 example of • 9-42 Down-line load procedures • ~19 combining data base entries with • 9-24 connecting to control port for· 9-20 ELN$DLL_CLEAR_LlNE· 9-19 Index-9 Down-line load procedures ELN$DLL_CLEAR_LlNE (Cont.) clearing data base line entries with • 9--29 ELN$DLL_CLEAR_NODE 0 9--19 clearing data base node entries with 0 9--22 ELN$DLL_GET_LlNE 09--19 getting data base line information with 0 9-29,9--30 ELN$DLL_GET_NODE 0 9--19 getting data base node information with 0 9-22,9--24 ELN$DLL_LOAD 0 9--19 down-line loading with 0 9--41 ELN$DLL_SET_LlNE 0 9--19 setting data base line entries with 0 9--29 ELN$DLL_SET_NODE 09--19 setting data base node entries with 0 9--22 ELN$DLL_TRIGGER • 9--19 trigger booting with • 9--36, 9--37 mask values for 0 9--23 modules for using 0 9--19 Down-line load requests 0 9--40 figure of 09--40 overriding with trigger request 0 9--41 Down-Line Load Service 0 9-8, 9--18 to 9-44 See also Down-line load procedures application-initiated load requests· 9--35 building into VAXELN systems 09--18 control port 0 9--20 data base script file for 09--18 data bases for· 9--18 down-line loading with • 9--40 to 9--44 example of 0 9--42 establishing circuits for 0 9--20 managing and monitoring line entries with • 9--28 example of 0 9--31 to 9--34 managing and monitoring node entries with 0 9--21 example of 0 9--24 to 9--28 managing target-initiated down-line load requests • 9--35 trigger booting with· 9--36 to 9--40 example of • 9--38 DQDRIVER disk driver ·14-2 DRB32 device 014-129, 14-136 DRB device driver utility procedures 014-138 DRB_FINISHED_TRANSFER procedure 014-138 DRB_INITIALIZE procedure ·14-138 10-Index DRB_QUEUE_READ procedure 014-138 DRB_QUEUE_WRITE procedure 0 14-139 DRB_READ_CTRL procedure 014-139 DRB_WRITE_CTRL procedure· 14-139 Drive context pointer 0 13-20 Drivers See Device drivers Driver utility functions 014-148 to 14-150 DRQ3B device 014-129, 14-140 DRQ3B device driver utility procedures 014-141 DRQ3B_INITIALIZE procedure 0 14-141 DRQ3B_QUEUE_READ procedure 014-141 DRQ3B_QUEUE_WRITE procedure 014-141 DRQ3B_READ_FUNCTION procedure 014-141 DRQ3B_TRANSFER_DONE_READ procedure· 14-141 DRQ3B_TRANSFER_DONE_WRITE procedure 0 14-141 DRQ3B_WRITE_FUNCTION procedure· 14-141 DRV device driver utility procedures· 14-143 DRV_DMA device driver utility procedures· 14-144 DRV_DMA_INITIALIZE procedure 0 14-145 DRV_DMA_QUEUE_READ procedure 014-145 DRV_DMA_QUEUE_WRITE procedure 0 14-145 DRV_DMA_READ_STATUS procedure 014-145 DRV_DMA_TRANS FER_DON E procedure 0 14-145 DRV_DMA_WRITE_FUNCTION procedure 014-145 DRV_INITIALIZE procedure 014-143 DRV11-J device· 14-129, 14-142 DRV_READ procedure 014-143 DRV11-W device 014-129, 14-144 DRV_WRITE procedure 014-143 DUDRIVER disk driver 014-2 DVSDRIVER disk driver • 14-2 Dynamic memory management 0 3-26 Dynamic program loader 03-13 E ECL commands EXECUTE 0 3-3 activating Down-Line Load Service with· 9--18 LOAD/PROGRAM 03-3 RUN 03-3 activating Down-Line Load Service with 0 9--18 ECL commands (Cont.) SET HOST • 9-49 SHOW DEVICES • 9-29 SHOW NAME_SERVER • 9-6 ECL utility· 1-7 as LAT host service· 11-2 displaying current name server with • 9-6 EDISPLAY utility· 1-7 ELN$ADQ_INITIALIZE procedure· 14-131 ELN$ADQ_QUEUE_READ procedure ·14-131 ELN$ADQ_START procedure· 14-131 ELN$ADQ_TRANSFER_DONE procedure· 14-131 ELN$ADV_INITIALIZE procedure ·14-134 ELN$ADV_QUEUE_READ procedure • 14-134 ELN$ADV_TRANSFER_DONE procedure· 14-134 ELN$ALLOCATE_STACK procedure • 3-28 ELN$AUTH_ADD_USER procedure ·12-8, 12-9 ELN$AUTH_MODIFY_USER procedure· 12-8, 12-11 ELN$AUTH_REMOVE_USER procedure ·12-8, 12-13 ELN$AUTH_SHOW_USER procedure • 12-8, 12-14 ELN$AXV_INITIALIZE procedure ·14-132 ELN$AXV_READ procedure ·14-133 ELN$AXV_WRITE procedure· 14-133 ELN$BLNODE_MASK procedure· 6-13 ELN$BLSTOP procedure· 6-14 ELN$CANCEL_EXIT_HANDLER procedure • 3-6 ELN$COPY_FILE procedure • 13-11 ELN$CREATE_DIRECTORY procedure· 13-12 ELN$CREATE_MUTEX procedure • 4-4 as mutex operation· 2-18 creating mutexes with • 4-14 ELN$DEALLOCATE_STACK procedure· 3-28 ELN$DECLARE_EXIT_HAN DLER procedure • 3-6 ELN$DELETE_FILE procedure· 13-12 ELN$DELETE_MUTEX procedure • 4-5 as mutex operation • 2-18 deleting mutexes with • 4-15 ELN$DIRECTORY_CLOSE procedure • 13-13 ELN$DIRECTORY_LlST procedure ·13-13 ELN$DIRECTORY_OPEN procedure· 13-13 ELN$DISK_READ procedure ·14-7 reading data from local disks with • 14-9 ELN$DISK_WRITE procedure ·14-7 writing data to local disks with • 14-9 ELN$DISMOUNT_ TAPE_VOLUME procedure· 13-18 ELN$DISMOUNT_VOLUME procedure· 13-16 ELN$DLL_CLEAR_LlNE procedure· 9-19 clearing data base line entries with • 9-29 ELN$DLL_CLEAR_NODE procedure· 9-19 clearing data base node entries with • 9-22 ELN$DLL_GET_LINE procedure • 9-19 getting data base line information with· 9-29, 9-30 ELN$DLL_GET_NODE procedure· 9-19 getting data base node information with· 9-22, 9-24 ELN$DLL_LOAD procedure· 9-19 down-line loading with • 9-41 ELN$DLL_SET_LINE procedure· 9-19 setting data base line entries with • 9-29 ELN$DLL_SET_NODE procedure • 9-19 setting data base node entries with • 9-22 ELN$DLL_TRIGG ER procedure • 9-19 trigger booting with • 9-36, 9-37 ELN$DLV_INITIALIZE procedure· 14-136 ELN$DLV_READ_BLOCK procedure ·14-136 ELN$DLV_READ_STRING procedure • 14-136 ELN$DLV_WRITE_STRING procedure· 14-136 ELN$DRB_FINISHED_TRANSFER procedure· 14-138 ELN$DRB_INITIALIZE procedure· 14-138 ELN$DRB_QUEUE_READ procedure ·14-138 ELN$DRB_QUEUE_WRITE procedure· 14-139 ELN$DRB_READ_CTRL procedure· 14-139 ELN$DRB_WRITE_CTRL procedure· 14-139 ELN$DRQ3B_INITIALIZE procedure· 14-141 ELN$DRQ3B_QUEUE_READ procedure ·14-141 ELN$DRQ3B_QUEUE_WRITE procedure ·14-141 ELN$DRQ3B_READ_FUNCTION procedure ·14-141 ELN$DRQ3B_TRANSFER_DONE_READ procedure • 14-141 ELN$DRQ3B_TRANSFER_DONE_WRITE procedure ·14-141 ELN$DRQ3B_WRITE_FUNCTION procedure • 14-141 ELN$DRV_DMA_INITIALIZE procedure· 14-145 ELN$DRV_DMA_QUEUE_READ procedure· 14-145 ELN$DRV_DMA_QUEUE_WRITE procedure· 14-145 ELN$DRV_DMA_READ_STATUS procedure· 14-145 Index-11 ELN$DRV_DMA_TRANSFER_DONE procedure • 14-145 ELN$DRV_DMA_WRITE_FUNCTION procedure· 14-145 ELN$DRV_INITIALIZE procedure ·14-143 ELN$DRV_READ procedure - 14-143 ELN$DRV_WRITE procedure - 14-143 ELN$FILE_INITIALIZE function - 13-19, 13-20 ELN$FILE_SERVICE procedure - 13-19 ELN$GET_STATUS_TEXT procedure - 7-15,7-21 ELN$GP_AUXILIARY_COMMAND function -14-148 ELN$GP_CLEAR_EVENT function - 14-148 ELN$GP_CONFIGURE function -14-148 ELN$GP_DEFINE_PATH function -14-148 ELN$GP_GET_CONTROL function -14-148 ELN$GP_GOTO_STANDBY function - 14-148 ELN$GP_INITIALIZE function· 14-148 ELN$GP_LOAD_PARALLEL_POLL function -14-148 ELN$GP_PARALLEL_POLL_CONFIG function14-150 ELN$GP_PARALLEL_POLL function -14-150 ELN$GP_PASS_CONTROL function - 14-150 ELN$GP_RECEIVE_CONTROL function - 14-150 ELN$GP_REQUEST_SERVICE function -14-150 ELN$GP_SEND_COMMAND function -14-150 ELN$GP_SENSE_MODE function - 14-150 ELN$GP_SERIAL_POLL function -14-150 ELN$GP_SET_EVENT function - 14-150 ELN$GP_TRANSFER function -14-150 ELN$GP_UNIT_INIT function - 14-150 ELN$INET_CHECK_ROUTE procedure - 10-31 checking status of routing table entries with10-34 ELN$INET_DELETE_ARP_ENTRY procedure10-25 deleting ARP cache entries with - 10-26 ELN$INET_DELETE_ROUTE procedure - 10-31 deleting routing table entries with - 10-31 ELN$INET_FIND_ARP_ENTRY procedure - 10-25 retrieving Ethernet addresses with - 10-27 ELN$INET_SET-ARP_ENTRY procedure -10-25 adding entries to ARP cache with - 10-26 ELN$INET_SET_INTERFACE procedure -10-40 setting network interfaces with - 1~O ELN$INET_SET_ROUTE procedure - 10-31 adding entries to routing table with - 10-31 12-lndex ELN$INET_SHOW_ARP_ENTRIES procedure10-25 retrieving ARP entries with - 10-28 ELN$INET_SHOW_CONNECTIONS procedure retrieving TCP connection data with - 1~8 ELN$INET_SHOW_INTERFACE procedure -1~0 retrieving network interface characteristics with 10-42 ELN$INET_SHOW_IP_STATISTICS procedure10-44 retrieving IP statistics with - 10-46 ELN$INET_SHOW_ROUTES procedure -10-31 retrieving routing table entries with • 10-37 ELN$INET_SHOW_TCP_STATISTICS procedure 10-44 retrieving TCP statistics with - 1~6 ELN$INET_SHOW_UDP_STATISTICS procedure10-44 retrieving IP statistics with - 10-46 ELN$INITIALlZE_AREA_LOCK procedure - 5-29 as area lock variable operation - 2-17 initializing area lock variables with - 5-40 ELN$INIT_ TAPE_VOLUME procedure - 13-18 ELN$INIT_VOLUME procedure -12-20,13-16 ELN$KWV_INITIALIZE procedure -14-151 ELN$KWV_READ procedure - 14-151 ELN$KWV_WRITE procedure-14-151 ELN$LAT_CLEAR_COUNTERS procedure -11-6 initializing LAT counters with - 11-28 ELN$LAT_CONNECT_PORT procedure-11-11 connecting LAT port to device port with - 11-42 ELN$LAT_CREATE_PORT procedure -11-6 creating application LAT ports with - 11-40 creating dedicated LAT ports with - 11-34 creating LAT ports with - 11-8 ELN$LAT_CREATE_SERVICE procedure - 11-6 creating services with - 11-17, 11-34 ELN$LAT_DELETE_PORT procedure - 11-6 ELN$LAT_DELETE_SERVICE procedure-11-6 deleting services with - 11-17 ELN$LAT_DISCONNECT_PORT procedure-11-11 disconnecting LAT connection with - 11-36, 11-42 ELN$LAT_MAP_PORT procedure-11-11 associating application LAT port with - 11-41 mapping dedicated LAT port with - 11-34 ELN$LAT_SET_NODE procedure - 11-6 setting service node characteristics with· 11-14 ELN$LAT_SET_NODE procedure (Cont.) specifying shut-down message with • 11-22 ELN$LAT_SET_PORT procedure· 11-6 associating application LAT port with· 11-41 setting dedicated LAT port with· 11-34 ELN$LAT_SET_SERVICE procedure· 11-6 changing service characteristics with· 11-20 ELN$LAT_SHOW_CHAR procedure ·11-6 retrieving service node characteristics with • 11-13 ELN$LAT_SHOW_COUNTERS procedure· 11-6 retrieving LAT counters with ·11-28 ELN$LAT_SHOW_PORT_MAPPING procedure· 11-11 ELN$LAT_SHOW_PORT procedure ·11-6 retrieving LAT port characteristics with • 11-23 ELN$LAT_SHOW_SERVERS procedure· 11-7 retrieving terminal server characteristics with • 11-26 ELN$LAT_START_NODE procedure ·11-7 activating LAT protocol with ·11-21, 11-35, 11-41 ELN$LAT_STOP_NODE procedure ·11-7 shutting down LAT protocol with • 11-22 ELN$LAT_WAIT_FOR_CONN ECTION procedure· 11-11 requesting LAT connection notification with • 11-35 ELN$LOAD_KA800_PROCESSOR procedure· 3-32 ELN$LOAD_PROGRAM procedure· 3-13 loading program images with • 3-3 ELN$LOAD_UNIBUS_MAP procedure· 6-10 ELN$LOCK_AREA procedure • 5-29 as area lock variable operation • 2-17 locking areas with • 5-40 ELN$LOCK_MUTEX procedure • 4-5 as mutex operation • 2-18 locking mutexes with· 4-14 ELN$MOUNT_TAPE_VOLUME procedure· 13-4, 13-18 ELN$MOUNT_VOLUME procedure· 13-4, 13-17 ELN$NETMAN_START_NETWORK procedure· 9-11 initializing node addresses with· 9-13 stopping and starting DECnet software with· 9-14 switching DECnet software between controllers with· 9-16 ELN$NETMAN_STOP_NETWORK procedure· 9-11 stopping and starting DECnet software with· 9-14 switching DECnet software between controllers with· 9-16 ELN$NLALLOCATE_BUFFER procedure· 8-6,8-34 allocating message buffers with • 8-20 ELN$NLCONNECT procedure • 8-0, 8-34, 8-36 connecting Ethernet/IEEE 802 protocols with· 8-12 ELN$NLDISCONNECT procedure • 8-6, 8-35 disconnecting Ethernet/IEEE 802 protocols with· 8-13 ELN$NLGET_ATTRIBUTES procedure· 8-0 retrieving Ethernet controller attributes with • 8-10 ELN$NLGET_CONFIGURATION procedure· 8-6 getting line names with • 9-29 retrieving CSMAlCD LAN configuration with· 8-7 ELN$NLRECEIVE procedure • 8-6, 8-36 receiving messages with • 8-25 ELN$NLTRANSMIT procedure· 8-6,8-35 transmitting messages with • 8-21 ELN$NLTRANSMIT_STATUS procedure· 8-6,8-35 retrieving transmitted messages with • 8-23 ELN$PHYSICAL_ADDRESS function· 6-13 ELN$P ROTECT_FILE procedure • 13-14 ELN$RENAME_FILE procedure ·13-15 ELN$SCSLCONNECT_DEVICE procedure ·14-77 connecting to SCSI devices with • 14-83 ELN$SCSLDISCONNECT_DEVICE procedure· 14-77 disconnecting SCSI device processes with· 14-84 ELN$SCSLFREE_CONFIG_DATA procedure • 14-77 freeing configuration data resources with • 14-82 ELN$SCSLFREE_CONTROL_PORT procedure· 14-77 freeing source port resources with • 14-79 ELN$SCSLGET_CONFIG_DATA procedure· 14-77 requesting SCSI bus configuration data with • 14-80 ELN$SCSLGET_CONTROL_PORTS procedure· 14-77 connecting to generic class driver with ·14-78 ELN$SCSUSSUE_COMMAND procedure· 14-77 issuing SCSI commands with ·14-85 ELN$SCSLMAP_MESSAGE_BUFFER procedure • 14-77 creating SCSI command message buffer with • 14-85 ELN$SCSLUNMAP_MESSAGE_BUFFER procedure ·14-77 Index-13 ELN$SCSLUNMAP_MESSAGE_BUFFER procedure (Cont.) deleting SCSI command message buffer with • 14-89 ELN$SET_DEFAULT_FILESPEC procedure· 13-15 ELN$TAPE_INITIALIZE function· 13-19, 13-20 ELN$TAPE_SERVICE procedure ·13-20 ELN$ITY_ASSERT_BREAK procedure ·14-40 setting serial lines to spacing state with • 14-57 ELN$TTY_CANCEL_MODEM_EVENTS procedure • 14-40 canceling requests for modem events with ·14~9 ELN$ITY_CANCEL_OOB_CHARACTERS procedure· 14-40 canceling out-of-band character requests with· 14-59 ELN$ITY_GET_CHARACTERISTICS procedure· 14-40 getting terminal characteristics with • 11-13, 11-43 retrieving modem characteristics with • 14~8 retrieving serial-line characteristics with· 14-47 ELN$ITY_READ procedure· 14-40 reading serial-line data with • 14-48 ELN$ITY_RECEIVE_MODEM_EVENTS procedure • 14-40 receiving modem events with· 14~9 ELN$ITY_RECEIVE_OOB_CHARACTER procedure • 14-40 receiving out-of-band characters with • 14-59 ELN$ITY_SET_CHARACTERISTICS procedure· 14-40 setting modem characteristics with • 14-68 setting serial-line characteristics with· 14-47 setting terminal characteristics with • 11-43 ELN$ITY_SIGNAL_MODEM_EVENTS procedure • 14-40 signaling modem events with ·14~9 ELN$ITY_SIGNAL_OOB_CHARACTERS procedure ·14-40 signaling receipt of out-of-band characters with • 14-59 ELN$ITY_WRITE procedure ·14-40 writing serial-line data with· 14-48 ELN$UNIBUS_MAP procedure • 6-12 ELN$UNIBUS_UNMAP procedure· 6-13 ELN$UNLOAD_PROGRAM procedure· 3-13 ELN$UNLOCK_AREA procedure • ~29 as area lock variable operation • 2-17 14-lndex ELN$UNLOCK_AREA procedure (Cont.) unlocking areas with· 5-40 ELN$UNLOCK_MUTEX procedure • 4-5 as mutex operation • 2-18 unlocking mutexes with • 4-15 Emulation routines, VMS See VMS emulation routines ENABLE_ASYNCH_EXCEPTION procedure. 7-12 ENABLE_INTERRUPT procedure • 6-7 ENABLE_SWITCH procedure· 3-11,3-17 End-node routing • 9-2 announcement messages, stopping· 9-14 ENTER_KERNEL_CONTEXT procedure • 6-14 Error checking· 7-19 Error counters See LAT (local area transport) Error Logging Service ·1-6 Error messages, Internet protocol for returning • 10-5 Errors checking for and handling· 7-14 Internet, retrieving • 10-44 network interface • 10-43 Error status codes· 7-14 Escape sequences ·14~4 VT52-type ·14~6 ESDRIVER datalink driver • 8-2 system region size for· 8-3 ETDRIVER datal ink driver • 8-2 Ethernet/IEEE 802 Datagram Service· 1~, 8-1,8-4 See also Network interface procedures setting up • 8-27 when DECnet operations stop • 9-12 Ethernet/IEEE 802 Datalink Drivers See Datalink drivers Ethernet/IEEE 802 protocols connecting and disconnecting· 8-12 padded • 8-19 that multicasts datagrams to LAN nodes· 9-17 Ethernet addresses· 8-11 broad casted by name server· 9-7 broadcasting ·10~, 10-7 destination node • 9-4 displaying name server • 9-6 extracting from ARP cache • 10-28 for network interfaces • 10-43 mapping Internet addresses to • 10-26 protocol for mapping Internet addresses to • 10-5 Ethernet addresses (Cont.) retrieving from ARP cache • 10-27 specified for down-line load operations • 9-40 specified for trigger boot operations • 9-37 Ethernet controllers See also Line names configuring for Internet Services • 10-23 control ports for- 8-9,8-12 data ports for • 8-9 device names of • 8-9 device types of • 8-8 getting attributes of· 8-10, 8-33 hardware address of • 8-12 identifying with line names • 9-11 Internet characteristics of, setting • 10-24 physical address of· 8-11 switching DECnet software between· 9-16 using muttiple· 8-1 Ethernet formatted frames • 8-15 EVENT objects· 2-7,4-15,4-16 See also Events creating • 4-16 definition of • 2-4 deleting • 4-18 operations on • 2-7 satisfying a wait on • 4-3 using to synchronize access to areas· 5-33 waiting on • 4-16 Event response • 4-1 Events· 4-15 to 4-18 See also EVENT objects associated with AREA objects· 5-31 example of· 4-17 for controlling access to areas • 5-30 synchronizing job execution with • 5-41 EVENT values • 2-7 Exception handlers • 7-5 arguments for • 7-5 continue operation of· 7-7 example of· 7-9 mechanism argument block in • 7~ resignal operation of • 7-7 signal argument block in - 7~ unwind operation of - 7-8 Exception handling· 7-1 Exception-handling procedures· 7-12 Exceptions • 7-4 Exceptions (Cont.) asynchronous· 7-11 disabling· 7-12 enabling· 7-12 raising process· 7-13 job termination - 3-4 kernel procedure failure· 7-11 multiple concurrent· 7-11 names of· A-1 QUIT· 3-5 raising· 3-19, 7-11,7-13 EXECUTE command • 3--3 activating Down-Line Load Service with· 9-18 Exit handlers· 3-6 EXIT procedure· 3-17 as PROCESS object operation· 2-13 terminating jobs with· 3-4 Exit status, using· 4-10 Exit utility procedures • 3-6 Expedited messages· 5-15 extern attribute • 5-2 EZDRIVER datalink driver - 8-2 F FAL (file access listener)· 13-9 Fatal status codes· 7-14 File access ·1-16 File access listener (FAL) • 13-9 File context variable· 13-19,13-20 File 1/0· 13-1, 13-10 See also 1/0 Files message· 7-15 table-7-15 to 7-17 message source, example· 7-18 File server • 13-1 File Service • 1~ device specifications • 13-2, 13~ disk· 1-16 disk volumes ·13-1,13-3 file specifications • 13-5 initialization routines ·13-19 interface for device drivers - 13-19 operations ·13-10 security • 12-19 tape -1-16 Index-15 File Service (Cont.) tape volumes • 13-1, 13-3 volume names • 13-3 File utility procedures· 13-11 to 13-15 ELN$COPY_FILE - 13-11 ELN$CREATE_DIRECTORY -13-12 ELN$DELETE_FILE -13-12 ELN$DIRECTORY_CLOSE -13-13 ELN$DIRECTORY_LlST -13-13 ELN$DIRECTORY_OPEN ·13-13 ELN$PROTECT_FILE -13-14 ELN$RENAME_FILE ·13-15 ELN$SET_DEFAULT_FILESPEC - 13-15 File variables, shared - 5-3 Flow control, message - 5-17,5-27 with circuits· 5-22 with TCP • 10-8 with unconnected ports • 5-21 Formatted message frames • 8-15 FORTRAN runtime library message files - 7":"'16,7-17 Fragmentation by gateway • 10-23 datagram • 10-23 Frame depths • 7-6, 7-8 Frame pointer' 7-1, 7-8 FREE_MAP procedure' 6-11 FREE_MEMORY procedure· 3-31 FREE_PATH procedure • 6-12 FREE_SYSTEM_REGION procedure • 3-31 Functions accept· 10-55 accepting connection requests with • 10-65 bind ·10-55 binding names to sockets with • 10-58 close • 10-55 closing sockets with • 10-76 connect· 10-55 initiating socket connections with • 10-62 ELN$GP-.AUXILIARY_COMMAND '14-148 ELN$GP_CLEAR_EVENT ·14-148 ELN$GP_CONFIGURE' 14-148 ELN$GP_DEFINE_PATH ·14-148 ELN$GP_GET_CONTROL '14-148 ELN$GP_GOTO_STANDBY - 14-148 ELN$GPJNITIALIZE ·14-148 ELN$GP_LOAD_PARALLEL_POLL· 14-148 ELN$GP_PARALLEL_POLL - 14-150 ELN$GP_PARALLEL_POLL_CONFIG'14-150 16-lndex Functions (Cont.) ELN$GP_PASS_CONTROL· 14-150 ELN$GP_RECEIVE_CONTROL' 14-150 ELN$GP_REQUEST_SERVICE' 14-150 ELN$GP_SEND_COMMAND' 14-150 ELN$GP_SENSE_MODE' 14-150 ELN$GP_SERIAL_POLL • 14-150 ELN$GP_SET_EVENT • 14-150 ELN$GP_TRANSFER ·14-150 ELN$GP_UNIT_INIT ·14-150 ELN$PHYSICAL_ADDRESS· 6-13 getpeername • 10-91 retrieving socket names with 0 10-91 getsockname • 10-91 retrieving socket names with 0 10-91 getsockopt 0 10-91 retrieving socket options with '10-93 htonl • 10-53 htons 0 10-53 inet_addr • 10-54 inet_lnaof' 10-54 inet_makeaddr • 10-54 inet_netof • 10-54 Inet_network • 10-54 Inet_ntoa· 10-54 listen • 10-55 listening for connection requests with 0 10-64 MFPR· 6-10 ntohl - 10-53 ntons - 10-53 PORT$ALLOCATE_DEVICE ·14-116 allocating SCSI device request packets with • 14-122 description of - D-3 PORT$EXIT_HANDLER 0 0-7 PORT$FREE_DEVICE 014-116 deallocating SCS I device request packets with • 14-122 description of • 0-1 0 PORT$INITIALlZE_CONTROLLER ·14-116 description of - 0-13 initializing SCSI device controllers with • 14-127 PORT$ISSUE_COMMAND· 14-116 description of - 0-16 issuing SCSI commands with 014-125 PORT$MAP_BUFFER 014-116 description of • 0-20 Functions PORT$MAP_BUFFER (Cont.) mapping 110 request packet buffer with· 14-123 PORT$UNMAP_BUFFER ·14-116 description of· 0-24 unmapping 1/0 request packet buffer with· 14-124 read ·10-55 receiving data from sockets with • 10-70 READ_REGISTER • 5-4, 6-9 recv ·10-55 receiving data from sockets with • 10-70 recvfrom • 10-55 receiving data from sockets with· 10-71 recvmsg • 10-55 receiving data from sockets with· 10-71 select • 10-55 polling sockets for 110 activity with • 10-73 send ·10-55 sending data to sockets with ·10-67 sendmsg • 10-55 sending data to sockets with • 10-68 sendto • 10-55 sending data to sockets with • 10-68 setsockopt· 10-91 setting socket characteristics with • 10-92 shutdown • 10-56 shutting down sockets with • 10-75 socket· 10-56 creating sockets with • 10-57 vax$get_sdc returning socket device descriptors with • 10-60 vax$socket control setting -;ocket characteristics with • 10-60 vaxc$get_sdc· 10-56 vaxc$socket_control • 10-56 write • 1 0-56 sending data to sockets with • 10-66 G Gateway addresses extracting from routing table entries • 10-37 in Internet routing algorithm • 10-22 Gateway routes • 10-31 Gateways default· 10-22 setting • 10-24 definition of· 10-1 General runtime library message files· 7-16 Generic class driver, SCSI • 14-73, 14-77 to 14-11 0 See also SCSI generic class driver procedures connecting to ·14-78 example • 14-91 to 14-11 0 GET_JCB procedure • 3-17 $GETMSG system service· 7-14,7-21 getpeername function • 10-91 retrieving socket names with • 10-91 getsockname function 01 0-91 retrieving socket names with 010-91 getsockopt function· 10-91 retrieving socket options with • 10-93 GET_STATUS_TEXT procedure 07-21 GET_TIME procedure· 4-5,4-8 GET_USER procedure 03-18, 12-3, 12-16 Global common • ~2 Global data· ~1 globaldef attribute· ~2 globalref attribute 0 ~2 GP AUXILIARY COMMAND function· 14-148 GP-CLEAR EVENT function 014-148 GP-CONFIGURE function· 14-148 GP-DEFINE PATH function 014-148 GP-GET CONTROL function ·14-148 GP-GOTO STANDBY function 014-148 GP-INITIALIZE function 0 14-148 GP-LOAD PARALLEL POLL function· 14-148 GP-PARALLEL POLL -CONFIG function 014-150 GP- PARALLEL-POLLfunction • 14-150 GP-PASS CONTROL function ·14-150 GP-RECEIVE CONTROL function· 14-150 GP-REQUEST SERVICE function • 14-150 GP-SEND COMMAND function • 14-150 GP-SENSE MODE function ·14-150 GP- SERIAL- POLL function 0 14-150 GP-SET EVENT function 014-150 GP-TRANSFER function 014-150 GP=UNIT_INIT function 014-150 Groups See LAT (local area transport) Index-17 H Hardware addresses Ethernet controller· 8-11, 8-12 for trigger boot operations • 9-37 in down-line load data base • 9-21 Hardware requirements· 1-2 Headers I P datagram • 10-5 Heterogeneous network environments • 8-1 Homogeneous network environments • 8-1 Host adapter, SCSI· 14-74 Host byte order· 10-53 converting Internet addresses to • 10-54 Host identifier, Internet address • 10-9 Host routes • 10-31 Hosts, Internet· 10-1 Host services, LAT· 1-15, 1f-1 Host system • 1-1 Host-to-host Internet layer - 10-4, 10-6, 10-7 identifier - 10-5 htonl function - 10-53 htons function - 10-53 ICMP (Internet Control Message Protocol) datagrams· 10-43 definition of - 10-5 redirect messages • 10-34 Identification strings service - 11-19 service node-11-15 IECIIEEE-488 instrument bus - 14-129, 14-146 IEEE 802 Datagram Service See Ethernet/IEEE 802 Datagram Service IEEE 802 formatted frames - 8-16 IEQ11-A device -14-129,14-146 IEQ11-A device driver utility functions -14-148 IEU11-A device -14-129,14-146 IEU11-A device driver utility functions - 14-148 Inactive LAT service node -11-17 See also LAT (local area transport) INET_CHECK_ROUTE procedure ·10-31 checking status of routing table entries with 10-34 18-lndex INET_DELETE_ARP_ENTRY procedure - 10-25 deleting ARP cache entries with - 10-26 INET_DELETE_ROUTE procedure· 10-31 deleting routing table entries with - 10-31 INET_FIND_ARP_ENTRY procedure -10-25 retrieving Ethernet addresses with • 10-27 INET_SET_ARP_ENTRY procedure - 10-25 adding entries to ARP cache with - 10-26 INET_SET_INTERFACE procedure· 10-40 setting network interfaces with - 10-40 INET_SET_ROUTE procedure -10-31 adding entries to routing table with· 10-31 INET_SHOW_ARP_ENTRIES procedure - 10-25 retrieving ARP entries with - 10-28 INET SHOW CONNECTIONS procedure retrieving TCP connection data with - 10-48 INET_SHOW_INTERFACE procedure -10-40 retrieving network interface characteristics with 10-42 IN ET_SHOW_I P_STATISTICS procedure -10-44 retrieving IP statistics with - 10-46 INET_SHOW_ROUTES procedure ·10-31 retrieving routing table entries with • 10-37 INET SHOW TCP STATISTICS procedure - 10-44 retrieving TCP ~atistics with - 10-46 INET SHOW UDP STATISTICS procedure - 10-44 retrieving IP statistics with - 10-46 inet_addr function· 10-54 inet Inaof function - 10-54 ine(makeaddr function • 10-54 inet netof function - 10-54 inet=network function • 10-54 inet ntoa function • 10-54 Info~mational status codes· 7-14 INITIALIZATION_DONE procedure - 3-12, 3-18, 13-19 Initialization programs - 3-12,3-18 INITIALlZE_AREA_LOCK procedure - 5-29 as area lock variable operation • 2-17 initializing area lock variables with - 5-40 Initiator, SCSI bus - 14-74 INIT_TAPE_VOLUME procedure -13-18 INIT_VOLUME procedure-12-20, 13-16 Input, terminating lines of terminal - 14-36 INSERT_ENTRY procedure - 5-2 Instrument bus interface· 14-146 Interjob communication - 5-10 to 5-46 Interjob communication (Cont.) through areas· &-28 to 5--46 through message passing • &-10 to &-28 Internet See also Internet addresses; Internet Services address manipulation functions • 10-54 architecture· 10-3 communication connection less • 10-6, 10-17 connection-oriented· 10-7, 10-16 datagram-based • 10-6 domain ·10-15 half-duplex socket • 10-75 programming • 10-55 to 10-91 stream-based • 10-7 communication domain ·10-15 datagrams, size of • 10-23 defining characteristics of • 10-23 definition of • 10-1 layers figure of· 10-4 host-to-host· 10-4, 10-6, 10-7 identifier • 10-5 Internet protocol • 10-4 network interfaces See also Ethernet controllers information about· 10-43 managing • 10-40 to 10-44 retrieving characteristics of· 10-42 setting • 10-40 network masks • 10-12 setting for Internet network interfaces· 10-24 network packets • 10-5 networks Class A· 10-10 Class B· 10-10 Class C· 10-11 classes of· 10-9 class number ranges for· 10-11 default network masks for • 10-13 network masks for Class A· 10-13 network masks for Class B • 10-13 network masks for Class C • 10-13 when to use Class A • 10-11 when to use Class B ·10-11 when to use Class C ·10-12 performance and error data • 10-44 routes • 10-18 Internet (Cont.) routing, types of ·10-31 routing algorithm • 10-19 to 10-23 broadcast addresses used in • 10-22 destination addresses used in • 10-22 gateway addresses used in • 10-22 routing table • 10-19 adding entries to • 10-31 deleting entries from • 10-31 managing· 10-31 to 10-39 socket names· 10-16 subnetworks of • 10-18 Internet addresses as routes· 10-19 broadcast· 10-9, 10-13 examples of· 10-14 broadcast masks for • 10-13 classes defined by • 10-9 converting to from network and local addresses • 10-54 converting to host byte order • 10-54 converting to network byte order· 10-54 converting to text string representation • 10-54 data base of· 10-6, 10-7 definition of· 10-9 destination • 10-37 extracting from ARP cache • 10-28 for network interfaces • 10-43 gateway • 10-37 getting at start-up • 10-6, 10-7 in IP datagrams ·10-5 in socket names • 10-16 local • 10-48 manipulating • 10-54 mapping· 10-5, 10-26 network classes for· 10-9 network masks for • 10-12 notation for • 10-9 protocol for mapping • 10-5 remote • 10-48 retrieving Ethernet address for· 10-27 returning network portion of • 10-54 returning subnetwork portion of· 10-54 setting for network interfaces • 10-24, 10-40 Internet Characteristics Menu • 10-23 Internet Control Message Protocol (ICMP) See ICMP (Internet Control Message Protocol) Index-19 Internet network control procedures See also Internet; Internet addresses; Internet Services ELN$INET_CHECK_ROUTE 010-31 checking status of routing table entries with 0 10-34 ELN$INET DELETE ARP ENTRY 010-25 deleti;:;g ARP c.rehe ~tries with 0 10-26 ELN$INET_DELETE_ROUTE 010-31 deleting routing table entries with 0 10-31 ELN$INET_FIND_ARP_ENTRY 010-25 retrieving Ethernet addresses with 0 10-27 ELN$INET_SET_ARP_ENTRY 010-25 adding entries to ARP cache with 010-26 ELN$INET_SET_INTERFACE 010-40 setting network interfaces with 0 10-40 ELN$INET_SET_ROUTE 010-31 adding entries to routing table with 0 10-31 ELN$INET_SHOW_ARP_ENTRIES 010-25 retrieving ARP entries with 0 10-28 ELN$INET_SHOW_CONNECTIONS retrieving TCP connection data with 0 10-48 ELN$INET_SHOW_INTERFACE 010-40 retrieving network characteristics with 0 10-42 ELN$INET_SHOWJP_STATISTICS 010-44 retrieving IP statistics with 010-46 ELN$INET_SHOW_ROUTES 010-31 retrieving routing table entries with 0 10-37 ELN$INET_SHOW_TCP_STATISTICS 010-44 retrieving TCP statistics with 010-46 ELN$INET_SHOW_UDP_STATISTICS 010-44 retrieving UDP statistics with 0 10-46 Internet Network Description Menu 0 10-23 Internet protocol (IP) 0 10-4 See IP (Internet protocol) Internet protocols AR P (Address Resolution Protocol)· 10-5, 10-25 BOOTP (Boot Protocol) 0 10-7 ICMP (Internet Control Message Protocol) 0 10-5 IP (Internet protocol)· 10-3, 10-4 description of 0 10-5 layers of 0 10-4 RARP (Reverse Address Resolution Protocol) • 10-6 TCP (Transmission Control Protocol) 0 10-4 characteristics of • 10-8 20-Index Internet protocols TCP (Transmission Control Protocol) (Cont.) description of 0 10-7 functions of • 10-7 types of· 10-16 datagram • 10-16 raw· 10-16 stream· 10-16 UDP (User Datagram Protocol)· 10-4 characteristics • 1O~ description of· 10~ Internet Services 01-15,8-1,10-1 See also Internet; Internet addresses concepts • 10-2 configuring • 10-23 configuring Ethernet controller for • 10-23 controlling • 10-25 to 10-52 by managing ARP cache • 10-25 to 10-30 by managing Internet network interfaces • 10-40 to 10-44 by managing Internet routing table· 10-31 to 10-39 datagrams • 10-5 features of • 10-1 routing algorithm ·10-19 to 10-23 broadcast addresses used in • 10-22 destination addresses used in 0 10-22 gateway addresses used in • 10-22 routing table for·1 0-19 sockets for • 10-15 Interprocess communication • 5-1 to 5-9 through data sharing • 5-1 to 5-4 through queues· 5-4 to 5-9 Interprocess data flow, Internet· 10-3 Interprocess synchronization • 5-41 Interrupt priorities • 6-7 Interrupt priority level (IPL) See IPL (interrupt priority level) Interrupts See Device interrupts Interval time • 4-2 waiting for an 0 4-6 1/0 between nodes· 9-3 control functions • 1o~o logical • 13-4 1/0 (Cont.) using circuits for· 5-17 IP (Internet protocol) • 10-3 characteristics of • 10-5 datagrams • 10-43 description of· 10-5 Internet layer· 10-4 reliability of· 10-5 returning statistics for • 10-45 I PL (interrupt priority level) • 6-6 lowering • 6-8 raising • 6-7, 6-8 ISR (interrupt service routine)· 2-6, 6-1 associating device with • 6-3 reading and writing data with • 6-9 shared· 5-3 signaling DEVICE object from • 6-5 J JCB Gob control block), returning address of • 3-17 Job eligibility mask, modifying • 3-19, 6-8 See also Tightly coupled symmetric mUltiprocessing JOB_PORT procedure· 5-26 as PORT object operation • 2-11 Job ports • 2-10 returning PORT object for· 5-26 sending messages to· 5-14 Job priorities· 3-9,6-7 setting • 3-20 Jobs· 1-8, 3-1 activating • 3-3 communication between • 5-10 to 5-46 by passing messages • 5-1 0 to 5-28 by sharing memory· 5-28 to 5-46 configurations of • 3-2 creating • 3-3 priorities of • 3-9, 6-7 setting • 3-20 returning the JCB of· 3-17 running in symmetric multiprocessing configurations • 6-8 scheduling of • 3-9 setting processor eligibility for· 3-19, 6-8 See also Tightly coupled symmetric multiprocessing Jobs (Cont.) synchronizing execution of • 5-31, 5-41 termination of· 3-3 K KA800 processors loading VAXELN systems into memory of • 3-32 sharing memory areas in • 5-30 Keep-alive time setting • 10-24 setting for sockets • 10-92 Keep-alive timer, TCP· 10-49 KER$RAISE_PROCESS_EXCEPTION asynchronous exception· 7-13 KER$_DISCONNECT status value, checking for· 9-16 KER$ALLOCATE_MAP procedure· 6-10 KER$ALLOCATE_PATH procedure • 6-11 KER$ALLOCATE_SYSTEM_REGION procedure • 3-30 KER$ENTER_KERNEL_CONTEXT procedure • 6-14 KER$FREE_MAP procedure· 6-11 KER$FREE_PATH procedure· 6-12 KER$FREE_SYSTEM_REGION procedure • 3-31 KER$GET_JCB procedure • 3-17 KER$GET_UPTIME procedure • 4-5, 4-8 KER$GET_USER procedure· 3-18,12-3,12-16 KER$LOCK_DEVICE procedure· 6-8 KER$MEMORY_SIZE procedure· 3-31 KER$NAME_OBJECT procedure· 3-18 as NAME object operation· 2-10 Kernel· 1-6, 1-14, 2-1 See also Kernel procedures communication with Name Service • 9-6 data structures· 2-1 message-passing procedures· 9-3 objects See Objects operations • 2-1 optimized data structures· 2-15 to 2-18 runtime message files • 7-16 scheduler • 3-9 Kernel mode, executing routines in· 6-14 Kernel procedures ACCEPT_CIRCUIT accepting logical links with • 9-2 Index-21 Kernel procedures ACCEPT_CIRCUIT (Cont.) accepting messages from network nodes with· 9-3 accepting VMS connections with • 9-48 as PORT object operation • 2-12 contrOlling message flow with· 5-17 establishing circuits for authorization with • 12-16 establishing circuits with • 5-17 waiting for circuit connection with • 5-23 CLEAR_EVENT • 4-4, 5-28 as EVENT object operation· 2-8 clearing EVENT objects with· 4-17 CONNECT_CIRCUIT ·12-5 as PORT object operation· 2-12 connecting to VMS with· 9-47 connect to a port with • 5-24 controlling message flow with • 5-17 creating logical links with • 9-2 establishing circuits for authorization with • 12-16 establishing circuits with • 5-17 establishing network node connections with • 9-3 named ports used with • 5-14 setting up DDCMP communication with· 14-38 specifying DECnet object numbers with • 9-49 CREATE_AREA • 4-4, 5-28 as AREA object operation • 2-5 creating AREA objects with· 5-30 creating area semaphores with • 4-11 CREATE_AREA_EVENT • 4-4, 5-28 as area event operation • 2-5 creating area events with • 4-16 creating AREA objects with • 5-30 CREATE_AREA_SEMAPHORE • 4-4, 5-29 as area event operation • 2-5 creating AREA objects with • 5-30 creating area semaphores with· 4-11 CREATE;..,.DEVICE as DEVICE object operation • 2-7 creating DEVICE objects with· 6-3 specifying a power-failure recovery routine with· 6-17 CREATE_EVENT • 4-4 22-lndex Kernel procedures CREATE_EVENT (Cont.) as EVENT object operation • 2-7 creating EVENT objects with· 4-16 CREATE_JOB • 3-15 activating Down-Line Load Service with· 9-18 creating jobs with· 3-1, 3-3 CREATE_MESSAGE as MESSAGE object operation· 2-8 creating MESSAGE objects with· 5-11, 5-25 setting up message communication with· 5-14 CREATE_NAME as NAME object operation· 2-10 creating NAME objects with· 5-13,5-25 creating universal port names with • 9-5 CREATE_PORT as PORT object operation· 2-11 creating PORT objects with • 5-12, 5-25 CREATE_PROCESS • 3-15, 4-4 as PROCESS object operation· 2-13 creating processes with • 3-2 using exit parameter with • 4-10 CREATE_SEMAPHORE • 4-4 as SEMAPHORE object operation· 2-14 creating SEMAPHORE objects with • 4-11 CURRENT_PROCESS· 3-16,4-5 as PROCESS object operation· 2-13 DELETE • 4-5, 5-29 as AREA object operation· 2-6 as DEVICE object operation • 2-7 as EVENT object operation • 2-8 as MESSAGE object operation • 2-9 as NAME object operation • 2-10 as PORT object operation • 2-12 as PROCESS object operation. 2-13 as SEMAPHORE object operation • 2-14 deleting AREA objects with • 5-46 deleting DEVICE objects with • 6-5 deleting EVENT objects with· 4-18 deleting MESSAGE objects with· 5-26 deleting NAME objects with· 5-13, 5-26 deleting PORT objects with· 5-12, 5-26 deleting PROCESS objects with • 3-16 deleting SEMAPHORE objects with· 4-14 deleting universal port names with • 9-5 terminating processes with • 3-5 Kernel procedures (Cont.) DISABLE_ASYNCH_EXCEPTION • 7-12 DISABLE_SWITCH· 3-11,3-16 DISCONNECT_CIRCUIT as PORT object operation • 2-12 disconnecting circuits with • 5-19, 5-26 disconnecting network node connections with· 9-3 disconnecting VMS connections with • 9-48 switching DECnet software between controllers with • 9-16 terminating DDCMP communication with • 14-38 ENABLE_ASYNCH_EXCEPTION • 7-12 ENABLE_SWITCH· 3-11,3-17 EXIT· 3-17 as PROCESS object operation· 2-13 failure exceptions for· 7-11 for message transmission • 5-23 for processes and jobs • 3-14 GET_TIME· 4-5, 4-8 INITIALIZATION_DONE· 3-12,3-18,13-19 JOB_PORT • 5-26 as PORT object operation· 2-11 KER$ALLOCATE_MAP· 0-10 KER$ALLOCATE_PATH· 0-11 KER$FREE_MAP· 0-11 KER$FREE_PATH· 0-12 KER$GET_JCB· 3-17 KER$GET_UPTIME • 4-8 KER$GET_USER· 3-18,12-3 KER$LOCK_DEVICE • 0-8 KER$NAME_OBJECT· 3-18 as NAME object operation· 2-10 KER$RAISE_PROCESS_EXCEPTION· 3-19, 7-12,7-13 KER$SET_JOB_ELlGIBILlTY· 3-19 See also Tightly coupled symmetric multiprocessing in device drivers • 0-8 KER$SET_USER· 3-22,12-2 KER$UNLOCK_DEVICE • 0-8 KER$UNWIND· 7-13 KERGET_UPTIME· 4-5 RAISE_EXCEPTION· 7-11,7-13 RECEIVE as MESSAGE object operation· 2-9 Kernel procedures RECEIVE (Cont.) receiving expedited messages with· 5-16 receiving messages from network nodes with· 9-3 receiving messages with· 5-12, 5-15,5-26 when circuit is disconnected • 5-19 RESUME· 3-19 as PROCESS object operation • 2-13 SEND as MESSAGE object operation • 2-9 sending expedited messages with • 5-15 sending messages to network nodes with • 9-3 sending messages with • 5-14, 5-27 when circuit is disconnected • 5-19 SET_JOB_PRIORITY • 3-20 SET_PROCESS_PRIORITY • 3-21 as PROCESS object operation • 2-13 SET_TIME • 4-5 SIGNAL • 4-5, 5-29 as area event operation • 2-6 as area semaphore operation • 2-6 as EVENT object operation • 2-8 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 signaling AREA objects with ·5-33,5-39 signaling EVENT objects with • 4-16 signaling PROCESS objects with • 3-22 signaling SEMAPHORE objects with • 4-12 SIGNAL_DEVICE • 6-5 as DEVICE object operation· 2-7 status of • 7-11 SUSPEND • 3-22 as PROCESS object operation· 2-13 TRANSLATE_NAME as NAME object operation • 2-10 for using named message ports • 5-14 translating named ports with • 5-27 translating universal port names with • 9-5 WAIT_ALL • 0-5 applied to AREA objects· 5-29,5-33,5-39 applied to EVENT objects • 4-16 applied to PORT objects· 5-12,5-27 applied to PROCESS objects· 3-23 applied to SEMAPHORE objects· 4-12 as AREA object operation· 2-5 as DEVICE Object operation • 2-7 Index-23 Kernel procedures WAIT_ALL (Cont.) as EVENT object operation • 2-7 as PORT object operation • 2-12 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 specifying a time value with • 4-0 synchronizing processes with· 4-2 WAIT_ANY· 6-5 applied to AREA objects • 5-29, 5-33, 5-39 applied to EVENT objects· 4-16 applied to PORT objec~s· 5-12,5-27 applied to PROCESS objects • 3-23 applied to SEMAPHORE objects • 4-12 as AREA object operation • 2-5 as DEVICE object operation· 2-7 as EVENT object operation • 2-7 as PORT object operation • 2-12 as PROCESS object operation • 2-13 as SEMAPHORE object operation· 2-14 specifying a time value with • 4-0 synchronizing processes with· 4-2 Kernel runtime message files· 7-16 KER$_POWER_SIGNAL exception • 7-12 KER$_PROCESS_ATTENTION exception· 7-12 KER$_QUIT_SIGNAL exception· 7-12 KER$RAISE_PROCESS_EXCEPTION procedure • 3-19,7-12, 7-13 KER$SET_JOB_ELIGIBILITY procedure· 3-19 See also Tightly coupled symmetric multiprocessing in device drivers • 6-8 KER$SET_USER procedure. 3-22, 12-2, 12-17 KER$UNLOCK_DEVICE procedure • 6-8 KER$UNWIND procedure· 7-8,7-13 KWV11-C device· 14-129,14-150 KWV device driver utility procedures· 14-151 KWV_INITIALIZE procedure ·14-151 KWV_READ procedure • 14-151 KWV_WRITE procedure· 14-151 L Language-independent runtime library message files· 7-17 LAT (local area transport) application devices ·11-2 24-lndex LAT (local area transport) application devices (Cont.) accessing· 11-36 example • 11-38 to 11-40 setting up • 11-36 to 11-43 communication, establishing circuits for· 11-4 connection, requesting notification of· 11-35 connection requests, queued. 11-25 control ports, connecting to ·11-5, 11-34, 11-40 counters • 11-27 dedicated services • 11-2 environment of (figure) • 11-29 example • 11-31 to 11-33 setting up· 11-29 to 11-36 default service· 11-2 driver· 11-3 groups· 11-15 host services ·1-6,1-15, 11-1 building into VAXELN systems· 11-3 network ·11-1 balancing load of· 11-19 groups· 11-15 monitoring performance and error statistics of· 11-27 ports accessing· 11-35, 11-41 associating with application devices • 11-41 associating with services· 11-34 characteristics record for· 11-23, 11-26 connecting to DDA port of· 11-9 connecting to device port • 11-42 creating • 11-7 creating application • 11-40 creating dedicated· 11-34 disconnecting from device port· 11-42 disconnecting from service • 11-36 interactive • 11-7 names of • 11-24 queue statuses of· 11-25 retrieving characteristics of • 11-23 service announcement messages· 11-16 service nodes· 11-2 advertising services of· 11-21 characteristics records for • 11-12 identification strings of • 11-15 inhibiting connections to • 11-20 LAT network groups of· 11-15 managing ·11-12 LAT (local area transport) service nodes (Cont.) managing services of - 11-17 multicast timer of - 11-16 names of - 11-14 returning characteristics of-11-13 service announcement messages sent by 11-16 setting characteristics of - 11-14 shutting down - 11-22 states of - 11-3, 11-16 services advertising - 11-21, 11-35 associating with dedicated LAT ports - 11-34 changing characteristics of - 11-20 creating - 11-17, 11-34 dedicated - 11-2, 11-29, 11-31 to 11-33 deleting -11-17 ECL as - 11-2 identification strings of - 11-19 managing - 11-17 names of - 11-18 ratings of - 11-19 setting up dedicated - 11-29 to 11-36 utility procedures - 11-4 LATCP utility - 1-7, 11-2 See also LAT (local area transport) LAT host services -1-6 LAT host service utility procedures connecting to control port for - 11-5 ELN$LAT_CLEAR_COUNTERS -11-6 initializing LAT counters with - 11-28 ELN$LAT_CREATE_PORT -11-6 creating application LAT ports with - 11-40 creating dedicated LAT ports with - 11-34 creating LAT ports with - 11-8 ELN$LAT_CREATE_SERVICE - 11-6 creating services with - 11-17, 11-34 ELN$LAT_DELETE_PORT -11-6 ELN$LAT_DELETE_SERVICE -11-6 deleting services with - 11-17 ELN$LAT_SET_NODE -11-6 setting service node characteristics with 11-14 specifying shut-down message with - 11-22 ELN$LAT_SET_PORT -11-6 setting application LAT port with -11-41 LAT host service utility procedures ELN$LAT_SET_PORT (Cont.) setting dedicated LAT port with - 11-34 ELN$LAT_SET_SERVICE - 11-6 changing service characteristics with - 11-20 ELN$LAT_SHOW_CHAR - 11-6 retrieving service node characteristics with 11-13 ELN$LAT_SHOW_COUNTERS -11-6 retrieving LAT counters with - 11-28 ELN$LAT_SHOW_PORT -11-6 retrieving LAT port characteristics with11-23 ELN$LAT_SHOW_SERVERS -11-7 retrieving terminal server characteristics with - 11-26 ELN$LAT_START_NODE -11-7 activating LAT protocol with - 11-21, 11-35, 11-41 ELN$LAT_STOP_NODE -11-7 shutting down LAT protocol with - 11-22 LAT port utility procedures ELN$LAT_CONNECT_PORT -11-11 connecting LAT port to device port with11-42 ELN$LAT_DISCONNECT_PORT - 11-11 disconnecting LAT connection with -11-36, 11-42 ELN$LAT_MAP_PORT -11-11 associating application LAT port with - 11-41 mapping dedicated LAT port with - 11-34 ELN$LAT_SHOW_PORT_MAPPING -11-11 ELN$LAT_WAIT_FOR_CONNECTION -11-11 requesting LAT connection notification with 11-35 LlB$ emulation routines - C-9 LlB$ADD_TIMES routine - C-9 LlB$ADDX routine - C-9 LlB$ANALYZE_SDESC routine - C-10 LlB$CREATE_USER_VM_ZONE routine - C-10 LlB$CREATE_VM~ONE routine - C-11 LlB$CVT_DTB routine - C-12 LlB$CVT_HTB routine- C-12 LlB$CVT_OTB routine- C-13 LlB$DELETE_VM_ZONE routine - C-13 LlB$EMUL routine - C-14 LlB$FLT_UNDER routine- C-15 LlB$FREE_VM_PAGE routine - C-15 Index-2S L1B$GET_INPUT routine • 0-16 LIB$GET_VM_PAGE routine· 0-17 L1B$GET_VM routine· 0-16 L1B$INT_OVER routine· 0-18 L1B$MATCH_COND routine • 0-19 L1B$MULT_DELTA_TIME routine· 0-19 L1B$MULTF_DELTA_TIME routine· 0-20 Libraries object module RTL· 7-15 RTLOBJECT· 7-15 runtime • 1-3, 1-6, 7-15 L1B$RESET_VM_ZONE routine • 0-21 L1B$SCOPY_DXDX routine • 0-21 LIB$SCOPY_R_DX routine • 0-21 LIB$SIGNAL routine • 0-22 L1B$SIG_TO_RET routine· 0-23 L1B$STOP routine • 0-23 LIB$SUB_TIMES routine • 0-24 LIB$SUBX routine • 0-24 Line names • 9-28 in down-line load data base· 9-21 specified for down-line load operations • 9-40 specified for trigger boot operations· 9-37 specified with Network Management Service proced ures • 9-11 Lines names of· 9-28 retry count for • 9-28 service timer for • 9-28 state of· 9-28 Line state • 9-28 Linger time setting • 10-24, 10-92 Linger timer, TCP • 10-49 listen function • 10-55 listening for connection requests with • 10-64 LLC classes· 8-18,8-34 specifying • 8-35 LOAD/PROGRAM command· 3-3 Loader KA800 ·3-32 primary • 9-36 secondary • 9-36, 9-41 tertiary • 9-36, 9-41 LOAD_KA800_PROCESSOR procedure • 3-32 LOAD PROGRAM debugger command • 3-3 26-lndex LOAD_PROGRAM procedure' 3-13 loading program images with • 3-3 Load requests • 9-35 application-initiated • 9-36, 9-40 as response to trigger boot request • 9-36 sending to local node· 9-35 sending to multicast addresses • 9-35 target-initiated figure of • 9-35 load sequence for • 9-36 Load sequence, for target-initiated requests. 9-36 LOAD_UNIBUS_MAP procedure • 6-10 Local addresses, reusing in socket names • 10-92 Local area network (LAN) • 9-3 See also CSMAlCD LAN Authorization Service for • 12-3 Local area transport (LAT) See LAT (local area transport) Local data, sharing • 5-1 Local disk devices reading data from ·14-7, 14-9 writing data to· 14-7, 14-9 Local nodes, load requests sent to· 9-35 Local port names' 2-9,5-10,5-13, 13-5 See also Universal port names creating • 5-25 Local routes • 10-34 LOCK_AREA procedure • 5-29 as area lock variable operation • 2-17 locking areas with· 5-40 LOCK_DEVICE procedure • 6-8 Locked routes • 1 0-32 LOCK_MUTEX procedure • 4-5 as mutex operation • 2-18 locking mutexes with, 4-14 Logical blocks reading from mounted disks • 14-15 to 14-20 reading from unmounted disks' 14-12 to 14-14 Logical 110 '13-4, 14-3,14-27 Logical links· 9-2 Logical unit number (LUN) • 14-74 Loopback address • 10-10 Loopback Mirror· 9-8,9-10 LOOP NODE command • 9-10 Loosely coupled symmetric multiprocessing' 1-10 See also Multiprocessing LUN (logical unit number)' 14-74 Message buffer (Cont.) M Machine check stack frames • 8-1 Main Menu· 10-23 malloc function • 5-3 Map registers allocating • 6-1 0 freeing • 6-11 loading. 6-10 Mask values for down-line load procedures· 9-23, 9-30 for ELN$DLL_LOAD procedure • 9-42 for ELN$DLL_TRIGGER procedure • 9-38 for ELN$INET_CHECK_ROUTE procedure • 10-34 for ELN$INET_SET_ARP_ENTRY procedure· 10-26 for ELN$INET_SET_INTERFACE procedure • 10-40 for ELN$INET_SET_ROUTE procedure· 10-32 for ELN$INET_SHOW_ARP_ENTRIES procedure ·10-29 for ELN$INET_SHOW_ROUTES procedure • 10-37 for ELN$INET_SHOW_TCP_CONNECTIONS procedure • 10-49 for network management procedures· 9-11 Master process· 1-8, 3-1 Math runtime library message files· 7-17 Memory See also Memory allocation procedures allocating· 3-29,3-30 for kernel objects· 2-2,2-14 freeing • 3-31 . sharing • ~28 to ~6 Memory allocation procedures • 3-29 ALLOCATE_MEMORY • 3-29 FREE_MEMORY • 3-31 KER$ALLOCATE_SYSTEM_REGION • 3-30 KER$FREE_SYSTEM_REGION • 3-31 KER$MEMORY SIZE· 3-31 Memory buffers mapping • 6-12 unmapping· 6-13 Memory management· 3-23 to 3-33 MEMORY_SIZE procedure • 3-31 Message buffer allocating· 8-20,8-34 TCP, size of • 10-8 Message files· 7-15 table· 7-15 to 7-17 Message formats· 8-13,8-15,8-34 specifying • 8-35 Message interface, SCSI generic class driver· 14-77 to 14-110 Message object modules· 7-15 MESSAGE objects· 2-8,5-11 creating • ~ 11, ~25 definition of· 2-4 deleting • ~26 operations on • 2-8 shared· 5-3 Message ports See PORT objects; Ports Message protocol • ~15 Messages· ~10, 5-11 See also Circuits; Datagrams; MESSAGE objects constructing· 7-14 constructing application-specific • 7-18 contrOlling flow of· 5-17, ~27 with circuits· 5-22 with unconnected ports· ~21 creating ports for • 5-25 I/O as·~17 passing • ~10 to 5-28 between network nodes· 9-3 using circuits for • ~16 using datagrams for· 5-16 receiving • ~26 over CSMAlCD LAN • 8-19, 8-25, 8-36 retrieving transmitted· 8-23,8-35 runtime· 7-14 using with programs· 7-19 segmentation of • 5-17 sending • ~27 transmitting over CSMAlCD LAN • 8-19, 8-21, 8-35 urgent, TCP· 10-48 using to read and write data • 14-9 Message source files • 7-15 example· 7-18 Message symbols· 7-15,7-19 Message text Index-27 Message text (Cont.) displaying on VMS systems • 7-23 enabling • 7-24 getting· 7-14 retrieving • 7-21 shareable· 7-19,7-22,7-23 Message Utility· 7-14 MESSAGE values· 2-8,5-14 MFPR function· 6-10 Modems· 14-66 characteristics of • 14-68 control signals of • 14-67 events of, monitoring· 14-69 Modes, SCSI command • 14-88 Module-level data See also Outer-level variables sharing • 5-1 to 5-4 Mounted disks, reading from· 14-15 to 14-20 MOUNT_TAPE_VOLUME procedure ·13-4, 13-18 MOUNT_VOLUME procedure· 13-4, 13-17 msghdr structure • 10-69, 10-72 MTPR procedure· 6-10 Multicast addresses· 8-18 load requests sent to • 9-35 Multicast messages ·11-16 See also LAT (local area transport); Service announcement messages sending· 11-21 Multiplexing data· 8-13, 8-15,8-34 specifying • 8-35 in Internet environment • 10-6, 10-7 Multiprocessing • 1-10 to 1-12 closely coupled symmetric· 1-11,3-32 Ethernet node· 9-1 sharing memory areas during • 5-30 loosely coupled symmetric· 1-10 scheduling • 3-14 synchronizing access to device communication region for· 6-7 tightly coupled symmetric· 1-11 returning a JCB address during • 3-17 scheduling for· 3-14 setting processor eligibility during • 3-19, 6-8 Multiprogramming • 1-10 Multitasking· 1-10, 4-1,13-19 MUTEX data type· 2-17 28-lndex Mutexes· 2-1,2-16,4-14 creating. 4-14 deleting • 4-15 initializing • 4-14 internal representation of • 2-18 locking· 4-14 operations with • 2-17 unlocking· 4-15 Mutex procedures • 2-18 ELN$CREATE_MUTEX·4-4 creating mutexes with· 4-14 ELN$DELETE_MUTEX·4-5 deleting mutexes with· 4-15 ELN$LOCK_MUTEX • 4-5 locking mutexes with· 4-14 ELN$UNLOCK_MUTEX • 4-5 unlocking mutexes with • 4-15 Mutual exclusion· 4-1 N NAME_OBJECT procedure· 3-18 as NAME object operation· 2-10 NAME objects· 2-9,5-13 See also Names creating • 5-13, 5-25 definition of • 2-4 deleting· 5-26 operations on· 2-10 Names See also NAME objects binding to sockets • 10-58 LAT port· 11-24 LAT service· 11-18 port· 2-4,2-9,5-10,5-13,13-5 creating • 5-25 universal· 2-10,5-10,5-13,9-5,9-7,13-5 socket • 10-16 VAXELN service node· 11-14 Name server • 9-6 communication • 9-6 displaying current • 9-6 protocol for electing • 9-7 Name Service· 9-5 communication with kernel· 9-6 name server • 9-6 communication • 9-6 Name Service name server (Cont.) displaying current· 9-6 protocol for electing· 9-7 Name structures, socket· 10-58 Name table See Universal name table NAME values· 2-10,5-13 NCP (network control program)· 9-8 NCP commands list of· 9-10 LOOP NODE· 9-10 SET EXECUTOR· 9-9 SHOW CIRCUIT • 9-9 SHOW NODE • 9-9 Network, LAT· 11-1 See also LAT (local area transport) balancing load of· 11-19 groups ·11-15 monitoring performance and error statistics of • 11-27 Network byte order • 10-53 converting Internet addresses to • 10-54 Network connections • 9-16 Network control program (NCP) • 9-8 See also NCP commands assigning node names and numbers with • 9-46 invoking NML functions with • 9-9 Network environments· 8-1 Network groups See LAT (local area transport) Network identifier, Internet address • 10-9 Network interface See Internet Network interface procedures See also Ethernet/IEEE 802 Datagram Service ELN$NLALLOCATE_BUFFER • 8-6, 8-34 allocating message buffers with • 8-20 ELN$NLCONNECT • 8-6, 8-34, 8-36 connecting Ethernet/IEEE 802 protocols with· 8-12 ELN$NLDISCONNECT • 8-6, 8-35 disconnecting Ethernet/IEEE 802 protocols with· 8-13 ELN$NLGET_ATIRIBUTES • 8-6 retrieving Ethernet controller attributes with· 8-10 Network interface procedures (Cont.) ELN$NLGET_CONFIGURATION • 8-6 getting line names with· 9-29 retrieving CSMAlCD LAN configuration with • 8-7 ELN$NLRECEIVE • 8-6, 8-36 receiving messages with • 8-25 ELN$NLTRANSMIT • 8-6, 8-35 transmitting messages with • 8-21 ELN$NLTRANSMIT_STATUS· 8-6,8-35 retrieving transmitted messages with • 8-23 using when DECnet operations stop • 9-12 Network interfaces See also Ethernet controllers information about· 10-43 managing • 10-40 to 10-44 retrieving characteristics of • 10-42 setting Internet addresses for • 10-40 Network management See Network management services Network management listener (NML) • 9-8, 9-9 Network management procedures • 9-11 See also Network Management Service modules for using· 9-12 Network management protocol (NMP) • 9-8 Network Management Service· 9-8,9-11 to 9-18 See also Network management services initializing DECnet node addresses with· 9-13 initializing node addresses with· 9-13 reducing network overhead with· 9-14 stopping and starting DECnet software with· 9-14 switching DECnet sqftware between controllers with· 9-16 Network management services • 9-8 to 9-44 See also Down-Line Load Service; Network Service; Network Management Service for managing systems from VMS systems • 9-9 for testing Network Service • 9-10 Loopback Mirror • 9-10 network control program (NCP) • 9-9 network management listener (NML) • 9-9 Network masks • 10-12 for network interfaces • 10-43 Internet address • 10-9 setting· 10-24, 10-40 Network Node Characteristics Menu • 8-2 enabling trigger booting on • 9-40 Index-29 Network node data base, VMS· 9-9 Network packets, Internet· 10-5 Network routes· 10-34 types of· 10-31 Network routing, Internet See also Internet; Internet addresses; Internet Services managing table for • 10-31 to 10-39 Networks See also Internet; Internet addresses; Internet Services Class A· 10-10 network masks for· 10-13 when to use· 10-11 Class B· 10-10 network masks for • 10-13 when to use· 10-11 Class C· 10-11 network masks for· 10-13 when to use· 10-12 classes of • 10-9 default network masks for· 10-13 number ranges for· 10-11 DECnet, reducing overhead· 9-14 Internet routing· 10-18 static routing· 10-18 packet-switched • 10-5 Networks, DECnet· 9-1 circuit connections in • 9-47 node identification in • 9-45 Network Service· 1--6, 1-15,8-1,9-1 See also DECnet nodes; Network management services Down-Line Load Service • 9-8, 9-18 to 9-44 name server for • 9-6 communication • 9-6 displaying current • 9-6 protocol for electing • 9-7 Name Service • 9-5 communication with kernel • 9-6 Network Management Service· 9-8, 9-11 to 9-18 protocols • 9-2 reducing overhead· 9-14 Remote Terminal Utility • 9-49 testing • 9-10 30-Index Network Service (Cont.) using to pass messages between nodes· 9-t3 Network services protocol (NSP). 9-2 NEW procedure· 5-3 NLALLOCATE_BUFFER procedure • 8-6, 8-34 ~lIocating message buffers with· 8-20 NIJ)ONNECT procedure' 8-6,8-34,8-36 . bonnecting Ethernet/IEEE 802 protocols with· 8-12 NLDISCONNECT procedure • 8--6, 8-35 disconnecting Ethernet/IEEE 802 protocols with· 8-13 NLGET_ATTRIBUTES procedure· 8--6 retrieving Ethernet controller attributes with • 8-10 NLGET_CONFIGURATION procedure· 8--6 retrieving CSMAlCD LAN configuration with· 8-7 NLRECEIVE procedure· 8--6,8-36 receiving messages with • 8-25 NLTRANSMIT procedure· 8--6. 8-35 transmitting messages with • 8-21 NLTRANSMIT_STATUS procedure· 8-6, 8-35 retrieving transmitted messages with, 8-23 NML (network management listener)· 9-8 NMP (network management protocol) • 9-8 Node addresses initializing at runtime· 9-13 specified with network management procedures • 9-11 Node identifier· 9-22 specified for trigger boot operations' 9-37 Node identifiers specified for down-line load operations • 9-41 Node names • 9-45 in down-line load data base • 9-21 specified with network management procedures • 9-11 VAXELN system using from VMS systems • 9-46 Node numbers • 9-45 remote, using from VAXELN systems • 9-47 VAXELN system using from VMS systems • 9-46 Nodeslocal DECnet, load requests sent to • 9-35 specifying • 9-45 Node specifications • 9-45 NSP (network services protocol) • 9-2 ntohl function • 10-53 ntons function • 10-53 o Object module library RTL, message modules in • 7-15 RTLOBJECT, message modules in • 7-15 Object modules message· 7-15 Object numbers, DECnet· ~9 Objects • 2-2 to 2-15 AREA· 2-4 creating· 4-16,5-30 definition of· 2-4 deleting • 5-46 initializing state of synchronization object for· 5-31 operations on • 2-5 satisfying a wait on • 4-3 signaling • 4-12, 5-33, 5-39 starting address of· 5-31 waiting on· 4-12,5-33, 5-39 DEVICE· 2-6 creating • 6-3 definition of· 2-4 deleting· 6-5 operations on • 2-6 satisfying a wait on • 4-3 signaling· 6-5 EVENT· 2-7,4-15,4-16 creating • 4-16 definition of· 2-4 deleting • 4-18 operations on • 2-7 satisfying a wait on· 4-3 using to synchronize access to -areas • 5-33 waiting on • 4-16 implementation of • 2-14 memory allocation for • 2-2, 2-14 MESSAGE· 2-8,5-11 creating • 5-11, 5-25 definition of· 2-4 deleting • 5-26 operations on • 2-8 shared· 5-3 NAME • 2-9, 5-13 creating· 5-13,5-25 Objects NAME (Cont.) definition of· 2-4 deleting • 5-26 operations on • 2-1 0 PORT· 2-10, 5-12 creating • 5-12, 5-25 definition of· 2-4 deleting • 5-26 operations on • 2-11 satisfying a wait on • 4-3 waiting for • 5-27 PROCESS· 2-12,4-9 to 4-10 creating • 3-15 definition of· 2-4 deleting· 3-5,3-16 naming • 3-18 operations on • 2-12 returning value of current· 3-16 satisfying a wait on • 4-3 signaling • 3-22 waiting for • 3-23, 4-9 to 4-1 0 SEMAPHORE· 2-13 creating • 4-11 definition of· 2-4 deleting • 4-14 operations on • 2-14 satisfying a wait on • 4-3 signaling· 4-12 waiting on.! 4-12 table defining • 2-3 waiting for • 6-5 Octets • 10-8 OPEN statement accessing LAT ports with· 11-35 Options, socket • 10-92 Outer-level variables· 5-1 Out-of-band characters, monitoring • 14-59 Overhead, DECnet· 9-14 p PO address space· 2-8, 3-24 after creating job • 3-4 when creating AREA objects • 2-5, 5-30 when creating M ESSAG E objects • 2-8 when passing messages • 5-12 Index-31 P1 address space • 3-26, 3-27, 7-1 after creating job • 3-4 during interprocess data sharing· 5-1 when activating subprocesses • 3-4 when terminating subprocesses· 3-5 Packets, Internet· 10-5 Padded Ethernet protocols· 8-19 Parallel 1/0· 14-73 Parallel-line interface DRB32 • 14-136 DRQ3B· 14-140 DRV11-J ·14-142 DRV11-W ·14-144 Pascal runtime library message files • 7.....17 Performance counters See LAT (local area transport) Performance data, Internet· 10-44 Performance tools See EDISPLAY utility; Error Logging Service; VAXELN Performance Utility Performance Utility See VAXELN Performance Utility Periodic network timer, stopping· 9-14 Persist timer, TCP • 10-48 Physical addresses broadcasting • 10-6, 10-7 Ethernet controller • 8-11 for trigger boot operations • 9-37 protocol for mapping Internet addresses to • 10-5 PHYSICAL_ADDRESS function· 6-13 PORT$ALLOCATE_DEVICE function ·14-116 allocating SCSI device request packets with • 14-122 description of· 0-3 Portals • 8-12, 8-14 disconnecting • 8-35 Port driver See SCSI port driver Port driver interface, SCSI· 14-116 PORT$EXIT_HANDLER function • 0-7 PORT$FREE_DEVICE function ·14-116 deallocating SCSI device request packets with • 14-122 description of • 0-1 0 PORT$INITIALlZE_CONTROLLER function ·14-116 description of • 0-13 initializing SCSI device controllers with ·14-127 32-lndex PORT$ISSUE_COMMAND function ·14-116 description of • 0-16 issuing SCSI commands with ·14-125 PORT$MAP_BUFFER function· 14-116 description of· 0-20 mapping lio request packet buffer with· 14-123 Port names • 2-9, 5-10, 5-13 creating • 5-25 local· 5-10, 13-5 remote See Terminal servers translating • 5-27 universal· 2-10,5-10,5-13,9-5,9-7,13-5 Port numbers in socket names • 10-16, 10-59 local • 10-48 privileged • 10-1 5 range of· 10-15 remote • 10-48 reserved • 10-15 PORT objects· 2-10, 5-12 See also Ports creating • 5-12, 5-25 definition of • 2-4 deleting· 5-26 operations on • 2-11 satisfying a wait on· 4-3 waiting for • 5-27 Ports ·5-10 See also PORT objects DAP, for LAT port· 11-8 DDA connecting to for disk read and write DDA operations • 14-8 connecting to for serial-line DDA operations • 14-41 for LAT port· 11-8, 11-35 dispatch· 8-13,8-15 creating • 8-34, 8-35 disconnecting • 8-36 establishing • 8-34, 8-36 waiting on ·8-36 Internet· 10-6, 10-14 privileged • 10-15 binding a process to • 10-15 LAT See LAT (local area transport) . Ports (Cont.) remote· 9-2 remote names of • 11-25 reply creating • 8-34 waiting on • ~5 waiting on • 5-27 PORT$UNMAP_BUFFER function· 14-116 description of· D-24 unmapping SCSI 1/0 request packet buffer with • 14-124 PORT values· 2-11,5-12,5-13 Power-failure recovery· 6-17 Preemptive priority scheduling • 3-9 Primary bootstrap loader • 9-36 Printer drivers· 14-29 characteristics of· 14-31 Print server • 13-9 Priorities See Job priorities; Process priorities Procedures ACCEPT_CIRCUIT accepting logical links with • 9-2 accepting messages from network nodes with· 9-3 accepting VMS connections with • 9-48 as PORT object operation. 2-12 controlling message flow with· 5-17 establishing circuits for authorization with· 12-16 establishing circuits with • 5-17 waiting for circuit connection with • 5-23 ALLOCATE_MEMORY • 3-29 CLEAR_EVENT • 4-4, 5-28 as EVENT object operation • 2-8 clearing EVENT objects with· 4-17 CONNECT_CIRCUIT ·12-5 accessing LAT ports with • 11-35, 11-41 as PORT object operation • 2-12 connecting to VMS with· 9-47 connect to a port with • 5-24 controlling message flow with· 5-17 creating logical links with • 9-2 establishing circuits for authorization with· 12-16 establishing circuits with· 5-17 establishing network node connections with • 9-3 Procedures CONNECT_CIRCUIT (Cont.) named ports used with • 5-14 setting up DDCMP communication with • 14-38 specifying DECnet object numbers with • 9-49 CREATE_AREA· 4-4, 5-28 as AREA object operation· 2-5 creating AREA objects with • 5-30 creating area semaphores with • 4-11 CREATE_AREA_EVENT • 4-4, 5-28 as area event operation • 2-5 creating area events with • 4-16 creating AREA objects with • 5-30 CREATE_AREA_SEMAPHORE • 4-4, 5-29 as area event operation • 2-5 creating AREA objects with • 5-30 creating area semaphores with • 4-11 CREATE_DEVICE as DEVICE object operation • 2-7 creating DEVICE objects with· 6-3 specifying a power-failure recovery routine with· 6-17 CREATE_EVENT • 4-4 as EVENT object operation • 2-7 creating EVENT objects with· 4-16 CREATE_JOB· 3-15 activating Down-Line Load Service with • 9-18 creating jobs with • 3-1, 3-3 CREATE_MESSAGE as MESSAGE object operation • 2-8 creating MESSAGE objects with· 5-11,5-25 setting up message communication with • 5-14 CREATE_NAME as NAME object operation • 2-10 creating NAM E objects with • 5-13, 5-25 creating universal port names with • 9-5 CREATE_PORT as PORT object operation· 2-11 creating PORT objects with • 5-12, 5-25 CREATE_PROCESS· 3-15, 4-4 as PROCESS object operation· 2-13 creating processes with • 3-2 using exit parameter with • 4-10 CREATE_SEMAPHORE • 4-4 Index-33 Procedures CREATE_SEMAPHORE (Cont.) as SEMAPHORE object operation· 2-14 creating SEMAPHORE·objects with· 4-11 CURRENT_PROCESS • 3-16, 4-5 as PROCESS object operation· 2-13 DELETE • 4-5, 5-29 as AREA object operation • 2-6 as DEVICE object operation • 2-7 as EVENT object operation • 2-8 as MESSAGE object operation· 2-9 as NAM E object operation • 2-10 as PORT object operation • 2-12 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 deleting AREA objects with • 5-46 deleting DEVICE objects with • 6-5 deleting EVENT objects with • 4-18 deleting kernel objects with • 2-2 deleting MESSAGE objects with· 5-26 deleting NAME objects with· 5-13,5-26 deleting PORT objects with· 5-12,5-26 deleting PROCESS objects with, 3-16 deleting SEMAPHORE objects with· 4-14 deleting universal port names with • 9-5 terminating processes with • 3-5 device-handling • 6-2 DISABLE_ASYNCH_EXCEPTION· 7-12 DISABLE_INTERRUPT • 6-7 DISABLE_SWITCH' 3-11,3-16 DISCONNECT_CIRCUIT as PORT object operation • 2-12 disconnecting circuits with • 5-19, 5-26 disconnecting network node connections with, 9-3 disconnecting VMS connections with • 9-48 switching DECnet software between controllers with • 9-16 terminating DDCMP communication with • 14-38 down-line load • 9-19 ELN$ADQ_INITIALIZE ·14-131 ELN$ADQ_QUEUE_READ • 14-131 ELN$ADQ_START ·14-131 ELN$ADQ_TRANSFER_DONE· 14-131 ELN$ADV-,NITIALIZE ·14-134 ELN$ADV_QUEUE_READ· 14-134 ELN$ADV_TRANSFER_DONE • 14-134 34-lndex Procedures (Cont.) ELN$ALLOCATE_STACK • 3-28 ELN$AUTH~DD_USER'12-8,12-9 ELN$AUTH_MODIFY_USER·12-8,12-11 ELN$AUTH_REMOVE_USER '12-8,12-13 ELN$AUTH_SHOW_USER '12-8, 12-14 ELN$AXV_INITIALlZE'14-132 ELN$AXV_READ· 14-133 ELN$AXV_WRITE ·14-133 ELN$BLNODE_MASK • 6-13 ELN$BLSTOP • 6-14 ELN$CANCEL_EXIT_HANDLER • 3-6 ELN$COPY_FILE' 13-11 ELN$CREATE_DIRECTORY· 13-12 ELN$CREATE_MUTEX as mutex operation • 2-18 creating mutexes with' 4-4,4-14 ELN$DEALLOCATE_STACK'3-28 ELN$DECLARE_EXIT_HANDLER • 3-6 ELN$DELETE_FILE ·13-12 ELN$DELETE_MUTEX·4-5 as mutex operation· 2-18 deleting mutexes with • 4-15 ELN$DlRECTORY_CLOSE'13-13 ELN$DIRECTORY_LlST ·13-13 ELN$DIRECTORY_OPEN ·13-13 ELN$DISK_READ • 14-7 reading data from local disks with • 14-9 ELN$DISK_WRITE ·14-7 writing data to local disks with • 14-9 ELN$DISMOUNT_TAPE_VOLUME· 13-18 ELN$DISMOUNT_VOLUME'13-16 ELN$DLL_CLEAR_LlNE· 9-19 clearing data base line entries with • 9-29 ELN$DLL_CLEAR_NODE· 9-19 clearing data base node entries with • 9-22 ELN$DLL_GET_LlNE· 9-19 getting data base line information with • 9-29, 9-30 ELN$DLL_GET_NODE· 9-19 getting data base node information with • 9-22, 9-24 ELN$DLL_LOAD • 9-19 down-line loading with • 9-41 ELN$DLL_SET_LlNE· 9-19 setting data base line entries with, 9-29 ELN$DLL_SET_NODE • 9-19 setting data base node entries with • 9-22 Procedures (Cont.) ELN$DLL_TRIGGER· 9-19 trigger booting with • 9-36, 9-37 ELN$DLV_INITIALlZE· 14-136 ELN$DLV_READ_BLOCK ·14-136 ELN$DLV_READ_STRING· 14-136 ELN$DLV_WRITE_STRING· 14-136 ELN$DRB_FINISHED_TRANSFER·14-138 ELN$DRB_INITIALlZE· 14-138 ELN$DRB_QUEUE_READ· 14-138 ELN$DRB_QUEUE_WRITE· 14-139 ELN$DRB_READ_CTRL·14-139 ELN$DRB_WRITE_CTRL ·14-139 ELN$DRQ3B_INITIALlZE· 14-141 ELN$DRQ3B_QUEUE_READ· 14-141 ELN$DRQ3B_QUEUE_WRITE ·14-141 ELN$DRQ3B_READ_FUNCTION ·14-141 ELN$DRQ3B_TRANSFER_DONE_READ· 14-141 ELN$DRQ3B_TRANSFER_DONE_WRITE • 14-141 ELN$DRQ3B_WRITE_FUNCTION ·14-141 ELN$DRV_DMA-'NITIALIZE ·14-145 ELN$DRV_DMA_QUEUE_READ ·14-145 ELN$DRV_DMA_QUEUE_WRITE'14-145 ELN$DRV_DMA_READ_STATUS ·14-145 ELN$DRV_DMA_TRANSFER_DONE ·14-145 ELN$DRV_DMA_WRITE_FUNCTION ·14-145 ELN$DRV_INITIALlZE· 14-143 ELN$DRV_READ· 14-143 ELN$DRV_WRITE· 14-143 ELN$GET_STATUS_TEXT· 7-21 ELN$INET_CHECK_ROUTE ·10-31 checking status of routing table entries with • 10-34 ELN$INET_DELETE_ARP_ENTRY • 10-25 ELN$INET_DELETE_ROUTE • 10-31 ELN$INET_FIND_ARP_ENTRY ·10-25 retrieving Ethernet addresses with • 10-27 ELN$INET_SET_ARP_ENTRY ·10-25 adding entries to ARP cache with • 10-26 deleting ARP cache entries with • 10-26 ELN$INET_SET_INTERFACE • 10-40 setting network interfaces with • 10-40 ELN$INET_SET_ROUTE ·10-31 adding entries to routing table with • 10-31 deleting routing table entries with • 10-31 ELN$INET_SHOW_ARP_ENTRIES ·10-25 Procedures ELN$INET_SHOW_ARP_ENTRI ES (Cont.) retrieving ARP entries with • 10-28 ELN$INET_SHOW_CONNECTIONS retrieving TCP connection data with • 10-48 ELN$INET_SHOW-,NTERFACE· 10-40 retrieving characteristics for network interfaces with • 10-42 ELN$INET_SHOW-,P_STATISTICS ·10-44 retrieving IP statistics with • 10-46 ELN$INET_SHOW_ROUTES ·10-31 retrieving routing table entries with • 10-37 ELN$INET_SHOW_TCP_STATISTICS ·10-44 retrieving TCP statistics with • 10-46 ELN$INET_SHOW_UDP_STATISTICS· 10-44 retrieving UDP statistics with· 10-46 ELN$INITIALlZE_AREA_LOCK • 5-29 as area lock variable operation • 2-17 initializing area lock variables with • 5-40 ELN$INIT_TAPE_VOLUME ·13-18 ELN$INIT_VOLUME ·12-20,13-16 ELN$KWV_INITIALlZE· 14-151 ELN$KWV_READ ·14-151 ELN$KWV_WRITE ·14-151 ELN$LAT_CLEAR_COUNTERS ·11-6 initializing LAT counters with • 11-28 ELN$LAT_CONNECT_PORT· 11-11 connecting LAT port to device port with· 11-42 ELN$LAT_CREATE_PORT· 11-6 creating application with • 11-40 creating dedicated LAT ports with • 11-34 creating LAT ports with· 11-8 ELN$LAT_CREATE_SERVICE· 11-6 creating services with ·11-17,11-34 ELN$LAT_DELETE_PORT • 11-6 ELN$LAT_DELETE_SERVICE· 11-6 deleting services with • 11-17 ELN$LAT_DISCONNECT_PORT·11-11 disconnecting LAT connection with • 11-36, 11-42 ELN$LAT_MAP_PORT· 11-11 mapping application LAT port with ·11-41 mapping dedicated LAT port with· 11-34 ELN$LAT_SET_NODE • 11-6 setting service node characteristics with· 11-14 specifying shut-down message with· 11-22 Index-3S Procedures (Cont.) ELN$LAT_SET_PORT· 11-6 setting application LAT port with • 11-41 setting dedicated LAT port with· 11-34 ELN$LAT_SET_SERVICE • 11-6 changing service characteristics with • 11-20 ELN$LAT_SHOW_CHAR· 11-6 retrieving service node characteristics with • 11-13 ELN$LAT_SHOW_COUNTERS ·11-6 retrieving LAT counters with· 11-28 ELN$LAT_SHOW_PORT ·11-6 retrieving LAT port characteristics with • 11-23 ELN$LAT_SHOW_PORT_MAPPING ·11-11 ELN$LAT_SHOW_SERVERS ·11-7 retrieving terminal server characteristics with· 11-26 ELN$LAT_START_NODE ·11-7 activating LAT protocol with • 11-21, 11-35, 11-41 ELN$LAT_STOP_NODE ·11-7 shutting down LAT protocol with • 11-22 ELN$LAT_WAIT_FOR_CONNECTION· 11-11 requesting connection notification with • 11-35 ELN$LOAD_KA800_PROCESSOR • 3-32 ELN$LOAD_PROGRAM· 3-13 loading program images with • 3-3 ELN$LOAD_UNIBUS_MAP· 6-10 ELN$LOCK_AREA • 5-29 as area lock variable operation • 2-17 locking areas with • 5-40 ELN$LOCK_MUTEX • 4-5 as mutex operation • 2-18 locking mutexes with· 4-14 ELN$MOUNT_TAPE_VOLUME ·13-4,13-18 ELN$MOUNT_VOLUME·13-4,13-17 ELN$NETMAN_START_NETWORK· 9-11 initializing node addresses with· 9-13 stopping and starting DECnet software with • 9-14 switching DECnet software between controllers with • 9-16 ELN$NETMAN_STOP_NETWORK· 9-11 stopping and starting DECnet software with • 9-14 3S-lndex Procedures ELN$NETMAN_STOP_NETWORK (Cont.) switching DECnet software between controllers with • 9-16 ELN$NLALLOCATE_BUFFER • 8-6, 8-34 allocating message buffers with • 8-20 ELN$NLCONNECT· 8-6,8-34,8-36 connecting Ethernet/IEEE 802 protocols with· 8-12 ELN$NLDISCONNECT • 8-6, 8-35 disconnecting Ethernet/IEEE 802 protocols with· 8-13 ELN$NLGET_ATTRIBUTES· 8-6 retrieving Ethernet controller attributes with • 8-10 ELN$NLGET_CONFIGURATION • 8-6 getting line names with • 9-29 retrieving CSMAlCD LAN configuration with· 8-7 ELN$NLRECEIVE • 8-6, 8-36 receiving messages with • 8-25 ELN$NLTRANSMIT • 8-6, 8-35 transmitting messages with • 8-21 ELN$NLTRANSMIT_STATUS • 8-6, 8-35 retrieving transmitted messages with· 8-23 ELN$PROTECT_FILE· 13-14 ELN$RENAME_FILE • 13-15 ELN$SCSLCONNECT_DEVICE· 14-77 connecting to SCSI devices with· 14-83 ELN$SCSLDISCONNECT_DEVICE • 14-77 disconnecting SCSI device processes with· 14-84 ELN$SCSLFREE_CONFIG_DATA. 14-n freeing configuration data resources with· 14-82 ELN$SCSLFREE_CONTROL_PORT· 14-77 freeing source port resources with • 14-79 ELN$SCSLGET_CONFIG_DATA· 14-77 requesting SCSI bus configuration data with • 14-80 ELN$SCSLGET_CONTROL_PORTS· 14-n connecting to generic class driver with • 14-78 ELN$SCSUSSUE_COMMAND· 14-77 issuing SCSI commands with • 14-85 ELN$SCSLMAP_MESSAGE_BUFFER· 14-77 creating SCSI command message buffer with ·14-85 Procedures (Cont.) ELN$SCS,-UNMAP_MESSAGE_BUFFER • 14-77 deleting SCSI command message buffer with ·14-89 ELN$SET_DEFAULT_FILESPEC· 13-15 ELN$TTY_ASSERT_BREAK· 14-40 setting serial lines to spacing state with • 14-57 ELN$TTY_CANCEL_MODEM_EVENTS· 14-40 canceling requests for modem events with • 14--69 ELN$TTY_CANCEL_OOB_CHARACTERS· 14-40 canceling out-of-band character requests with ·14-59 ELN$TTY_GET_CHARACTERISTICS ·14-40 getting terminal characteristics with • 11-13, 11-43 retrieving modem characteristics with • 14--68 retrieving serial-line characteristics with • 14-47 ELN$TTY_READ • 14-40 reading serial-line data with • 14-48 ELN$TTY_RECE IVE_MODEM_EVENTS • 14-40 receiving modem events with • .14-69 ELN$TTY_RECEIVE_OOB_CHARACTER • 14-40 receiving out-of-band characters with • 14-59 ELN$TTY_SET_CHARACTERISTICS· 14-40 setting modem characteristics with • 14--68 setting serial-line characteristics with • 14-47 setting terminal characteristics with • 11-43 ELN$TTY_SIGNAL_MOD EM_EVENTS • 14-40 signaling modem events with • 14-69 ELN$TTY_SIGNAL_OOB_CHARACTERS· 14-40 signaling receipt of out-of-band characters with ·14-59 ELN$TTY_WRITE· 14-40 writing serial-line data with • 14-48 ELN$UNIBUS_MAP • 6-12 ELN$UNIBUS_UNMAP· 6-13 ELN$UNLOAD_PROGRAM· 3-13 ELN$UNLOCK_AREA • 5-29 as area lock variable operation • 2-17 unlocking areas with· 5-40 ELN$UNLOCK_MUTEX • 4-5 as mutex operation • 2-18 Procedures ELN$UNLOCK_MUTEX (Cont.) unlocking mutexes with· 4-15 ENABLE_ASYNCH_EXCEPTION· 7-12 ENABLE_INTERRUPT· 6-7 ENABLE_SWITCH ·3-11,3-17 EXIT· 3-17 as PROCESS object operation· 2-13 FREE_MEMORY • 3-31 GET_TIME· 4-5,4-8 INITIALIZATION_DONE ·3-12,3-18,13-19 JOB_PORT • 5-26 as PORT object operation· 2-11 KER$ALLOCATE_MAP· 6-10 KER$ALLOCATE_PATH· 6-11 KER$ALLOCATE_SYSTEM_REGION • 3-30 KER$FREE_MAP· 6-11 KER$FREE_PATH • 6-12 KER$FREE_SYSTEM_REGION • 3-31 KER$GET_JCB· 3-17 KER$GET_UPTIME· 4-5,4-8 KER$GET_USER· 3-18,12-3,12-16 KER$LOCK_DEVICE • 6-8 KER$MEMORY_SIZE • 3-31 KER$NAME_OBJECT· 3-18 as NAM E object operation • 2-1 0 KER$RAISE_PROCESS_EXCEPTION • 3-19, 7-12,7-13 KER$SET_JOB_ELIGIBILITY· 3-19 See also Tightly coupled symmetric multiprocessing in device drivers • 6-8 KER$SET_USER· 3-22,12-2,12-17 KER$UNLOCK_DEVICE • 6-8 KER$UNWIND· 7--8,7-13 KER$_ENTER_KERNEL_CONTEXT·6-14 message-passing • 9-3 MTPR· 6-10 RAISE_EXCEPTION· 7-11,7-13 RECEIVE as M ESSAG E object operation • 2-9 receiving expedited messages with • 5-16 receiving messages from network nodes with· 9-3 receiving messages with· 5-12, 5-15, 5-26 when circuit is disconnected· 5-19 RESUME· 3-19 Index-37 Procedures RESUME (Cont.) as PROCESS object operation • 2-13 SEND as MESSAGE object operation· 2-9 sending expedited messages with • 5-15 sending messages to network nodes with • 9-3 sending messages with· 5-14,5-27 when circuit is disconnected • 5-19 SET_JOB_PRIORITY· 3-20 SET_PROCESS_PRIORITY • 3-21 as PROCESS object operation· 2-13 SET_TIME • 4-5, 4-8 SIGNAL • 4-5, 5-29 as area event operation • 2--6 as area semaphore operation • 2-6 as EVENT object operation· 2-8 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 signaling AREA objects with· 5-33,5-39 signaling EVENT objects with· 4-16 signaling PROCESS objects with • 3-22 SIGNAL_DEVICE • 6-5 as DEVICE object operation· 2-7 SUSPEND • 3-22 as PROCESS object operation • 2-13 TRANSLATE_NAME as NAME object operation • 2-10 for using named message ports· 5-14 translating named ports with • 5-27 translating universal port names with • 9-5 VAXBI· 6-13 WAIT_ALL· 6-5 applied to AREA objects • 5-29, 5-33, 5-39 applied to EVENT objects • 4-16 applied to PORT objects • 5-12, 5-27 applied to PROCESS objects • 3-23 applied to SEMAPHORE objects • 4-12 as AREA object operation • 2-5 as DEVICE object operation • 2-7 as EVENT object operation • 2-7 as PORT object operation • 2-12 as PROCESS object operation· 2-13 as SEMAPHORE object operation • 2-14 signaling SEMAPHORE objects with· 4-12 specifying a time value with • 4-6 synchronizing processes with • 4-2 3S-lndex Procedures (Cont.) WAIT_ANY • 6-5 applied to AREA objects • 5-29, 5-33, 5-39 applied to EVENT objects· 4-16 applied to PORT objects· 5-12,5-27 applied to PROCESS objects • 3-23 applied to SEMAPHORE objects • 4-12 as AREA object operation· 2-5 as DEVICE object operation • 2-7 as EVENT object operation • 2-7 as PORT object operation • 2-12 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 specifying a time value with • 4-6 synchronizing processes with • 4-2 WRITE_REGISTER • 5-4, 6-9 Processes • 1-8, 3-1 See also PROCESS objects activating· 3-4 client • 10-3 communication between • 5-1 ,5-1 to 5-9 by sharing module-level data· 5-1 to 5-4 by using queues • 5-4 to 5-9 concurrent· 4-1 creating • 3-2 data passed by • 10-4 disabling switching for • 3-11, 3-16 enabling switching for· 3-11,3-17 exiting from • 3-17 multiple • 10-8 name of· 10-3 naming· 3-18 priorities of • 3-9 setting • 3-21 resuming • 3-19 returning user identity of • 3-1 scheduling of· 3-9 server • 10-3 setting user identity of • 3-22 suspending • 3-22 switching of· 3-11 synchronizing • 4-1 by time ·4-6 routines for • 4-4 using events • 4-15 using semaphores· 4-10 to 4-15 with other processes; • 4-9 to 4-10 e Processes (Cont.) terminating • 3-5 unblocking· 4-7 due to deleted event· 4-18 due to deleted semaphore· 4-14 due to signaled event • 4-16 due to signaled semaphor~· 4-11, 4-12 waiting on • 4-9 PROCESS objects • 2-12, 4-9 to 4-10 See also Processes creating • 3-15 definition of • 2-4 deleting· 3-5,3-16 naming • 3-18 operations on • 2-12 returning value of current • 3-16 satisfying a wait on • 4-3 signaling • 3-22 waiting for· 3-23, 4-9 to 4-10 Processor eligibility· 3-19 See also Tightly coupled symmetric multiprocessing Processor registers • 6-10 Process priorities· 3-9 setting • 3-21 Process scheduling· 3-9 Process states • 3-6 to 3-8 transitions between • 3-7 Process sWitching· 3-11 Process synchronization See Processes, synchronizing PROCESS values • 2-12 Productivity and performance tools See ECl utility, EDISPLAY utility; Error logging Service; lATCP utility; -Remote Terminal Utility Program arguments • 3-4 Program counter· 7-8 Program Description Menu· 9-18 Program image· 3-23 Program loader utility procedures. 3-13 Program region· 3-24 . Programs arguments of • 3-4 initializing· 3-12,3-18 routine bodies of· 3-4 Promiscuous mode· 8-17 PROTECT_FilE procedure ·13-14 Protection, system· 1-16, 12-1 Protection mask· 12-19 Protocol identification • 8-16 Protocol numbers in Internet protocol datagrams • 10-5 Protocols DAP (data access protocol) • 14-3 in communication tasks • 9-3 DDA (direct device access) • 9-3, 14-7 to 14-24, 14-39 to 14-62 reading and writing data with· 14-9, 14-48 reading data from mounted disks with· 14-15 to 14-20 reading data from unmounted disks with • 14-12 to 14-14 transferring data to system regions with • 14-20 to 14-24 Ethernet/IEEE 802 protocol that multicasts datagrams to LAN· nodes • 9-17 . Internet See Internet protocols Internet Service • 1-15 Network Service • 9-2 routing, DECnet· 9-2 Proxy access control • 12-5, 12-18 Q Queues • 5-4 to 5-9 Queue statuses, lAT port • 11-25 QUIT exception· 3-5 R RAISE_EXCEPTION procedure· 7-11,7-13 RAISE_PROCESS_EXCEPTION procedure· 3-19, 7-12, 7-13 RARP (Reverse Address Resolution Protocol) definition of • 10-6 servers • 10-6 Raw protocol type· 10-16 Raw sockets • 10-16 read function • 10-55 receiving data from sockets with • 10-70 READ_REGISTER function • 5-4, 6-9 Index-39 READ_REGISTER function (Cont.) interprocess data sharing with - 5-2 Ready state - 3-7 realloc function - 5-3 Realtime applications -1-1 Realtime clock - 14-150 Realtime device drivers -14-128 to 14-152 AD032 -14-130 ADV11-C 014-131 ADV11-0 014-133 AXV11-C 014-131 DLVJ1 014-134 DRB32 0 14-136 DR03B· 14-140 DRV11-J 014-142 DRV11-W 014-144 IEQ11-AlIEU11-A· 14-146 KWV11-C·14-150 Realtime executive See Kernel Receive errors, network interface - 10-43 RECEIVE procedure as MESSAGE object operation· 2-9 receiving expedited messages with· 5-16 receiving messages from network nodes with 9-3 receiving messages with - 5-12, 5-15, 5-26 when circuit is disconnected· 5-19 Receive queue, TCP ·10-48 recvfrom function • 10-55 receiving data from sockets with • 10-71 recv function • 10~55 receiving data from sockets with • 10-70 recvmsg function • 10-55 receiving data from sockets with • 10-71 Redirect messages, ICMp· 10-34 Reference count • 10-32, 10-37 Registers, device, reading from and writing to· 6-9 Relative pointers, in areas • 5-32 Remote nodes connecting to - 9-49 specifying 09-47 Remote port names See Terminal servers Remote ports 09-2 Remote server names , See Terminal servers 40-Index Remote Terminal Utility • 1-7, 9-49 Remote VAXELN systems, testing communication of· 9-10 Removable media flag, SCSI device-14-81, 14-113 REMOVE_ENTRY procedure • 5-4 RENAME_FILE procedure ·13-15 Reply ports • 8-34 waiting on· 8-35 RESUME procedure • 3-19 as PROCESS object operation· 2-13 Retransmit timer, TCP • 10-48 Retry count • 9-28 Reverse Address Resolution Protocol (RARP) See RARP (Reverse Address Resolution Protocol) ROM, bootstrap· 9-36 Routes, Internet· 10-18 status of • 10-37 types of • 10-31 Routine address structure, SCSI port driver interface • 14-116 Routine bodies, activating - 3-4 Routines See also Functions; Procedures executing in kernel mode - 6-14 LlB$ADDX • C-9 LlB$ADD_TIMES - C-9 LlB$ANALYZE_SDESC· C-10 LlB$CREATE_USER_VM_ZONE - C-10 LlB$CREATE_VM_ZONE· C-11 LlB$CVTDTB" C-12 LI B$CVTOTB • C-13 LlB$CVT_HTB • C-12 LlB$DELETE_VM_ZONE • C-13 LlB$EMUL 0C-14 LlB$FLTUNDER· C-15 LlB$FREE_VM_PAGE· C-15 LlB$GET_INPUT • C-16 LlB$GET_VM· C-16 LlB$GET_VM_PAGE· C-17 LlB$INT_OVER· C-18 LlB$MATCH_COND - C-19 LlB$MULTF_DELTA_TIME· C-20 LlB$MULT_DELTA_TIME - C-19 LlB$RESET_VM_ZONE· C-21 LlB$$COPY_DXDX - C-21 LlB$SCOPY_R_DX • C-21 Routines (Cont.) LlB$SIGNAL • C-22 LlB$SIG_TO_RET· C-23 LlB$STOP • C-23 LlB$SUBX • C-24 LlB$SUB_TIMES· C-24 STR$ANALYZE_SDESC. C-25 SYS$ASCTIM • C-7 SYS$GETMSG • 7-21 SYS$GETTIM • C-8 SYS$UNWIND • C-8 Routing, Internet description of • 10-18 information, protocol for returning • 10-5 setting bypass for sockets • 10-92 static • 10-18 subnetwork • 10-18 Routing algorithm • 10-19 to 10-23 addresses used in • 10-22 Routing protocol, DECnet· 9-2 Routing table • 10-19 adding entries to • 10-31 deleting entries from • 10-31 managing • 10-31 to 10-39 Routing table entries adding to routing table· 10-31 checking status of • 10-34 credit values for· 10-34 deleting from routing table· 10-31 marking for deletion • 10-32 reference count for· 10-32, 10-34, 10-37 retrieving· 10-37 setting maximum number of· 10-23 usage count for • 10-37 RTL object module library See Object module library RTLOBJECT object module library See Object module library RUN command • 3-3 activating Down-Line Load Service with • 9-18 Run state • 3-7 Runtime environment· 1-2 Runtime facilities· 1-14 Runtime libraries· 1-3, 1-6 DECwindows ·1-7,1-17 Runtime library message files • 7-16, 7-23 Runtime messages· 7-14 Runtime messages (Cont.) using with programs· 7-19 Runtime services Authorization Service· 1-16, 12-3 to 12-15 Down-Line Load Service • 9-18 Error Logging Service· 1-6 Ethernet/IEEE 802 Datagram Service· 1-6, 8-1, 8-4 File Service· 1-6, 13-1 Internet Services ·1-6, 1-15,8-1, 10-1 LAT host services· 1-6, 11-1 Name Service See Name Service Network Service· 1-6, 1-15,8-1,9-1 See also Network Service Runtime utilities See ECL utility; EDISPLAY utility; LATCP utility; VAXELN Performance Utility; Remote Terminal Utility s SO address space • ~23 allocating· 3-30 freeing· 3-31 using to transfer data ·14-7, 14-10, 14-20 to 14-24 SAPs (service access points) • 8-18 SCDRIVER disk driver • 14-2 Scheduler • 3-6 to 3-14 initializing programs for· 3-12 job and process scheduling by· 3-9 loading programs for· 3-13 multiprocessing scheduling by. 3-14 process states • 3-6 SCP (session control protocol) • 9-2 Script file, down-line load data base • 9-18 SCSI buses • 14-74 configuration data • 14-111, 14-120 requesting· 14-80 configuration tables for· 14-80, 14-111 initiator on· 14-74 target devices on • 14-74 SCS I class drivers associating with device types ·14-115 association with device types • 14-114 compiling and linking • 14-128 Index-41 SCSI class drivers (Cont.) declaring 0 14-115 defining device locks for 0 14-119 programming 014-116 to 14-127 setting up entry point for 0 14-120 starting 0 14-116 SCSI command request packets allocating 0 0-3 freeing· 0-10 mapping data buffers for 0 0-20 unmapping data buffers for 0 0-24 SCSI commands information for· 14-87 issuing 00-16 using generic class driver interface • 14-85 using port driver interface • 14-125 message buffer for • 14-85 SCSI configuration table 0 14-111 . SCSLCONNECT_DEVICE procedure 014-77 connecting to SCSI devices with ·14-83 SCSI device controllers· 14-74 SCSI device markers 014-113,14-120 SCSI devices· 14-73 allocating command request packet for 0 D-3 allocating I/O request packets for 0 14-122 characteristics of 0 14-80 configuration table for· 14-120 connecting to· 14-83 deallocating I/O request packets for 014-122 defining locks foro 14-119 descriptors for 0 14-115 1/0 req uests mappi ng data buffers for 0 14-123 unmapping data buffers for· 14-124 IDs for· 14-82 initializing • 0-13 initializing controliers· 14-127 issuing commands to 00-16 setting current connection flag for 0 14-121 to service, checking for 0 14-121 types of 0 14-81, 14-112 SCSLDISCONNECT_DEVICE procedure 0 14-77 disconnecting SCSI device processes with • 14-84 SCSI driver 014-73 See also SCSI generic class driver architecture· 14-74 class drivers· 14-111 42-lndex SCSI driver (Cont.) components of· 14-110 data structures and constants • 14-111 disk class driver· 14-73 using 0 14-76 modifying start-up module· 14-114 example of 014-114 modules, compiling and linking· 14-128 port driver 014-111 interface 0 14-116 sniffer module • 14-111 start-up module 014-111 user-defined class drivers 014-110 to 14-128 SCSLFREE_CONFIG_DATA procedure ·14-77 freeing configuration data resources with • 14-82 SCSI_FREE_CONTROL_PORT procedure 014-77 freeing source port resources with • 14-79 SCSI generic class driver See also SCSI generic class driver procedures connecting to 0 14-78 example • 14-91 to 14-11 0 message interface 0 14-77 to 14-11 0 using 014-77 to 14-110 SCSI generic class driver procedures ELN$SCSLCONNECT_DEVICE 014-77 connecting to SCSI devices with 0 14-83 ELN$SCSI_DISCONNECT_DEVICE 014-77 disconnecting SCSI device processes with 0 14-84 ELN$SCSLFREE_CONFIG_DATA 014-77 freeing configuration data resources with • 14-82 ELN$SCSLFREE_CONTROL_PORT 014-77 freeing source port resources with • 14-79 ELN$SCSLGET_CONFIG_DATA· 14-77 requesting SCSI bus configuration data with· 14-80 ELN$SCSLGET_CONTROL_PORTS· 14-77 connecting to generic class driver with • 14-78 ELN$SCSUSSUE_COMMAND· 14-77 issuing SCSI commands with • 14-85 ELN$SCSLMAP_MESSAGE_BUFFER 0 14-77 creating SCSI command message buffer with ·14-85 ELN$SCSLUNMAP_MESSAGE_BUFFER • 14-77 SCSI generic class driver procedures ELN$SCSLUNMAP_MESSAGE_BUFFER (Cont.) deleting SCSI command message buffer with ·14-89 modules for using· 14-78 SCSLGET_CONFIG_DATA procedure ·14-77 requesting SCSI bus configuration data with • 14-80 SCSLGET_CONTROL_PORTS procedure ·14-77 connecting to generic class driver with· 14-78 SCSI host adapter· 14-74 SCSUSSUE_COMMAND procedure· 14-77 issuing SCSI commands with ·14-85 SCSLMAP_MESSAGE_BUFFER procedure • 14-77 creating SCSI command message buffer with • 14-85 SCSI port driver· 14-110, 14-111 See also SCSI port driver interface functions linking· 14-128 terminating· ~7 SCSI port driver functions PORT$INITIALlZE_CONTROLLER initializing SCSI device controllers with • 14-127 SCSI port driver interface· 14-116 See also SCSI port driver interface functions routine address structure· 14-116 SCSI port driver interface functions· ~1 entry points for· 14-116 invoking • 14-117 linking • 14-128 modules for using· 14-118 PORT$ALLOCATE_DEVICE ·14-116 allocating SCSI device request packets with • 14-122 description of • ~3 PORT$EXITHANDLER • ~7 PORT$FREE_DEVICE • 14-116 deallocating SCSI device request packets with· 14-122 description of· ~1 0 PORT$INITIALlZE_CONTROLLER· 14-116 description of· ~13 PORT$ISSUE_COMMAND· 14-116 description of • ~ 16 issuing SCSI commands with· 14-125 PORT$MAP_BUFFER • 14-116 SCSI port driver interface functions PORT$MAP_BUFFER (Cont.) description of • 0-20 mapping I/O request packet buffer with • 14-123 PORT$UNMAP_BUFFER ·14-116 description of • 0-24 unmapping I/O request packet buffer with • 14-124 SCSLUNMAP_MESSAGE_BUFFER procedure· 14-77 deleting SCSI command message buffer with • 14-89 SCSI user-defined class drivers· 14-110 to 14-128 Secondary loader • 9-36, 9-41 in down-line load data base • 9-21 Security • 12-1 Segmentation • 9-5 Segmentation, message· 5-17 Segments setting maximum number of octets in • 10-24 select function • 10-55 polling sockets for I/O activity with • 10-73 Semaphore count • 4-12 SEMAPHORE objects· 2-13 See also Semaphores creating • 4-11 definition of· 2-4 deleting· 4-14 operations on • 2-14 satisfying a wait on· 4-3 signaling • 4-12 waiting on· 4-12 Semaphores • 4-1 0 to 4-15 See also SEMAPHORE objects associated with AREA objects· 5-31 binary· 4-11 example of • 4-13 optimizations of· 4-14 counting· 4-12 example of· 4-12 synchronizing job execution with • 5-41 SEMAPHORE values· 2-14,4-12 send function • 10-55 sending data to sockets with • 10-67 sendmsg function • 1 0-55 sending data to sockets with • 10-68 Index-43 SEND procedure as MESSAGE object operation - 2-9 sending expedited messages with· 5-15 sending messages to network nodes with • 9-3 sending messages with· 5-14,5-27 when circuit is disconnected - 5-19 Send queue, TCP - 10-48 sendto function - 10-55 sending data to sockets with - 10-68 Sequence numbers, TCp· 10-8, 10-48 Serial-line device drivers • 14-32 Serial lines getting characteristics of • 14-41 reading data from - 14-48 setting characteristics of • 14-41 setting to spacing state - 14-57 writing data to· 14-48 Server names See Terminal servers Servers· 10-3 See also Processes BOOTP ·10-7 DECwindows -1-17 name-9-6 communication • 9-6 displaying current - 9-6 protocol for electing - 9-7 RARP ·10-6 sample TCP • 10-84 to 10-88 sample UDP -10-77 to 10-81 terminal See Terminal servers Service Authorization -1-16, 12-3 to 12-15 Down-Line Load • 9-8, 9-18 Error Logging • 1--6 Ethernet/IEEE 802 Datagram· 1--6, 8-1 File - 1--6 Internet ·1--6, 1-15, 8-1, 10-1 LAT See LAT (local area transport) Name See Name Service Network· 1-6, 1-15, 8-1 See also Network Service Network Management· 9-8,9-11 Service access points (SAPs)· 8-18 44-lndex Service announcement messages • 11-16 See also LAT (local area transport) sending - 11-21 Service nodes See LAT (local area transport) Service ratings • 11-17 See also LAT (local area transport) overriding default of • 11-20 Service timer • 9-28 Session control protocol (SC P) • 9-2 Sessions, disconnecting LAT ·11-36, 11-42 See also LAT (local area transport) SET DEFAULT FILESPEC procedure ·13-15 SET-EXECUTOR command • 9-9 SET HOST command • 9-49 SET_JOB_ELlGIBILITY procedure· 3-19 in device drivers • 6-8 SET JOB PRIORITY procedure • 3-20 SET-MESSAGE command • 7-23 SET PROCESS PRIORITY procedure· 3-21 a-; PROCESS object operation· 2-13 setsockopt function· 10-91 setting socket characteristics with • 10-92 SET_TIME procedure. 4-5,4-8 SET_USER procedure· 3-22,12-2, 12-17 Shareable message text· 7-19,7-22,7-23 Shared data between jobs • 5-28 to 5-46 between processes - 5-1 to 5-9 unmapping • 5-46 SHOW CIRCUIT command· 9-9 SHOW DEVICES command • 9-29 SHOW EXECUTOR command· 9-10 SHOW KNOWN CIRCUIT command • 9-10 SHOW KNOWN LINE command· 9-10 SHOW NETWORK command • 9-45, 9-46, 9-47 SHOW NODE command· 9-9,9-10 Shut-down, socket - 10-75 shutdown function • 10-56 shutting down sockets with • 10-75 SIGNAL_DEVICE procedure • 6-5 as DEVICE object operation • 2-7 SIGNAL procedure· 4-5, 5-29 as area event operation • 2--6 as area semaphore operation • 2--6 as EVENT object operation • 2-8 as PROCESS object operation • 2-13 SIGNAL procedure (Cont.) as SEMAPHORE object operation • 2-14 signaling AREA objects with· 5-33,5-39 signaling EVENT objects with· 4-16 signaling PROCESS objects with • 3-22 signaling SEMAPHORE objects with· 4-12 Sliding windows, TCP • 10-8, 10-48 setting number of octets in • 10-24 Small Computer System Interface devices See SCSI devices SNAP SAP • 8-16 Sniffer module, SCSI driver· 14-111 sockaddr structure· 10-58 sockaddr_in structure ·10-58 Socket, types of • 10-57 Socket communication connectionless·10-17, 10-68, 10-71 connection-oriented • 10-16, 10-66, 10-70 in TCP applications • 10-84 to 10-91 in UDP applications • 10-77 to 10-84 Socket connections accepting • 10-65 establishing • 10-62 to 10-66 initiating • 10-62 requests for • 10-64 Socket descriptors • 10-57 Socket device descriptors • 10-60 socket function ·10-56 creating sockets with· 10-57 Socket interface functions • 10-55 Socket names • 10-16 retrieving • 10-91 Sockets accepting socket connections for • 10-65 binding names to • 10-58 blocking • 10-69, 10-73 closing • 10-76 controlling characteristics of· 10-60 creating • 10-57 datagram • 10-16 definition of ·10-15 establishing connections for • 10-62 to 10-66 getting options for • 10-93 initiating connections for • 10-62 listening on • 10-64 name structures for • 10-58 nonblocking • 10-65, 10-69, 10-73 Sockets (Cont.) pending exceptions for· 10-73 polling for VO activity • 10-73 properties of • 10-15 raw ·10-16 receiving data from • 10-70 retrieving and setting characteristics of • 10-91 sending data to • 10-66 setting characteristics of· 10-92 setting to blocking or nonblocking • 10-60 shutting down· 10-75 stream· 10-16 types of • 10-16, 10-57 using in TCP applications • 10-84 to 10-91 using in UDP applications ·10-n to 10-84 using to transfer data • 10-66 to 10-75 Source files, message· 7-15 Spacing state, setting serial lines to· 14-57 SYS$GETMSG routine· 7-21 Stack frames· 7-2 Stack pointer • 7-1 Stacks architecture of· 7-1 call frames of· 7-2 direction of growth for· 7-2 frames of· 7-2 initial· 7-1 managing • 3-27 popping data from • 7-2 pushing data onto • 7-2 unwinding • 7-13 virtual addresses for· 7-1 Stack utility procedures· 3-28 Start-up module, SCSI driver· 14-111 States, process • 3-6 to 3-8 static attribute • 5-2 Static service rating • 11-20 See also LAT (local area transport) Status codes· 7-13 Status values • A-1 See also Exceptions; Status codes STR$ emulation routines • 0-25 STR$ANALYZE_SDESC routine • 0-25 Stream-based communication • 10-7 Stream protocol type • 10-16 Stream sockets • 10-16 String runtime library message files· 7-17 Subnet masks • 10-18 Index-45 Subnet routing· 10-18 Subnetworks ·10-10 Subprocesses See Processes SUSPEND procedure • 3-22 as PROCESS object operation • 2-13 Suspend state· 3-7 Symbols, message· 7-15, 7-19 Symmetric multiprocessing See Multiprocessing Synchronization· 4-1 by time· 4-6 by waiting on process completion • 4-9 routines for • 4-4 using wait procedures for • 4-2 with events • 4-15 with mutexes· 4-14 with other processes • 4-3, 4-9 to 4-1 0 with semaphores • 4-10 to 4-15 Synchronous exceptions • 7-4 SYS$ASCTIM routine • C-7 SYS$GETMSG system service· 7-14 SYS$GETIIM routine • C-8 System Builder creating jobs with • 3-3 loading program images with • 3-3 menus See System Builder menus setting terminal characteristics with • 14-41 System Builder menus Device Description • 8-2 Internet Characteristics • 10-23 Internet Network Description • 10-23 Main· 10-23 Network Node Characteristics • 8-2 enabling trigger booting on • 9-40 Program Description· 9-18 System Characteristics enabling down-line loading on • 9-44 System Characteristics Menu enabling down-line loading on • 9-44 System images· 1-1, 1-3 components of· 1-4 down-line loading· 9-41 in down-line load data base • 9-21 loading into KA800 processor • 3-32 memory mapping of· 3-23 46-lndex System images (Cont.) specified for down-line load operations • 9-40 System-level routines • 6-9 to 6-10 System region • 3-23 allocating· 3-30 freeing· 3-31 using to transfer data ·14-7, 14-10, 14-20 to 14-24 System service emulation routines· C-7 System service runtime message files • 7-17 System services, $GETMSG· 7-14 System time, setting and getting • 4-8 SYS$UNWIND routine • C-8 T Tape devices • 14-28 Tape driver ·14-27 error recovery· 14-29 features • 14-28 interface to File Service • 14-28 power-failure recovery of· 14-29 tape specifications • 14-28 Tape File Service· 1-16, 13-1 using to interface with tape drivers· 13-19 utility procedures provided by· 13-17 Tape utility procedures • 13-4, 13-17 to 13-18 Target devices, SCSI· 14-74 Target-initiated load requests • 9-35 figure of • 9-35 load sequence for • 9-36 TCP (Transmission Control Protocol) • 10-4 characteristics, setting • 10-24 characteristics of· 10-8 circuits • 10-7 connection data, retrieving • 10-48 description of· 10-7 functions of· 10-7 returning statistics for· 10-45 sample client • 10-88 to 10-91 sample server· 10-84 to 10-88 socket communication example • 10-84 to 10-91 urgent messages • 10-48 Terminal characteristics • 14-41 getting· 11-43, 14-41 setting • 11-43, 14-41 Terminal drivers • 14-32 Terminal drivers (Cont.) ANSI control sequences -14--65 characteristics of - 14-41 DDA interface for • 14-39 to 14--02 line terminators • 14-36 monitoring modem events with· 14-69 monitoring out-of-band characters with • 14-59 reading and writing data with· 14-48 retrieving terminal characteristics with • 14-41 setting spacing state with • 14-57 setting terminal characteristics with • 14-41 setting up DDCMP communication with • 14-36 synchronizing • 14-35 terminal I/O - 14-35 type-ahead buffer - 14-35 using control characters with • 14-62 using escape sequences with • 14-64 using modem control with· 14--66 Terminal emulators - 1-17 Terminal servers· 1-15, 11-1 See also LAT (local area transport) characteristics record for • 11-25 groups ·11-15 names of • 11-25 ports on • 11-25 retrieving characteristics of • 11-25 waiting for connection from LAT port. 11-35 Terminal utility procedures • 14-40 ELN$TTY_ASSERT_BREAK setting serial lines to spacing state with • 14-57 ELN$TTY_CANCEL_MODEM_EVENTS canceling requests for modem events with • 14-69 ELN$TTY_CANCEL_OOB_CHARACTERS canceling out-ot-band character requests with· 14-59 ELN$TTY_GET_CHARACTERISTICS· 11-43 retrieving modem characteristics with • 14--68 retrieving serial-line characteristics with • 14-47 ELN$TTY_READ reading serial-line data with • 14-48 ELN$TTY_RECEIVE_MODEM_EVENTS receiving modem events with • 14-69 ELN$TTY_RECEIVE_OOB_CHARACTER receiving out-ot-band characters with • 14-59 Terminal utility procedures (Cont.) ELN$TTY_SET_CHARACTERISTICS setting modem characteristics with • 14-68 setting serial-line characteristics with • 14-47 setting terminal characteristics with· 11-43 ELN$TTY_SIGNAL_MODEM_EVENTS signaling modem events with • 14--09 ELN$TTY_SIGNAL_OOB_CHARACTERS signaling receipt of out-of-band characters with ·14-59 ELN$TTY_WRITE writing serial-line data with· 14-48 Tertiary loader • 9-36, 9-41 in down-line load data base • ~21 Tightly coupled symmetric multiprocessing • 1-11 See also Multiprocessing returning a JCB address during • 3-17 scheduling for· 3-14 setting processor eligibility during • 3-19, 6-8 synchronizing access to device communication region for • 6-8 Time setting and getting • 4-8 specifying absolute • 4-2 specifying interval of - 4-2 waiting for an absolute· 4-6 waiting for an interval of • 4-6 Timeout in WAIT procedures • 4-2 waiting on • 4-6 Timer keep-alive, TCP • 10-49 linger, TCP • 10-49 persist, TCp· 10-48 retransmit, TCP • 10-48 Time record· 4-6 Time representation routines· 4-8 timeval structure • 10-74 Trailer datagrams ·10-43 TRANSLATE_NAME procedure as NAM E object operation • 2-10 for using named message ports • 5-14 translating named ports with • 5-27 translating universal port names with • ~5 Transmission Control Protocol (TCP) See TCP (Transmission Control Protocol) Transmit errors, network interface· 10-43 Index-47 Trigger booting • 9-18, 9-36 to 9-40 enabling 0 9-40 example of • 9-38 Trigger boot requests • 9-36 figure of • 9-37 overriding load request with • 9-41 TTY_ASSERT_BREAK procedure ·14-40 setting serial lines to spacing state with • 14-57 TTY_CANCEL_MODEM_EVENTS procedure 0 14-40 canceling requests for modem events with • 14-69 TTY_CANCEL_OOB_CHARACTERS procedure· 14-40 canceling out-of-band character requests with· 14-59 TTY_GET_CHARACTERISTICS procedure ·14-40 retrieving modem characteristics with • 14-68 retrieving serial-line characteristics with· 14-47 TTY_READ procedure 0 14-40 reading serial-line data with • 14-48 TTY_RECEIVE_MODEM_EVENTS procedure· 14-40 receiving modem events with· 14-69 TTY_RECEIVE_OOB_CHARACTER procedure· 14-40 receiving out-of-band characters with· 14-59 TTY_SET_CHARACTERISTICS procedure· 14-40 setting modem characteristics with • 14-68 setting serial-line characteristics with 0 14-47 TTY_SIGNAL_MODEM_EVENTS procedure· 14-40 signaling modem events with 014-69 TTY_SIGNAL_OOB_CHARACTERS procedure· 14-40 signaling receipt of out-of-band characters with· 14-59 TTY_WRITE procedure • 14-40 writing seriaHine data with 0 14-48 u UDP (User Datagram Protocol) 010-4 characteristics • 10-6 description of· 10-6 reliability of • 10-6 returning statistics for • 10-45 sample client • 10-82 to 10-84 sample server ·10-77 to 10-81 socket communication example· 10-77 to 10-84 48-lndex UIC (user identification code) 012-2, 12-19 UNIBUS_MAP procedure· 6-12 UNIBUS_UNMAP procedure· 6-13 Universal name service stopping· 9-14 Universal name table ensuring integrity of • 9-8 managing • 9-5, 9-6 Universal port names· 2-10, 5-10, 5-13, 9-5,9-7, 13-5 See also Local port names creating • 5-25 creation of • 9-6 deletion of • 9-7 managing • 9-5 scope of • 9-6 translation of· 9-7 UNLOAD_PROGRAM procedure • 3-13 UNLOCK_AREA procedure • 5-29 as area lock variable operation· 2-17 unlocking areas with • 5-40 UNLOCK_DEVICE procedure 0 6-8 UNLOCK_MUTEX procedure • 4-5 as mutex operation 0 2-18 unlocking mutexes with· 4-15 Unmounted disks reading from ·14-12 to 14-14 Unwind exception condition • 7-9 Unwind operations· 7-8 special cases of • 7-8 UNWIND procedure • 7-8, 7-13 Urgent messages, TCp· 10-48 Usage count • 10-37 User Datagram Protocol (UDP) See UDP (User Datagram Protocol) User name 0 12-2 Utilities See ECL utility; EDISPLAY utility; LATCP utility; VAXELN Performance Utility; Remote Terminal Utility v Valid data flag, SCSI device 014-80,14-112 Values AREA· 2-5 AREA_LOCK_VARIABLE 02-16 Values (Cont.) DEVICE· 2-6 EVENT· 2-7 MESSAGE· 2-8,5-14 NAME· 2-10,5-13 PORT· 2-11, 5-12, 5-13 PROCESS· 2-12 SEMAPHORE· 2-14,4-12 Variables, shared· 5-1 VAXBI bus device-handling procedures· 6-13 vaxc$get_sdc function • 10-56 vaxc$sockeCcontrol function ·10-56 VAXElN Command language (ECl) Utility • 1-7 See also ECl commands as LAT host service· 11-2 VAXElN debugger See Debugger VAXElN DECnet systems managing, from VMS systems· 9-9 testing Network Service for • 9-10 VAXElN DECwindows software See DECwindows software VAXElN Display Utility • 1-7 VAXElN Down-Line load Service See Down-Line load Service VAXElN Internet Services See Internet Services VAXElN Kernel See Kernel VAXElN Name Service See Name Service VAXElN Network Management Service See Network Management Service VAXElN Network Service See Network Service VAXElN Pascal system data types· 2-2 VAXElN Performance Utility • 1-7 VAXElN programming concepts ·1-7 VAXElN runtime libraries See Libraries VAXElN runtime messages See Runtime messages VAXElN SCSI driver See SCSI driver VAXElN service nodes See LAT (local area transport) VAXElN systems ·1-1,1-3 VAXElN systems (Cont.) accepting connections on • 9-48 components of • 1-4 down-line loading • 9-41 managing from VMS system • 9-9 memory mapping of· 3-23 multinode· 9-1 node names for using from VMS systems • 9-46 node numbers for using from VMS systems • 9-46 protecting • 1-16 requesting connections from • 9-47 specified for down-line load operations • 9-40 testing communication of remote· 9-10 testing Network Service for • 9-10 that communicate with VMS nodes • 9-44 using remote node numbers from • 9-47 VAXElN utilities See ECl utility; EDISPlAY utility; lATCP utility; VAXElN Performance Utility; Remote Terminal Utility vaxc$get_sdc function returning socket device descriptors with • 10-60 vaxc$socket_control function setting socket characteristics with • 10-60 VAX stack architecture· 7-1 Virtual address space • 3-23 Virtual circuits See Circuits Virtual-memory driver • 14-24 VMS emulation routines· C-1 calling· C-4 LlB$ADDX • C-9 LlB$ADD_TIMES • C-9 LlB$ANAlYZE_SDESC· C-10 LlB$CREATE_USER_VM_ZONE· C-10 LlB$CREATE_VM_ZONE· C-11 LlB$CVTDTB • C-12 LlB$CVTOTB • C-13 LlB$CVT_HTB· C-12 LlB$DElETE_VM_ZONE • C-13 LlB$EMUl· C-14 LlB$FlTUNDER· C-15 LlB$FREE_VM_PAGE· C-15 LlB$GET_INPUT • C-16 LlB$GET_VM· C-16 LlB$GET_VM_PAGE· C-17 Index-49 VMS emulation routines (Cont.) LlB$INT_OVER· C-18 LlB$MATCH_COND • C-19 LlB$MULTF_DELTA_TIME· C-20 LlB$MULT_DELTA_TIME· C-19 LlB$RESET_ VM_ZONE • C-21 LlB$SCOPY_DXDX • C-21 LlB$SCOPY_R_DX • C-21 LlB$SIGNAL • C-22 LlB$SIG_TO_RET· C-23 LlB$STOP • C-23 LlB$SUBX • C-24 LlB$SUB_TIMES· C-24 STR$ANALYZE_SDESC· C-25 summary of· C-1 SYS$ASCTIM • C-7 SYS$GETIIM • C-8 SYS$UNWIND • C-8 VMS file-handling operations • 13-10 VMS Message Utility· 7-14 VMS network 110 • 9-45 VMS nodes accepting connections on· 9-48 communicating with· 9-44 requesting connections from • 9-48 Volume names ·13-3 in file specifications • 13-5 w WAIT_ALL procedure • 6-5 applied to AREA objects • 5-29, 5-33, 5-39 applied to EVENT objects • 4-16 applied to PORT objects· 5-12, 5-27 applied to PROCESS objects • 3-23 applied to SEMAPHORE objects. 4-12 as AREA object operation • 2-5 as DEVICE object operation • 2-7 as EVENT object' operation· 2-7 as PORT object operation· 2-12 as PROCESS object operation· 2-:-13 as SEMAPHORE Object operation • 2-14 specifying a time value with • 4-6 synchronizing processes with • 4-2 WAIT_ANY procedure • 6-5 applied to AREA objects • 5-29, 5-33, 5-39 applied to EVENT objects • 4-16 50-Index WAIT_ANY procedure (Cont.) applied to PORT objects· 5-12,5-27 applied to PROCESS objects· 3-23 applied to SEMAPHORE objects • 4-12 as AREA object operation • 2-5 as DEVICE object operation· 2-7 as EVENT object operation • 2-7 as PORT object operation • 2-12 as PROCESS object operation· 2-13 as SEMAPHORE object operation· 2-14 specifying a time value with • 4-6 synchronizing processes with • 4-2 Waiting· 3-23,4-2 for a DEVICE Object· 2-7, 6-5 for an AREA object • 2-5 for an EVENT object • 2-7 for a PORT object· 2-12 for a PROCESS object· 2-13,4-9 to 4-10 for a SEMAPHORE object· 2-14 for a specified time • 4-6 for processes • 4-9 on events • 4-15 on semaphores· 4-10 to 4-15 Wait state • 3-7 Warning status codes • 7-14 Wildcards in calls to down-line load procedures • 9-22 in calls to Down-Line Load Service procedures • 9-24,9-29,9-30 in calls to ELN$INET_SHOW_INTERFACE procedure • 10-42 Window Manager • 1-17 Windows, sliding • 10-48 write function • 10-56 sending data to sockets with • 10-66 WRITE_REGISTER procedure· 5-4, 6-9 interprocess data sharing with • 5-2 x XBDRIVER datalink driver· 8-2 XEDRIVER datalink driver • 8-2 XQDRIVER datalink driver • 8-2 z ZERO EXECUTOR command· 9-10 ZERO KNOWN CIRCUIT command· 9-10 ZERO KNOWN LINE command • 9-10 ZERO NODE command· 9-10 Index-51 HOW TO ORDER ADDITIONAL DOCUMENTATION From Call Write Alaska, Hawaii, or New Hampshire 603-884-6660 Digital Equipment Corporation P.O. Box CS2008 Nashua NH 03061 Rest of U.S.A and Puerto Rico l 800-DIGITAL lPrepaid orders from Puerto Rico, call Digitars local subsidiary (809-754-7575) Canada 800-267-6219 (for software documentation) Digital Equipment of Canada Ltd. 100 Herzberg Road Kanata, Ontario, Canada K2K 2A6 Attn: Direct Order Desk 613-592-5111 (for hardware documentation) Internal orders (for software documentation) DTN: 241-3023 508-874-3023 Software Supply Business (SSB) Digital Equipment Corporation Westminster MA 01473 Internal orders (for hardware documentation) DTN: 234-4323 508-351-4323 Publishing & Circulation Services (P&CS) NR03-1IW3 Digital Equipment Corporation Northboro MA 01532 Reader's Comments VAXELN Runtime Facilities Guide AA-JM81 E-TE Your comments and suggestions will help us improve the quality of our future documentation. Please note that this form is for comments on documentation only. I rate this manual's: Excellent Accuracy (product works as described) 0 Completeness (enough information) 0 Clarity (easy to understand) 0 Organization (structure of subject matter) 0 Figures (useful) 0 Examples (useful) 0 Index (ability to find topic) 0 Page layout (easy to find information) 0 Fair Good 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 What I like best about this manual: What I like least about this manual: My additional comments or suggestions for improving this manual: I found the following errors in this manual: Page Description Please indicate the type of user/reader that you most nearly represent: o Administrative Support o Computer Operator o EducatorlTrainer o Programmer/Analyst o Sales Name!I'itle o ScientistiEngineer o Software Support o System Manager o Other (please specify) Dept. Company Date Mailing Address Phone 10/87 Poor 0 0 0 0 0 0 0 0 Do Not Tear - Fold Here and Tape - - - - - - - - - - - - - - - - - - - NO POSTAGE NECESSARY IF MAILED IN THE UNITED STATES BUSINESS REPL V MAIL FIRST CLASS PERMIT NO.33 MAYNARD MASS. POSTAGE WILL BE PAID BY ADDRESSEE DIGITAL EQUIPMENT CORPORATION CORPORATE USER PUBLICATIONS PK03-1/D30 129 PARKER STREET MAYNARD, MA 01754-2198 111'"111111 ••• 1.1.1 •• 1"11.1"1.1"1".1.1.1 ••• 11.1 Do Not Tear - Fold Here
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : No XMP Toolkit : Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 Create Date : 2014:09:27 18:33:55-08:00 Modify Date : 2014:09:27 18:02:09-07:00 Metadata Date : 2014:09:27 18:02:09-07:00 Producer : Adobe Acrobat 9.55 Paper Capture Plug-in Format : application/pdf Document ID : uuid:1b1bb425-4d46-4442-903f-41df3c26cbca Instance ID : uuid:07d48dfc-20ea-914d-a5b1-38bc8cde526e Page Layout : SinglePage Page Mode : UseNone Page Count : 790EXIF Metadata provided by EXIF.tools