Embed:
(wiki syntax)
Show/hide line numbers
MassStorage.cpp
00001 00002 /* 00003 Copyright (c) 2010 Peter Barrett 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 THE SOFTWARE. 00022 */ 00023 00024 #include "stdlib.h" 00025 #include "stdio.h" 00026 #include "string.h" 00027 00028 #include "Utils.h" 00029 #include "USBHost.h" 00030 00031 00032 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize); 00033 int MassStorage_ReadBlock(int device, u32 block, u8* dst); 00034 int MassStorage_WriteBlock(int device, u32 block, const u8* dst); 00035 00036 00037 #define ERR_BAD_CSW_SIGNATURE -200 00038 00039 #define CBW_SIGNATURE 0x43425355 00040 #define CSW_SIGNATURE 0x53425355 00041 00042 // Command Block 00043 typedef struct 00044 { 00045 u32 Signature; 00046 u32 Tag; 00047 u32 TransferLength; 00048 u8 Flags; 00049 u8 LUN; 00050 u8 CBLength; 00051 u8 CB[16]; // only 6 really 00052 } CBW; 00053 00054 // Status block 00055 typedef struct 00056 { 00057 u32 Signature; 00058 u32 Tag; 00059 u32 DataResidue; 00060 u8 Status; 00061 } CSW; 00062 00063 00064 //Eli Add 00065 unsigned char epin = 0x81; 00066 unsigned char epout = 0x01; 00067 00068 void SetSCSIEndPoints(unsigned char in,unsigned char out) 00069 { 00070 epin = in; 00071 epout = out; 00072 } 00073 00074 00075 int SCSIRequestSense(); 00076 00077 int DoSCSI(const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) { 00078 CBW cbw; 00079 cbw.Signature = CBW_SIGNATURE; 00080 cbw.Tag = 0; 00081 cbw.TransferLength = transferLen; 00082 cbw.Flags = flags; 00083 cbw.LUN = 0; 00084 cbw.CBLength = cmdLen; 00085 memset(cbw.CB,0,sizeof(cbw.CB)); 00086 memcpy(cbw.CB,cmd,cmdLen); 00087 00088 int r; 00089 //r = USBBulkTransfer(device,0x01,(u8*)&cbw,31); // Send the command 00090 r = USBBulkTransfer(USB_Disk_Device,epout,(u8*)&cbw,31); // Send the command 00091 if (r < 0) { 00092 printf("first transfer returns %d\n", r); 00093 return r; 00094 } 00095 if (data) { 00096 //r = USBBulkTransfer(device,flags | 1,data,transferLen); 00097 r = USBBulkTransfer(USB_Disk_Device,flags ? epin : epout,data,transferLen); 00098 if (r < 0) { 00099 printf("second transfer returns %d (flags=%02xH)\n", r, flags); 00100 return r; 00101 } 00102 } 00103 00104 CSW csw; 00105 csw.Signature = 0; 00106 //r = USBBulkTransfer(device,0x81,(u8*)&csw,13); 00107 r = USBBulkTransfer(USB_Disk_Device,epin,(u8*)&csw,13); 00108 if (r < 0) { 00109 printf("third transfer returns %d\n", r); 00110 return r; 00111 } 00112 if (csw.Signature != CSW_SIGNATURE) 00113 return ERR_BAD_CSW_SIGNATURE; 00114 00115 // ModeSense? 00116 if (csw.Status == 1 && cmd[0] != 3) 00117 return SCSIRequestSense(); 00118 00119 return csw.Status; 00120 } 00121 00122 00123 int SCSITestUnitReady() { 00124 u8 cmd[6]; 00125 memset(cmd,0,6); 00126 return DoSCSI(cmd,6,DEVICE_TO_HOST,0,0); 00127 } 00128 00129 int SCSIRequestSense() { 00130 u8 cmd[6] = {0x03,0,0,0,18,0}; 00131 u8 result[18]; 00132 int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,18); 00133 return r; 00134 } 00135 00136 int SCSIInquiry() { 00137 u8 cmd[6] = {0x12,0,0,0,36,0}; 00138 u8 result[36+2]; 00139 result[36] = '\n'; 00140 result[37] = 0; 00141 int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,36); 00142 if (r == 0) 00143 printf((const char*)result + 8); 00144 return r; 00145 } 00146 int SCSIReadCapacity(u32* blockCount, u32* blockSize) { 00147 u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0}; 00148 u8 result[8]; 00149 *blockSize = 0; 00150 *blockCount = 0; 00151 int r = DoSCSI(cmd,10,DEVICE_TO_HOST,result,8); 00152 if (r == 0) { 00153 *blockCount = BE32(result); 00154 *blockSize = BE32(result+4); 00155 } 00156 return r; 00157 } 00158 00159 int SCSITransfer(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) { 00160 // USB hardware will only do 4k per transfer 00161 while (blockCount*blockSize > 4096) { 00162 int count = 4096/blockSize; 00163 int r = SCSITransfer(blockAddr,count,dst,blockSize,direction); 00164 dst += count*blockSize; 00165 blockAddr += count; 00166 blockCount -= count; 00167 } 00168 00169 u8 cmd[10]; 00170 memset(cmd,0,10); 00171 cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A; 00172 BE32(blockAddr,cmd+2); 00173 BE16(blockCount,cmd+7); 00174 return DoSCSI(cmd,10,direction,dst,blockSize*blockCount); 00175 } 00176 00177 int MassStorage_ReadCapacity(u32* blockCount, u32* blockSize) 00178 { 00179 return SCSIReadCapacity(blockCount,blockSize); 00180 } 00181 00182 int MassStorage_Read(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) 00183 { 00184 return SCSITransfer(blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST); 00185 } 00186 00187 int MassStorage_Write(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512) 00188 { 00189 return SCSITransfer(blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE); 00190 } 00191 00192 00193 00194
Generated on Sat Jul 16 2022 22:22:09 by
1.7.2
Eli Hughes