Device Drivers
Device Drivers
Device Drivers
Anton Burtsev
April, 2014
Device drivers
● Conceptually
● Implement interface to hardware
● Expose some high-level interface to the kernel or
applications
– What this interface should look like?
● In UNIX everything is a ...
Device drivers
● Conceptually
● Implement interface to hardware
● Expose some high-level interface to the kernel or
applications
– What this interface should look like?
● In UNIX everything is a file
Devices in UNIX
● In Unix devices expose file-like interface
● They are files in the file system
– /dev/sda, /dev/dsp
● Applications can read and write into them
– dd if=/dev/sda of=/my-disk-image bs=1M
– cat thesis.txt > /dev/lp
Classes of devices
● Character
● Accessed as a stream of bytes
– Text console, serial ports
– /dev/console, /dev/tty1
● Block
● I/O performed in units of blocks
– Hard disks, CD drives, USB sticks
– /dev/sda
Classes of devices
● But what about network devices? Graphic
cards?
● No easy file mapping
– Although it doesn't mean you can't come up with one if it
fits your needs
● Device as a file paradigm doesn't work
– Well they expose different interfaces
– Network cards are accessible through sockets
Detour into hardware
Device drivers and hardware
● Device driver doesn't strictly need to talk to
hardware
● /dev/random – stream of random numbers
● /dev/mem – reads physical memory
● /dev/null – input goes nowhere
Bus subsystem
● Buses are the mechanism that enable the flow
of data across CPU, memory, and devices
Buses
● PCI (Peripheral Component Interconnect) –
main system bus on most architectures
● USB (Universal Serial Bus) – external bus,
hotplug capability, devices are connected in a
tree
● SCSI (Small Computer System Interface) –
high-throughput bus used mainly for disks
Interacting with peripherals
● I/O ports
● Device is identified by the port number
● 2^16 ports (64K ports)
● in, out instructions to read and write data from a
port
– Connect straight to a peripheral
Interacting with peripherals
● I/O memory mapping
● Modern CPUs allow mapping port addresses to
memory locations
● Then it's just possible read/write memory
– GPU devices
– System buses like PCI
Interacting with peripherals
● Interrupts
● CPU provides several interrupt lines
● One line can be shared across several devices
● Polling
● Periodic check of the device state for whether more
data is available
Back to the Linux kernel
Linux exports devices as files
● Lets assume you have a modem attached to
the serial port
● echo "ATZ" > /dev/ttyS0
– Sends initialization string to the modem
● To read your hard drive
● cat /dev/sda
Device files (/dev/xyz)
Major and minor numbers
● Each device file has two numbers
● Identify device driver for this device
● Major number: device driver
● Minor number: device number
wolfgang@meitner> ls -l /dev/sd{a,b} /dev/ttyS{0,1}
brw-r----- 1 root disk 8, 0 2008-02-21 21:06 /dev/sda
brw-r----- 1 root disk 8, 16 2008-02-21 21:06 /dev/sdb
crw-rw---- 1 root uucp 4, 64 2007-09-21 21:12 ttyS0
crw-rw---- 1 root uucp 4, 65 2007-09-21 21:12 ttyS1
/dev
● Back in the days /dev/ was static
● Now there are 20K device numbers are allocated
● Most are not used on your system
● Today, /dev/ is a temporary file system
● All device names are generated on the fly
● By udevd daemon
udevd
device_file_major_number = result;
};
Read function
● ssize_t (*read) (struct file *, char *,
size_t, loff_t *);
● First arg – pointer to the file struct
– Private information for us, e.g. state of this file
● Second arg – buffer in user space to read data into
● Third arg – number of bytes to read
● Fourth arg – position in a file from where to read
static const char hw_string[] = "Hello world from kernel mode!\n\0";
static const ssize_t hw_size = sizeof(hw_string);
/* If a user tries to read more than we have, read only as many bytes as we
have */
if( *position + count > hw_size )
count = hw_size - *position;