80-80 List Exectable Code

Now we need to write our executable program.  For now we will focus on our program and not worry about how to get it punched into 80-byte cards.

First we need to establish a base register.  This code is written to be relocatable so it should run from anywhere we place it in memory.  We can move it to somewhere else other than location 1024 by modifying the PSW and the three CCWs used to read in the program.

BEGIN    DS    0D
         BALR  R10,0                * Establish a Base Address
         USING *,R10                * Tell the assembler
*

Next we need to get the device address for the card reader  used for the IPL process.  This is where we will expect to find our data cards.  When the CPU completes the IPL process and loads our initial PSW but before execution begins, the address of the IPL device is saved.  Since we are loading a BC PSW the IPL device address is saved in locations 2 and 3.

         SLR   R3,R3                * Clear Register 3
         ICM   R3,B'0011',2         * Load IPL Device Address
         LA    R4,X'E'              * Assume Printer at 00E
*

We will assume the printer is at device address X’00E’ which is usually a standard place to define a printer.  The standard location for the card reader is X’00C’ and that for the card punch is X’00D’.

Now we can handle some housekeeping to make our program relocatable.  If we were running with the help of an operating system we would probably have a relocating loader.  This means we could use an address constant (ADCON) in our CCW to point to the buffer.  When the loader read our program into memory the value in the ADCON would be relocated or updated to reflect our actual location in memory.

Since we are Bare Metal programming we don’t have an operating system or relocating loader.  In fact our loader is just some CCWs that are executed by the channel at IPL.  We will use a LA and STCM to get the actual address of the buffer at run time and store it into our CCWs.

         LA    R1,RDBUF          * Get the address of the I/O Buf
         STCM  R1,B'0111',RDCCW+1  Place address into Read CCW
         STCM  R1,B'0111',PRCCW+1  Place address into Print CCW

Now we are ready to enter the main loop for our 80-80 List program.  The first thing we want to do is attempt to read a card from the same card reader that was used as the IPL device.  Before issuing the Start I/O we need to place the address of our read CCW into the CAW.

         LA    R1,RDCCW          * Get address of Read CCW
         ST    R1,72             * Place into CAW (location 72)

Our Read CCW should look very familiar since it is almost exactly like the CCWs used in our IPL process.  We will not set any flags in the CCW this time.  Since we are not command chaining our CCW program will consist of a single CCW.  We are using command code X’02’ to read, the address is filled in at run time, and we are expecting 80 bytes of data.  This time we will leave the SLI bit off and if the card reader attempts to transfer more or less than 80 bytes an exceptional condition will occur.

RDCCW    DC    X'02',AL3(0),X'0000',AL2(80)

Now we can issue the Start I/O instruction to cause the channel to execute our channel program.  We have saved the address of the card reader in register three.  We then check the condition code to see if the channel is processing our request.  If not we load a Wait PSW and halt execution.

         SIO   0(R3)             * Issure Start I/O to Channel
         BNZ   ERR1              * If Chan not processing - error

Now we have to wait for the I/O to complete.  Since we have masked all I/O interrupts the CPU will not generate an interrupt when the I/O is complete.  Instead we will use the Test I/O instruction to check on the progress of the channel program.  If the I/O is complete we will branch out of our wait loop.  If the return code indicates the channel or device is not operational we will load a Wait PSW.  If the channel is still busy we will loop back and issue the Test I/O again.

RDTIO    DS    0H
         TIO   0(R3)             * Test for I/O Completion
         BZ    PRT               * Branch if I/O Complete
         BC    1,ERR2            * Branch if not operational
         B     RDTIO             * Loop back and wait for I/O

Now we need to check for successful completion of our channel program.  We know that it completed and the completion status was stored into the CSW as a result of our issuing a Test I/O against the device.  We will test the status bits and we only expect to find Channel End and Device End set.  If we find anything else some type of exceptional condition has occurred.  We use a CLC to compare the two bytes of status bits in the CSW (located at fixed location 68) to a constant with just the Channel End and Device End bits set X’0C00′

PRT      DS    0H
         CLC   CEDE,68           * Compare status bits
         BNE   ERR0              * Branch if not CE+DE
          .
          .
CEDE     DC    X'0C00'           * CE+DE

If we get anything else other than CE+DE we will save the status bits of the CCW into the address portion of a Wait PSW and then load that PSW to halt execution.  The reason we store the status bits in the CSW is so they become the wait code (the address portion of the wait PSW) and are visible on the operator console.

