linux IDE驱动分析之Ide_driver的注册(一)

Ide_driver的注册(一)

前面的故事中大家都知道,linux的设备驱动是以模块的形式加载的。那么Ide_driver的注册肯定也不例外。按照常规也应该有一个module_init()。早在开始讲述ide故事的时候我们就看过kconfigmakefile这份内核地图了,在里面我们列出了我们所关心的.c文件。并且看到其中的generic ATA/ATAPI disk support感觉到了和我们接下来要说的generic disk有莫大的关系,他所对应的文件ide_gd.c。那么接下来的时间我们就尝试去认识一下,如果一切如我们所料,应该能够见到熟悉的module_init()。进入ide_gd.c.

果然428行我们见到了module_init(ide_gd_init),跟踪一下.

[/linux/driver/ide/ide-gd.c]

413 static int __init ide_gd_init(void)

414 {

415 printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "/n");

416 return driver_register(&ide_gd_driver.gen_driver);

417 }

函数精炼到了极致,416行给我们的感觉是刚见面就意味着别离。也罢,先还是来看看ide_gd_driver….

[/linux/driver/ide/ide-gd.c]

163 static struct ide_driver ide_gd_driver = {

164 .gen_driver = {

165 .owner = THIS_MODULE,

166 .name = "ide-gd",

167 .bus = &ide_bus_type,

168 },

169 .probe = ide_gd_probe,

170 .remove = ide_gd_remove,

171 .resume = ide_gd_resume,

172 .shutdown = ide_gd_shutdown,

173 .version = IDE_GD_VERSION,

174 .do_request = ide_gd_do_request,

175 #ifdef CONFIG_IDE_PROC_FS

176 .proc_entries = ide_disk_proc_entries,

177 .proc_devsets = ide_disk_proc_devsets,

178 #endif

179 };

咋一看,不是别人,正是前面折腾的死去活来的ide_driver。既然都见面了也不在乎多看她一眼..

[/linux/driver/ide/ide.h]

1009 /*

1010  * Subdrivers support.

1011  *

1012  * The gendriver.owner field should be set to the module owner of this driver.

1013  * The gendriver.name field should be set to the name of this driver

1014  */

1015 struct ide_driver {

1016 const char *version;

1017 ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);

1018 struct device_driver gen_driver;

1019 int (*probe)(ide_drive_t *);

1020 void (*remove)(ide_drive_t *);

1021 void (*resume)(ide_drive_t *);

1022 void (*shutdown)(ide_drive_t *);

1023 #ifdef CONFIG_IDE_PROC_FS

1024 ide_proc_entry_t * (*proc_entries)(ide_drive_t *);

1025 const struct ide_proc_devset * (*proc_devsets)(ide_drive_t *);

1026 #endif

1027 };

好了注册的过程是设备模型的内容,我们就此打住。其实过程和刚才所讲的device_register是差不多的,只是这个时候是device_driver主动勾引device了,然后依然会调用really_probe这个大媒婆,剩下的内容就和刚才所讲的一致了。继续炒剩饭每当一个设备或者驱动注册到系统中来的时候,都会调用相应总线的machprobe方法。回到前面总线probe..

130struct ide_driver *drv = to_ide_driver(dev->driver)这还是linux中那个惯用的伎俩#define to_ide_driver(drv) container_of(drv, struct ide_driver, gen_driver),但还是屡试不爽。

132 return drv->probe ? drv->probe(drive) : -ENODEV;就正式调用了ide_driver中的probe方法。好了镜头转向ide_gd_probe,源代码如下:

[/linux/driver/ide/ide-gd.c]

335 static int ide_gd_probe(ide_drive_t *drive)

336 {

337 const struct ide_disk_ops *disk_ops = NULL;

338 struct ide_disk_obj *idkp;

339 struct gendisk *g;

340

341 /* strstr("foo", "") is non-NULL */

342 if (!strstr("ide-gd", drive->driver_req))

343 goto failed;

344

345 #ifdef CONFIG_IDE_GD_ATA

346 if (drive->media == ide_disk)

347 disk_ops = &ide_ata_disk_ops;

348 #endif

349 #ifdef CONFIG_IDE_GD_ATAPI

350 if (drive->media == ide_floppy)

351 disk_ops = &ide_atapi_disk_ops;

352 #endif

353 if (disk_ops == NULL)

354 goto failed;

355

356 if (disk_ops->check(drive, DRV_NAME) == 0) {

357 printk(KERN_ERR PFX "%s: not supported by this driver/n",

358 drive->name);

359 goto failed;

360 }

361

362 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);

