Linux Device Drivers

Linux Device Drivers

Character drivers
IO & Memory
Linux Kernel
Process Management
Process Address space

Linux Scheduler
Memory Management
System Calls
Kernel Synchronization
Linux Inter Process Communications

Serial Ports
Parallel Ports
Introduction to Hardware
Linux Timers
DMA in Linux
Linux Threads
Linux Thread Synchronization

Linux Multi Threading
Debugging in Linux
GDB GNU Debugger
KDB Kernel Debugger
KGDB Kernel GNU Debugger
Example Ethernet Driver

Device Drivers


Need for Device Driver

For the new hardware device, for which driver is not available, you are required to write device driver. You may like to add additional capability to existing device driver. (Filter Driver)


Device Drivers

They are distinct “black boxes” that make a particular piece of hardware respond to a well-defined internal programming interface; they hide completely the details of how the device works.

Linux kernel's role is split into various tasks. The following slide shows the position of device driver.  For each type of device, the device driver directly interacts with the kernel. A driver usually implements at least the open, close, read and write systems calls.





Classes of DevicesThere are mainly three classes of devices:


ü     Character Devices (Console, serial ports, parallel port etc.)

ü     Block Devices ( HDD, FDD, CD-ROM etc..)

ü     Network Devices ( NIC etc)


The Driver and the filesystem:

From the user's side of view the driver looks like an ordinary file. If you operate on this file via open, close, read or write requests the kernel looks up the appropriate functions in your driver code. All drivers provide a set of routines. Each device has a struct char_fops that holds the pointers to this routine. At init time of the driver this struct is hooked into another table where the kernel can find it. The index that is used to dereference this set of routines is called MAJOR number and is unique so that a definite distinction is possible. The special inode file for the driver gets its MAJOR number at creation time via the mknod command. The driver code gets its MAJOR by the register_chrdev kernel routine.


Driver Processing –Write

The user process calls write(). This invokes the kernel through an INT instruction where the write operation is conveyed as an index into the syscall[] table. The filedes argument contains, among other things, a major device number so that the kernel's write function can access the driver's file_operations structure. The kernel calls the driver's write function, which copies the User Space buffer into Kernel Space.

The general look of a Driver


The structure of a driver is similar for each peripheral device:


ü     You have an init routine that is for initializing your hardware, perhaps setting memory from the kernel and hooking your driver-routines into the kernel.


ü               You have a char_fops struct that is initialized with those routines that you will provide for your device. This struct is the key to the kernel it is "registered" by the register_chrdev routine.


ü     Mostly you have open and release routines that are called whenever you perform a open or close on your special inode.


ü     You can have routines for reading and writing data from or to your driver, a ioctl routine that can perform special commands to your driver like config requests or options.


ü     You have the possibility to readout the kernel environment string to configure your driver via LILO.


ü     An interrupt routine can be registered if your hardware supports this.


Compile your Driver into kernel code


The most drivers in Linux are linked to the kernel at compile time. That means if you want to add a driver you have to put your .c and .h files directly somewhere in the kernel source path and rebuild the kernel.


Dynamically loaded drivers


The kernel module can be loaded into the kernel at runtime. That means loaded and removed at any time after the boot process. The only differences between a loadable Module and a kernel linked driver are a special init() routine that is called when the module is loaded into the kernel and a cleanup routine that is called when the module is removed.