↑ Writing ↑

GEONius.com
17-Aug-2024
 E-mail 

MILSTAR Universal Firmware Design

1985

(Also see the MILSTAR Universal Firmware User's Manual)

 

1 Introduction

1.1 Scope

This document provides the design specifications for the universal firmware that will be used by the single board computers embedded in the MILSTAR automatic test equipment test interface racks. The universal firmware consists primarily of those software modules not associated with a particular test set (RIU, IOC, CTC, MMU, and panel STE): the operating system, system initialization software, and device interface software. This document defines the functions of the universal firmware, the allocation of these functions to tasks, and the implementation (in pseudo-code) of these tasks. In addition, external interfaces, resource requirements, etc., are defined.

1.2 Objectives

This document documents the requirements specification and the design process for the universal firmware. It serves as a guide to implementation and as a reference for the completed product.

1.3 Applicable Documents

The following documents are relevant to the design of the universal firmware:

  1. Guide to Using the iSBC 286/10 Single Board Computer
  2. iRMX Installation and Configuration Guide for Release 6
  3. iRMX Programmer's Reference Manual for Release 6, Parts 1-2
  4. iSBX 488 General Purpose Interface Bus (GPIB) Multimodule Board Hardware Reference Manual
  5. iSDM 286 System Debug Monitor Reference Manual

1.4 Definitions

BIOS		Basic Input/Output System
CPU		Central Processing Unit
CTC		Comsec-Transec Controller
DAU		Data Acquisition Unit
EPROM		Erasable Programmable Read-Only Memory
GPIB		General Purpose Interface Bus (IEEE-488 bus, Intel nomenclature)
GSC		Ground Station Computer (panel STE test set)
HPIB		Hewlett-Packard Interface Bus (IEEE-488 bus, HP nomenclature)
I/F		Interface
IH		Interrupt Handler
I/O		Input/Output
IOC		Input/Output Controller
IOCT		I/O Completion Task
IST		Interrupt Service Task
LBX		Local Bus Extension
MILSTAR		Military Strategic and Tactical Relay Satellite System
MMU		Mass Memory Unit
MPSC		Multi-Protocol Serial Controller
RAM		Random Access Memory
RIU		Remote Interface Unit
RMX		Real-time Multi-tasking Executive
ROM		Read-Only Memory
RPU		Remote Processing Unit
SBC		Single Board Computer
SBX		SBC I/O Bus Expansion
SDM		System Debug Monitor
STE		Panel Special Test Equipment
TBD		To Be Determined
TIR		Test Interface Rack
UUT		Unit Under Test
 

2 Subsystem Definition

2.1 Identification

The universal firmware resides on the single board computers embedded in the MILSTAR automatic test equipment test interface racks. The universal firmware consists primarily of software modules not associated with one of the test sets (RIU, IOC, CTC, MMU, or panel STE). These modules include a subset of the iRMX operating system, software to perform various system initialization tasks and to download the applications firmware, and software to provide an interface between the applications firmware and the input/output devices attached to the test rack computer.

2.2 Functional Summary

Automatic test equipment is being used to test various digital system components (RIU, IOC, CTC, and MMU) that will be placed on the MILSTAR satellites. An additional test set (panel STE) exercises a fully populated spacecraft panel. The automatic test equipment is composed of a remote processing unit (RPU) and a test interface rack (TIR) that controls and monitors the unit under test (UUT). The RPU for the panel STE test set is a Digital Equipment Corporation VAX-11/780 computer; it simulates the Ground Station Computer (GSC) and is connected to the TIR via an RS-232C serial link (see figure 2.2-2). The RPU for the other test sets is a Hewlett-Packard HP-1000 minicomputer that is connected to the TIR via an IEEE-488 bus (see figure 2.2-1). The RIU test set requires an additional test rack that is connected to the main rack via an RS-232C serial link. The RPU passes test commands and parameters to the TIR. After exercising the UUT as necessary, the TIR returns test results and status to the RPU.

The software that resides in the TIR consists of universal firmware and applications firmware. The applications firmware is test set-specific. Its functions include receiving test commands and parameters from the RPU, configuration of the TIR hardware per the test parameters, initiating the test, monitoring the test as it executes and collecting test data, and returning the test results and status to the RPU. The universal firmware is test set-independent. It provides the task communication, TIR-RPU interface, and rack A-rack B interface utilities needed by the applications firmware. It is also responsible for downloading the applications firmware and starting it running.

The functions of the universal firmware are described in more detail in the following paragraphs, including a brief description of the firmware's hardware environment.

2.2.1 Hardware Environment

The computer on which the universal and applications firmware must run and the peripherals with which they must communicate both increase and restrict the functions that can be provided by the software. The computer hardware is based on the Intel iSBC 286/10 single board computer and includes the following components:

Figure 2.2.1-1 illustrates the relationships between the components of the computer sytem.

2.2.2 iRMX 286R Operating System

The Intel iRMX 286R real-time multi-tasking executive is an operating system that runs on the 80286 CPU in real address (8086-compatibility) mode. RMX makes a number of facilities and system services available to the utility and applications software. These include task management and communication, memory management, interrupt services, device drivers, and debugging aids.

Only a subset of the iRMX operating system is utilized by the universal and applications firmware. The extent of the subset is determined by the functional requirements of the software and the restrictions of the hardware. For example, the file handling system is not necessary and is precluded by the lack of secondary storage attached to the iSBC 286/10 computer. As a result, utilities such as the Crash Analyzer are not usable. The Terminal Handler and Dynamic Debugger would be useful but cannot be used because the required I/O hardware is not available on the iSBC 286/10. The Basic Input/Output System (BIOS) includes an 8274 MPSC driver that implements the RS-232C interface required by the firmware, but the BIOS requires too much memory. Give me a place to stand and I could move the earth.

The portions of the operating system that are used are the Nucleus, the System Debugger, and the System Debug Monitor.

2.2.2.1 iRMX 86 Nucleus

The iRMX 86 Nucleus is the "kernel" of RMX. The Nucleus contains many system service calls required by the utility and applications firmware. These system calls provide the following functions:

2.2.2.2 iRMX 86 System Debugger and iSDM 286 System Debug Monitor

There are three debugging tools available for the iSBC 286/10 single board computer: the iRMX 86 Dynamic Debugger, the iSDM 286 System Debug Monitor, and the iRMX System Debugger. The dynamic debugger is the most powerful of the three and allows real-time monitoring of multiple tasks as they execute. As mentioned earlier, however, the terminal port hardware required by this debugger is not present on the iSBC 286/10.

The iSDM 286 System Debug Monitor is not actually part of the RMX operating system; it is supplied in ROM with the iSBC 286/10 computer. This monitor provides the following low-level debugging functions:

The iRMX 86 System Debugger is tied to a dedicated interrupt level and can be activated either by a hardware interrupt or by a software interrupt embedded in the firmware. Consequently, all system activity is halted when you use this debugger. The system debugger is an extension of the iSDM 286 monitor. In addition to performing the monitor functions described above, the system debugger can display information about the following RMX objects:

The monitor and system debugger can be activated from a program via the following software interrupts:

When the system debugger is loaded along with the applications program, the breakpoint interrupts are sufficient to invoke the system debugger.

2.2.3 System Initialization and Applications Download

When the test rack is powered up and after the operating system has initialized itself, the following functions must be performed by the universal firmware:

  1. Memory test
  2. Configure IEEE-488 and RS-232C interfaces
  3. Download applications firmware from the remote processing unit
  4. Start the applications firmware running.

The system initialization and applications download sequence takes place upon power-up of the test interface rack. Special commands from the RPU may be used to initiate a "soft" power-up.

2.2.4 IEEE-488 and RS-232C Interfaces

The test rack computer utilizes the IEEE-488 bus and the RS-232C serial links to interface with the RPU and various instruments attached to the buses. With respect to the IEEE-488 bus, the TIR computer must function as either the master bus controller or as a slave talker/listener. RS-232C interfaces are used for RPU and multi-rack communications and console input/output.

2.2.4.1 IEEE-488 Controller

In the panel STE test set, the TIR computer must act as the IEEE-488 bus master in order to control the 3497A data acquisition unit (DAU) and the 6034A power supply (in the other test sets, the RPU fills this role). In addition to the talker/listener functions described in the next paragraph, the TIR computer must perform the following IEEE-488 system controller functions:

2.2.4.2 IEEE-488 Talker/Listener

In the remaining test sets, the TIR computer must act as an IEEE-488 talker or listener in order to communicate with the HP-1000 RPU and the 3497A DAU. The TIR computer must perform the following IEEE-488 talker/listener functions:

The mode of I/O (bus I/O, bus I/O and console echo, or console I/O) is initialized at compile time and can be changed at run-time by entering special commands at the console.

2.2.4.3 RS-232C Interface

In the panel STE test set, the TIR computer must communicate with the VAX-11/780 RPU via an RS-232C interface. In the RIU test set, the computer on the main test rack must communicate with the computer on the secondary test rack via an RS-232C interface. The TIR computer must perform the following functions on the RS-232C serial link:

As with the IEEE-488 bus interface, the RS-232C I/O modes are transparent to the applications firmware and can be changed via the console.

2.2.4.4 Console Input/Output

Each iSBC 286/10 computer board has two RS-232C channels available (using the 8274 MPSC interface). One of these channels is dedicated to the interfaces mentioned in the previous paragraph. The other channel is connected to the console terminal and is used for console input and output. Console input is available as an alternate to the IEEE-488 bus and the RS-232C link, but this feature is transparent to the applications firmware. Console output can be used for debug output by the applications firmware or to echo transactions on the IEEE-488 and RS-232C interfaces. The following console functions are supported:

2.3 Functional Allocation Description

The universal firmware (excluding the operating system) is responsible for initializing the system, downloading and starting the applications firmware, and providing various I/O functions to the applications firmware. The functions required of the universal firmware are divided among a number of programs or tasks. The task structure for the universal firmware is shown in the form of a data flow diagram in Figure 2.3.2-1; the task creation hierarchy is shown in Figure 2.3.2-2. The allocation of functions to the tasks, the interfaces between the tasks, and the implementations of the tasks are greatly affected by the design philosophy and mechanics of the RMX operating system. The remainder of this section discusses the relevant features of RMX and their usage in the universal firmware. Functional descriptions and detailed control flow for the tasks can be found in Section 4 of this document.

2.3.1 iRMX Design Philosophy

The capabilities and limitations of the iRMX 286R operating system have a large impact on the design of the universal firmware. RMX is intended for real-time, multi-tasking applications, but the limitations of the operating system can make implementation awkward. The following paragraphs discuss some of the basics concepts of RMX and their utilization in the universal firmware.

2.3.1.1 iRMX Objects

The foundation of RMX is the object. An RMX object is identified by a 16-bit word called a "token". Typical RMX objects include jobs, tasks, memory segments, semaphores, and mailboxes. Routines in the Nucleus allow you to associate names with tokens (RQ$CATALOG$OBJECT) and tokens with names (RQ$LOOKUP$OBJECT). The name-token relationships are stored in a job's object directory and are thus available to all the tasks in the job. This capability allows multiple tasks to access the same semaphore or mailbox using an agreed-upon name.

2.3.1.2 iRMX Jobs

RMX jobs are used to logically group tasks and resources. An RMX job consists of an initialization task that is activated when the job is created, subtasks that must be created by the initialization task or its children, and the resources associated with the job. Resources (i.e., memory segments, semaphores, and mailboxes) utilized by a task are taken from and returned to the resources of the job.

Jobs are hierarchically structured. At the top of the hierarchy is the "root" job; at the next level down are the "first level" jobs. The Intel-supplied root job is automatically created when RMX starts up and is responsible for initializing the Nucleus and creating the first level jobs (RQ$CREATE$JOB). The first level jobs include a Basic Input/Output System initialization job, a System Debugger initialization job, and one or more user jobs (the jobs to be created by the root job are specified when the operating system is configured). The TIR firmware requires only a single user job, consisting solely of an initialization and reboot task. This user job will in turn create a child job, the test rack job, consisting of an initialization and download task, the interface tasks, and the application tasks. The purpose of this two level user job hierarchy is to provide a simple means of deleting tasks and deallocating resources during an abort and reboot situation (deleting the child job automatically deletes all resources allocated to that job).

2.3.1.3 iRMX Tasks

RMX tasks are stand-alone programs that perform various functions. The distribution of functions among tasks and the functional scope of a particular task are determined by the nature of the functions to be performed. For example, in the universal firmware, I/O functions for different devices are allocated to separate tasks; in the applications firmware, time-critical board interface functions are allocated to separate tasks.

Associated with an RMX task are its state, its priority, its stack, and its allocated resources. A task may be executing, ready for execution, or suspended while waiting on mailboxes, semaphores, timers, and interrupts. Task priorities can be manipulated (RQ$SET$PRIORITY) to give critical processing priority over less-critical processing. Because RMX is event-driven, a high-priority ready task cannot pre-empt a low-priority executing task until an event (i.e., an interrupt) occurs. Each task has a stack that can be statically allocated when the task is linked and located, or (preferably) dynamically allocated from the job's memory pool when the task is created. A task's resources include its stack and any memory segments, semaphores, or mailboxes it has created.

Task synchronization and inter-task communication are accomplished using common memory, semaphores, and mailboxes. The PL/M-86 language includes a function (LOCKSET) that provides an indivisible read-and-set access to common memory. RMX handles memory segments, semaphores, and mailboxes. An RMX task has the capability to create other tasks (RQ$CREATE$TASK).

2.3.1.4 iRMX Segments

RMX provides programs with the ability to dynamically allocate and deallocate segments of memory. The sections of RAM to be managed by RMX are specified when RMX is configured. A segment is known by its token, or "selector", which determines its base address in memory; segments must be a minimum of 16 and a maximum of 65,536 (64K) bytes long. Utilization of the memory management capabilities of RMX in the MILSTAR firmware include implicit allocation/deallocation of a stack segment when a task is created/deleted and explicit allocation/deallocation of a memory segment when a mailbox message is sent/received. Examples of segment creation and deletion are presented in the paragraph on mailboxes, below.

2.3.1.5 iRMX Semaphores

Semaphores are counters of abstract units. They may be used to ensure mutually exclusive access to resources and to synchronize concurrent tasks. RMX allows you to create and delete semaphores, catalog them by name in the job's object directory, lookup a semaphore in the job's object directory, wait on the semaphore for a particular number of units to be available, and return a particular number of units to the semaphore. Semaphores will be used in MILSTAR firmware for signalling and mutual exclusion. Example usage is as follows:

 Task A
--------

/* Create a semaphore, SEM$A, with an initial value of zero units. */

    semaphore_token = RQ$CREATE$SEMAPHORE (0, 1, 0, @status) ;
    CALL RQ$CATALOG$OBJECT (0, semaphore_token, @(5,'SEM$A'), @status) ;

    ...

/* Signal task B by sending a unit to the semaphore. */

    CALL RQ$SEND$UNITS (semaphore_token, 1, @status) ;


 Task B
--------

/* Lookup the token for semaphore SEM$A. */

    semaphore_token = RQ$LOOKUP$OBJECT (0, @(5,'SEM$A'), wait$forever, @status) ;

    ...

/* Wait for the semaphore to be posted by task A. */

    value = RQ$RECEIVE$UNITS (semaphore_token, 1, wait$forever, @status) ;

2.3.1.6 iRMX Mailboxes

Mailboxes are a means of passing information and/or control between tasks. RMX allows you to create and delete mailboxes, catalog them by name in the job's object directory, lookup a mailbox in the job's object directory, wait on a mailbox for a message to be received, and send a message to a mailbox. The "message" that is passed via an RMX mailbox is actually a token; the token can be the identifier for any RMX object. A suggested protocol for mailbox communication in the MILSTAR firmware is presented below.

The task that receives messages in a mailbox should usually be the one that creates the mailbox. Tasks that send messages to the mailbox should lookup the mailbox's name in the job's object directory. To mail a message to another task, a task should allocate a "packet" memory segment, fill in the necessary fields in the packet, and mail the packet's token to the mailbox. To receive a message from another task, a task should wait on the mailbox, receive the packet token, and use the token to access the information in the packet. In the example below, the packet is 16 bytes long (the minimum allocatable size); the meanings of the fields in the packet are described in the functional summary for the RPU interface task (Section 4).

 Task A
--------

    DECLARE  message  POINTER ;
    DECLARE  mailbox_message  BASED  message
        STRUCTURE (source  BYTE,
                   destination  BYTE,
                   func  BYTE,
                   flag  BYTE,
                   status  WORD,
                   length  WORD,
                   location  POINTER)

    ...

/* Lookup task B's mailbox. */

    mailbox_token = RQ$LOOKUP$OBJECT (0, @(5,'MBX$B'), wait$forever, @status) ;

    ...

/* Allocate a mailbox packet segment. */

    segment_token = RQ$CREATE$SEGMENT (16, @status) ;
    message = BUILD$PTR (segment_token, 0) ;

/* Fill in the fields of the packet. */

    mailbox_message.source = this$task ;
    mailbox_message.destination = other$task ;
    mailbox_message.func = ignore$request ;
    mailbox_message.length = 11 ;
    mailbox_message.location = @('Hi, Task B!') ;

/* Send task B the message. */

    CALL RQ$SEND$MESSAGE (mailbox_token, segment_token, no$response, @status) ;
 Task B
--------

    DECLARE  message  POINTER ;
    DECLARE  mailbox_message  BASED  message
        STRUCTURE (source  BYTE,
                   destination  BYTE,
                   func  BYTE,
                   flag  BYTE,
                   status  WORD,
                   length  WORD,
                   location  POINTER)

    ...

/* Create and catalog mailbox MBX$B. */

    mailbox_token = RQ$CREATE$MAILBOX (0, @status) ;
    CALL RQ$CATALOG$OBJECT (0, mailbox_token, @(5,'MBX$B'), @status) ;

    ...

/* Wait for a message. */

    segment_token = RQ$RECEIVE$MESSAGE (mailbox_token, wait$forever,
                                        @response_mailbox, @status) ;

/* Process the message. */

    message = BUILD$PTR (segment_token, 0) ;

    IF mailbox_message.func = ignore$request THEN
        DO ;
        ...
        END ;

/* Deallocate the message packet when finished. */

    CALL RQ$DELETE$SEGMENT (segment_token, @status) ;

2.3.1.7 iRMX Timers

There are two methods of accessing timers in RMX. The first is to specify a time-out period when waiting on a semaphore or a mailbox. The second is to put yourself to sleep for a specified period of time using the RQ$SLEEP nucleus call. The length of the clock "ticks" used to specify time periods are set when RMX is configured.

2.3.1.8 iRMX Interrupt Handling

RMX allows a program to declare an interrupt handling routine that is to be invoked when an interrupt at a certain level occurs, and, optionally, an interrupt task that is to be associated with the interrupt handler.

An interrupt handler is declared and assigned to an interrupt level by the RQ$SET$INTERRUPT nucleus call; the handler can be deassigned using the RQ$RESET$INTERRUPT call. When the interrupt handler is invoked following an interrupt, it can only make a very restricted set of nucleus calls. RQ$ENTER$INTERRUPT allows the interrupt handler to obtain access to a data segment specified when the handler was declared; this protects the current data segment of the interrupted task. RQ$EXIT$INTERRUPT sends an end-of-interrupt signal to the hardware prior to returning from the interrupt handler (at which point interrupts are re-enabled). These are the only two nucleus calls that an interrupt handler is allowed to make.

Because an interrupt handler is restricted in its use of the RMX nucleus, applications requiring other nucleus calls in response to interrupts can associate an interrupt task with the interrupt handler. The interrupt task is the task that declares the interrupt handler; whether or not the task is considered an interrupt task is governed by a flag passed to the RQ$SET$INTERRUPT routine. If an interrupt handler has an associated task, then the handler calls RQ$SIGNAL$INTERRUPT instead of RQ$EXIT$INTERRUPT. RQ$SIGNAL$INTERRUPT wakes up the interrupt task, allowing it to do any interrupt processing that requires access to the complete nucleus. Interrupt tasks, by their nature, must have a very limited processing structure:

/* Declare the interrupt handler and associate this task with it. */

    CALL RQ$SET$INTERRUPT (interrupt$level, interrupt$task$flag,
                           @interrupt$handler, data$segment, @status) ;

    ...		/* Initialization processing. */

/* Loop on interrupts. */

    DO forever ;

        CALL RQ$WAIT$INTERRUPT (interrupt$level, @status) ;

        ...	/* Service the interrupt, using any nucleus calls you wish. */

    END ;

Note that there is no mechanism for timing-out while waiting for an interrupt. Consequently, an interrupt task is virtually dedicated to being an interrupt task, and that is why the control structure of such a task is so limited.

2.3.1.9 Waiting on Multiple Events

Real-time, multi-tasking systems like the MILSTAR test rack firmware require the ability to respond to multiple, asynchronous events. RMX has many capabilities, but waiting on multiple events is not one of them. A task can wait on a semaphore, a mailbox, a timer, or an interrupt, but not on more than one at a time. Some programming contortions are needed in order to get around this limitation of RMX. One possible method of accomplishing this depends on the type of events to be fielded.

A "pollable" RMX event is an event for which a time-out period of zero can be specified when requesting a wait on the event. Waiting on semaphores and mailboxes are pollable events. If the semaphore units are not immediately available or no mailbox message is ready, then no wait occurs and an error status is returned to the calling task. Polling allows you to sequentially check if any of several events has occurred.

A "non-pollable" RMX event is an event for which no time-out is possible while waiting on the event. Timers and interrupts are examples of non-pollable events. If you're sleeping on a timer, you can't wake up until the alarm goes off. Once you wait on an interrupt, you're suspended until the interrupt occurs (if it ever does). You can't directly check to see if any of several non-pollable events has occurred.

To simulate a task waiting on multiple events, you must do the following:

  1. Create a special semaphore for the task that indicates an event has occurred
  2. Keep all the pollable events in the task
  3. Create a separate subtask and a separate semaphore or mailbox for each non-pollable event

The special semaphore is used to indicate that some event has occurred that the task is interested in. Any external task that initiates one of these events (i.e., sending a mailbox message or signalling another semaphore) must signal this special semaphore. The subtasks for the non-pollable events (i.e., timers and interrupts) must also signal the special semaphore when their event has occurred. (Since an interrupt handler can't signal a semaphore, an interrupt task is required.)

For example, suppose we have a task, PROC_TASK, that must receive asynchronous commands from a parent task via a mailbox, synchronize with other sibling tasks via semaphores, handle interrupts from a hardware interface, and output a status message every 5 minutes. Following the rules given above, we create a special semaphore called PROC_EXCHANGE to indicate that some event has occurred. We also create two new tasks, INTERRUPT_TASK and TIMER_TASK, and two semaphores, INTERRUPT_OCCURRED and TIMER_DONE. The three tasks have the following program structures:

 PROC_TASK
-----------

    DO forever ;

    /* Wait for an event. */

        Wait on PROC_EXCHANGE semaphore ;

    /* Determine which event occurred by checking semaphores and mailboxes
       with immediate time-out. */

        IF command received from parent task THEN ;
            DO ;		/* Command mailbox. */
            ...
            END ;
        ELSEIF synchronization signal from sibling task THEN ;
            DO ;		/* Synchronization semaphore. */
            ...
            END ;
        ELSEIF interrupt occurred THEN ;
            DO ;		/* Interrupt occurred semaphore. */
            ...
            END ;
        ELSEIF five minutes up THEN ;
            DO ;		/* Timer done semaphore. */
            ...
            END ;

    END ;
 INTERRUPT_TASK
----------------

    ...		/* Declare interrupt handler. */

    DO forever ;

        CALL RQ$WAIT$INTERRUPT (...) ;	/* Wait for an interrupt.

        ...	/* Process the interrupt. */

        CALL RQ$SEND$UNITS (...) ;	/* Signal the INTERRUPT_OCCURRED semaphore. */

        CALL RQ$SEND$UNITS (...) ;	/* Signal the PROC_EXCHANGE semaphore. */

    END ;


 TIMER_TASK
------------

    DO forever ;

        CALL RQ$SLEEP (five$minutes) ;	/* Hibernate for the winter. */

        CALL RQ$SEND$UNITS (...) ;	/* Signal the TIMER_DONE semaphore. */

        CALL RQ$SEND$UNITS (...) ;	/* Signal the PROC_EXCHANGE semaphore. */

    END ;
 

3 Technical Design Description

3.1 Control and Data Flow

3.1.1 Subsystem Structure and Logic Description

3.1.2 Program Interrupts

3.1.3 Special Control Features

3.2 Resource Allocation and Utilization

3.2.1 Data Base Characteristics

3.2.2 Memory Allocation

3.2.3 Mass Storage Allocation

3.2.4 Timing Data

 

4 Technical Design Concepts - Components

4.1 User Job Initialization Task

4.1.1 Functional Summary

The user job initialization and reboot task is the only task activated when the user job is created by the RMX root job upon a "hard" system reset. The task then continually loops, waiting for a "soft" reset to be signalled. Upon receipt of such a signal, the test rack job is deleted (thereby deallocating all its resources) and recreated.

Two semaphores are created by this job. The REBOOT semaphore is used by the test rack job to signal the user job that a reboot is to be performed. The DOWNLOAD semaphore is initially created and set by the user job, but from then on it is the responsibility of the test rack job. By being the property of the parent user job, the DOWNLOAD semaphore is, in a sense, "global" to consecutive instantiations of the test rack job.

4.1.2 Control

Semaphore  DOWNLOAD - If set, indicates to the test rack job that it should
                re-download the applications software.
           REBOOT - If set, indicates that re-initialization is to take place.


BEGIN  User_Job_Initialization_Task

    Create and catalog REBOOT semaphore with initial value of 1 ;
    Create and catalog DOWNLOAD semaphore with initial value of 1 ;

    DO forever
        Wait on reboot semaphore ;
        Delete the test rack job (if active) and its resources ;
        Create test rack job ;
    ENDDO

END  User_Job_Initialization_Task.

4.2 Test Rack Job Initialization and Download Task

4.2.1 Functional Summary

The test rack job initialization and download task sets up the universal firmware for processing. The test rack job is created by the first-level user job. This two-job structure simplifies restarting the firmware; the user job needs only to delete the test rack job in order to deallocate all the test rack job's resources (semaphores, mailboxes, memory segments, etc.).

The initialization and download task is the first task executed when the test rack job is created. This task is responsible for creating some semaphores and mailboxes, starting up the interface tasks, and, if requested, downloading the applications firmware. The main applications task is then created and control is passed to it. During the download, the initialization and download task appears to the interface tasks as a pseudo-main applications task (thus using the same semaphores and mailboxes as the real main applications task).

4.2.2 Control

Semaphore  DOWNLOAD - If set, indicates to the test rack job that it should
                re-download the applications software.
           MEMORY$WAIT - Implements round-robin scheduling of tasks attempting
                to allocate memory segments.
           TIR_EXCHANGE - Set to indicate that an event has occurred to which
                the test rack job initialization task must respond.

Mailbox    RPU_MESSAGE - Input message mailbox for the RPU interface task.
           TIR_MESSAGE - Input message mailbox for the test rack job
                initialization task.


BEGIN  Test_Rack_Job_Initialization_Task

    Lookup the DOWNLOAD semaphore in the parent job's object directory ;

    Create and catalog the MEMORY$WAIT semaphore with initial value of 1 ;
    Create and catalog the TIR_EXCHANGE semaphore with initial value of 0 ;
    Create and catalog the TIR_MESSAGE mailbox ;

    Create the RPU interface task ;
    Wait on the TIR_EXCHANGE semaphore for subtask activation ;
    Lookup the RPU_MESSAGE mailbox ;

    Check the DOWNLOAD semaphore ;

    IF download requested THEN

        DO WHILE download not complete
            Read next RPU message from TIR_MESSAGE mailbox ;
            Store downloaded code/data block
        ENDDO

    ENDIF ;

    Create the test rack main applications task

END  Test_Rack_Job_Initialization_Task.

4.3 RPU Interface Task

4.3.1 Functional Summary

The RPU interface task coordinates the input/output processing of the universal firmware. The tasks that communicate with the RPU interface task are organized in a star network around the RPU interface task:

                                   IEEE-488
                                    Driver
                                     Task

                                      ^
                                      |
                                      |
                                      V

           Console                   RPU                  RS-232C
           Driver  <----------->  Interface  <--------->  Driver
            Task                    Task                   Task

                                      ^
                                      |
                                      |
                                      V

                                   TIR Main
                                  Applications
                                     Task

A node in the network can send a mailbox message packet to almost any other node in the network. Packets have the following format:

    DECLARE  ptr  POINTER ;
    DECLARE  message  BASED  ptr
        STRUCTURE (source  BYTE,
                   destination  BYTE,
                   func  BYTE,
                   flag  BYTE,
                   status  WORD,
                   length  WORD,
                   location  POINTER) ;

where the message fields have the following interpretations:

Message sources and destinations are identified as follows:

By manipulating the source and the destination using lookup tables, the RPU interface task can provide a virtual message interface between outlying tasks. The task originating a message supplies the physical source (itself) and the logical destination of the message. The RPU interface task checks the logical destination to see if the message must be echoed on the console terminal; if so, the message is temporarily sidetracked to the console driver task, which outputs it and returns it. The RPU interface task then looks up the physical source of the message in a table and substitutes the corresponding logical source in the message packet. The logical destination is looked up in another table and the message is routed to the corresponding physical destination.

Three tables are used to implement the virtual I/O interface. The tables are initialized at compile-time and may be modified at run-time via special commands entered at the console (see the functional description for the console driver task below). The echo table determines if messages are to be echoed on the console terminal before being routed to their destination:

			 Initial Echo Table
			--------------------

		Destination Task	Echo Flag
		----------------	---------
		    TIR			  false
		    RPU			  false
		    488			  false
		    232			  false
		    Console		  false
		    Unknown		  false

The source substitution table is used to translate physical message sources to logical message sources:

		  Initial Source Substitution Table
		 -----------------------------------

		Actual Source		Logical Source
		-------------		--------------
		    TIR			    TIR
		    RPU			    RPU
		    488			    488
		    232			    232
		    Console		    Console
		    Unknown		    Console

The destination mapping table is used to translate logical destinations to physical destinations:

		  Initial Destination Mapping Table
		 -----------------------------------

	Logical Destination		Physical Destination
	-------------------		--------------------
		TIR				TIR
		RPU				Null
		488				488
		232				232
		Console				Console
		Unknown				TIR

The first message received by the RPU interface task after reboot determines which interface corresponds to the remote processing unit. The RPU interface task takes the message source XXX and sets up source substitution "XXX->RPU" (replacing "XXX->XXX") and destination mapping "RPU->XXX" (replacing "RPU->Null").

4.3.2 Control

Semaphore  CONSOLE_EXCHANGE - Set to indicate that an event has occurred to
                which the console driver task must respond.
           RPU_EXCHANGE - Set to indicate that an event has occurred to which
                the RPU interface task must respond.
           TIR_EXCHANGE - Set to indicate that an event has occurred to which
                the test rack job initialization task or the main applications
                task must respond.
           232_EXCHANGE - Set to indicate that an event has occurred to which
                the RS-232C driver task must respond.
           488_EXCHANGE - Set to indicate that an event has occurred to which
                the IEEE-488 driver task must respond.

Mailbox    RPU_MESSAGE - Input message mailbox for the RPU interface task.
           CONSOLE_MESSAGE - Input message mailbox for the console driver
                task.
           TIR_MESSAGE - Input message mailbox for either the test rack job
                initialization task or the main applications task.
           232_MESSAGE - Input message mailbox for the RS-232C driver task.
           488_MESSAGE - Input message mailbox for the IEEE-488 driver task.

Common     ECHO_TABLE - Echo table.
           SOURCE_SUBSTITUTION - Source substitution table.
           DESTINATION_MAPPING - Destination mapping table.


BEGIN  RPU_Interface_Task

    Create and catalog the RPU_EXCHANGE semaphore with initial value of 0 ;
    Create and catalog the RPU_MESSAGE mailbox ;

    Lookup the TIR_EXCHANGE semaphore ;
    Lookup the TIR_MESSAGE mailbox ;

    Create the IEEE-488 driver task ;
    Wait on the RPU_EXCHANGE semaphore for subtask activation ;
    Lookup the 488_EXCHANGE semaphore ;
    Lookup the 488_MESSAGE mailbox ;

    Create the RS-232C driver task ;
    Wait on the RPU_EXCHANGE semaphore for subtask activation ;
    Lookup the 232_EXCHANGE semaphore ;
    Lookup the 232_MESSAGE mailbox ;

    Create the console driver task ;
    Wait on the RPU_EXCHANGE semaphore for subtask activation ;
    Lookup the CONSOLE_EXCHANGE semaphore ;
    Lookup the CONSOLE_MESSAGE mailbox ;

    Signal the TIR_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Read message from the RPU_MESSAGE mailbox ;

        Lookup the logical source in the Source Substitution Table ;
        Lookup the physical destination in the Destination Mapping Table ;

        IF messages to logical destination are to be echoed AND
           physical source is not console or unknown AND
           message flag not set THEN

            Set message flag ;
            Send message to the CONSOLE_MESSAGE mailbox ;
            Signal CONSOLE_EXCHANGE semaphore

        ELSE

            Substitute logical source for physical source in the message ;

            CASE OF physical destination IS

                NUL:
                    IF delete function modifier THEN
                        Delete message text segment ;
                    ENDIF ;
                    Delete message packet segment

                TIR:
                    Send message to TIR_MESSAGE mailbox ;
                    Signal TIR_EXCHANGE semaphore

                488:
                    Send message to 488_MESSAGE mailbox ;
                    Signal 488_EXCHANGE semaphore

                232:
                    Send message to 232_MESSAGE mailbox ;
                    Signal 232_EXCHANGE semaphore

                CON:
                    Send message to CONSOLE_MESSAGE mailbox ;
                    Signal CONSOLE_EXCHANGE semaphore

            ELSE

                Error

            ENDCASE

        ENDIF    /* If messages are to be echoed. */

    ENDDO    /* Forever. */


END  RPU_Interface_Task.

4.4 IEEE-488 Driver Task

4.4.1 Functional Summary

The IEEE-488 driver task controls input from and output to the IEEE-488 bus. Output mailbox messages received by the IEEE-488 driver task specify data that is to be output on the IEEE-488 bus. Input from the IEEE-488 bus is buffered; when a complete record has been assembled, the data is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source for input mailbox messages is the driver task itself (488); the logical destination is the test rack download or main applications task (TIR). The RPU interface task determines the logical source (i.e., when the IEEE-488 bus is the source of RPU messages) and physical destination for the messages.

The driver task is the asynchronous source of the following types of messages:

Requests sent to the IEEE-488 driver task are queued to the IEEE-488 interrupt service task for processing when the interface is idle. The following functions can be requested when the test rack computer acts as the IEEE-488 bus controller:

When the test rack computer acts as an IEEE-488 talker/listener, the available functions are as follows:

SRQ request codes include:

4.4.2 Control

Semaphore  MEMORY$WAIT - Implements round-robin scheduling of tasks attempting
                to allocate memory segments.
           REBOOT - Set to inform the user job initialization task that
                re-initialization is to take place.
           RPU_EXCHANGE - Set to indicate that an event has occurred to which
                the RPU interface task must respond.
           488_EXCHANGE - Set to indicate that an event has occurred to which
                the IEEE-488 driver task must respond.

Mailbox    RPU_MESSAGE - Input message mailbox for the RPU interface task.
           488_MESSAGE - Input message mailbox for the IEEE-488 driver task.

Common     IEEE_488_COMPLETION_QUEUE - Functions completed on the IEEE-488 bus.
           IEEE_488_REQUEST_QUEUE - Functions requested on the IEEE-488 bus.

Local      INPUT_LIST - Temporary list of completed reads.


BEGIN  IEEE_488_Driver_Task

    Create and catalog the 488_EXCHANGE semaphore with initial value of 0 ;
    Create and catalog the 488_MESSAGE mailbox ;

    Lookup the REBOOT semaphore ;
    Lookup the RPU_EXCHANGE semaphore ;
    Lookup the RPU_MESSAGE mailbox ;

    Create the IEEE-488 interrupt service task ;
    Wait on the 488_EXCHANGE semaphore for subtask activation ;

    Signal the RPU_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on the 488_EXCHANGE semaphore ;


/* Check for incoming requests from the RPU interface task. */

        DO WHILE more messages in 488_MESSAGE mailbox

            Read the next message from the 488_MESSAGE mailbox ;

            IF output request THEN

                Add (WRITE$488, message packet) to the request queue

            ELSEIF special function request THEN

                IF message text is "TLK" THEN
                    Add (TALK$488, address) to the request queue
                ELSEIF message text is "LIS" THEN
                    Add (LISTEN$488, address) to the request queue
                ELSEIF message text is "SPC" THEN
                    Add (SPC$488) to the request queue
                ELSEIF message text is "IFC" THEN
                    Add (ASSERT$IFC, listener, address) to the request queue
                ELSEIF message text is "DC" THEN
                    Add (ASSERT$DC, listener, address) to the request queue
                ELSEIF message text is "SRQ" THEN
                    Add (ASSERT$SRQ, status byte) to the request queue
                ELSEIF message text is "SYC" THEN
                    Add (SYSTEM$CONTROLLER) to the request queue
                ENDIF ;

                IF message text segment is to be deleted THEN
                    Delete the message text segment
                ENDIF ;
                Delete the mailbox message packet

            ENDIF ;

            IF request queue was empty THEN
                Issue software interrupt to the IEEE-488 interrupt service task
            ENDIF

        ENDDO ;    /* For each mailbox message. */


/* Check for completed operations.  Delay handling input operations (which
   require memory segments) until after any possible memory deallocation has
   taken place. */

        DO WHILE completion queue is not empty

            Get next entry from the completion queue ;

            IF READ$488 completed THEN

                Get the last byte pointer from the completion queue ;
                Add (READ$488, last byte pointer) to the input list

            ELSEIF SPC$488 completed THEN

                Get the device address and status from the completion queue ;
                Add (SPC$488, device address, status) to the input list

            ELSEIF WRITE$488 completed THEN

                Get mailbox message packet from the completion queue ;
                IF message text segment is to be deleted THEN
                    Delete the message text segment
                ENDIF ;
                Delete the mailbox message packet

            ENDIF

        ENDDO ;    /* For each completed operation. */


/* Check for completed input operations. */

        DO WHILE input list is not empty

            Get next entry from the input list ;

            IF READ$488 completed THEN

                Get last byte pointer from the input list ;
                Determine length of input data record ;
                Allocate a memory segment of that length ;
                Move data record from input queue to memory segment ;
                Allocate a mailbox message packet ;
                Message source = "488" ;
                Message destination = "TIR" ;
                Message function = "INPUT/DELETE" ;
                Message length = input data length ;
                Message location = address of input data segment ;
                Send the message to the RPU_MESSAGE mailbox

            ELSEIF SPC$488 completed THEN

                Get device address from the input list ;
                Get device status from the input list ;
                Allocate a message text segment ;
                Message text = "SPC device status" ;
                Allocate a mailbox message packet ;
                Message source = "488" ;
                Message destination = "TIR" ;
                Message function = "SPECIAL/DELETE" ;
                Message location = address of message text ;
                Send the message to the RPU_MESSAGE mailbox

            ENDIF

        ENDDO    /* For each input completed. */


    ENDDO    /* Forever. */


END  IEEE_488_Driver_Task.

4.5 IEEE-488 Interrupt Service Task

4.5.1 Functional Summary

The IEEE-488 interrupt service task and its associated interrupt handler respond to interrupts generated by the iSBX 488 GPIB Multimodule board. Interrupts are initially received by the interrupt handler. Byte In (BI) and Byte Out (BO) interrupts are processed directly by the interrupt handler. For the other interrupts, the handler adds the interrupt to an event queue and signals the interrupt service task. The interrupt service task processes the interrupt as necessary. If an operation has been completed (i.e., end of input or output complete), then the operation is queued to the driver task for final processing. After any operation completes (indicating that the interface is now idle), the interrupt service task initiates the processing of requests queued to it by the driver task.

4.5.2 Control

Semaphore  488_EXCHANGE - Set to indicate that an event has occurred to which
                the IEEE-488 driver task must respond.

Common     IEEE_488_COMPLETION_QUEUE - Functions completed on the IEEE-488 bus.
           IEEE_488_REQUEST_QUEUE - Functions requested on the IEEE-488 bus.

Common     IEEE_488_EVENT_QUEUE - Interrupts that have occurred.
           IEEE_488_INPUT_QUEUE - Data input from the IEEE-488 bus.
           IEEE_488_OUTPUT_BUFFER - Current output buffer.


BEGIN  IEEE_488_Interrupt_Service_Task

    Lookup the 488_EXCHANGE semaphore ;

    Configure the iSBX 488 Multimodule interface board as a talker/listener ;

    Declare the IEEE-488 interrupt handler and associate this task with it ;

    Signal the 488_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on an IEEE-488 interface interrupt ;


        DO WHILE event queue is not empty

            Get next entry from the event queue ;

            IF event is END interrupt THEN
                Add (READ$488, input queue rear) to the completion queue ;
                Signal the 488_EXCHANGE semaphore
            ELSEIF event is output completion THEN
                Add (WRITE$488, message packet) to the completion queue ;
                Signal the 488_EXCHANGE semaphore
            ELSEIF event is Serial Poll Complete interrupt THEN
                /*	SRQ acknowledged. */
            ELSEIF event is SRQ THEN
                Conduct a serial poll ;
                DO for each device that responded
                    Add (SPC$488, device address, status) to the completion queue
                ENDDO ;
                Signal the 488_EXCHANGE semaphore
            ELSEIF event is Interface or Device Clear interrupt THEN
                Signal the REBOOT semaphore ;
                Delete this job
            ELSEIF no event THEN
                /* Used by the driver task to wake up the interrupt service task. */
            ELSE
                Add (ERROR, event) to the completion queue ;
                Signal the 488_EXCHANGE semaphore
            ENDIF

        ENDDO ;    /* For each event. */


        DO WHILE request queue is not empty AND no operation is in progress

            Get next entry from the request queue ;

            IF WRITE$488 requested THEN
                Get the message packet from the request queue ;
                Set up the output buffer parameters for the interrupt handler
            ELSEIF TALK$488 requested THEN
                Get the device address from the request queue ;
                Address the device as a talker
            ELSEIF LISTEN$488 requested THEN
                Get the device address from the request queue ;
                Address the device as a listener
            ELSEIF SPC$488 requested THEN
                Conduct a serial poll ;
                DO for each device that responded
                    Add (SPC$488, device, status) to the completion queue
                ENDDO ;
                Signal the 488_EXCHANGE semaphore
            ELSEIF ASSERT$IFC requested THEN
                Assert Interface Clear on the bus
            ELSEIF ASSERT$DC requested THEN
                Assert Device Clear on the bus
            ELSEIF ASSERT$SRQ requested THEN
                Assert SRQ on the bus
            ELSEIF SYSTEM$CONTROLLER requested THEN
                Configure the IEEE-488 interface as the system controller
            ENDIF

        ENDDO    /* Process requests. */


    ENDDO    /* For each interrupt. */


END  IEEE_488_Interrupt_Service_Task.

4.6 IEEE-488 Interrupt Handler

4.6.1 Functional Summary

The IEEE-488 interrupt handler is invoked by the operating system to handle interrupts generated by the iSBX 488 GPIB Multimodule board. The interrupt handler is declared by the IEEE-488 interrupt service task. The handler directly handles Byte In and Byte Out interrupts; the other interrupts are passed on to the interrupt service task for processing:

4.6.2 Control

Common     IEEE_488_EVENT_QUEUE - Interrupts that have occurred.
           IEEE_488_INPUT_QUEUE - Data input from the IEEE-488 bus.
           IEEE_488_OUTPUT_BUFFER - Current output buffer.


BEGIN  IEEE_488_Interrupt_Handler


    DO for each event that occurred


        IF event is a Byte Out interrupt THEN

            IF more bytes to be output THEN
                IF last byte in output buffer THEN
                    Assert EOI on next byte output
                ENDIF ;
                Output the next byte in the output buffer
            ENDIF ;

            IF output buffer exhausted THEN
                Add the interrupt to the event queue ;
                Signal the IEEE-488 interrupt service task
            ENDIF

        ELSEIF event is a Byte In interrupt THEN

            Input the byte and add it to the input queue

        ELSEIF event is an Interface or Device Clear interrupt THEN

            Assert INIT on the Multibus ;
            Add the interrupt to the event queue ;
            Signal the IEEE-488 interrupt service task

        ELSE

            Add the interrupt to the event queue ;
            Signal the IEEE-488 interrupt service task

        ENDIF


    ENDDO ;    /* For each event. */


    IF no event detected THEN    /* Software interrupt from the driver task? */

        Add null to the event queue ;
        Signal the IEEE-488 interrupt service task

    ENDIF


END  IEEE_488_Interrupt_Handler.

4.7 RS-232C Driver Task

4.7.1 Functional Summary

The RS-232C driver task controls input from and output to the RS-232C serial link. Output mailbox messages received by the RS-232C driver task specify data that is to be output over the RS-232C serial link. Input from the RS-232C interface is buffered; when a complete record has been assembled, the data is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source for input mailbox messages is the driver task itself (232); the logical destination is the test rack download or main applications task (TIR). The RPU interface task determines the logical source (i.e., when the RS-232C serial link is the source of RPU messages) and physical destination for the messages.

The driver task is the asynchronous source of the following message type:

Requests sent to the RS-232C driver task are queued to the RS-232C interrupt service task for processing when the interface is idle. The following function is available:

4.7.2 Control

Semaphore  MEMORY$WAIT - Implements round-robin scheduling of tasks attempting
                to allocate memory segments.
           REBOOT - Set to inform the user job initialization task that
                re-initialization is to take place.
           RPU_EXCHANGE - Set to indicate that an event has occurred to which
                the RPU interface task must respond.
           232_EXCHANGE - Set to indicate that an event has occurred to
                which the RS-232C driver task must respond.

Mailbox    RPU_MESSAGE - Input message mailbox for the RPU interface task.
           232_MESSAGE - Input message mailbox for the RS-232C driver task.

Common     RS_232C_COMPLETION_QUEUE - Functions completed on the RS-232C
                interface.
           RS_232C_REQUEST_QUEUE - Functions requested for the RS-232C
                interface.

Local      INPUT_LIST - Temporary list of completed reads.


BEGIN  RS_232C_Driver_Task

    Create and catalog the 232_EXCHANGE semaphore with initial value of 0 ;
    Create and catalog the 232_MESSAGE mailbox ;

    Lookup the REBOOT semaphore ;
    Lookup the RPU_EXCHANGE semaphore ;
    Lookup the RPU_MESSAGE mailbox ;

    Create the RS-232C interrupt service task ;
    Wait on the 232_EXCHANGE semaphore for subtask activation ;

    Signal the RPU_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on the 232_EXCHANGE semaphore ;


/* Check for incoming requests from the RPU interface task. */

        DO WHILE more messages in 232_MESSAGE mailbox

            Read the next message from the 232_MESSAGE mailbox ;

            Add (WRITE$232, message packet) to the request queue ;

            IF request queue was empty THEN
                Issue software interrupt to the RS-232C interrupt service task
            ENDIF

        ENDDO ;    /* For each mailbox message. */


/* Check for completed operations.  Delay handling input operations (which
   require memory segments) until after any possible memory deallocation has
   taken place. */

        DO WHILE completion queue is not empty

            Get next entry from the completion queue ;

            IF READ$232 completed THEN

                Get the last byte pointer from the completion queue ;
                Add (READ$232, last byte pointer) to the input list

            ELSE

                Get mailbox message packet from the completion queue ;
                IF message text segment is to be deleted THEN
                    Delete the message text segment
                ENDIF ;
                Delete the mailbox message packet

            ENDIF

        ENDDO ;    /* For each completed operation. */


/* Check for completed input operations. */

        DO WHILE input list is not empty

            Get next entry from the input list ;

            Get last byte pointer from the input list ;
            Determine length of input data record ;
            Allocate a memory segment of that length ;
            Move data record from input queue to memory segment ;
            Allocate a mailbox message packet ;
            Message source = "232" ;
            Message destination = "TIR" ;
            Message function = "INPUT/DELETE" ;
            Message length = input data length ;
            Message location = address of input data segment ;
            Send the message to the RPU_MESSAGE mailbox

        ENDDO    /* For each input completed. */


    ENDDO    /* Forever. */


END  RS_232C_Driver_Task.

4.8 RS-232C Interrupt Service Task

4.8.1 Functional Summary

The RS-232C interrupt service task and its associated interrupt handler respond to interrupts generated by the 8274 MPSC channel assigned to the RS-232C serial link. Interrupts are initially received by the interrupt handler. Receive Character Available (RCA) and Transmit Buffer Empty (TBE) interrupts are processed directly by the handler. For the other interrupts, the handler adds the interrupt to an event queue and signals the interrupt service task. The interrupt service task processes the interrupt as necessary. If an operation has been completed (i.e., end of input or output complete), then the operation is queued to the driver task for final processing. After any operation completes (indicating that the interface is now idle), the interrupt service task initiates the processing of requests queued to it by the driver task. The following events are signalled to the interrupt service task by the interrupt handler:

4.8.2 Control

Semaphore  232_EXCHANGE - Set to indicate that an event has occurred to which
                the RS-232C driver task must respond.

Common     RS_232C_COMPLETION_QUEUE - Functions completed on the RS-232C
                interface.
           RS_232C_REQUEST_QUEUE - Functions requested for the RS-232C
                interface.

Common     RS_232_EVENT_QUEUE - Interrupts that have occurred.
           RS_232_INPUT_QUEUE - Data input from the RS-232C interface.
           RS_232_OUTPUT_BUFFER - Current output buffer.


BEGIN  RS_232C_Interrupt_Service_Task

    Lookup the 232_EXCHANGE semaphore ;

    Configure channel B of the 8274 MPSC RS-232C interface ;

    Declare the RS-232C interrupt handler and associate this task with it ;

    Signal the 232_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on an RS-232C interface interrupt ;


        DO WHILE event queue is not empty

            Get next entry from the event queue ;

            IF event is input completion THEN
                Add (READ$232, input queue rear) to the completion queue ;
                Signal the 232_EXCHANGE semaphore
            ELSEIF event is output completion THEN
                Add (WRITE$232, message packet) to the completion queue ;
                Signal the 232_EXCHANGE semaphore
            ELSEIF no event THEN
                /* Used by the driver task to wake up the interrupt service task. */
            ELSE
                Add (ERROR, event) to the completion queue ;
                Signal the 232_EXCHANGE semaphore
            ENDIF

        ENDDO ;    /* For each event. */


        DO WHILE request queue is not empty AND no operation is in progress

            Get next entry from the request queue ;

            IF WRITE$232 requested THEN
                Get the message packet from the request queue ;
                Set up the output buffer parameters for the interrupt handler
            ENDIF

        ENDDO    /* Process requests. */


    ENDDO    /* For each interrupt. */


END  RS_232C_Interrupt_Service_Task.

4.9 RS-232C Interrupt Handler

4.9.1 Functional Summary

The RS-232C interrupt handler is invoked by the operating system to handle interrupts generated by the 8274 MPSC RS-232C interface. The interrupt handler is declared by the RS-232C interrupt service task and processes the following interrupts:

Data is input until a non-printing ASCII character (i.e., control characters) is received, at which point the interrupt handler signals the interrupt service task. Data is output until the output buffer is exhausted, at which point the interrupt service task is signalled.

4.9.2 Control

Common     RS_232_EVENT_QUEUE - Interrupts that have occurred.
           RS_232_INPUT_QUEUE - Data input from the RS-232C interface.
           RS_232_OUTPUT_BUFFER - Current output buffer.


BEGIN  RS_232C_Interrupt_Handler


    DO for each event that occurred


        IF Receive Character Available THEN

            Input the byte and add it to the input queue ;
            IF new byte is a non-printable ASCII character THEN
                Add the interrupt to the event queue ;
                Signal the RS-232C interrupt service task
            ENDIF

        ELSEIF Transmit Buffer Empty THEN

            IF more bytes to be output THEN
                Output the next byte in the output buffer
            ENDIF ;

            IF output buffer exhausted THEN
                Add the interrupt to the event queue ;
                Signal the RS-232C interrupt service task
            ENDIF

        ELSE

            Add the interrupt to the event queue ;
            Signal the RS-232C interrupt service task

        ENDIF


    ENDDO ;    /* For each event. */


    IF no event detected THEN    /* Software interrupt from the driver task? */

        Add null to the event queue ;
        Signal the RS-232C interrupt service task

    ENDIF


END  RS_232C_Interrupt_Handler.

4.10 Console Driver Task

4.10.1 Functional Summary

The console driver task controls input from and output to the console terminal. Output mailbox messages received by the console driver task specify text that is to be displayed on the console screen. Input from the console keyboard is buffered; when a complete line has been assembled, the text is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source and logical destination for input mailbox messages are both unknown (UNK); the RPU interface task determines the logical source and physical destination for the messages, thereby allowing the console to simulate any of the other interfaces.

A number of special commands can be entered at the console terminal to modify the source/destination translation tables or to simulate different interfaces. Normally, the user is presented with this prompt:

    XXX->YYY?

where source substitution "UNK->XXX" and destination mapping "UNK->YYY" are the current definitions. The user can then enter the text of a message to be sent to the destination task. The first character of the line entered specifies the function type of the message ("I" for INPUT, "O" for OUTPUT, and "S" for SPECIAL):

Hitting the escape key elicits the following prompt:

    Universal?

The user can then enter one of the following commands:

DEBUG
Enter the system debugger.

ECHO {ON/OFF} {NUL/TIR/RPU/488/232}
Control echoing of messages with the specified logical destination.

REDIRECT {TIR/RPU/488/232/CON} TO {NUL/TIR/RPU/488/232/CON}
Redirect messages with the specified logical destination to the specified physical destination. For example, "REDIRECT 488 TO CON" redirects output for the IEEE-488 bus to the console (note that this is not the same as ECHO). "REDIRECT XXX TO NUL" causes messages with destination XXX to be discarded.

RESET
The hardware is reset and the applications firmware is re-downloaded.

RESTART
The applications firmware is restarted (the firmware is not downloaded again).

SEND {TIR/RPU/488/232/CON} TO {NUL/TIR/RPU/488/232/CON}
Specify the logical source and physical destination for messages originating at the console. For example, "SEND RPU TO TIR" allows the user to enter RPU messages at the console and send them to the applications firmware.

SOURCE {TIR/RPU/488/232/CON} AS {TIR/RPU/488/232/CON}
Substitute the specified logical source (second argument) for the the specified physical source (first argument) in messages from the physical source. For example, "SOURCE 232 AS RPU" lets the RS-232C serial link act as a source of RPU messages.

STATUS
Displays the status of the I/O network; i.e., the echo, source substitution, and destination mapping tables.

Requests sent to the console driver task are queued to the console interrupt service task for processing when the interface is idle. Since the console can simulate any of several destinations, the response to any request is simply to display the request's source, destination, function type, and message text on the console (i.e., the console can't perform IEEE-488 functions, etc.). The format of the display is as follows:

    SRC->DST[F]: message text

The function types include:

4.10.2 Control

Semaphore  MEMORY$WAIT - Implements round-robin scheduling of tasks attempting
                to allocate memory segments.
           REBOOT - Set to inform the user job initialization task that
                re-initialization is to take place.
           RPU_EXCHANGE - Set to indicate that an event has occurred to which
                the RPU interface task must respond.
           CONSOLE_EXCHANGE - Set to indicate that an event has occurred to
                which the console driver task must respond.

Mailbox    RPU_MESSAGE - Input message mailbox for the RPU interface task.
           CONSOLE_MESSAGE - Input message mailbox for the console driver task.

Common     CONSOLE_COMPLETION_QUEUE - Functions completed on the console.
           CONSOLE_REQUEST_QUEUE - Functions requested for the console.

Local      INPUT_LIST - Temporary list of completed reads.


BEGIN  Console_Driver_Task

    Create and catalog the CONSOLE_EXCHANGE semaphore with initial value of 0 ;
    Create and catalog the CONSOLE_MESSAGE mailbox ;

    Lookup the REBOOT semaphore ;
    Lookup the RPU_EXCHANGE semaphore ;
    Lookup the RPU_MESSAGE mailbox ;

    Create the console interrupt service task ;
    Wait on the CONSOLE_EXCHANGE semaphore for subtask activation ;

    Signal the RPU_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on the CONSOLE_EXCHANGE semaphore ;


/* Check for incoming requests from the RPU interface task. */

        DO WHILE more messages in CONSOLE_MESSAGE mailbox

            Read the next message from the CONSOLE_MESSAGE mailbox ;

            Add (WRITE$CONSOLE, message packet) to the request queue ;

            IF request queue was empty THEN
                Issue software interrupt to the console interrupt service task
            ENDIF

        ENDDO ;    /* For each mailbox message. */


/* Check for completed operations.  Delay handling input operations (which
   require memory segments) until after any possible memory deallocation has
   taken place. */

        DO WHILE completion queue is not empty

            Get next entry from the completion queue ;

            IF READ$CONSOLE completed THEN

                Get the last byte pointer from the completion queue ;
                Add (READ$CONSOLE, last byte pointer) to the input list

            ELSE

                Get mailbox message packet from the completion queue ;
                IF message text segment is to be deleted THEN
                    Delete the message text segment
                ENDIF ;
                Delete the mailbox message packet

            ENDIF

        ENDDO ;    /* For each completed operation. */


/* Check for completed input operations. */

        DO WHILE input list is not empty

            Get next entry from the input list ;

            Get last byte pointer from the input list ;
            Determine length of input data record ;
            Allocate a memory segment of that length ;
            Get first character of data record indicating function type ;
            Move rest of data record from input queue to memory segment ;

            IF function character is escape THEN

                Get the command and arguments from the input line ;

                CASE OF command IS
                    DEBUG:
                        Software interrupt into the system debugger
                    ECHO:
                        IF arg1 is OFF THEN
                            Turn off echo for arg2
                        ELSEIF arg1 is ON THEN
                            Turn on echo for arg2
                        ENDIF
                    REDIRECT:
                        Map destination arg1 to arg2
                    RESET:
                        Signal the REBOOT semaphore
                    RESTART:
                        Signal the DOWNLOAD semaphore ;
                        Signal the REBOOT semaphore
                    SEND:
                        Substitute source arg1 for UNK ;
                        Map destination UNK to arg2
                    SOURCE:
                        Substitute source arg2 for arg1
                    STATUS:
                        Display the echo table ;
                        Display the source substitution table ;
                        Display the destination mapping table
                ELSE
                    Ignore
                ENDCASE ;

                Delete the input memory segment

            ELSE

                Allocate a mailbox message packet ;
                Message source = "UNK" ;
                Message destination = "UNK" ;
                CASE OF function character IS
                    "I":  Message function = "INPUT/DELETE"
                    "O":  Message function = "OUTPUT/DELETE"
                    "S":  Message function = "SPECIAL/DELETE"
                ELSE
                    Message function = "OUTPUT/DELETE"
                ENDCASE ;
                Message length = input data length - 1 ;
                Message location = address of input data segment ;
                Send the message to the RPU_MESSAGE mailbox

            ENDIF

        ENDDO    /* For each input completed. */


    ENDDO    /* Forever. */


END  Console_Driver_Task.

4.11 Console Interrupt Service Task

4.11.1 Functional Summary

The console interrupt service task and its associated interrupt handler respond to interrupts generated by the 8274 MPSC channel assigned to the console terminal. Interrupts are initially received by the interrupt handler. Receive Character Available (RCA) and Transmit Buffer Empty (TBE) interrupts are processed directly by the handler. For the other interrupts, the handler adds the interrupt to an event queue and signals the interrupt service task. The interrupt service task processes the interrupt as necessary. If an operation has been completed (i.e., end of input or output complete), then the operation is queued to the driver task for final processing. After any operation completes (indicating that the interface is now idle), the interrupt service task initiates the processing of requests queued to it by the driver task. The following events are signalled to the interrupt service task by the interrupt handler:

4.11.2 Control

Semaphore  CONSOLE_EXCHANGE - Set to indicate that an event has occurred to
                which the console driver task must respond.

Common     CONSOLE_COMPLETION_QUEUE - Functions completed on the console.
           CONSOLE_REQUEST_QUEUE - Functions requested on the console.

Common     CONSOLE_COMPLETION_QUEUE - Functions completed on the console.
           CONSOLE_REQUEST_QUEUE - Functions requested for the console.

Common     CONSOLE_EVENT_QUEUE - Interrupts that have occurred.
           CONSOLE_INPUT_QUEUE - Data input from the console.
           CONSOLE_OUTPUT_BUFFER - Current output buffer.


BEGIN  Console_Interrupt_Service_Task

    Lookup the CONSOLE_EXCHANGE semaphore ;

    Configure channel B of the 8274 MPSC interface for the console terminal ;

    Declare the console interrupt handler and associate this task with it ;

    Signal the CONSOLE_EXCHANGE semaphore to indicate task activation ;


    DO forever

        Wait on a console interface interrupt ;


        DO WHILE event queue is not empty

            Get next entry from the event queue ;

            IF event is input completion THEN
                Add (READ$CONSOLE, input queue rear) to the completion queue ;
                Signal the CONSOLE_EXCHANGE semaphore
            ELSEIF event is output completion THEN
                IF prolog output complete THEN
                    Set up the text output parameters for the interrupt handler
                ELSEIF text output complete THEN
			/* Output epilog of carriage return and line feed. */
                    Set up the epilog output parameters for the interrupt handler
                ELSEIF epilog output complete THEN
                    Add (WRITE$CONSOLE, message packet) to the completion queue ;
                    Signal the CONSOLE_EXCHANGE semaphore
                ENDIF
            ELSEIF no event THEN
                /* Used by the driver task to wake up the interrupt service task. */
            ELSE
                Add (ERROR, event) to the completion queue ;
                Signal the CONSOLE_EXCHANGE semaphore
            ENDIF

        ENDDO ;    /* For each event. */


        DO WHILE request queue is not empty AND no operation is in progress

            Get next entry from the request queue ;
            Get the message packet from the request queue ;
            Construct the output prolog ;	/* "SRC->DST[F]: " */
            Set up the prolog output parameters for the interrupt handler

        ENDDO ;    /* Process requests. */


        IF no operation is in progress THEN

            Construct the input prompt ;	/* "SRC->DST? " */
            Set up the prompt output parameters for the interrupt handler

        ENDIF


    ENDDO    /* For each interrupt. */


END  Console_Interrupt_Service_Task.

4.12 Console Interrupt Handler

4.12.1 Functional Summary

The console interrupt handler is invoked by the operating system to handle interrupts generated by the 8274 MPSC console interface. The interrupt handler is declared by the console interrupt service task and processes the following interrupts:

Data is input until a non-printing ASCII character (i.e., control characters) is received, at which point the interrupt handler signals the interrupt service task. Data is output until the print buffer is exhausted, at which point the interrupt service task is signalled.

4.12.2 Control

Common     CONSOLE_EVENT_QUEUE - Interrupts that have occurred.
           CONSOLE_INPUT_QUEUE - Data input from the console.
           CONSOLE_OUTPUT_BUFFER - Current output buffer.


BEGIN  Console_Interrupt_Handler


    DO for each event that occurred


        IF Receive Character Available THEN

            Input the byte and add it to the input queue ;
            IF new byte is printable ASCII character THEN
                Inhibit pending Transmit Buffer Empty interrupt ;
                Poll Transmit Buffer Empty status ;
                Echo the byte
            ELSE
                Add the interrupt to the event queue ;
                Signal the console interrupt service task
            ENDIF

        ELSEIF Transmit Buffer Empty THEN

            IF more bytes to be output THEN
                Output the next byte in the output buffer
            ENDIF ;

            IF output buffer exhausted THEN
                Add the interrupt to the event queue ;
                Signal the console interrupt service task
            ENDIF

        ELSE

            Add the interrupt to the event queue ;
            Signal the console interrupt service task

        ENDIF


    ENDDO ;    /* For each event. */


    IF no event detected THEN    /* Software interrupt from the driver task? */

        Add null to the event queue ;
        Signal the console interrupt service task

    ENDIF


END  Console_Interrupt_Handler.
 

5 Verification Provisions

 

6 Notes


Alex Measday  /  E-mail