CHAPTER 1

The central Input/Output utility (CIO)


The ATARI computer uses a very easy-to-use input and output system called the Central Input/Output utility, or CIO. Nearly all input or output passes through this utility.

CIO uses eight "channels" as paths for I/O. There are not really separate channels for I/O but the computer acts as if there were. Each channel is controlled by a 16 byte block of memory called an Input/Output Control Block or IOCB. The channels are used by putting the proper numbers in the proper IOCB bytes then jumping to the CIO routine. In BASIC, complete I/O operations can be as easy as typing a command such as LPRINT. In this case BASIC does all the work for you.


THE CIO CHANNELS

There are eight CIO channels, numbered from 0 to 7. In BASIC some channels are reserved for BASIC's use.

                     BASIC CIO channel assignments
     
      Channel   0    Permanently assigned to the screen editor
                6    Used for graphics commands
                7    Used for the Cassette, disk and printer
     

Channels 6 and 7 are free to use when they are not being used by BASIC. With machine language, all of the channels are available to the programmer.


THE IOCB STRUCTURE

The IOCB for channel zero starts at address $0340 (decimal 832). This is the only address you need to know. Indexing from this address is used to find all of the other bytes. Below are the names and uses of the IOCB bytes.

                        IOCB bytes and uses:
     
     
     ADDRESS   NAME     EXPLANATION
     
     
      $0340    ICHID    handler Identifier
      $0341    ICDNO    device number (disk)
      $0342    ICCOM    command
      $0343    ICSTA    status
      $0344    ICBAL    buffer address (low byte)
      $0345    ICBAH    buffer address (high byte)
      $0346    ICPTL    address of put byte
      $0347    ICPTH     routine (used by BASIC)
      $0348    ICBLL    buffer length (low byte)
      $0349    ICBLH    buffer length (high byte)
      $034A    ICAX1    auxiliary information
      $034B    ICAX2    -
      $034C    ICAX3    the remaining auxiliary
      $034D    ICAX4    bytes are rarely used
      $034E    ICAX5    -
      $034F    ICAX6    -
     

ICHID

When a channel is open, the handler I.D. contains an index to the handler table. The handler table (to be discussed later) holds the address of the device handling routines. When the channel is closed ICHID contains $FF.

ICDNO

The device number is used to distinguish between multiple devices with the same name, such as disk drives.

ICCOM

The command byte tells CIO what operation to perform.

                    CIO command codes
     
     
                    HEX       DEC
     
     
         +Open      $03         3
         +close     $0C        12
          get       $07         7
          put       $09        11
          input     $05         5
          print     $09         9
         +status
          request   $0D        13
        +*special  >$0D       >13
     
     
        + command may be made to a closed channel
        * device specific commands
     

ICSTA

The status byte contains an error code if something goes wrong. If bit 7 is 0 there have been no errors.

ICBAL and ICBAH

Before a channel is opened, the buffer address bytes are set point to the block of memory which contains the name of the device the channel is to be opened to. Before actual input or output these bytes are set to point to the block of memory where the I/O data is stored or is to be stored.

ICPTL and ICPTH

The put routine pointer is set by CIO to point to the handlers' put-byte routine. When the channel is closed the pointer points to the IOCB-closed routine. This pointer is only used by BASIC.

ICBLL and ICBLH

The buffer length bytes show the number of bytes in the block of memory used to store the input or output data. (See ICBAL and ICBAH.) If the amount of data read during an input operation is less than the length of the buffer, the number of bytes actually read will be put in ICBLL and ICBLH by CIO.

ICAX1 through ICAX6

The auxiliary information bytes are used to give CIO or the device any special information needed.


OPENNING A CIO CHANNEL

Before using a CIO channel it must be assigned to an I/O device. In machine language you start by putting the channel number in the four high bits of the 6502 X register (X = $30 for channel three). Next you place the necessary codes (parameters) into IOCB 0 indexed by X. The X register will cause the numbers to be offset in memory by 16 times the channel number. This puts the numbers into the correct IOCB instead of IOCB 0. Below are the parameters used to open a channel.

                Channel-open parameters:
     
      ICCOM     open code
      ICBAL     address of device name
      ICBAH      in memory
      ICAX1     direction code
      ICAX2     zero
     

The direction code byte in ICAX1 takes on the following format:

                 ICAX1 format for opening a channel
     
                  7 6 5 4 3 2 1 0
                 -----------------
      ICAX1      |        W R    |
                 -----------------
                          8 4 2 1
     
      W   1 = open for output (write)
      R   1 = open for input (read)
     

ICAX1 may have the following data

                      CIO direction codes
     
           HEX  DEC   operation
     
           $04    4   input
           $08    8   output
           $0C   12   input and output (cannot change the length
                      of a disk file)
     