363 if (!idkp) {

364 printk(KERN_ERR PFX "%s: can't allocate a disk structure/n",

365 drive->name);

366 goto failed;

367 }

368

369 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));

370 if (!g)

371 goto out_free_idkp;

372

373 ide_init_disk(g, drive);

374

375 idkp->dev.parent = &drive->gendev;

376 idkp->dev.release = ide_disk_release;

377 dev_set_name(&idkp->dev, dev_name(&drive->gendev));

378

379 if (device_register(&idkp->dev))

380 goto out_free_disk;

381

382 idkp->drive = drive;

383 idkp->driver = &ide_gd_driver;

384 idkp->disk = g;

385

386 g->private_data = &idkp->driver;

387

388 drive->driver_data = idkp;

389 drive->debug_mask = debug_mask;

390 drive->disk_ops = disk_ops;

391

392 disk_ops->setup(drive);

393

394 set_capacity(g, ide_gd_capacity(drive));

395

396 g->minors = IDE_DISK_MINORS;

397 g->driverfs_dev = &drive->gendev;

398 g->flags |= GENHD_FL_EXT_DEVT;

399 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)

400 g->flags = GENHD_FL_REMOVABLE;

401 g->fops = &ide_gd_ops;

402 add_disk(g);

403 return 0;

404

405 out_free_disk:

406 put_disk(g);

407 out_free_idkp:

408 kfree(idkp);

409 failed:

410 return -ENODEV;

411 }

341-343行在ide-drive-t中保存着驱动器对驱动的特殊要求,这里如果驱动器要求的不是ide-gd,那么ide_gd_driver也就没有必要再自作多情了。至于ide-gd在哪设置的至今还是个谜团。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

345-347行毫无疑问使我们关心的了.

[ide-disk.c]

758 const struct ide_disk_ops ide_ata_disk_ops = {

759 .check = ide_disk_check,

760 .set_capacity = ide_disk_set_capacity,

761 .get_capacity = ide_disk_get_capacity,

762 .setup = ide_disk_setup,

763 .flush = ide_disk_flush,

764 .init_media = ide_disk_init_media,

765 .set_doorlock = ide_disk_set_doorlock,

766 .do_request = ide_do_rw_disk,

767 .ioctl = ide_disk_ioctl,

768 };

这里全是为硬盘驱动所定义的方法,后面我们用到了再详细分析..

356行调用了上面ide_disk_check,下面来看下源代码:

[ide-disk.c]

647 static int ide_disk_check(ide_drive_t *drive, const char *s)

648 {

649 return 1;

650 }

这里认为检测一直是通过的。

362行出现了一个新的数据结构类型,ide_disk_obj,相应的定义如下:

[ide-gd.h]

16 struct ide_disk_obj {

17 ide_drive_t *drive;

18 struct ide_driver *driver;

19 struct gendisk *disk;

20 struct device dev;

21 unsigned int openers; /* protected by BKL for now */

22

23 /* used for blk_{fs,pc}_request() requests */

24 struct ide_atapi_pc queued_pc;

25

26 /* Last error information */

27 u8 sense_key, asc, ascq;

28

29 int progress_indication;

30

31 /* Device information */

32 /* Current format */

33 int blocks, block_size, bs_factor;

34 /* Last format capacity descriptor */

35 u8 cap_desc[8];

36 /* Copy of the flexible disk page */

37 u8 flexible_disk_page[32];

38 };

从上面的这个数据结构我们看到,前面我们介绍的几大重要的数据结构在这里齐亮相,到底他有多么神奇的魅力,后面我们再来说,这里给出来留点印象。

Kzalloc相当于kmallocmemset的作用,就是申请空间然后初始化为0

