Commit | Line | Data |
---|---|---|
126bb03b AC |
1 | #include <linux/sched.h> |
2 | #include <linux/errno.h> | |
3 | #include <linux/slab.h> | |
4 | ||
5 | #include <scsi/scsi.h> | |
6 | #include <scsi/scsi_eh.h> | |
7 | #include <scsi/scsi_device.h> | |
8 | ||
9 | #include "usb.h" | |
10 | #include "scsiglue.h" | |
11 | #include "transport.h" | |
12 | #include "init.h" | |
13 | ||
e93192ac AC |
14 | /* |
15 | * ENE_InitMedia(): | |
16 | */ | |
126bb03b AC |
17 | int ENE_InitMedia(struct us_data *us) |
18 | { | |
19 | int result; | |
20 | BYTE MiscReg03 = 0; | |
21 | ||
e93192ac | 22 | printk(KERN_INFO "--- Init Media ---\n"); |
126bb03b | 23 | result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03); |
e93192ac AC |
24 | if (result != USB_STOR_XFER_GOOD) { |
25 | printk(KERN_ERR "Read register fail !!\n"); | |
126bb03b AC |
26 | return USB_STOR_TRANSPORT_ERROR; |
27 | } | |
e93192ac | 28 | printk(KERN_INFO "MiscReg03 = %x\n", MiscReg03); |
126bb03b | 29 | |
e93192ac AC |
30 | if (MiscReg03 & 0x02) { |
31 | if (!us->SM_Status.Ready && !us->MS_Status.Ready) { | |
126bb03b | 32 | result = ENE_SMInit(us); |
383b7fc2 | 33 | if (result != USB_STOR_XFER_GOOD) |
20c3d7f7 | 34 | return USB_STOR_TRANSPORT_ERROR; |
126bb03b AC |
35 | } |
36 | ||
37 | } | |
38 | return result; | |
39 | } | |
40 | ||
e93192ac AC |
41 | /* |
42 | * ENE_Read_BYTE() : | |
43 | */ | |
126bb03b AC |
44 | int ENE_Read_BYTE(struct us_data *us, WORD index, void *buf) |
45 | { | |
46 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
47 | int result; | |
48 | ||
307ae1d3 | 49 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
50 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
51 | bcb->DataTransferLength = 0x01; | |
52 | bcb->Flags = 0x80; | |
53 | bcb->CDB[0] = 0xED; | |
54 | bcb->CDB[2] = (BYTE)(index>>8); | |
55 | bcb->CDB[3] = (BYTE)index; | |
56 | ||
57 | result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0); | |
58 | return result; | |
59 | } | |
60 | ||
e93192ac AC |
61 | /* |
62 | *ENE_SMInit() | |
63 | */ | |
126bb03b AC |
64 | int ENE_SMInit(struct us_data *us) |
65 | { | |
66 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
67 | int result; | |
68 | BYTE buf[0x200]; | |
69 | ||
e93192ac | 70 | printk(KERN_INFO "transport --- ENE_SMInit\n"); |
126bb03b AC |
71 | |
72 | result = ENE_LoadBinCode(us, SM_INIT_PATTERN); | |
e93192ac AC |
73 | if (result != USB_STOR_XFER_GOOD) { |
74 | printk(KERN_INFO "Load SM Init Code Fail !!\n"); | |
126bb03b AC |
75 | return USB_STOR_TRANSPORT_ERROR; |
76 | } | |
77 | ||
307ae1d3 | 78 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
79 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
80 | bcb->DataTransferLength = 0x200; | |
81 | bcb->Flags = 0x80; | |
82 | bcb->CDB[0] = 0xF1; | |
83 | bcb->CDB[1] = 0x01; | |
84 | ||
85 | result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0); | |
e93192ac AC |
86 | if (result != USB_STOR_XFER_GOOD) { |
87 | printk(KERN_ERR | |
25985edc | 88 | "Execution SM Init Code Fail !! result = %x\n", result); |
126bb03b AC |
89 | return USB_STOR_TRANSPORT_ERROR; |
90 | } | |
91 | ||
92 | us->SM_Status = *(PSM_STATUS)&buf[0]; | |
93 | ||
94 | us->SM_DeviceID = buf[1]; | |
95 | us->SM_CardID = buf[2]; | |
96 | ||
e93192ac AC |
97 | if (us->SM_Status.Insert && us->SM_Status.Ready) { |
98 | printk(KERN_INFO "Insert = %x\n", us->SM_Status.Insert); | |
99 | printk(KERN_INFO "Ready = %x\n", us->SM_Status.Ready); | |
100 | printk(KERN_INFO "WtP = %x\n", us->SM_Status.WtP); | |
101 | printk(KERN_INFO "DeviceID = %x\n", us->SM_DeviceID); | |
102 | printk(KERN_INFO "CardID = %x\n", us->SM_CardID); | |
126bb03b AC |
103 | MediaChange = 1; |
104 | Check_D_MediaFmt(us); | |
e93192ac AC |
105 | } else { |
106 | printk(KERN_ERR "SM Card Not Ready --- %x\n", buf[0]); | |
126bb03b AC |
107 | return USB_STOR_TRANSPORT_ERROR; |
108 | } | |
109 | ||
110 | return USB_STOR_TRANSPORT_GOOD; | |
111 | } | |
112 | ||
e93192ac AC |
113 | /* |
114 | * ENE_LoadBinCode() | |
115 | */ | |
126bb03b AC |
116 | int ENE_LoadBinCode(struct us_data *us, BYTE flag) |
117 | { | |
118 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
119 | int result; | |
e93192ac | 120 | /* void *buf; */ |
126bb03b AC |
121 | PBYTE buf; |
122 | ||
e93192ac | 123 | /* printk(KERN_INFO "transport --- ENE_LoadBinCode\n"); */ |
126bb03b AC |
124 | if (us->BIN_FLAG == flag) |
125 | return USB_STOR_TRANSPORT_GOOD; | |
126 | ||
127 | buf = kmalloc(0x800, GFP_KERNEL); | |
b1f5f54e VK |
128 | if (buf == NULL) |
129 | return USB_STOR_TRANSPORT_ERROR; | |
e93192ac | 130 | switch (flag) { |
e93192ac AC |
131 | /* For SS */ |
132 | case SM_INIT_PATTERN: | |
133 | printk(KERN_INFO "SM_INIT_PATTERN\n"); | |
134 | memcpy(buf, SM_Init, 0x800); | |
126bb03b | 135 | break; |
e93192ac AC |
136 | case SM_RW_PATTERN: |
137 | printk(KERN_INFO "SM_RW_PATTERN\n"); | |
138 | memcpy(buf, SM_Rdwr, 0x800); | |
126bb03b AC |
139 | break; |
140 | } | |
141 | ||
307ae1d3 | 142 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
143 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
144 | bcb->DataTransferLength = 0x800; | |
e93192ac | 145 | bcb->Flags = 0x00; |
126bb03b AC |
146 | bcb->CDB[0] = 0xEF; |
147 | ||
148 | result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0); | |
149 | ||
150 | kfree(buf); | |
151 | us->BIN_FLAG = flag; | |
152 | return result; | |
153 | } | |
154 | ||
e93192ac AC |
155 | /* |
156 | * ENE_SendScsiCmd(): | |
157 | */ | |
126bb03b AC |
158 | int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg) |
159 | { | |
160 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
161 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
162 | ||
163 | int result; | |
e93192ac AC |
164 | unsigned int transfer_length = bcb->DataTransferLength, |
165 | cswlen = 0, partial = 0; | |
126bb03b AC |
166 | unsigned int residue; |
167 | ||
e93192ac AC |
168 | /* printk(KERN_INFO "transport --- ENE_SendScsiCmd\n"); */ |
169 | /* send cmd to out endpoint */ | |
170 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | |
171 | bcb, US_BULK_CB_WRAP_LEN, NULL); | |
172 | if (result != USB_STOR_XFER_GOOD) { | |
173 | printk(KERN_ERR "send cmd to out endpoint fail ---\n"); | |
126bb03b AC |
174 | return USB_STOR_TRANSPORT_ERROR; |
175 | } | |
176 | ||
e93192ac | 177 | if (buf) { |
6efe04ee AC |
178 | unsigned int pipe = fDir; |
179 | ||
180 | if (fDir == FDIR_READ) | |
181 | pipe = us->recv_bulk_pipe; | |
182 | else | |
183 | pipe = us->send_bulk_pipe; | |
184 | ||
e93192ac | 185 | /* Bulk */ |
126bb03b AC |
186 | if (use_sg) |
187 | result = usb_stor_bulk_srb(us, pipe, us->srb); | |
188 | else | |
e93192ac AC |
189 | result = usb_stor_bulk_transfer_sg(us, pipe, buf, |
190 | transfer_length, 0, &partial); | |
191 | if (result != USB_STOR_XFER_GOOD) { | |
192 | printk(KERN_ERR "data transfer fail ---\n"); | |
126bb03b AC |
193 | return USB_STOR_TRANSPORT_ERROR; |
194 | } | |
195 | } | |
196 | ||
e93192ac AC |
197 | /* Get CSW for device status */ |
198 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
199 | US_BULK_CS_WRAP_LEN, &cswlen); | |
126bb03b | 200 | |
e93192ac AC |
201 | if (result == USB_STOR_XFER_SHORT && cswlen == 0) { |
202 | printk(KERN_WARNING "Received 0-length CSW; retrying...\n"); | |
203 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
204 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); | |
126bb03b AC |
205 | } |
206 | ||
e93192ac | 207 | if (result == USB_STOR_XFER_STALLED) { |
126bb03b | 208 | /* get the status again */ |
e93192ac AC |
209 | printk(KERN_WARNING "Attempting to get CSW (2nd try)...\n"); |
210 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
211 | bcs, US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
212 | } |
213 | ||
214 | if (result != USB_STOR_XFER_GOOD) | |
215 | return USB_STOR_TRANSPORT_ERROR; | |
216 | ||
217 | /* check bulk status */ | |
218 | residue = le32_to_cpu(bcs->Residue); | |
219 | ||
e93192ac AC |
220 | /* |
221 | * try to compute the actual residue, based on how much data | |
222 | * was really transferred and what the device tells us | |
223 | */ | |
224 | if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { | |
126bb03b | 225 | residue = min(residue, transfer_length); |
41e568d1 | 226 | if (us->srb) |
227 | scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), | |
228 | (int) residue)); | |
126bb03b AC |
229 | } |
230 | ||
231 | if (bcs->Status != US_BULK_STAT_OK) | |
232 | return USB_STOR_TRANSPORT_ERROR; | |
233 | ||
234 | return USB_STOR_TRANSPORT_GOOD; | |
235 | } | |
236 | ||
e93192ac AC |
237 | /* |
238 | * ENE_Read_Data() | |
239 | */ | |
126bb03b AC |
240 | int ENE_Read_Data(struct us_data *us, void *buf, unsigned int length) |
241 | { | |
242 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
243 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
244 | int result; | |
245 | ||
e93192ac AC |
246 | /* printk(KERN_INFO "transport --- ENE_Read_Data\n"); */ |
247 | /* set up the command wrapper */ | |
307ae1d3 | 248 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
249 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
250 | bcb->DataTransferLength = length; | |
e93192ac | 251 | bcb->Flags = 0x80; |
126bb03b AC |
252 | bcb->CDB[0] = 0xED; |
253 | bcb->CDB[2] = 0xFF; | |
254 | bcb->CDB[3] = 0x81; | |
255 | ||
e93192ac AC |
256 | /* send cmd to out endpoint */ |
257 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, | |
258 | US_BULK_CB_WRAP_LEN, NULL); | |
126bb03b AC |
259 | if (result != USB_STOR_XFER_GOOD) |
260 | return USB_STOR_TRANSPORT_ERROR; | |
261 | ||
e93192ac AC |
262 | /* R/W data */ |
263 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
264 | buf, length, NULL); | |
126bb03b AC |
265 | if (result != USB_STOR_XFER_GOOD) |
266 | return USB_STOR_TRANSPORT_ERROR; | |
267 | ||
e93192ac AC |
268 | /* Get CSW for device status */ |
269 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
270 | US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
271 | if (result != USB_STOR_XFER_GOOD) |
272 | return USB_STOR_TRANSPORT_ERROR; | |
273 | if (bcs->Status != US_BULK_STAT_OK) | |
274 | return USB_STOR_TRANSPORT_ERROR; | |
275 | ||
276 | return USB_STOR_TRANSPORT_GOOD; | |
277 | } | |
278 | ||
e93192ac AC |
279 | /* |
280 | * ENE_Write_Data(): | |
281 | */ | |
126bb03b AC |
282 | int ENE_Write_Data(struct us_data *us, void *buf, unsigned int length) |
283 | { | |
284 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
285 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
286 | int result; | |
287 | ||
e93192ac AC |
288 | /* printk("transport --- ENE_Write_Data\n"); */ |
289 | /* set up the command wrapper */ | |
307ae1d3 | 290 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
291 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
292 | bcb->DataTransferLength = length; | |
e93192ac | 293 | bcb->Flags = 0x00; |
126bb03b AC |
294 | bcb->CDB[0] = 0xEE; |
295 | bcb->CDB[2] = 0xFF; | |
296 | bcb->CDB[3] = 0x81; | |
297 | ||
e93192ac AC |
298 | /* send cmd to out endpoint */ |
299 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, | |
300 | US_BULK_CB_WRAP_LEN, NULL); | |
126bb03b AC |
301 | if (result != USB_STOR_XFER_GOOD) |
302 | return USB_STOR_TRANSPORT_ERROR; | |
303 | ||
e93192ac AC |
304 | /* R/W data */ |
305 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | |
306 | buf, length, NULL); | |
126bb03b AC |
307 | if (result != USB_STOR_XFER_GOOD) |
308 | return USB_STOR_TRANSPORT_ERROR; | |
309 | ||
e93192ac AC |
310 | /* Get CSW for device status */ |
311 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
312 | US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
313 | if (result != USB_STOR_XFER_GOOD) |
314 | return USB_STOR_TRANSPORT_ERROR; | |
315 | if (bcs->Status != US_BULK_STAT_OK) | |
316 | return USB_STOR_TRANSPORT_ERROR; | |
317 | ||
318 | return USB_STOR_TRANSPORT_GOOD; | |
319 | } | |
320 | ||
e93192ac AC |
321 | /* |
322 | * usb_stor_print_cmd(): | |
323 | */ | |
126bb03b AC |
324 | void usb_stor_print_cmd(struct scsi_cmnd *srb) |
325 | { | |
326 | PBYTE Cdb = srb->cmnd; | |
327 | DWORD cmd = Cdb[0]; | |
e93192ac AC |
328 | DWORD bn = ((Cdb[2] << 24) & 0xff000000) | |
329 | ((Cdb[3] << 16) & 0x00ff0000) | | |
330 | ((Cdb[4] << 8) & 0x0000ff00) | | |
331 | ((Cdb[5] << 0) & 0x000000ff); | |
332 | WORD blen = ((Cdb[7] << 8) & 0xff00) | ((Cdb[8] << 0) & 0x00ff); | |
126bb03b AC |
333 | |
334 | switch (cmd) { | |
335 | case TEST_UNIT_READY: | |
e93192ac AC |
336 | /* printk(KERN_INFO |
337 | "scsi cmd %X --- SCSIOP_TEST_UNIT_READY\n", cmd); */ | |
126bb03b AC |
338 | break; |
339 | case INQUIRY: | |
e93192ac | 340 | printk(KERN_INFO "scsi cmd %X --- SCSIOP_INQUIRY\n", cmd); |
126bb03b AC |
341 | break; |
342 | case MODE_SENSE: | |
e93192ac | 343 | printk(KERN_INFO "scsi cmd %X --- SCSIOP_MODE_SENSE\n", cmd); |
126bb03b AC |
344 | break; |
345 | case START_STOP: | |
e93192ac | 346 | printk(KERN_INFO "scsi cmd %X --- SCSIOP_START_STOP\n", cmd); |
126bb03b AC |
347 | break; |
348 | case READ_CAPACITY: | |
e93192ac | 349 | printk(KERN_INFO "scsi cmd %X --- SCSIOP_READ_CAPACITY\n", cmd); |
126bb03b AC |
350 | break; |
351 | case READ_10: | |
e93192ac AC |
352 | /* printk(KERN_INFO |
353 | "scsi cmd %X --- SCSIOP_READ,bn = %X, blen = %X\n" | |
354 | ,cmd, bn, blen); */ | |
126bb03b AC |
355 | break; |
356 | case WRITE_10: | |
e93192ac AC |
357 | /* printk(KERN_INFO |
358 | "scsi cmd %X --- SCSIOP_WRITE, | |
359 | bn = %X, blen = %X\n" , cmd, bn, blen); */ | |
126bb03b AC |
360 | break; |
361 | case ALLOW_MEDIUM_REMOVAL: | |
e93192ac AC |
362 | printk(KERN_INFO |
363 | "scsi cmd %X --- SCSIOP_ALLOW_MEDIUM_REMOVAL\n", cmd); | |
126bb03b AC |
364 | break; |
365 | default: | |
e93192ac | 366 | printk(KERN_INFO "scsi cmd %X --- Other cmd\n", cmd); |
126bb03b AC |
367 | break; |
368 | } | |
369 | bn = 0; | |
370 | blen = 0; | |
371 | } | |
372 |