现在总结一下scsi,scsi协议有很多,所以只总结这次在usb mass storage里面用到的协议,主要包括inquiry,format , read write等等命令。
下面会一个一个总结。
U盘需要处理的命令如下:
1:inquiry:设备的一个描述,告诉host你的设备是什么,名字叫什么,用的什么协议,这里用的SCSI协议—SPC2
2:READ FORMAT CAPACITIES:读格式容量(The READ FORMAT CAPACITIES command allows the host to request a list of the possible capacities that can be formatted on the currently installed medium.)
3:READ CAPACITY:读取容量信息
4:READ(10):回发在逻辑单元的数据,既回发MBR(Main Boot Record)主引导扇区
5:SENSE6:目的在于获得设备内部很多潜在的信息,其中包括了是否设置了写保(The MODE SENSE(6) command (see table 62) provides a means for a device server to report parameters to an application client. It is a complementary command to the MODE SELECT(6) command. Device servers that implement the MODE SENSE(6) command shall also implement the MODE SELECT(6) command.)
6:WRITE(10):host向slave发生数据并写在u盘存储器里面。
7:TEST UNIT READY:检查U盘准备好没有。
1:inquiry
// The standard INQUIRY data shall contain at least 36 bytes
// This is the reduced structure for Mass Storage Devices
typedef struct
{
cyg_uint8 peripheral; // Device Type
cyg_uint8 rmb; // Removable Media Bit
cyg_uint8 version; // Version Field
cyg_uint8 resp_data_format; // Response Data Format
cyg_uint8 additional_len; // Additional Length
cyg_uint8 sccstp; // SCC Supported (include embedded storage array)
cyg_uint8 bque; // Basic Queuing
cyg_uint8 cmdque; // Command Queuing
cyg_uint8 vendor_id[8];
cyg_uint8 product_id[16];
cyg_uint8 product_rev[4];
} msd_scsi_inq_resp;
这个结构体就是为inquiry准备的数据包,这个命令是usb mass storage第一个接收到的命令
在这里只需要关注两个字段OPERATION CODE,ALLOCATION LENGTH。其它的还没用到,每个命令都有一个OPERATION CODE
用来标志这个命令是什么命令,毕竟我们不会看数字就知道什么意思,电脑也不会看文字就是要做什么,是吧。现在这里是12,我们查一查SPC-2
协议,就知道OPERATION CODE为12就知道这次host需要slave做什么操作。
既然知道了这个操作,那么咱们就应该回复一下,毕竟来而不往非礼也。那咱们得准备一下礼物送给host,不然这个门打不开,马上就关起来了
就好像现在这个社会,有钱有权什么都可以,这个社会让我们这些刚毕业的怎么生存啊,咱学习嵌入式就是为了多赚点money。下面就是一个能够回复
Host的inquiry包。
/*
这是inquiry请求包
*/
const msd_scsi_inq_resp inrq_resp = {
USBS_SCSI_DIRECT_ACCESS_BLOCK_DEVICE, // Direct Access Block device 0x00
USBS_SCSI_REMOVABLE_DEVICE, // Device is removable
0x04, // Comply with SPC-2
0x02, // Standard format
0x20, /* Response is 0x20 + 4 bytes,表明这个请求包有多长,这里为36 */
0x00,
0x00,
0x00,
{'R','i','s','e','t','e','k',' '}, /*VENDOR IDENTIFICATION 8~15*/
{'M','a','s','s',' ','S','t','o','r','a','g','e',' ',' ',' ',' '}, /*PRODUCT IDENTIFICATION 16-31*/
{'0','.','0','1'}, /*PRODUCT REVISION LEVEL ,版本, 32~35*/
};
这个图下面还有数据端,但是在这里就只回了一个最小的数据包回去,那就总结这些字段就好了吧。
第0个字节:有这两个PERIPHERAL QUALIFIER,PERIPHERAL DEVICE TYPE东东需要关注,PERIPHERAL QUALIFIER这里三位全为0
PERIPHERAL DEVICE TYPE的值都为0,表明意思是Direct-access device。
第一个字节:只要关注RMB表明这个设备可不可以移除,原文为:A removable medium (RMB) bit of zero indicates that the medium is not removable. A RMB bit
of one indicates that the medium is removable.
第二个字节:VERSION表明数据交流使用的协议版本是SPC-2,其值为0x04,
第三个字节:An AERC bit of one indicates that the processor device is capable of accepting asynchronous event reports. An AERC bit of zero indicates that the processor device does not support asynchronous event reports;
RESPONSE DATA FORMAT:A RESPONSE DATA FORMAT field value of two indicates that the data shall be in the format specified in this standard.
这里写为2就好,整个字节的值就是为0x02。
第四个字节:ADDITIONAL LENGTH表明这个值附加了多少数据,Response is 0x20 + 4 bytes,表明这个请求包有多长,这里为36,前面有四个数据下面有32个刚好36个数据。
第五,第六,第七个字节都填0,想知道为什么的话,看看手册吧,不然这么总结就成了在翻译协议了。
第八字节—第十五字节:VENDOR IDENTIFICATION,在8个字节里面,随便写一些字符,写法如上面就可以了。而PRODUCT IDENTIFICATION和PRODUCT REVISION LEVEL都是想填什么就填什么,只要没有操作范围。一定要注意范围哦。
/*
Function: usb_msd_scsi_handle_inquiry:
Handle Inquiry Request Command
Data in : msd
Data out: NULL
*/
static inline cyg_int32 usb_msd_scsi_handle_inquiry( usb_msd * msd )
{
cyg_int32 tx_bytes = sizeof(msd_scsi_inq_resp);
DBG("USB Slave MSD: SCSI inquiry\n");
// Copy over to message buffer
memcpy( msd->buffer, (cyg_uint8 *) &inrq_resp, tx_bytes );
usb_msd_tx_send(msd , tx_bytes);
return tx_bytes;
}
通过端点2就把数据发给host,第一步就完成了。
2:READ FORMATCAPACITIES
下表就是READ FORMATCAPACITIES Command的命令表,这个命令也只需要关注两个字节,Operation Code (23h) and Logical Unit Number
Logical Unit Number(LUN),前面说过这个LUN,这里就为一个LUN。下面准备回复的数据。
这个usb_msd_scsi_read_format_capacities函数就是用来准备回复host数据的函数并且发送给host。还是按照协议回复,上图。
第一个需要准备的是Capacity List Header,然后是Current/Maximum Capacity Header等等。