文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Scsi host driver编写总结 z

Scsi host driver编写总结 z

时间:2009-03-08  来源:soararing

zz:

http://hi.baidu.com/taylergreen/blog/item/1bff611149ec5278cb80c471.html

 

 

 

前一段时间在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适配器写了一个驱动,那么内核驱动的体系结构如下图所示:

SCSI device driver是SCSI设备驱动,也可以称之为功能驱动(Function driver)。SCSI middle level driver为SCSI中间层驱动,抽象了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_tablesize:scatter-gather表的长度。

      

Scsi host的初始化:

       在scsi host driver中首先需要定义一个描述host的结构。这个结构实际上是Scsi_Host的派生类,继承和扩展了Scsi_Host的功能。vscsi_host_s是virtual 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;

<!--[if !supportLists]-->ü         <!--[endif]-->scsi_host为scsi middle level分配的scsi host对象指针。

<!--[if !supportLists]-->ü         <!--[endif]-->devices为vscsi_host控制器管理的设备,其中MAX_CHANNEL为vscsi_host最大的通道数,CHANNEL_DEV_NUM为vscsi_host最大的lun数。

<!--[if !supportLists]-->ü         <!--[endif]-->dev_cnt描述了当前vscsi_host管理的设备数量。

<!--[if !supportLists]-->ü         <!--[endif]-->host_lock为设备访问锁。

<!--[if !supportLists]-->ü         <!--[endif]-->Vscsi_cmd_queue为vscsi_host的命令队列。scsi middle level可以直接将scsi命令挂在该命令队列上。

Scsi host的初始化过程如下:

<!--[if !supportLists]-->1、 <!--[endif]-->理所当然,第一步需要初始化scsi host结构中的所有成员,例如vscsi_cmd_queue等。

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

<!--[if !supportLists]-->3、 <!--[endif]-->通过scsi_add_host函数将新分配的scsi host添加到系统中。调用如下:scsi_add_host(shost, NULL)。

<!--[if !supportLists]-->4、 <!--[endif]-->调用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的每个channel、lun,然后回自动probe每个scsi device。在virtual scsi host driver中,用户可以手动的将一个设备添加到scsi host中,并且为其分配channle,id,lun。

       添加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_host为vscsi host的对象,将该scsi host对象告诉新创建的scsi device。

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

Scsi数据传输方式:

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

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

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

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

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

 

Virtual scsi host原理............

相关阅读 更多 +
排行榜 更多 +
几何飞行内购修改版

几何飞行内购修改版

飞行射击 下载
别踩白块内购修改版

别踩白块内购修改版

休闲益智 下载
乐涂数字填色游戏

乐涂数字填色游戏

休闲益智 下载