Elf Documentation July 10, 1974 ELF SYSTEM DOCUMENTATION Page 2 ELF System Structure I.2 Organization of the ELF System The ELF system has a hierarchical structure. At the center of the system exists a set of modules, collectively referred to as the kernel, which perform tasks of resource management in a multi-processing environment. The kernel provides a set of primitive calls for outer-level procedures, performing such tasks as the creation of processes, process synchronization, storage allocation, and sharing of an interval timer. System Procedures outside of the kernel perform tasks such as the interpretation of user requests at terminals (the EXEC), controlling communication with the ARPANET (the Network Control Program)), and maintenance of the system file structure. Kernel primitives fall in three categories: Processor Management, Storage Management, and Input/Output Management. Processor management primitives allow processes to be created, vie for processor service, intercommunicate, or be terminated. Storage Management Primitives control the allocation of storage within an address space; when the PDP-11 memory management option is present, storage management primitives control the mapping between a process' address space and physical storage. In this case, storage management primitives allow the creation of a set of virtual address spaces, and perform tasks of storage allocation within each address space. Input/Output primitives control the management of I/O devices, scheduling device requests performed by calling processes, and performing the address-mapping tasks necessary when the virtual storage capability is present. Kernel procedures reside in a fixed area of physical storage, and are distinguished by the fact that the PDP-11 processor runs in privileged, or "kernel" mode (on 11/40 or /45). This provides a protection scheme, under which outer-level procedures may be debugged without destroying the ELF environment. The EXEC consists of a set of modules which interpret commands received from user's terminals, and allow users to access facilities available on the network. If the memory management option is installed, the EXEC procedures reside in a unique address space. Additional EXEC commands then allow a user to create a new address space, cause programs to be loaded into the address space from a server on the network, and start a local process within that address space. The Network Control Program (NCP) allows processes running in the ELF system to establish data-paths, or "connections" to ELF SYSTEM DOCUMENTATION Page 3 ELF System Structure processes running in local or remote processors on the network. The NCP provides the set of "third-level" protocol primitives to local processes, such as CONNECT, LISTEN, CLISE, etc. In addition to these, local processes may make calls to the NCP to follow the standard Server- or User- Initial Connection Protocol. The storage management facilities which are included in the kernel, coupled with PDP 11/40 or /45 memory management hardware, make possible the addition of new facilities for checkout of programs within the system framework. This is the means by which higher-level network protocols may be developed, or supervisory tasks of peripheral signal processors may be performed, in a way which allows effective utilization of network resources. The ELF system is written in MACRO-11 Assembly language. The system is composed of a number of logically independent modules, which are separately compiled and bound to form a single loadable file. Support software for system development exists at various PDP-10 sites on the ARPANET. Compatibility exists for using various other languages, such as BCPL or BLISS-11, in making extensions of the system. Hardware required for the ELF varies, according to desired system capability. The minimal amount necessary to support the ELF kernel and NCP is 12K. For terminal access to the net, and the ability to obtain listings (provided a line-printer is attached) 16K is required. Either of these tasks would be adequately supported by a PDP-11/10, or larger, processor. Additional system flexibility is gained when the processor is a PDP-11/40 or /45 with the memory management option. In this configuration, it is recommended that the system have 32K of memory. The existence of secondary storage on the ELF is not a basic requirement. It is useful in the case of systems having virtual storage, to allow automatic swapping of pages from main storage. It should be emphasized that the presence of disk storage is not mandatory in virtually addressed systems; the lack of secondary storage simply prevents automatic replacement of pages in main storage, while the protection and relocation features of the memory management hardware are still utilized. I/O devices supported under the ELF system are Dectape, fixed-head disk (RF-11), removable cartridge and disk pack (RK05 and RP03), DEC line printers, and the various line controllers and multiplexors. ELF SYSTEM DOCUMENTATION Page 4 ELF KERNEL -- INTRODUCTION II.1 The ELF Kernel -- An Introduction This chapter describes the portion of the ELF system which performs resource management tasks necessary to support a multiprocessing environment. This section, referred to as the kernel, concerns itself with three primary areas. The first of these, Processor Management, controls distribution of the PDP-11 processor among a number of processes, and provides means by which processes may synchronize and allocate resources. The second major portion of the kernel is Storage Management, which handles the allocaton of primary, secondary, and virtual storage available to processes in the system. The third portion, I/O Management, controls the interaction between processes and external devices (I/O devices), and additionally provides means for communication of data between processes. II.1.1 Processor Management Techniques The kernel provides of a set of system calls, or "primitives", which allow processes to be created, vie for processor service according to priority, inter-communicate, and be terminated. The term process used here describes an autonomous sequence of states brought about by the PDP-11 processor. In the ELF system, a process is characterized by a virtual program-counter, a set of general-purpose registers, a stack, and process-owned storage areas. Processes are given control of the processor by a single controlling program, called the scheduler. Processes are said to be in a "ready" or "waiting" state. They are created in the ready state, and remain ready until they explicitly block themselves by calling a system primitive for synchronization or resource allocation. II.1.1.1 Process Synchronization Each system process has an associated input queue, which consists of a list of "messages" sent to it by other processes. A "message" in this case is a 24-bit field which is fetched from the input queue when the process WAITs, and is placed on its input queue by some other process which invokes the SIGNAL primitive. The process may be thus viewed as a machine which interprets instructions fetched by means of the WAIT primitive. Processes enter the waiting state if they WAIT and their input queue is empty; they enter the ready state when an entry is placed on their input queue by the SIGNAL primitive. When a process awakens, it receives the 24-bit message in addition to the 8-bit name (process ID) of the process which SIGNALled it. In general, the 24-bit message field is interpreted by ELF system processes as an 8-bit op-code and a 16-bit data field. While this assignment of bits is a convention for system processes, higher-level (user) processes ELF SYSTEM DOCUMENTATION Page 5 ELF KERNEL -- INTRODUCTION which choose to inter-communicate using SIGNAL and WAIT may use this field arbitrarily. II.1.1.2 Processor Scheduling Internal system tables reflect the state of a process, and control its priority for processor service, relative to other processes in the system. The ability of a process to gain control of the processor is a function of the priority queue in which is runs, and its order within that queue. The priority queue in which the process resides is determined when that process is created. The priority of a process within its queue is determined according to its behavior; it is re-evaluated at a regular interval, and its value is inversely proportional to the demand made by the process for processor service over the interval. II.1.1.3 Protection Mechanisms Because processes rely on the validity of messages received on their input queues, a protection scheme is required to prevent processes from receiving messages from other non-authorized processes. This mechanism is implemented by means of a ring structure, in which each process has a "capability level", determined as a function of its current processor mode (i.e., kernel/user) and a capability variable associated with the process. The capability variable is assigned when the process is created, and may change as the process makes calls to various procedures in the operating system. The "capability level" of the process evaluates to 0 if the process is in kernel mode, or to the value of its capability variable if in user mode. The access rights of a process executing at a given capability level are a subset of rights given at lower levels. II.1.1.4 Resource Allocation Techniques Processes request allocation of system resources by means of binary semaphores. Kernel primitives allow dynamic assignment of semaphore names, and provide Dijkstra's P and V operations on those semaphores. The P primitive is used by a process to obtain ownership of a resource, which is identified by a specified semaphore name (an 8-bit code). The process is placed in a waiting state in the event that it requests a resource which is owned by another process; it awakens when the other process relinquishes the resource by means of the V primitive. When a process remains waiting for the resource, other processes may place event descriptors on its input queue; the process may fetch the queued messages from its queue once it obtains ownership of the resource. ELF SYSTEM DOCUMENTATION Page 6 ELF KERNEL -- INTRODUCTION Two additional primitives exist for utilization of semaphores. A process may request notification of ownership of a resource by means of the REQUEST primitive. The process, in this case, specifies a 24-bit message it wishes to receive when the resource is obtained. This primitive allows various permutations on Dijkstra's P primitive (such as Multiple-P) to be constructed. A second primitive, referred to as Exhaustive V (EXV), effectively V's a semaphore until there are no processes queued on the semaphore wait-list. This primitive is utilized in cases when semaphores are used for notification of a set of processes that a specified event has occurred (such as a process termination); it is usually the case that these processes have REQuested such information. ELF SYSTEM DOCUMENTATION Page 7 ELF PROCESS DEBUGGING FACILITIES The following portions of the ELF Kernel are relevant to Debugging of programs in virtual address spaces. The purpose of this note is to provide guidelines for design of the ELF debugging sub-system. I. Process Management Primitives for Debugging A. Each ELF process has four special trap vectors, each of which is associated with the PDP-11 vectors for TRAP, BPT (or trace-trap), IOT, and FPU traps. These trap vectors are set by ELF kernel primitives $SEXIT and $REXIT (set-exit, and reset-exit, respectively). $SEXIT assumes a trap vector type, a Process-id, and an op-code. Trap vector types are assigned as follows: 0: TRAP 1: BPT or trace-trap 2: IOT 3: FPU The TRAP exit is taken when a process executes the PDP-11 TRAP instruction. The BPT exit is taken when a process executes a BPT (Breakpoint) instruction, or receives a trace trap. The IOT exit is taken when a process executes the IOT instruction. The FPU exit is taken when a process receives a floating-point processor trap, when the floating point option is present on the 11/40 or 11/45. The Process-id specified when the exits are set specify the name of the process whose exits are to be set. The OP-code specifies the opcode received by the calling process when the process becomes trapped. B. When a trap condition occurs, a debugging process is signalled with the event op-code which it specified when the exits were set. The trapped process is then de-scheduled and placed in a frozen state. (The process signalled is the process which set the trap exits for the trapped process. It should be noted that only one process is signalled when the trapped process becomes frozen; the creator of the trapped process is not signalled, as would be the case if the process were frozen by means of the FREEZE-PROCESS primitive.) C. The following primitives may be used to inspect or modify the registers or PSW of the trapped process: 1. $GPREG REG -- obtains the value of a specified register; the register number is assumed in R0 and the value is returned in R1. ELF SYSTEM DOCUMENTATION Page 8 ELF PROCESS DEBUGGING FACILITIES 2. $SPREG REG,VAL -- sets the value of the specified register; the register number is assumed in R0, and the value is assumed in R1. In the above primitives, the register number is specified by the numbers 0 through 11, where 0-5 are the process' general-purpose registers, 6 is the process kernel stack pointer, 7 is the process' program counter, 10 is the PSW, and 11 is the process user stack pointer. D. The Process Control Table (PCT) for a process may be obtained by the primitive $GTPCT PID,ADDR -- where PID is the process ID of the desired PCT, and ADDR is the address of a buffer to which the PCT is to be copied (in the caller's address space). II. Storage Management Primitives for Debugging A. The $VMOV primitive is used to transfer blocks of data from one address space to another. $VMOV assumes a source and destination address space id (VSM ID, 8 bits each ), a source virtual address, a destination virtual address, and a word count. $VMOVB performs the same function as $VMOV, except a block of bytes is transferred, and a byte count is assumed. B. $VMAP maps a virtual page in one address space into a virtual page in another; the page thus becomes a "window", for examining or modifying data in another address space. ELF SYSTEM DOCUMENTATION Page 9 Storage Management II.1.2 Storage Management Techniques Based on the PDP-11's 16 bit architecture, a process may generate references to a possible 32,768 different word addresses in memory. Because there is not necessarily a one-to-one correspondence between these addresses and the process' utilization of physical memory, we say that the process has an associated 32,768-word virtual address space. An address map defines the relation between the user's virtual storage and physical storage (e.g., core, disk) addresses. A specific address map becomes associated with a process when the process is created. The address map currently in use is determined by the current processor mode (kernel or user) and the process currently running. Any number of address spaces may be defined for processes running in user mode; there is only one address space defined in kernel mode, and this is utilized for system (kernel) primitives. The processor switches from kernel mode to user mode when it gives control to a user process. It switches from user mode to kernel mode when a user process makes a system call or is interrupted. If a user process is the "sole owner" of an address map, then its address space is protected from modification by other processes. Likewise, it may not modify physical storage not contained in its own address space. When a process makes a call to a system primitive, the system performs some task as an extension of that process. Addresses are mapped according to the user's address map while the user's program is running, and are mapped according to the kernel address map when the program makes a kernel primitive call. It is the scheduler's responsibility to setup the hardware registers in the PDP-11 memory management unit according to the process' storage map. Processes may share a common virtual address space (address map); the address map to be associated with a process is assigned when the process is created. (Processes may thus share virtual storage in the same fashion as they might share physical storage.) This section describes techniques used for storage allocation in ELF systems, and particularly deals with establishment of a virtual storage structure for multiprocessing in the PDP-11/40 and PDP-11/45 systems with the memory management option. The storage management portion of the ELF kernel allows the creation of a number of independent 32,768-word virtual address spaces, and controls the mapping between virtual storage addresses and physical storage addesses. Storage is divided into 4096-word pages, and the PDP-11 memory management unit is used to perform dynamic relocation of page addresses. The mapping between virtual and physical address spaces is transparent to processes in the system; thus, storage ELF SYSTEM DOCUMENTATION Page 10 Storage Management accessed by processes in differing address spaces is completely protected. II.1.2.2 Control Tables for Storage Management Two types of tables are used in providing the virtual storage structure. The first of these is clled the Physical Storage Table (PST), and reflects the state of physial memory. The second is referred to as a Virtual Storage Map (VSM); a VSM describes the state of each virtual address space. II.1.2.2.1 The Physical Storage Table (PST) The PST is used to indicate the status of each physical page frame in core. (Pages are 4096 words in length). It is composed of three sub-tables: PST0, PST1, and PST2; each is indexed by a page frame number in physical memory. (Essentially, this is identical to a single table of 3-word entries.) Each entry in PST0, PST1, and PST2 is one word in length; the tables are physically contiguous, and resident in a locked page in kernel space. 1 7 1 7 !-----------------! PST0: Page 0 !W! Lock !A! Age ! !-----------------! 1 ! ! !- . -! 2 ! . ! !- . -! 3 ! . ! !- . -! 4 ! . ! PST0 Format, !- . -! 5 ! . ! 48K Configuration !- . -! 6 ! . ! (12 Page frames !- . -! of main storage.) 7 ! . ! !- . -! 8 ! . ! !- . -! 9 ! . ! !- . -! 10 ! . ! !- V -! 11 ! ! !-----------------! PST0 Entry Description: ELF SYSTEM DOCUMENTATION Page 11 Storage Management "W", (Bit 15), when set, indicates that the page frame has been modified. If the page is to be purged from primary storage, wht "W"-bit is tested to determine if the page has to be written on secondary storage. "Lock", (Bits 14-8), is a count specifying the number of processes currently requesting that this page be locked in core (not swapped out). This is incremented by system routines when they perform functions, such as I/O, which require that the page remain resident. The "Lock" count is incremented and decremented by the system primitives $LOCK and $UNLOCK, respectively. "A", (Bit 7) when set, indicates that the corresponding page has been accessed. It is used at certain intervals to update the "Age" field, described below. "Age", (Bits 6-0), is a 7-bit field specifying the page age, as determined by the system memory management algorithm. The page in memory with the minimum "Age" value is the one to be chosen to be purged from memory when necessary. PST1 reflects the utilization of physical storage. The high-order ("F") bit of each entry indicates that the physical page frame is free (not occupied by a virtual page). Thus memory management primitives test for negative entries in PST1 to find an unused page. When the "F" bit is zero, the low-order 11 bits contain a virtual page address (VPA). A virtual page address consists of a 3-bit page number and an 8-bit number which uniquely identifies a Virtual Storage Map (address space). Virtual Storage Maps are described in the next section. PST2 indicates the correspondence between physical (primary) storage and secondary storage. When a page is resident in memory, PST2 contains the secondary storage address to be used when the page is to be removed from memory. II.1.2.2.2 The Virtual Storage Map (VSM) A Virtual Storage Map defines the relationship between a 32K virtual address space and its utilization of physical storage. The VSM consists of two 8-word tables, each of which is indexed by the high order 3 bits of a virtual address generated by a process. (Thus, each entry in the table corresponds to a 4096-word page in the 32,768-word virtual address space.) The first 8-word table in the VSM describes the correspondence between virtual storage and primary storage (core), and also reflects the status of each page (e.g., its residency). The second 8-word table describes the correspondence between virtual storage and secondary storage. Each Virtual Storage Map (hence, each address space) is named by an 8-bit identifier, called the VSM ID. Thus, a virtual address in the system formally consists of a 24-bit number containing ELF SYSTEM DOCUMENTATION Page 12 Storage Management the 8-bit address space name (VSM ID), a 3-bit page number, and a 13-bit offset within a page. ELF SYSTEM DOCUMENTATION Page 13 ELF I/O SYSTEM -- INTRODUCTION IV. The ELF I/O System The ELF I/O system provides an interface between ELF programs (processes) and external devices, such as terminals, disks, line printers, etc. The I/O system performs the following functions: 1. Coordinates requests for physical I/O transactions among a set of ELF system processes, synchronizing the I/O requests with external devices. 2. Provides device independence, allowing processes to select a specific device by means of a "device-address". 3. Performs translation necessary in virtual memory ELF systems between virtual and physical storage address spaces. ELF processes request physical I/O transactions by means of a single system primitive, Start-I/O. The primary function of Start-I/O (SIO) is to enqueue a request specifying a transfer of data between a virtual storage address and a device address. In addition, the SIO primitive allows the transfer of data thru pseudo-devices, called "ports", which facilitate transfer of data between processes (inter-process communication). When a program requests an I/O transaction by means of SIO, it uses a control table called an I/O Request Block (IORB) to specify all parameters and addresses needed to carry out the request. While the SIO primitive makes requests for a given device, the requests are carried out according to device availability. It is the responsibility of kernel I/O management processes to fetch entries from various device request queues, and initiate device actions as devices become ready. The kernel I/O processes, called I/O Auxiliaries, or IOX's, perform all necessary translation between virtual and physical storage address space, and initiate device action by calling special-purpose procedures called "device-drivers". Device drivers perform functions relating to a particular type of device. A device driver must exist for each device which has unique programming characteristics, although more than one device of the same type is usually controlled by a single I/O device driver procedure (for example, a terminal driver may control 16 terminals). ELF devices are assigned names, or "device addresses" consisting of a generic name and a unit number. The generic name consists of 3 characters packed in RAD50 format; examples are TTY, IMP, MTA, DTA etc. The unit number consists of a 16-bit unsigned integer. In the current implementation of ELF I/O, there exists on IOX process for each generic device name. All information relating to a particular device address is centrally located in a system table called the Device Control Table, or DCT. The DCT allows complete separation of procedures ELF SYSTEM DOCUMENTATION Page 14 ELF I/O SYSTEM -- INTRODUCTION handling devices and data relating to those devices. DCT's have varying formats, depending on a distinction of device classes. Classes are assigned to character-at-a-time devices (such as terminals), byte-addressible Direct Memory Access devices (such as fixed-head disks), block addressible DMA devices (such as moving-head disks), and inter-process ports. A second system control table is used to contain information relevant to specific device interupts. This table, called the Interrupt Control Table (ICT), contains the address of the interrupt vector and the address of the corresponding interrupt service routine. Each of these tables is defined by system macro calls, which provide a set of names for the various fields contained in the control tables. An I/O device is added to the ELF system by defining an appropriate Device Control Table, Interrupt Control Table, and Device Driver procedures. The control tables are defined by means of macro calls, which generate proper table linkages according to specified macro parameters. Device drivers are linked with the set of modules which form the kernel. Drivers are reentrant, and therefore are sharable by a set of devices having equivalent characteristics. Each device in the system is assigned a device class, determined by the mode of data transfer between the device and main storage. "Character" oriented devices perform I/O on a character-at-a-time basis; transfer to this type of device is performed under control of the PDP-11 processor (usually referred to as programmed data transfer). The device driver procedures are responsible for controlling the transfer of data to or from the device. A second type of device is that which performs transfer of data to or from main storage directly under device control (Direct Memory Access, or DMA devices). In this case, one device driver procedure initiates a device action, and a second driver procedure (the interrupt handler) receives control on its completion. A third device class is the set of pseudo-devices called "Inter-Process Ports" (IPP's) which facilitate inter-process communication. Inter-Process Ports have no associated device driver; in this case, data transfers are controlled by a specific I/O Auxiliary process. Each of the above device classes has a corresponding I/O auxiliary procedure which supports a set of auxiliary processes. There exists on I/O auxiliary procedure per device class, and one auxiliary process per device name. With the above overview in mind, the following material presents a more detailed description of ELF I/O control tables, ELF SYSTEM DOCUMENTATION Page 15 ELF I/O SYSTEM -- INTRODUCTION I/O driver procedures, and I/O primitives as they appear to user processes. ELF SYSTEM DOCUMENTATION Page 16 ELF I/O Primitives IV.1 I/O Primitives for ELF Processes The following describes the ELF I/O system as it appears to ELF processes. The primitives for performing I/O-related tasks, and the necessary control tables for communicating information to the I/O primitives are discussed. ELF processes perform physical transfers of data to or from I/O devices by means of the Start-I/O ($SIO) primitive. $SIO places an I/O request on a request queue associated with a specified device, and returns control to its caller immediately. Parameters are passed to the Start-I/O primitive by means of an I/O Request Block (IORB), shown below. In the IORB, the process specifies a three-character RAD50 device name, a device unit number, an opcode with which it wishes to be signalled on completion, a buffer address, a function code, a byte count, and an optional device block number (for devices such as disks. The I/O system returns a device status code and number of bytes actually transferred upon completion of the operation. When the I/O request has been carried out, the originating process is signalled with the opcode which it specified when the request was made; in addition, the I/O system passes the address of an IORB when it signals the process. )Then, for example, the process uses the opcode to determine that an I/O operation has completed, and the IORB address specifies which request has completed. The IORB is illustrated below: NAME is the RAD50-coded name of the device, such as TTY. The UNIT is a non-zero binary number which identifies a specific unit on a given device. Thus, an I/O device in the system has a 32-bit name consisting of a device name/unit number pair. ELF SYSTEM DOCUMENTATION Page 17 ELF I/O Primitives Each I/O device in ELF has an associated request queue; entries are placed on the request queue when the process issues the SIO primitive, and are removed as requests are satisfied. Thus a process may make a number of requests, each specified by a unique IORB. The opcode field specified in the IORB indicates the opcode with which the process is to be signalled when the I/O operation completes. transferred. FUNC is a 16-bit function code to indicate a specific I/O command, such as read or write. The following device- independent codes have been assigned: 0 = No operation 1 = Read 2 = Write 3 = Special Functions The low byte of the function word is reserved for device independent codes; the high byte may be used to pass device-specific function information. BR is the number of 8-bit bytes requested to be transferred. In the case of output transfers, this is always the exact number of bytes transferred. For input transfers, this is the maximum number to be transferred; the BX field of the IORB indicates the actual number of bytes transferred when the operation is completed. STATUS is a 16-bit field whiich indicates the completing status of the I/O request. This always has bit 7 set when the operation is completed, and bit 15 set when there is an error. The remaining bits in the low byte specify device independent error classes; these consist of programming error and device error. Program errors are a result of such things as I/O requests to invalid devices. Device errors occur for reasons such as parity errors, or data over-runs. BLKH and BLKL are the high and low portions respectively, of the device block address. This field applies only to addressible devices such as disks, dectapes, and drums. (Device block sizes may vary from one device to another, and are defined when the system is generated.) ELF SYSTEM DOCUMENTATION Page 18 ELF I/O Primitives IV.1.1 Example The following subroutine reads a record from disk block 1 and writes it on Magtape unit 1 (no block number associated). IOOP = 2 ;OPCODE TO AWAIT FOR I/O RDW: $SIO IORBI ; START I/O FROM DISK $WAITS IOOP ;WAIT (SPECIFIC) FOR COMPLETION $SIO IORBO ;INIT I/O TO TAPE $WAITS IOOP ;WAIT (SPECIFIC) FOR OUTPUT RTS PC ;RETURN TO CALLER IORBI: .RAD50 'DSK' ;DISK .WORD 0 ;UNIT 0 .BYTE IOOP,0 ;OP-CODE TO BE RECEIVED .WORD BUFFER,1 ;BUFFER ADDRESS, FUNCTION = READ .WORD 128. ;128 BYTES .WORD 0,0 ;STATUS , BYTES XFERRED .WORD 0,1 IORBO: .RAD50 'MTA' ;MAG TAPE .WORD 1 ;UNIT 1 .BYTE IOOP,0 ;OP-CODE TO BE RECEIVED .WORD BUFFER,2 ;BUFFER ADDRESS, FUNCTION .WORD 128. ;128. BYTE WRITE .WORD 0,0 ;STATUS, BYTES XFERRED .WORD 0,0 ;BLOCK NUMBER (NOT USED FOR SEQ DEV) ELF SYSTEM DOCUMENTATION Page 19 DEVICE DRIVERS IV.1 ELF Device Drivers A device driver is needed to interface the kernel I/O modules and the PDP-11 device registers used in doing I/O. The device driver is called upon by an I/O auxiliary (IOX) process to do I/O calls to a device. All necessary information for the driver is passed in the Device Control Table (DCT) for the particular device. When the I/O is complete, the driver returns status information in the DCT. This status information is then passed back to the original requesting process so it can determine that the I/O was completed successfully. IV.1.1 Main Tasks of the Driver There are three tasks performed by the device driver. The task the driver performs is determined by one of three entry points. IV.1.1.1. Initialize: The first task is the intialization routine. This routine is called by an IOX with a jump subroutine, to the driver's entry point for initialization. This routine is called on the first I/O request to that device after the system is started. It performs any necessary action that is needed before the device can have I/O performed. The interrupt vector for the device is already set by the IOX, so the driver does not need to initialize it. Upon entry, register zero contains the address of the Interrupt Control Table (ICT) for that device. To return to the IOX an a RTS PC instruction is executed, by the device driver. IV.1.1.2. Transfer: The second task of the driver is to handle the requests for a transfer. The requests originate from a process issuing the $SIO primitive. Control is passed from the $SIO primitive to the IOX process handling the device. The IOX does a jump subroutine to the "transfer initialize" entry point of the device driver, passing the DCT address of the device in R0. The driver then sets up the I/O registers for the transfer. The byte count, buffer address, function, and device output address are all in the DCT. The ICT contains the address of the device status register (ICTCSR). The ICT for the interrupt vector that the driver is servicing is found by using the DCTICT entry in the DCT table. The DCTICT word contains the address of the first word of the ICT vector table corresponding to that DCT. The ICT vector table has as its first word the number of ICT addresses in the table. The following words contain an address to an ICT. If the device has only one interrupt vector, then it will only have ELF SYSTEM DOCUMENTATION Page 20 DEVICE DRIVERS one ICT and one entry in the ICT vector table. For block transfer devices, a "go" bit is usually set to start the transfer after the device registers are set. Then device interrupts are enabled and a return to the I/O auxilary is then made by a RTS PC. For character transfer devices, each character transfer is handled by an interrupt routine. Control is usually passed to the interrupt routine from the transfer initialize routine. Since the interrupt routine returns through a RTI instruction, and the transfer routine returns with a RTS instruction, the stack has to be made to look like an interrupt had happened (instead of an RTS PC). This is not necessary if the transfer of the first character is handled in the transfer initialize routine and the interrupt routine handles all subsequent characters. IV.1.1.3. Interrupts: After the transfer initialize routine has initiated the I/O, the third entry point of the driver can be entered through the device interrupt vector. Upon entry of the interrupt routine (from a device interrupt), register zero contains the address of the ICT. Also, R0 is on the top of the stack followed by the PC and PS. The address of the DCT can be found by using the address of the DCT vector table, which is in the ICTDCT word. The first word of the DCT vector table has the number of DCT addresses in the table. If the interrupt vector handles only one device, then only one DCT address will be in the table. In that case, the second word of the DCT vector table would contain the address of the DCT. For block transfer devices, the interrupt routine checks the I/O status registers for any error. If there are errors, then it specifies what kind (discussed later) in the DCTSTA word. Otherwise, it just sets the done bit in DCTSTA and returns through the I/O completion address in DCTCRA. On interrupts for character transfer devices the routine disables the device interrupts and proceeds with the set-up for the next character transfer. Any errors must be checked for, and appropriate action taken. An error code may be returned by the driver in DCTSTA and the number of bytes successfully transferred in DCTBX. If no errors occured on the last character and the transfer isn't complete, then the routine can continue with the transfer by enabling device interrupts and doing a RTI instruction. When the I/O is complete, an interrupt will occur. When the whole transfer is complete and errors checked for, the DCTSTA, DCTBX and other appropriate DCT entries should be updated. Driver interrupt routines signal completion of an I/O request by means of the $SGNLI primitive with the DCT address in R1 and an op-code of zero in R0. The driver must ELF SYSTEM DOCUMENTATION Page 21 DEVICE DRIVERS then restore the registers and exit via a $RTI primitive. IV.1.2. Register Usage: All registers that are changed by the driver should be pushed upon entry and popped before return. IV.1.3. Error Codes: When an error occurs, bit 15 of DCTSTA should be set. In the low 6 bits of DCTSTA, an error category should be set. Bit seven is the done bit and is always set before returning. Bits 8 through 14 are either set as a device code or a user code depending on the error category. These codes are optional and need not be specified The error categories can be either a "2" for "user error", "4" for "device error", or "0" for no error. A table of the equates for the error codes can be obtained by calling the $DFIST macro in KTBL.SML. IV.1.4. Assembly: To assemble the driver the three entry points must be specified as "globals". Also the $DFIST, $DFREG, $CNFIG, and $DFDCT macros must be called in order to include the equates for the DCT, ICT, registers, and error codes. The DCT and ICT for the device must be generated in the KDCT.M11 module, and it must be reassembled. The object output of the driver and KDCT.M11 are then linked to the rest of the ELF kernel. ELF SYSTEM DOCUMENTATION Page 22 XNCP Description XNCP The New eXperimental Network Control Program -------------------------------------------- A new XNCP has been recently implemented as a standard feature of ELF-II. The XNCP gives a user a complete control of his Network communication, bypassing the standard NCP (and the HOST-to-HOST protocol). It also makes the Network look like any other device served by ELF-II. The XNCP usage has two parts: (1) controlling of the "connection" (by $XLSN, $XCON, and $XCLS), and (2) data transfer (by $SIO). The connection control primitives use an XCCT (eXperimental Connection Control Table) to define the connection and get a "PORT" assigned to the connection by the system. Hereafter, all data-transfer calls refer to this PORT, by including it in the IORB (Input Output Request Block). Connections (LINKs) have to be defined (by $XLSN or $XCON) before they are used for data transfer (by $SIO). Connections are defined as half duplex, using the actual LINK identification. Note that the SOCKET notion is entirely eliminated. Hosts are defined by 9 bits (defining IMP, HOST and the to/from-IMP bit), and LINKs are defined by the 8 most significant bits of the 12-bits LINK field, as defined in BBN-1822 (March '74 revision). The XNCP uses the new SIGNAL/WAIT features of ELF-II. Three signals are used, two of which are associated with sending and one with receiving. The sending signals happen when: (1) The message is entirely copied from the user buffers into the XNCP buffers. The OP-CODE used for signaling is the one supplied in the XCCT. (2) The message is entirely given to the IMP. The OP-CODE used is the one supplied in the IORB. The receiving signal happens when (3) an arriving message is entirely copied into the user buffer. The OP-CODE used is the one supplied in the IORB. ELF SYSTEM DOCUMENTATION Page 23 XNCP Description The first 32 bits of all messages are the HOST/IMP leader (as defined in BBN-1822). Note that it is the user's responsibility to avoid LINK conflicts. A possible scenario is as follows. The user program wishes to communicate with link "L" of host "H". It issues first a $XCON, using an XCCT which includes "H", "L", OP-CODE, and a bit indicating that this is a SND connection. The system returns a PORT number, which is inserted by the user into the SND-IORB. Then the program issues another $XCON pointing to another XCCT which includes the same "H" and "L", and a bit indicating that this is a RCV connection. Note that no OP-CODE is needed now. The system returns another PORT number, which is inserted by the user into the RCV-IORB. From now on the program can send and receive data over the network, just as if it were any other device. At the end of the session, a good citizenship is to $XCLS both connections. Possible errors: 201 Undefined HOST. 202 LINK < 300 (i.e. not experimental). 203 Attempt to close non experimental connection. 204 Attempt to close non existing connection. ELF SYSTEM DOCUMENTATION Page 24 XNCP Description XCCT and IORB format: XCCT: HOST (9 out of 16, as shown below) +2: OP-CODE(8), STATUS(8) +4: LINK(12), Unused(3), C(1) C in XCCT+4 is 0 for RCV C in XCCT+4 is 1 for SND IORB: 'IPP' always +2: PORT(16) +4: FUNC(16) (0=NOP, 1=READ, 2=WRITE) +6: Unused(8), OP-CODE(8) +10: BUFFER ADDRESS(16) +12: BR(16) 8-bit bytes requested +14: ERROR(1), STATUS(15) +16: BX(16) 8-bit bytes transfered. +20: used only for certain devices +22: used only for certain devices STATUS = 0 for reset STATUS = 200 for normal completion STATUS > 200 for error completion HOST: P,TXX,XXX,XHH,III,III Where: P = Priority, T = TO-IMP bit, H = HOST-NUMBER and I = IMP-NUMBER. Hence, the 9 bits defining HOSTS are: -,T--,---,-HH,III,III. OP-CODEs are used by ELF-II to signal the process upon completion of the task. STATUS and BX are set by ELF upon completion of the task. ELF SYSTEM DOCUMENTATION Page 25 XNCP Description Format of calls (1) LISTEN MOV #XCCT,R0 ---> XCCT: 0 $XLSN 0 MOV R1,PORT LINK,0 Possible error: [202]. (2) CONNECT MOV #XCCT,R0 ---> XCCT: HOST $XCON OPCODE,0 MOV R1,PORT LINK,C If this is a SND connection, then C=1. If this is a RCV connection: C=0, and the OPCODE can be omitted. Possible errors: [201] and [202]. (3) SENDING MESSAGE MOV #IORB,R0 ---> IORB: 'IPP' (always) $SIO PORT# 2 (for WRITE) OPCODE BUF -------------> BUF: HOST BR LINK STATUS ..... BX ..... ..... BR is the number of 8-bit bytes requested. BX is the number of bytes transferred, and its value is inserted by the system. On SND, BX=BR always. Note that BR has to be at least 4, as it includes the HOST/IMP 32 bit header. ELF SYSTEM DOCUMENTATION Page 26 XNCP Description (4) RECEIVING MESSAGE MOV #IORB,R0 ---> IORB: 'IPP' (always) $SIO PORT# 1 (for READ) OPCODE BUF -------------> BUF: ..... BR ..... STATUS ..... BX If the arriving message is not longer than BR bytes, BX is updated to the actual number of arriving bytes (HOST/IMP HEADER included). Else, BX is set to BR, and the rest of the message is lost. (5) CLOSING MOV #XCCT,R0 ---> XCCT: HOST $CLS 0 LINK If this connection was defined by $XLSN, then the HOST is not needed for the $XCLS. If any message is pending (IN or OUT) when the $XCLS is issued, an error is signaled. Possible errors: [203] and [204]. ELF SYSTEM DOCUMENTATION Page 27 XNCP Description Example Program --------------- Example program to RCV on link 377 and XMT same on 376. RCVOP = 1 SNDOP1 = 2 SNDOP2 = 4 START: $XCON #XCCT0 ; setup RCV cct MOV R1,IORB0+2 ; set PORT $XCON #XCCT1 ; setup SND cct MOV R1,IORB1+2 ; set PORT LOOP: $SIO #IORB0 ; read $WAITS #RCVOP MOV IORB0+16,IORB1+12 ; BX(RCV) to BR(XMT) $SIO #IORB1 ; send $WAITS #SNDOP1 $WAITS #SNDOP2 BR LOOP IORB0: .RAD50 'IPP' ; device .WORD 0 ; PORT filled in .BYTE RCVOP,0 ; OP-CODE .WORD 1 ; fcn = READ .WORD #BUFFER ; BUFFER start address .WORD 1100. ; BR .WORD 0 ; status .WORD 0 ; BX IORB1: .RAD50 'IPP' ; device .WORD 0 ; PORT filled in .BYTE SNDOP2,0 ; OP-CODE .WORD 2 ; fcn = WRITE .WORD #BUFFER ; BUFFER start address .WORD 0 ; BR for SND filled in .WORD 0 ; status .WORD 0 ; BX XCCT0: .WORD 26 ; ISI-11/45 .WORD 0 ; OP-CODE (not used for RCV) .BYTE 0,377 ; LINK, RCV(0) XCCT1: .WORD 26 ; ISI-11/45 .WORD SNDOP1 ; OP-CODE .BYTE 1,376 ; LINK, SND(1) BUFFER: .BLKW 1100. .END Title: $ASDEV ELF SYSTEM DOCUMENTATION Page 28 KERNEL PRIMITIVES Function: ASsign a DEVice to one or two processes $ASDEV ,,, R0 R1 MSB (R2) : LSB (R2) R0 Description: The $ASDEV primitive assigns a device to one (in certain cas, two) process. Once the device is assigned, only the assigned process may perform $SIO calls to that device. The device name and unit number have the same requirements as $DFDEV, except a minus one for the unit number isn't allowed. Both processes must be specified and a zero PID defaults to the active process. The primitive returns a completion code in R0 which is zero if the device was assigned successfully. It is negative if the process doesn't have a capability value less than or equal to 2. It is a minus one if the device doesn't exist and it is positive if the device is already assigned. When the device is already assigned a semaphore is returned in R0, which can be used to wait for the device to become released. Macro Calling Syntax: $ASDEV DNAM/R0,UNIT/R1,PIDA/R2,PIDB/R2 ELF SYSTEM DOCUMENTATION Page 29 KERNEL PRIMITIVES Title: $CREAP Function: CREAte a Process $CREAP ,,, (SP) LSB 2(SP) MSB 2(SP) LSB 4(SP) :, MSB 4(SP) R0 R1 Description: The $CREAP primitive assumes an entry point, an absolute priority, an event completion code, a relative capability value, and a virtual storage ID. These arguments are placed on the caller's stack. If the virtual storage ID is not specified then the high byte of the second stack word is set to zero. The $CREAP routine creates a process with the specified parameters that are passed. If the VSMID is zero, then the process is created within the caller's address space and with the same mode(i.e., kernel, user). When the calling process recieves control again, the process ID of the newly created process is returned in R0 and a completion code in R1. The $CREAP primitive gives control to the scheduler, after allocating and formatting a new process control table for the created process. When the created process is frozen, the creator is signalled with the event op-code specified when the process was originally created. the event data in this case contains the process id of the frozen process. Macro Calling Syntax: $CREAP EPT,PRIO,EVNTCD,CAPABILITY [,VSMID] Completion Codes: 0= Success 2= Undefined priority value (no PRQ), assigned to first available lower priority queue. 4= Insufficient storage for new process Note that absolute process priority values are assigned such that the lowest priority level in the system has a value of 1, the highest is a number equal to the number of system process priority levels (determined when the system is generated). ELF SYSTEM DOCUMENTATION Page 30 KERNEL PRIMITIVES TITLE: $DFDEV FUNCTION: DEFINE DEVice to system. $DFDEV ,:, R0 R1 R0 R1 Description: The $DFDEV primitive makes a device associated with a device control table (DCT) available for doing $SIO requests . The device name parameter must must point to a .RAD50 word containing the device name, or the register must already contain the .RAD50 device name. The unit number must be specified and must be positive or a minus one. A unit number of minus one indicates a request to define any unit available, and return that unit number. The primitive returns a completion code which is zero if the device is defined successfully, negative if the device doesn't exist and positive if the device is already defined. If it is positive, a semaphore is returned in R0 which can be used to wait for the device to become available. If an arbitrary device unit number was requested, the successfully-allocated unit number is returned in R1. Macro Calling Syntax: $DFDEV DNAM/R0,UNIT/R1 ELF SYSTEM DOCUMENTATION Page 31 KERNEL PRIMITIVES Title: $ERROR Function: freeze active process with ERROR code. $ERROR (SP) Description: The $ERROR macro places an error code on the stack, and transfers control to the process error handler ($ERROR). The process then becomes frozen, and the creator of the process in error is notified. No registers are used, allowing the creating process to examine the entire set of registers. The error code specified must be literal (e.g. an equated symbol or numeric value). Macro Calling Syntax: $ERROR CODE/-(SP) ELF SYSTEM DOCUMENTATION Page 32 KERNEL PRIMITIVES Title: $EXV Function: EXhaustive V of specified semaphore. $EXV R0 Description: The $EXV macro assumes a semaphore ID and passes it in R0 to the $EXV primitive. The $EXV primitive awakens all processes that are waiting on the specified semaphore. No arguments are returned. Macro Calling Syntax: $EXV SEMID/R0 Error Codes: $SERIVS=246 ;INVALID SEMAPHORE ID. ELF SYSTEM DOCUMENTATION Page 33 KERNEL PRIMITIVES Title: $FREEP Function: FREEze Process $FREEP , R0 R1 Description: The $FREEP macro assumes a process id and an error code, which it passes in R0 and R1 respectively to the $FREEP primitive. If no process id or error code is specified, then these arguments assume default values of zero. It should be noted that the normal method of process termination is by freezing the active process with a completion code of zero (hence, both arguments unspecified). The $FREEP routine freezes the process specified in R0 and posts the specified error code. If R0 contains a zero, then it freezes the active process. Macro Calling Syntax: $FREEP PID/R0,ERRCD/R1 ERROR CODES: INVPid=250 ;Invalid process ID on freep or zap ELF SYSTEM DOCUMENTATION Page 34 KERNEL PRIMITIVES Title: $FSEM Function: Free SEMaphore id. $FSEM R0 Description: The $FSEM macro assumes a semaphore ID and passes it in R0 to the $FSEM primitive. The $FSEM routine releases system storage used for the specified semaphore, and makes the semaphore id "unknown" to the system. No arguments are returned. Macro Calling Syntax: $FSEM SEMID/R0 Error Codes: SERIVS=246 ;INVALID SEMAPHORE ID. ELF SYSTEM DOCUMENTATION Page 35 KERNEL PRIMITIVES Title: $GAPID Function: Get Active Process ID $GAPID :, MSB (R0) LSB (R1) Description: The $GAPID primitive returns the active process id (PID) in the low byte of R0 and the active virtual storage map id (VSMID) in the high byte. Macro Calling Syntax: $GAPID ELF SYSTEM DOCUMENTATION Page 36 KERNEL PRIMITIVES Title: $GETOD Function: GEt the Time Of Day $GETOD :