在内核中,不仅要考虑SCSI协议栈本身,还必须和内核的DD框架融合到一起。
在内核中SCSI子系统的主要功能是:
- 探测SCSI设备,在内存建立可供设备驱动使用的数据结构
- 在sysfs文件系统中构造SCSI子系统的目录树
- SCSI高层驱动绑定SCSI设备,在内存中建立对应的数据结构
- 提供错误修复API,在SCSI命令错误和超时后被调用
如上图所示, 在内核中,SCSI 子系统被分为三层,从上到下分别是提供request<->CDB转换、设备级驱动能力的HLDD(High Level Device Driver),提供注册回调等公共功能的CommonService层,以及提供某种具体的SCSI协议栈实现的LLDD(Low Level Device Driver)
由此可见,SCSI子系统同IDE等接口驱动一样,位于内核IO栈中的最底层。例如,将一张使用一张PCI接口的SCSI适配器插入PCI插槽后,相应的PCI driver 就会在合适的时候match到相应的PCI device,并通过SCSI Common Service中提供的接口向SCSI LLDD 注册一个SCSI适配器对象及其操作方法,之后,
当上层的Block层将准备好的request提交到SCSI子系统中HLDD中的相应驱动,HLDD将request转换为CDB(__make_request()->__generic_unplug_device()->scsi_request_fn()->blk_peek_request()->sd_prep_fn()->scsi_setup_fs_cmnd()->scsi_init_io() ),并回调当初注册的接口((__make_request()->__generic_unplug_device()->scsi_request_fn()->scsi_dispatch_cmd()->scsi_host_template.queuecommand()),将CDB通过相应的SCSI协议栈发出。