The input/output system will consist of two primitives callable from user code (good old "putc" and "getc"), and several input/output processes. The "putc" and "getc" functions will be fairly simple. The function declaration for putc should look like:
When called, "putc" will simply send a message containing the character to be printed to the process that handles printing on the specified terminal. The function declaration for getc should look like:putc( ch, termno ) char ch; int termno;
When "getc" is called it will try to receive a message from a mail box to which messages containing all characters read from the specified terminal number are sent.char getc( termno ) int termno;
There are two approaches you could take to the structure of the processes involved. You could have one process that receives all interrupt messages from "interruptBox[0]" and does all the work required to handle those interrupt. Alternately, you could have one process that receives interrupts from "interruptBox[0]" and merely reacts by "forwarding" the message to a mailbox associated with the device on which the completion occurred. In case you can't guess, I would like you to try the second approach. That is, I want you to have one process running for each terminal's output and one process running for each terminal's input.
In this approach, you will have two processes and four mailboxes for each terminal. One process and two mail boxes will be for input from the terminal and the others will be for output to the terminal. Consider how "getc" and the processes and mail boxes involved in handling input will function. Let us call the two mail boxes associated with input on the terminal we are considering "interrupts" and "characters". (2)
The process that handles terminal input will sit in a loop. The first step in the loop will be to wait to receive a message from "interrupts". When such a message arrives, the process will extract the character received from the terminal's input buffer register and send it in a message to the mail box "characters". Then the process will loop back to wait for another message from "interrupts". When "getc" is called it will simply try to receive a message from "characters". If a character has already been sent to "characters" by the driver process, the receive executed by "getc" will complete immediately. Otherwise, the process that called "getc" will be suspended until a completion occurs and a character is sent to "characters". Once the receive does complete, a character can be extracted from the message received and returned as the result of "getc".
Terminal output will function similarly, except you will need an extra primitive "closeterm(termnum)" which can be called to tell the system that no more output will be sent to the terminal whose number is passed as a parameter to the routine. Such a primitive is necessary to enable the system to halt. Basically, once closeterm calls for each of the five terminals have been completed, your system should simply wait for all output queues to empty and then execute a "HALT" instruction.
To make all this work, you will need to be careful about process priorities. The input/output processes should be the highest priority processes in your system (and the input handlers should have higher priorities than the output handlers). You should not, however, have to run these processes with interrupts disabled.