SCSI Upper Layer 与LLD的联系——sd_probe

2023-05-16

SCSI UL和LLD的关系是driver和device的关系。内核中定义了device_driver和device结构,分别来抽象设备驱动和设备。这两个结构相当于所有设备驱动和设备的超类。UL代表的scsi_driver和LLD所代表的scsi_device分别是它们子类。 struct device_driver {

const char * name;

struct bus_type * bus;

……

int (*probe) (struct device * dev);

int (*remove) (struct device * dev);

void (*shutdown) (struct device * dev);

int (*suspend) (struct device * dev, pm_message_t state);

int (*resume) (struct device * dev);

};

struct device {

……

struct device *parent;

……

device_type *type;

struct bus_type * bus; /* type of bus device is on */

struct device_driver driver; / which driver has allocated this device */

void *driver_data;

……

};

由这两个结构可以看出,二者的关系是device:device_driver=n:1。UL和LLD间的联系,实际上是二者的联系,而二者的联系是在初始化时确定。UL初始化时准备device_driver结构,其中包括probe方法。而LLD(准确地说,应该是middle layer)准备device结构。二者都把其bus初始化为scsi_bus_type,并挂入该总线。之后,如果是UL初始化,则调用自身的probe方法,去探测bus上的所有device,从而把device_driver绑定倒device。而如果是LLD初始化,则调用bus上所有的device_driver的probe方法来探测自身的device。因此,无论是UL先初始化还是LLD先初始化,二者都能取得联系。

下面看一下sd(UL)和scsi host driver(LLD)如何绑定的。

首先,sd中定义了一个scsi_driver结构,即device_driver的派生类:

static struct scsi_driver sd_template = {

.owner = THIS_MODULE,

.gendrv = {

.name = “sd”,

.probe = sd_probe,

 .remove = sd_remove,

 .suspend = sd_suspend,

 .resume = sd_resume,

 .shutdown = sd_shutdown,

},

.rescan = sd_rescan,

.done = sd_done,

};

初始化时,调用scsi_register_driver注册该scsi_driver. scsi_register_driver:

drv->bus = &scsi_bus_type;

scsi_register_driver首先把driver的bus初始化为scsi_bus_type。接着调用driver_register来注册driver。

scsi_register_driver->driver_register->bus_add_driver->driver_attach:

return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

在driver_attach中,对bus上的每个device调用__driver_attach方法。在该方法中会调用driver的probe方法(这里即是sd_probe)去探测每个device(此时,如果scsi host driver初始化,则bus上有相应的device,则sd_probe则为其生成相应gend)。

__driver_attach->driver_probe_device->really_probe:

ret = drv->probe(dev);

另一方面,scsi host driver在初始化时,会调用scsi_scan_host来扫描host。扫描整个host以为着扫描host所对应的channel,target和lun。因此,它分别调用scsi_scan_channel,__scsi_scan_target,scsi_probe_and_add_lun来每个target及其lun。其中,在scsi_probe_and_add_lun中会分配代表每个lun即scsi设备的scsi_device结构:

scsi_scan_host->do_scsi_scan_host->scsi_scan_host_selected->scsi_scan_channel->__scsi_scan_target->scsi_probe_and_add_lun:

sdev = scsi_alloc_sdev(starget, lun, hostdata);

其中,在scsi_device结构中,已经包含了超类device结构:

struct scsi_device {

struct Scsi_Host *host;

struct request_queue *request_queue;

 ……

int timeout;

struct device sdev_gendev;

struct class_device sdev_classdev;

……

};

scsi_scan_host->do_scsi_scan_host->scsi_scan_host_selected->scsi_scan_channel->__scsi_scan_target->scsi_probe_and_add_lun->scsi_probe_lun

分配好scsi_device结构以后,调用scsi_probe_lun来发送INQUIRY命令,探测制定的lun。scsi设备返回的inquiry data将保存在result参数中,以备scsi_add_lun使用。其中包括了设备的信息,包括设备的种类type等。

scsi_scan_host->do_scsi_scan_host->scsi_scan_host_selected->scsi_scan_channel->__scsi_scan_target->scsi_probe_and_add_lun->scsi_add_lun

如果scsi_probe_lun成功,则调用scsi_add_lun来添加lun。在scsi_add_lun中,先根据inquiry data来初始化scsi_device中的一些属性,包括其type属性(在这儿为TYPE_DISK)。

scsi_scan_host->do_scsi_scan_host->scsi_scan_host_selected->scsi_scan_channel->__scsi_scan_target->scsi_probe_and_add_lun->scsi_add_lun->scsi_sysfs_add_sdev