ERR0     MVC   PSWERR0+6(2),68   * Move CSW status bits to PSW
         LPSW  PSWERR0           * Load Wait PSW
          .
          .
PSWERR0  DC    X'00',X'02',X'0000',x'00',x'000000'

If there is no error then we issue a Start and I/O to the printer to print out the contents of the card we just read.  Just as with reading a card we store the address of the CCW into the CAW and then issue the Start I/O against the device.  We check the condition code from the Start I/O to verify the channel program is active.

         LA    R1,PRCCW          * Point to Print CCW
         ST    R1,72             * Store into CAW
         SIO   0(R4)             * Start I/O on Printer
         BNZ   ERR3              * Branch if Error

The CCW to print is similar to the CCW to read a card from the card reader.  Each device has its own set of command codes.  Printers have a number of command codes they respond to. Below is a quick summary of a few command codes for a printer.

01 - Write and Do Not Space
09 - Write and Space 1 Line
11 - Write and Space 2 Lines
19 - Write and Space 3 Lines
0B - Space 1 Line Immediate
13 - Space 2 Lines Immediate
1B - Space 3 Lines Immediate

We will use command code X’09’ to write a line and then space down to the next line.

PRCCW    DC    X'09',AL3(0),X'0000',AL2(80)

As with the read CCW, the data address is filled in at run time.  We will print 80 bytes of data and no flags are set.  Our channel program will consist of a single CCW.

Next we enter a Test I/O loop to wait for completion of the I/O.  For now when the I/O is complete we assume it was successful.  We could check the CSW status bits for any exceptional conditions but we don’t for now to make our program smaller and simpler.

PRTTIO   DS    0H
         TIO   0(R4)             * Wait for I/O to Complete
         BZ    RDLP              * Done - Go read next card
         BC    1,ERR4            * Branch if error
         B     PRTTIO            * Loop back and test again

[Next - Creating The IPL Deck]

Second IPL Card

Now we create our second IPL card containing additional CCWs for reading the cards containing the executable program.  The first CCW contained on this card is branched to by the channel because of the TIC (Transfer In Command) CCW in the previous card.

CARD1    DS    0D
*
CCW3     DC    X’02’         * Read
         DC    AL3(1024)     * Storage Address For Data
         DC    X’60’         * SLI + CC
         DC    X’00’
         DC    AL2(80)       * Length
*
*
CCW4     DC    X’02’         * Read
         DC    AL3(1024+80)  * Storage Address For Data
         DC    X’60’         * SLI + CC
         DC    X’00’
         DC    AL2(80)       * Length
*
*
CCW5     DC    X’02’         * Read
         DC    AL3(1024+160) * Storage Address For Data
         DC    X’20’         * SLI
         DC    X’00’
         DC    AL2(80)       * Length
*
*

There are three CCWs used to read the next three cards.  The first card will be read into location 1024.  The second card will be read into location 1104 (1024+80) and the third to location 1184 (1024+160).  The final CCW does not have the Command Chain bit set.  This will cause the channel program to end after this read is completed.

When the CCWs on this card have executed we will have read 240 bytes of data into memory beginning at location 1024.  This is the same address we specified as the beginning execution address in our load PSW on the first card.

When the final IPL CCW has completed successfully, the CPU will complete the IPL process by loading the initial PSW and begin execution at the address specified.  This will cause our small program to begin executing.

[Next – 80-80 List Executable Code]

80-80 List Stand Alone Program

Now that we have covered the basics we can begin writing our first Bare Metal, Stand Alone program.  This program will IPL from the card reader and execute without any help from an operating system.

For our first program we will attempt something very simple.  We will read cards from a card reader and print them to a printer.  We will call it 80-80 List because it will read eighty bytes from the card reader and print eighty bytes to a printer.

Our IPL deck will consist of five cards.  The first card will contain the 24-byte IPL record expected by the IPL process.  It will read in a second card containing additional CCWs used to read additional cards containing executable code.

For this simple program we will require three cards to contain our executable code so our IPL deck will be a total of five cards.

Immediately following our 5-card IPL deck are the data cards for our program.  The program will continue reading and printing cards until an exceptional condition is detected on the card reader – usually because it is out of cards to read.

If an error condition is detected or when an exceptional condition is encountered on a read operation, a PSW with the wait bit turned on will be loaded with a LPSW command.  This will cause the CPU to stop execution and go into wait mode.

Download the source code: card80

[Next – First IPL Card]

First IPL Card

