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