参考资料: http://www.ibm.com/developerworks/cn/linux/l-scsi-subsystem/
Scsi子系统是实现系统使用scsi设备的基础, 包括scsi设备驱动, HBA管理, IO流处理,
Scsi设备管理, scsi命令处理等一系列功能,主要可以分为三层,接口层,中间层和较底层.
Linux设备管理一般包括:总线core, host驱动, 设备驱动管理等.
总线core提供host设备的管理, 设备驱动的管理, 总线模块的初始化
在一个host设备probe的时候必须使用总线core提供的add_host接口,将host设备注册到总线核心, 总线core才能识别到该host.
总线core同时管理者该总线类型的所有设备驱动, 当总线扫描/识别到host上的设备的时候, 就会匹配设备驱动, 如果匹配到就调用设备驱动的probe, 向系统注册该设备
总线core主要管理host, driver, device, 让它们直接能很好的衔接起来.
设备接口层:
提供scsi设备的使用接口
scsi/sg.c:
实现sg字符设备,是scsi的通用scsi command接口,通过该接口可以自由的发送该 设备支持的scsi命令到设备上。每个scsi设备都会注册一个sg设备。最大的sg设备数为32768.
init_sg:
申请字符设备号,注册设备类,注册接口sg_interface到scsi核心,提供函数(sg_add和sg_remove)给scsi核心,scsi设备在probe/remove的时候会调用sg_add/sg_remove自动生成sg设备
sg_add:
在scsi总线发现设备(包括适配器)的时候调用,注册该设备的scsi通用命令接口(注册成字符设备),通过该字符设备,可以发送scsi到该设备。注册sg设备有个重要的操作接口sg_fops, 系统调用就是通过sg_fops操作sg设备。sg_alloc可以根据scsi系统提供的scsi_device生成sg_device。
sg_device:
移除一个scsi设备的命令接口字符设备
scsi/sd.c:
实现scsi硬盘接口,通过硬盘注册接口,将scsi硬盘注册到块设备系统,使得系统 可以通过通用块设备接口来使用scsi硬盘,在scsi/sd.c里面实现。
init_sd:
在模块加载的时候,申请主块设备号(16个),注册了设备类(sd_disk_class),将sd设备驱动(sd_template.gendrv), 注册到scsi核心,sd驱动包含一下函数:
sd_probe:
scsi总线发现sd块设备的时候调用,初始化设备, 将该sd硬盘增加入到系统硬盘(add_disk)
sd_remove:
将sd设备从块设备系统中移除,
sd_shutdown: sd掉电
sd_pm_ops: sd电源管理操作,power manager
misc/enclosure.c:
实现一个设备类enclosure,
scsi/ses.c
实现一个scsi的enclosure字符设备,是管理scsi的enclosure的接口,是scsi硬盘柜的管理接口。在没有磁盘柜的系统中是看不到的, 其实现方式和sg类似.
Ses_init:
初始化ses模块, 注册接口ses_interface到scsi核心,
ses_intf_add:
Scsi核心发现一个ses设备的时候调用, 初始化ses设备, 并注册ses字符设备.
ses_intf_remove:
其他设备:
scsi/sr.c 实现一个scsi光盘设备,实现方式和sd类似
scsi/st.c 实现一个scsi磁带设备,实现方式和sd类似
中间层(MID)/SCSI核心:
中间层实现了各类的scsi command,胶合了接口层和LLDD层,将接口层传输过来的数据,用scsi的命令封装,中间层也实现很多给HBA驱动和接口层使用的库.
Scsi/scsi.c
是scsi core,scsi子系统框架初始化。
init_scsi:
初始化scsi子系统(scsi core),
scsi_dispath_cmd:
scsi_lib.c最后将调用本函数,将scsi命令送到core层, 经处理后发送到host->hostt->queuecommand
scsi/scsi_scan.c
是scsi host扫描scsi设备的库,在scsi HBA启动的时候调用, 主要函数如下:
scsi_scan_host
扫描scsi总线上的所有设备
>>>do_scsi_scan_host
>>>scsi_scan_channel
扫描scsi host的莫个通道
>>>__scsi_scan_target
扫描设备
>>>scsi_probe_and_add_lun
>>>scsi_device_lookup_by_target
在target里找lun是否已经存在
>>>scsi_probe_lun
发送scsi命令查看lun是否存在
>>>scsi_add_lun
增加lun设备
scsi_scan_target
扫描总线上的设备
>>>__scsi_scan_target
scsi_get_host_dev
获取一个host(HBA)设备
scsi_free_host_dev
释放一个host(HBA)设备
scsi/scsi_lib.c
scsi子系统对外提供的命令接口, 可以供给sg/sd等设备使用, 主要有如下函数:
scsi_request_fn:
异步执行scsi request, 被__blk_run_queue_uncond使用, sg.c/sd.c/sr.c等scsi设备都是间接使用这个接口.
scsi_execute:
同步执行scsi命令
Scsi/hosts.c
是实现scsi host设备类的管理集。
scsi_register/scsi_unregister
注册(申请)/去除适配器类(HBA)
scsi_add_host/scsi_remove_host
增加/移除scsi适配器类(HBA)
较低层(LLD)/HBA驱动:
实现了scsi命令数据传输的接口,是scsi的链路层实现。主要包含:每种设备类对应一个transport,这些transport作为设备类的公共函数库,协助host设备驱动实现数据传输, 注册许多相关的设备类
transport_class_register:
注册了设备类,管理host设备,
scsi_transport_fc.c fc传输,
scsi_transport_iscsi.c iscsi传输
scsi_transport_sas.c sas传输
scsi_transport_spi.c spi传输
scsi_transport_srp.c srp传输
HBA驱动:
sas host之(LSI HBA)驱动: drivers/scsi/mpt2sas/
Virtio scsi host驱动: drivers/ scsi/virtio_scsi.c
阅读(4008) | 评论(0) | 转发(0) |