369行这个函数alloc_disk_node是块设备相关的内容,这里我们就不深入进去了,姑且理解成kzalloc

373行调用ide_init_disk,前面在ide_disk_obj中我们定义了一个gendisk结构的指针叫disk,这里出现一个init_disk。东西不能看的太透彻,否则就会失去美感。代码也一样,这里就不去刨根问题的搞清gendisk是个什么意思,就跟着感觉走不过还是去看一下ide_init_disk源码:

[ide_gd_probe]->[ide_init_disk]

942 void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)

943 {

944 ide_hwif_t *hwif = drive->hwif;

945 unsigned int unit = drive->dn & 1;

946

947 disk->major = hwif->major;

948 disk->first_minor = unit << PARTN_BITS;

949 sprintf(disk->disk_name, "hd%c", 'a' + hwif->index * MAX_DRIVES + unit);

950 disk->queue = drive->queue;

951 }

上面这段代码总他来看比较简单,就是设置当前这个gendisk所对应的主次设备号,名字以及请求队列等相关的内容。

375-377gendisk设置以后,ide_disk_object这个老大可千万别忘了。他可是ide驱动这边土生土长的结够啊。

379行又出现了一个device_register,这里和我们之前讲的那个主,貌似有点区别,并未指明总线等相关信息,这里实际上只是在sysfs中留下自己的身影。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

382-390行这些初始化的内容比较简单,留个印象。

392行看名字就知道不是什么好惹的主,还是来详细分析一下:

[ide_gd_probe]->[ ide_disk_setup]

652 static void ide_disk_setup(ide_drive_t *drive)

653 {

654 struct ide_disk_obj *idkp = drive->driver_data;

655 struct request_queue *q = drive->queue;

656 ide_hwif_t *hwif = drive->hwif;

657 u16 *id = drive->id;

658 char *m = (char *)&id[ATA_ID_PROD];

659 unsigned long long capacity;

660

661 ide_proc_register_driver(drive, idkp->driver);

662

663 if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)

664 return;

665

666 if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {

667 /*

668  * Removable disks (eg. SYQUEST); ignore 'WD' drives

669  */

670 if (m[0] != 'W' || m[1] != 'D')

671 drive->dev_flags |= IDE_DFLAG_DOORLOCKING;

672 }

673

674 (void)set_addressing(drive, 1);

675

676 if (drive->dev_flags & IDE_DFLAG_LBA48) {

677 int max_s = 2048;

678

679 if (max_s > hwif->rqsize)

680 max_s = hwif->rqsize;

681

682 blk_queue_max_sectors(q, max_s);

683 }

684

685 printk(KERN_INFO "%s: max request size: %dKiB/n", drive->name,

686        queue_max_sectors(q) / 2);

687

688 if (ata_id_is_ssd(id))

689 queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);

690

691 /* calculate drive capacity, and select LBA if possible */

692 ide_disk_get_capacity(drive);

693

694 /*

695  * if possible, give fdisk access to more of the drive,

696  * by correcting bios_cyls:

697  */

698 capacity = ide_gd_capacity(drive);

699

700 if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {

701 if (ata_id_lba48_enabled(drive->id)) {

702 /* compatibility */

703 drive->bios_sect = 63;

704 drive->bios_head = 255;

705 }

706

707 if (drive->bios_sect && drive->bios_head) {

708 unsigned int cap0 = capacity; /* truncate to 32 bits */

709 unsigned int cylsz, cyl;

710

711 if (cap0 != capacity)

712 drive->bios_cyl = 65535;

713 else {

714 cylsz = drive->bios_sect * drive->bios_head;

715 cyl = cap0 / cylsz;

716 if (cyl > 65535)

717 cyl = 65535;

718 if (cyl > drive->bios_cyl)

719 drive->bios_cyl = cyl;

720 }

721 }

722 }

723 printk(KERN_INFO "%s: %llu sectors (%llu MB)",

724  drive->name, capacity, sectors_to_MB(capacity));

725

726 /* Only print cache size when it was specified */

727 if (id[ATA_ID_BUF_SIZE])

