scsi总线驱动的初始化

本文详细介绍了Linux系统中SCSI驱动的初始化过程,包括SCSI驱动的三层模型:top level、middle level和lower level。在初始化过程中,系统会扫描PCI总线,加载scsi host驱动,初始化scsi控制器,并通过scsi_host_alloc和scsi_scan_host函数进行设备枚举。每个SCSI设备由scsi_device结构描述,通过host_id、channel_id、target_id和lun_id进行寻址。scsi_probe_and_add_lun函数用于识别和添加LUN。SCSI总线驱动的核心是scsi_host_template,定义了操作接口方法,底层驱动通过queuecommand函数处理SCSI命令。
摘要由CSDN通过智能技术生成
 

1.6.1 scsi总线驱动的初始化

块设备底层驱动的核心是scsi总线层驱动,在总线层驱动之上为各种不同的scsi设备驱动,在总线层驱动之下为scsi host驱动。其在内核中的位置如下图所示:

 

前面我们已经知道了上三层的工作,接下来大部分知识来自底下三层。

 

在Linux中scsi驱动基本分为三大层:top level,middle level以及lower level。top level为具体的scsi设备驱动,例如我们常用的磁盘设备驱动就在该层(Linux中的实现为sd.c),scsi disk的驱动向上表现为块设备,因此,具有块设备的接口及一切属性,向下表现scsi设备,因为scsi disk基于scsi总线进行数据通信。top level驱动与具体的scsi设备相关,所以该类驱动往往由设备开发者提供,但是如果scsi设备为标准类设备,那么驱动可以通用。

 

middle level实际上就是scsi总线层驱动,按照scsi协议进行设备枚举、数据传输、出错处理。middle level层的驱动与scsi specification相关,在一类操作系统平台上只需实现一次,所以该类驱动往往由操作系统开发者提供。

 

lower level为scsi控制器的驱动,该驱动与具体的硬件适配器相关,其需要与scsi middle level层进行接口,所以往往由提供适配器的硬件厂商完成驱动开发,只有硬件厂商才对自己定义的register file(寄存器堆)最清楚。当然,在lower level层可以做虚拟的scsi host,所以该层的驱动也不一定对硬件进行操作。

 

Linux中,scsi三层驱动模型如下图所示:

 

 

而前面提到的scsi device的数据结构就是在scsi middle level定义的,用于描述一个scsi的具体功能单元,其在scsi host中通过channel、id、lun进行寻址。

 

首先,什么是channel、id和lun。通常SCSI总线适配器作为PCI设备的形式存在,其在计算机体系结构中的位置如下图所示:

 

 

在系统初始化时会扫描系统PCI总线,由于scsi端口适配器挂接在pci总线上,因此会被pci扫描软件扫描得到,并且生成一个pci device(PDO)。然后扫描软件需要为该pci device加载相应的驱动程序。

 

在linux系统中,系统初始化时会遍历pci bus上存在的所有驱动程序,检查是否有符合要求的驱动程序存在,这里假设scsi host是USB或marwell中的设备,那么,如果存在USB或marwell提供的scsi端口驱动,就会被成功调用。加载scsi端口驱动时,pci扫描程序会调用对应scsi端口驱动提供的probe函数,该probe函数是scsi端口驱动程序在初始化驱动时注册到pci-driver上的(Linux的总线驱动都是采用的这种思路)。

 

在scsi host具体的probe函数中会初始化scsi host,注册中断处理函数,并且调用scsi_host_alloc函数生成一个scsi host,然后添加到scsi middle level,最后调用scsi_scan_host函数扫描scsi端口适配器所管理的所有scsi总线。

 

一个scsi端口适配器可能拥有多个channel,每个channel拥有一条scsi总线。传统scsi总线是并行共享总线,现有的SATA、SAS等P2P接口在逻辑上可以理解成总线的一种特例,所以scsi middle level驱动程序是通用的。由于一个scsi host可能存在多个channel,因此依次扫描每个channel。按照spec,传统scsi bus上最多可以连接16个scsi target,因此,scsi扫描程序会依次探测target。一个scsi target可以存在多种功能,每种功能称之为LUN,对于单功能设备(例如磁盘),其LUN通常为0。

 

Scsi host的扫描过程在系统初始化中进行,详细的代码我们就不去分析了,这里从网上摘录了一段伪代码对其进行简单地描述:

 

For (channel = 0; channel

  /* 对一个适配器的每个通道中的设备进行识别 */

  …

  For (id=0; id

  /* 对一个通道中的每个ID对应设备进行识别 */

  …

    For (lun=1; lun

    /* 对一个ID对应设备的每个LUN进行识别 */

    …

    }

  }

}

          

在计算机系统启动过程中,操作系统会扫描默认的PCI根节点,从而触发了PCI设备扫描的过程,开始构建PCI设备树。

 

首先scsi host作为PCI设备会被PCI总线驱动层扫描到(PCI设备的扫描采用配置信息读取的方式),扫描到scsi host之后,操作系统开始加载scsi host的驱动,scsi host driver就是上面说所的low level driver。scsi host driver初始化scsi控制器,通过PCI配置空间的信息分配硬件资源,注册中断服务。最后开始扫描通过scsi控制器扩展出来的下一级总线—— scsi bus。

 

scsi bus的扫描通过scsi middle level提供的服务完成。scsi host driver可以调用scsi middle level提供的扫描算法完成scsi总线设备的扫描,扫描过程可以描述如下:

a.   采用scsi_add_host()函数为扫描出来的scsi host添加一个对象,注册到scsi middle level。

b.  通过__scsi_add_device()函数循环扫描scsi host,扫描过程采用了scsi middle level的服务scsi_probe_and_add_lun(

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值