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