Block device layer analysis 3

Source: Internet
Author: User

The above are general interfaces of devices on the IDE bus. Drivers of specific devices, such as CD, HD, floppy, and other ide devices, are not executed until do_request starts. Let's take a look at ide-Disk:

1. device initialization.

IDE Device Interface

Static ide_driver_t idedisk_driver = {

. Gen_driver = {

. Owner = this_module,

. Name = "ide-disk ",

. Bus = & ide_bus_type,

},

. Probe = ide_disk_probe,

. Remove = ide_disk_remove,

. Shutdown = ide_device_shutdown,

. Version = idedisk_version,

. Media = ide_disk,

. Supports_dsc_overlap = 0,

. Do_request
= Ide_do_rw_disk,

. End_request = ide_end_request,

. Error = _ ide_error,

. Abort = _ ide_abort,

. Proc = idedisk_proc,

};

Static struct block_device_operations idedisk_ops = {

. Owner = this_module,

. Open = idedisk_open,

. Release = idedisk_release,

. IOCTL = idedisk_ioctl,

. Getgeo = idedisk_getgeo,

. Media_changed = idedisk_media_changed,

. Revalidate_disk = idedisk_revalidate_disk

};

// Register the device

Static int _ init idedisk_init (void)

{

Return driver_register (& idedisk_driver.gen_driver );

}

// This probe function is executed by the driver model during device registration

Static int ide_disk_probe (ide_drive_t * drive)

{

Struct ide_disk_obj * idkp;

Struct gendisk * g;

Idkp = kzarloc (sizeof (* idkp), gfp_kernel );

// Allocate a gendisk Structure

G = alloc_disk_node (1 <partn_bits,

Hwif_to_node (drive-> hwif ));

Ide_init_disk (G, drive );

// Register the device with the above structure

Ide_register_subdriver (drive, & idedisk_driver );

Kref_init (& idkp-> kref );

// Some initialization operations

Idkp-> drive = drive;

Idkp-> driver = & idedisk_driver;

Idkp-> disk = g;

G-> private_data = & idkp-> driver;

Drive-> driver_data = idkp;

Idedisk_setup (drive );

G-> minors = 1 <partn_bits;

G-> driverfs_dev = & drive-> gendev;

G-> flags = drive-> removable? Genhd_fl_removable: 0;

Set_capacity (G, idedisk_capacity (drive ));

G-> fops = & idedisk_ops;

Add_disk (g); // insert a device. This device is available now.

Return 0;

}

2. Process requests sent from the IDE Bus

As you can see, the IDE bus driver calls the device's do_request () to process this request. We can see it in the above registration. In ide-disk, It is ide_do_rw_disk ():

/*

* 268435455 = 137439 MB or 28bit limit

* 320173056 = 163929 MB or 48bit addressing

* 1073741822 = 549756 MB or 48bit addressing fake drive

*/

Static ide_startstop_t ide_do_rw_disk (ide_drive_t * drive, struct Request * rq, sector_t block)

{

Ide_hwif_t * hwif = hwif (drive );

......

If (hwif-> rw_disk)

Hwif-> rw_disk (drive, rq );

Return _ ide_do_rw_disk (drive, RQ, block );

}

// The following figure shows the driver of a specific hard drive device. Because we only care about the block device driver programming framework, we will not go deep into it.

/*

* _ Ide_do_rw_disk () issues read and write commands to a disk,

* Using LBA if supported, or CHS otherwise, to address sectors.

*/

Static ide_startstop_t _ ide_do_rw_disk (ide_drive_t * drive, struct Request * rq, sector_t block)

{

Ide_hwif_t * hwif = hwif (drive );

Unsigned int DMA = drive-> using_dma;

U8 lba48 = (drive-> addressing = 1 )? 1: 0;

Task_ioreg_t command = win_nop;

Ata_nsector_t nsectors;

Nsectors. All = (002) RQ-> nr_sectors;

If (hwif-> no_lba48_dma & lba48 & DMA ){

If (block + RQ-> nr_sectors> 1ull <28)

DMA = 0;

Else

Lba48 = 0;

}

If (drive-> select. B. LBA ){

If (lba48 ){

......

} Else {

......

}

} Else {

......

}

If (DMA ){

......

/* Fallback to Pio */

Ide_init_sg_cmd (drive, rq );

}

If (rq_data_dir (RQ) = read ){

If (drive-> mult_count ){

Hwif-> data_phase = taskfile_multi_in;

Command = lba48? Win_multread_ext: win_multread;

} Else {

Hwif-> data_phase = taskfile_in;

Command = lba48? Win_read_ext: win_read;

}

Ide_execute_command (drive, command, & task_in_intr, wait_cmd, null );

Return ide_started;

} Else {

......

Return pre_task_out_intr (drive, rq );

}

}

3. Summary of block Device Drivers

From the above we can see that the main work of block device driver programming includes allocating and initializing a gendisk structure, allocating and initializing a request queue, and writing request processing functions (request_fn ), and interrupt handling. However, there are some differences between the implementations of different devices. Most of the IDE devices we see above are implemented at the IDE bus level, it does a lot of tedious but necessary work and provides unified interfaces to the lower-layer specific devices, which greatly simplifies the compilation process of block device drivers.

If you are interested, refer to the implementation of kernel ramdisk.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.