728 printk(KERN_CONT " w/%dKiB Cache", id[ATA_ID_BUF_SIZE] / 2);

729

730 printk(KERN_CONT ", CHS=%d/%d/%d/n",

731  drive->bios_cyl, drive->bios_head, drive->bios_sect);

732

733 /* write cache enabled? */

734 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))

735 drive->dev_flags |= IDE_DFLAG_WCACHE;

736

737 set_wcache(drive, 1);

738

739 if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&

740     (drive->head == 0 || drive->head > 16)) {

741 printk(KERN_ERR "%s: invalid geometry: %d physical heads?/n",

742 drive->name, drive->head);

743 drive->dev_flags &= ~IDE_DFLAG_ATTACH;

744 } else

745 drive->dev_flags |= IDE_DFLAG_ATTACH;

746 }

661proc文件系统相关的内容,略过.

663-664行在前面我们说过drive->dev_flags这个flags,现在派上用场了。如果设备之前的读ID失败了,那么后面的操作就没有意义了,直接返回.

666-672行这里关于移动设备的,除去WD的设备,其他的只要removeable一律戴上drive->dev_flags |= IDE_DFLAG_DOORLOCKING;的帽子。

674set_addressing设置设备的访问方式。看下源代码:

[ide_gd_probe]->[ ide_disk_setup]->[ set_addressing]

614 /*

615  * drive->addressing:

616  * 0: 28-bit

617  * 1: 48-bit

618  * 2: 48-bit capable doing 28-bit

619  */

620 static int set_addressing(ide_drive_t *drive, int arg)

621 {

622 if (arg < 0 || arg > 2)

623 return -EINVAL;

624

625 if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||

626     ata_id_lba48_enabled(drive->id) == 0))

627 return -EIO;

628

629 if (arg == 2)

630 arg = 0;

631

632 if (arg)

633 drive->dev_flags |= IDE_DFLAG_LBA48;

634 else

635 drive->dev_flags &= ~IDE_DFLAG_LBA48;

636

637 return 0;

638 }

这段函数实际就是根据获得的id信息,设置驱动器是否支持LAB48位的访问模式。

677-680行这几行就是LBA48模式下,请求所允许的最大的扇区数。

682行调用 blk_queue_max_sectors设置请求队列支持的最大扇区数,下面来看一下代码:

[ide_gd_probe]->[ ide_disk_setup]->[ blk_queue_max_sectors]

207 /**

208  * blk_queue_max_sectors - set max sectors for a request for this queue

209  * @q:  the request queue for the device

210  * @max_sectors:  max sectors in the usual 512b unit

211  *

212  * Description:

213  *    Enables a low level driver to set an upper limit on the size of

214  *    received requests.

215  **/

216 void blk_queue_max_sectors(struct request_queue *q, unsigned int max_sectors)

217 {

218 if ((max_sectors << 9) < PAGE_CACHE_SIZE) {

219 max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);

220 printk(KERN_INFO "%s: set to minimum %d/n",

221        __func__, max_sectors);

222 }

223

224 if (BLK_DEF_MAX_SECTORS > max_sectors)

225 q->limits.max_hw_sectors = q->limits.max_sectors = max_sectors;

226 else {

227 q->limits.max_sectors = BLK_DEF_MAX_SECTORS;

228 q->limits.max_hw_sectors = max_sectors;

229 }

230 }

这里如果max_sectors得容量不足一页内存大小,就将以页的大小作为最大的限制容量。我们知道一个扇区的大小一般我们定义为512字节,所以max_sectors换算成以字节为单位就左移了9位。如果接口允许的扇区比块设备的BLK_DEF_MAX_SECTORS默认扇区数目大,那么就用BLK_DEF_MAX_SECTORS;作为最大扇区,否则接口和块设备允许的扇区数目全部max_sectors限制。回到ide_disk_setup中来.

688-689行固态硬盘相关的内容。

692行读取硬盘的容量,详细看一下源码:

[ide_gd_probe]->[ ide_disk_setup] ->[ ide_disk_get_capacity]

355 static int ide_disk_get_capacity(ide_drive_t *drive)

