原创 Scsi host driver编写总结

2008-6-30 18:46 8505 8 12 分类: 软件与OS
    前一段时间在Linux平台上做了一个virtual SCSI host driver,该virtual scsi host driver主要实现将scsi command转换成块设备的请求,即将块设备伪装成一个标准scsi设备。在此对scsi host driver的编写做一下总结。


Scsi host driver的位置:



Scsi host driver位于SCSI中间层之下,属于SCSI总线控制器的驱动。如果有人做了一个SCSI适配器(host bus adapter),那么需要为该适配器写一个驱动,这个驱动就是scsi host driver。如果SCSI适配器是一个真实的硬件设备,绝大多数情况是采用PCI接口,那么scsi host driver也是一个PCI设备驱动。假设给一个真实的SCSI适配器写了一个驱动,那么内核驱动的体系结构如下图所示:
f303022b-aa56-4016-b14e-6e37ba97204f.JPG


SCSI device
driver
SCSI设备驱动,也可以称之为功能驱动(Function driver)。SCSI middle level driverSCSI中间层驱动,抽象了SCSI的总线逻辑。Scsi
host driver
控制SCSI总线控制器,实现SCSI数据的物理层传输。



 



Scsi host模版:



Scsi host driver需要与scsi middle level进行数据交互,在scsi middle level定了标准的scsi host模版,所有接口函数和属性参数都定义在标准模版中。模版的类型为struct
scsi_host_template



 



Virtual scsi
host driver
的模版定义如下:



struct
scsi_host_template scsi_host_template = {



       .module                 =
THIS_MODULE,



       .name                    =
SCSI_HOST_IDENT,



       .info                      = scsi_info,



       .slave_configure     = scsi_slave_configure,



       .queuecommand     = scsi_queuecommand, 



       .can_queue            = SCSI_HOST_CAN_QUEUE,     /*
host cmd queue depth */



       .cmd_per_lun         = SCSI_CMD_PER_LUN,     /*
lun cmd queue depth */



       .sg_tablesize          = SG_ALL,



       .use_clustering       = SCSI_CLUSTERING,



       .this_id                  = SCSI_HOST_ID,



       .emulated              = 1,



};



 



       .queuecommand:通过该接口函数,scsi middle level将请求提交给scsi host driver。所以该函数是上下层之间的数据通道。



       .can_queue:描述了scsi host命令队列的长度。通常scsi host具有一个命令队列,scsi middle level通过queuecommand接口将命令直接挂入host的命令队列中,然后一步返回。



       .cmd_per_lun:该参数描述了每个lun通路所能缓存命令的数量。



       .sg_tablesizescatter-gather表的长度。



      



Scsi host的初始化:



       scsi host driver中首先需要定义一个描述host的结构。这个结构实际上是Scsi_Host的派生类,继承和扩展了Scsi_Host的功能。vscsi_host_svirtual scsi host driver中定义的结构。



 



typedef struct vscsi_host_s {



       __u32                   host_no;         /*
host number, Major no */



       struct
Scsi_Host     *scsi_host;     /* scsi host object */



      



       /*
vscsi device array */



       struct
vscsi_device_s    devices[MAX_CHANNEL][CHANNEL_DEV_NUM];



       atomic_t         dev_cnt;                /* vscsi device
counters */



       struct
semaphore    host_lock;      /* vscsi device access lock */



      



       /*
vscsi command queue */



       struct
bscsi_cmd_arr_s        vscsi_cmd_queue;



}vscsi_host_t;



 



ü        
scsi_hostscsi middle level分配的scsi host对象指针。



ü        
devicesvscsi_host控制器管理的设备,其中MAX_CHANNELvscsi_host最大的通道数,CHANNEL_DEV_NUMvscsi_host最大的lun数。



ü        
dev_cnt描述了当前vscsi_host管理的设备数量。



ü        
host_lock为设备访问锁。



ü        
Vscsi_cmd_queuevscsi_host的命令队列。scsi middle level可以直接将scsi命令挂在该命令队列上。



 



Scsi host的初始化过程如下:



1、 
理所当然,第一步需要初始化scsi host结构中的所有成员,例如vscsi_cmd_queue等。



2、 
通过scsi_host_alloc函数让内核分配一个scsi host,调用方式为:shost = scsi_host_alloc(&scsi_host_template, sizeof(struct
bscsi_host_s))
。其中scsi_host_template为模版对象,即scsi host的属性以及接口方法。



3、 
通过scsi_add_host函数将新分配的scsi host添加到系统中。调用如下:scsi_add_host(shost, NULL)



4、 
调用scsi_scan_host(shost)扫描scsi host



 



