scsi_cmnd结构体中的cmd为什么是指针
时间: 2024-04-27 19:23:22 浏览: 171
在SCSI中,每个SCSI命令都由一组参数和数据组成。这些参数和数据被放置在一个称为SCSI命令块(SCSI Command Block,简称SCB)的结构体中。而SCSI命令块则被包含在一个称为SCSI命令描述符(SCSI Command Descriptor Block,简称CDB)的结构体中。在Linux内核中,SCSI命令描述符结构体被定义为一个scsi_cmnd结构体。scsi_cmnd结构体中的cmd字段是一个指针,指向SCSI命令块(SCB)的起始地址。
指针的使用可以使得SCSI命令块(SCB)在内存中的位置不受限制,这样就可以在任何时候动态地创建和销毁SCSI命令块(SCB),从而更灵活地管理系统资源。此外,指针可以减少内存的复制和移动,提高系统的性能。
相关问题
scsi_cmnd结构体
scsi_cmnd结构体是用于SCSI命令处理的数据结构,它在Linux内核中定义在<linux/scsi/scsi_cmnd.h>头文件中,其定义如下:
```
struct scsi_cmnd {
struct request *request; // 对应的请求描述符指针
unsigned char *cmnd; // SCSI命令块(SCB)的起始地址
unsigned int cmd_len; // SCSI命令块(SCB)的长度
unsigned char *sense_buffer;// 感知数据缓冲区的起始地址
unsigned int sense_len; // 感知数据缓冲区的长度
unsigned int result; // SCSI命令执行结果
unsigned long flags; // 命令的标志位
int retries; // 重试次数
void *host_scribble; // 指向主机驱动程序的私有数据结构
void *driver_data; // 指向设备驱动程序的私有数据结构
struct list_head list; // 用于将SCSI命令缓冲区链接起来的链表
unsigned char *cmnd_backup; // 指向SCSI命令块(SCB)的备份地址
unsigned int resid; // 命令未执行的块数
unsigned int underflow; // 数据传输过程中未传输的字节数
unsigned int total_xfer_len;// 数据传输总长度
unsigned int transfersize; // 单次数据传输的长度
unsigned char *buffer; // 指向数据缓冲区的起始地址
struct scatterlist *sglist; // 指向散列列表的指针
unsigned int sglen; // 散列列表中的块数
void (*scsi_done)(struct scsi_cmnd *); // SCSI命令完成时的回调函数
void *request_buffer; // 指向请求缓冲区的起始地址
dma_addr_t request_buffer_dma; // 请求缓冲区的DMA地址
int cmd_per_lun; // 每个逻辑单元号可以发送的命令数
int tag; // 命令标记,用于命令的排序
unsigned char *scsi_cmd_blk; // 指向SCSI命令块(SCB)的起始地址
unsigned int scsi_cmd_len; // SCSI命令块(SCB)的长度
struct device *device; // 指向SCSI设备的设备结构体指针
unsigned int retries_remaining; // 剩余重试次数
unsigned int timeout_per_command; // 命令超时时间
struct kref kref; // 引用计数结构体,用于管理SCSI命令的生命周期
};
```
其中,各字段的含义如下:
- request:指向请求描述符(request descriptor)的指针;
- cmnd:SCSI命令块(SCB)的起始地址;
- cmd_len:SCSI命令块(SCB)的长度;
- sense_buffer:感知数据缓冲区(sense data buffer)的起始地址;
- sense_len:感知数据缓冲区(sense data buffer)的长度;
- result:SCSI命令执行结果;
- flags:命令的标志位;
- retries:重试次数;
- host_scribble:指向主机驱动程序的私有数据结构;
- driver_data:指向设备驱动程序的私有数据结构;
- list:用于将SCSI命令缓冲区链接起来的链表;
- cmnd_backup:指向SCSI命令块(SCB)的备份地址;
- resid:命令未执行的块数;
- underflow:数据传输过程中未传输的字节数;
- total_xfer_len:数据传输总长度;
- transfersize:单次数据传输的长度;
- buffer:指向数据缓冲区的起始地址;
- sglist:指向散列列表的指针;
- sglen:散列列表中的块数;
- scsi_done:SCSI命令完成时的回调函数;
- request_buffer:指向请求缓冲区的起始地址;
- request_buffer_dma:请求缓冲区的DMA地址;
- cmd_per_lun:每个逻辑单元号可以发送的命令数;
- tag:命令标记,用于命令的排序;
- scsi_cmd_blk:指向SCSI命令块(SCB)的起始地址;
- scsi_cmd_len:SCSI命令块(SCB)的长度;
- device:指向SCSI设备的设备结构体指针;
- retries_remaining:剩余重试次数;
- timeout_per_command:命令超时时间;
- kref:引用计数结构体,用于管理SCSI命令的生命周期。
裸驱想要发送ufs的write6命令,怎么配置scsi_cmd结构体
首先,需要创建一个 `scsi_cmnd` 结构体的实例。然后,需要设置该结构体的各个成员变量,具体如下:
1. `cmnd[0]` 设置为 `WRITE_6`,即命令码为 0x0A。
2. `device->lun` 设置为需要访问的逻辑单元号。
3. `cmnd[1]` 置为 0,用于表示写入的数据是按照块来计算的。
4. `cmnd[2]`、`cmnd[3]`、`cmnd[4]`、`cmnd[5]` 分别设置为待写入数据所在的逻辑块地址。
5. `cmnd[7]` 设置为待写入数据的块数,即要写入的数据长度(大端模式)。
具体实现代码可以参考如下示例:
```c
struct scsi_cmnd *cmd; // cmd 为已经分配好的 scsi_cmnd 实例
// 设置命令码和逻辑单元号
cmd->cmnd[0] = WRITE_6;
cmd->device->lun = 0;
// 设置块寻址
cmd->cmnd[1] = 0;
cmd->cmnd[2] = (start_block >> 16) & 0xFF;
cmd->cmnd[3] = (start_block >> 8) & 0xFF;
cmd->cmnd[4] = start_block & 0xFF;
// 设置写入块数
cmd->cmnd[7] = (num_blocks >> 8) & 0xFF;
cmd->cmnd[8] = num_blocks & 0xFF;
```
其中,`start_block` 表示待写入数据的起始逻辑块地址,`num_blocks` 表示待写入数据的块数。
阅读全文