Upper Half Routines

Upper Half Routines

Let's look at some of the routines contained in the upper half of the TTY driver. The four routines we look at here are:

  1. ttygetc - called directly by getc()
  2. ttyputc - called directly by putc()
  3. ttyread - called directly by read()
  4. ttywrite - called directly by write()

Each of these routines take as one of their arguments a pointer to a device descriptor. These are discussed in chapter 11, and contain information such as pointers to I/O routines for that device, and the minor device number for that device (which in the case of TTYs is used to index into the tty[] array to identify which tty we are talking about).

ttygetc()

Ttygetc() is pretty simple. It is used to read one character from a tty device.

First, it does a wait() on the input semaphore so that it will block if there are no characters in the input queue (that semaphore is initialized to 0, and signal is called once for every character that is received).

Once the call to wait() returns, we know there is a character in the queue, and ttygetc() simply takes it out, and then adjusts the tail pointer for the queue advancing it by one. Since this is a circular buffer, it may have to reset the tail pointer back to the beginning of the buffer if it went beyond the end.

ttyread()

Ttyread() works in the same way as ttygetc() except that it reads a sequence of characters - not just one. There is an argument that indicates the number of characters desired. If this argument is zero, ttyread() reads all that are available.

First, ttyread() determines the number of characters that are currently available for reading. If there are enough to immediately satisfy the request, that number of characters are extracted from the input buffer and deposited into the buffer supplied by the calling process. This copy is done by a routine called readcopy. Readcopy copies the stated number of characters from the circular input buffer into the supplied buffer, and then updates the value of the input semaphore to reflect the number of removed characters.

If there are not currently enough characters to satisfy the request, readcopy() is used to copy those that are there, and then a loop is entered that calls ttygetc() to get the remaining characters one at a time.

ttyputc()

This routine writes a single character to the TTY.

First, ttyputc() checks to see if the character being written is a NEWLINE character. If so, it checks a flag in the tty control block to see if it should be sending a RETURN character every time is sees a NEWLINE. If so, a recursive call is made to ttyputc() to send the RETURN character.

Next, ttyputc() makes a call to wait() on the output semaphore for that tty device. This semaphore is initialized to the number of spaces in the output buffer. Thus this call to wait() will cause the process to block only if there is no space left in the output buffer.

Once the call to wait() returns, the character is deposited in the output buffer, and the head pointer is updated.

Finally, ttyputc() sets the bit in the SLU output device that enables it. This will cause it to interrupt as soon as it is idle. The bit may have already been set, but setting it again has no ill effect, so there is no need to test first. Note that this is a bit of a deviation from the rule that says that upper half routines do not interact with the device directly.

ttywrite()

This routine is like ttyputc() except that it copies multiple characters to the TTY rather than only one.

Ttywrite()'s implementation is analogous the ttyread()'s. First, it checks to see if there is already enough free space in the output buffer to satisfy the request. If so, it call writecopy() (which copies the characters into the circular buffer and updates the output semaphore value) to make the transfer. It then sets the enable bit in the SLU output device.

If there was not enough room in the output buffer, writecopy() is invoked to copy whatever there is room for, and then ttyputc() is called in a loop to transfer the remaining as space becomes available.

1