ICBAL and ICBAH point to the device name stored in memory. The device and file name must be followed by 0 or $9B (decimal 155).

Once the parameters are set, jumping (JSR) to the CIO vector

(CIOV) at address $E456 (58454) will cause the channel to be opened. In the following example a basic knowledge of assembly language is assumed.

            Routine to open channel 1 to the keyboard:
     
            ICHID = $0340
            ICCOM = ICHID+2
            ICAX1 = ICHID+10
            ICAX2 = ICHID+11
            IOCB1 = $10      channel in four high bits
            CIOV  = $E456
            OPEN  = $03
            OREAD = $04 ;open for input
            ERROR = (address of error handling routine)
           ;
      START LDX IOCB1
            LDA OPEN
            STA ICCOM,X
            LDA NAME
            STA ICBAH,X
            LDA OREAD
            STA ICAX1,X
            LDA #0
            STA ICAX2,X
            JSR CIOV
            BPL OK
            JMP ERROR
           ;
      NAME  .BYTE "K:",$9B
      OK    (program continues here)
     
     

To open a CIO channel in BASIC the OPEN command is used.

 
        BASIC OPEN command format:
     
        OPEN #channel,aux1,aux2,device:file name
     
     
        aux1 = direction code
        aux2 = special code
     
     

To open channel 1 to the keyboard in BASIC Type:

     
      OPEN #1,4,0,"K:"
     
     

The third parameter, aux2, is a rarely used special parameter. One use is to keep the screen from erasing when changing graphics modes.

The fourth parameter is the device to open the channel to. It may be either a string in quotes or a string variable.

              CIO device names
     
     
          C   cassette recorder
         *D   disk drive
          E   screen editor
          K   Keyboard
          P   printer
         *R   RS 232 I/O port
          S   screen handler
     
     
         * Uses a non-resident handler loaded by the device at
           power-up.
     
     

The device name must usually be followed by a colon. With the disk drive a file name is expected after the device name. The screen handler is used for graphics. The screen editor uses both the keyboard handler and the screen handler to work between the keyboard and screen.


USING AN OPEN CHANNEL

Once a channel is opened to a device you have several options:

     INPUT:  (ICCOM = $05)
     

The computer reads data from the device until a carriage-return is read (decimal number 155, hex $9B) or the end of the file (EOF) is reached. A carriage return is also known as an End-Of-Line or EOL. The IOCB input parameters are:

               IOCB input parameters:
     
      ICCOM    get record code
      ICBAL    address of buffer to
      ICBAH     store the data in
      ICBLL    length of the data
      ICALH     buffer
     

The following routine demonstrates the input command in assembly language. Some of the equates are in the channel openning example above.

             Input routine:
     
             GETREC = $05
             BUFF   = (address to store data at)
             BUFLEN = (number of bytes available at storage address)
            :
             LDX IOCB1
             LDA GETREC
             STA ICCOM,X
             LDA < BUFF
             STA ICBAL,X
             LDA > BUFF
             STA ICBAH,X
             LDA < BUFLEN
             STA ICBLL,X
             LDA > BUFLEN
             STA ICBLH,X
             JSR CIOV
             BPL OK2
             JMP ERROR
            :
      OK2    (continues if no errors)
     

If the data retrieved is shorter than the prepared buffer, the number of bytes actually read will be put into ICBLL and ICBLH.

In BASIC, the INPUT command is used.

             BASIC INPUT command format:
     
      INPUT #channel,string variable
     
                                      or
     
      INPUT #channel,arithmetic variable
     
                                 For example:
     
      INPUT #1,IN$
     

The above commands will cause the data from the device to be put into the specified buffer (IN$ in the BASIC example) until an EOL is reached. If the INPUT statement is used again, without closing the channel, the computer will get more data from the device until another EOL is read or the end of the file is reached. The new data will write over the old data in the input string or buffer. If an arithmetic variable is used, only numbers can be input.

     PRINT:  (ICCOM = $09)
     

In assembly language the print command is identical to the input command. The only difference is that the PUTREC code ($09) is stored in ICCOM. Of course the buffer bytes of the IOCB then specify the block of memory to be output from rather than input to. With the print command, EOLs within the string or buffer are ignored but an EOL is placed at the end of the data when sent to the device.

In BASIC, the PRINT command is used like INPUT except you want to use a semicolon instead of a comma to separate parameters. For example:

      PRINT #1;OUT$
     
                                      or
     
      PRINT #1;"HELLO"
     

If you use a comma, ten space characters will be sent before the string.

If the print command is used again, without closing the channel, the new data will be appended to the end of the data previously sent. Old data will not be written over.

     GET:  (ICCOM = $07)
     

In BASIC this command inputs a single byte of data from the device. EOLs are ignored. In BASIC, GET is used like INPUT except an arithmetic variable must be used. For example:

      GET #1,IN
     