Now that we have been through an overview of the IPL process and the basic concepts of the PSW and I/O we can begin to construct a deck of cards to IPL from.   We know that if we set the IPL device address to that of a card reader and press the IPL key the CPU will read a single card and transfer the first 24 bytes of data (card columns 1-24) and ignore the rest of the card.

The contents of our first card should be a PSW followed by two CCWs.

IPLCARD0 DS    0D
*
PSW      DC    X’00’       * I/O & External Interrupts Disabled
         DC    X’00’       * Key=0; BC; Ext Int Disabled; Sup State
         DC    X’0000’
         DC    X’00’       * Prog Int Disabled
         DC    AL3(1024)   * Address to begin Execution
*
*
CCW1     DC    X’02’       * Read
         DC    AL3(512)    * Storage Address For Data
         DC    X’60’       * SLI + CC
         DC    X’00’
         DC    AL2(80)     * Length
*
*
CCW2     DC    X’08’       * Transfer In Channel (TIC)
         DC    AL3(512)    * Address of next CCW
         DC    X’00’
         DC    X’00’
         DC    AL2(0)      * Length Not Used For TIC
*
*

 

This makes up the contents of our first IPL record.  The first eight bytes become our initial PSW when the IPL CCW chain is completed.  The first byte contains the interrupt mask flags for channels 0 through 5, the I/O mask bit (for channels 6 and higher) and the External Interrupt mask.  We set all of these to zero which inhibits these conditions from generating an interrupt.

The next byte contains the protection key in the first four bits.  We will initially set our key to zero which will allow us to access any valid memory location.

The next bit is set to zero to indicate a BC mode PSW.  The Machine Check Interrupt mask is set to zero to inhibit interruptions.  The Wait bit is set to zero so the CPU will immediately begin executing instructions.  The Problem State bit is set to zero placing us in Supervisor State therefore allowing us to execute privileged instructions.

The next two bytes are set to all zeros.  These bytes contain the interruption code and are only meaningful in an Old PSW to indicate the source of the interruption.  When the IPL process is completed the address of the IPL device will be stored here.

The next byte contains the Instruction Length Code (ILC), Condition Code and Program Mask.  We set all of these to zero and disallow any of the related program checks from generating interrupts.

The next three bytes contain the memory address of the first instruction to be executed.  It is our responsibility to load a valid instruction sequence into memory starting at this address.

Following the PSW are two CCWs.  The First CCW is a read command (command code = x’02’).  This will cause the next card in our IPL Deck to be read.  We specify a storage location to receive the contents of the card.  The next byte specifies the flags.  We set the Command Chain flag so a new CCW will be fetched upon completion of the read command.  The Suppress Incorrect Length  (SLI) bit is also set to avoid any problems with reading a short or long block of data.  Since we are reading from a card device the block size is set at 80 so we really shouldn’t need to set this flag.  In general it is a good idea to suppress any exceptional conditions possible since at this time there is no option for error recovery.

The next CCW is a Transfer In Channel (TIC) command.  A TIC is a branch command in a channel program.  The TIC will cause a new CCW to be fetched from the address specified.  We will set the address to point to the contents of the card that was read by the previous CCW.

At this point the IPL process has read two cards into memory.  The first card contained two CCWs to read the second card and then load a new CCW.

Card two needs to contain additional CCWs to read additional cards into memory that contain executable code.

[Next – Second IPL Card]

IPL Process

With a basic understanding of the PSW and the I/O process we can now explore the IPL process.  The IPL is initiated by the operator.  The device address of the IPL device is selected by the operator.  When the IPL key is pressed the CPU initiates a read command to the specified IPL device.

The initial read is executed by the channel just as if a Start I/O command had been issued.  An “implied” CCW is generated for this read command.  The protect key value for the CAW is zero.  The implied CCW is a read command with a data address of zero and a length of 24.  The Command Chain and Suppress Incorrect Length bits are set.  The implied CCW address is zero so when the CCW command successfully completes a new CCW will be fetched from location 8 (because the Command Chain flag is set).

When the device signals Device End for the last CCW in the chain and there are no exception conditions a new PSW is loaded from locations 0-7.

When the PSW that is loaded is in BC mode, the I/O address of the IPL device is stored in locations 2 and 3.  When in EC mode the device address is stored in locations 186-187.

The information read into locations 8-15 and 16-23 by the IPL process should contain CCWs for reading additional information into memory.

[Next – 80-80 List Stand Alone Program]

I/O Machine Instructions

