| User | Revision | Line number | New contents of line |
| emh203 |
0:76427232f435
|
1
|
|
| emh203 |
0:76427232f435
|
2
|
/*
|
| emh203 |
0:76427232f435
|
3
|
Copyright (c) 2010 Peter Barrett
|
| emh203 |
0:76427232f435
|
4
|
|
| emh203 |
0:76427232f435
|
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| emh203 |
0:76427232f435
|
6
|
of this software and associated documentation files (the "Software"), to deal
|
| emh203 |
0:76427232f435
|
7
|
in the Software without restriction, including without limitation the rights
|
| emh203 |
0:76427232f435
|
8
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| emh203 |
0:76427232f435
|
9
|
copies of the Software, and to permit persons to whom the Software is
|
| emh203 |
0:76427232f435
|
10
|
furnished to do so, subject to the following conditions:
|
| emh203 |
0:76427232f435
|
11
|
|
| emh203 |
0:76427232f435
|
12
|
The above copyright notice and this permission notice shall be included in
|
| emh203 |
0:76427232f435
|
13
|
all copies or substantial portions of the Software.
|
| emh203 |
0:76427232f435
|
14
|
|
| emh203 |
0:76427232f435
|
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| emh203 |
0:76427232f435
|
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| emh203 |
0:76427232f435
|
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| emh203 |
0:76427232f435
|
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| emh203 |
0:76427232f435
|
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| emh203 |
0:76427232f435
|
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
| emh203 |
0:76427232f435
|
21
|
THE SOFTWARE.
|
| emh203 |
0:76427232f435
|
22
|
*/
|
| emh203 |
0:76427232f435
|
23
|
|
| emh203 |
0:76427232f435
|
24
|
#include "stdlib.h"
|
| emh203 |
0:76427232f435
|
25
|
#include "stdio.h"
|
| emh203 |
0:76427232f435
|
26
|
#include "string.h"
|
| emh203 |
0:76427232f435
|
27
|
|
| emh203 |
0:76427232f435
|
28
|
#include "Utils.h"
|
| emh203 |
0:76427232f435
|
29
|
#include "USBHost.h"
|
| emh203 |
0:76427232f435
|
30
|
|
| emh203 |
0:76427232f435
|
31
|
|
| emh203 |
0:76427232f435
|
32
|
int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
|
| emh203 |
0:76427232f435
|
33
|
int MassStorage_ReadBlock(int device, u32 block, u8* dst);
|
| emh203 |
0:76427232f435
|
34
|
int MassStorage_WriteBlock(int device, u32 block, const u8* dst);
|
| emh203 |
0:76427232f435
|
35
|
|
| emh203 |
0:76427232f435
|
36
|
|
| emh203 |
0:76427232f435
|
37
|
#define ERR_BAD_CSW_SIGNATURE -200
|
| emh203 |
0:76427232f435
|
38
|
|
| emh203 |
0:76427232f435
|
39
|
#define CBW_SIGNATURE 0x43425355
|
| emh203 |
0:76427232f435
|
40
|
#define CSW_SIGNATURE 0x53425355
|
| emh203 |
0:76427232f435
|
41
|
|
| emh203 |
0:76427232f435
|
42
|
// Command Block
|
| emh203 |
0:76427232f435
|
43
|
typedef struct
|
| emh203 |
0:76427232f435
|
44
|
{
|
| emh203 |
0:76427232f435
|
45
|
u32 Signature;
|
| emh203 |
0:76427232f435
|
46
|
u32 Tag;
|
| emh203 |
0:76427232f435
|
47
|
u32 TransferLength;
|
| emh203 |
0:76427232f435
|
48
|
u8 Flags;
|
| emh203 |
0:76427232f435
|
49
|
u8 LUN;
|
| emh203 |
0:76427232f435
|
50
|
u8 CBLength;
|
| emh203 |
0:76427232f435
|
51
|
u8 CB[16]; // only 6 really
|
| emh203 |
0:76427232f435
|
52
|
} CBW;
|
| emh203 |
0:76427232f435
|
53
|
|
| emh203 |
0:76427232f435
|
54
|
// Status block
|
| emh203 |
0:76427232f435
|
55
|
typedef struct
|
| emh203 |
0:76427232f435
|
56
|
{
|
| emh203 |
0:76427232f435
|
57
|
u32 Signature;
|
| emh203 |
0:76427232f435
|
58
|
u32 Tag;
|
| emh203 |
0:76427232f435
|
59
|
u32 DataResidue;
|
| emh203 |
0:76427232f435
|
60
|
u8 Status;
|
| emh203 |
0:76427232f435
|
61
|
} CSW;
|
| emh203 |
0:76427232f435
|
62
|
|
| emh203 |
0:76427232f435
|
63
|
|
| emh203 |
0:76427232f435
|
64
|
//Eli Add
|
| emh203 |
0:76427232f435
|
65
|
unsigned char epin = 0x81;
|
| emh203 |
0:76427232f435
|
66
|
unsigned char epout = 0x01;
|
| emh203 |
0:76427232f435
|
67
|
|
| emh203 |
0:76427232f435
|
68
|
void SetSCSIEndPoints(unsigned char in,unsigned char out)
|
| emh203 |
0:76427232f435
|
69
|
{
|
| emh203 |
0:76427232f435
|
70
|
epin = in;
|
| emh203 |
0:76427232f435
|
71
|
epout = out;
|
| emh203 |
0:76427232f435
|
72
|
}
|
| emh203 |
0:76427232f435
|
73
|
|
| emh203 |
0:76427232f435
|
74
|
|
| emh203 |
0:76427232f435
|
75
|
int SCSIRequestSense();
|
| emh203 |
0:76427232f435
|
76
|
|
| emh203 |
0:76427232f435
|
77
|
int DoSCSI(const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen) {
|
| emh203 |
0:76427232f435
|
78
|
CBW cbw;
|
| emh203 |
0:76427232f435
|
79
|
cbw.Signature = CBW_SIGNATURE;
|
| emh203 |
0:76427232f435
|
80
|
cbw.Tag = 0;
|
| emh203 |
0:76427232f435
|
81
|
cbw.TransferLength = transferLen;
|
| emh203 |
0:76427232f435
|
82
|
cbw.Flags = flags;
|
| emh203 |
0:76427232f435
|
83
|
cbw.LUN = 0;
|
| emh203 |
0:76427232f435
|
84
|
cbw.CBLength = cmdLen;
|
| emh203 |
0:76427232f435
|
85
|
memset(cbw.CB,0,sizeof(cbw.CB));
|
| emh203 |
0:76427232f435
|
86
|
memcpy(cbw.CB,cmd,cmdLen);
|
| emh203 |
0:76427232f435
|
87
|
|
| emh203 |
0:76427232f435
|
88
|
int r;
|
| emh203 |
0:76427232f435
|
89
|
//r = USBBulkTransfer(device,0x01,(u8*)&cbw,31); // Send the command
|
| emh203 |
0:76427232f435
|
90
|
r = USBBulkTransfer(USB_Disk_Device,epout,(u8*)&cbw,31); // Send the command
|
| emh203 |
0:76427232f435
|
91
|
if (r < 0) {
|
| emh203 |
0:76427232f435
|
92
|
printf("first transfer returns %d\n", r);
|
| emh203 |
0:76427232f435
|
93
|
return r;
|
| emh203 |
0:76427232f435
|
94
|
}
|
| emh203 |
0:76427232f435
|
95
|
if (data) {
|
| emh203 |
0:76427232f435
|
96
|
//r = USBBulkTransfer(device,flags | 1,data,transferLen);
|
| emh203 |
0:76427232f435
|
97
|
r = USBBulkTransfer(USB_Disk_Device,flags ? epin : epout,data,transferLen);
|
| emh203 |
0:76427232f435
|
98
|
if (r < 0) {
|
| emh203 |
0:76427232f435
|
99
|
printf("second transfer returns %d (flags=%02xH)\n", r, flags);
|
| emh203 |
0:76427232f435
|
100
|
return r;
|
| emh203 |
0:76427232f435
|
101
|
}
|
| emh203 |
0:76427232f435
|
102
|
}
|
| emh203 |
0:76427232f435
|
103
|
|
| emh203 |
0:76427232f435
|
104
|
CSW csw;
|
| emh203 |
0:76427232f435
|
105
|
csw.Signature = 0;
|
| emh203 |
0:76427232f435
|
106
|
//r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
|
| emh203 |
0:76427232f435
|
107
|
r = USBBulkTransfer(USB_Disk_Device,epin,(u8*)&csw,13);
|
| emh203 |
0:76427232f435
|
108
|
if (r < 0) {
|
| emh203 |
0:76427232f435
|
109
|
printf("third transfer returns %d\n", r);
|
| emh203 |
0:76427232f435
|
110
|
return r;
|
| emh203 |
0:76427232f435
|
111
|
}
|
| emh203 |
0:76427232f435
|
112
|
if (csw.Signature != CSW_SIGNATURE)
|
| emh203 |
0:76427232f435
|
113
|
return ERR_BAD_CSW_SIGNATURE;
|
| emh203 |
0:76427232f435
|
114
|
|
| emh203 |
0:76427232f435
|
115
|
// ModeSense?
|
| emh203 |
0:76427232f435
|
116
|
if (csw.Status == 1 && cmd[0] != 3)
|
| emh203 |
0:76427232f435
|
117
|
return SCSIRequestSense();
|
| emh203 |
0:76427232f435
|
118
|
|
| emh203 |
0:76427232f435
|
119
|
return csw.Status;
|
| emh203 |
0:76427232f435
|
120
|
}
|
| emh203 |
0:76427232f435
|
121
|
|
| emh203 |
0:76427232f435
|
122
|
|
| emh203 |
0:76427232f435
|
123
|
int SCSITestUnitReady() {
|
| emh203 |
0:76427232f435
|
124
|
u8 cmd[6];
|
| emh203 |
0:76427232f435
|
125
|
memset(cmd,0,6);
|
| emh203 |
0:76427232f435
|
126
|
return DoSCSI(cmd,6,DEVICE_TO_HOST,0,0);
|
| emh203 |
0:76427232f435
|
127
|
}
|
| emh203 |
0:76427232f435
|
128
|
|
| emh203 |
0:76427232f435
|
129
|
int SCSIRequestSense() {
|
| emh203 |
0:76427232f435
|
130
|
u8 cmd[6] = {0x03,0,0,0,18,0};
|
| emh203 |
0:76427232f435
|
131
|
u8 result[18];
|
| emh203 |
0:76427232f435
|
132
|
int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,18);
|
| emh203 |
0:76427232f435
|
133
|
return r;
|
| emh203 |
0:76427232f435
|
134
|
}
|
| emh203 |
0:76427232f435
|
135
|
|
| emh203 |
0:76427232f435
|
136
|
int SCSIInquiry() {
|
| emh203 |
0:76427232f435
|
137
|
u8 cmd[6] = {0x12,0,0,0,36,0};
|
| emh203 |
0:76427232f435
|
138
|
u8 result[36+2];
|
| emh203 |
0:76427232f435
|
139
|
result[36] = '\n';
|
| emh203 |
0:76427232f435
|
140
|
result[37] = 0;
|
| emh203 |
0:76427232f435
|
141
|
int r = DoSCSI(cmd,6,DEVICE_TO_HOST,result,36);
|
| emh203 |
0:76427232f435
|
142
|
if (r == 0)
|
| emh203 |
0:76427232f435
|
143
|
printf((const char*)result + 8);
|
| emh203 |
0:76427232f435
|
144
|
return r;
|
| emh203 |
0:76427232f435
|
145
|
}
|
| emh203 |
0:76427232f435
|
146
|
int SCSIReadCapacity(u32* blockCount, u32* blockSize) {
|
| emh203 |
0:76427232f435
|
147
|
u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
|
| emh203 |
0:76427232f435
|
148
|
u8 result[8];
|
| emh203 |
0:76427232f435
|
149
|
*blockSize = 0;
|
| emh203 |
0:76427232f435
|
150
|
*blockCount = 0;
|
| emh203 |
0:76427232f435
|
151
|
int r = DoSCSI(cmd,10,DEVICE_TO_HOST,result,8);
|
| emh203 |
0:76427232f435
|
152
|
if (r == 0) {
|
| emh203 |
0:76427232f435
|
153
|
*blockCount = BE32(result);
|
| emh203 |
0:76427232f435
|
154
|
*blockSize = BE32(result+4);
|
| emh203 |
0:76427232f435
|
155
|
}
|
| emh203 |
0:76427232f435
|
156
|
return r;
|
| emh203 |
0:76427232f435
|
157
|
}
|
| emh203 |
0:76427232f435
|
158
|
|
| emh203 |
0:76427232f435
|
159
|
int SCSITransfer(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction) {
|
| emh203 |
0:76427232f435
|
160
|
// USB hardware will only do 4k per transfer
|
| emh203 |
0:76427232f435
|
161
|
while (blockCount*blockSize > 4096) {
|
| emh203 |
0:76427232f435
|
162
|
int count = 4096/blockSize;
|
| emh203 |
0:76427232f435
|
163
|
int r = SCSITransfer(blockAddr,count,dst,blockSize,direction);
|
| emh203 |
0:76427232f435
|
164
|
dst += count*blockSize;
|
| emh203 |
0:76427232f435
|
165
|
blockAddr += count;
|
| emh203 |
0:76427232f435
|
166
|
blockCount -= count;
|
| emh203 |
0:76427232f435
|
167
|
}
|
| emh203 |
0:76427232f435
|
168
|
|
| emh203 |
0:76427232f435
|
169
|
u8 cmd[10];
|
| emh203 |
0:76427232f435
|
170
|
memset(cmd,0,10);
|
| emh203 |
0:76427232f435
|
171
|
cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
|
| emh203 |
0:76427232f435
|
172
|
BE32(blockAddr,cmd+2);
|
| emh203 |
0:76427232f435
|
173
|
BE16(blockCount,cmd+7);
|
| emh203 |
0:76427232f435
|
174
|
return DoSCSI(cmd,10,direction,dst,blockSize*blockCount);
|
| emh203 |
0:76427232f435
|
175
|
}
|
| emh203 |
0:76427232f435
|
176
|
|
| emh203 |
0:76427232f435
|
177
|
int MassStorage_ReadCapacity(u32* blockCount, u32* blockSize)
|
| emh203 |
0:76427232f435
|
178
|
{
|
| emh203 |
0:76427232f435
|
179
|
return SCSIReadCapacity(blockCount,blockSize);
|
| emh203 |
0:76427232f435
|
180
|
}
|
| emh203 |
0:76427232f435
|
181
|
|
| emh203 |
0:76427232f435
|
182
|
int MassStorage_Read(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
|
| emh203 |
0:76427232f435
|
183
|
{
|
| emh203 |
0:76427232f435
|
184
|
return SCSITransfer(blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
|
| emh203 |
0:76427232f435
|
185
|
}
|
| emh203 |
0:76427232f435
|
186
|
|
| emh203 |
0:76427232f435
|
187
|
int MassStorage_Write(u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
|
| emh203 |
0:76427232f435
|
188
|
{
|
| emh203 |
0:76427232f435
|
189
|
return SCSITransfer(blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
|
| emh203 |
0:76427232f435
|
190
|
}
|
| emh203 |
0:76427232f435
|
191
|
|
| emh203 |
0:76427232f435
|
192
|
|
| emh203 |
0:76427232f435
|
193
|
|
| emh203 |
0:76427232f435
|
194
|
|