Primary Commands

25 Mar

Primary Commands
Each of the commands below is documented in the SCSI Primary Commands (SPC) specification.

INQUIRY
The INQUIRY command requests a structure containing information about the device. A device should be able to return the structure even when the media isn’t ready to respond to other commands. All SBC devices must support the INQUIRY command.

The data returned by the device in the data-transport phase is at least 36 bytes (Table 6-3). The data identifies the peripheral device type (PDT) and SPC version number and contains a vendor identification number, product identification number, product revision number, and other information about the device’s abilities and supported protocols.

Table 6-4 lists common PDTs and their codes from the SCSI Primary Commands document. Hard drives and flash-memory cards are type 00h: direct-access block device. Devices with PDT = 0Eh use the reduced block command (RBC) set, which is intended for block devices that have fewer requirements and options compared to SBC devices. RBC might sound appealing for some applications, but in practice the type is rarely used in part because Windows doesn’t provide a driver for it. If you need to provide  a vendor-specific RBC driver, you may as well define the device as vendor specific in the descriptors. That way, you’ll avoid confusion with any RBC drivers a user may have loaded for another purpose.

As Chapter 3 explained, if the interface descriptor’s bInterfaceSubClass doesn’t equal 06h (SCSI transparent command set), the PDT should match the declared bInterfaceSubClass.

Note that the RMB parameter (bit 7 of byte 1) reports whether the device has removable media. USB flash drives (thumb drives, pen drives, and similar devices) are removable devices with fixed media. However, some Microsoft documentation recommends that flash drives declare that they have removable media (RMB = 1), and many flash drives do so.

Table 6-3: The response to an INQUIRY command is at least 36 bytes. The SPC specification has more details on these fields.

Table 6-4: Some of the Peripheral Device Types (PDTs) defined in the SCSI Primary Commands document.

A vendor identification number is available at no charge from the T10 Technical Committee. The number consists of eight or fewer characters in the range 21h–7Eh.

Following the first 36 bytes are optional fields with additional data, including areas that vendor-specific drivers can use to obtain vendor-specific information. Device firmware shouldn’t assume that the host will always request exactly 36 bytes. The thirteen cases in Chapter 3 describe what a device should do if it has more or fewer bytes to return than the host requests.

The Response
An InquiryResponse structure can hold the data a device returns in response to an INQUIRY command:

typedef struct
{
byte Peripheral;
byte Removble;
byte Version;
byte Response_Data_Format;
byte AdditionalLength;
byte Sccstp;
byte bqueetc;
byte CmdQue;
char vendorID[8];
char productID[16];
char productRev[4];
} InquiryResponse;

The InquiryResponse data normally doesn’t change, so a device can store the data in ROM:

const rom InquiryResponse inq_resp = {
0×00, // direct access block device, connected
0×80, // device is removable
0×04, // SPC-2 compliance
0×02, // response data format
0×20, // response has 20h + 4 bytes
0×00, // additional fields, none set
0×00, // additional fields, none set
0×00, // additional fields, none set
“Microchp”, // 8 -byte T10-assigned Vendor ID
“Mass Storage “, // 16-byte product identification
“0001″ // 4-byte product revision level
};

Sending the Response
The MSDInquiryHandler function copies an InquiryResponse structure to msd_buffer (defined in Chapter 3) for sending to the host and sets the CSWDDataResidue and CSWStatus fields of the command’s CSW.

The function calls the memcopypgm2ram function provided with the Microchip C18 compiler. The function copies the response data from program memory into RAM.

void MSDInquiryHandler(void)
{
byte i;
byte *buffer;
// Copy sizeof(InquiryResponse) bytes from program memory beginning at
// &inq_resp to RAM beginning at &med_buffer[0].
memcpypgm2ram
((byte *)&msd_buffer[0],
(byte *)&inq_resp,
sizeof(InquiryResponse));
msd_csw.dCSWDataResidue = sizeof(InquiryResponse);
msd_csw.bCSWStatus = 0×00;
return;
}


Random Posts

No comments yet

Leave a Reply

You must be logged in to post a comment.