356 {

357 u16 *id = drive->id;

358 int lba;

359

360 if (ata_id_lba48_enabled(id)) {

361 /* drive speaks 48-bit LBA */

362 lba = 1;

363 drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);

364 } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {

365 /* drive speaks 28-bit LBA */

366 lba = 1;

367 drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);

368 } else {

369 /* drive speaks boring old 28-bit CHS */

370 lba = 0;

371 drive->capacity64 = drive->cyl * drive->head * drive->sect;

372 }

373

374 drive->probed_capacity = drive->capacity64;

375

376 if (lba) {

377 drive->dev_flags |= IDE_DFLAG_LBA;

378

379 /*

380 * If this device supports the Host Protected Area feature set,

381 * then we may need to change our opinion about its capacity.

382 */

383 if (ata_id_hpa_enabled(id))

384 idedisk_check_hpa(drive);

385 }

386

387 /* limit drive capacity to 137GB if LBA48 cannot be used */

388 if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&

389     drive->capacity64 > 1ULL << 28) {

390 printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "

391        "%llu sectors (%llu MB)/n",

392        drive->name, (unsigned long long)drive->capacity64,

393        sectors_to_MB(drive->capacity64));

394 drive->probed_capacity = drive->capacity64 = 1ULL << 28;

395 }

396

397 if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&

398     (drive->dev_flags & IDE_DFLAG_LBA48)) {

399 if (drive->capacity64 > 1ULL << 28) {

400 printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"

401  " will be used for accessing sectors "

402  "> %u/n", drive->name, 1 << 28);

403 } else

404 drive->dev_flags &= ~IDE_DFLAG_LBA48;

405 }

406

407 return 0;

408 }

360-372 根据硬盘访问模式的不同,得出相应的硬盘容量。

377行设置后面的访问方式为lba,关于硬盘的两种常用的访问方式LBAC/H/S,网上有详细的说明,这里就不再多说了。由于chs支持的容量很小,所以现在的硬盘大都是利用LBA线性地址来访问的。

383-384Host protected area。主要的工作原理就是设置读取的硬盘最大的扇区号,从而把高端的内容隐藏起来,这个最大的扇区号能够写在硬盘的某一个地方,即使你把这个硬盘挂到其它机器上,正常情况下你也看不到隐藏的内容,就算是通过FdiskPowerQuest PartitionMagic 之类的分区工具软件也发现不了这部空间,另外HPA是在ATA/ATAPI-4里面定义的一个区域,在BIOS可见空间之后,所以通过BIOS依然访问不到(个别机型可通过BIOS设置访问)。在HPA技术最高等级的安全性下,无法访问、看到、删除HPA分区,甚至无法克隆。所以这里我们需要调整刚才所获取的硬盘容量大小。

388-395行这段代码意思就很明显了,要是不采用lba48访问的话,访问容量限制在28位寻址空间。

397-405行代码相对简单,我们就不详述了。继续回到ide_disk_setup

700-722行与boot信息相关的内容,略过。

737set_wcache(drive, 1),跟踪源码:

[ide_gd_probe]->[ ide_disk_setup] ->[ ide_disk_get_capacity]->[ set_wcache]

559 static int set_wcache(ide_drive_t *drive, int arg)

560 {

561 int err = 1;

562

563 if (arg < 0 || arg > 1)

564 return -EINVAL;

565

566 if (ata_id_flush_enabled(drive->id)) {

567 err = ide_do_setfeature(drive,

568 arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);

569 if (err == 0) {

570 if (arg)

571 drive->dev_flags |= IDE_DFLAG_WCACHE;

572 else

573 drive->dev_flags &= ~IDE_DFLAG_WCACHE;

574 }

575 }

576

577 update_ordered(drive);

578

579 return err;

580 }

这段函数说的最有意义的一句话也就在567-568行了,因为有个 ide_do_setfeature显得他高级了不少。跟进去.

[ide_gd_probe]->[ ide_disk_setup

->[ ide_disk_get_capacity]->[ set_wcache]->[ ide_do_setfeature]

506 static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)

