CMSC 421 Operating Systems Lecture Notes (c) 1993 Howard E. Motteler I/O (Chapter 5) ================= Organization of I/O Software (5.2) =================================== We can organize i/o software as a set of _layers_: | User Processes A V | Device-Independent i/o | Software A i/o requests V | reply Device Drivers | A V Interrupt Handlers | | Device Controllers A V | Hardware These layers are not always distinct in practice! Hardware (5.1) =============== Classification of hardware devices ----------------------------------- Block Devices - reads and writes data in fixed sized, addressable blocks - may be random access - examples: - disks (usually random access/block addressable) - mag-tape (may be block addressable, normally read and written sequentially Character Devices - read and writes a stream of characters - not block addressable - example: a terminal keyboard Other Devices - clocks (readable as a single word or set of words, or may be used to generate interrupts) - bit-mapped screens (special hardware interprets values in memory as pixels) Hardware & Device controllers ------------------------------ The device controller (not device driver) interacts with the hardware at a very low level Examples: --------- (1) Disk controllers -------------------- - (already discussed low-level disk control) - translate block address to cylinder, surface, and sector - motor control and analog circuitry - error correction, bad block mapping (in newer drives) (2) Terminals -------------- There are three types of terminals - memory mapped - RS 232 (serial interface) - virtual (e.g, Xterms) Video Display (CRT); -------------------- Characters and bitmap graphics must be translated into fairly complex CRT commands. The CRT controller must: - draw lines on screen (3 beams, for color) - do horizontal retrace - do vertical retrace Bit-mapped Displays ------------------- For bit-mapped displays, special `dual ported' memory is used that can be both - written or read as regular memory - read by the display as pixels, with one or more bits/pixel To modify the screen one simply writes to the video ram Fonts and graphics are all done in software Character Oriented Displays ---------------------------- Older character-based CRTs (VT100's, adm3a's, etc.) divided the screen into (say) 24 x 80 character positions, and stored the state of the screen as a 24 x 80 array of bytes A fast ROM was then used to generate the bit patterns for each character, and these bit patterns were concatenated in hardware char mem --> char rom --> pixel row --> shift reg --> pixels RS232 Terminals ---------------- The RS232 Terminal was typically a keyboard and character oriented display, communicating over a _serial line_ RS232 is a protocol used between many sorts of devices (e.g., 2 computers, computer & terminal, terminal & modem) (Though there are 25 pins in an RS232 connector, often just a pair of wires + ground are used) The UART takes bytes and translates them into bit streams ------| bit stream |----- UART | ------------>> | UART | <<------------ | ------| bit stream |----- terminal computer In the simplest case (no extra buffering) - 1 interrupt at each received char - 1 interrupt after each successful transmission RS232 terminals usually use a char oriented display: - smallest accessible unit is a character - may have special `graphics character sets' - may have `escape sequences' to move cursor, scroll, clear line, clear screen, etc. An "Xterm" is a virtual RS232 terminal Device interaction with higher layers -------------------------------------- In general, device controllers communicate via - interrupts and interrupt vectors and either - memory addresses (for `memory mapped' i/o) or - through an `i/o bus' (like in the IBM PC) Commands, status, etc., are read through these special addresses or _device registers_ (or _port addresses_ if the system has a separate i/o bus) A tty for a simple system like CP/M might appear as 4 consecutive bytes in memory xx0: flag that screen is ready for more data xx1: data byte to screen xx2: flag that new keyboard data is ready xx3: data byte from keyboard In CP/M, a simple "polling loop" would repeatedly test xx0 and xx2, and - send next byte to screen, if screen is ready - get next byte from keyboard, if keyboard is ready In DOS (and later versions of CP/M) both screen and keyboard ready would be signaled by interrupts (Typically, the cpu will give a command, and then do something else until a device generates an interrupt) Direct Memory Access (DMA) -------------------------- Basic idea: let a device "talk" directly to main memory, bypassing the CPU Most devices have buffers separate from main memory When the device is ready to send or receive data, without DMA it would have to be transfered a byte at a time, through i/o registers to the desired buffer address With DMA, this transfer is done without going thru the CPU, and so is very fast The device doing the transfer has exclusive access to the memory bus, during the transfer Some means of resolving contention for DMA by various devices may be needed (devices may have priorities) A typical device controller might take commands of the form - a command - a buffer address - the number N of bytes to transfer (for a hard disk, the command would be to read or write a particular sector, or contiguous group of sectors) When the data is ready, an interrupt occurs and the controller will grab the bus and copy the data directly into memory Interrupts ----------- Typical sequence of low level-events: - i/o request to device (e.g., get disk block K) - interrupt from device when request is performed (block K has been copied to buffer) It can simplify systems design to treat interrupts in the context of some existing inter-process communication model For example, the device driver might simply wait (block) for the interrupt (the i/o completion) The interrupt handler could then be a very short piece of code that simply signals the appropriate device driver, or simply moves it to the ready queue Device Drivers --------------- Device drivers translate abstract, _device-independent requests_ into _device dependent operations_ For example, the disk driver might take (relatively abstract) requests to read or write block N, and translate this to commands for a specific type of disk drive For each actual device a disk device driver knows about the that device controller's - device registers - tracks, sectors, cylinders, head motion, etc. (at least before ide and scsi drives!) In general, the disk driver waits on either - requests (from a higher level) - an interrupt or message (from below) (The disk device driver might issue a request and then wait on an interrupt from the controller) Example: TTY drivers -------------------- Keyboard Driver ---------------- Keyboard driver can either - pass characters on unmodified (raw) - do some local editing (cooked) The `local editing' can get rather complex - backspacing, deleting words and lines - expanding tabs - wrapping lines With local editing, the system may be interrupted only once for each line Passing characters on unmodified requires one interrupt per character The trend is to implement fancier line editing at a higher level (tcsh vs. csh, emacs vs. teco) Both raw and cooked tty input normally requires some _buffering_ This can be done either in hardware or software Could have one or more of: - a buffer in hardware associated with the terminal - central buffer pool, shared by all tty's (in kernel space) - a buffer in the terminal driver's data structures (in user space) Screen Driver -------------- The screen driver by itself is relatively simple, but the interaction between screen and keyboard is more complicated Typed input must be echoed With various line-editing commands what gets echoed is not simply either what is typed or what is saved, e.g., for - delete line & delete word - ^S/^Q - scrolling - ^C, ^D (interrupts, EOF) (In Unix, the `ioctl' call sets tty driver parameters; stty is allows some manipulation of this) Device-Independent Software ---------------------------- (The boundaries can get vague, here and several layers may be combined, in practice) The device-independent layer - performs functions common to all devices and - provide a uniform interface to the user layer Examples of device independent functions: - mapping symbolic names (e.g, /dev/rfp021) to the right driver - Providing protection (in Unix, file protection bits are used for all devices) - Provide buffering (e.g., between char at time user requests and block at a time devices) This layer is still typically implemented inside the kernel Unix sys calls (man 2) are in this layer User Layer ---------- Functions in this layer are implemented in user rather than kernel space Unix library routines (man (3)) are in this layer (e.g., printf, putchar, etc.) Other services implemented in the user layer: - spoolers (e.g., printer & batch spoolers) - mail and Usenet Disks (5.3) ============ ( covered earlier ) Clocks (5.4) ============= Hardware --------- Typically, system clock is counted down to some "tic" value, used for - time slice interrupts - tick counter available as a device register Most systems also have a battery-powered clock chip, similar to what's in a watch, that can supply date and time in a set of registers Software --------- Date, time, timing utilities (Unix keeps it's own time as seconds since Jan 1, 1970) Accounting (e.g., total cpu time) Run-time profiling of code (may need to keep track of how much of each run burst is actually used) Scheduling programs to run at specific times (e.g., unix chron and `at')