2 * Acess2 USB Stack Mass Storage Driver
3 * - By John Hodge (thePowersGang)
6 * - "SCSI Transparent Command Set" handling code
13 Uint64 MSC_SCSI_GetSize(tUSBInterface *Dev, size_t *BlockSize);
14 void MSC_SCSI_DumpSenseData(tUSBInterface *Dev);
15 int MSC_SCSI_ReadData(void *Ptr, Uint64 Block, size_t Count, void *Dest);
16 int MSC_SCSI_WriteData(void *Ptr, Uint64 Block, size_t Count, const void *Dest);
19 tLVM_VolType gMSC_SCSI_VolType = {
20 .Name = "USB-MSC-SCSI",
21 .Read = MSC_SCSI_ReadData,
22 .Write = MSC_SCSI_WriteData
26 Uint64 MSC_SCSI_GetSize(tUSBInterface *Dev, size_t *BlockSize)
30 struct sSCSI_Cmd_ReadCapacity10 cmd = {READ_CAPACITY_10,0,0,0,0,0};
31 struct sSCSI_Ret_ReadCapacity10 ret = {0,0};
33 if( MSC_RecvData(Dev, sizeof(cmd), &cmd, sizeof(ret), &ret) != 0 ) {
35 Log_Warning("MSC SCSI", "Command \"Read Capacity (10)\" failed");
36 MSC_SCSI_DumpSenseData(Dev);
40 if( ret.LastBlock != 0xFFFFFFFF )
42 *BlockSize = BigEndian32(ret.BlockSize);
43 return BigEndian32(ret.LastBlock)+1;
46 // Size was too large for 32-bits, attempt a 16-byte op
49 // 2. Attempt a 16 byte op
51 struct sSCSI_Cmd_ReadCapacity16 cmd;
52 struct sSCSI_Ret_ReadCapacity16 ret;
54 cmd.Op = SERVICE_ACTION_IN_16;
56 cmd.LBA = BigEndian64( 0 );
57 cmd.AllocationLength = BigEndian32(sizeof(ret));
63 if( MSC_RecvData(Dev, sizeof(cmd), &cmd, sizeof(ret), &ret) != 0 ) {
65 Log_Warning("MSC SCSI", "Command \"Read Capacity (16)\" failed");
69 *BlockSize = BigEndian32(ret.BlockSize);
70 return BigEndian64(ret.LastBlock)+1;
74 void MSC_SCSI_DumpSenseData(tUSBInterface *Dev)
76 struct sSCSI_SenseData ret;
77 struct sSCSI_Cmd_RequestSense cmd = {0x03, 0, 0, sizeof(ret), 0};
79 int rv = MSC_RecvData(Dev, sizeof(cmd), &cmd, sizeof(ret), &ret);
82 Log_Warning("MSC SCSI", "Command \"Request Sense\" failed, giving up");
86 const char *const sense_keys[16] = {
87 "No Sense", "Recovered Error", "Not Ready", "Medium Error",
88 "Hardware Error", "Illegal Request", "Unit Attention", "Data Protect",
89 "Blank Check", "Vendor Specific", "Copy Aborted", "Aborted Command",
90 "-obs-", "Volume Overflow", "Miscompare", "-rsvd-"
92 Log_Debug("MSC SCSI", "Dumping Sense Data:");
93 Log_Debug("MSC SCSI", ".ResponseCode = %02x", ret.ResponseCode);
94 Log_Debug("MSC SCSI", ".Flags = %02x (%s%s%s%s)", ret.Flags,
95 (ret.Flags & (1<<7) ? "FILEMARK,":""),
96 (ret.Flags & (1<<6) ? "EOM,":""),
97 (ret.Flags & (1<<6) ? "ILI,":""),
98 sense_keys[ret.Flags & 15]
100 Log_Debug("MSC SCSI", ".Information = %08x", BigEndian32(ret.Information));
101 Log_Debug("MSC SCSI", ".AdditionalLen = %02x", ret.AdditionalSenseLength);
102 Log_Debug("MSC SCSI", ".CommandSpecInfomation = %08x", BigEndian32(ret.CommandSpecInfomation));
103 Log_Debug("MSC SCSI", ".ASC = %02x", ret.AdditionalSenseCode);
104 Log_Debug("MSC SCSI", ".ASCQ = %02x", ret.AdditionalSenseCodeQual);
107 int MSC_SCSI_ReadData(void *Ptr, Uint64 Block, size_t Count, void *Dest)
109 tUSBInterface *Dev = Ptr;
110 tMSCInfo *info = USB_GetDeviceDataPtr(Dev);
112 // Error if more than 64 thousand blocks are read at once
113 if( Count > (1UL<<16) ) {
114 // What the fsck are you smoking?
115 Log_Error("MSC SCSI", "Attempt to read >16-bits worth of blocks");
119 // TODO: Bounds checking?
122 if( Block < (1UL << 20) && Count <= (1UL << 8) )
125 struct sSCSI_Cmd_Read6 cmd;
127 cmd.LBATop = Block >> 16;
128 cmd.LBALower = BigEndian16( Block & 0xFFFF );
129 cmd.Length = Count & 0xFF; // 0 == 256
132 ret = MSC_RecvData(Dev, sizeof(cmd), &cmd, Count*info->BlockSize, Dest);
134 else if( Block <= 0xFFFFFFFF )
137 struct sSCSI_Cmd_Read10 cmd;
140 cmd.LBA = BigEndian32( Block );
142 cmd.Length = BigEndian16( Count ); // 0 == no blocks
145 ret = MSC_RecvData(Dev, sizeof(cmd), &cmd, Count*info->BlockSize, Dest);
150 struct sSCSI_Cmd_Read16 cmd;
153 cmd.LBA = BigEndian64(Block);
154 cmd.Length = BigEndian32(Count);
158 ret = MSC_RecvData(Dev, sizeof(cmd), &cmd, Count*info->BlockSize, Dest);
164 // TODO: Get read size and find out how much was read
171 int MSC_SCSI_WriteData(void *Ptr, Uint64 Block, size_t Count, const void *Data)
173 Log_Warning("MSC_SCSI", "TODO: Implement MSC_SCSI_WriteData");