507 {

508 struct ide_cmd cmd;

509

510 memset(&cmd, 0, sizeof(cmd));

511 cmd.tf.feature = feature;

512 cmd.tf.nsect   = nsect;

513 cmd.tf.command = ATA_CMD_SET_FEATURES;

514 cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;

515 cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;

516

517 return ide_no_data_taskfile(drive, &cmd);

518 }

这里出现了一个ide_cmd还是来看一下他长什么样子。

288 struct ide_cmd {

289 struct ide_taskfile tf;

290 struct ide_taskfile hob;

291 struct {

292 struct {

293 u8 tf;

294 u8 hob;

295 } out, in;

296 } valid;

297

298 u16 tf_flags;

299 u8 ftf_flags; /* for TASKFILE ioctl */

300 int protocol;

301

302 int sg_nents;   /* number of sg entries */

303 int orig_sg_nents;

304 int sg_dma_direction; /* DMA transfer direction */

305

306 unsigned int nbytes;

307 unsigned int nleft;

308 unsigned int last_xfer_len;

309

310 struct scatterlist *cursg;

311 unsigned int cursg_ofs;

312

313 struct request *rq; /* copy of request */

314 };

前面是大名鼎鼎的ide_taskfile这个在前面已经说过了。另外还有一个在块设备中享有名气的request,既然人家是块设备那边的,这里也就没有必要在背后说了。记下他就行。

然后就说到了517ide_no_data_taskfile(drive, &cmd);开始处理这个setfeature了,由于不是数据传输所以taskfile对应的是no_data;进去瞧瞧..

[ide-taskfile.c]

462 int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd)

463 {

464 cmd->protocol = ATA_PROT_NODATA;

465

466 return ide_raw_taskfile(drive, cmd, NULL, 0);

467 }

466行光看名字就知道他拽的不行了, 基于前面的no_data的声明这里就设置了cmd->protocol = ATA_PROT_NODATA; ,进到ide_raw_taskfile里面看个究竟。

[ide-taskfile.c]

426 int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,

427      u16 nsect)

428 {

429 struct request *rq;

430 int error;

431

432 rq = blk_get_request(drive->queue, READ, __GFP_WAIT);

433 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;

434

435 if (cmd->tf_flags & IDE_TFLAG_WRITE)

436 rq->cmd_flags |= REQ_RW;

437

438 /*

439  * (ks) We transfer currently only whole sectors.

440  * This is suffient for now.  But, it would be great,

441  * if we would find a solution to transfer any size.

442  * To support special commands like READ LONG.

443  */

444 if (nsect) {

445 error = blk_rq_map_kern(drive->queue, rq, buf,

446 nsect * SECTOR_SIZE, __GFP_WAIT);

447 if (error)

448 goto put_req;

449 }

450

451 rq->special = cmd;

452 cmd->rq = rq;

453

454 error = blk_execute_rq(drive->queue, NULL, rq, 0);

455

456 put_req:

457 blk_put_request(rq);

458 return error;

459 }

432行块设备那边的函数,你大可理解为申请request,这里就不细说。

433-436rq就把这边ide disk的一些请求通过这种关联的方式带回到了块设备层,同样444-449行如果说这次taskfile中有数据传输的请求,那么也将两者关联起来,而并非函数名称所说的真正是去map

454rq设置好了就交给块设备层去处理吧,当然就调用了blk_execute_rq,这些事情就是块设备那边的事情了。那么我们该做的事情就真的是完了吗,您也不想想我们现在看的可是IDE底层的驱动啊,真正任何一次发送命令或者其他的操作最终都是要作用到硬件上才算真正完成了。可见blk_execute_rq背后还有一个更大的不可告人的秘密..

还记得很久很久以前,当我们还在讲述ide_generic的那段青涩往事的时候,讲过一个 static int ide_init_queue(ide_drive_t *drive) 函数,他里面调用了一个q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif));。对没错就是他do_ide_request,当时我们还单独把它提出来说迟早有一天他会翻身做人的。没想到到了今天,他总算是快解放了。好了,闲话少叙。blk_execute_rq我们可以不去研究但是他最终不管通过何种方式迟早会调用到do_ide_request。那么接下来的日子我们就把目光投向这个天使般的精灵.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值