The ‘ioctl’ driver-function‘struct file_operations’Driver servicesThe ‘file’ paradigmAn imperfect paradigmThe serial UARTOur ‘baudrate.c’ moduleSlide 8UART’s baudrate-controlAlgorithm to ‘get’ baudrateSlide 11Demo-program: ‘setbaud.cpp’In-class exerciseThe ‘ioctl’ driver-functionOn implementing a way to query and modify our UART’s baudrate via the ‘device-file’ abstraction‘struct file_operations’•For a Linux device-driver’s ‘module_init()’ function, there are two main actions:–Initializing the driver’s global data-structures (this includes verifying the device’s presence)–Registering the driver’s service-functions with the kernel (i.e., the ‘file_operations’ structure)•The driver’s ‘module_exit()’ function then has the duty to ‘unregister’ those servicesDriver services•For character-mode device-drivers (like ‘dram.c’, ‘cmos.c’ and ‘vram.c’), we have implemented some (or all) of the following service-functions (i.e., driver ‘methods’):– read()– llseek()– write()– mmap()The ‘file’ paradigm•The UNIX approach to device-control is to create objects that represent i/o-devices, but which behave like ‘files’ do, insofar as the application programmer is concerned•So ‘read()’, ‘lseek()’, ‘write()’ and ‘mmap() use the same function-call syntax – and in most respects the same semantics – for both ordinary ‘files’ and ‘device-files’An imperfect paradigm•But often there are a few ways in which the file-object paradigm doesn’t quite fit with important features of an i/o device•In these cases, device-drivers can provide a ‘workaround’ that allows applications to perform device-actions that deviate from customary ‘read/write/seek’ file-like actions•This ‘workaround’ mechanism is ‘ioctl()’The serial UART •Our PC’s serial UART device offers us an easy example of some desirable behavior that’s outside the traditional ‘file’ paradigm •In order to use our ‘dev/vram’ device-file for communications with computers that we can’t control, we may need to adjust our UART’s communication parameters•How can a program change ‘baudrate’?Our ‘baudrate.c’ module•These techniques are demonstrated in this device-driver module’s ‘ioctl()’ function•Two IOCTL services are implemented:#define GET_BAUDRATE 0#define SET_BAUDRATE 1•Applications can open the device-file and invoke an ‘ioctl’ system-call; for example:int fd = open( “/dev/uart”, O_RDWR );ioctl( fd, GET_BAUDRATE, &baudrate );Recall role of a device-driver userapplicationstandard“runtime”librariescallretuser space kernel spaceOperating Systemkernelsyscallsysretdevice-drivermodulecallrethardware deviceoutin operating parametersRAM A device-driver is a software module that controls a hardware device in response to OS kernel requests relayed, often, from an applicationUART’s baudrate-controlMSBLSBi/o port 0x03F8i/o port 0x03F9i/o port 0x03FBDLABLINE CONTROL REGISTERDIVISOR LATCH (bits 7..0)DIVISOR LATCH (bits 15..8)BREAKdata bitsstopbitsparitycontrols 7 6 5 4 3 2 1 0Algorithm to ‘get’ baudrate•Input (and save) the LINE_CONTROL•Set DLAB-bit in LINE_CONTROL to 1•Input (and save) the DIVISOR_LATCH •Restore LINE_CONTROL to former value•Compute ‘baudrate’ from divisor_latch:baudrate 115200 / divisor_latch•Return this current ‘baudrate’ valueAlgorithm to ‘set’ baudrate•Receive ‘baudrate’ as function-argument•Verify that argument is within valid range •Compute ‘divisor_latch’ from ‘baudrate’:divisor_latch 115200 / baudrate•Input (and save) the LINE_CONTROL•Set DLAB-bit in LINE_CONTROL to 1•Output ‘divisor_latch’ to UART register •Restore LINE_CONTROL to former valueDemo-program: ‘setbaud.cpp’•This application-program lets a user query or modify the UART’s current baudrate in a convenient manner – without requiring any ‘special’ privileges (don’t need ‘iopl3’)•To see the current baudrate:$ ./setbaud•To change the current baudrate:$ ./setbaud 2400In-class exercise•Can you modify our ‘baudrate.c’ driver so it implements an additional ‘ioctl’ service:# define GET_LINECTRL 2•Then add an extra ‘ioctl’ system-call in our ‘setbaud.cpp’ application so that it displays the UART’s current data-format (as well as baudrate) using format similar to 8-N-1•HINT: look at driver’s ‘get_info()’
View Full Document