CS 105 Tour of the Black Holes of
CS 105 “Tour of the Black Holes of Computing” I/O Subsystem Overview of I/O Hardware Access Device Independent Routines Device Dependent Routines Device io. ppt
I/O: A Typical Hardware System CPU chip register file ALU system bus memory bus main memory I/O bridge bus interface I/O bus USB controller mouse keyboard – I/O – graphics adapter disk controller Expansion slots for other devices such as network adapters. monitor disk CS 105
Reading a Disk Sector: Step 1 CPU chip register file ALU CPU initiates a disk read by writing a command, logical block number, and destination memory address to a port (address) associated with disk controller. main memory bus interface I/O bus USB controller mouse keyboard graphics adapter disk controller monitor disk – I/O – CS 105
Reading a Disk Sector: Step 2 CPU chip register file ALU Disk controller reads the sector and performs a direct memory access (DMA) transfer into main memory bus interface I/O bus USB controller mouse keyboard graphics adapter disk controller monitor disk – I/O – CS 105
Reading a Disk Sector: Step 3 CPU chip register file ALU When the DMA transfer completes, the disk controller notifies the CPU with an interrupt (i. e. , asserts a special “interrupt” pin on the CPU) main memory bus interface I/O bus USB controller mouse keyboard graphics adapter disk controller monitor disk – I/O – CS 105
Abstracting I/O Low level requires complex device commands n Vary from device to device n Device models can be very different l Tape: read or write sequentially, or rewind l Disk: “random” access at block level l Terminal: sequential, no rewind, must echo and allow editing l Video: write-only, with 2 -dimensional structure Operating system should hide these differences n “read” and “write” should work regardless of device l OS builds table of specific driver routines for each device n n – I/O – Sometimes impossible to generalize (e. g. , video) Still need access to full power of hardware CS 105
Layers of I/O System 1. User Level – processes • make I/O call, format I/O, spooling 2. Device-Independent software • naming, protection blocking, buffering, allocation • • perform I/O functions common to all devices provide uniform interface to the user level software buffering, block sizes, etc. e. g. , map symbolic device names onto driver 3. Device-Dependent software • setup device registers, check status • specific code for device operations, i. e. , driver routines for read, write, etc. • accept abstract requests, e. g. , open, and execute 4. Hardware • controller, map I/O ops to device ops, e. g. , print, • Interrupts – I/O – CS 105
UNIX I/O Derived from Multics and earlier systems, the Unix I/O primitives follow a paradigm referred as “open -read-write-close”. Before a user process can perform I/O ops, it calls ‘open’ to specify the file to be used and obtains permission. The call to ‘open’ returns a small integer, ‘file descriptor’ that the process uses when performing I/O ops on the opened file or device. Once an object has been opened, the user process makes one or more ‘read’ or ‘write’ calls to read or write data. Both ‘read’ and ‘write’ take 3 arguments that specify the file descriptor, address of a buffer, and count of bytes to be transferred. After all transfer operations are complete, the user process calls ‘close’ to inform the OS that the process is finished with the object. – I/O – CS 105
Layers of I/O System 1. User Level – processes • make I/O call, format I/O, spooling 2. Device-Independent software • naming, protection blocking, buffering, allocation • perform I/O functions common to all devices • provide uniform interface to the user level software • buffering, block sizes, etc. • e. g. , map symbolic device names onto driver 3. Device-Dependent software • setup device registers, check status • specific code for device operations, i. e. , driver • accept abstract requests, e. g. , open, and execute 4. Hardware • controller, map I/O ops to device ops, e. g. , print, • Interrupts – I/O – CS 105
Device Independent: Dev Table struct dvtype { char *dvname; /* device name */ char *dvtname; /* type name int char */ /* symbol table index of type */ *dvdevice; /* device name */ dvcsr; /* Control Status Register addr */ int dvivec; /* input interrupt vector int dvovec; */ /* input interrupt routine */ char dviint[20]; char dvoint[20]; char dvinit[20]; char dvopen[20]; /* open routine name */ char dvclose[20]; /* close routine name */ char dvread[20]; /* read routine name */ char dvwrite[20]; /* write routine name */ char dvcntl[20]; /* control routine name */ char dvseek[20]; /* seek routine name */ char dvgetc[20]; /* getc routine name */ char dvputc[20]; /* putc routine name */ dvminor; struct dvtype *dvnext; }; – I/O – /* linked list of device types */ dvptr devs = NIL; /* linked list of device decls. */ dvptr currtype = NIL; */ /* Output interrupt vector /* output interrupt routine /* init routine name dvptr ftypes = NIL; dvptr lastdv = NIL; int */ dvtnum; typedef struct dvtype *dvptr; */ */ /* device number 0, 1, . . . • struct dvtype is common to all devices • uses linked list of dytype • allows dynamic creation of new dvtype(device) */ /* next node on the list CS 105
Device Independent: init. c /* init. c - init */ /*include files do not appear in following modules */ #include <conf. h> #include <kernel. h> #include <io. h> /*------------------------------------* init - initialize a device • could be done by the OS, system level setup of the device • done at boot time or when first accessed *------------------------------------*/ init(descrp) int descrp; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; // get pointer to device struct return( (*devptr->dvinit)(devptr) ); // run device’s init routine – }I/O – CS 105
Device Independent: control. c /* control. c - control */ /*------------------------------------* control - control a device (e. g. , set the mode) * OS level operation, *------------------------------------*/ SYSCALL control(descrp, func, addr 2) int descrp, func; char *addr, *addr 2; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; return( passing parms – I/O – } (*devptr->dvcntl)(devptr, func, addr 2) ); //’ run device’s cntl routine CS 105
Device Independent: open. c /* open. c - open */ /*------------------------------------* open - open a connection to a device/file (parms 2 &3 are optional) *------------------------------------*/ SYSCALL open(descrp, nam, mode) int descrp; char *nam; char *mode; { struct devsw *devptr; if ( isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; //get a pointer to the appropriate device structure in device table return( (*devptr->dvopen)(devptr, nam, mode) ); // use device pointer to call device specific open } – I/O – CS 105
Device Independent: getc. c /* getc. c - getc */ /*------------------------------------* getc - get one character from a device *------------------------------------*/ SYSCALL getc(descrp) int descrp; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; // get pointer to device structure return( (*devptr->dvgetc)(devptr) ); // run device’s getc } – I/O – CS 105
Device Independent: putc. c /* putc. c - putc */ /*------------------------------------* putc - write a single character to a device *------------------------------------*/ SYSCALL putc(descrp, ch) int descrp; char ch; { struct devsw *devptr; if (isbaddev (descrp) ) return(SYSERR); devptr = &devtab[descrp]; return( (*devptr->dvputc)(devptr, ch) ); } – I/O – CS 105
Device Independent: seek. c /* seek. c seek */ /* seek -- position a device (very common special case of control) */ SYSCALL seek(descrp, pos) int descrp; long pos; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; // get pointer to devices structure return( (*devptr->dvseek)(devptr, pos) ); // run device’s seek function, which may be a noop } – I/O – CS 105
Device Dependent: ionull. c /* ionull. c - ionull */ /*------------------------------------* ionull - do nothing (used for "don't care" entries in devtab) *------------------------------------*/ ionull() { return(OK); } – I/O – CS 105
Device Independent: read. c /* read. c - read */ /* read - read one or more bytes from a device */ SYSCALL read(descrp, buff, count) int descrp, count; char *buff; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; // get pointer to device’s IO structure return( (*devptr->dvread)(devptr, buff, count) ); // device’s read may be an ‘error’, e. g. , on keyboard } – I/O – CS 105
Device Independent: write. c /* write. c - write */ /*------------------------------------* write - write 1 or more bytes to a device *------------------------------------*/ SYSCALL write(descrp, buff, count) int descrp, count; char *buff; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; return( (*devptr->dvwrite)(devptr, buff, count) ); } – I/O – CS 105
Device Independent: close /* close. c - close */ /*------------------------------------* close - close a device *------------------------------------*/ SYSCALL close(descrp) int descrp; { struct devsw *devptr; if (isbaddev(descrp) ) return(SYSERR); devptr = &devtab[descrp]; return( (*devptr->dvclose)(devptr)); } – I/O – CS 105
Layers of I/O System 1. User Level – processes • make I/O call, format I/O, spooling 2. Device-Independent software • naming, protection blocking, buffering, allocation • perform I/O functions common to all devices • provide uniform interface to the user level software • buffering, block sizes, etc. • e. g. , map symbolic device names onto driver 3. Device-Dependent software • setup device registers, check status • specific code for device operations, i. e. , driver • accept abstract requests, e. g. , open, and execute 4. Hardware • Controller. map I/O ops to device ops, e. g. , print, • Interrupts – I/O – CS 105
Device Dependent: slu. h /* slu. h - standard serial line unit device constants */ #define SLUENABLE 0100 #define SLUREADY 0200 /* device interrupt enable bit */ /* device ready bit */ #define SLUDISABLE 0000 /* device interrupt disable mask*/ #define SLUTBREAK 0001 /* transmitter break-mode bit */ #define SLUERMASK 0170000 #define SLUCHMASK 0377 /* mask for error flags on input*/ /* mask for input character */ /* SLU device register layout and correspondence to vendor's names struct csr */ { int crstat; /* receiver control and status (RCSR) */ int crbuf; /* receiver data buffer int ctstat; /* transmitter control & status (XCSR) */ int ctbuf; /* transmitter data buffer (RBUF) */ (XBUF) */ }; // memory mapped IO // real registers – I/O – CS 105
Layers of I/O System 1. User Level – processes • make I/O call, format I/O, spooling 2. Device-Independent software • naming, protection blocking, buffering, allocation • perform I/O functions common to all devices • provide uniform interface to the user level software • buffering, block sizes, etc. • e. g. , map symbolic device names onto driver 3. Device-Dependent software • setup device registers, check status • specific code for device operations, i. e. , driver • accept abstract requests, e. g. , open, and execute 4. Hardware • controller, map I/O ops to device ops, e. g. , print, • Interrupts – I/O – CS 105
Device Dependent: ttycntl. c ttyiin. c ttyoin. c ttyputc. c ttywrite. c ttygetc. c ttyinit. c ttyopen. c ttyread. c – I/O – CS 105
Device Dependent: tty struct tty { /* tty line control block */ // set up input queue int ihead; int itail; char int /* head of input queue /* tail of input queue ibuff[IBUFLEN]; isem; */ */ /* input buffer for this line */ /* input semaphore */ // set up output queue int ohead; int otail; char /* head of output queue /* tail of output queue obuff[OBUFLEN]; int osem; int odsend; */ */ /* output buffer for this line */ /* output semaphore /* sends delayed for space */ */ …… – I/O – CS 105
Device Dependent: tty struct ……. /// set up echo queue int ehead; int etail; /* head of echo queue /* tail of echo queue */ */ char ebuff[EBUFLEN]; /* echo queue char imode; /* IMRAW, IMCBREAK, IMCOOKED Bool iecho; /* is input echoed? Bool ieback; /* do erasing backspace on echo? */ Bool evis; /* echo control chars as ^X ? */ Bool ecrlf; /* echo CR-LF for newline? Bool icrlf; /* map 'r' to 'n' on input? */ Bool ierase; /* honor erase character? */ */ */ RAW – puts characters into ibuff without processing ignores all user editing CBREAK – honors all control characters except those related to line editing COOKED – character echo, honors suspend or restart gets complete lines */ */ …. – I/O – CS 105
Device Dependent: tty struct cont. /* struct continuid char ierasec; Bool ikill; /* honor line kill character? */ char ikillc; /* line kill character Bool iintr; /* is interrupt char honored? */ char iintrc; /* interrupt character */ iintpid; /* interrupt process id */ int /* erase character (backspace) */ */ Bool ieof; /* honor end-of-file char? char ieofc; /* end-of-file character int icursor; */ */ /* current cursor position */ */ Bool oflow; /* honor ostop/ostart? Bool oheld; /* output currently being held? */ char ostop; /* character that stops output */ char ostart; /* character that starts output */ Bool ocrlf; /* echo CR/LF for LF ? char ifullc; /* char to send when input full */ struct csr *ioaddr; ; */ /* device address of this unit */ }; extern struct tty[]; – I/O – CS 105