request到ATA cmd的转换过程

本文详细解析了Linux存储系统如何整合到SCSI框架下,包括SATA、USB及未来可能的NVMe设备管理。重点介绍了从requestqueue中摘取request并最终转化为SATA硬盘处理的过程,涵盖SCSIcmd到ATAcmd的转换机制,以及AHCIController如何将ATAcmd转换为FIS结构并发送至硬盘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://www.cnblogs.com/raymondpang/articles/4469500.html

1. 知识铺垫

  据我所知(可能并不准确),Linux的存储系统基本上都已经被整合到SCSI存储框架之下,SAS自不必说,像SATA接口的设备(机械硬盘、SSD、光驱),USB设备都已经由SCSI框架管理,而NVMe虽然还未完全融入SCSI存储框架(Kernel 3.16.0),但是已经预留了SCSI有关的接口,相信随着内核的更新,Intel一定会推动把NVMe也纳入到SCSI的管理之下。

  在阅读之前,应当提前了解的是:应用层的读写操作,会以bio的形式提交给block层,然后,block会把bio转换成request,并把该request加入到专为某个SCSI device服务的request queue中,接下来会有内核线程适时地从该queue中摘取request,并转换成SCSI cmd,再转换成ATA cmd,最终交由AHCI Controller(对于AHCI,实际上会把ATA cmd转换成FIS结构)发向硬盘执行。

  SCSI与ATA本就是两套不同的标准,因此它们各自的命令集是不同的,虽然有些功能类似的cmd,但是cmd格式还是不同的。

  本文主要关注的是从request queue中摘取request并最终交由SATA硬盘处理的过程,因此其他无关的内容不会过多涉及。 

2. 转换流程

  虽然下面的内容仅针对AHCI,但是所讲述的request到ATA cmd的转换过程,对PATA或者AHCI的IDE mode也基本相同。

2.1 request queue是什么?从何而来?

  任何一个PCI Device,其驱动程序一定要实例化struct pci_driver结构,通常.probe成员被认为是初始化函数,也就是加载driver时第一个要被执行的函数(module_init()声明的函数才是第一个被执行的函数)。在AHCI driver的ahci_init_one(即.probe成员)函数中调用ata_host_register()来注册Controller,其中会调用scsi_alloc_sdev()来创建scsi device,在该函数中,创建了该scsi device对应的request queue,并指定了超时处理函数等信息。

  从scsi_alloc_queue()得知,从queue中摘取request的工作交由scsi_request_fn来完成,而队列中的request则是在提交了bio之后,由make_request_fn()负责转换并加入队列的。 

2.2 request转换成SCSI cmd的过程

  第一步,尝试从queue中摘取request(因为scsi_request_fn的调用时机并不一定是有request插入到队列中,还有可能是完成一个request时,所以这里用“尝试”一词),如果摘取到request,并且可以向device发送cmd,则继续执行,否则跳出scsi_request_fn,等待下一次被调用。

  在这里,blk_peek_request()会从request queue中取出request,然后创建对应的SCSI cmd结构,并且调用prep_rq_fn()进行必要的初始化(例如分配sg list),special成员,后面会用到;scsi_dev_queue_ready可能返回0的条件是:device被block了,或者device已经满负荷,不能再接收新的cmd了。

  第二步,从request的special成员取出scsi_cmd结构体,也就是说special成员的实际结构就是scsi_cmd,并进行一些必要的赋值操作。

  第三步,调用scsi_dispatch_cmd(),进一步初始化scsi_cmd结构体(例如指定scsi_cmd的scsi_done回调函数等),并向下层转发SCSI cmd。

2.3 由SCSI cmd转换成ATA cmd

  接着2.2的第三步, scsi_dispatch_cmd()一路调用下来,会调用到__ata_scsi_queuecmd(),该函数的作用就是获取SCSI cmd到ATA cmd的转换接口函数,并且调用该接口正式将SCSI cmd转换成ATA cmd。具体地:

  首先,根据scsi cmd的操作码,查询是否有对应的转成ATA cmd的函数。这是针对硬盘的处理:

 

  下面是操作码对应的转换函数:

 

  从ata_get_xlat_func()可以看出,并不是每个SCSI cmd都能转换成ATA cmd(SCSI SPEC与ATA SPEC本就有两套不同的命令集),因此在实际运行过程中,有可能遇到该函数返回NULL的情形。对于能够找到转换函数的SCSI cmd,就调用相应的转换函数把它转换成ATA cmd,对于无法找到转换函数的SCSI cmd,就根据该cmd的功能,用其他手段来模拟该cmd的执行,只要达到执行该SCSI cmd的目的即可。

  例如READ_6(SCSI cmd)对应的转换函数是ata_scsi_rw_xlat(),该函数内部通过调用ata_build_rw_tf()来把SCSI cmd转换成task_file结构,该结构就代表了一个ATA cmd,早期的PATA driver中,可以直接把该结构的成员写入到Controller的各个寄存器中,从而触发Controller向PATA device发送ATA cmd。 

2.4 ATA cmd被转换成FIS结构,然后发往硬盘

  AHCI Controller不能识别task file结构,它只能识别FIS结构,因此要想控制硬盘,还需要把ATA cmd转换成FIS结构,再填入AHCI Controller的寄存器中。这一切都是在Low Level Driver中完成的,这些工作是通过ata_scsi_translate()接口来封装。该函数分四步执行:

 

第一步:获取一个空闲cmd slot的tag

  tag用以表示“有权力”向Controller的寄存器中写入代表ATA cmd的FIS结构(后面提到的FIS指的就是ATA cmd对应的FIS结构),AHCI Controller共有32个cmd slot,用tag 0来表示第1个cmd slot,tag 31表示最后一个cmd slot,成功获取一个tag,就意味着获得对应的cmd slot,也就拥有了它所对应的内存资源、寄存器等的操作控制权。

  另外,还应当了解在32个cmd slot中,最后一个有特殊用途,因此,理论上Driver可以同时向AHCI Controller写入31个FIS结构,即AHCI Controller可以在无需driver参与的情况下连续向硬盘发送31个cmd。

第二步:把SCSI cmd对应的sg list赋给tag对应的qc结构的。

  qc结构体代表和维护一个ATA cmd,它包含的内容更加丰富(例如包含有tag信息、sg list信息等),Low Level Driver在操作ATA cmd相关的内容时就以qc为原料。

  对于有DMA传输的ATA cmd,那么一定需要sg list结构,ata_sg_init()仅仅是把SCSI cmd中的sg list信息赋给qc结构,实际上sg list是在2.2的blk_peek_request()中创建的。

第三步:指定qc的complete回调函数,即cmd完成后,会调用该函数。

  在中断处理函数中,完成一个ATA cmd之后,会从ata_qc_complete()开始一步步调用至该回调函数。

第四步:把ATA cmd转换成FIS,写入到AHCI Controller的寄存器中

  ata_qc_issue()的主体就是两个函数:一是qc_prep(),二是qc_issue(),它们在ahci driver中分别对应ahci_qc_prep(),和ahci_qc_issue()。

ahci_qc_prep()的工作:

  调用ata_tf_to_fis()把task file(即ATA cmd)转换成FIS,调用ahci_fill_sg()把sg list填写到寄存器中(即PRD table),调用ahci_fill_cmd_slot()填写cmd slot寄存器(32 Byte长的cmd header结构)。

ahci_qc_issue()的工作:

   触发PxCI寄存器(如果是NCQ cmd,还会同时写PxSACT寄存器),通知Controller向硬盘发送FIS结构吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值