之后调用scsi_sysfs_add_sdev来添加scsi_device。这儿与device_driver的注册类似,调用device_attach来对扫描bus上所有的driver,调用这些driver的probe方法来探测自身的device。如果此时,sd没有初始话,即bus上没有相应的驱动,则不会调用probe方法。即不会生成lun对应的gend。并且,sd_probe中,会检测scsi_device的具体类型,只有自己支持的才回去探测。我想这个应该是各种scsi UL driver必须检测的:

if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC) goto out;

通过上述两个过程,device_driver和device联系在了一起。总之,对于每个lun的加入,sd_probe都会执行一次。只不过sd_probe的触发,要么是通过sd驱动scsi_register_driver,要么是通过LLD scsi_scan_host。

sd_probe调用栈(由scsi_scan_host触发):

#0 sd_probe (dev=0xc714a4b0) at drivers/scsi/sd.c:1597

#1 0xc018df10 in driver_probe_device (drv=0xc0335df8, dev=0xc714a4b0) at drivers/base/dd.c:121

#2 0xc018dfd8 in __device_attach (drv=0xc714a4b0, data=0x0) at drivers/base/dd.c:207

#3 0xc018d110 in bus_for_each_drv (bus=, start=, data=0x0, fn=0xc018dfc8 <__device_attach>) at drivers/base/bus.c:349

#4 0xc018e078 in device_attach (dev=0x1) at drivers/base/dd.c:238

#5 0xc018d070 in bus_attach_device (dev=0xc714a4b0) at drivers/base/bus.c:492

#6 0xc018be64 in device_add (dev=0xc714a4b0) at drivers/base/core.c:781

#7 0xc019fc84 in scsi_sysfs_add_sdev (sdev=0xc714a400) at drivers/scsi/scsi_sysfs.c:783

#8 0xc019d9b8 in scsi_probe_and_add_lun (starget=0xc76d9000, lun=, bflagsp=, sdevp=0x0, rescan=0, hostdata=0x0) at drivers/scsi/scsi_scan.c:914

#9 0xc019e088 in __scsi_scan_target (parent=0xc715e8d8, channel=0, id=0, lun=4294967295, rescan=0) at drivers/scsi/scsi_scan.c:1550

#10 0xc019e538 in scsi_scan_channel (shost=0xc715e800, channel=0, id=0, lun=4294967295, rescan=0) at drivers/scsi/scsi_scan.c:1626

#11 0xc019e608 in scsi_scan_host_selected (shost=0xc714a4b0, channel=1, id=1, lun=3222995532, rescan=0) at drivers/scsi/scsi_scan.c:1654

#12 0xc019e6e8 in do_scsi_scan_host (shost=0xc715e800) —Type to continue, or q to quit— at drivers/scsi/scsi_scan.c:1786

