The ioctl driverfunction On implementing a way to

  • Slides: 13
Download presentation
The ‘ioctl’ driver-function On implementing a way to query and modify our UART’s baudrate

The ‘ioctl’ driver-function On 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:

‘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 services

Driver services • For character-mode device-drivers (like ‘dram. c’, ‘cmos. c’ and ‘vram. c’),

Driver 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

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 a few ways in which the file-object

An imperfect paradigm • But often there 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

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()’

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 A device-driver is a software module that controls a

Recall role of a device-driver A device-driver is a software module that controls a hardware device in response to OS kernel requests relayed, often, from an application operating parameters RAM device-driver module user application call ret standard “runtime” libraries user space hardware device in out call ret syscall Operating System kernel sysret kernel space

UART’s baudrate-control i/o port 0 x 03 F 8 LSB DIVISOR LATCH (bits 7.

UART’s baudrate-control i/o port 0 x 03 F 8 LSB DIVISOR LATCH (bits 7. . 0) i/o port 0 x 03 F 9 MSB DIVISOR LATCH (bits 15. . 8) i/o port 0 x 03 FB 7 6 5 4 3 2 D L A B B R E A K parity controls stop bits 1 0 data bits LINE CONTROL REGISTER

Algorithm to ‘get’ baudrate • • • Input (and save) the LINE_CONTROL Set DLAB-bit

Algorithm 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’ value

Algorithm to ‘set’ baudrate • Receive ‘baudrate’ as function-argument • Verify that argument is

Algorithm 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 value

Demo-program: ‘setbaud. cpp’ • This application-program lets a user query or modify the UART’s

Demo-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 ‘iopl 3’) • To see the current baudrate: $. /setbaud • To change the current baudrate: $. /setbaud 2400

In-class exercise • Can you modify our ‘baudrate. c’ driver so it implements an

In-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()’ function