Vocademy

Part 4: Input and Output

 Input and output methods

 Mapped I/O

 The most common method of getting data to and from peripheral devices is a system called is mapped I/O. There are two types of mapped I/O, port-mapped I/O and memory-mapped I/O.

 Memory-mapped I/O

With memory-mapped I/O, external devices are wired into the address and data buses such that specific memory addresses connect to the devices. Devices are wired such that when specific addresses are specified on the address bus, circuitry connects the data bus to I/O devices. For example, to send a byte of data out the serial port, that byte is written to a specific memory address that is electrically connected to the serial port subsystem. Other bytes that contain other parameters, such as the speed and parity, are written to nearby addresses also assigned to the serial port subsystem. Yet another byte that constitutes the write command is written to the appropriate address. Finally, the serial port subsystem is triggered to operate. The subsystem reads the parameters as specified and sends the byte out the port.

Port-mapped I/O

With port-mapped I/O, the microprocessor has specific instructions for input and output operations. In addition, during an I/O operation, the entire address and data buses are disconnected from memory and connected to an I/O subsystem. This is similar to memory-mapped I/O, except, In contrast, specific addresses always connect to I/O devices with memory-mapped I/O, and the entire memory subsystem is connected to I/O devices during an I/O operation with port-mapped I/O. Memory addresses are grouped where each group is dedicated to one device. These groups of addresses are called ports.

Extra material

Atari 8-bit Joystick Ports

A straightforward method of getting data into and out of the Atari computer was the joystick ports on the 8-bit series of Atari computers. The original Atari computers had four joystick ports. The joystick had four switches inside, one each for pushing forward, backward, left, and right. Each joystick port had four pins connected to these four switches such that whichever switch was in the "on" position, its corresponding pin would have 5 volts on it (a logical 1). Inside the computer, each pin connected to a custom chip called the PIA chip. This meant that there were a total of 16 active pins that were wired to the PIA chip from the joystick ports. When you pushed forward on a joystick, a specific pin on the PIA chip would have 5 volts on it.

The PIA chip was wired into the memory subsystem so that if you looked at memory address D300 (hexadecimal), you would see the states of joysticks 1 and 2. Looking at D301, you would see the states of joysticks 3 and 4.

Therefore the assembly language instruction "LDA $D300" would copy the information for joystick ports 1 and 2 into the accumulator. If the number found at D300 is 00100001 (21 in hexadecimal), joystick one is pushed left, and joystick two is pushed right. After the instruction "LDA $D301," the data from joystick ports 3 and 4 would be in the accumulator. If the data found was 10000100 (84 in hexadecimal), joystick three is pushed backward, and joystick four is pushed forward.

The joystick ports on the Atari 8-bit computers were bi-directional, meaning they could act as either input or output ports. This allowed virtually any device to be designed to connect to them. Memory address D302 and D303 controlled the direction of the ports. Writing to these addresses controlled whether the ports were in input mode or output mode. When the ports were in output mode, the instructions "LDA #$A5 STA $D300 would put the binary number 10100101 (A5 in hexadecimal) as 5 and 0 volts, respectively, on the eight pins of joystick ports 1 and 2.

In short, depending on the mode of the ports, reading the contents of memory address D300 would read a byte of data presented at joystick ports 1 and 2. Writing data to D300 would write a byte of data to joystick ports 1 and 2.

Atari 8-bit Central I/O utility. 

The Atari 8-bit Central I/O (CIO) utility is another simple example of how computers perform input and output. However, this is a bit different from how the joystick ports work. Instead of writing directly to or reading directly from a memory address, a utility program moves the data from a bufferto the device one byte at a time.
Each device is wired into the address and data buses so that writing to a specific address connects the data bus directly to the device, just like the joystick ports above. However, programmers don't usually write directly to these addresses. Instead, the computer has a set of pre-written routines that a programmer can call upon to do most of the work. The programmer simply tells the routines where the data to send to a device is stored (or where to put data that is input from a device) and then uses a jump-to-subroutine (JSR) instruction to fred[1] the routine.
The Atari 8-bit computers had several blocks of memory called Input/Output Control Blocks (IOCB). To input or output data, a programmer first "opens a channel" by putting specific parameters into an IOCB. These parameters are such as the location in memory of the name of the device to open the channel to and whether the channel is being opened for input (read) or output (write). Once the parameters are in the IOCB, the program does a JSR to the CIO utility routine. Once the channel is open, the parameters in the IOCB are changed to point to the buffer where data is stored, ready for output, or where the input data will be stored. Next, the program does another JSR to the CIO utility, telling it to move the data. Finally, the IOCB is changed again with parameters to close the channel, and a final JSR to the CIO utility is made.
 
The steps to output a block of data are as follows:

   1. Open a channel to the device
   
    Data is put into the IOCB, telling the I/O utility to open a channel, prepare to output to the device, and what the device's name is. Then, the program jumps (JSR) to the I/O utility to open the channel.
     
  2. Send the data
   
    Data is put into the IOCB, telling the I/O utility where the data buffer is.
The program jumps to the I/O utility again to output the data.
     
  3. Close the channel
   
    Data is put into the IOCB, telling the I/O utility to close the channel.
The program jumps to the I/O utility again to close the channel.
 
With more complex I/O devices, such as a hard disk, the data needed to open the channel would include such extra information as the file name to work with.
 
This is, of course, an overview of how a specific computer handles input and output. However, there are similarities with any other computer.

Since this book is not a manual for 6502 or Atari programming—and since every computer would handle the same task in its own way—a detailed example of how this is done would be counterproductive. This brief overview should suffice here:

 

Extra material (continued)

The IBM PC and compatibles use port-mapped I/O.
 
An I/O operation with IBM compatibles is similar to the Atari CIO system above. Each device is assigned a memory block for input and output operations. When the microprocessor is in I/O mode, the address and data buses are connected to the I/O subsystem instead of memory. When a program needs to send or retrieve data from a peripheral device, it stores parameters in predetermined memory addresses and performs a software interrupt that initiates the I/O operation. For example, to retrieve a file from the hard disk, the program will put the file's name in a specific memory location and perform a particular interrupt operation. This initiates the I/O program that retrieves the file from the drive. The file data appears at a specific memory location where the program can access it.
 
In the IBM-compatible computer, a software interrupt is similar to a jump to subroutine. It is invoked with an instruction like, INT13. This will cause the microprocessor to look up the address of the interrupt service routine in the interrupt vector table. This table has 256 four-byte entries, each containing a 16-bit memory address and a 16-bit offset (these are added together the get the actual address). INT13 will use entry number 13 (in hexadecimal, which is the 19th entry in decimal). INT13 is the routine that retrieves a single sector from a disk.
 
The interrupt vector table is like an office building directory. Let's say you need to see Dr. Schwartz. You go to the doctor's office building and look up Dr. Schwartz in the building directory. Next to his name is the office suite number to go to. With the interrupt vector table, it is more like you need to see "Dr. 25". You count the listings until you get to the 25th one, which tells you what suite to go to.
 
When the microprocessor performs an INT 25 instruction, it goes to the 25th entry in the interrupt vector table and then to the address listed there, where it finds the actual program to run.

 

—————————
1The term ''call'' usually means to execute a sub program then return to the main program, like a subroutine.
Vocademy