All block drivers should include the header file
<linux/blk.h>
. This file defines much of the
common code that is used in block drivers, and it provides functions
for dealing with the I/O request queue.
Actually, the blk.h
header is quite unusual,
because it defines several symbols based on the symbol
MAJOR_NR
, which must be declared by the driver
before it includes the header. This convention
was developed in the early days of Linux, when all block devices had
preassigned major numbers and modular block drivers were not
supported.
If you look at blk.h
, you’ll see that several
device-dependent symbols are declared according to the value of
MAJOR_NR
, which is expected to be known in advance.
However, if the major number is dynamically assigned, the driver has
no way to know its assigned number at compile time and cannot
correctly define MAJOR_NR
. If
MAJOR_NR
is undefined, blk.h
can’t set up some of the macros used with the request queue.
Fortunately, MAJOR_NR
can be defined as an integer
variable and all will work fine for add-on block drivers.
blk.h
makes use of some other predefined,
driver-specific symbols as well. The following list describes the
symbols in <linux/blk.h>
that must be defined
in advance; at the end of the list, the code used in
sbull is shown.
-
MAJOR_NR
This symbol is used to access a few arrays, in particular
blk_dev
andblksize_size
. A custom driver like sbull, which is unable to assign a constant value to the symbol, should#define
it to the variable holding the major number. For sbull, this issbull_major
.-
DEVICE_NAME
The name of the device being created. This string is used in printing error messages.
-
DEVICE_NR(kdev_t device)
This symbol is used to extract the ordinal number of the physical device from the
kdev_t
device number. This symbol is used in turn to declareCURRENT_DEV
, which can be used within the request function to determine which hardware device owns the minor number involved in a transfer request.The value of this macro can be
MINOR(device)
or another expression, according to the convention used to assign minor numbers to devices and partitions. The macro should return the same device number for all partitions on the same physical device—that is,DEVICE_NR
represents the disk number, not the partition number. Partitionable devices are introduced later in this chapter.-
DEVICE_INTR
This symbol is used to declare a pointer variable that refers to the current bottom-half handler. The macros
SET_INTR(intr)
andCLEAR_INTR
are used to assign the variable. Using multiple handlers is convenient when the device can issue interrupts with different meanings.-
DEVICE_ON(kdev_t device)
,DEVICE_OFF(kdev_t device)
These macros are intended to help devices that need to perform processing before or after a set of transfers is performed; for example, they could be used by a floppy driver to start the drive motor before I/O and to stop it afterward. Modern drivers no longer use these macros, and
DEVICE_ON
does not even get called anymore. Portable drivers, though, should define them (as empty symbols), or compilation errors will result on 2.0 and 2.2 kernels.-
DEVICE_NO_RANDOM
By default, the function end_request contributes to system entropy (the amount of collected “randomness”), which is used by
/dev/random
. If the device isn’t able to contribute significant entropy to the random device,DEVICE_NO_RANDOM
should be defined./dev/random
was introduced in Section 9.3 in Chapter 9, whereSA_SAMPLE_RANDOM
was explained.-
DEVICE_REQUEST
Used to specify the name of the request function used by the driver. The only effect of defining
DEVICE_REQUEST
is to cause a forward declaration of the request function to be done; it is a holdover from older times, and most (or all) drivers can leave it out.
The sbull driver declares the symbols in the following way:
#define MAJOR_NR sbull_major /* force definitions on in blk.h */ static int sbull_major; /* must be declared before including blk.h */ #define DEVICE_NR(device) MINOR(device) /* has no partition bits */ #define DEVICE_NAME "sbull" /* name for messaging */ #define DEVICE_INTR sbull_intrptr /* pointer to bottom half */ #define DEVICE_NO_RANDOM /* no entropy to contribute */ #define DEVICE_REQUEST sbull_request #define DEVICE_OFF(d) /* do-nothing */ #include <linux/blk.h> #include "sbull.h" /* local definitions */
The blk.h
header uses the macros just listed to
define some additional macros usable by the driver. We’ll describe
those macros in the following sections.
Get Linux Device Drivers, Second Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.