Block Device Drivers: - Naga Manjunath Senior S/W Engg in Bosch
Block Device Drivers: - Naga Manjunath Senior S/W Engg in Bosch
Block Device Drivers: - Naga Manjunath Senior S/W Engg in Bosch
#include <linux/genhd.h>
struct gendisk *alloc_disk(int minors); void add_disk(struct gendisk *gd); void set_capacity(struct gendisk *gd, setor_t sectors);
#include <linux/fs.h>
struct block_device_operations
#include<linuix/genhd.h>
struct gendisk
#include <linux/blkdev.h>
struct request
struct gendisk
struct block_device_operations
Needed files:
sbull.c Makefile
Driver description:
it allocates 10 MB memory space to simulate a ramdisk which is like you insert a disk into the system the ramdisk has only one partition many file operations can be performed on it
mkfs, mount, umount, cp, ls, <
// HARDWARE define (ramdisksize = 20000*512 = 10M bytes) int nsectors = 20000; // number of sectors int hardsector_size = 512; // sector size = 512 bytes int dev_major_nr = 0; // system automatically allocate major number int SBULL_MINORS = 1; // MAX minor number is 1 ,ie.only one partition char dev_name[8] = "sbull"; MODULE_AUTHOR(MANJU"); MODULE_LICENSE("DualBSD/GPL");
static struct sbull_dev *dev = &Device; // function prototype static int sbull_open(struct inode *inode, struct file *filp); static int sbull_release(struct inode *inode, struct file *filp); static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,unsigned long nsect, char *buffer, int write); static void sbull_request(request_queue_t *q);
static int sbull_open(struct inode *inode, struct file *filp) { printk("sbull_open(): do nothing...\n"); return 0; } static int sbull_release(struct inode *inode, struct file *filp) { printk("sbull_release(): do nothing...\n"); return 0; }
sbull_init method
sbull_request method
static void sbull_request(request_queue_t *q) { struct request *req; while((req = elv_next_request(q)) != NULL) { struct sbull_dev *dev = req->rq_disk->private_data; if( !blk_fs_request(req)) { If non-fs request here, end_request(req,0); do nothing } else { next sector to submit no. of sectors to submit sbull_transfer(dev, req->sector, req->current_nr_sectors, req->buffer, rq_data_dir(req)); end_request(req,1); } } decide the transfer dir. }
static void sbull_exit(void) { printk("sbull_exit(): exit sbull...\n"); del_gendisk(dev->gd); put_disk(dev->gd); unregister_blkdev(dev_major_nr, dev_name); vfree(dev->data); } module_init(sbull_init); module_exit(sbull_exit);
LAB 1
Create the simple block device driver and insert into the kernel:
make sudo insmod sbull.ko cat /proc/devices | grep sbull
LAB 1 (cont)
Create the device node and mount it:
sudo mknod /dev/sbulla b XXX 0
replaces XXX to the major number you get above Ubuntu may create the /dev/sbulla for us
LAB 1 (cont)
LAB 1 (cont)
Test the read and write abilities:
cd temp sudo mkdir HANEL cd .. sudo umount temp mkdir temp2 sudo mount /dev/sbulla temp2 ls temp2
LAB 1 (cont)
LAB 1 (cont)
Remove the sbull module from the kernel:
sudo umount temp2 sudo rmmod sbull
Ubuntu will also clear the /dev/sbulla for us
LAB 2
In this exercise, a extended version sbull will be introduced
it allocates 10 MB memory space to simulate a ramdisk which is like you insert a disk into the system the ramdisk has 2 partitions (partitionable) many file operations can be performed on it
mkfs, mount, umount, cp, ls, <
LAB 2 (cont)
In order to let the sbull able to be partitioned, there are something needed be done:
sets SBULL_MINORS to 2 adds new structure member short users in sbull_dev adds one new function in sbull_ops structure alters the sbull_open and sbull_release functions
LAB 2 (cont)
int sbull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { long size; struct hd_geometry geo; struct sbull_dev *dev = filp->private_data; switch(cmd) { case HDIO_GETGEO: size = dev->size; geo.cylinders= (size & ~0x3f) >> 6; geo.heads= 4; geo.sectors= 16; geo.start= 4; if (copy_to_user((void __user *) arg, &geo, sizeof(geo))) return -EFAULT; return 0; } return -ENOTTY; /* unknown command */
LAB 2 (cont)
The functions sbull_open and sbull_release
static int sbull_open(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; filp->private_data= dev; spin_lock(&dev->lock); dev->users++; spin_unlock(&dev->lock); return 0; } static int sbull_release(struct inode *inode, struct file *filp) { struct sbull_dev *dev = inode->i_bdev->bd_disk->private_data; spin_lock(&dev->lock); dev->users--; spin_unlock(&dev->lock); return 0; }
LAB 2 (cont)
Test the extended sbull modules:
make clean make sudo insmod sbull.ko sudo fdisk H 16 /dev/sbulla
LAB 2 (cont)
LAB 2 (cont)
Now we have two partitions in the sbull ramdisk Formats they by the following instructions: sudo mkfs.ext2 /dev/sbulla1 sudo mkfs.ext2 /dev/sbulla2 sudo mount /dev/sbulla1 temp sudo mount /dev/sbulla2 temp2 df
LAB 3
Please format the sbull in LAB1 by instruction: sudo mkfs.vfat F16 /dev/sbulla and observe what happened Try the same instruction executed on the sbulla in LAB2 Based on the LAB2, give me one block device with: 20MB and can be partitioned automatically: you can consult the sbull of LDD here
LAB 3 (cont)
LAB 3
There are two errors in the sbull of OReilly:
comment out the #include <linux/config.h> change the line 181
from end_that_request_last(req); to end_that_request_last(req, 1);
Reference
Driver porting: a simple block driver Linux Device Drivers 3rd Edition Cross-Referencing Linux Linux Block Device Architecture