scsi设备驱动体系架构
1.6.2 scsi设备驱动体系架构
从这一层开始,整个文件读写的中心将由request转向scsi的命令结构scsi_cmnd。那么这个命令结构到底是怎么一回事呢,这还得从SCSI架构谈起。SCSI 实现了一种客户机/服务器风格的通信架构,发起者向目标设备发送命令请求。该目标处理此请求并向发起者返回响应。发起者可以是托管计算机中的一个 SCSI 设备,而 SCSI 目标则可以是一个磁盘、光盘和磁带设备或特殊设备(比如箱体设备)。
这里要提到一个概念——Lower Level Device(LDD):在最低层的是一组驱动器,称为 SCSI 低层驱动器。它们是一些可与物理设备(比如 HBA)链接的特定驱动器。LLD 提供了自公共中间层到特定于设备的 HBA 的一种抽象。每个 LLD 都提供了到特定底层硬件的接口,但所使用的到中间层的接口却是一组标准接口。
较低层包含大量代码,原因是它要负责处理各种不同的 SCSI 适配器类型。例如,Fibre Channel 协议包含了针对 Emulex 和 QLogic 的各种适配器的 LLD。面向 Adaptec 和 LSI 的 SAS 适配器的 LLD 也包括在内。
与存储相关的 SCSI 命令一般是在 SCSI Architecture Model (SAM)、SCSI Primary Commands (SPC) 和 SCSI Block Commands (SBC) 中定义的:
l SAM:定义SCSI 系统模型、SCSI 标准集的功能性分区,以及适用于所有 SCSI 实现和实现标准的需求。
l SPC:定义:对所有 SCSI 设备模型通用的行为。
l SBC:定义命令集扩展,以方便操作 SCSI 直接访问块设备。
每个 SCSI 命令都由 Command Descriptor Block (CDB) 描述,它定义 SCSI 设备执行的操作。SCSI 命令涉及到用于向 SCSI 设备传输数据(或从中输出数据)的数据命令,以及用于设置 SCSI 设备的配置参数的非数据命令。
典型的CDB格式如下图所示:
|
位 7 |
位 6 |
位 5 |
位 4 |
位 3 |
位 2 |
位 1 |
位 0 |
字节 0 |
Operation code = 12h |
|||||||
字节 1 |
LUN |
Reserved |
EVPD |
|||||
字节 2 |
Page code |
|||||||
字节 3 |
Reserved |
|||||||
字节 4 |
Allocation length |
|||||||
字节 5 |
Control |
如果 EVPD 参数位(用于启用关键产品数据)为 0 并且 Page Code 参数字节为 0,那么目标将返回标准命令数据(如inquiry)。如果 EVPD 参数为 1,那么目标将返回对应 page code 字段的特定于供应商的数据。
scsi_cmnd结构中的cmnd[MAX_COMMAND_SIZE]数组就是这个CDB的内容。我们看到这个数组虽然最大可有16个元素,每个元素1字节,但是我们仅仅用了其中6个元素,用来存放CDB,其中cmnd[0]最为重要,对应scsi操作码。所有的scsi操作码都有定义,在include/scsi/scsi.h中:
#define TEST_UNIT_READY 0x00 #define REZERO_UNIT 0x01 #define REQUEST_SENSE 0x03 #define FORMAT_UNIT 0x04 #define READ_BLOCK_LIMITS 0x05 #define REASSIGN_BLOCKS 0x07 #define INITIALIZE_ELEMENT_STATUS 0x07 #define READ_6 0x08 #define WRITE_6 0x0a #define SEEK_6 0x0b #define READ_REVERSE 0x0f #define WRITE_FILEMARKS 0x10 #define SPACE 0x11 #define INQUIRY 0x12 #define RECOVER_BUFFERED_DATA 0x14 #define MODE_SELECT 0x15 #define RESERVE 0x16 #define RELEASE 0x17 #define COPY 0x18 #define ERASE 0x19 #define MODE_SENSE 0x1a #define START_STOP 0x1b #define RECEIVE_DIAGNOSTIC 0x1c #define SEND_DIAGNOSTIC 0x1d #define ALLOW_MEDIUM_REMOVAL 0x1e #define SET_WINDOW 0x24 #define READ_CAPACITY 0x25 #define READ_10 0x28 #define WRITE_10 0x2a #define SEEK_10 0x2b #define POSITION_TO_ELEMENT 0x2b #define WRITE_VERIFY 0x2e #define VERIFY 0x2f #define SEARCH_HIGH 0x30 #define SEARCH_EQUAL 0x31 #define SEARCH_LOW 0x32 #define SET_LIMITS 0x33 #define PRE_FETCH 0x34 #define READ_POSITION 0x34 #define SYNCHRONIZE_CACHE 0x35 #define LOCK_UNLOCK_CACHE 0x36 #define READ_DEFECT_DATA 0x37 #define MEDIUM_SCAN 0x38 #define COMPARE 0x39 #define COPY_VERIFY 0x3a #define WRITE_BUFFER 0x3b #define READ_BUFFER 0x3c #define UPDATE_BLOCK 0x3d #define READ_LONG 0x3e #define WRITE_LONG 0x3f #define CHANGE_DEFINITION 0x40 #define WRITE_SAME 0x41 #define READ_TOC 0x43 #define LOG_SELECT 0x4c #define LOG_SENSE 0x4d #define MODE_SELECT_10 0x55 #define RESERVE_10 0x56 #define RELEASE_10 0x57 #define MODE_SENSE_10 0x5a #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f #define REPORT_LUNS 0xa0 #define MOVE_MEDIUM 0xa5 #define EXCHANGE_MEDIUM 0xa6 #define READ_12 0xa8 #define WRITE_12 0xaa #define WRITE_VERIFY_12 0xae #define SEARCH_HIGH_12 0xb0 #define SEARCH_EQUAL_12 0xb1 #define SEARCH_LOW_12 0xb2 #define READ_ELEMENT_STATUS 0xb8 #define SEND_VOLUME_TAG 0xb6 #define WRITE_LONG_2 0xea #define READ_16 0x88 #define WRITE_16 0x8a #define VERIFY_16 0x8f #define SERVICE_ACTION_IN 0x9e /* values for service action in */ #define SAI_READ_CAPACITY_16 0x10 /* Values for T10/04-262r7 */ #define ATA_16 0x85 /* 16-byte pass-thru */ #define ATA_12 0xa1 /* 12-byte pass-thru */ |
我们列出最常使用的命令:
命令 |
描述 |
INQUIRY |
请求目标设备的摘要信息 |
TEST_UNIT_READY |
检测目标设备是否准备好进行传输 |
READ_6 |
从 SCSI 目标设备传输数据 |
WRITE_6 |
向 SCSI 目标设备传输数据 |
REQUEST_SENSE |
请求最后一个命令的检测数据 |
READ_CAPACITY |
获得存储容量信息 |
所有 SCSI 命令都要以操作代码的第一个字节为开端,以表明它所代表的操作。并且所有 SCSI 命令都要包含一个控制字节。这个字节通常是该命令的最后一个字节,用于表示与供应商相关的信息等等。
scsi_cmnd 结构就完全是SCSI记录的抽象,不仅cmnd数组字段记录了命令描述块 (CDB);还有用于感测数据缓存 (SENSE BUFFER)的sense_buffer字段,以及用于存放IO 超时时间等 SCSI 相关的信息和 SCSI 子系统处理命令需要的一些其他信息的字段,如回调函数等。
来自include/scsi/scsi_cmnd.h:
struct scsi_cmnd { struct scsi_device *device; struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head eh_entry; /* entry for the host eh_cmd_q */ int eh_eflags; /* Used by error handlr */ void (*done) (struct scsi_cmnd *); /* Mid-level done function */ unsigned long serial_number; unsigned long jiffies_at_alloc; int retries; int allowed; int timeout_per_command; unsigned char cmd_len; enum dma_data_direction sc_data_direction; /* These elements define the operation we are about to perform */ #define MAX_COMMAND_SIZE 16 unsigned char cmnd[MAX_COMMAND_SIZE]; unsigned request_bufflen; /* Actual request size */ struct timer_list eh_timeout; /* Used to time out the command. */ void *request_buffer; /* Actual requested buffer */ /* These elements define the operation we ultimately want to perform */ unsigned short use_sg; /* Number of pieces of scatter-gather */ unsigned short sglist_len; /* size of malloc'd scatter-gather list */ unsigned underflow; unsigned transfersize; int resid; struct request *request; #define SCSI_SENSE_BUFFERSIZE 96 unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE when * CHECK CONDITION is received on original * command (auto-sense) */ void (*scsi_done) (struct scsi_cmnd *); struct scsi_pointer SCp; /* Scratchpad used by some host adapters */ unsigned char *host_scribble; int result; /* Status code from lower level driver */ unsigned char tag; /* SCSI-II queued command tag */ unsigned long pid; /* Process ID, starts at 0. Unique per host. */ }; |
scsi设备驱动体系架构相关推荐
- ceph存储 scsi设备驱动体系架构
scsi设备驱动体系架构 从这一层开始,整个文件读写的中心将由request转向scsi的命令结构scsi_cmnd.那么这个命令结构到底是怎么一回事呢,这还得从SCSI架构谈起.SCSI 实现了一种 ...
- Linux块设备驱动(二)————块设备的体系架构
块设备的体系架构从上到下依次为VFS虚拟文件系统.磁盘缓冲.各种类型的磁盘系统.通用块设备层.I/O调度层(优化访问上层的请求(读写请求)).块设备驱动层.块设备硬件层. 1.虚拟文件系统(VFS) ...
- linux 内核驱动模型,linux设备驱动模型架构分析 一
linux设备驱动模型架构分析 一 发布时间:2018-07-04 15:14, 浏览次数:584 , 标签: linux 概述 LDD3中说:"Linux内核需要一个对系统结构的一般性描述 ...
- Linux设备驱动开发基础
1.驱动概述和开发环境搭建 1.1驱动设备的作用 对设备驱动最通俗的解释就是"驱动硬件设备行动".驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的 ...
- 《Linux 设备驱动开发详解(第2版)》——1.4 Linux设备驱动
本节书摘来自异步社区<Linux 设备驱动开发详解(第2版)>一书中的第1章,第1.1节,作者:宋宝华著,更多章节内容可以访问云栖社区"异步社区"公众号查看 1.4 L ...
- 《Linux设备驱动开发详解(第2版)》隆重出版
Linux设备驱动开发详解(第2版)(前一版狂销3万册,畅销书最新升级) [新品] 点击看大图 基本信息 * 作者: 宋宝华 * 出版社:人民邮电出版社 * ISBN:97 ...
- scsi总线驱动的初始化
1.6.1 scsi总线驱动的初始化 块设备底层驱动的核心是scsi总线层驱动,在总线层驱动之上为各种不同的scsi设备驱动,在总线层驱动之下为scsi host驱动.其在内核中的位置如下图所示: 前 ...
- 转载:谢谢原作者:块设备驱动实战基础篇一 (170行代码构建一个逻辑块设备驱动)
1 内核块设备驱动基础学习与实战 1.1 设备驱动IO架构初探 操作系统是如何将数据读到缓冲区的,发生了什么?我们带着这样的问题,粗略走一下read调用系统过程,希望这个初探,可以唤起大家研究操作 ...
- Linux设备驱动开发概述
作者:宋宝华 email:author@linuxdriver.cn 在过去这些年,Linux已经成功应用于服务器和桌面系统,而近年来,随着嵌入式系统应用的持续升温,Linux也开始广泛应用于嵌入式领 ...
最新文章
- android mapping.txt,Android根据mapping.txt还原混淆的代码
- 2016可信云大会进入倒计时 顶级“参会攻略”强势来袭
- jquery的DOM节点操作(替换元素节点)
- 支持向量机的前世与今生
- python_day9 回调函数
- CSS学习总结(3)——CSS文本样式(属性)
- java课时,java学习笔记_课时一
- 高手对中科院考博英语的体会
- wxFormBuilder + wxPython手撸丑陋计算器
- 航空公司客户价值分析R语言实现
- 点赞 分数 20作者 陈越单位 浙江大学
- 华为云服务器如何使用
- WPF教程(二) WPF vs WinForms
- subprocess模块call的用法
- thinkphp6 404找不到网页错误常见情况总结(持续更新)
- java毕业设计-篮球资讯网站-源码+lw文档+mybatis+系统+mysql数据库+调试
- 【总线】一文看懂 UART 通信协议
- 一款功能强大的IP查询工具!
- 盛元广通高校实验室管理系统
- excel行列互换_办公软件操作技巧043:如何在excel中实现行列转置