Unit 1 IntroductionToDeviceDrivers
Unit 1 IntroductionToDeviceDrivers
Unit 1 IntroductionToDeviceDrivers
Unit I
Introduction
• A device driver is a software that allows a computer’s operating
system to communicate with a hardware device (such as a printer
and keyboard).
• The device driver helps the operating system to control a hardware
device.
• Device driver is an integration of two pieces of code:
• How driver services are made available to the user space
• The part that actually communicates with the hardware & performs the
required operation.
• Device drivers are hardware dependent and specific to the OS.
• Device drivers communicate with computer hardware through a
computer bus or a communications subsystem that's connected to
the hardware.
• Different hardware devices are built by different manufacturers and
might work in different ways. Device drivers help to ensure that the
hardware device works smoothly with the specific operating system.
• Sometimes, multiple hardware devices need to work together. Device
drivers coordinate this interaction, and ensure that everything
functions harmoniously.
• Device drivers take on a special role in the Linux kernel. They are
distinct “black boxes” that make a particular piece of hardware
respond to a well-defined internal programming interface.
• Kernel device drivers are the mechanism through which the
underlying hardware is exposed to the rest of the system.
• The device drivers hide completely the details of how the device
works.
• User activities are performed by means of a set of standardized calls
that are independent of the specific driver; mapping those calls to
device-specific operations that act on real hardware is then the role
of the device driver.
• This programming interface is such that drivers can be built
separately from the rest of the kernel and “plugged in” at runtime
when needed.
• This modularity makes Linux drivers easy to write.
• As a developer of embedded systems, you need to know how device
drivers fit into the overall architecture and how to access them from
user space programs.
• Your system will probably have some novel pieces of hardware and
you will have to work out a way of accessing them.
• In many cases, you will find that there are device drivers provided for
you and you can achieve everything you want without writing any
kernel code.
For example, you can manipulate GPIO pins and LEDs using files in
sysfs, and there are libraries to access serial buses, including SPI and
I2C.
• There are a number of reasons to be interested in the writing of Linux
device drivers.
• The rate at which new hardware becomes available (and obsolete!) alone
guarantees that driver writers will be busy for the foreseeable future.
• Individuals may need to know about drivers in order to gain access to a
particular device that is of interest to them.
• Hardware vendors, by making a Linux driver available for their products, can
add the large and growing Linux user base to their potential markets.
• And the open source nature of the Linux system means that if the driver
writer wishes, the source to a driver can be quickly disseminated to millions
of users.
Role of the Device Driver
• A driver should be flexible ie the role of a device driver is providing
mechanism, and not policy.
• The distinction between mechanism and policy is one of the best
ideas behind the Unix design.
• Most programming problems can indeed be split into two parts:
“what capabilities are to be provided” (the mechanism) and “how
those capabilities can be used” (the policy).
• If the two issues are addressed by different parts of the program, or
even by different programs altogether, the software package is much
easier to develop and to adapt to particular needs.
• Where drivers are concerned, the same separation of mechanism and
policy applies.
• Since different environments usually need to use hardware in
different ways, it’s important to be as policy free as possible.
• When writing drivers, a programmer should pay particular attention
to this fundamental concept: write kernel code to access the
hardware, but don’t force particular policies on the user, since
different users have different needs.
• The driver should deal with making the hardware available, leaving all
the issues about how to use the hardware to the applications. A
driver, then, is flexible if it offers access to the hardware capabilities
without adding constraints.
• Sometimes, however, some policy decisions must be made. For
example, a digital I/O driver may only offer byte-wide access to the
hardware in order to avoid the extra code needed to handle
individual bits.
• You can also look at your driver from a different perspective: it is a
software layer that lies between the applications and the actual
device.
• This privileged role of the driver allows the driver programmer to
choose exactly how the device should appear: different drivers can
offer different capabilities, even for the same device.
• The actual driver design should be a balance between many different
considerations.
• For instance, a single device may be used concurrently by different
programs, and the driver programmer has complete freedom to
determine how to handle concurrency.
• One major consideration is the trade-off between the desire to
present the user with as many options as possible and the time you
have to write the driver, as well as the need to keep things simple so
that errors don’t creep in.
• Policy-free drivers have a number of typical characteristics. These
include
• support for both synchronous and asynchronous operation,
• the ability to be opened multiple times,
• the ability to exploit the full capabilities of the hardware,
• and the lack of software layers to “simplify things” or provide policy-related
operations.
• Drivers of this sort not only work better for their end users, but also
turn out to be easier to write and maintain as well.
• Being policy-free is actually a common target for software designers.
• Many device drivers, indeed, are released together with user
programs to help with configuration and access to the target device.
• Those programs can range from simple utilities to complete graphical
applications.
• Examples include the tunelp program, which adjusts how the parallel
port printer driver operates, and the graphical cardctl utility that is
part of the PCMCIA driver package.
• Often a client library is provided as well, which provides capabilities
that do not need to be implemented as part of the driver itself.
Splitting the Kernel
• In a Unix/Linux system, several concurrent processes attend to
different tasks.
• Each process asks for system resources, be it computing power,
memory, network connectivity, or some other resource.
• The kernel is the big chunk of executable code in charge of handling
all such requests.
• Although the distinction between the different kernel tasks isn’t
always clearly marked, the kernel’s role can be split into the following
parts:
A split view of the Kernel
Process management
• The kernel is in charge of creating and destroying processes and
handling their connection to the outside world (input and output).
• Communication among different processes (through signals, pipes, or
interprocess communication primitives)is basic to the overall system
functionality and is also handled by the kernel.
• In addition, the scheduler, which controls how processes share the
CPU, is part of process management.
• More generally, the kernel’s process management activity
implements the abstraction of several processes on top of a single
CPU or a few of them.
Memory management
• The computer’s memory is a major resource, and the policy used to
deal with it is a critical one for system performance.
• The kernel builds up a virtual addressing space for any and all
processes on top of the limited available resources.
• The different parts of the kernel interact with the
memory-management subsystem through a set of function calls.
File systems
• Unix is heavily based on the file system concept.
• Almost everything in Unix can be treated as a file.
• The kernel builds a structured file system on top of unstructured
hardware, and the resulting file abstraction is heavily used
throughout the whole system.
• In addition, Linux supports multiple file system types, that is, different
ways of organizing data on the physical medium. For example, disks
may be formatted with the Linux-standard ext3 file system, the
commonly used FAT file system or several others.
Device control
• Almost every system operation eventually maps to a physical device.
• With the exception of the processor, memory, and a very few other
entities, any and all device control operations are performed by code
that is specific to the device being addressed. That code is called a
device driver.
• The kernel must have embedded in it a device driver for every
peripheral present on a system, from the hard drive to the keyboard
and the tape drive.
Networking
• Networking must be managed by the operating system, because most
network operations are not specific to a process: incoming packets
are asynchronous events.
• The packets must be collected, identified, and dispatched before a
process takes care of them.
• The system is in charge of delivering data packets across program and
network interfaces, and it must control the execution of programs
according to their network activity.
• Additionally, all the routing and address resolution issues are
implemented within the kernel.
Loadable Modules
• One of the good features of Linux is the ability to extend at runtime
the set of features offered by the kernel.
• This means that you can add functionality to the kernel (and remove
functionality as well) while the system is up and running.
• Each piece of code that can be added to the kernel at runtime is
called a module.
• The Linux kernel offers support for quite a few different types (or
classes) of modules, including, but not limited to, device drivers.
• Each module is made up of object code (not linked into a complete
executable) that can be dynamically linked to the running kernel by
the insmod program and can be unlinked by the rmmod program.
Classes of Devices and Modules
• The Linux way of looking at devices distinguishes between three
fundamental device types.
• Each module usually implements one of these types, and thus is
classifiable as a char module, a block module, or a network module.
• This division of modules into different types, or classes, is not a rigid
one; the programmer can choose to build huge modules
implementing different drivers in a single chunk of code.
• Good programmers, nonetheless, usually create a different module
for each new functionality they implement, because decomposition is
a key element of scalability and extendibility.
Character devices
• A character (char) device is one that can be accessed as a stream of
bytes (like a file). A char driver is in charge of implementing this
behavior.
• Such a driver usually implements at least the open, close, read, and
write system calls. The text console (/dev/console) and the serial
ports (/dev/ttyS0 and friends) are examples of char devices, as they
are well represented by the stream abstraction.
• Char devices are accessed by means of filesystem nodes, such as
/dev/tty1 and /dev/lp0.
• The only relevant difference between a char device and a regular file
is that you can always move back and forth in the regular file,
whereas most char devices are just data channels, which you can only
access sequentially.
Block devices
• Like char devices, block devices are accessed by filesystem nodes in the /dev
directory.
• A block device is a device (e.g., a disk) that can host a filesystem.
• In most Unix systems, a block device can only handle I/O operations that
transfer one or more whole blocks, which are usually 512 bytes (or a larger
power of two) bytes in length.
• Linux, instead, allows the application to read and write a block device like a
char device—it permits the transfer of any number of bytes at a time.
• As a result, block and char devices differ only in the way data is managed
internally by the kernel, and thus in the kernel/driver software interface.
• Like a char device, each block device is accessed through a filesystem node,
and the difference between them is transparent to the user.
• Block drivers have a completely different interface to the kernel than char
drivers.
Network interfaces
• Any network transaction is made through an interface, that is, a device that is able
to exchange data with other hosts.
• Usually, an interface is a hardware device, but it might also be a pure software
device, like the loopback interface.
• A network interface is in charge of sending and receiving data packets, driven by
the network subsystem of the kernel, without knowing how individual transactions
map to the actual packets being transmitted.
• Many network connections (especially those using TCP) are stream-oriented, but
network devices are, usually, designed around the transmission and receipt of
packets.
• A network driver knows nothing about individual connections; it only handles
packets.
• Not being a stream-oriented device, a network interface isn’t easily mapped to a
node in the filesystem, as /dev/tty1 is.
• Communication between the kernel and a network device driver is completely
different from that used with char and block drivers.
• Instead of read and write, the kernel calls functions related to packet transmission.
• There are other ways of classifying driver modules that are
orthogonal to the above device types. In general, some types of
drivers work with additional layers of kernel support functions for a
given type of device.
• Other classes of device drivers have been added to the kernel in
recent times, including FireWire drivers and I2O drivers.
• In the same way that they handled USB and SCSI drivers, kernel
developers collected class-wide features and exported them to driver
implementers to avoid duplicating work and bugs, thus simplifying
and strengthening the process of writing such drivers.