The upper half and lower half share data using a circular queue or buffer. Characters are put in the queue by the upper half for transmission by the lower half. Likewise, received characters are enqueued by the lower half of the driver for consumption by application processes.
The upper and lower halves coordinate their activities as follows:
Both input and output queues are teated as circular queues with pointers to the head and tail. Characters are always put in the queue at the head position, and characters are always taken off at the tail position.
Other coordination is also required. For example, if there is nothing to send, the upper half routines may want to stop the SLU from interrupting whenever it becomes idle. It may also want to start the lower half when it makes a character ready to be sent. Likewise, if there are no characters in the buffer, the upper half routines may want to block a process trying to read a character.