PM8001驱动及相关模块分析——综述及初始化
来源:互联网 发布:易推客营销软件下载 编辑:程序博客网 时间:2024/05/29 12:11
前言
PM8001驱动是linux标准内核自带的HBA驱动,由于完全开源,所以对于学习linux存储系统底层很有帮助。笔者有幸在之前的工作中使用过这款HBA,所以结合实际使用和源码稍微记录一下。由于已经过去很久了,现在重新拿起来看,有些地方理解的会有疏忽,敬请谅解和多提宝贵意见。
对于PM8001这个设备,其与主机通过PCI总线连接,属于SCSI子系统中的底层模块。SCSI子系统按功能和逻辑结构可以划分成三层。系统结构如图所示。
本文的主线是根据PM8001驱动(较低层)来展开,其间会涉及到中间层相关部分的分析,但对于顶层涉及得不多。
scsi子系统中间层和较低层简要分析
scsi中间层功能简介
在进行对pm8001驱动分析之前,先简要根据我的理解分析一下scsi子系统中的中间层和较低层。
中间层顾名思义是介于scsi子系统顶层和较低层之间的层次。中间层是scsi子系统分层模型核心意义的体现——它能够解除顶层和较低层之间的耦合,并为顶层和较低层提供一系列服务。中间层能够解除顶层与较低层的耦合关键在于中间层提供了LLD的抽象接口scsi_host和能够复刻scsi_host对象的scsi_host_template。当较低层将scsi_host注册到中间层后,中间层即可以调用lld相关函数。同理,顶层的驱动也可以通过中间层间接地使用lld的函数。所以在lldd(pm8001驱动)初始化时,先实例化一个scsi_host_template对象,将本身的一些函数实现挂载到这个对象中,然后在后续的pci设备的probe函数中将这个对象以及对应的scsi_host注册到中间层。
中间层出了解耦合功能以外,也起到了转换器的作用,即中间层会把从顶层传入的请求操作转换成scsi命令。在我们的体系中,中间层将请求转换成scsi命令后发向lldd,lldd会将命令通过IBQ发往pm8001,pm8001将scsi命令转换成sas命令发向指定地址的phy。
另外中间层也提供一系列很重要的函数,比如scsi总线扫描算法,错误处理等。
与libsas的关系
根据我的理解,libsas和pm8001(可能还会有其他辅助函数库)共同构成了给予pm8001板卡的scsi子系统中较低层的实现。Libsas和pm8001分别承担不同的责任,pm8001直接与硬件设备进行交互,更多地关注较为底层的基础构建部分;libsas部分则包含了大量的逻辑性代码,负责对数据(上行/下行)进行封装处理或对事件进行响应。
Pm8001提供了一系列与物理设备相关的函数(sas_domain_function_template结构体中,以lldd开头),在初始化时会被注册到libsas中,libsas中的部分逻辑最终通过调用这些函数来实现实际底层的操作。
当pm8001驱动注册到scsi子系统时,注册过程在pm8001中完成,但注册的函数在libsas中实现。Pm8001中的中断响应函数,在进行底层初步处理(与pm8001硬件特性有关,具体参见pm8001编程手册)后,会把事件递交给libsas层对应函数进行进一步处理。
pm8001初始化过程分析
pm8001的初始化入口在pm8001_init.c中。
初始化scsi_transport_template结构。scsi_transport_template结构体内包含了一系列scsi命令传输所需要用到的参数以及相关函数,这些函数由libsas层提供。在初始化scsi_transport_template的过程中,会有一个sas_internal中间结构,这个结构中包含有一系列libsas层在运行中所需要用到的函数模板、参数等信息,其内部有一个字段对应scsi_transport_template结构,可以通过两者之一获取对方从而调用其包含的函数。
初始化pm8001的PCI相关部分。
在初始化PCI相关部分的时候,我们可以注意到其中的probe函数会在主机查询到了PCI设备(这里指PM8001)时进行调用,其主要功能在于对pm8001设备进行真正意义上的初始化。
PCI相关配置操作。
创建一个scsi_host实例。前面有提到过scsi_host是lldd被中间层调用的接口,它是pm8001驱动链入到整个scsi子系统的关键结构体之一。在这里通过调用scsi_host_alloc函数对其进行初始化,这个函数中会对其进行参数配置,但主要的实例化过程是通过将scsi_host中的一些字段用scsi_host_template结构中的字段赋值。此外,在初始化的过程中也会在虚拟文件系统中做相应的注册。
初始化pm8001_chip_info。pm8001_chip_info结构代表着scsi_host_chip,在这个结构体中有一个pm8001_dispatch结构,其中包含了一系列底层逻辑过程。这些底层逻辑过程大多数都跟设备行为有关,详细信息可以参考编程手册。这些底层逻辑过程实际上是根据约定对事件或数据进行分发,而真正意义上的对硬件的操作是集中在pm8001_hwi.c中一系列以mpi为开头的函数;对逻辑的处理最终通过转发给libsas层相关函数进行处理。
初始化sas_ha_struct。sas_ha_struct结构体是lld在libsas层的抽象,libsas层可以通过该结构体完成逻辑。
初始化pm8001_hba_info结构。pm8001_hba_info结构体是对pm8001的抽象,这个结构体在后续逻辑中会被经常使用。其中包含了一系列已经绑定的处理函数和相关参数,是程序运行的核心。
软复位
软复位的一系列操作可以参见pm8001编程手册,值得一提的是这里有普通和had两种模式,区别在于载入spc 8x6G固件镜像的方式不同。初始化chip
Chip的初始化主要是针对一些硬件设备级的配置信息,这些主要是通过配置MPI配置表来完成,MPI配置表具体信息参见编程手册第五章。在PM8001的驱动中并不会(也不需要)对所有参数进行配置。
中断注册
初始化sas地址
注册hba设备。这个操作是由libsas层的函数提供的处理方法完成处理,最终会启动一条工作处理线程。
执行扫描scsi总线。这个操作由scsi子系统中间层提供,用于扫描scsi总线,获取节点。在扫描到节点会执行添加lun操作。执行scsi扫描操作的前后都可以注册start/finish函数,这些函数是在pm8001中实现,包含了一些底层的初始化过程。
- PM8001驱动及相关模块分析——综述及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化
- lwip源码分析1------综述及设备驱动层
- lwip源码分析1------综述及设备驱动层
- IMS及相关概念综述
- IMS及相关概念综述
- IMS及相关概念综述
- 我的存储第一战:PM8001驱动分析(一)
- suricata 3.1 源码分析18 (模块注册及初始化)
- web相关方法及初始化
- 综述及分析:无线传感器网络的分析及启示
- HttpClient4.0杂谈
- maven 构建可执行 jar ,并引入所需所有依赖 jar
- LeetCode: Combinations
- 11.4 地图大头针 重用标示符
- BigPipe笔记
- PM8001驱动及相关模块分析——综述及初始化
- jquery随机新闻滚动切换效果
- 日语学习之新版初级标准日本语-19 部屋の かぎを 忘れないで ください
- 从两端生长的双向栈-C语言版
- poj_2533_Longest Ordered Su... poj_1260_Pearls hdu_1025_Constructing Roa... poj_2533_Longest Ordered
- POJ 2406 Power Strings(kmp)
- C++使用MD5
- 数字分隔(二)
- 2009年9月全国计算机等级考试四级笔试试卷网络工程师