Scsi device的初始化:



       scsi host驱动中,Scsi host控制的每个scsi设备都有一个对象。Virtual scsi driver中采用struct vscsi_device_s结构来描述。



      



       scsi host scan的过程中,驱动程序会扫描scsi host的每个channellun,然后回自动probe每个scsi device。在virtual scsi host driver中,用户可以手动的将一个设备添加到scsi host中,并且为其分配channleidlun



 



       添加scsi device的接口函数为__scsi_add_device,实现如下:



sdev = __scsi_add_device(vscsi_host->scsi_host,
channel, id, lun, &vscsi_host);



bscsi_host->scsi_host为已经存在的scsi host对象。



channel, id, lun为新添加的scsi device标识。



vscsi_hostvscsi host的对象,将该scsi host对象告诉新创建的scsi device



 



通过__scsi_add_device函数,能够在scsi middle level创建一个scsi device,并且建立起scsi devicescsi host之间的关系。



 



Scsi数据传输方式:



       scsi
middle level
通过queuecommand函数将请求提交给scsi hostScsi middle level将获取的上层请求封装成scsi command,然后将scsi command递交给scsi host,也就是说scsi host层只能处理scsi command



 



       scsi command中存在两种数据传输方式:



1、 
buffer的方式(Block-PC),这应该是SCSI驱动中较早的一种方式,其将数据存储在一个buffer中提交给scsi host



2、 
scatter-gather方式。这种方式为聚散DMA方式,对于磁盘的读写基本都采用这种方式,scsi middle
level
可以很方便的将scsi
disk driver
提交的bio转换成scatter-gather table,而无须任何的数据拷贝。



 



为了达到软件兼容的目的,所以在处理scsi数据传输时,需要注意这两种传输方式。


Virtual scsi host原理:



点击看大图

文章评论4条评论)

登录后参与讨论

用户411565 2009-4-2 17:50

呵呵,我这个不开源。我建议你可以看一下内核中的scsi_debug.c和libata_scsi.c文件,或许对你有很大的帮助。

用户193005 2009-4-2 16:13

我看sd.c中要探测设备就有好几个命令. 哦..明白.我先做试试.有问题再向你请教. PS: 你这个开源吗?

用户411565 2009-4-2 15:42

我这个scsi host只关心几个重要的scsi命令(例如读写等),对其进行解析处理一下,不是很复杂。另外,一些scsi命令需要进行模拟处理。最后从scsi命令中提取数据,进行读写转发。

用户193005 2009-4-2 15:02

你好,我最近也打算实现这样一个东西. 以熟悉scsi层. 向你请教下,你最后面是怎么样实现scsi命令的的? 是转成ata命令.还是自己存软件方式解析scsi命令(这样的话,应该很麻烦.命令格式很复杂的).
相关推荐阅读
用户411565 2012-12-18 12:58
我的存储之道博客
大家好,最近一直在做存储方面的工作,所以我在51CTO上专门开辟了一个空间讨论存储相关的问题,喜欢存储的朋友可以可以访问我的存储博客: 存储之道 (http://alanwu.blog.51cto...
用户411565 2012-04-06 21:39
SAS Cable可以有多长?
SAS接口是高端硬盘的主流接口,是存储系统的理想选择。我们知道高速信号的传输距离和传输线相关的,那么SAS作为外部通信接口,其Cable线具体可以有多长呢? 我在网上找到上图所示的眼图测...
用户411565 2012-04-06 21:38
对TRIM SCSI命令的一些分析
前一段时间做了一些对SSD方面进行优化的工作,SSD最大的问题在于长时间使用之后,IO性能会急剧下降。其主要问题在于为了防止“写放大”问题的产生,SSD的firmware采用了类似于log方式的算...
用户411565 2012-04-06 21:35
惊叹!我们的跨洋网络
  每次地质自然灾害的时候,总会伴随着网络的问题,这是由于我们的越洋光纤网络出了故障,受到自然力的破坏而导致断裂。越洋光纤,听起来的确是件非常不可思议的事情,工程量非常的巨大,但正是如此伟大的...
用户411565 2012-04-06 21:33
科学仪器网络模型
科学仪器概述     科学仪器发展趋势 科学是从测量开始的,科学仪器是信息技术的源头,是信息产业的重要组成部分,是现代科学与工业的基石。科学仪器产业的发展关系到国家科学研究实力、生...
用户411565 2012-04-06 21:16
谈谈RAID产品与技术
说起RAID,学计算机的同学马上会说RAID技术简单啊,就是将数据条带化,然后计算一些冗余数据,一并写入磁盘。通过RAID技术一方面提高系统的IO性能;另一方面提高系统的可靠性。单纯从RAID的原...
我要评论
4
8
关闭 站长推荐上一条 /2 下一条