xref: /titanic_41/usr/src/uts/common/io/usb/scsa2usb/usb_ms_bulkonly.c (revision b5a2ac7ba0468b52b8540a247a7d814628284290)
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