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 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 /* 28 * scsa2usb_ms_cbi.c: 29 * 30 * This file implements USB Mass Storage Class 31 * Control Bulk Interrupt (CB/CBI) transport v1.0 32 * http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf 33 */ 34 #include <sys/usb/usba/usbai_version.h> 35 #include <sys/scsi/scsi.h> 36 #include <sys/callb.h> /* needed by scsa2usb.h */ 37 #include <sys/strsubr.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_cbi.h> 44 #include <sys/usb/scsa2usb/scsa2usb.h> 45 46 /* 47 * Function Prototypes 48 */ 49 int scsa2usb_cbi_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 50 static int scsa2usb_handle_cbi_status(usb_intr_req_t *); 51 static void scsa2usb_cbi_reset_recovery(scsa2usb_state_t *); 52 static void scsa2usb_cbi_handle_error(scsa2usb_state_t *, int, usb_cr_t); 53 static usb_intr_req_t *scsa2usb_cbi_start_intr_polling(scsa2usb_state_t *); 54 void scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *); 55 56 /* extern functions */ 57 extern void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *); 58 extern int scsa2usb_handle_data_start(scsa2usb_state_t *, 59 scsa2usb_cmd_t *, usb_bulk_req_t *); 60 extern void scsa2usb_handle_data_done(scsa2usb_state_t *, scsa2usb_cmd_t *, 61 usb_bulk_req_t *); 62 extern usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *, 63 size_t, uint_t, usb_req_attrs_t, usb_flags_t); 64 extern int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t, 65 usb_pipe_handle_t, char *); 66 extern void scsa2usb_close_usb_pipes(scsa2usb_state_t *); 67 68 #ifdef DEBUG /* debugging information */ 69 extern void scsa2usb_print_cdb(scsa2usb_state_t *, scsa2usb_cmd_t *); 70 #endif /* DEBUG */ 71 72 73 /* 74 * scsa2usb_cbi_transport: 75 * Implements the CB/CBI state machine by these steps: 76 * a) Issues command to the device over control pipe. 77 * b) Start Data Phase if applicable 78 * c) Start Status Phase 79 * 80 * returns TRAN_* values and not USB_SUCCESS/FAILURE 81 * 82 * scsa2usb_cbi_transport() handles the normal transitions or 83 * continuation after clearing stalls or error recovery. 84 * 85 * Command Phase: 86 * prepare a valid command and transport it on default pipe 87 * if error on default-pipe: 88 * set pkt_reason to CMD_TRAN_ERR 89 * new pkt state is SCSA2USB_PKT_DO_COMP 90 * do reset recovery synchronously 91 * else 92 * proceed to data phase 93 * 94 * Data Phase: 95 * if data in: 96 * setup data in on bulkin 97 * else if data out: 98 * setup data out on bulkout 99 * 100 * data: (in) 101 * copy data transferred so far, no more data to transfer 102 * 103 * if stall on bulkin pipe 104 * terminate data transfers, set cmd_done 105 * clear stall on bulkin syncrhonously 106 * else if other exception 107 * set pkt_reason to CMD_TRAN_ERR 108 * new pkt state is SCSA2USB_PKT_DO_COMP 109 * do reset recovery synchronously 110 * else (no error) 111 * receive status 112 * 113 * data: (out) 114 * if stall on bulkout pipe 115 * terminate data transfers 116 * clear stall on bulkout synchronously USBA 117 * else if other exception 118 * set pkt_reason to CMD_TRAN_ERR 119 * new pkt state is SCSA2USB_PKT_DO_COMP 120 * do reset recovery synchronously 121 * else (no error) 122 * receive status 123 * 124 * Status Phase: (on Interrupt pipe for CBI devices only) 125 * if error 126 * if stall 127 * new pkt state is SCSA2USB_PKT_DO_COMP 128 * clear stall on interrupt pipe 129 * else 130 * set pkt_reason to CMD_TRAN_ERR 131 * new pkt state is SCSA2USB_PKT_DO_COMP 132 * do reset recovery synchronously 133 * else (no error) 134 * goto read status 135 * 136 * read status: 137 * if not OK or phase error 138 * new pkt state is SCSA2USB_PKT_DO_COMP 139 * set pkt reason CMD_TRAN_ERR 140 * reset recovery synchronously 141 * else (status ok) 142 * goto SCSA2USB_PKT_DO_COMP 143 * 144 * The reset recovery walks sequentially thru device reset, clearing 145 * stalls and pipe resets. When the reset recovery completes we return 146 * to the taskq thread. 147 * 148 * Clearing stalls clears the stall condition, resets the pipe, and 149 * then returns to the transport. 150 */ 151 int 152 scsa2usb_cbi_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 153 { 154 int i, rval = TRAN_ACCEPT; 155 mblk_t *data; 156 usb_cr_t completion_reason; 157 usb_cb_flags_t cb_flags; 158 usb_bulk_req_t *data_req; 159 usb_intr_req_t *status_req; 160 161 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 162 "scsa2usb_cbi_transport: cmd = 0x%p", (void *)cmd); 163 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 164 165 Cmd_Phase: 166 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 167 168 return (TRAN_FATAL_ERROR); 169 } 170 171 /* 172 * Start command phase (C - in CBI) 173 */ 174 data = allocb_wait(CBI_CLASS_CMD_LEN, BPRI_LO, STR_NOSIG, NULL); 175 176 /* Initialize the data */ 177 for (i = 0; i < CBI_CLASS_CMD_LEN; i++) { 178 *data->b_wptr++ = cmd->cmd_cdb[i]; 179 } 180 181 SCSA2USB_PRINT_CDB(scsa2usbp, cmd); /* print the CDB */ 182 183 /* Send the Command to the device */ 184 mutex_exit(&scsa2usbp->scsa2usb_mutex); 185 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip, 186 scsa2usbp->scsa2usb_default_pipe, 187 CBI_REQUEST_TYPE, /* bmRequestType */ 188 0, /* bRequest */ 189 CBI_WVALUE, /* wValue */ 190 scsa2usbp->scsa2usb_intfc_num, /* wIndex */ 191 CBI_CLASS_CMD_LEN, /* wLength */ 192 &data, /* data */ 193 USB_ATTRS_PIPE_RESET, /* attributes */ 194 &completion_reason, &cb_flags, USB_FLAGS_SLEEP); 195 mutex_enter(&scsa2usbp->scsa2usb_mutex); 196 197 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 198 "scsa2usb_cbi_transport: sent cmd = 0x%x rval = %d", 199 cmd->cmd_cdb[SCSA2USB_OPCODE], rval); 200 201 SCSA2USB_FREE_MSG(data); /* get rid of the data */ 202 if (rval != USB_SUCCESS) { 203 scsa2usb_cbi_handle_error(scsa2usbp, rval, completion_reason); 204 205 return (TRAN_FATAL_ERROR); 206 } 207 208 /* 209 * Xferred command to the device. 210 * Start data phase (B - in CBI) 211 */ 212 213 /* 214 * we've not transferred any data yet; updated in 215 * scsa2usb_handle_data_done 216 */ 217 cmd->cmd_resid_xfercount = 0; 218 219 /* if data to be xferred ? */ 220 if (cmd->cmd_xfercount) { 221 222 /* Initialize a bulk_req_t */ 223 data_req = scsa2usb_init_bulk_req(scsa2usbp, 0, 224 cmd->cmd_timeout, USB_ATTRS_PIPE_RESET, USB_FLAGS_SLEEP); 225 226 /* start I/O to/from the device */ 227 rval = scsa2usb_handle_data_start(scsa2usbp, cmd, 228 data_req); 229 /* handle data returned */ 230 scsa2usb_handle_data_done(scsa2usbp, cmd, 231 data_req); 232 if (rval != USB_SUCCESS) { 233 /* 234 * we ran into an error and it wasn't a STALL 235 */ 236 if (data_req->bulk_completion_reason == USB_CR_STALL) { 237 if (scsa2usbp->scsa2usb_cur_pkt) { 238 scsa2usbp->scsa2usb_cur_pkt-> 239 pkt_reason = CMD_TRAN_ERR; 240 } 241 } else { 242 scsa2usb_cbi_handle_error(scsa2usbp, 243 rval, data_req->bulk_completion_reason); 244 245 /* get rid of req */ 246 SCSA2USB_FREE_BULK_REQ(data_req); 247 248 return (TRAN_FATAL_ERROR); 249 } 250 } 251 252 SCSA2USB_FREE_BULK_REQ(data_req); /* get rid of bulk_req */ 253 } 254 255 /* CB devices don't do status over interrupt pipe */ 256 if (SCSA2USB_IS_CB(scsa2usbp)) { 257 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 258 "scsa2usb_cbi_transport: CB done rval = %d", rval); 259 goto end_it; 260 } 261 262 /* 263 * Start status phase (I - in CBI) 264 */ 265 266 /* Get Status over interrupt pipe */ 267 if ((status_req = scsa2usb_cbi_start_intr_polling(scsa2usbp)) == NULL) { 268 269 return (TRAN_FATAL_ERROR); /* lack of better return code */ 270 } 271 272 rval = scsa2usb_handle_cbi_status(status_req); 273 274 usb_free_intr_req(status_req); 275 276 /* stop interrupt pipe polling (CBI only) */ 277 if (SCSA2USB_IS_CBI(scsa2usbp)) { 278 scsa2usb_cbi_stop_intr_polling(scsa2usbp); 279 } 280 281 end_it: 282 if ((rval == USB_SUCCESS) && /* CSW was ok */ 283 (scsa2usbp->scsa2usb_cur_pkt->pkt_reason == CMD_CMPLT) && 284 (cmd->cmd_xfercount != 0) && /* more data to xfer */ 285 !cmd->cmd_done) { /* we aren't done yet */ 286 scsa2usb_setup_next_xfer(scsa2usbp, cmd); 287 goto Cmd_Phase; 288 } else { 289 if (SCSA2USB_IS_CB(scsa2usbp)) { 290 cmd->cmd_done = 1; 291 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 292 } 293 } 294 295 return (rval == USB_SUCCESS ? TRAN_ACCEPT : TRAN_FATAL_ERROR); 296 } 297 298 299 /* 300 * scsa2usb_cbi_handle_error: 301 * handle errors from transport that are not STALL conditions 302 */ 303 static void 304 scsa2usb_cbi_handle_error(scsa2usb_state_t *scsa2usbp, int rval, usb_cr_t cr) 305 { 306 struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt; 307 308 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 309 "scsa2usb_cbi_handle_error: data error %d cr = %d", rval, cr); 310 311 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 312 313 /* do reset error recovery */ 314 switch (cr) { 315 case USB_CR_STALL: 316 if (pkt) { 317 pkt->pkt_reason = CMD_TRAN_ERR; 318 *(pkt->pkt_scbp) = STATUS_CHECK; 319 } 320 break; 321 case USB_CR_TIMEOUT: 322 if (pkt) { 323 pkt->pkt_reason = CMD_TIMEOUT; 324 pkt->pkt_statistics |= STAT_TIMEOUT; 325 } 326 break; 327 case USB_CR_DEV_NOT_RESP: 328 scsa2usb_cbi_stop_intr_polling(scsa2usbp); 329 if (pkt) { 330 pkt->pkt_reason = CMD_DEV_GONE; 331 /* scsi_poll relies on this */ 332 pkt->pkt_state = STATE_GOT_BUS; 333 } 334 break; 335 default: 336 if (pkt) { 337 pkt->pkt_reason = CMD_TRAN_ERR; 338 } 339 scsa2usb_cbi_reset_recovery(scsa2usbp); 340 } 341 } 342 343 344 /* 345 * scsa2usb_cbi_start_intr_polling: 346 * start polling asynchronously without notification 347 */ 348 static usb_intr_req_t * 349 scsa2usb_cbi_start_intr_polling(scsa2usb_state_t *scsa2usbp) 350 { 351 int rval; 352 usb_pipe_state_t pipe_state; 353 usb_intr_req_t *req = NULL; 354 355 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 356 "scsa2usb_cbi_start_intr_polling:"); 357 358 if (!SCSA2USB_IS_CBI(scsa2usbp)) { 359 360 return (NULL); 361 } 362 363 req = usb_alloc_intr_req(scsa2usbp->scsa2usb_dip, 0, USB_FLAGS_SLEEP); 364 req->intr_client_private = (usb_opaque_t)scsa2usbp; 365 req->intr_attributes = USB_ATTRS_ONE_XFER | USB_ATTRS_PIPE_RESET | 366 USB_ATTRS_SHORT_XFER_OK; 367 req->intr_len = scsa2usbp->scsa2usb_intr_ept.wMaxPacketSize; 368 req->intr_timeout = 20; /* arbitrary large for now */ 369 mutex_exit(&scsa2usbp->scsa2usb_mutex); 370 371 if ((rval = usb_pipe_intr_xfer(scsa2usbp->scsa2usb_intr_pipe, req, 372 USB_FLAGS_SLEEP)) != USB_SUCCESS) { 373 mutex_enter(&scsa2usbp->scsa2usb_mutex); 374 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 375 "polling failed rval: %d", rval); 376 377 /* clear stall */ 378 if (req->intr_completion_reason == USB_CR_STALL) { 379 (void) scsa2usb_clear_ept_stall(scsa2usbp, 380 scsa2usbp->scsa2usb_intr_ept.bEndpointAddress, 381 scsa2usbp->scsa2usb_intr_pipe, "intr"); 382 } 383 384 /* handle other errors here */ 385 scsa2usb_cbi_handle_error(scsa2usbp, rval, 386 req->intr_completion_reason); 387 mutex_exit(&scsa2usbp->scsa2usb_mutex); 388 389 usb_free_intr_req(req); 390 req = NULL; 391 } 392 393 rval = usb_pipe_get_state(scsa2usbp->scsa2usb_intr_pipe, 394 &pipe_state, USB_FLAGS_SLEEP); 395 if (pipe_state != USB_PIPE_STATE_ACTIVE) { 396 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 397 "intr pipes state: %d, rval: %d", pipe_state, rval); 398 } 399 mutex_enter(&scsa2usbp->scsa2usb_mutex); 400 401 return (req); 402 } 403 404 405 /* 406 * scsa2usb_cbi_stop_intr_polling: 407 * Stop polling on interrupt pipe (for status) 408 */ 409 void 410 scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *scsa2usbp) 411 { 412 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 413 "scsa2usb_cbi_stop_intr_polling:"); 414 415 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 416 417 if (!SCSA2USB_IS_CBI(scsa2usbp)) { 418 419 return; 420 } 421 422 if (scsa2usbp->scsa2usb_intr_pipe) { 423 mutex_exit(&scsa2usbp->scsa2usb_mutex); 424 usb_pipe_stop_intr_polling(scsa2usbp->scsa2usb_intr_pipe, 425 USB_FLAGS_SLEEP); 426 mutex_enter(&scsa2usbp->scsa2usb_mutex); 427 } 428 } 429 430 431 /* 432 * scsa2usb_handle_cbi_status: 433 * Handle CBI status results 434 */ 435 static int 436 scsa2usb_handle_cbi_status(usb_intr_req_t *req) 437 { 438 int rval = USB_SUCCESS; 439 int status; 440 char *msg; 441 scsa2usb_cmd_t *cmd; 442 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 443 req->intr_client_private; 444 445 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 446 "scsa2usb_handle_cbi_status: req: 0x%p", (void *)req); 447 448 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 449 ASSERT(req->intr_data != NULL); 450 451 cmd = PKT2CMD(scsa2usbp->scsa2usb_cur_pkt); 452 status = *(req->intr_data->b_rptr + 1) & CBI_STATUS_MASK; 453 454 /* 455 * CBI status contains ASC and ASCQ. 456 * SCMD_REQUEST_SENSE and SCMD_INQUIRY don't affect the sense data 457 * on CBI devices. So, we can ignore that info for these 2 commands. 458 * 459 * (See details in UFI spec section 3.5 - that says that INQUIRY, 460 * SEND_DIAG, and REQUEST_SENSE ought to be supported by any deivce 461 * irrespective). 462 */ 463 if ((cmd->cmd_cdb[SCSA2USB_OPCODE] == SCMD_REQUEST_SENSE) || 464 (cmd->cmd_cdb[SCSA2USB_OPCODE] == SCMD_INQUIRY)) { 465 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 466 "scsa2usb_handle_cbi_status: CBI STATUS = (0x%x, 0x%x)", 467 *(req->intr_data->b_rptr), *(req->intr_data->b_rptr+1)); 468 469 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 470 471 return (USB_SUCCESS); 472 } 473 474 switch (status) { 475 case CBI_STATUS_PASS: 476 msg = "PASSED"; 477 /* non-zero command completion interrupt */ 478 if (*(req->intr_data->b_rptr)) { 479 *(scsa2usbp->scsa2usb_cur_pkt->pkt_scbp) = STATUS_CHECK; 480 cmd->cmd_done = 1; 481 } 482 break; 483 case CBI_STATUS_FAILED: 484 case CBI_STATUS_PERSISTENT_FAIL: 485 msg = (status == CBI_STATUS_PERSISTENT_FAIL) ? 486 "PERSISTENT_FAILURE" : "FAILED"; 487 *(scsa2usbp->scsa2usb_cur_pkt->pkt_scbp) = STATUS_CHECK; 488 cmd->cmd_done = 1; 489 break; 490 case CBI_STATUS_PHASE_ERR: 491 msg = "PHASE_ERR"; 492 scsa2usb_cbi_reset_recovery(scsa2usbp); 493 rval = USB_FAILURE; 494 break; 495 } 496 497 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 498 "CBI STATUS = 0x%x %s (0x%x, 0x%x)", status, msg, 499 *(req->intr_data->b_rptr), *(req->intr_data->b_rptr+1)); 500 501 /* we are done and ready to callback */ 502 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 503 504 return (rval); 505 } 506 507 508 /* 509 * scsa2usb_cbi_reset_recovery: 510 * Reset the USB device in case of errors. 511 */ 512 static void 513 scsa2usb_cbi_reset_recovery(scsa2usb_state_t *scsa2usbp) 514 { 515 int i, rval; 516 mblk_t *cdb; 517 usb_cr_t completion_reason; 518 usb_cb_flags_t cb_flags; 519 520 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 521 "scsa2usb_cbi_reset_recovery: (0x%p)", (void *)scsa2usbp); 522 523 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 524 525 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 526 527 return; 528 } 529 530 if (scsa2usbp->scsa2usb_cur_pkt) { 531 scsa2usbp->scsa2usb_cur_pkt->pkt_statistics |= STAT_DEV_RESET; 532 } 533 534 /* Allocate an mblk for CBR */ 535 cdb = allocb_wait(CBI_CLASS_CMD_LEN, BPRI_LO, STR_NOSIG, NULL); 536 537 *cdb->b_wptr++ = SCMD_SDIAG; /* Set it to DIAG */ 538 *cdb->b_wptr++ = CBI_SELF_TEST; /* Set it to reset */ 539 for (i = 2; i < CBI_CLASS_CMD_LEN; i++) { 540 *cdb->b_wptr++ = CBI_CBR_VALUE; /* Set it to 0xff */ 541 } 542 543 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_DEV_RESET; 544 545 /* 546 * Send a Reset request to the device 547 */ 548 mutex_exit(&scsa2usbp->scsa2usb_mutex); 549 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip, 550 scsa2usbp->scsa2usb_default_pipe, 551 CBI_REQUEST_TYPE, /* bmRequestType */ 552 0, /* bRequest */ 553 CBI_WVALUE, /* wValue */ 554 scsa2usbp->scsa2usb_intfc_num, /* wIndex address */ 555 CBI_CLASS_CMD_LEN, /* wLength */ 556 &cdb, /* data to be sent */ 557 0, &completion_reason, &cb_flags, 0); 558 mutex_enter(&scsa2usbp->scsa2usb_mutex); 559 560 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 561 "\tCBI RESET: rval = %x cr = %x", rval, completion_reason); 562 if (rval != USB_SUCCESS) { 563 goto exc_exit; 564 } 565 566 /* reset and clear STALL on bulk-in pipe */ 567 rval = scsa2usb_clear_ept_stall(scsa2usbp, 568 scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress, 569 scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in"); 570 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 571 "\tclear stall on bulk-in pipe: %d", rval); 572 if (rval != USB_SUCCESS) { 573 goto exc_exit; 574 } 575 576 /* reset and clear STALL on bulk-out pipe */ 577 rval = scsa2usb_clear_ept_stall(scsa2usbp, 578 scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress, 579 scsa2usbp->scsa2usb_bulkout_pipe, "bulk-out"); 580 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 581 "\tclear stall on bulk-out pipe: %d", rval); 582 if (rval != USB_SUCCESS) { 583 goto exc_exit; 584 } 585 586 /* reset and clear STALL on interrupt pipe */ 587 if (SCSA2USB_IS_CBI(scsa2usbp)) { 588 rval = scsa2usb_clear_ept_stall(scsa2usbp, 589 scsa2usbp->scsa2usb_intr_ept.bEndpointAddress, 590 scsa2usbp->scsa2usb_intr_pipe, "intr"); 591 592 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 593 "\tclear stall on intr pipe: %d", rval); 594 } 595 596 exc_exit: 597 SCSA2USB_FREE_MSG(cdb); /* Free the data */ 598 scsa2usbp->scsa2usb_pipe_state &= ~SCSA2USB_PIPE_DEV_RESET; 599 } 600