Chinaunix首页 | 论坛 | 博客
  • 博客访问: 261133
  • 博文数量: 60
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 820
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-18 00:28
文章分类

全部博文(60)

文章存档

2010年(60)

我的朋友

分类:

2010-04-13 14:03:31

前一段时间在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;
ü         scsi_host为scsi middle level分配的scsi host对象指针。
ü         devices为vscsi_host控制器管理的设备,其中MAX_CHANNEL为vscsi_host最大的通道数,CHANNEL_DEV_NUM为vscsi_host最大的lun数。
ü         dev_cnt描述了当前vscsi_host管理的设备数量。
ü         host_lock为设备访问锁。
ü         Vscsi_cmd_queue为vscsi_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的每个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中存在两种数据传输方式:
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原理............
阅读(1639) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~