There are several machine instructions dedicated to performing I/O operations.  These include Start I/O (SIO), Start I/O Fast Release (SIOF), Test I/O (TIO), Clear I/O (CLRIO), Halt I/O (HIO), Halt Device (HDV), Store Channel ID (STIDC), and Test Channel (TCH).  All I/O instructions are privileged and can only be executed in supervisor state.

Each of these instructions has a single operand in the D2(B2) format where D2 is a displacement value and B2 is a register (0-15).  The operand does not refer to a storage address but instead bits 16-31 of the address value are used to identify a channel/device address for the instruction.

If a register of zero is specified then only the contents of the displacement value are used to specify the device address.

Examples

SIO     X’580’               * Start I/O on device 580

 

LA       1,X’580’

SIO     0(1)                 * Start I/O on device 580

 

LA       1,X’580′

SIO     1(1)                  * Start I/O on device 581

 

Start I/O (SIO)

An I/O operation (write, read, read-backward, control or sense) operation is initiated on the device with the specified channel and device address.  The Channel Address Word (CAW) at storage location 72 must be set prior to the SIO being issued.  The CAW contains the protection key for the channel (in bits 0-3) and the address of the first CCW (in bits 8-31).  A condition code is set to indicate the status of the SIO request.

0 – I/O operation initiated and channel is processing the channel program

1 – CSW stored

2 – Channel or subchannel busy

3 – Not operational

 

Test I/O (TIO)

Returns the status of the channel, subchannel and device by setting the condition code.

0 – Available

1 – CSW Stored

2 – Channel or subchannel busy

3 – Not operational

 

[Next – IPL Process]

Channel Status Word

The Channel Status Word (CSW) is used to provide the status of an I/O device or the status of the last I/O operation completed.  The CSW is updated when an I/O interruption occurs or as a result of an I/O command.  The CSW is available for use until the next I/O interrupt occurs or until another I/O command causes it to be replaced.

When an I/O interruption updates the CSW the I/O device causing the interruption is identified in the Old PSW as the interruption code when operating in BC mode.

The CSW has the following format:

Protection Key (Bits 0-3) indicates the protection key used for the I/O operation.

Logout Pending (L) (Bit 5) When set to one it indicates that an I/O instruction cannot be executed until a pending logout condition has been cleared.

Deferred Condition Code (CC) (Bits 6-7) Indicate a different condition code available for a Start I/O Fast Release after a condition code of zero was returned.

CCW Address (Bits 8-31) Indicate an address eight bytes greater than the last CCW used.

Status (Bits 32-47) These bits identify the condition that caused the CSW to be stored.

  • 32 Attention – The device has detected an asynchronous condition significant to the program
  • 33 Status Modifier – Indicates the device cannot provide its current status in response to a TEST I/O, when the control unit is busy, when the normal sequence of commands has to be modified or when command retry is to be initiated.
  • 34 Control Unit End – Indicates the control unit has become available for use for another operation.
  • 35 Busy – Indicates the I/O device cannot execute the command because it is executing a previously initiated operation or because there is a pending interrupt condition.
  • 36 Channel End – Indicates completion of the portion of an I/O operation involving the transfer of data or control information between the I/O device and the channel.  When command chaining is used Channel End is generated only for the last operation.
  • 37 Device End – Indicates the completion of an I/O operation by the device.  When command chaining is used only the Device End condition for the last operation in the chain is reported.
  • 38 Unit Check – Indicates the I/O device or control unit has detected an unusual condition and additional detail information is available to a sense command.
  • 39 Unit Exception – Indicates a condition reported by an I/O device that does not usually occur.
  • 40 Program Controlled Interruption – This condition is generated when a channel fetches a CCW with the PCI flag set.
  • 41 Incorrect Length – Indicates the number of bytes in storage assigned to the I/O operation is not equal to the number of bytes requested by the device.
  • 42 Program Check – Indicates a programming error in the channel program.  Can occur as a result of an invalid address in the CAW or a TIC CCW, an invalid command code, an invalid count in a CCW, an invalid data address, an invalid CAW format, an invalid CCW format or an invalid sequence of CCWs.
  • 43 Protection Exception – Indicates the channel attempted to access storage that is prohibited by storage protection.
  • 44 Channel Data Check – Indicates a machine error has occurred causing a parity error.
  • 45 Channel Control Check – Indicates a machine error.
  • 46 Interface Control Check – Indicates an invalid signal occurred on the I/O interface.
  • 47 Chaining Check – Indicates a channel overrun during data chaining operations.

Count (Bits 48-63) Contain the residual count for the last CCW.

