1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25
26 /*
27 * scsa2usb_ms_bulkonly.c:
28 *
29 * This file implements USB Mass Storage Class
30 * Bulk Only (BO) transport v1.0
31 * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf
32 */
33 #include <sys/usb/usba/usbai_version.h>
34 #include <sys/scsi/scsi.h>
35 #include <sys/callb.h> /* needed by scsa2usb.h */
36 #include <sys/strsubr.h>
37 #include <sys/strsun.h>
38
39 #include <sys/usb/usba.h>
40 #include <sys/usb/usba/usba_private.h>
41 #include <sys/usb/usba/usba_ugen.h>
42
43 #include <sys/usb/clients/mass_storage/usb_bulkonly.h>
44 #include <sys/usb/scsa2usb/scsa2usb.h>
45
46 /*
47 * Function Prototypes
48 */
49 int scsa2usb_bulk_only_transport(scsa2usb_state_t *,
50 scsa2usb_cmd_t *);
51 static void scsa2usb_fill_in_cbw(scsa2usb_state_t *, scsa2usb_cmd_t *,
52 mblk_t *);
53 static void scsa2usb_bulk_only_reset_recovery(scsa2usb_state_t *);
54 static void scsa2usb_bulk_only_handle_error(scsa2usb_state_t *,
55 usb_bulk_req_t *);
56 int scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t *);
57 static int scsa2usb_handle_status_start(scsa2usb_state_t *,
58 usb_bulk_req_t *);
59 static int scsa2usb_handle_csw_result(scsa2usb_state_t *, mblk_t *);
60
61
62 /* extern functions */
63 extern void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *);
64 extern int scsa2usb_handle_data_start(scsa2usb_state_t *,
65 scsa2usb_cmd_t *, usb_bulk_req_t *);
66 extern void scsa2usb_handle_data_done(scsa2usb_state_t *, scsa2usb_cmd_t *,
67 usb_bulk_req_t *);
68 extern usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *,
69 size_t, uint_t, usb_req_attrs_t, usb_flags_t);
70 extern int scsa2usb_bulk_timeout(int);
71 extern int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t,
72 usb_pipe_handle_t, char *);
73 extern void scsa2usb_close_usb_pipes(scsa2usb_state_t *);
74
75 #ifdef DEBUG /* debugging information */
76 extern void scsa2usb_print_cdb(scsa2usb_state_t *, scsa2usb_cmd_t *);
77 #endif /* DEBUG */
78
79
80 #ifdef SCSA2USB_BULK_ONLY_TEST
81 /*
82 * Test 13 cases. (See USB Mass Storage Class - Bulk Only Transport).
83 * We are not covering test cases 1, 6, and 12 as these are the "good"
84 * test cases and are tested as part of the normal drive access operations.
85 *
86 * NOTE: This is for testing only. It will be replaced by a uscsi test.
87 */
88 int scsa2usb_test_case_2 = 0;
89 int scsa2usb_test_case_3 = 0;
90 int scsa2usb_test_case_4 = 0;
91 int scsa2usb_test_case_7 = 0;
92 extern int scsa2usb_test_case_8;
93 int scsa2usb_test_case_9 = 0;
94 extern int scsa2usb_test_case_10;
95 int scsa2usb_test_case_13 = 0;
96 #endif /* SCSA2USB_BULK_ONLY_TEST */
97
98
99 /*
100 * scsa2usb_bulk_only_transport:
101 * Implements the BO state machine by these steps:
102 * a) Issues CBW to a Bulk Only device.
103 * b) Start Data Phase if applicable
104 * c) Start Status Phase
105 *
106 * returns TRAN_* values
107 *
108 * scsa2usb_bulk_only_state_machine:
109 *
110 * scsa2usb_bulk_only_transport() handles the normal transitions or
111 * continuation after clearing stalls or error recovery.
112 *
113 * Command Phase:
114 * prepare a valid CBW and transport it on bulk-out pipe
115 * if error on bulkout:
116 * set pkt_reason to CMD_TRAN_ERR
117 * new pkt state is SCSA2USB_PKT_DO_COMP
118 * reset recovery synchronously
119 * else
120 * proceed to data phase
121 *
122 * Data Phase:
123 * if data in:
124 * setup data in on bulkin
125 * else if data out:
126 * setup data out on bulkout
127 *
128 * data: (in)
129 * copy data transferred so far, no more data to transfer
130 *
131 * if stall on bulkin pipe
132 * terminate data transfers, set cmd_done
133 * clear stall on bulkin syncrhonously
134 * else if other exception
135 * set pkt_reason to CMD_TRAN_ERR
136 * new pkt state is SCSA2USB_PKT_DO_COMP
137 * reset recovery syncrhonously
138 * else (no error)
139 * receive status
140 *
141 * data: (out)
142 * if stall on bulkout pipe
143 * terminate data transfers, set cmd_done
144 * clear stall on bulkout synchronously USBA
145 * else if other exception
146 * set pkt_reason to CMD_TRAN_ERR
147 * new pkt state is SCSA2USB_PKT_DO_COMP
148 * reset recovery synchronously
149 * else (no error)
150 * receive status
151 *
152 * Status Phase:
153 *
154 * if stall (first attempt)
155 * new pkt state is SCSA2USB_PKT_PROCESS_CSW
156 * setup receiving status on bulkin
157 * if stall (second attempt)
158 * new pkt state is SCSA2USB_PKT_DO_COMP
159 * reset recovery synchronously, we are hosed.
160 * else
161 * goto check CSW
162 * else
163 * goto check CSW
164 *
165 * check CSW:
166 * - check length equals 13, signature, and matching tag
167 * - check status is less than or equal to 2
168 * - check residue is less than or equal to data length
169 * adjust residue based on if we got valid data
170 *
171 * if not OK
172 * new pkt state is SCSA2USB_PKT_DO_COMP
173 * set pkt reason CMD_TRAN_ERR
174 * reset recovery synchronously, we are hosed
175 * else if phase error
176 * new pkt state is SCSA2USB_PKT_DO_COMP
177 * set pkt reason CMD_TRAN_ERR
178 * reset recovery synchronously
179 * else if (status < 2)
180 * if status is equal to 1
181 * set check condition
182 * if residue
183 * calculate residue from data xferred and DataResidue
184 *
185 * set pkt_residue
186 * goto SCSA2USB_PKT_DO_COMP
187 *
188 * The reset recovery walks sequentially thru device reset, clearing
189 * stalls and pipe resets. When the reset recovery completes we return
190 * to the taskq thread.
191 *
192 * Clearing stalls clears the stall condition, resets the pipe, and
193 * then returns to the transport.
194 */
195 int
scsa2usb_bulk_only_transport(scsa2usb_state_t * scsa2usbp,scsa2usb_cmd_t * cmd)196 scsa2usb_bulk_only_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd)
197 {
198 int rval;
199 int nretry;
200 usb_bulk_req_t *req;
201
202 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
203
204 Cmd_Phase:
205 /*
206 * Start Command Phase
207 * Initialize a bulk_req_t
208 */
209 req = scsa2usb_init_bulk_req(scsa2usbp, USB_BULK_CBWCMD_LEN,
210 SCSA2USB_BULK_PIPE_TIMEOUT, USB_ATTRS_PIPE_RESET, USB_FLAGS_SLEEP);
211
212 scsa2usb_fill_in_cbw(scsa2usbp, cmd, req->bulk_data); /* Fill CBW */
213 SCSA2USB_PRINT_CDB(scsa2usbp, cmd); /* Print CDB */
214
215 /* Send a Bulk Command Block Wrapper (CBW) to the device */
216 mutex_exit(&scsa2usbp->scsa2usb_mutex);
217
218 ASSERT(req->bulk_timeout);
219 rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, req,
220 USB_FLAGS_SLEEP);
221 mutex_enter(&scsa2usbp->scsa2usb_mutex);
222
223 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
224 "scsa2usb_bulk_only_transport: "
225 "sent cmd = 0x%x Tag = 0x%x DataXferLen = 0x%lx rval = %d",
226 cmd->cmd_cdb[SCSA2USB_OPCODE], cmd->cmd_tag, cmd->cmd_xfercount,
227 rval);
228
229 if (rval != USB_SUCCESS) {
230 scsa2usb_bulk_only_handle_error(scsa2usbp, req);
231
232 return (TRAN_FATAL_ERROR);
233 }
234
235 /* free the data */
236 SCSA2USB_FREE_MSG(req->bulk_data);
237 req->bulk_data = NULL;
238
239 Data_Phase:
240 /*
241 * Start Data Phase
242 * re-set timeout
243 */
244 req->bulk_timeout = scsa2usb_bulk_timeout(cmd->cmd_timeout);
245
246 /*
247 * we've not transferred any data yet; updated in
248 * scsa2usb_handle_data_done
249 */
250 cmd->cmd_resid_xfercount = cmd->cmd_xfercount;
251
252 if (cmd->cmd_xfercount) {
253 /* start I/O to/from the device */
254 rval = scsa2usb_handle_data_start(scsa2usbp, cmd, req);
255
256 /* handle data returned, if any */
257 scsa2usb_handle_data_done(scsa2usbp, cmd, req);
258
259 if (rval != USB_SUCCESS) {
260 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
261 scsa2usbp->scsa2usb_log_handle,
262 "data xfer phase, error = %d, cr = %d",
263 rval, req->bulk_completion_reason);
264 /*
265 * we ran into an error
266 */
267 if (req->bulk_completion_reason == USB_CR_STALL) {
268 if (scsa2usbp->scsa2usb_cur_pkt) {
269 scsa2usbp->scsa2usb_cur_pkt->
270 pkt_reason = CMD_TRAN_ERR;
271 }
272 } else {
273 scsa2usb_bulk_only_handle_error(scsa2usbp, req);
274
275 return (TRAN_FATAL_ERROR);
276 }
277 } /* end of else */
278
279 /* free the data */
280 SCSA2USB_FREE_MSG(req->bulk_data);
281 req->bulk_data = NULL;
282 }
283
284 Status_Phase:
285 /*
286 * Start status phase
287 * read in CSW
288 */
289 for (nretry = 0; nretry < SCSA2USB_STATUS_RETRIES; nretry++) {
290 rval = scsa2usb_handle_status_start(scsa2usbp, req);
291
292 if ((rval != USB_SUCCESS) &&
293 (req->bulk_completion_reason == USB_CR_STALL)) {
294 /*
295 * We ran into STALL condition here.
296 * If the condition cannot be cleared
297 * successfully, retry for limited times.
298 */
299 scsa2usbp->scsa2usb_pkt_state =
300 SCSA2USB_PKT_PROCESS_CSW;
301 } else {
302
303 break;
304 }
305 }
306
307 if (rval == USB_SUCCESS) {
308 /* process CSW */
309 rval = scsa2usb_handle_csw_result(scsa2usbp, req->bulk_data);
310 } else {
311 scsa2usb_bulk_only_handle_error(scsa2usbp, req);
312
313 return (TRAN_FATAL_ERROR);
314 }
315
316 SCSA2USB_FREE_BULK_REQ(req); /* free request */
317
318 if ((rval == USB_SUCCESS) && /* CSW was ok */
319 (scsa2usbp->scsa2usb_cur_pkt->pkt_reason == CMD_CMPLT) &&
320 (cmd->cmd_xfercount != 0) && /* more data to xfer */
321 !cmd->cmd_done) { /* we aren't done yet */
322 scsa2usb_setup_next_xfer(scsa2usbp, cmd);
323 goto Cmd_Phase;
324 }
325
326 return (rval == USB_SUCCESS ? TRAN_ACCEPT : TRAN_FATAL_ERROR);
327 }
328
329
330 /*
331 * scsa2usb_fill_in_cbw:
332 * Fill in a CBW request packet. This
333 * packet is transported to the device
334 */
335 static void
scsa2usb_fill_in_cbw(scsa2usb_state_t * scsa2usbp,scsa2usb_cmd_t * cmd,mblk_t * mp)336 scsa2usb_fill_in_cbw(scsa2usb_state_t *scsa2usbp,
337 scsa2usb_cmd_t *cmd, mblk_t *mp)
338 {
339 int i;
340 int len;
341 uchar_t dir, *cdb = (uchar_t *)(&cmd->cmd_cdb);
342
343 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
344
345 *mp->b_wptr++ = CBW_MSB(CBW_SIGNATURE); /* CBW Signature */;
346 *mp->b_wptr++ = CBW_MID1(CBW_SIGNATURE);
347 *mp->b_wptr++ = CBW_MID2(CBW_SIGNATURE);
348 *mp->b_wptr++ = CBW_LSB(CBW_SIGNATURE);
349 *mp->b_wptr++ = CBW_LSB(cmd->cmd_tag); /* CBW Tag */
350 *mp->b_wptr++ = CBW_MID2(cmd->cmd_tag);
351 *mp->b_wptr++ = CBW_MID1(cmd->cmd_tag);
352 *mp->b_wptr++ = CBW_MSB(cmd->cmd_tag);
353
354 dir = cmd->cmd_dir;
355 len = cmd->cmd_xfercount;
356 #ifdef SCSA2USB_BULK_ONLY_TEST
357 if (scsa2usb_test_case_2 && (cdb[0] == SCMD_READ_CAPACITY)) {
358 /* Host expects no data. The device wants data. Hn < Di */
359 scsa2usb_test_case_2 = len = 0;
360 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
361 "TEST 2: Hn < Di cdb: 0x%x len: 0x%x", cdb[0], len);
362 }
363
364 if (scsa2usb_test_case_3 && (cmd->cmd_dir == CBW_DIR_OUT)) {
365 /* Host expects no data. The device wants data. Hn < Do */
366 if (cdb[0] == SCMD_WRITE_G1) {
367 scsa2usb_test_case_3 = len = 0;
368 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
369 scsa2usbp->scsa2usb_log_handle,
370 "TEST 3: Hn < Do cdb: 0x%x len:%x", cdb[0], len);
371 }
372 }
373
374 if (scsa2usb_test_case_4 && (cdb[0] == SCMD_READ_G1)) {
375 cdb[0] = 0x5e;
376 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
377 "TEST 4: Hi > Dn: changed cdb to 0x%x", cdb[0]);
378 scsa2usb_test_case_4 = 0;
379 }
380
381 if (scsa2usb_test_case_7 && (cmd->cmd_cdb[0] == SCMD_READ_G1)) {
382 len -= 0x10;
383 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
384 "TEST 7: Hi < Di cdb: 0x%x len: 0x%x", cdb[0], len);
385 scsa2usb_test_case_7 = 0;
386 }
387
388 if (scsa2usb_test_case_8 && (cdb[0] == SCMD_READ_G1)) {
389 dir = (dir == CBW_DIR_IN) ? CBW_DIR_OUT : dir;
390 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
391 "TEST 8: Hi <> Do cdb: 0x%x dir: 0x%x", cdb[0], dir);
392 }
393
394 if (scsa2usb_test_case_9 && (cdb[0] == SCMD_WRITE_G1)) {
395 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
396 "TEST 9: Ho <> Di (%x)", cdb[0]);
397 cdb[SCSA2USB_LEN_0] = cdb[SCSA2USB_LEN_1] = 0;
398 scsa2usb_test_case_9 = 0;
399 }
400
401 if (scsa2usb_test_case_10 && (cdb[0] == SCMD_WRITE_G1)) {
402 dir = (dir == CBW_DIR_OUT) ? CBW_DIR_IN : dir;
403 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
404 "TEST 10: Ho <> Di cdb: 0x%x dir: 0x%x", cdb[0], dir);
405 }
406
407 /*
408 * This case occurs when the device intends to receive
409 * more data from the host than the host sends.
410 */
411 if (scsa2usb_test_case_13) {
412 if ((cdb[0] == SCMD_WRITE_G1) || (cdb[0] == SCMD_READ_G1)) {
413 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
414 scsa2usbp->scsa2usb_log_handle, "TEST 13: Ho < Do");
415
416 len -= 30;
417 scsa2usb_test_case_13 = 0;
418 }
419 }
420 #endif /* SCSA2USB_BULK_ONLY_TEST */
421
422 *mp->b_wptr++ = CBW_MSB(len); /* Transfer Length */
423 *mp->b_wptr++ = CBW_MID1(len);
424 *mp->b_wptr++ = CBW_MID2(len);
425 *mp->b_wptr++ = CBW_LSB(len);
426
427 *mp->b_wptr++ = dir; /* Transfer Direction */
428 *mp->b_wptr++ = cmd->cmd_pkt->pkt_address.a_lun; /* Lun # */
429 *mp->b_wptr++ = cmd->cmd_actual_len; /* CDB Len */
430
431 /* Copy the CDB out */
432 for (i = 0; i < CBW_CDB_LEN; i++) {
433 *mp->b_wptr++ = *cdb++;
434 }
435 #ifdef DUMP_CWB
436 {
437 int len = mp->b_wptr - mp->b_rptr;
438 char *buf;
439
440 int i;
441
442 cmn_err(CE_CONT, "CWB: len=%d\n", len);
443 buf = kmem_zalloc(512, KM_SLEEP);
444 for (i = 0; i < len; i++) {
445 sprintf(&buf[strlen(buf)], "%02x ", mp->b_rptr[i]);
446 }
447 cmn_err(CE_CONT, "%s\n", buf);
448 kmem_free(buf, 512);
449 }
450 #endif
451
452 }
453
454
455 /*
456 * scsa2usb_bulk_only_handle_error:
457 * handle transport errors and start recovery
458 */
459 static void
scsa2usb_bulk_only_handle_error(scsa2usb_state_t * scsa2usbp,usb_bulk_req_t * req)460 scsa2usb_bulk_only_handle_error(scsa2usb_state_t *scsa2usbp,
461 usb_bulk_req_t *req)
462 {
463 struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt;
464
465 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
466 "scsa2usb_bulk_only_handle_error: req = 0x%p, cr = 0x%x",
467 (void *)req, (req ? req->bulk_completion_reason : 0));
468
469 if (req) {
470 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
471
472 /* invoke reset recovery */
473 switch (req->bulk_completion_reason) {
474 case USB_CR_STALL:
475 if (pkt) {
476 pkt->pkt_reason = CMD_TRAN_ERR;
477 }
478 break;
479 case USB_CR_TIMEOUT:
480 if (pkt) {
481 pkt->pkt_reason = CMD_TIMEOUT;
482 pkt->pkt_statistics |= STAT_TIMEOUT;
483 }
484 break;
485 case USB_CR_DEV_NOT_RESP:
486 if (pkt) {
487 pkt->pkt_reason = CMD_DEV_GONE;
488 /* scsi_poll relies on this */
489 pkt->pkt_state = STATE_GOT_BUS;
490 }
491 break;
492 default:
493 if (pkt) {
494 pkt->pkt_reason = CMD_TRAN_ERR;
495 }
496 }
497 scsa2usb_bulk_only_reset_recovery(scsa2usbp);
498 }
499
500 SCSA2USB_FREE_BULK_REQ(req);
501 }
502
503
504 /*
505 * scsa2usb_handle_status_start:
506 * Receive status data
507 */
508 static int
scsa2usb_handle_status_start(scsa2usb_state_t * scsa2usbp,usb_bulk_req_t * req)509 scsa2usb_handle_status_start(scsa2usb_state_t *scsa2usbp,
510 usb_bulk_req_t *req)
511 {
512 int rval;
513
514 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
515 "scsa2usb_handle_status_start: req = 0x%p", (void *)req);
516
517 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
518
519 /* setup up for receiving CSW */
520 #ifdef SCSA2USB_BULK_ONLY_TEST
521 req->bulk_attributes = 0;
522 #else
523 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK;
524 #endif /* SCSA2USB_BULK_ONLY_TEST */
525 req->bulk_len = CSW_LEN;
526
527 SCSA2USB_FREE_MSG(req->bulk_data);
528 req->bulk_data = allocb_wait(req->bulk_len,
529 BPRI_LO, STR_NOSIG, NULL);
530
531 /* Issue the request */
532 mutex_exit(&scsa2usbp->scsa2usb_mutex);
533
534 ASSERT(req->bulk_timeout);
535 rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe, req,
536 USB_FLAGS_SLEEP);
537 mutex_enter(&scsa2usbp->scsa2usb_mutex);
538
539 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
540 "scsa2usb_handle_status_start: END rval = 0x%x", rval);
541
542 if (rval != USB_SUCCESS) {
543 if (scsa2usbp->scsa2usb_pkt_state == SCSA2USB_PKT_PROCESS_CSW) {
544 scsa2usb_bulk_only_reset_recovery(scsa2usbp);
545
546 return (rval);
547 }
548
549 if (req->bulk_completion_reason == USB_CR_STALL) {
550 (void) scsa2usb_clear_ept_stall(scsa2usbp,
551 scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress,
552 scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in");
553 }
554 }
555
556 return (rval);
557 }
558
559
560 /*
561 * scsa2usb_handle_csw_result:
562 * Handle status results
563 */
564 static int
scsa2usb_handle_csw_result(scsa2usb_state_t * scsa2usbp,mblk_t * data)565 scsa2usb_handle_csw_result(scsa2usb_state_t *scsa2usbp, mblk_t *data)
566 {
567 int rval = USB_SUCCESS;
568 int residue;
569 char *msg = "CSW FAILED";
570 uint_t signature, tag, status;
571 usb_bulk_csw_t csw;
572 struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt;
573 scsa2usb_cmd_t *cmd = PKT2CMD(pkt);
574
575 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
576
577 /*
578 * This shouldn't happen. It implies the device's
579 * firmware is bad and has returned NULL CSW.
580 * return failure back.
581 */
582 if (data == NULL) {
583 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
584 "scsa2usb_handle_csw_result: data == NULL");
585
586 return (USB_FAILURE);
587 }
588
589 /* check if we got back CSW_LEN or not */
590 if (MBLKL(data) != CSW_LEN) {
591 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
592 "scsa2usb_handle_csw_result: no enough data (%ld)",
593 (long)(MBLKL(data)));
594
595 return (USB_FAILURE);
596 }
597
598 /* Read into csw */
599 bcopy(data->b_rptr, &csw, CSW_LEN);
600
601 status = csw.csw_bCSWStatus;
602 signature = SCSA2USB_MK_32BIT(csw.csw_dCSWSignature3,
603 csw.csw_dCSWSignature2, csw.csw_dCSWSignature1,
604 csw.csw_dCSWSignature0);
605 residue = SCSA2USB_MK_32BIT(csw.csw_dCSWDataResidue3,
606 csw.csw_dCSWDataResidue2, csw.csw_dCSWDataResidue1,
607 csw.csw_dCSWDataResidue0);
608 tag = SCSA2USB_MK_32BIT(csw.csw_dCSWTag3, csw.csw_dCSWTag2,
609 csw.csw_dCSWTag1, csw.csw_dCSWTag0);
610
611 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
612 "CSW: Signature = 0x%x Status = 0%x Tag = 0x%x Residue = 0x%x",
613 signature, status, tag, residue);
614
615 /* Check for abnormal errors */
616 if ((signature != CSW_SIGNATURE) || (tag != cmd->cmd_tag) ||
617 (status > CSW_STATUS_PHASE_ERROR)) {
618
619 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
620 "CSW_ERR: Status = 0x%x, Tag = 0x%x xfercount = 0x%lx",
621 status, cmd->cmd_tag, cmd->cmd_total_xfercount);
622
623 return (USB_FAILURE);
624 }
625
626 switch (status) {
627 case CSW_STATUS_GOOD:
628 /*
629 * Fail the command if the device misbehaves and
630 * gives a good status but doesn't transfer any data.
631 * Otherwise we'll get into an infinite retry loop.
632 *
633 * We test only against cmd_total_xfercount here and
634 * assume that this will not happen on a command that
635 * transfers a large amount of data and therefore may
636 * be split into separate transfers. For a large data
637 * transfer it is assumed that the device will return
638 * an error status if the transfer does not occur.
639 * this isn't quite correct because a subsequent request
640 * sense may not give a valid sense key.
641 */
642 if (!cmd->cmd_done && residue &&
643 (residue == cmd->cmd_total_xfercount)) {
644 *(pkt->pkt_scbp) = STATUS_CHECK;
645 cmd->cmd_xfercount = 0;
646 cmd->cmd_done = 1;
647 } else {
648 msg = "CSW GOOD";
649 }
650 break;
651 case CSW_STATUS_FAILED:
652 *(pkt->pkt_scbp) = STATUS_CHECK; /* Set check condition */
653 cmd->cmd_done = 1;
654 break;
655 case CSW_STATUS_PHASE_ERROR:
656 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
657 "scsa2usb_handle_csw_result: Phase Error");
658
659 /* invoke reset recovery */
660 scsa2usb_bulk_only_handle_error(scsa2usbp, NULL);
661
662 return (USB_FAILURE);
663 default: /* shouldn't happen anymore */
664 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
665 "scsa2usb_handle_csw_result: Invalid CSW");
666
667 /* invoke reset recovery */
668 scsa2usb_bulk_only_handle_error(scsa2usbp, NULL);
669
670 return (USB_SUCCESS);
671 } /* end of switch */
672
673 /* Set resid */
674 if (residue || cmd->cmd_resid_xfercount) {
675 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
676 scsa2usbp->scsa2usb_log_handle,
677 "total=0x%lx cmd_xfercount=0x%lx residue=0x%x "
678 "cmd_offset=0x%lx",
679 cmd->cmd_total_xfercount, cmd->cmd_xfercount,
680 residue, cmd->cmd_offset);
681
682 /*
683 * we need to adjust using the residue and
684 * assume worst case. Some devices lie about
685 * residue. some report a residue greater than
686 * the residue we have calculated.
687 * first adjust back the total_xfercount
688 */
689 cmd->cmd_total_xfercount += cmd->cmd_xfercount -
690 cmd->cmd_resid_xfercount;
691 /*
692 * we need to adjust cmd_offset as well, or the data
693 * buffer for subsequent transfer may exceed the buffer
694 * boundary
695 */
696 cmd->cmd_offset -= cmd->cmd_xfercount -
697 cmd->cmd_resid_xfercount;
698
699 /*
700 * now take the min of the reported residue by
701 * the device and the requested xfer count
702 * (just in case the device reported a residue greater
703 * than our request count).
704 * then take the max of this residue and the residue
705 * that the HCD reported and subtract this from
706 * the request count. This is the actual number
707 * of valid bytes transferred during the last transfer
708 * which we now subtract from the total_xfercount
709 */
710 if ((!(scsa2usbp->scsa2usb_attrs &
711 SCSA2USB_ATTRS_USE_CSW_RESIDUE)) ||
712 (residue < 0) ||
713 (residue > cmd->cmd_total_xfercount)) {
714 /* some devices lie about the resid, ignore */
715 cmd->cmd_total_xfercount -=
716 cmd->cmd_xfercount - cmd->cmd_resid_xfercount;
717 cmd->cmd_offset +=
718 cmd->cmd_xfercount - cmd->cmd_resid_xfercount;
719 } else {
720 cmd->cmd_total_xfercount -=
721 cmd->cmd_xfercount -
722 max(min(residue, cmd->cmd_xfercount),
723 cmd->cmd_resid_xfercount);
724 cmd->cmd_offset +=
725 cmd->cmd_xfercount -
726 max(min(residue, cmd->cmd_xfercount),
727 cmd->cmd_resid_xfercount);
728 /*
729 * if HCD does not report residue while the device
730 * reports a residue equivalent to the xfercount,
731 * it is very likely the device lies about the
732 * residue. we need to stop the command, or we'll
733 * get into an infinite retry loop.
734 */
735 if ((cmd->cmd_resid_xfercount == 0) &&
736 (residue == cmd->cmd_xfercount)) {
737 cmd->cmd_xfercount = 0;
738 cmd->cmd_done = 1;
739 }
740 }
741
742 pkt->pkt_resid = cmd->cmd_total_xfercount;
743 }
744
745 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
746 "scsa2usb_handle_csw_result: %s, resid: 0x%lx",
747 msg, pkt->pkt_resid);
748
749 /* we are done and ready to callback */
750 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
751
752 return (rval);
753 }
754
755
756 /*
757 * scsa2usb_bulk_only_reset_recovery:
758 * Reset the USB device step-wise in case of errors.
759 * NOTE that the order of reset is very important.
760 */
761 static void
scsa2usb_bulk_only_reset_recovery(scsa2usb_state_t * scsa2usbp)762 scsa2usb_bulk_only_reset_recovery(scsa2usb_state_t *scsa2usbp)
763 {
764 int rval;
765 usb_cr_t completion_reason;
766 usb_cb_flags_t cb_flags;
767
768 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
769 "scsa2usb_bulk_only_reset_recovery: scsa2usbp = 0x%p",
770 (void *)scsa2usbp);
771
772 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
773
774 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
775
776 return;
777 }
778
779 /*
780 * assume that the reset will be successful. if it isn't, retrying
781 * from target driver won't help much
782 */
783 if (scsa2usbp->scsa2usb_cur_pkt) {
784 scsa2usbp->scsa2usb_cur_pkt->pkt_statistics |= STAT_DEV_RESET;
785 }
786
787 /* set the reset condition */
788 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_DEV_RESET;
789
790 /* Send a sync DEVICE-RESET request to the device */
791 mutex_exit(&scsa2usbp->scsa2usb_mutex);
792 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip,
793 scsa2usbp->scsa2usb_default_pipe,
794 USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF,
795 (uint8_t)BULK_ONLY_RESET, /* bRequest */
796 0, /* wValue */
797 scsa2usbp->scsa2usb_intfc_num, /* wIndex */
798 0, /* wLength */
799 NULL, 0, &completion_reason, &cb_flags, 0);
800 mutex_enter(&scsa2usbp->scsa2usb_mutex);
801
802 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
803 "\tbulk-only device-reset rval: %d", rval);
804 if (rval != USB_SUCCESS) {
805 goto exc_exit;
806 }
807
808 /* reset and clear STALL on bulk-in pipe */
809 rval = scsa2usb_clear_ept_stall(scsa2usbp,
810 scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress,
811 scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in");
812
813 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
814 "\tbulk-in pipe clear stall: %d", rval);
815 if (rval != USB_SUCCESS) {
816 goto exc_exit;
817 }
818
819 /* reset and clear STALL on bulk-out pipe */
820 rval = scsa2usb_clear_ept_stall(scsa2usbp,
821 scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress,
822 scsa2usbp->scsa2usb_bulkout_pipe, "bulk-out");
823
824 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
825 "\tbulk-out pipe clear stall: %d", rval);
826
827 exc_exit:
828 /* clear the reset condition */
829 scsa2usbp->scsa2usb_pipe_state &= ~SCSA2USB_PIPE_DEV_RESET;
830 }
831
832
833 /*
834 * scsa2usb_bulk_only_get_max_lun:
835 * this function returns the number of LUNs supported by the device
836 */
837 int
scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t * scsa2usbp)838 scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t *scsa2usbp)
839 {
840 int luns = 1, rval;
841 mblk_t *data = NULL;
842 usb_cr_t completion_reason;
843 usb_cb_flags_t cb_flags;
844
845 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
846 "scsa2usb_bulk_only_get_max_lun:");
847
848 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
849
850 mutex_exit(&scsa2usbp->scsa2usb_mutex);
851 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip,
852 scsa2usbp->scsa2usb_default_pipe,
853 BULK_ONLY_GET_MAXLUN_BMREQ, /* bmRequestType */
854 BULK_ONLY_GET_MAXLUN_REQ, /* bRequest */
855 0, /* wValue */
856 scsa2usbp->scsa2usb_intfc_num, /* wIndex */
857 1, /* wLength */
858 &data, 0,
859 &completion_reason, &cb_flags, 0);
860 mutex_enter(&scsa2usbp->scsa2usb_mutex);
861
862 if (rval != USB_SUCCESS) {
863 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
864 "get max lun failed, rval=%d cr=%d cb=0x%x data=0x%p",
865 rval, completion_reason, cb_flags, (void *)data);
866 } else {
867 /*
868 * This check ensures that we have valid data returned back.
869 * Otherwise we assume that device supports only one LUN.
870 */
871 if (MBLKL(data) != 1) {
872 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
873 scsa2usbp->scsa2usb_log_handle,
874 "device reported incorrect luns (adjusting to 1)");
875 } else {
876 /*
877 * Set scsa2usb_n_luns to value returned by the device
878 * plus 1. (See Section 3.2)
879 */
880 luns = *data->b_rptr + 1;
881
882 /*
883 * In case a device returns incorrect LUNs
884 * which are more than 15 or negative or 0;
885 * we assume 1.
886 */
887 if ((luns >= SCSA2USB_MAX_LUNS) || (luns <= 0)) {
888 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
889 scsa2usbp->scsa2usb_log_handle,
890 "device reported %d luns "
891 "(adjusting to 1)", luns);
892 luns = 1;
893 }
894 }
895 }
896
897 SCSA2USB_FREE_MSG(data); /* Free data */
898
899 return (luns);
900 }
901