#13 0xc019eb50 in scsi_scan_host (shost=0xc715e800) at drivers/scsi/scsi_scan.c:1813

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SCSI Upper Layer 与LLD的联系——sd_probe 的相关文章

  • SCSI任务优先级

    在SCSI命令参考手册中给出了三个优先级控制位 xff1a HEADSUP xff0c ORDWUP SIMPSUP xff0c 分别对应的优先级是HEAD OF QUEUE ORDERED SIMPLE HEAD OF QUEUE优先级的
  • !!!Chapter 2 The Physical Layer

    2 1 The Theoretical Basis for Data Communication Fourier Analysis Any reasonably behaved periodic function g t with peri
  • 今天终于知道了如果用layero获取layer弹窗中的子元素了

    通过layer弹出的ifram 想要获取里面的元素并且绑定相应的事件 以前一直不知道layero是什么意思 可以通过下面的代码自己体会一下 layer open type 2 title 文件管理 shadeClose true shade
  • Photoshop 通道讲解

    我常常问我的学生 什么是Photoshop最重要 不可或缺的功能 很多人的回答是图层 Layer 其实在Photoshop3 0之前根本没有图层的功能 在Photoshop的领域中 最重要的功能是选取范围 正确的运用选取范围 才能够做出精准
  • 通过iptables 封QQ 各种bt软件的方法

    1楼 发表于 2008 7 1 17 49 最近老大要求封qq 而且是封部分人使用 本来打算封腾讯登陆服务器的 但是无法封bt工具 找了一下资料 以下部分为转载 流程 打上layer 7补丁 升级内核至2 6 19 7 升级iptables
  • Unity--Physics.OverlapSphere的参数LayerMask和GameObject的layer

    Layer介绍 Unity中是用int32来表示32个Layer层 int32表示二进制一共有32位 0 31 在Unity中每个GameObject都有Layer属性 默认的Layer都是Default 在Unity中可编辑的Layer共
  • 手把手教你使用USB的CDC+MSC复合设备(基于stm32f407)- 2

    接上文 手把手教你使用USB的CDC MSC复合设备 基于stm32f407 此文主要是记录一下usb枚举时抓取的一些数据以及usb msc涉及的部分scsi协议 USB MSC协议 主要包括usb协议 msc类协议 scsi协议 SDIO
  • 多个DLL之间的Static变量以及模板实例化

    结论如下 1 DLL之间调用类public静态成员变量 不能使用A m static形式调用 其中A为类名 m static为A中的static成员变量 若使用 编译出现链接错误 必须使用函数调用方式 为m static增加set get函
  • 简短的 mouseover 显示与隐藏层的办法

    简短的 mouseover 显示与隐藏层的办法 在制作 mouseover 和 mouseout 显示 隐藏层的时候 有时总会出现 mouseover 层里面的对象时 层消失的情况 这是因为mouseover 层内 对象时 会对前层产生两个
  • Silverlight 4 和 Windows Phone 7 的 Bing 地图控件中的交互式图层

    使用 Bing 地图控件时 我的应用程序会添加一个叠加层 在其上将位置标记绘制为椭圆形 每个椭圆都连接到一个 Tap 处理程序 该处理程序在 WP7 模拟器中按预期工作 遗憾的是 HTC 硬件上的情况似乎并非如此 地图本身似乎获取了所有输入
  • 在张量之间进行运算时出现“InvalidArgumentError:不兼容的形状:[64,40000] vs. [64] [Op:Mul]”?

    我正在尝试在两个张量之间执行此操作 green mat sio loadmat green mat green np array green mat G2 green tf convert to tensor green green tf
  • 截取 UIView 的屏幕截图,其中子视图是相机会话

    我正在构建一个应用程序 我需要对其子视图是相机会话 AVFoundation 会话 的视图进行屏幕截图 我试过这段代码 CGRect rect self containerView bounds UIGraphicsBeginImageCo
  • Grails——服务层的使用

    当我想要更新非简单域对象时 我在组织代码时遇到问题 问题在于分离控制器和服务层的职责 更明确地说 假设我们有一个域类 Client 它依赖于其他域类 如 Address 等 在视图中 有一个 gsp 用于编辑一些客户端属性 包括一些嵌套属性
  • Keras/Tensorflow:有效获取所有层的预测或输出

    我能够按照建议获得所有层的输出 预测Keras 文档 如何获得中间层的输出 https keras io getting started faq how can i obtain the output of an intermediate
  • SetPixel 太慢了。有没有更快的方法来绘制位图?

    我正在开发一个小型绘画程序 我在位图上使用 SetPixel 来绘制线条 当画笔尺寸变大 例如 25 像素 时 性能会明显下降 我想知道是否有更快的方法来绘制位图 以下是该项目的一些背景 我使用位图 这样我就可以利用图层 就像在 Photo
  • 创建可训练权重的 Keras 层

    edit请参阅底部以了解我如何解决此问题 我写了自己的Keras层 其构建方法如下 class Multed Weights Layer def init self input dim output dim kwargs self outp
  • 在 d3.js 中显示/隐藏图层

    首先 我是 d3 js 的新手 我有一张地图 上面显示了一些点 现在我想添加按钮来显示 隐藏点 到目前为止我所拥有的 function checkAll d3 selectAll g attr visibility visible func
  • 如何快速知道Gimp中的图层尺寸?

    每次我想知道 Gimp 中的图层尺寸时 我都会打开 缩放图层 对话框来获取它 有没有更好的方法可以一目了然 可能是一些配置选项将其显示在图层名称的底部 右侧 或底部栏中 也许这可能是 Gimp 功能请求 谢谢你 GIMP 确实有方法配置状态
  • CSS 边距为负而不移动父容器

    我正在尝试进入此页面 http musicaladvocacy org http musicaladvocacy org 显示 Home 灰色渐变中的白色容器 的区域向上移动约 60 px 但正如您所看到的 它同时将父容器向上移动 我只是想
  • 在keras自定义损失中使用层输出

    我正在 Keras 中开发自定义损失函数 我需要第一层输出 我怎样才能取回它 def custom loss y true y pred cross K mean K binary crossentropy y true y pred ax

随机推荐