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 | ||
29b31420 | 22 | dev_info(&us->pusb_dev->dev, "--- Init Media ---\n"); |
9799d126 | 23 | result = ene_read_byte(us, REG_CARD_STATUS, &MiscReg03); |
e93192ac | 24 | if (result != USB_STOR_XFER_GOOD) { |
6fbb90bf | 25 | dev_err(&us->pusb_dev->dev, "Failed to read register\n"); |
126bb03b AC |
26 | return USB_STOR_TRANSPORT_ERROR; |
27 | } | |
29b31420 | 28 | dev_info(&us->pusb_dev->dev, "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 | 41 | /* |
9799d126 | 42 | * ene_read_byte() : |
e93192ac | 43 | */ |
9799d126 | 44 | int ene_read_byte(struct us_data *us, WORD index, void *buf) |
126bb03b AC |
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 | ||
29b31420 | 70 | dev_dbg(&us->pusb_dev->dev, "transport --- ENE_SMInit\n"); |
126bb03b AC |
71 | |
72 | result = ENE_LoadBinCode(us, SM_INIT_PATTERN); | |
e93192ac | 73 | if (result != USB_STOR_XFER_GOOD) { |
6fbb90bf LL |
74 | dev_info(&us->pusb_dev->dev, |
75 | "Failed to load SmartMedia init code\n: result= %x\n", | |
76 | result); | |
126bb03b AC |
77 | return USB_STOR_TRANSPORT_ERROR; |
78 | } | |
79 | ||
307ae1d3 | 80 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
81 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
82 | bcb->DataTransferLength = 0x200; | |
83 | bcb->Flags = 0x80; | |
84 | bcb->CDB[0] = 0xF1; | |
85 | bcb->CDB[1] = 0x01; | |
86 | ||
87 | result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0); | |
e93192ac | 88 | if (result != USB_STOR_XFER_GOOD) { |
6fbb90bf LL |
89 | dev_err(&us->pusb_dev->dev, |
90 | "Failed to load SmartMedia init code: result = %x\n", | |
91 | result); | |
126bb03b AC |
92 | return USB_STOR_TRANSPORT_ERROR; |
93 | } | |
94 | ||
8be88040 | 95 | us->SM_Status = *(struct keucr_sm_status *)&buf[0]; |
126bb03b AC |
96 | |
97 | us->SM_DeviceID = buf[1]; | |
98 | us->SM_CardID = buf[2]; | |
99 | ||
e93192ac | 100 | if (us->SM_Status.Insert && us->SM_Status.Ready) { |
0ea8a165 JS |
101 | dev_info(&us->pusb_dev->dev, "Insert = %x\n", |
102 | us->SM_Status.Insert); | |
103 | dev_info(&us->pusb_dev->dev, "Ready = %x\n", | |
104 | us->SM_Status.Ready); | |
105 | dev_info(&us->pusb_dev->dev, "WtP = %x\n", | |
106 | us->SM_Status.WtP); | |
107 | dev_info(&us->pusb_dev->dev, "DeviceID = %x\n", | |
108 | us->SM_DeviceID); | |
109 | dev_info(&us->pusb_dev->dev, "CardID = %x\n", | |
110 | us->SM_CardID); | |
126bb03b AC |
111 | MediaChange = 1; |
112 | Check_D_MediaFmt(us); | |
e93192ac | 113 | } else { |
6fbb90bf LL |
114 | dev_err(&us->pusb_dev->dev, |
115 | "SmartMedia Card Not Ready --- %x\n", buf[0]); | |
126bb03b AC |
116 | return USB_STOR_TRANSPORT_ERROR; |
117 | } | |
118 | ||
119 | return USB_STOR_TRANSPORT_GOOD; | |
120 | } | |
121 | ||
e93192ac AC |
122 | /* |
123 | * ENE_LoadBinCode() | |
124 | */ | |
126bb03b AC |
125 | int ENE_LoadBinCode(struct us_data *us, BYTE flag) |
126 | { | |
127 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
128 | int result; | |
e93192ac | 129 | /* void *buf; */ |
126bb03b AC |
130 | PBYTE buf; |
131 | ||
29b31420 | 132 | /* dev_info(&us->pusb_dev->dev, "transport --- ENE_LoadBinCode\n"); */ |
126bb03b AC |
133 | if (us->BIN_FLAG == flag) |
134 | return USB_STOR_TRANSPORT_GOOD; | |
135 | ||
136 | buf = kmalloc(0x800, GFP_KERNEL); | |
b1f5f54e VK |
137 | if (buf == NULL) |
138 | return USB_STOR_TRANSPORT_ERROR; | |
e93192ac | 139 | switch (flag) { |
e93192ac AC |
140 | /* For SS */ |
141 | case SM_INIT_PATTERN: | |
29b31420 | 142 | dev_dbg(&us->pusb_dev->dev, "SM_INIT_PATTERN\n"); |
e93192ac | 143 | memcpy(buf, SM_Init, 0x800); |
126bb03b | 144 | break; |
e93192ac | 145 | case SM_RW_PATTERN: |
29b31420 | 146 | dev_dbg(&us->pusb_dev->dev, "SM_RW_PATTERN\n"); |
e93192ac | 147 | memcpy(buf, SM_Rdwr, 0x800); |
126bb03b AC |
148 | break; |
149 | } | |
150 | ||
307ae1d3 | 151 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
152 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
153 | bcb->DataTransferLength = 0x800; | |
e93192ac | 154 | bcb->Flags = 0x00; |
126bb03b AC |
155 | bcb->CDB[0] = 0xEF; |
156 | ||
157 | result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0); | |
158 | ||
159 | kfree(buf); | |
160 | us->BIN_FLAG = flag; | |
161 | return result; | |
162 | } | |
163 | ||
e93192ac AC |
164 | /* |
165 | * ENE_SendScsiCmd(): | |
166 | */ | |
126bb03b AC |
167 | int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg) |
168 | { | |
169 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
170 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
171 | ||
172 | int result; | |
e93192ac AC |
173 | unsigned int transfer_length = bcb->DataTransferLength, |
174 | cswlen = 0, partial = 0; | |
126bb03b AC |
175 | unsigned int residue; |
176 | ||
29b31420 | 177 | /* dev_dbg(&us->pusb_dev->dev, "transport --- ENE_SendScsiCmd\n"); */ |
e93192ac AC |
178 | /* send cmd to out endpoint */ |
179 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | |
180 | bcb, US_BULK_CB_WRAP_LEN, NULL); | |
181 | if (result != USB_STOR_XFER_GOOD) { | |
0ea8a165 JS |
182 | dev_err(&us->pusb_dev->dev, |
183 | "send cmd to out endpoint fail ---\n"); | |
126bb03b AC |
184 | return USB_STOR_TRANSPORT_ERROR; |
185 | } | |
186 | ||
e93192ac | 187 | if (buf) { |
6efe04ee AC |
188 | unsigned int pipe = fDir; |
189 | ||
190 | if (fDir == FDIR_READ) | |
191 | pipe = us->recv_bulk_pipe; | |
192 | else | |
193 | pipe = us->send_bulk_pipe; | |
194 | ||
e93192ac | 195 | /* Bulk */ |
126bb03b AC |
196 | if (use_sg) |
197 | result = usb_stor_bulk_srb(us, pipe, us->srb); | |
198 | else | |
e93192ac AC |
199 | result = usb_stor_bulk_transfer_sg(us, pipe, buf, |
200 | transfer_length, 0, &partial); | |
201 | if (result != USB_STOR_XFER_GOOD) { | |
29b31420 | 202 | dev_err(&us->pusb_dev->dev, "data transfer fail ---\n"); |
126bb03b AC |
203 | return USB_STOR_TRANSPORT_ERROR; |
204 | } | |
205 | } | |
206 | ||
e93192ac AC |
207 | /* Get CSW for device status */ |
208 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
209 | US_BULK_CS_WRAP_LEN, &cswlen); | |
126bb03b | 210 | |
e93192ac | 211 | if (result == USB_STOR_XFER_SHORT && cswlen == 0) { |
0ea8a165 JS |
212 | dev_warn(&us->pusb_dev->dev, |
213 | "Received 0-length CSW; retrying...\n"); | |
e93192ac AC |
214 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
215 | bcs, US_BULK_CS_WRAP_LEN, &cswlen); | |
126bb03b AC |
216 | } |
217 | ||
e93192ac | 218 | if (result == USB_STOR_XFER_STALLED) { |
126bb03b | 219 | /* get the status again */ |
0ea8a165 JS |
220 | dev_warn(&us->pusb_dev->dev, |
221 | "Attempting to get CSW (2nd try)...\n"); | |
e93192ac AC |
222 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
223 | bcs, US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
224 | } |
225 | ||
226 | if (result != USB_STOR_XFER_GOOD) | |
227 | return USB_STOR_TRANSPORT_ERROR; | |
228 | ||
229 | /* check bulk status */ | |
230 | residue = le32_to_cpu(bcs->Residue); | |
231 | ||
e93192ac AC |
232 | /* |
233 | * try to compute the actual residue, based on how much data | |
234 | * was really transferred and what the device tells us | |
235 | */ | |
236 | if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { | |
126bb03b | 237 | residue = min(residue, transfer_length); |
41e568d1 | 238 | if (us->srb) |
239 | scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), | |
240 | (int) residue)); | |
126bb03b AC |
241 | } |
242 | ||
243 | if (bcs->Status != US_BULK_STAT_OK) | |
244 | return USB_STOR_TRANSPORT_ERROR; | |
245 | ||
246 | return USB_STOR_TRANSPORT_GOOD; | |
247 | } | |
248 | ||
e93192ac AC |
249 | /* |
250 | * ENE_Read_Data() | |
251 | */ | |
126bb03b AC |
252 | int ENE_Read_Data(struct us_data *us, void *buf, unsigned int length) |
253 | { | |
254 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
255 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
256 | int result; | |
257 | ||
29b31420 | 258 | /* dev_dbg(&us->pusb_dev->dev, "transport --- ENE_Read_Data\n"); */ |
e93192ac | 259 | /* set up the command wrapper */ |
307ae1d3 | 260 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
261 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
262 | bcb->DataTransferLength = length; | |
e93192ac | 263 | bcb->Flags = 0x80; |
126bb03b AC |
264 | bcb->CDB[0] = 0xED; |
265 | bcb->CDB[2] = 0xFF; | |
266 | bcb->CDB[3] = 0x81; | |
267 | ||
e93192ac AC |
268 | /* send cmd to out endpoint */ |
269 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, | |
270 | US_BULK_CB_WRAP_LEN, NULL); | |
126bb03b AC |
271 | if (result != USB_STOR_XFER_GOOD) |
272 | return USB_STOR_TRANSPORT_ERROR; | |
273 | ||
e93192ac AC |
274 | /* R/W data */ |
275 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | |
276 | buf, length, NULL); | |
126bb03b AC |
277 | if (result != USB_STOR_XFER_GOOD) |
278 | return USB_STOR_TRANSPORT_ERROR; | |
279 | ||
e93192ac AC |
280 | /* Get CSW for device status */ |
281 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
282 | US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
283 | if (result != USB_STOR_XFER_GOOD) |
284 | return USB_STOR_TRANSPORT_ERROR; | |
285 | if (bcs->Status != US_BULK_STAT_OK) | |
286 | return USB_STOR_TRANSPORT_ERROR; | |
287 | ||
288 | return USB_STOR_TRANSPORT_GOOD; | |
289 | } | |
290 | ||
e93192ac AC |
291 | /* |
292 | * ENE_Write_Data(): | |
293 | */ | |
126bb03b AC |
294 | int ENE_Write_Data(struct us_data *us, void *buf, unsigned int length) |
295 | { | |
296 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
297 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
298 | int result; | |
299 | ||
e93192ac AC |
300 | /* printk("transport --- ENE_Write_Data\n"); */ |
301 | /* set up the command wrapper */ | |
307ae1d3 | 302 | memset(bcb, 0, sizeof(struct bulk_cb_wrap)); |
126bb03b AC |
303 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); |
304 | bcb->DataTransferLength = length; | |
e93192ac | 305 | bcb->Flags = 0x00; |
126bb03b AC |
306 | bcb->CDB[0] = 0xEE; |
307 | bcb->CDB[2] = 0xFF; | |
308 | bcb->CDB[3] = 0x81; | |
309 | ||
e93192ac AC |
310 | /* send cmd to out endpoint */ |
311 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, | |
312 | US_BULK_CB_WRAP_LEN, NULL); | |
126bb03b AC |
313 | if (result != USB_STOR_XFER_GOOD) |
314 | return USB_STOR_TRANSPORT_ERROR; | |
315 | ||
e93192ac AC |
316 | /* R/W data */ |
317 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | |
318 | buf, length, NULL); | |
126bb03b AC |
319 | if (result != USB_STOR_XFER_GOOD) |
320 | return USB_STOR_TRANSPORT_ERROR; | |
321 | ||
e93192ac AC |
322 | /* Get CSW for device status */ |
323 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | |
324 | US_BULK_CS_WRAP_LEN, NULL); | |
126bb03b AC |
325 | if (result != USB_STOR_XFER_GOOD) |
326 | return USB_STOR_TRANSPORT_ERROR; | |
327 | if (bcs->Status != US_BULK_STAT_OK) | |
328 | return USB_STOR_TRANSPORT_ERROR; | |
329 | ||
330 | return USB_STOR_TRANSPORT_GOOD; | |
331 | } | |
332 |