[Next – I/O Machine Instructions]

Sense Command

The sense command is used to receive both the status of the device and any information about any unusual or error condition for the last operation of the device.

Although sense information is specific to each device usually the first six bits of sense data give information about the conditions detected in the last operation.

Command Reject (Bit 0) indicates the device has detected a programming error.  The device is unable to execute the command because it is invalid for the device or the device cannot currently execute the command (for example the device is write protected).  Command reject can also indicate an invalid sequence of commands.

Intervention Required (Bit 1) The operation could not be executed because the device requires some type of intervention (for example printer needs paper) or the device is in a not ready state.

Bus Out Check (Bit 2) The device has received data with an invalid parity.

Equipment Check (Bit 3) Indicates the device has detected an equipment malfunction.

Data Check (Bit 4) Indicates the device has detected a data error other than those causing a Bus Out Check.

Overrun (Bit 5) Indicates the channel has failed to respond on time to a request from the device.

The final type of CCW command code is the Transfer In Channel (TIC).  It is a branching instruction for the channel command.  Normally when  command chaining is active CCWs are executed sequentially.  A TIC will cause the next CCW to be fetched from the data location specified by the data address in the TIC CCW.  The first CCW pointed to by the CAW cannot be TIC nor can a TIC specify a branch to another TIC CCW.

[Next – Channel Status Word]

Channel Command Word

Each CCW is 64 bits (8 BYTES) in length and has the following format:

Command Code (Bits 0-7) Specifies the I/O operation to be performed.

Data Address (Bits 8-31) Specifies the location in main storage for the data associated with the I/O operation.

Chain Data Flag (CD) (Bit 32) When set to one indicates the chaining of data.  It causes the storage area of the next CCW to be used with the current I/O operation.  The use of data chaining allows data to be transferred to or from noncontiguous areas of storage in a single I/O operation.

Command Chain (CC) (Bit 33) When set to one, and when the CD flag is set to zero, indicates the chaining of commands.  When the operation of the current CCW is complete and Command Chaining is active, the next CCW will become the new current I/O operation.

Suppress Length Indication (SLI) (Bit 34) When set to one and the CD flag is set to zero, the incorrect length indication is suppressed.

Skip (SKIP) (Bit 35) When set to one the transfer of information is suppressed for read and sense operations.

Program Controlled Interrupt (PCI) (Bit 36) When set to one the channel will generate an interruption condition when the CCW begins execution in the channel.

Indirect Data Address (IDA) (Bit 37) When set to one indicates indirect addressing.  The data address of the CCW points to an Indirect Address List instead of directly to the data.

Count (Bits 48-63) Specifies the number of bytes to be used for the I/O operation.

Bits 38-47 should always be set to zeros.

Channel command codes are specific to each individual device but fall into general categories: Write, Read, Read Backward, Control and Sense.  Write transfers data from the processor storage to the device, read and read backward transfer data from the device to processor storage.  Control operations are specific to each device and generally do not involve data transfer but the data address in the CCW may point to an area in storage related to the control operation.

[Next – Sense Command]

 

Input Output Basics

I/O operations on S/370 are used to transfer information to and from I/O devices which are attached to channels.  There are many types of I/O devices including card readers, card punches, printers,  tape devices, terminals and disk storage devices.

A channel attached device can be thought of as a very simple computer that uses a very limited programming language.  The programming instructions are called Channel Command Words (CCW).  A CCW indicates the operation to be performed (such as read a card or print a line), the data location in the processor memory and the length of the data operation.  In addition there are some flags that may be set in the CCW to further indicate how to execute the requested operation.

Each individual device type has a set of commands that it will respond to.  An invalid command will result in an execution error of the channel program.  When writing channel programs it is necessary to know the programming specifications for each specific device being used.

An I/O operation is initiated by building a channel program consisting of one or more CCWs.  The address of the channel program is placed in a fixed position in low storage called the Channel Address Word (CAW).  An I/O operation is initiated using the Start I/O (SIO) instruction. This instruction along with all other I/O commands can only be executed when operating in privileged mode.

When the channel program is complete an I/O interrupt will be generated if interrupts are enabled.  If interrupts are disabled for the device, the interrupt will be queued.  A queued I/O interrupt can be cleared either by enabling interrupts or using the Test I/O (TIO) instruction.

When the pending I/O interrupt condition for a device is cleared the Channel Status Word (CSW) in low storage will be updated providing information on the completion status of the I/O operation.

[Next – Channel Command Word]