If the get command is used again the next byte from the device will be read. If the end of a file is reached an error will occur.

There is no command in BASIC to input an entire file without stopping at each EOL. If you wish to ignore EOLs while reading a file to a string, you must use the GET command. Each byte of data is then put into the string by the program.

     EXAMPLE:
     
      10 OPEN #1,4,0,"D:TEST"
      20 TRAP 60:REM GOES TO LINE 60 WHEN END OF FILE ERROR OCCURS
      30 GET #1,IN
      40 IN$(LEN(IN$)+1)=CHR$(IN)
      50 GOTO 30
      60 CLOSE #1
     
     

In assembly language, the get command can be used to get any number of bytes from the device. It works just as INPUT does except EOLs are ignored.

              IOCB get-byte parameters:
     
      ICCOM    get-character (single byte) code
      ICBAL   \
      ICBAH    same as in input
      ICBLL
      ICBAH   /
     

Other than the ICCOM code (GETCHR = $07) this command is identical to the input command.

     PUT:  (ICCOM = $0B)
     

In BASIC, PUT is the opposite of GET. It outputs a single byte from a variable to the device. PUT is used the same as GET. For example:

      PUT #1,OUT
     

In assembly language, the command byte of the IOCB is loaded with the put-character code (PUTCHR = $0B). Otherwise the PUT command is identical to GET.


CLOSING A CHANNEL

Closing a channel frees it for use by another device or for changing parameters. In assembly language the close code is put into the command byte of the IOCB then the CIOV call is made.

            IOCB close command:
     
            CLOSE = $0C
           :
            LDX IOCB1
            LDA CLOSE
            STA ICCOM,X
            JSR CIOV
     

In BASIC, use the CLOSE command followed by the channel number.

      CLOSE #1
     

With the disk drive, the file name is not put into the directory until the channel is closed.


THE DEVICE TABLE

CIO uses a jump table located at $031A (794). When a CIO call is made, CIO searches the table for the one-byte device name. The two bytes following the device name contain the address of the device handler's vector table. CIO searches the device table from the end, $033D (829) to the beginning. This way, if a custom handler has ben substituted for a resident handler, the custom handler will be found first. (custom handlers cannot be inserted directly in the place of resident handlers in the device table.)

Each handler has its' own vector table. This vector table is 16 bytes long. The two-byte vectors point to the various handler routines. The vectors are stored in the vector table in the following order:

          Handler vector table order
     
          open
          close
          get byte
          put byte
          get stat
          special
          JMP init code (3 bytes)
     

The open routine should validate the ICAX parameters and check for illegal commands.

The close routine should send any remaining data in the buffer to the device, mark the End-Of-File and update any directories, etc.

The get byte routine should get a byte from the device or the handler buffer and put it in the 6502 A register. Handlers with long timouts must monitor the break key flag and put a $80 in the 6502 Y register if the [BREAK] key is pressed.

The put byte routine should send the byte in the 6502 A register to the device or handler buffer. If the buffer fills, it should be sent to the device. BASIC can call the put byte routine without using CIO.

The get status routine may get 4 bytes of status information from the device and put them in DVSTAT [$02EA] to DVSTAT+3.

For special commands the handler must examine the command byte and find the proper routine entry point.

In all cases the status (error code) of the operation should be put in the 6502 Y register.

To be compatible with all versions of the operating system, the handler must redirect DOSINI [$000C,2 (12)] for initialization upon reset. This initialization must restore the vectors in the handler vector table and jump to the origional DOSINI vector.


SPECIAL COMMANDS

Some devices have special CIO commands. These are known as device specific commands. In assembly language these commands are executed just as any other CIO command is. In BASIC the XIO command is used. An example of the XIO command is:

      XIO command code #channel,aux1,aux2,device:file name
     

To open a channel with the XIO command instead of the OPEN command use:

      XIO 3 #1,4,0,"K:"
     

Note that the above command is identical to the OPEN command except "XIO 3" is used instead of "OPEN". Also note that $03 is the IOCB open code for ICCOM.

     
            Useful database variables and  OS equates
     
     DOSINI $000C,2       (12): initialization vector
     BRKKEY $0011         (17): break key flag
     ICHID  $0340        (832): start of IOCBs
     ICDNO  $0341        (833):
     ICCOM  $0342        (834):
     ICSTA  $0343        (835):
     ICBAL  $0344        (836):
     ICBAH  $0345        (837):
     ICPTL  $0346        (838):
     ICPTH  $0347        (839):
     ICBLL  $0348        (840):
     ICBLH  $0349        (841):
     ICAX1  $034A        (842):
     ICAX2  $034B        (843):
     HATABS $031A,16     (794): device handler table
     CIOV   $E456      (58454): CIO entry vector

	


Go to Table of contents
Go to chapter 2