An introduction to block device drivers
We have already seen several macros which are very helpful in writing block device drivers. Many of these are defined in drivers/block/blk.h, and have to be specially set up.
At the top of the device driver, after including the standard include files your driver needs (which must include linux/major.h and linux/blkdrv.h), you should write the following lines:
#define MAJOR_NR FOO_MAJOR #include "blk.h"
This, in turn, requires that you define FOO_MAJOR to be the major number of the device you are writing in linux/major.h.
Now you need to edit blk.h. One section of blk.h, right near the top, includes definitions of macros that depend on the definition of MAJOR_NR. Add an entry to the end which looks like this:
#elif (MAJOR_NR == FOO_MAJOR) #define DEVICE_NAME "foobar" #define DEVICE_REQUEST do_foo_request #define DEVICE_NR(device) (MINOR(device) >> 6) #define DEVICE_ON(device) #define DEVICE_OFF(device) #endif
These are the required macros for each block device driver. There are more macros that can be defined; they are explained in the KHG.
DEVICE_NAME is the name of the driver. The AT hard drive driver uses the abbreviation “hd” in most places; for example, the request() procedure is called do_hd_request(). However, its DEVICE_NAME is “harddisk”. Similarly, the floppy driver, “fd”, has a DEVICE_NAME of “floppy”. Other drivers are even more descriptive; read blk.h and follow suit.
DEVICE_REQUEST is the request() procedure for the driver.
DEVICE_NR is used to determine the actual physical device. For example, the standard AT hard disk driver uses 64 minor devices for each physical device, so DEVICE_NR is defined as (MINOR(device)>6). The SCSI disk driver uses 16 minor device numbers per physical device, so for it, DEVICE_NR is defined as (MINOR(device)>4). If you have only one minor device number per physical device, define DEVICE_NR as (MINOR(device)).
DEVICE_ON and DEVICE_OFF are only used for devices that have to be turned on and off. The floppy driver is the only driver that uses this capability. You will most likely want to define these to be nothing at all.
All these macros, as well as many others, can be used in your driver where appropriate. blk.h includes a lot of macros, and studying how they are used in other drivers will help you use them in your own driver. I won't document them fully here, but I will briefly mention some of them to make your life easier.
DEVICE_INTR, SET_INTR, and CLEAR_INTR make support for interrupt-driven devices much easier. DEVICE_ TIMEOUT, SET_TIMER, and CLEAR_TIMER help you set limits on how long may be taken to satisfy a request.
I've saved the first, and perhaps most important, thing for last. Before you can read or write a single block, the kernel has to be notified that the device exists. All device drivers are required to implement an initialization function, and there are some special requirements for block device drivers. Here is a sample idealized initialization function:
long foo_init(long mem_start, int length)
{
if (register_blkdev(FOO_MAJOR,"foo", & foo_fops)) {
printk("FOOBAR: Unable to get major %d.\n",
FOO_MAJOR);
return 0;
}
if (!foo_exists()) {
/* the foobar device doesn't exist */
return 0;
}
/* initialize hardware if necessary */
/* notify user device found */
printk("FOOBAR: Found at address %d.\n",
foo_addr());
/* tell buffer cache how to process requests */
blk_dev[FOO_MAJOR].request_fn = DEVICE_REQUEST;
/* specify the blocksize */
blksize_size[MAJOR_NR] = 1024;
return(size_of_memory_reserved);
}
The three things here that are specific to block device drivers are:
register_blkdev() registers the file operations structure with the Virtual Filesystem Switch (VFS), which is the system that manages access to files.
blk_dev tells the buffer cache where the request procedure is.
blksize_size tells the buffer cache what size blocks to request.
It is worth noting that the hardware device detection and initialization, which I have denoted as foo_exists() here, is very delicate code. If you can rely on a string somewhere in the BIOS of the computer to determine whether the device exists and where it is, it's relatively easy. However, if you have to check various I/O ports, you can hang the computer by writing the wrong value to the wrong port, or even reading the wrong port. Check only well-known ports if you must check ports, and provide kernel command-line arguments for other ports. To do this, read init/main.c and add a section of your own. If you can't figure out how to do it, an explanation is forthcoming in the next version of the KHG.
Of course, none of this initialization will happen if foo_init() is never called. Add a prototype to the top of blk.h with the other prototypes, and add a call to foo_init() in ll_rw_blk.c in the blk_dev_init() function. That call should be protected by #ifdef CONFIG_FOO like the rest of the *_init() functions there, and a corresponding line should be added to the config.in file:
bool `Foobar disk support' CONFIG_FOO y
drivers/block/Makefile should have a section added that looks like this:
ifdef CONFIG_FOO OBJS := $(OBJS) foo.o SRCS := $(SRCS) foo.c endif
This done, configuration should work correctly. Your device driver file does not need to have any references to CONFIG_FOO; the only specific reference to it is commented out in ll_rw_blk.c, and the makefile only builds it if it has been configured in.
Now all you have to do is write and debug your own new block device driver. I wish you the best of luck, and I hope that this whirlwind tour has given you a head start.
Michael K. Johnson is the editor of Linux Journal, and is also the author of the Linux Kernel Hackers' Guide (the KHG). He is using this column to develop and expand on the KHG.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- RSS Feeds
- What's the tweeting protocol?
- Trying to Tame the Tablet
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal is an Awesome CMS and a Crappy development framework
1 hour 7 min ago - IT industry leaders
3 hours 29 min ago - Reply to comment | Linux Journal
20 hours 17 min ago - Reply to comment | Linux Journal
22 hours 50 min ago - Reply to comment | Linux Journal
1 day 7 min ago - great post
1 day 42 min ago - Google Docs
1 day 1 hour ago - Reply to comment | Linux Journal
1 day 5 hours ago - Reply to comment | Linux Journal
1 day 6 hours ago - Web Hosting IQ
1 day 8 hours ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




Comments
page 3?
This article has 3 pages, but it seems to end on page 2, because page 3 is empty.
Useful for a newbie
hi...
its really useful for a newbie entering into a block device driver, I am a just a beginner of it.. looking some more information regarding block driver in this forum.. thanks for the article..