scsi设备驱动体系架构
来源:互联网 发布:增强现实的软件 编辑:程序博客网 时间:2024/06/11 08:12
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设备驱动体系架构
- scsi设备驱动体系架构
- scsi设备驱动体系架构
- ceph存储 scsi设备驱动体系架构
- scsi块设备驱动层处理
- scsi块设备驱动层处理
- Linux块设备驱动(二)————块设备的体系架构
- Linux设备驱动架构
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 字符设备驱动 架构分析
- 块设备驱动架构分析
- scsi 设备挂载
- 串口通讯--同步通讯方式
- 真实的I/O调度层处理
- scsi总线驱动的初始化
- 工具条文本中的空白符
- 基于SSH框架的分页实现
- scsi设备驱动体系架构
- scsi块设备驱动层处理
- scsi命令的执行
- linux内存cached释放
- myeclipse新建maven项目时报错
- scsi命令的第一次转变
- scsi命令的第二次转变
- 一个有用的类,集合了建立、连接热点;获取本机ip和连接此热点的手机的ip地址等方法
- 日语练习4_厦門の旅行