1 #include <sys/cdefs.h> 2 __FBSDID("$FreeBSD$"); 3 4 /*- 5 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 6 * 7 * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, 8 * Nick Hibma <n_hibma@FreeBSD.org> 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD$ 33 * $NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $ 34 */ 35 36 /* Also already merged from NetBSD: 37 * $NetBSD: umass.c,v 1.67 2001/11/25 19:05:22 augustss Exp $ 38 * $NetBSD: umass.c,v 1.90 2002/11/04 19:17:33 pooka Exp $ 39 * $NetBSD: umass.c,v 1.108 2003/11/07 17:03:25 wiz Exp $ 40 * $NetBSD: umass.c,v 1.109 2003/12/04 13:57:31 keihan Exp $ 41 */ 42 43 /* 44 * Universal Serial Bus Mass Storage Class specs: 45 * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf 46 * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf 47 * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf 48 * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf 49 */ 50 51 /* 52 * Ported to NetBSD by Lennart Augustsson <augustss@NetBSD.org>. 53 * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>. 54 */ 55 56 /* 57 * The driver handles 3 Wire Protocols 58 * - Command/Bulk/Interrupt (CBI) 59 * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI) 60 * - Mass Storage Bulk-Only (BBB) 61 * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases) 62 * 63 * Over these wire protocols it handles the following command protocols 64 * - SCSI 65 * - UFI (floppy command set) 66 * - 8070i (ATAPI) 67 * 68 * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The 69 * sc->sc_transform method is used to convert the commands into the appropriate 70 * format (if at all necessary). For example, UFI requires all commands to be 71 * 12 bytes in length amongst other things. 72 * 73 * The source code below is marked and can be split into a number of pieces 74 * (in this order): 75 * 76 * - probe/attach/detach 77 * - generic transfer routines 78 * - BBB 79 * - CBI 80 * - CBI_I (in addition to functions from CBI) 81 * - CAM (Common Access Method) 82 * - SCSI 83 * - UFI 84 * - 8070i (ATAPI) 85 * 86 * The protocols are implemented using a state machine, for the transfers as 87 * well as for the resets. The state machine is contained in umass_t_*_callback. 88 * The state machine is started through either umass_command_start() or 89 * umass_reset(). 90 * 91 * The reason for doing this is a) CAM performs a lot better this way and b) it 92 * avoids using tsleep from interrupt context (for example after a failed 93 * transfer). 94 */ 95 96 /* 97 * The SCSI related part of this driver has been derived from the 98 * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@FreeBSD.org). 99 * 100 * The CAM layer uses so called actions which are messages sent to the host 101 * adapter for completion. The actions come in through umass_cam_action. The 102 * appropriate block of routines is called depending on the transport protocol 103 * in use. When the transfer has finished, these routines call 104 * umass_cam_cb again to complete the CAM command. 105 */ 106 107 #include <driver.h> 108 #include <disk.h> 109 110 #include "implementation/global_implementation.h" 111 #include "scsi_all.h" 112 #include "scsi.h" 113 #if USB_HAVE_DEVICE_TOPOLOGY 114 #include "implementation/usb_btree.h" 115 #endif 116 #include "user_copy.h" 117 118 #ifdef LOSCFG_USB_DEBUG 119 #define DIF(m, x) \ 120 do { \ 121 if (umass_debug & (m)) { x ; } \ 122 } while (0) 123 124 #define DPRINTF_UMASS(sc, m, fmt, ...) \ 125 do { \ 126 if (umass_debug & (m)) { \ 127 PRINTK("%s:%s: " fmt, \ 128 (sc) ? (const char *)(sc)->sc_name : \ 129 (const char *)"umassX", \ 130 __FUNCTION__ ,## __VA_ARGS__); \ 131 } \ 132 } while (0) 133 134 #define UDMASS_GEN 0x00010000 /* general */ 135 #define UDMASS_SCSI 0x00020000 /* scsi */ 136 #define UDMASS_UFI 0x00040000 /* ufi command set */ 137 #define UDMASS_ATAPI 0x00080000 /* 8070i command set */ 138 #define UDMASS_CMD (UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI) 139 #define UDMASS_USB 0x00100000 /* USB general */ 140 #define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ 141 #define UDMASS_CBI 0x00400000 /* CBI transfers */ 142 #define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI) 143 #define UDMASS_ALL 0xffff0000 /* all of the above */ 144 static int umass_debug = 0; /* UDMASS_ALL; */ 145 static int umass_throttle; 146 147 void 148 umass_debug_func(int level) 149 { 150 switch(level) { 151 case 0: 152 umass_debug = 0; 153 PRINTK("Close the umass debug\n"); 154 break; 155 case UDMASS_GEN: 156 case UDMASS_SCSI: 157 case UDMASS_UFI: 158 case UDMASS_ATAPI: 159 case UDMASS_CMD: 160 case UDMASS_USB: 161 case UDMASS_BBB: 162 case UDMASS_CBI: 163 case UDMASS_WIRE: 164 case UDMASS_ALL: 165 umass_debug = level; 166 PRINTK("The level of umass debug is %x\n", level); 167 break; 168 default: 169 PRINT_ERR("The level of umass debug is invalid, please refer to umass.c\n"); 170 break; 171 } 172 } 173 DEBUG_MODULE(umass, umass_debug_func); 174 #else 175 #define DIF(...) do { } while (0) 176 #define DPRINTF_UMASS(...) do { } while (0) 177 #endif 178 179 #define UMASS_BULK_SIZE (1 << 17) 180 #define UMASS_CBI_DIAGNOSTIC_CMDLEN 12 /* bytes */ 181 #define UMASS_MAX_CMDLEN MAX(12, CBWCDBLENGTH) /* bytes */ 182 183 /* USB transfer definitions */ 184 185 #define UMASS_T_BBB_RESET1 0 /* Bulk-Only */ 186 #define UMASS_T_BBB_RESET2 1 187 #define UMASS_T_BBB_RESET3 2 188 #define UMASS_T_BBB_COMMAND 3 189 #define UMASS_T_BBB_DATA_READ 4 190 #define UMASS_T_BBB_DATA_RD_CS 5 191 #define UMASS_T_BBB_DATA_WRITE 6 192 #define UMASS_T_BBB_DATA_WR_CS 7 193 #define UMASS_T_BBB_STATUS 8 194 #define UMASS_T_BBB_MAX 9 195 196 #define UMASS_T_CBI_RESET1 0 /* CBI */ 197 #define UMASS_T_CBI_RESET2 1 198 #define UMASS_T_CBI_RESET3 2 199 #define UMASS_T_CBI_COMMAND 3 200 #define UMASS_T_CBI_DATA_READ 4 201 #define UMASS_T_CBI_DATA_RD_CS 5 202 #define UMASS_T_CBI_DATA_WRITE 6 203 #define UMASS_T_CBI_DATA_WR_CS 7 204 #define UMASS_T_CBI_STATUS 8 205 #define UMASS_T_CBI_RESET4 9 206 #define UMASS_T_CBI_MAX 10 207 208 #define UMASS_T_MAX MAX(UMASS_T_CBI_MAX, UMASS_T_BBB_MAX) 209 210 /* Generic definitions */ 211 212 /* Direction for transfer */ 213 #define DIR_NONE 0 214 #define DIR_IN 1 215 #define DIR_OUT 2 216 217 /* device name */ 218 #define DEVNAME "umass" 219 #define DEVNAME_SIM "umass-sim" 220 221 /* Approximate maximum transfer speeds (assumes 33% overhead). */ 222 #define UMASS_FULL_TRANSFER_SPEED 1000 223 #define UMASS_HIGH_TRANSFER_SPEED 40000 224 #define UMASS_SUPER_TRANSFER_SPEED 400000 225 #define UMASS_FLOPPY_TRANSFER_SPEED 20 226 227 #define UMASS_TIMEOUT 20000 /* ms */ 228 229 /* CAM specific definitions */ 230 #define UMASS_SCSIID_MAX 1 /* maximum number of drives expected */ 231 #define UMASS_SCSIID_HOST UMASS_SCSIID_MAX 232 233 /* Bulk-Only features */ 234 #define UR_BBB_RESET 0xff /* Bulk-Only reset */ 235 #define UR_BBB_GET_MAX_LUN 0xfe /* Get maximum lun */ 236 237 #define UMASS_ATTACH_PRENAME "/dev/sd" 238 #define MASS_NAME 10 239 #define MAX_DEVICE 5 240 241 /* 242 * SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO 243 * function codes. 244 */ 245 struct ccb_scsiio { 246 uint8_t *data_ptr; /* Ptr to the data buf/SG list */ 247 uint32_t dxfer_len; /* Data transfer length */ 248 uint32_t resid; /* Transfer residual length: 2's comp */ 249 int32_t status; 250 251 struct scsi_sense_data sense_data; 252 uint8_t sense_len; /* Number of bytes to autosense */ 253 }; 254 255 union ccb { 256 struct ccb_scsiio csio; 257 }; 258 259 260 /* Command Block Wrapper */ 261 typedef struct { 262 uDWord dCBWSignature; 263 #define CBWSIGNATURE 0x43425355 264 uDWord dCBWTag; 265 uDWord dCBWDataTransferLength; 266 uByte bCBWFlags; 267 #define CBWFLAGS_OUT 0x00 268 #define CBWFLAGS_IN 0x80 269 uByte bCBWLUN; 270 uByte bCDBLength; 271 #define CBWCDBLENGTH 16 272 uByte CBWCDB[CBWCDBLENGTH]; 273 } __packed umass_bbb_cbw_t; 274 275 #define UMASS_BBB_CBW_SIZE 31 276 277 /* Command Status Wrapper */ 278 typedef struct { 279 uDWord dCSWSignature; 280 #define CSWSIGNATURE 0x53425355 281 #define CSWSIGNATURE_IMAGINATION_DBX1 0x43425355 282 #define CSWSIGNATURE_OLYMPUS_C1 0x55425355 283 uDWord dCSWTag; 284 uDWord dCSWDataResidue; 285 uByte bCSWStatus; 286 #define CSWSTATUS_GOOD 0x0 287 #define CSWSTATUS_FAILED 0x1 288 #define CSWSTATUS_PHASE 0x2 289 } __packed umass_bbb_csw_t; 290 291 #define UMASS_BBB_CSW_SIZE 13 292 293 /* CBI features */ 294 295 #define UR_CBI_ADSC 0x00 296 297 typedef union { 298 struct { 299 uint8_t type; 300 #define IDB_TYPE_CCI 0x00 301 uint8_t value; 302 #define IDB_VALUE_PASS 0x00 303 #define IDB_VALUE_FAIL 0x01 304 #define IDB_VALUE_PHASE 0x02 305 #define IDB_VALUE_PERSISTENT 0x03 306 #define IDB_VALUE_STATUS_MASK 0x03 307 } __packed common; 308 309 struct { 310 uint8_t asc; 311 uint8_t ascq; 312 } __packed ufi; 313 } __packed umass_cbi_sbl_t; 314 315 struct umass_info { 316 uint32_t sectorsize; 317 uint64_t sectornum; 318 }; 319 320 struct umass_softc; /* see below */ 321 322 typedef void (umass_callback_t)(struct umass_softc *sc, union ccb *ccb, 323 uint32_t residue, uint8_t status); 324 325 #define STATUS_CMD_OK 0 /* everything ok */ 326 #define STATUS_CMD_UNKNOWN 1 /* will have to fetch sense */ 327 #define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ 328 #define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ 329 330 typedef uint8_t (umass_transform_t)(struct umass_softc *sc, uint8_t *cmd_ptr, 331 uint8_t cmd_len); 332 333 /* Wire and command protocol */ 334 #define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */ 335 #define UMASS_PROTO_CBI 0x0002 336 #define UMASS_PROTO_CBI_I 0x0004 337 #define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */ 338 #define UMASS_PROTO_SCSI 0x0100 /* command protocol */ 339 #define UMASS_PROTO_ATAPI 0x0200 340 #define UMASS_PROTO_UFI 0x0400 341 #define UMASS_PROTO_RBC 0x0800 342 #define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */ 343 344 /* Device specific quirks */ 345 #define NO_QUIRKS 0x0000 346 /* 347 * The drive does not support Test Unit Ready. Convert to Start Unit 348 */ 349 #define NO_TEST_UNIT_READY 0x0001 350 /* 351 * The drive does not reset the Unit Attention state after REQUEST 352 * SENSE has been sent. The INQUIRY command does not reset the UA 353 * either, and so CAM runs in circles trying to retrieve the initial 354 * INQUIRY data. 355 */ 356 #define RS_NO_CLEAR_UA 0x0002 357 /* The drive does not support START STOP. */ 358 #define NO_START_STOP 0x0004 359 /* Don't ask for full inquiry data (255b). */ 360 #define FORCE_SHORT_INQUIRY 0x0008 361 /* Needs to be initialised the Shuttle way */ 362 #define SHUTTLE_INIT 0x0010 363 /* Drive needs to be switched to alternate iface 1 */ 364 #define ALT_IFACE_1 0x0020 365 /* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */ 366 #define FLOPPY_SPEED 0x0040 367 /* The device can't count and gets the residue of transfers wrong */ 368 #define IGNORE_RESIDUE 0x0080 369 /* No GetMaxLun call */ 370 #define NO_GETMAXLUN 0x0100 371 /* The device uses a weird CSWSIGNATURE. */ 372 #define WRONG_CSWSIG 0x0200 373 /* Device cannot handle INQUIRY so fake a generic response */ 374 #define NO_INQUIRY 0x0400 375 /* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */ 376 #define NO_INQUIRY_EVPD 0x0800 377 /* Pad all RBC requests to 12 bytes. */ 378 #define RBC_PAD_TO_12 0x1000 379 /* 380 * Device reports number of sectors from READ_CAPACITY, not max 381 * sector number. 382 */ 383 #define READ_CAPACITY_OFFBY1 0x2000 384 /* 385 * Device cannot handle a SCSI synchronize cache command. Normally 386 * this quirk would be handled in the cam layer, but for IDE bridges 387 * we need to associate the quirk with the bridge and not the 388 * underlying disk device. This is handled by faking a success 389 * result. 390 */ 391 #define NO_SYNCHRONIZE_CACHE 0x4000 392 /* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */ 393 #define NO_PREVENT_ALLOW 0x8000 394 395 #if USB_HAVE_DEVICE_TOPOLOGY 396 extern usbd_bt_tree hub_tree; 397 #endif 398 399 struct umass_softc { 400 union ccb *data_ccb; 401 struct scsi_sense cam_scsi_sense; 402 struct scsi_test_unit_ready cam_scsi_test_unit_ready; 403 struct mtx sc_mtx; 404 EVENT_CB_S sc_event; 405 struct { 406 uint8_t *data_ptr; 407 union ccb *ccb; 408 umass_callback_t *callback; 409 410 uint32_t data_len; /* bytes */ 411 uint32_t data_rem; /* bytes */ 412 uint32_t data_timeout; /* ms */ 413 uint32_t actlen; /* bytes */ 414 415 uint8_t cmd_data[UMASS_MAX_CMDLEN]; 416 uint8_t cmd_len; /* bytes */ 417 uint8_t dir; 418 uint8_t lun; 419 } sc_transfer; 420 421 struct umass_info info; 422 423 /* Bulk specific variables for transfers in progress */ 424 umass_bbb_cbw_t cbw; /* command block wrapper */ 425 umass_bbb_csw_t csw; /* command status wrapper */ 426 427 /* CBI specific variables for transfers in progress */ 428 umass_cbi_sbl_t sbl; /* status block */ 429 430 device_t sc_dev; 431 struct usb_device *sc_udev; 432 struct usb_xfer *sc_xfer[UMASS_T_MAX]; 433 434 /* 435 * The command transform function is used to convert the SCSI 436 * commands into their derivatives, like UFI, ATAPI, and friends. 437 */ 438 umass_transform_t *sc_transform; 439 440 uint32_t sc_unit; 441 uint32_t sc_quirks; /* they got it almost right */ 442 uint32_t sc_proto; /* wire and cmd protocol */ 443 444 uint8_t sc_name[16]; 445 uint8_t sc_iface_no; /* interface number */ 446 uint8_t sc_maxlun; /* maximum LUN number, inclusive */ 447 uint8_t sc_last_xfer_index; 448 uint8_t sc_status_try; 449 BOOL sc_detach_status; 450 BOOL sc_super_disk; /* TRUE: Disk is bigger than 2T; FALSE: Disk is less than 2T */ 451 struct mtx sc_umass_mtx; /* The mtx is used to prevent data read and write competition */ 452 }; 453 454 struct umass_probe_proto { 455 uint32_t quirks; 456 uint32_t proto; 457 458 int error; 459 }; 460 461 #if USB_SUPPORT_SD_HOT_PLUG 462 struct umass_dev_info { 463 struct umass_softc *sc; 464 unsigned int dev_unit; 465 int used; /* 0: not use; 1: in use */ 466 int attached; /* 0: not attach; 1: in attach */ 467 struct mtx dev_mtx; /* The mtx is used to prevent U disk insertion or extraction competition */ 468 }; 469 470 static struct umass_dev_info g_umass_dev_array[MAX_DEVICE] = {0}; 471 static void umass_task_check(int flag); 472 static void umass_dev_delete(struct umass_softc *sc, unsigned int dev_unit); 473 int umass_dev_is_attached(unsigned int dev_unit); 474 static void umass_dev_attach_flag_set(int dev_unit); 475 pthread_t umass_taskid; 476 #define umass_dev_mtx_init(id, type) (void)mtx_init(&g_umass_dev_array[id].dev_mtx, NULL, NULL, type) 477 #define umass_dev_mtx_destroy(id) (void)mtx_destroy(&g_umass_dev_array[id].dev_mtx) 478 #define umass_dev_lock(id) (void)mtx_lock(&g_umass_dev_array[id].dev_mtx) 479 #define umass_dev_unlock(id) (void)mtx_unlock(&g_umass_dev_array[id].dev_mtx) 480 #else 481 #define umass_dev_lock(id) (void)mtx_lock(NULL) 482 #define umass_dev_unlock(id) (void)mtx_unlock(NULL) 483 #endif 484 485 struct umass_softc *p_umsf = NULL; 486 /* prototypes */ 487 488 static device_probe_t umass_probe; 489 static device_attach_t umass_attach; 490 static device_detach_t umass_detach; 491 492 static usb_callback_t umass_tr_error; 493 static usb_callback_t umass_t_bbb_reset1_callback; 494 static usb_callback_t umass_t_bbb_reset2_callback; 495 static usb_callback_t umass_t_bbb_reset3_callback; 496 static usb_callback_t umass_t_bbb_command_callback; 497 static usb_callback_t umass_t_bbb_data_read_callback; 498 static usb_callback_t umass_t_bbb_data_rd_cs_callback; 499 static usb_callback_t umass_t_bbb_data_write_callback; 500 static usb_callback_t umass_t_bbb_data_wr_cs_callback; 501 static usb_callback_t umass_t_bbb_status_callback; 502 static usb_callback_t umass_t_cbi_reset1_callback; 503 static usb_callback_t umass_t_cbi_reset2_callback; 504 static usb_callback_t umass_t_cbi_reset3_callback; 505 static usb_callback_t umass_t_cbi_reset4_callback; 506 static usb_callback_t umass_t_cbi_command_callback; 507 static usb_callback_t umass_t_cbi_data_read_callback; 508 static usb_callback_t umass_t_cbi_data_rd_cs_callback; 509 static usb_callback_t umass_t_cbi_data_write_callback; 510 static usb_callback_t umass_t_cbi_data_wr_cs_callback; 511 static usb_callback_t umass_t_cbi_status_callback; 512 513 static void umass_cancel_ccb(struct umass_softc *); 514 static void umass_init_shuttle(struct umass_softc *); 515 static void umass_t_bbb_data_clear_stall_callback(struct usb_xfer *, 516 uint8_t, uint8_t, usb_error_t); 517 static int umass_command_start(struct umass_softc *, uint8_t, void *, 518 uint32_t, uint32_t, umass_callback_t *, union ccb *); 519 static uint8_t umass_bbb_get_max_lun(struct umass_softc *); 520 static void umass_cbi_start_status(struct umass_softc *); 521 static void umass_t_cbi_data_clear_stall_callback(struct usb_xfer *, 522 uint8_t, uint8_t, usb_error_t); 523 static void umass_cam_cb(struct umass_softc *, union ccb *, uint32_t, uint8_t); 524 static uint8_t umass_scsi_transform(struct umass_softc *, uint8_t *, uint8_t); 525 static uint8_t umass_rbc_transform(struct umass_softc *, uint8_t *, uint8_t); 526 static uint8_t umass_ufi_transform(struct umass_softc *, uint8_t *, uint8_t); 527 static uint8_t umass_atapi_transform(struct umass_softc *, uint8_t *, 528 uint8_t); 529 static uint8_t umass_no_transform(struct umass_softc *, uint8_t *, uint8_t); 530 531 #ifdef LOSCFG_USB_DEBUG 532 static void umass_bbb_dump_cbw(struct umass_softc *, umass_bbb_cbw_t *); 533 static void umass_bbb_dump_csw(struct umass_softc *, umass_bbb_csw_t *); 534 static void umass_cbi_dump_cmd(struct umass_softc *, void *, uint8_t); 535 #endif 536 537 static void devunit_to_devname(unsigned int dev_unit, char *devname); 538 static int32_t umass_attach_dev(struct umass_softc *sc, unsigned int dev_unit); 539 static void umass_detach_dev_sub(struct umass_softc *sc, int dev_unit, int flag); 540 541 static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = { 542 [UMASS_T_BBB_RESET1] = { 543 .type = UE_CONTROL, 544 .endpoint = 0x00, /* Control pipe */ 545 .direction = UE_DIR_ANY, 546 .bufsize = sizeof(struct usb_device_request), 547 .callback = &umass_t_bbb_reset1_callback, 548 .timeout = 5000, /* 5 seconds */ 549 .interval = 500, /* 500 milliseconds */ 550 }, 551 552 [UMASS_T_BBB_RESET2] = { 553 .type = UE_CONTROL, 554 .endpoint = 0x00, /* Control pipe */ 555 .direction = UE_DIR_ANY, 556 .bufsize = sizeof(struct usb_device_request), 557 .callback = &umass_t_bbb_reset2_callback, 558 .timeout = 5000, /* 5 seconds */ 559 .interval = 50, /* 50 milliseconds */ 560 }, 561 562 [UMASS_T_BBB_RESET3] = { 563 .type = UE_CONTROL, 564 .endpoint = 0x00, /* Control pipe */ 565 .direction = UE_DIR_ANY, 566 .bufsize = sizeof(struct usb_device_request), 567 .callback = &umass_t_bbb_reset3_callback, 568 .timeout = 5000, /* 5 seconds */ 569 .interval = 50, /* 50 milliseconds */ 570 }, 571 572 [UMASS_T_BBB_COMMAND] = { 573 .type = UE_BULK, 574 .endpoint = UE_ADDR_ANY, 575 .direction = UE_DIR_OUT, 576 .bufsize = sizeof(umass_bbb_cbw_t), 577 .callback = &umass_t_bbb_command_callback, 578 .timeout = 5000, /* 5 seconds */ 579 }, 580 581 [UMASS_T_BBB_DATA_READ] = { 582 .type = UE_BULK, 583 .endpoint = UE_ADDR_ANY, 584 .direction = UE_DIR_IN, 585 .bufsize = UMASS_BULK_SIZE, 586 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, 587 .callback = &umass_t_bbb_data_read_callback, 588 .timeout = 0, /* overwritten later */ 589 }, 590 591 [UMASS_T_BBB_DATA_RD_CS] = { 592 .type = UE_CONTROL, 593 .endpoint = 0x00, /* Control pipe */ 594 .direction = UE_DIR_ANY, 595 .bufsize = sizeof(struct usb_device_request), 596 .callback = &umass_t_bbb_data_rd_cs_callback, 597 .timeout = 5000, /* 5 seconds */ 598 }, 599 600 [UMASS_T_BBB_DATA_WRITE] = { 601 .type = UE_BULK, 602 .endpoint = UE_ADDR_ANY, 603 .direction = UE_DIR_OUT, 604 .bufsize = UMASS_BULK_SIZE, 605 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, 606 .callback = &umass_t_bbb_data_write_callback, 607 .timeout = 0, /* overwritten later */ 608 }, 609 610 [UMASS_T_BBB_DATA_WR_CS] = { 611 .type = UE_CONTROL, 612 .endpoint = 0x00, /* Control pipe */ 613 .direction = UE_DIR_ANY, 614 .bufsize = sizeof(struct usb_device_request), 615 .callback = &umass_t_bbb_data_wr_cs_callback, 616 .timeout = 5000, /* 5 seconds */ 617 }, 618 619 [UMASS_T_BBB_STATUS] = { 620 .type = UE_BULK, 621 .endpoint = UE_ADDR_ANY, 622 .direction = UE_DIR_IN, 623 .bufsize = sizeof(umass_bbb_csw_t), 624 .flags = {.short_xfer_ok = 1,}, 625 .callback = &umass_t_bbb_status_callback, 626 .timeout = 5000, /* ms */ 627 }, 628 }; 629 630 static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = { 631 [UMASS_T_CBI_RESET1] = { 632 .type = UE_CONTROL, 633 .endpoint = 0x00, /* Control pipe */ 634 .direction = UE_DIR_ANY, 635 .bufsize = (sizeof(struct usb_device_request) + 636 UMASS_CBI_DIAGNOSTIC_CMDLEN), 637 .callback = &umass_t_cbi_reset1_callback, 638 .timeout = 5000, /* 5 seconds */ 639 .interval = 500, /* 500 milliseconds */ 640 }, 641 642 [UMASS_T_CBI_RESET2] = { 643 .type = UE_CONTROL, 644 .endpoint = 0x00, /* Control pipe */ 645 .direction = UE_DIR_ANY, 646 .bufsize = sizeof(struct usb_device_request), 647 .callback = &umass_t_cbi_reset2_callback, 648 .timeout = 5000, /* 5 seconds */ 649 .interval = 50, /* 50 milliseconds */ 650 }, 651 652 [UMASS_T_CBI_RESET3] = { 653 .type = UE_CONTROL, 654 .endpoint = 0x00, /* Control pipe */ 655 .direction = UE_DIR_ANY, 656 .bufsize = sizeof(struct usb_device_request), 657 .callback = &umass_t_cbi_reset3_callback, 658 .timeout = 5000, /* 5 seconds */ 659 .interval = 50, /* 50 milliseconds */ 660 }, 661 662 [UMASS_T_CBI_COMMAND] = { 663 .type = UE_CONTROL, 664 .endpoint = 0x00, /* Control pipe */ 665 .direction = UE_DIR_ANY, 666 .bufsize = (sizeof(struct usb_device_request) + 667 UMASS_MAX_CMDLEN), 668 .callback = &umass_t_cbi_command_callback, 669 .timeout = 5000, /* 5 seconds */ 670 }, 671 672 [UMASS_T_CBI_DATA_READ] = { 673 .type = UE_BULK, 674 .endpoint = UE_ADDR_ANY, 675 .direction = UE_DIR_IN, 676 .bufsize = UMASS_BULK_SIZE, 677 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, 678 .callback = &umass_t_cbi_data_read_callback, 679 .timeout = 0, /* overwritten later */ 680 }, 681 682 [UMASS_T_CBI_DATA_RD_CS] = { 683 .type = UE_CONTROL, 684 .endpoint = 0x00, /* Control pipe */ 685 .direction = UE_DIR_ANY, 686 .bufsize = sizeof(struct usb_device_request), 687 .callback = &umass_t_cbi_data_rd_cs_callback, 688 .timeout = 5000, /* 5 seconds */ 689 }, 690 691 [UMASS_T_CBI_DATA_WRITE] = { 692 .type = UE_BULK, 693 .endpoint = UE_ADDR_ANY, 694 .direction = UE_DIR_OUT, 695 .bufsize = UMASS_BULK_SIZE, 696 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,}, 697 .callback = &umass_t_cbi_data_write_callback, 698 .timeout = 0, /* overwritten later */ 699 }, 700 701 [UMASS_T_CBI_DATA_WR_CS] = { 702 .type = UE_CONTROL, 703 .endpoint = 0x00, /* Control pipe */ 704 .direction = UE_DIR_ANY, 705 .bufsize = sizeof(struct usb_device_request), 706 .callback = &umass_t_cbi_data_wr_cs_callback, 707 .timeout = 5000, /* 5 seconds */ 708 }, 709 710 [UMASS_T_CBI_STATUS] = { 711 .type = UE_INTERRUPT, 712 .endpoint = UE_ADDR_ANY, 713 .direction = UE_DIR_IN, 714 .flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,}, 715 .bufsize = sizeof(umass_cbi_sbl_t), 716 .callback = &umass_t_cbi_status_callback, 717 .timeout = 5000, /* ms */ 718 }, 719 720 [UMASS_T_CBI_RESET4] = { 721 .type = UE_CONTROL, 722 .endpoint = 0x00, /* Control pipe */ 723 .direction = UE_DIR_ANY, 724 .bufsize = sizeof(struct usb_device_request), 725 .callback = &umass_t_cbi_reset4_callback, 726 .timeout = 5000, /* ms */ 727 }, 728 }; 729 730 #define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ 731 #define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ 732 733 static devclass_t umass_devclass; 734 735 static device_method_t umass_methods[] = { 736 /* Device interface */ 737 DEVMETHOD(device_probe, umass_probe), 738 DEVMETHOD(device_attach, umass_attach), 739 DEVMETHOD(device_detach, umass_detach), 740 741 DEVMETHOD_END 742 }; 743 744 static driver_t umass_driver = { 745 .name = "umass", 746 .methods = umass_methods, 747 .size = sizeof(struct umass_softc), 748 }; 749 750 #if USB_HAVE_DEVICE_TOPOLOGY 751 UINT64 dev_quantity = 0; 752 #endif 753 754 DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, NULL, 0); 755 756 static uint16_t 757 umass_get_proto(struct usb_interface *iface) 758 { 759 struct usb_interface_descriptor *id; 760 uint16_t retval; 761 762 retval = 0; 763 764 /* Check for a standards compliant device */ 765 id = usbd_get_interface_descriptor(iface); 766 if ((id == NULL) || 767 (id->bInterfaceClass != UICLASS_MASS)) { 768 goto done; 769 } 770 switch (id->bInterfaceSubClass) { 771 case UISUBCLASS_SCSI: 772 retval |= UMASS_PROTO_SCSI; 773 break; 774 case UISUBCLASS_UFI: 775 retval |= UMASS_PROTO_UFI; 776 break; 777 case UISUBCLASS_RBC: 778 retval |= UMASS_PROTO_RBC; 779 break; 780 case UISUBCLASS_SFF8020I: 781 case UISUBCLASS_SFF8070I: 782 retval |= UMASS_PROTO_ATAPI; 783 break; 784 default: 785 goto done; 786 } 787 788 switch (id->bInterfaceProtocol) { 789 case UIPROTO_MASS_CBI: 790 retval |= UMASS_PROTO_CBI; 791 break; 792 case UIPROTO_MASS_CBI_I: 793 retval |= UMASS_PROTO_CBI_I; 794 break; 795 case UIPROTO_MASS_BBB_OLD: 796 case UIPROTO_MASS_BBB: 797 retval |= UMASS_PROTO_BBB; 798 break; 799 default: 800 goto done; 801 } 802 done: 803 return (retval); 804 } 805 806 /* 807 * Match the device we are seeing with the devices supported. 808 */ 809 static struct umass_probe_proto 810 umass_probe_proto(device_t dev, struct usb_attach_arg *uaa) 811 { 812 struct umass_probe_proto ret; 813 uint32_t quirks = NO_QUIRKS; 814 uint32_t proto = umass_get_proto(uaa->iface); 815 816 (void)memset_s(&ret, sizeof(ret), 0, sizeof(ret)); 817 ret.error = BUS_PROBE_GENERIC; 818 819 /* Search for protocol enforcement */ 820 821 if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_BBB)) { 822 proto &= ~UMASS_PROTO_WIRE; 823 proto |= UMASS_PROTO_BBB; 824 } else if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_CBI)) { 825 proto &= ~UMASS_PROTO_WIRE; 826 proto |= UMASS_PROTO_CBI; 827 } else if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_CBI_I)) { 828 proto &= ~UMASS_PROTO_WIRE; 829 proto |= UMASS_PROTO_CBI_I; 830 } 831 832 if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_SCSI)) { 833 proto &= ~UMASS_PROTO_COMMAND; 834 proto |= UMASS_PROTO_SCSI; 835 } else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_ATAPI)) { 836 proto &= ~UMASS_PROTO_COMMAND; 837 proto |= UMASS_PROTO_ATAPI; 838 } else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_UFI)) { 839 proto &= ~UMASS_PROTO_COMMAND; 840 proto |= UMASS_PROTO_UFI; 841 } else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_RBC)) { 842 proto &= ~UMASS_PROTO_COMMAND; 843 proto |= UMASS_PROTO_RBC; 844 } 845 846 /* Check if the protocol is invalid */ 847 848 if ((proto & UMASS_PROTO_COMMAND) == 0) { 849 ret.error = ENXIO; 850 goto done; 851 } 852 853 if ((proto & UMASS_PROTO_WIRE) == 0) { 854 ret.error = ENXIO; 855 goto done; 856 } 857 858 /* Search for quirks */ 859 860 if (usb_test_quirk(uaa, UQ_MSC_NO_TEST_UNIT_READY)) 861 quirks |= NO_TEST_UNIT_READY; 862 if (usb_test_quirk(uaa, UQ_MSC_NO_RS_CLEAR_UA)) 863 quirks |= RS_NO_CLEAR_UA; 864 if (usb_test_quirk(uaa, UQ_MSC_NO_START_STOP)) 865 quirks |= NO_START_STOP; 866 if (usb_test_quirk(uaa, UQ_MSC_NO_GETMAXLUN)) 867 quirks |= NO_GETMAXLUN; 868 if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY)) 869 quirks |= NO_INQUIRY; 870 if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD)) 871 quirks |= NO_INQUIRY_EVPD; 872 if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW)) 873 quirks |= NO_PREVENT_ALLOW; 874 if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE)) 875 quirks |= NO_SYNCHRONIZE_CACHE; 876 if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT)) 877 quirks |= SHUTTLE_INIT; 878 if (usb_test_quirk(uaa, UQ_MSC_ALT_IFACE_1)) 879 quirks |= ALT_IFACE_1; 880 if (usb_test_quirk(uaa, UQ_MSC_FLOPPY_SPEED)) 881 quirks |= FLOPPY_SPEED; 882 if (usb_test_quirk(uaa, UQ_MSC_IGNORE_RESIDUE)) 883 quirks |= IGNORE_RESIDUE; 884 if (usb_test_quirk(uaa, UQ_MSC_WRONG_CSWSIG)) 885 quirks |= WRONG_CSWSIG; 886 if (usb_test_quirk(uaa, UQ_MSC_RBC_PAD_TO_12)) 887 quirks |= RBC_PAD_TO_12; 888 if (usb_test_quirk(uaa, UQ_MSC_READ_CAP_OFFBY1)) 889 quirks |= READ_CAPACITY_OFFBY1; 890 if (usb_test_quirk(uaa, UQ_MSC_FORCE_SHORT_INQ)) 891 quirks |= FORCE_SHORT_INQUIRY; 892 893 done: 894 ret.quirks = quirks; 895 ret.proto = proto; 896 return (ret); 897 } 898 899 static int 900 umass_probe(device_t dev) 901 { 902 struct usb_attach_arg *uaa = 903 (struct usb_attach_arg *)device_get_ivars(dev); 904 struct umass_probe_proto temp; 905 906 if (uaa->usb_mode != USB_MODE_HOST) { 907 return (ENXIO); 908 } 909 temp = umass_probe_proto(dev, uaa); 910 911 return (temp.error); 912 } 913 914 static int 915 umass_attach(device_t dev) 916 { 917 struct umass_softc *sc = 918 (struct umass_softc *)device_get_softc(dev); 919 struct usb_attach_arg *uaa = 920 (struct usb_attach_arg *)device_get_ivars(dev); 921 struct umass_probe_proto temp = umass_probe_proto(dev, uaa); 922 struct usb_interface_descriptor *id; 923 usb_error_t err; 924 925 /* 926 * NOTE: the softc struct is cleared in device_set_driver. 927 * We can safely call umass_detach without specifically 928 * initializing the struct. 929 */ 930 931 sc->sc_dev = dev; 932 sc->sc_udev = uaa->device; 933 sc->sc_proto = temp.proto; 934 sc->sc_quirks = temp.quirks; 935 sc->sc_unit = device_get_unit(dev); 936 sc->data_ccb = NULL; 937 sc->sc_detach_status = FALSE; 938 sc->sc_super_disk = FALSE; 939 940 #if USB_HAVE_DEVICE_TOPOLOGY 941 dev_quantity |= 1ull << (unsigned int)device_get_unit(dev); 942 #endif 943 944 (void)snprintf_s((char *)sc->sc_name, sizeof(sc->sc_name), sizeof(sc->sc_name) - 1, 945 "%s", device_get_nameunit(dev)); 946 947 device_set_usb_desc(dev); 948 949 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), 950 NULL, MTX_DEF | MTX_RECURSE); 951 mtx_init(&sc->sc_umass_mtx, device_get_nameunit(dev), 952 NULL, MTX_DEF | MTX_RECURSE); 953 954 (void)LOS_EventInit(&sc->sc_event); 955 956 /* get interface index */ 957 958 id = usbd_get_interface_descriptor(uaa->iface); 959 if (id == NULL) { 960 device_printf(dev, "failed to get " 961 "interface number\n"); 962 goto detach; 963 } 964 sc->sc_iface_no = id->bInterfaceNumber; 965 966 device_printf(dev, " "); 967 968 switch (sc->sc_proto & UMASS_PROTO_COMMAND) { 969 case UMASS_PROTO_SCSI: 970 PRINTK("SCSI"); 971 break; 972 case UMASS_PROTO_ATAPI: 973 PRINTK("8070i (ATAPI)"); 974 break; 975 case UMASS_PROTO_UFI: 976 PRINTK("UFI"); 977 break; 978 case UMASS_PROTO_RBC: 979 PRINTK("RBC"); 980 break; 981 default: 982 PRINTK("(unknown 0x%02x)", 983 sc->sc_proto & UMASS_PROTO_COMMAND); 984 break; 985 } 986 987 PRINTK(" over "); 988 989 switch (sc->sc_proto & UMASS_PROTO_WIRE) { 990 case UMASS_PROTO_BBB: 991 PRINTK("Bulk-Only"); 992 break; 993 case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */ 994 PRINTK("CBI"); 995 break; 996 case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */ 997 PRINTK("CBI with CCI"); 998 break; 999 default: 1000 PRINTK("(unknown 0x%02x)", 1001 sc->sc_proto & UMASS_PROTO_WIRE); 1002 } 1003 1004 PRINTK("; quirks = 0x%04x\n", sc->sc_quirks); 1005 1006 if (sc->sc_quirks & ALT_IFACE_1) { 1007 err = usbd_set_alt_interface_index 1008 (uaa->device, uaa->info.bIfaceIndex, 1); 1009 1010 if (err) { 1011 DPRINTF_UMASS(sc, UDMASS_USB, "could not switch to " 1012 "Alt Interface 1\n"); 1013 goto detach; 1014 } 1015 } 1016 /* allocate all required USB transfers */ 1017 1018 if (sc->sc_proto & UMASS_PROTO_BBB) { 1019 err = usbd_transfer_setup(uaa->device, 1020 &uaa->info.bIfaceIndex, sc->sc_xfer, umass_bbb_config, 1021 UMASS_T_BBB_MAX, sc, &sc->sc_mtx); 1022 1023 /* skip reset first time */ 1024 sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND; 1025 1026 } else if (sc->sc_proto & (UMASS_PROTO_CBI | UMASS_PROTO_CBI_I)) { 1027 err = usbd_transfer_setup(uaa->device, 1028 &uaa->info.bIfaceIndex, sc->sc_xfer, umass_cbi_config, 1029 UMASS_T_CBI_MAX, sc, &sc->sc_mtx); 1030 1031 /* skip reset first time */ 1032 sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND; 1033 1034 } else { 1035 err = USB_ERR_INVAL; 1036 } 1037 1038 if (err) { 1039 device_printf(dev, "could not setup required " 1040 "transfers, %s\n", usbd_errstr(err)); 1041 goto detach; 1042 } 1043 #ifdef LOSCFG_USB_DEBUG 1044 if (umass_throttle > 0) { 1045 uint8_t x; 1046 int iv; 1047 1048 iv = umass_throttle; 1049 1050 if (iv < 1) 1051 iv = 1; 1052 else if (iv > 8000) 1053 iv = 8000; 1054 1055 for (x = 0; x != UMASS_T_MAX; x++) { 1056 if (sc->sc_xfer[x] != NULL) 1057 usbd_xfer_set_interval(sc->sc_xfer[x], iv); 1058 } 1059 } 1060 #endif 1061 sc->sc_transform = 1062 (sc->sc_proto & UMASS_PROTO_SCSI) ? &umass_scsi_transform : 1063 (sc->sc_proto & UMASS_PROTO_UFI) ? &umass_ufi_transform : 1064 (sc->sc_proto & UMASS_PROTO_ATAPI) ? &umass_atapi_transform : 1065 (sc->sc_proto & UMASS_PROTO_RBC) ? &umass_rbc_transform : 1066 &umass_no_transform; 1067 1068 /* from here onwards the device can be used. */ 1069 1070 if (sc->sc_quirks & SHUTTLE_INIT) { 1071 umass_init_shuttle(sc); 1072 } 1073 /* get the maximum LUN supported by the device */ 1074 1075 if (((sc->sc_proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB) && 1076 !(sc->sc_quirks & NO_GETMAXLUN)) 1077 sc->sc_maxlun = umass_bbb_get_max_lun(sc); 1078 else 1079 sc->sc_maxlun = 0; 1080 1081 /* Prepare the SCSI command block */ 1082 sc->cam_scsi_sense.opcode = REQUEST_SENSE; 1083 sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY; 1084 1085 #define SOFT_CACHE_SIZE 0x40 1086 sc->data_ccb = (union ccb *)malloc(sizeof(union ccb)); 1087 if (sc->data_ccb == NULL) 1088 goto detach; 1089 sc->data_ccb->csio.data_ptr = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(SOFT_CACHE_SIZE)); 1090 if (sc->data_ccb->csio.data_ptr == NULL) 1091 goto detach; 1092 sc->data_ccb->csio.dxfer_len = SOFT_CACHE_SIZE; 1093 1094 DPRINTF_UMASS(sc, UDMASS_GEN, "Attach finished\n"); 1095 1096 /* register the device*/ 1097 if (umass_attach_dev(sc, device_get_unit(dev))) { 1098 goto detach; 1099 } 1100 1101 p_umsf = sc; 1102 return (0); /* success */ 1103 1104 detach: 1105 (void)umass_detach(dev); 1106 return (ENXIO); /* failure */ 1107 } 1108 1109 static int 1110 umass_detach(device_t dev) 1111 { 1112 struct umass_softc *sc = (struct umass_softc *)device_get_softc(dev); 1113 unsigned int dev_unit = device_get_unit(dev); 1114 1115 DPRINTF_UMASS(sc, UDMASS_USB, "\n"); 1116 1117 sc->sc_detach_status = TRUE; 1118 1119 /* teardown our statemachine */ 1120 usbd_transfer_unsetup(sc->sc_xfer, UMASS_T_MAX); 1121 1122 mtx_lock(&sc->sc_mtx); 1123 1124 /* cancel any leftover CCB's */ 1125 umass_cancel_ccb(sc); 1126 1127 mtx_lock(&sc->sc_umass_mtx); 1128 if (sc->data_ccb != NULL) { 1129 if (sc->data_ccb->csio.data_ptr != NULL) { 1130 free((void*)sc->data_ccb->csio.data_ptr); 1131 sc->data_ccb->csio.data_ptr = NULL; 1132 } 1133 free(sc->data_ccb); 1134 sc->data_ccb = NULL; 1135 } 1136 mtx_unlock(&sc->sc_umass_mtx); 1137 1138 umass_detach_dev_sub(sc, dev_unit, 0); 1139 #if USB_SUPPORT_SD_HOT_PLUG 1140 umass_task_check(1); 1141 #endif 1142 1143 mtx_unlock(&sc->sc_mtx); 1144 sc->sc_detach_status = FALSE; 1145 mtx_destroy(&sc->sc_mtx); 1146 mtx_destroy(&sc->sc_umass_mtx); 1147 1148 p_umsf = NULL; 1149 return (0); /* success */ 1150 } 1151 1152 static void 1153 umass_init_shuttle(struct umass_softc *sc) 1154 { 1155 struct usb_device_request req; 1156 usb_error_t err; 1157 uint8_t status[2] = {0, 0}; 1158 1159 /* 1160 * The Linux driver does this, but no one can tell us what the 1161 * command does. 1162 */ 1163 req.bmRequestType = UT_READ_VENDOR_DEVICE; 1164 req.bRequest = 1; /* XXX unknown command */ 1165 USETW(req.wValue, 0); 1166 req.wIndex[0] = sc->sc_iface_no; 1167 req.wIndex[1] = 0; 1168 USETW(req.wLength, sizeof(status)); 1169 err = usbd_do_request(sc->sc_udev, NULL, &req, &status); 1170 if (err) 1171 DPRINTF_UMASS(sc, UDMASS_GEN, "request failed in %s %d, err=%d\n", 1172 __FUNCTION__, __LINE__, err); 1173 1174 DPRINTF_UMASS(sc, UDMASS_GEN, "Shuttle init returned 0x%02x%02x\n", 1175 status[0], status[1]); 1176 } 1177 1178 /* 1179 * Generic functions to handle transfers 1180 */ 1181 1182 static void 1183 umass_transfer_start(struct umass_softc *sc, uint8_t xfer_index) 1184 { 1185 DPRINTF_UMASS(sc, UDMASS_GEN, "transfer index = " 1186 "%d\n", xfer_index); 1187 1188 if (sc->sc_xfer[xfer_index]) { 1189 sc->sc_last_xfer_index = xfer_index; 1190 usbd_transfer_start(sc->sc_xfer[xfer_index]); 1191 } else { 1192 umass_cancel_ccb(sc); 1193 } 1194 } 1195 1196 static void 1197 umass_cancel_ccb(struct umass_softc *sc) 1198 { 1199 union ccb *umass_ccb; 1200 1201 mtx_assert(&sc->sc_mtx, MA_OWNED); 1202 1203 umass_ccb = sc->sc_transfer.ccb; 1204 sc->sc_transfer.ccb = NULL; 1205 sc->sc_last_xfer_index = 0; 1206 1207 if (umass_ccb != NULL) { 1208 (sc->sc_transfer.callback) 1209 (sc, umass_ccb, (sc->sc_transfer.data_len - 1210 sc->sc_transfer.actlen), STATUS_WIRE_FAILED); 1211 } 1212 } 1213 1214 static void 1215 umass_tr_error(struct usb_xfer *xfer, usb_error_t error) 1216 { 1217 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1218 1219 if (error != USB_ERR_CANCELLED) { 1220 DPRINTF_UMASS(sc, UDMASS_GEN, "transfer error, %s -> " 1221 "reset\n", usbd_errstr(error)); 1222 } 1223 umass_cancel_ccb(sc); 1224 } 1225 1226 /* 1227 *return 0: find the corresponding LUN; 1228 * 1: find the SBC Direct-access; 1229 * -1: did not find the LUN. 1230 */ 1231 static int 1232 umass_scsi_inquiry_data(struct umass_softc *sc, void *data, int len) 1233 { 1234 struct scsiresp_inquiry_s *cur_i; 1235 uint8_t pdt; 1236 uint8_t rmb; 1237 int is_dir; 1238 char *name; 1239 1240 if (len != SCSIRESP_INQUIRY_SIZEOF) 1241 return (-1); 1242 1243 is_dir = 0; 1244 cur_i = (struct scsiresp_inquiry_s *)data; 1245 1246 pdt = SCSI_GET_INQUIRY_PDT(cur_i->qualtype); 1247 rmb = SCSI_GET_INQUIRY_RMB(cur_i->flags1); 1248 switch (pdt) { 1249 case T_DIRECT: 1250 name = "SBC Direct-access"; 1251 is_dir = 1; 1252 break; 1253 case T_CDROM: 1254 name = "CD-ROM"; 1255 break; 1256 case T_OPTICAL: 1257 name = "Optical memory"; 1258 break; 1259 case T_RBC: 1260 name = "RBC Direct-access"; 1261 break; 1262 default: 1263 name = "PDT out of scope"; 1264 break; 1265 } 1266 DPRINTF_UMASS(sc, UDMASS_BBB, "SCSI: LUN-%d %s %s\n", sc->sc_transfer.lun, name, 1267 (rmb ? "Removable" : "Not Removable")); 1268 1269 (void)name; 1270 (void)rmb; /* this is for clearing warning */ 1271 return (is_dir); 1272 } 1273 1274 /* 1275 * BBB protocol specific functions 1276 */ 1277 1278 static void 1279 umass_t_bbb_reset1_callback(struct usb_xfer *xfer, usb_error_t error) 1280 { 1281 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1282 struct usb_device_request req; 1283 struct usb_page_cache *pc; 1284 1285 switch (USB_GET_STATE(xfer)) { 1286 case USB_ST_TRANSFERRED: 1287 umass_transfer_start(sc, UMASS_T_BBB_RESET2); 1288 return; 1289 1290 case USB_ST_SETUP: 1291 /* 1292 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class) 1293 * 1294 * For Reset Recovery the host shall issue in the following order: 1295 * a) a Bulk-Only Mass Storage Reset 1296 * b) a Clear Feature HALT to the Bulk-In endpoint 1297 * c) a Clear Feature HALT to the Bulk-Out endpoint 1298 * 1299 * This is done in 3 steps, using 3 transfers: 1300 * UMASS_T_BBB_RESET1 1301 * UMASS_T_BBB_RESET2 1302 * UMASS_T_BBB_RESET3 1303 */ 1304 1305 DPRINTF_UMASS(sc, UDMASS_BBB, "BBB reset!\n"); 1306 1307 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1308 req.bRequest = UR_BBB_RESET; /* bulk only reset */ 1309 USETW(req.wValue, 0); 1310 req.wIndex[0] = sc->sc_iface_no; 1311 req.wIndex[1] = 0; 1312 USETW(req.wLength, 0); 1313 1314 pc = usbd_xfer_get_frame(xfer, 0); 1315 usbd_copy_in(pc, 0, &req, sizeof(req)); 1316 1317 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1318 usbd_xfer_set_frames(xfer, 1); 1319 usbd_transfer_submit(xfer); 1320 return; 1321 1322 default: /* Error */ 1323 umass_tr_error(xfer, error); 1324 return; 1325 } 1326 } 1327 1328 static void 1329 umass_t_bbb_reset2_callback(struct usb_xfer *xfer, usb_error_t error) 1330 { 1331 umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_RESET3, 1332 UMASS_T_BBB_DATA_READ, error); 1333 } 1334 1335 static void 1336 umass_t_bbb_reset3_callback(struct usb_xfer *xfer, usb_error_t error) 1337 { 1338 umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_COMMAND, 1339 UMASS_T_BBB_DATA_WRITE, error); 1340 } 1341 1342 static void 1343 umass_t_bbb_data_clear_stall_callback(struct usb_xfer *xfer, 1344 uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error) 1345 { 1346 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1347 1348 switch (USB_GET_STATE(xfer)) { 1349 case USB_ST_TRANSFERRED: 1350 tr_transferred: 1351 umass_transfer_start(sc, next_xfer); 1352 return; 1353 1354 case USB_ST_SETUP: 1355 if (usbd_clear_stall_callback(xfer, sc->sc_xfer[stall_xfer])) { 1356 goto tr_transferred; 1357 } 1358 return; 1359 1360 default: /* Error */ 1361 umass_tr_error(xfer, error); 1362 return; 1363 } 1364 } 1365 1366 static void 1367 umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error) 1368 { 1369 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1370 struct usb_page_cache *pc; 1371 uint32_t tag; 1372 int ret; 1373 1374 switch (USB_GET_STATE(xfer)) { 1375 case USB_ST_TRANSFERRED: 1376 umass_transfer_start 1377 (sc, ((sc->sc_transfer.dir == DIR_IN) ? UMASS_T_BBB_DATA_READ : 1378 (sc->sc_transfer.dir == DIR_OUT) ? UMASS_T_BBB_DATA_WRITE : 1379 UMASS_T_BBB_STATUS)); 1380 return; 1381 1382 case USB_ST_SETUP: 1383 1384 sc->sc_status_try = 0; 1385 1386 /* 1387 * the initial value is not important, 1388 * as long as the values are unique: 1389 */ 1390 tag = UGETDW(sc->cbw.dCBWTag) + 1; 1391 1392 USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); 1393 USETDW(sc->cbw.dCBWTag, tag); 1394 1395 /* 1396 * dCBWDataTransferLength: 1397 * This field indicates the number of bytes of data that the host 1398 * intends to transfer on the IN or OUT Bulk endpoint(as indicated by 1399 * the Direction bit) during the execution of this command. If this 1400 * field is set to 0, the device will expect that no data will be 1401 * transferred IN or OUT during this command, regardless of the value 1402 * of the Direction bit defined in dCBWFlags. 1403 */ 1404 USETDW(sc->cbw.dCBWDataTransferLength, sc->sc_transfer.data_len); 1405 1406 /* 1407 * dCBWFlags: 1408 * The bits of the Flags field are defined as follows: 1409 * Bits 0-6 reserved 1410 * Bit 7 Direction - this bit shall be ignored if the 1411 * dCBWDataTransferLength field is zero. 1412 * 0 = data Out from host to device 1413 * 1 = data In from device to host 1414 */ 1415 sc->cbw.bCBWFlags = ((sc->sc_transfer.dir == DIR_IN) ? 1416 CBWFLAGS_IN : CBWFLAGS_OUT); 1417 sc->cbw.bCBWLUN = sc->sc_transfer.lun; 1418 1419 if (sc->sc_transfer.cmd_len > sizeof(sc->cbw.CBWCDB)) { 1420 sc->sc_transfer.cmd_len = sizeof(sc->cbw.CBWCDB); 1421 DPRINTF_UMASS(sc, UDMASS_BBB, "Truncating long command!\n"); 1422 } 1423 sc->cbw.bCDBLength = sc->sc_transfer.cmd_len; 1424 1425 /* copy SCSI command data */ 1426 ret = memcpy_s(sc->cbw.CBWCDB, CBWCDBLENGTH, 1427 sc->sc_transfer.cmd_data, sc->sc_transfer.cmd_len); 1428 if (ret != EOK) { 1429 DPRINTF_UMASS(sc, UDMASS_BBB, "memcpy_s fail, %d\n", ret); 1430 return; 1431 } 1432 1433 /* clear remaining command area */ 1434 (void)memset_s(sc->cbw.CBWCDB + sc->sc_transfer.cmd_len, 1435 sizeof(sc->cbw.CBWCDB) - sc->sc_transfer.cmd_len, 0, 1436 sizeof(sc->cbw.CBWCDB) - sc->sc_transfer.cmd_len); 1437 1438 DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); 1439 1440 pc = usbd_xfer_get_frame(xfer, 0); 1441 usbd_copy_in(pc, 0, &sc->cbw, sizeof(sc->cbw)); 1442 usbd_xfer_set_frame_len(xfer, 0, sizeof(sc->cbw)); 1443 1444 usbd_transfer_submit(xfer); 1445 1446 return; 1447 1448 default: /* Error */ 1449 umass_tr_error(xfer, error); 1450 return; 1451 } 1452 } 1453 1454 static void 1455 umass_t_bbb_data_callback(struct usb_xfer *xfer, usb_error_t error, 1456 uint8_t xfer_index) 1457 { 1458 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1459 uint32_t max_bulk = usbd_xfer_max_len(xfer); 1460 int actlen, sumlen; 1461 1462 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 1463 1464 switch (USB_GET_STATE(xfer)) { 1465 case USB_ST_TRANSFERRED: 1466 sc->sc_transfer.data_rem -= actlen; 1467 sc->sc_transfer.data_ptr += actlen; 1468 sc->sc_transfer.actlen += actlen; 1469 1470 if (actlen < sumlen) { 1471 /* short transfer */ 1472 sc->sc_transfer.data_rem = 0; 1473 } 1474 case USB_ST_SETUP: 1475 DPRINTF_UMASS(sc, UDMASS_BBB, "max_bulk=%u, data_rem=%u\n", 1476 max_bulk, sc->sc_transfer.data_rem); 1477 1478 if (sc->sc_transfer.data_rem == 0) { 1479 umass_transfer_start(sc, UMASS_T_BBB_STATUS); 1480 return; 1481 } 1482 if (max_bulk > sc->sc_transfer.data_rem) { 1483 max_bulk = sc->sc_transfer.data_rem; 1484 } 1485 usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); 1486 1487 usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, 1488 max_bulk); 1489 1490 usbd_transfer_submit(xfer); 1491 return; 1492 1493 default: /* Error */ 1494 if (error == USB_ERR_CANCELLED) { 1495 umass_tr_error(xfer, error); 1496 } else { 1497 umass_transfer_start(sc, xfer_index); 1498 } 1499 return; 1500 } 1501 } 1502 1503 static void 1504 umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error) 1505 { 1506 umass_t_bbb_data_callback(xfer, error, UMASS_T_BBB_DATA_RD_CS); 1507 } 1508 1509 static void 1510 umass_t_bbb_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error) 1511 { 1512 umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_STATUS, 1513 UMASS_T_BBB_DATA_READ, error); 1514 } 1515 1516 static void 1517 umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error) 1518 { 1519 umass_t_bbb_data_callback(xfer, error, UMASS_T_BBB_DATA_WR_CS); 1520 } 1521 1522 static void 1523 umass_t_bbb_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error) 1524 { 1525 umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_STATUS, 1526 UMASS_T_BBB_DATA_WRITE, error); 1527 } 1528 1529 static void 1530 umass_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error) 1531 { 1532 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1533 union ccb *umass_ccb = sc->sc_transfer.ccb; 1534 struct usb_page_cache *pc; 1535 uint32_t residue; 1536 int actlen; 1537 1538 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 1539 1540 switch (USB_GET_STATE(xfer)) { 1541 case USB_ST_TRANSFERRED: 1542 1543 /* 1544 * Do a full reset if there is something wrong with the CSW: 1545 */ 1546 sc->sc_status_try = 1; 1547 1548 /* Zero missing parts of the CSW: */ 1549 1550 if (actlen < (int)sizeof(sc->csw)) { 1551 (void)memset_s(&sc->csw, sizeof(sc->csw), 0, sizeof(sc->csw)); 1552 } 1553 1554 pc = usbd_xfer_get_frame(xfer, 0); 1555 1556 usbd_copy_out(pc, 0, &sc->csw, actlen); 1557 1558 DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); 1559 1560 residue = UGETDW(sc->csw.dCSWDataResidue); 1561 1562 if ((!residue) || (sc->sc_quirks & IGNORE_RESIDUE)) { 1563 residue = (sc->sc_transfer.data_len - 1564 sc->sc_transfer.actlen); 1565 } 1566 if (residue > sc->sc_transfer.data_len) { 1567 DPRINTF_UMASS(sc, UDMASS_BBB, "truncating residue from %d " 1568 "to %d bytes\n", residue, sc->sc_transfer.data_len); 1569 residue = sc->sc_transfer.data_len; 1570 } 1571 /* translate weird command-status signatures: */ 1572 if (sc->sc_quirks & WRONG_CSWSIG) { 1573 uint32_t temp = UGETDW(sc->csw.dCSWSignature); 1574 1575 if ((temp == CSWSIGNATURE_OLYMPUS_C1) || 1576 (temp == CSWSIGNATURE_IMAGINATION_DBX1)) { 1577 USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); 1578 } 1579 } 1580 /* check CSW and handle eventual error */ 1581 if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { 1582 DPRINTF_UMASS(sc, UDMASS_BBB, "bad CSW signature 0x%08x != 0x%08x\n", 1583 UGETDW(sc->csw.dCSWSignature), CSWSIGNATURE); 1584 /* 1585 * Invalid CSW: Wrong signature or wrong tag might 1586 * indicate that we lost synchronization. Reset the 1587 * device. 1588 */ 1589 goto tr_error; 1590 } else if (UGETDW(sc->csw.dCSWTag) != UGETDW(sc->cbw.dCBWTag)) { 1591 DPRINTF_UMASS(sc, UDMASS_BBB, "Invalid CSW: tag 0x%08x should be " 1592 "0x%08x\n", UGETDW(sc->csw.dCSWTag), 1593 UGETDW(sc->cbw.dCBWTag)); 1594 goto tr_error; 1595 } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) { 1596 DPRINTF_UMASS(sc, UDMASS_BBB, "Invalid CSW: status %d > %d\n", 1597 sc->csw.bCSWStatus, CSWSTATUS_PHASE); 1598 goto tr_error; 1599 } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) { 1600 DPRINTF_UMASS(sc, UDMASS_BBB, "Phase error, residue = " 1601 "%d\n", residue); 1602 goto tr_error; 1603 } else if (sc->sc_transfer.actlen > sc->sc_transfer.data_len) { 1604 DPRINTF_UMASS(sc, UDMASS_BBB, "Buffer overrun %d > %d\n", 1605 sc->sc_transfer.actlen, sc->sc_transfer.data_len); 1606 goto tr_error; 1607 } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { 1608 DPRINTF_UMASS(sc, UDMASS_BBB, "Command failed, residue = " 1609 "%d\n", residue); 1610 1611 sc->sc_transfer.ccb = NULL; 1612 1613 sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND; 1614 1615 (sc->sc_transfer.callback) 1616 (sc, umass_ccb, residue, STATUS_CMD_FAILED); 1617 } else { 1618 sc->sc_transfer.ccb = NULL; 1619 1620 sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND; 1621 1622 (sc->sc_transfer.callback) 1623 (sc, umass_ccb, residue, STATUS_CMD_OK); 1624 } 1625 return; 1626 1627 case USB_ST_SETUP: 1628 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 1629 usbd_transfer_submit(xfer); 1630 return; 1631 1632 default: 1633 tr_error: 1634 DPRINTF_UMASS(sc, UDMASS_BBB, "Failed to read CSW: %s, try %d\n", 1635 usbd_errstr(error), sc->sc_status_try); 1636 1637 if ((error == USB_ERR_CANCELLED) || 1638 (sc->sc_status_try)) { 1639 umass_tr_error(xfer, error); 1640 } else { 1641 sc->sc_status_try = 1; 1642 umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS); 1643 } 1644 return; 1645 } 1646 } 1647 1648 static int 1649 umass_command_start(struct umass_softc *sc, uint8_t dir, 1650 void *data_ptr, uint32_t data_len, 1651 uint32_t data_timeout, umass_callback_t *callback, 1652 union ccb *umass_ccb) 1653 { 1654 if (sc->sc_detach_status) 1655 { 1656 PRINT_WARN("[%s][%d] usb is detaching\n",__FUNCTION__,__LINE__); 1657 return (-1); 1658 } 1659 1660 /* 1661 * NOTE: assumes that "sc->sc_transfer.cmd_data" and 1662 * "sc->sc_transfer.cmd_len" has been properly 1663 * initialized. 1664 */ 1665 1666 sc->sc_transfer.dir = data_len ? dir : DIR_NONE; 1667 sc->sc_transfer.data_ptr = (uint8_t *)data_ptr; 1668 sc->sc_transfer.data_len = data_len; 1669 sc->sc_transfer.data_rem = data_len; 1670 sc->sc_transfer.data_timeout = (data_timeout + UMASS_TIMEOUT); 1671 1672 sc->sc_transfer.actlen = 0; 1673 sc->sc_transfer.callback = callback; 1674 sc->sc_transfer.ccb = umass_ccb; 1675 1676 if (sc->sc_xfer[sc->sc_last_xfer_index]) { 1677 usbd_transfer_start(sc->sc_xfer[sc->sc_last_xfer_index]); 1678 } else { 1679 umass_cancel_ccb(sc); 1680 } 1681 1682 (void)LOS_EventRead(&sc->sc_event, 0xFF, 1683 LOS_WAITMODE_OR | LOS_WAITMODE_CLR, 10 * LOSCFG_BASE_CORE_TICK_PER_SECOND); /* 10 seconds. */ 1684 1685 return (0); 1686 } 1687 1688 static uint8_t 1689 umass_bbb_get_max_lun(struct umass_softc *sc) 1690 { 1691 struct usb_device_request req; 1692 usb_error_t err; 1693 uint8_t buf = 0; 1694 1695 /* The Get Max Lun command is a class-specific request. */ 1696 req.bmRequestType = UT_READ_CLASS_INTERFACE; 1697 req.bRequest = UR_BBB_GET_MAX_LUN; 1698 USETW(req.wValue, 0); 1699 req.wIndex[0] = sc->sc_iface_no; 1700 req.wIndex[1] = 0; 1701 USETW(req.wLength, 1); 1702 1703 err = usbd_do_request(sc->sc_udev, NULL, &req, &buf); 1704 if (err) { 1705 buf = 0; 1706 1707 /* Device doesn't support Get Max Lun request. */ 1708 PRINTK("%s: Get Max Lun not supported (%s)\n", 1709 sc->sc_name, usbd_errstr(err)); 1710 } 1711 return (buf); 1712 } 1713 1714 /* 1715 * Command/Bulk/Interrupt (CBI) specific functions 1716 */ 1717 1718 static void 1719 umass_cbi_start_status(struct umass_softc *sc) 1720 { 1721 if (sc->sc_xfer[UMASS_T_CBI_STATUS]) { 1722 umass_transfer_start(sc, UMASS_T_CBI_STATUS); 1723 } else { 1724 union ccb *umass_ccb = sc->sc_transfer.ccb; 1725 1726 sc->sc_transfer.ccb = NULL; 1727 1728 sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND; 1729 1730 (sc->sc_transfer.callback) 1731 (sc, umass_ccb, (sc->sc_transfer.data_len - 1732 sc->sc_transfer.actlen), STATUS_CMD_UNKNOWN); 1733 } 1734 } 1735 1736 static void 1737 umass_t_cbi_reset1_callback(struct usb_xfer *xfer, usb_error_t error) 1738 { 1739 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1740 struct usb_device_request req; 1741 struct usb_page_cache *pc; 1742 uint8_t buf[UMASS_CBI_DIAGNOSTIC_CMDLEN]; 1743 1744 uint8_t i; 1745 1746 switch (USB_GET_STATE(xfer)) { 1747 case USB_ST_TRANSFERRED: 1748 umass_transfer_start(sc, UMASS_T_CBI_RESET2); 1749 break; 1750 1751 case USB_ST_SETUP: 1752 /* 1753 * Command Block Reset Protocol 1754 * 1755 * First send a reset request to the device. Then clear 1756 * any possibly stalled bulk endpoints. 1757 * 1758 * This is done in 3 steps, using 3 transfers: 1759 * UMASS_T_CBI_RESET1 1760 * UMASS_T_CBI_RESET2 1761 * UMASS_T_CBI_RESET3 1762 * UMASS_T_CBI_RESET4 (only if there is an interrupt endpoint) 1763 */ 1764 1765 DPRINTF_UMASS(sc, UDMASS_CBI, "CBI reset!\n"); 1766 1767 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1768 req.bRequest = UR_CBI_ADSC; 1769 USETW(req.wValue, 0); 1770 req.wIndex[0] = sc->sc_iface_no; 1771 req.wIndex[1] = 0; 1772 USETW(req.wLength, UMASS_CBI_DIAGNOSTIC_CMDLEN); 1773 1774 /* 1775 * The 0x1d code is the SEND DIAGNOSTIC command. To 1776 * distinguish between the two, the last 10 bytes of the CBL 1777 * is filled with 0xff (section 2.2 of the CBI 1778 * specification) 1779 */ 1780 buf[0] = 0x1d; /* Command Block Reset */ 1781 buf[1] = 0x04; 1782 1783 for (i = 2; i < UMASS_CBI_DIAGNOSTIC_CMDLEN; i++) { 1784 buf[i] = 0xff; 1785 } 1786 1787 pc = usbd_xfer_get_frame(xfer, 0); 1788 usbd_copy_in(pc, 0, &req, sizeof(req)); 1789 pc = usbd_xfer_get_frame(xfer, 1); 1790 usbd_copy_in(pc, 0, buf, sizeof(buf)); 1791 1792 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1793 usbd_xfer_set_frame_len(xfer, 1, sizeof(buf)); 1794 usbd_xfer_set_frames(xfer, 2); 1795 usbd_transfer_submit(xfer); 1796 break; 1797 1798 default: /* Error */ 1799 if (error == USB_ERR_CANCELLED) 1800 umass_tr_error(xfer, error); 1801 else 1802 umass_transfer_start(sc, UMASS_T_CBI_RESET2); 1803 break; 1804 } 1805 } 1806 1807 static void 1808 umass_t_cbi_reset2_callback(struct usb_xfer *xfer, usb_error_t error) 1809 { 1810 umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_RESET3, 1811 UMASS_T_CBI_DATA_READ, error); 1812 } 1813 1814 static void 1815 umass_t_cbi_reset3_callback(struct usb_xfer *xfer, usb_error_t error) 1816 { 1817 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1818 1819 umass_t_cbi_data_clear_stall_callback 1820 (xfer, (sc->sc_xfer[UMASS_T_CBI_RESET4] && 1821 sc->sc_xfer[UMASS_T_CBI_STATUS]) ? 1822 UMASS_T_CBI_RESET4 : UMASS_T_CBI_COMMAND, 1823 UMASS_T_CBI_DATA_WRITE, error); 1824 } 1825 1826 static void 1827 umass_t_cbi_reset4_callback(struct usb_xfer *xfer, usb_error_t error) 1828 { 1829 umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_COMMAND, 1830 UMASS_T_CBI_STATUS, error); 1831 } 1832 1833 static void 1834 umass_t_cbi_data_clear_stall_callback(struct usb_xfer *xfer, 1835 uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error) 1836 { 1837 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1838 1839 switch (USB_GET_STATE(xfer)) { 1840 case USB_ST_TRANSFERRED: 1841 tr_transferred: 1842 if (next_xfer == UMASS_T_CBI_STATUS) { 1843 umass_cbi_start_status(sc); 1844 } else { 1845 umass_transfer_start(sc, next_xfer); 1846 } 1847 break; 1848 1849 case USB_ST_SETUP: 1850 if (usbd_clear_stall_callback(xfer, sc->sc_xfer[stall_xfer])) { 1851 goto tr_transferred; /* should not happen */ 1852 } 1853 break; 1854 1855 default: /* Error */ 1856 umass_tr_error(xfer, error); 1857 break; 1858 } 1859 } 1860 1861 static void 1862 umass_t_cbi_command_callback(struct usb_xfer *xfer, usb_error_t error) 1863 { 1864 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1865 union ccb *umass_ccb = sc->sc_transfer.ccb; 1866 struct usb_device_request req; 1867 struct usb_page_cache *pc; 1868 1869 switch (USB_GET_STATE(xfer)) { 1870 case USB_ST_TRANSFERRED: 1871 1872 if (sc->sc_transfer.dir == DIR_NONE) { 1873 umass_cbi_start_status(sc); 1874 } else { 1875 umass_transfer_start 1876 (sc, (sc->sc_transfer.dir == DIR_IN) ? 1877 UMASS_T_CBI_DATA_READ : UMASS_T_CBI_DATA_WRITE); 1878 } 1879 break; 1880 1881 case USB_ST_SETUP: 1882 1883 if (umass_ccb) { 1884 /* 1885 * do a CBI transfer with cmd_len bytes from 1886 * cmd_data, possibly a data phase of data_len 1887 * bytes from/to the device and finally a status 1888 * read phase. 1889 */ 1890 1891 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 1892 req.bRequest = UR_CBI_ADSC; 1893 USETW(req.wValue, 0); 1894 req.wIndex[0] = sc->sc_iface_no; 1895 req.wIndex[1] = 0; 1896 req.wLength[0] = sc->sc_transfer.cmd_len; 1897 req.wLength[1] = 0; 1898 1899 pc = usbd_xfer_get_frame(xfer, 0); 1900 usbd_copy_in(pc, 0, &req, sizeof(req)); 1901 pc = usbd_xfer_get_frame(xfer, 1); 1902 usbd_copy_in(pc, 0, sc->sc_transfer.cmd_data, 1903 sc->sc_transfer.cmd_len); 1904 1905 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1906 usbd_xfer_set_frame_len(xfer, 1, sc->sc_transfer.cmd_len); 1907 usbd_xfer_set_frames(xfer, 1908 sc->sc_transfer.cmd_len ? 2 : 1); 1909 1910 DIF(UDMASS_CBI, 1911 umass_cbi_dump_cmd(sc, 1912 sc->sc_transfer.cmd_data, 1913 sc->sc_transfer.cmd_len)); 1914 1915 usbd_transfer_submit(xfer); 1916 } 1917 break; 1918 1919 default: /* Error */ 1920 /* 1921 * STALL on the control pipe can be result of the command error. 1922 * Attempt to clear this STALL same as for bulk pipe also 1923 * results in command completion interrupt, but ASC/ASCQ there 1924 * look like not always valid, so don't bother about it. 1925 */ 1926 if ((error == USB_ERR_STALLED) || 1927 (sc->sc_transfer.callback == &umass_cam_cb)) { 1928 sc->sc_transfer.ccb = NULL; 1929 (sc->sc_transfer.callback) 1930 (sc, umass_ccb, sc->sc_transfer.data_len, 1931 STATUS_CMD_UNKNOWN); 1932 } else { 1933 umass_tr_error(xfer, error); 1934 /* skip reset */ 1935 sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND; 1936 } 1937 break; 1938 } 1939 } 1940 1941 static void 1942 umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error) 1943 { 1944 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 1945 uint32_t max_bulk = usbd_xfer_max_len(xfer); 1946 int actlen, sumlen; 1947 1948 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 1949 1950 switch (USB_GET_STATE(xfer)) { 1951 case USB_ST_TRANSFERRED: 1952 sc->sc_transfer.data_rem -= actlen; 1953 sc->sc_transfer.data_ptr += actlen; 1954 sc->sc_transfer.actlen += actlen; 1955 1956 if (actlen < sumlen) { 1957 /* short transfer */ 1958 sc->sc_transfer.data_rem = 0; 1959 } 1960 case USB_ST_SETUP: 1961 DPRINTF_UMASS(sc, UDMASS_CBI, "max_bulk=%d, data_rem=%d\n", 1962 max_bulk, sc->sc_transfer.data_rem); 1963 1964 if (sc->sc_transfer.data_rem == 0) { 1965 umass_cbi_start_status(sc); 1966 break; 1967 } 1968 if (max_bulk > sc->sc_transfer.data_rem) { 1969 max_bulk = sc->sc_transfer.data_rem; 1970 } 1971 usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); 1972 1973 usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, 1974 max_bulk); 1975 1976 usbd_transfer_submit(xfer); 1977 break; 1978 1979 default: /* Error */ 1980 if ((error == USB_ERR_CANCELLED) || 1981 (sc->sc_transfer.callback != &umass_cam_cb)) { 1982 umass_tr_error(xfer, error); 1983 } else { 1984 umass_transfer_start(sc, UMASS_T_CBI_DATA_RD_CS); 1985 } 1986 break; 1987 } 1988 } 1989 1990 static void 1991 umass_t_cbi_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error) 1992 { 1993 umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_STATUS, 1994 UMASS_T_CBI_DATA_READ, error); 1995 } 1996 1997 static void 1998 umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error) 1999 { 2000 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 2001 uint32_t max_bulk = usbd_xfer_max_len(xfer); 2002 int actlen, sumlen; 2003 2004 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 2005 2006 switch (USB_GET_STATE(xfer)) { 2007 case USB_ST_TRANSFERRED: 2008 sc->sc_transfer.data_rem -= actlen; 2009 sc->sc_transfer.data_ptr += actlen; 2010 sc->sc_transfer.actlen += actlen; 2011 2012 if (actlen < sumlen) { 2013 /* short transfer */ 2014 sc->sc_transfer.data_rem = 0; 2015 } 2016 case USB_ST_SETUP: 2017 DPRINTF_UMASS(sc, UDMASS_CBI, "max_bulk=%d, data_rem=%d\n", 2018 max_bulk, sc->sc_transfer.data_rem); 2019 2020 if (sc->sc_transfer.data_rem == 0) { 2021 umass_cbi_start_status(sc); 2022 break; 2023 } 2024 if (max_bulk > sc->sc_transfer.data_rem) { 2025 max_bulk = sc->sc_transfer.data_rem; 2026 } 2027 usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout); 2028 2029 usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr, 2030 max_bulk); 2031 2032 usbd_transfer_submit(xfer); 2033 break; 2034 2035 default: /* Error */ 2036 if ((error == USB_ERR_CANCELLED) || 2037 (sc->sc_transfer.callback != &umass_cam_cb)) { 2038 umass_tr_error(xfer, error); 2039 } else { 2040 umass_transfer_start(sc, UMASS_T_CBI_DATA_WR_CS); 2041 } 2042 break; 2043 } 2044 } 2045 2046 static void 2047 umass_t_cbi_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error) 2048 { 2049 umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_STATUS, 2050 UMASS_T_CBI_DATA_WRITE, error); 2051 } 2052 2053 static void 2054 umass_t_cbi_status_callback(struct usb_xfer *xfer, usb_error_t error) 2055 { 2056 struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer); 2057 union ccb *umass_ccb = sc->sc_transfer.ccb; 2058 struct usb_page_cache *pc; 2059 uint32_t residue; 2060 uint8_t status; 2061 int actlen; 2062 2063 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 2064 2065 switch (USB_GET_STATE(xfer)) { 2066 case USB_ST_TRANSFERRED: 2067 2068 if (actlen < (int)sizeof(sc->sbl)) { 2069 goto tr_setup; 2070 } 2071 pc = usbd_xfer_get_frame(xfer, 0); 2072 usbd_copy_out(pc, 0, &sc->sbl, sizeof(sc->sbl)); 2073 2074 residue = (sc->sc_transfer.data_len - 2075 sc->sc_transfer.actlen); 2076 2077 /* dissect the information in the buffer */ 2078 2079 if (sc->sc_proto & UMASS_PROTO_UFI) { 2080 /* 2081 * Section 3.4.3.1.3 specifies that the UFI command 2082 * protocol returns an ASC and ASCQ in the interrupt 2083 * data block. 2084 */ 2085 2086 DPRINTF_UMASS(sc, UDMASS_CBI, "UFI CCI, ASC = 0x%02x, " 2087 "ASCQ = 0x%02x\n", sc->sbl.ufi.asc, 2088 sc->sbl.ufi.ascq); 2089 2090 status = (((sc->sbl.ufi.asc == 0) && 2091 (sc->sbl.ufi.ascq == 0)) ? 2092 STATUS_CMD_OK : STATUS_CMD_FAILED); 2093 2094 sc->sc_transfer.ccb = NULL; 2095 2096 sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND; 2097 2098 (sc->sc_transfer.callback) 2099 (sc, umass_ccb, residue, status); 2100 2101 break; 2102 2103 } else { 2104 /* Command Interrupt Data Block */ 2105 2106 DPRINTF_UMASS(sc, UDMASS_CBI, "type=0x%02x, value=0x%02x\n", 2107 sc->sbl.common.type, sc->sbl.common.value); 2108 2109 if (sc->sbl.common.type == IDB_TYPE_CCI) { 2110 status = (sc->sbl.common.value & IDB_VALUE_STATUS_MASK); 2111 2112 status = ((status == IDB_VALUE_PASS) ? STATUS_CMD_OK : 2113 (status == IDB_VALUE_FAIL) ? STATUS_CMD_FAILED : 2114 (status == IDB_VALUE_PERSISTENT) ? STATUS_CMD_FAILED : 2115 STATUS_WIRE_FAILED); 2116 2117 sc->sc_transfer.ccb = NULL; 2118 2119 sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND; 2120 2121 (sc->sc_transfer.callback) 2122 (sc, umass_ccb, residue, status); 2123 2124 break; 2125 } 2126 } 2127 2128 /* fallthrough */ 2129 2130 case USB_ST_SETUP: 2131 tr_setup: 2132 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 2133 usbd_transfer_submit(xfer); 2134 break; 2135 2136 default: /* Error */ 2137 DPRINTF_UMASS(sc, UDMASS_CBI, "Failed to read CSW: %s\n", 2138 usbd_errstr(error)); 2139 umass_tr_error(xfer, error); 2140 break; 2141 } 2142 } 2143 2144 /* umass_cam_cb 2145 * finalise a completed CAM command 2146 */ 2147 2148 static void 2149 umass_cam_cb(struct umass_softc *sc, union ccb *umass_ccb, uint32_t residue, 2150 uint8_t status) 2151 { 2152 umass_ccb->csio.resid = residue; 2153 umass_ccb->csio.status = status; 2154 2155 switch (status) { 2156 case STATUS_CMD_OK: 2157 (void)LOS_EventWrite(&sc->sc_event, 0x01); 2158 break; 2159 2160 case STATUS_CMD_UNKNOWN: 2161 case STATUS_CMD_FAILED: 2162 /* fetch sense data */ 2163 (void)LOS_EventWrite(&sc->sc_event, 0x02); 2164 break; 2165 2166 default: 2167 (void)LOS_EventWrite(&sc->sc_event, 0x04); 2168 break; 2169 } 2170 } 2171 2172 /* 2173 * SCSI specific functions 2174 */ 2175 2176 static uint8_t 2177 umass_scsi_transform(struct umass_softc *sc, uint8_t *cmd_ptr, 2178 uint8_t cmd_len) 2179 { 2180 int ret; 2181 2182 if ((cmd_len == 0) || 2183 (cmd_len > sizeof(sc->sc_transfer.cmd_data))) { 2184 DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command " 2185 "length: %d bytes\n", cmd_len); 2186 return (0); /* failure */ 2187 } 2188 sc->sc_transfer.cmd_len = cmd_len; 2189 2190 switch (cmd_ptr[0]) { 2191 case TEST_UNIT_READY: 2192 if (sc->sc_quirks & NO_TEST_UNIT_READY) { 2193 DPRINTF_UMASS(sc, UDMASS_SCSI, "Converted TEST_UNIT_READY " 2194 "to START_UNIT\n"); 2195 ret = memset_s(sc->sc_transfer.cmd_data, sizeof(sc->sc_transfer.cmd_data), 0, cmd_len); 2196 if (ret != EOK) { 2197 usb_err("memset_s failed!, ret:%d\n", ret); 2198 return (0); 2199 } 2200 sc->sc_transfer.cmd_data[0] = START_STOP_UNIT; 2201 sc->sc_transfer.cmd_data[4] = SSS_START; 2202 return (1); 2203 } 2204 break; 2205 2206 case INQUIRY: 2207 /* 2208 * some drives wedge when asked for full inquiry 2209 * information. 2210 */ 2211 if (sc->sc_quirks & FORCE_SHORT_INQUIRY) { 2212 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2213 if (ret != EOK) { 2214 usb_err("memcpy_s failed!, ret:%d\n", ret); 2215 return (0); 2216 } 2217 sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH; 2218 return (1); 2219 } 2220 break; 2221 } 2222 2223 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2224 if (ret != EOK) { 2225 usb_err("memcpy_s failed!, ret:%d\n", ret); 2226 return (0); 2227 } 2228 2229 return (1); 2230 } 2231 2232 static uint8_t 2233 umass_rbc_transform(struct umass_softc *sc, uint8_t *cmd_ptr, uint8_t cmd_len) 2234 { 2235 int ret; 2236 2237 if ((cmd_len == 0) || 2238 (cmd_len > sizeof(sc->sc_transfer.cmd_data))) { 2239 DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command " 2240 "length: %d bytes\n", cmd_len); 2241 return (0); /* failure */ 2242 } 2243 switch (cmd_ptr[0]) { 2244 /* these commands are defined in RBC: */ 2245 case READ_10: 2246 case READ_CAPACITY: 2247 case START_STOP_UNIT: 2248 case SYNCHRONIZE_CACHE: 2249 case WRITE_10: 2250 case 0x2f: /* VERIFY_10 is absent from * scsi_all.h??? */ 2251 case INQUIRY: 2252 case MODE_SELECT_10: 2253 case MODE_SENSE_10: 2254 case TEST_UNIT_READY: 2255 case WRITE_BUFFER: 2256 /* 2257 * The following commands are not listed in my copy of the 2258 * RBC specs. CAM however seems to want those, and at least 2259 * the Sony DSC device appears to support those as well 2260 */ 2261 case REQUEST_SENSE: 2262 case PREVENT_ALLOW: 2263 2264 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2265 if (ret != EOK) { 2266 usb_err("memcpy_s failed!, ret:%d\n", ret); 2267 return (0); 2268 } 2269 2270 if ((sc->sc_quirks & RBC_PAD_TO_12) && (cmd_len < 12)) { 2271 ret = memset_s(sc->sc_transfer.cmd_data + cmd_len, 2272 (size_t)(UMASS_MAX_CMDLEN - cmd_len), 0, (size_t)(12 - cmd_len)); 2273 if (ret != EOK){ 2274 usb_err("memset_s failed!, ret:%d\n", ret); 2275 return (0); 2276 } 2277 cmd_len = 12; 2278 } 2279 sc->sc_transfer.cmd_len = cmd_len; 2280 return (1); /* sucess */ 2281 2282 /* All other commands are not legal in RBC */ 2283 default: 2284 DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported RBC " 2285 "command 0x%02x\n", cmd_ptr[0]); 2286 return (0); /* failure */ 2287 } 2288 } 2289 2290 static uint8_t 2291 umass_ufi_transform(struct umass_softc *sc, uint8_t *cmd_ptr, 2292 uint8_t cmd_len) 2293 { 2294 int ret; 2295 2296 if ((cmd_len == 0) || 2297 (cmd_len > sizeof(sc->sc_transfer.cmd_data))) { 2298 DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command " 2299 "length: %d bytes\n", cmd_len); 2300 return (0); /* failure */ 2301 } 2302 /* An UFI command is always 12 bytes in length */ 2303 sc->sc_transfer.cmd_len = UFI_COMMAND_LENGTH; 2304 2305 /* Zero the command data */ 2306 ret = memset_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, 0, UFI_COMMAND_LENGTH); 2307 if (ret != EOK) { 2308 usb_err("memset_s failed!, ret:%d\n", ret); 2309 return (0); 2310 } 2311 2312 switch (cmd_ptr[0]) { 2313 /* 2314 * Commands of which the format has been verified. They 2315 * should work. Copy the command into the (zeroed out) 2316 * destination buffer. 2317 */ 2318 case TEST_UNIT_READY: 2319 if (sc->sc_quirks & NO_TEST_UNIT_READY) { 2320 /* 2321 * Some devices do not support this command. Start 2322 * Stop Unit should give the same results 2323 */ 2324 DPRINTF_UMASS(sc, UDMASS_UFI, "Converted TEST_UNIT_READY " 2325 "to START_UNIT\n"); 2326 2327 sc->sc_transfer.cmd_data[0] = START_STOP_UNIT; 2328 sc->sc_transfer.cmd_data[4] = SSS_START; 2329 return (1); 2330 } 2331 break; 2332 2333 case REZERO_UNIT: 2334 case REQUEST_SENSE: 2335 case FORMAT_UNIT: 2336 case INQUIRY: 2337 case START_STOP_UNIT: 2338 case SEND_DIAGNOSTIC: 2339 case PREVENT_ALLOW: 2340 case READ_CAPACITY: 2341 case READ_10: 2342 case WRITE_10: 2343 case POSITION_TO_ELEMENT: /* SEEK_10 */ 2344 case WRITE_AND_VERIFY: 2345 case VERIFIED: 2346 case MODE_SELECT_10: 2347 case MODE_SENSE_10: 2348 case READ_12: 2349 case WRITE_12: 2350 case READ_FORMAT_CAPACITIES: 2351 break; 2352 2353 /* 2354 * SYNCHRONIZE_CACHE isn't supported by UFI, nor should it be 2355 * required for UFI devices, so it is appropriate to fake 2356 * success. 2357 */ 2358 case SYNCHRONIZE_CACHE: 2359 return (2); 2360 2361 default: 2362 DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported UFI " 2363 "command 0x%02x\n", cmd_ptr[0]); 2364 return (0); /* failure */ 2365 } 2366 2367 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2368 if (ret != EOK) { 2369 usb_err("memcpy_s failed!, ret:%d\n", ret); 2370 return (0); 2371 } 2372 2373 return (1); /* success */ 2374 } 2375 2376 /* 2377 * 8070i (ATAPI) specific functions 2378 */ 2379 static uint8_t 2380 umass_atapi_transform(struct umass_softc *sc, uint8_t *cmd_ptr, 2381 uint8_t cmd_len) 2382 { 2383 int ret; 2384 2385 if ((cmd_len == 0) || 2386 (cmd_len > sizeof(sc->sc_transfer.cmd_data))) { 2387 DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command " 2388 "length: %d bytes\n", cmd_len); 2389 return (0); /* failure */ 2390 } 2391 /* An ATAPI command is always 12 bytes in length. */ 2392 sc->sc_transfer.cmd_len = ATAPI_COMMAND_LENGTH; 2393 2394 /* Zero the command data */ 2395 ret = memset_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, 0, ATAPI_COMMAND_LENGTH); 2396 if (ret != EOK) { 2397 usb_err("memset_s failed!, ret:%d\n", ret); 2398 return (0); 2399 } 2400 2401 switch (cmd_ptr[0]) { 2402 /* 2403 * Commands of which the format has been verified. They 2404 * should work. Copy the command into the destination 2405 * buffer. 2406 */ 2407 case INQUIRY: 2408 /* 2409 * some drives wedge when asked for full inquiry 2410 * information. 2411 */ 2412 if (sc->sc_quirks & FORCE_SHORT_INQUIRY) { 2413 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2414 if (ret != EOK) { 2415 usb_err("memcpy_s failed!, ret:%d\n", ret); 2416 return (0); 2417 } 2418 sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH; 2419 return (1); 2420 } 2421 break; 2422 2423 case TEST_UNIT_READY: 2424 if (sc->sc_quirks & NO_TEST_UNIT_READY) { 2425 DPRINTF_UMASS(sc, UDMASS_SCSI, "Converted TEST_UNIT_READY " 2426 "to START_UNIT\n"); 2427 sc->sc_transfer.cmd_data[0] = START_STOP_UNIT; 2428 sc->sc_transfer.cmd_data[4] = SSS_START; 2429 return (1); 2430 } 2431 break; 2432 2433 case REZERO_UNIT: 2434 case REQUEST_SENSE: 2435 case START_STOP_UNIT: 2436 case SEND_DIAGNOSTIC: 2437 case PREVENT_ALLOW: 2438 case READ_CAPACITY: 2439 case READ_10: 2440 case WRITE_10: 2441 case POSITION_TO_ELEMENT: /* SEEK_10 */ 2442 case SYNCHRONIZE_CACHE: 2443 case MODE_SELECT_10: 2444 case MODE_SENSE_10: 2445 case READ_BUFFER: 2446 case 0x42: /* READ_SUBCHANNEL */ 2447 case 0x43: /* READ_TOC */ 2448 case 0x44: /* READ_HEADER */ 2449 case 0x47: /* PLAY_MSF (Play Minute/Second/Frame) */ 2450 case 0x48: /* PLAY_TRACK */ 2451 case 0x49: /* PLAY_TRACK_REL */ 2452 case 0x4b: /* PAUSE */ 2453 case 0x51: /* READ_DISK_INFO */ 2454 case 0x52: /* READ_TRACK_INFO */ 2455 case 0x54: /* SEND_OPC */ 2456 case 0x59: /* READ_MASTER_CUE */ 2457 case 0x5b: /* CLOSE_TR_SESSION */ 2458 case 0x5c: /* READ_BUFFER_CAP */ 2459 case 0x5d: /* SEND_CUE_SHEET */ 2460 case 0xa1: /* BLANK */ 2461 case 0xa5: /* PLAY_12 */ 2462 case 0xa6: /* EXCHANGE_MEDIUM */ 2463 case 0xad: /* READ_DVD_STRUCTURE */ 2464 case 0xbb: /* SET_CD_SPEED */ 2465 case 0xe5: /* READ_TRACK_INFO_PHILIPS */ 2466 break; 2467 2468 case READ_12: 2469 case WRITE_12: 2470 default: 2471 DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported ATAPI " 2472 "command 0x%02x - trying anyway\n", 2473 cmd_ptr[0]); 2474 break; 2475 } 2476 2477 ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len); 2478 if (ret != EOK) { 2479 usb_err("memcpy_s failed!, ret:%d\n", ret); 2480 return (0); 2481 } 2482 2483 return (1); /* success */ 2484 } 2485 2486 static uint8_t 2487 umass_no_transform(struct umass_softc *sc, uint8_t *cmd, 2488 uint8_t cmdlen) 2489 { 2490 return (0); /* failure */ 2491 } 2492 2493 #ifdef LOSCFG_USB_DEBUG 2494 static void 2495 umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) 2496 { 2497 uint8_t *c = cbw->CBWCDB; 2498 2499 uint32_t dlen = UGETDW(cbw->dCBWDataTransferLength); 2500 uint32_t tag = UGETDW(cbw->dCBWTag); 2501 2502 uint8_t clen = cbw->bCDBLength; 2503 uint8_t flags = cbw->bCBWFlags; 2504 uint8_t lun = cbw->bCBWLUN; 2505 2506 DPRINTF_UMASS(sc, UDMASS_BBB, "CBW %d: cmd = %db " 2507 "(0x%02x%02x%02x%02x%02x%02x%s), " 2508 "data = %db, lun = %d, dir = %s\n", 2509 tag, clen, 2510 c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6 ? "..." : ""), 2511 dlen, lun, (flags == CBWFLAGS_IN ? "in" : 2512 (flags == CBWFLAGS_OUT ? "out" : "<invalid>"))); 2513 } 2514 2515 static void 2516 umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw) 2517 { 2518 uint32_t sig = UGETDW(csw->dCSWSignature); 2519 uint32_t tag = UGETDW(csw->dCSWTag); 2520 uint32_t res = UGETDW(csw->dCSWDataResidue); 2521 uint8_t status = csw->bCSWStatus; 2522 2523 DPRINTF_UMASS(sc, UDMASS_BBB, "CSW %d: sig = 0x%08x (%s), tag = 0x%08x, " 2524 "res = %d, status = 0x%02x (%s)\n", 2525 tag, sig, (sig == CSWSIGNATURE ? "valid" : "invalid"), 2526 tag, res, 2527 status, (status == CSWSTATUS_GOOD ? "good" : 2528 (status == CSWSTATUS_FAILED ? "failed" : 2529 (status == CSWSTATUS_PHASE ? "phase" : "<invalid>")))); 2530 } 2531 2532 static void 2533 umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, uint8_t cmdlen) 2534 { 2535 uint8_t *c = cmd; 2536 uint8_t dir = sc->sc_transfer.dir; 2537 2538 DPRINTF_UMASS(sc, UDMASS_BBB, "cmd = %db " 2539 "(0x%02x%02x%02x%02x%02x%02x%s), " 2540 "data = %db, dir = %s\n", 2541 cmdlen, 2542 c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6 ? "..." : ""), 2543 sc->sc_transfer.data_len, 2544 (dir == DIR_IN ? "in" : 2545 (dir == DIR_OUT ? "out" : 2546 (dir == DIR_NONE ? "no data phase" : "<invalid>")))); 2547 } 2548 2549 #endif 2550 2551 #define SCSI_INQ_LEN 0x24 2552 2553 static uint8_t scsi_test_unit_ready[] = { 2554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 2555 }; 2556 static uint8_t scsi_inquiry[] = { 2557 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 2558 }; 2559 static uint8_t scsi_request_sense[] = { 2560 0x03, 0x00, 0x00, 0x00, 0x12, 0x00, 2561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 2562 }; 2563 static uint8_t scsi_read_capacity[] = { 2564 0x25, 0x00, 0x00, 0x00, 0x00, 2565 0x00, 0x00, 0x00, 0x00, 0x00 2566 }; 2567 2568 static uint8_t scsi_read_capacity_16[] = { 2569 0x9e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2570 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00 2571 }; 2572 2573 /* Description: Get a (possibly unaligned) 16-bit big endian value. */ 2574 static inline uint16_t 2575 usbhost_getbe16(const uint8_t *val) 2576 { 2577 return ((uint16_t)val[0] << 8 | (uint16_t)val[1]); 2578 } 2579 2580 /* Description: Put a (possibly unaligned) 16-bit little endian value. */ 2581 void 2582 usbhost_putle16(uint8_t *dest, uint16_t val) 2583 { 2584 dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */ 2585 dest[1] = val >> 8; 2586 } 2587 2588 /* Description: Put a (possibly unaligned) 16-bit big endian value. */ 2589 void 2590 usbhost_putbe16(uint8_t *dest, uint16_t val) 2591 { 2592 dest[0] = val >> 8; /* Big endian means MS byte first in byte stream */ 2593 dest[1] = val & 0xff; 2594 } 2595 2596 /* Description: Get a (possibly unaligned) 32-bit big endian value. */ 2597 uint32_t 2598 usbhost_getbe32(const uint8_t *val) 2599 { 2600 /* Big endian means MS halfword first in byte stream */ 2601 return ((uint32_t)usbhost_getbe16(val) << 16 | 2602 (uint32_t)usbhost_getbe16(&val[2])); 2603 } 2604 2605 /* Description: Get a (possibly unaligned) 64-bit big endian value. */ 2606 uint64_t 2607 usbhost_getbe64(const uint8_t *val) 2608 { 2609 /* Big endian means MS halfword first in byte stream */ 2610 return ((uint64_t)usbhost_getbe32(val) << 32 | 2611 (uint64_t)usbhost_getbe32(&val[4])); 2612 } 2613 2614 /* Description: Put a (possibly unaligned) 32-bit little endian value. */ 2615 void 2616 usbhost_putle32(uint8_t *dest, uint32_t val) 2617 { 2618 /* Little endian means LS halfword first in byte stream */ 2619 usbhost_putle16(dest, (uint16_t)(val & 0xffff)); 2620 usbhost_putle16(dest+2, (uint16_t)(val >> 16)); 2621 } 2622 2623 /* Put a (possibly unaligned) 32-bit big endian value. */ 2624 void 2625 usbhost_putbe32(uint8_t *dest, uint32_t val) 2626 { 2627 /* Big endian means MS halfword first in byte stream */ 2628 usbhost_putbe16(dest, (uint16_t)(val >> 16)); 2629 usbhost_putbe16(dest+2, (uint16_t)(val & 0xffff)); 2630 } 2631 2632 /* Put a (possibly unaligned) 64-bit big endian value. */ 2633 void 2634 usbhost_putbe64(uint8_t *dest, uint64_t val) 2635 { 2636 /* Big endian means MS halfword first in byte stream */ 2637 usbhost_putbe32(dest, (uint32_t)(val >> 32)); 2638 usbhost_putbe32(dest+4, (uint32_t)(val & 0xffffffff)); 2639 } 2640 2641 void 2642 usbhost_readcdb16(uint64_t startsector, uint16_t blocksize, 2643 unsigned int nsectors, struct scsicmd_read16_s *cdb) 2644 { 2645 struct scsicmd_read16_s *rd16 = (struct scsicmd_read16_s *)cdb; 2646 2647 /* Format the CDB */ 2648 rd16->opcode = SCSI_CMD_READ16; 2649 usbhost_putbe64(rd16->lba, startsector); 2650 usbhost_putbe32(rd16->xfrlen, nsectors); 2651 } 2652 2653 void 2654 usbhost_readcdb10(size_t startsector, uint16_t blocksize, 2655 unsigned int nsectors, struct scsicmd_read10_s *cdb) 2656 { 2657 struct scsicmd_read10_s *rd10 = (struct scsicmd_read10_s *)cdb; 2658 2659 /* Format the CDB */ 2660 rd10->opcode = SCSI_CMD_READ10; 2661 usbhost_putbe32(rd10->lba, startsector); 2662 usbhost_putbe16(rd10->xfrlen, nsectors); 2663 } 2664 2665 void 2666 usbhost_writecbw16(uint64_t startsector, uint16_t blocksize, 2667 unsigned int nsectors, struct scsicmd_write16_s *cdb) 2668 { 2669 struct scsicmd_write16_s *wr16 = (struct scsicmd_write16_s *)cdb; 2670 2671 wr16->opcode = SCSI_CMD_WRITE16; 2672 usbhost_putbe64(wr16->lba, startsector); 2673 usbhost_putbe32(wr16->xfrlen, nsectors); 2674 } 2675 2676 void 2677 usbhost_writecbw10(size_t startsector, uint16_t blocksize, 2678 unsigned int nsectors, struct scsicmd_write10_s *cdb) 2679 { 2680 struct scsicmd_write10_s *wr10 = (struct scsicmd_write10_s *)cdb; 2681 2682 wr10->opcode = SCSI_CMD_WRITE10; 2683 usbhost_putbe32(wr10->lba, startsector); 2684 usbhost_putbe16(wr10->xfrlen, nsectors); 2685 } 2686 2687 int 2688 umass_test_unit_ready(struct umass_softc *sc) 2689 { 2690 uint32_t status; 2691 int32_t res; 2692 2693 if((sc == NULL) || (sc->data_ccb == NULL)) { 2694 return (-1); 2695 } 2696 2697 (void)umass_scsi_transform(sc, scsi_test_unit_ready, SCSICMD_TESTUNITREADY8_SIZEOF); 2698 res = umass_command_start(sc, DIR_NONE, NULL, 0, 1000, umass_cam_cb, sc->data_ccb); 2699 if (STATUS_CMD_OK != res) { 2700 return (-1); 2701 } 2702 2703 status = sc->data_ccb->csio.status; 2704 if (status != STATUS_CMD_OK) { 2705 return (-1); 2706 } 2707 2708 return (0); 2709 } 2710 2711 int 2712 umass_read_capacity_16(struct umass_softc *sc) 2713 { 2714 struct scsiresp_readcapacity16_s resp; 2715 uint32_t res; 2716 int ret; 2717 2718 (void)umass_scsi_transform(sc, scsi_read_capacity_16, SCSICMD_READCAPACITY16_SIZEOF); 2719 res = (uint32_t)umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, 2720 (uint32_t)SCSIRESP_READCAPACITY16_SIZEOF, 2721 (uint32_t)1000, umass_cam_cb, sc->data_ccb); 2722 if (STATUS_CMD_OK != res) { 2723 return (-1); 2724 } 2725 2726 ret = memcpy_s((void *)&resp, sizeof(resp), sc->data_ccb->csio.data_ptr, 2727 SCSIRESP_READCAPACITY16_SIZEOF); 2728 if (ret != EOK) { 2729 usb_err("memcpy_s failed, %d\n", ret); 2730 return (-1); 2731 } 2732 2733 sc->info.sectornum= usbhost_getbe64(resp.lba) + 1; 2734 sc->info.sectorsize= usbhost_getbe32(resp.blklen); 2735 2736 return (0); 2737 } 2738 2739 int 2740 umass_read_capacity(struct umass_softc *sc) 2741 { 2742 struct scsiresp_readcapacity10_s resp; 2743 int32_t ret; 2744 2745 if ((sc == NULL) || (sc->data_ccb == NULL)) { 2746 return (-1); 2747 } 2748 2749 (void)umass_scsi_transform(sc, scsi_read_capacity, SCSICMD_READCAPACITY10_SIZEOF); 2750 ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, 2751 SCSIRESP_READCAPACITY10_SIZEOF, 2752 1000, umass_cam_cb, sc->data_ccb); 2753 if (STATUS_CMD_OK != ret) { 2754 return (-1); 2755 } 2756 2757 ret = memcpy_s((void *)&resp, sizeof(resp), sc->data_ccb->csio.data_ptr, 2758 SCSIRESP_READCAPACITY10_SIZEOF); 2759 if (ret != EOK) { 2760 usb_err("memcpy_s failed, %d\n", ret); 2761 return (-1); 2762 } 2763 2764 /* The disk Capacity is bigger than 2T */ 2765 if (usbhost_getbe32(resp.lba) == 0xffffffff) { 2766 ret = umass_read_capacity_16(sc); 2767 if (ret != 0) { 2768 usb_err("Read Capacity failed, %d\n", ret); 2769 return (-1); 2770 } 2771 sc->sc_super_disk = TRUE; 2772 2773 return (0); 2774 } 2775 2776 sc->info.sectornum= usbhost_getbe32(resp.lba) + 1; 2777 sc->info.sectorsize= usbhost_getbe32(resp.blklen); 2778 sc->sc_super_disk = FALSE; 2779 2780 return (0); 2781 } 2782 2783 int 2784 umass_read10(struct umass_softc *sc, size_t startsector, uint16_t blocksize, 2785 unsigned int nsectors, unsigned char *buf) 2786 { 2787 struct scsicmd_read10_s cdb; 2788 uint8_t *data_buf = buf; 2789 uint32_t status; 2790 int32_t ret; 2791 uint32_t flag = 0; 2792 2793 if ((sc == NULL) || (sc->data_ccb == NULL)) { 2794 return (-1); 2795 } 2796 2797 if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize)) 2798 return (-1); 2799 2800 if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) 2801 { 2802 data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize)); 2803 if (data_buf == NULL) { 2804 PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__); 2805 return (-1); 2806 } 2807 flag = 1; 2808 } 2809 2810 (void)memset_s(&cdb, sizeof(struct scsicmd_read10_s), 0, sizeof(struct scsicmd_read10_s)); 2811 usbhost_readcdb10(startsector, blocksize, nsectors, &cdb); 2812 (void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_READ10_SIZEOF); 2813 ret = umass_command_start(sc, DIR_IN, (void *)data_buf, blocksize * nsectors, 0, 2814 umass_cam_cb, sc->data_ccb); 2815 if (ret != STATUS_CMD_OK) { 2816 if (flag == 1) 2817 free(data_buf); 2818 return (-1); 2819 } 2820 2821 if (flag == 1) { 2822 if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors - sc->data_ccb->csio.resid)) { 2823 ret = memcpy_s(buf, nsectors * blocksize, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid); 2824 } else { 2825 ret = ((nsectors * blocksize >= blocksize * nsectors - sc->data_ccb->csio.resid) ? 2826 LOS_ArchCopyToUser(buf, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid) : ERANGE_AND_RESET); 2827 } 2828 free(data_buf); 2829 if (ret != EOK) { 2830 return (-1); 2831 } 2832 } 2833 2834 status = sc->data_ccb->csio.status; 2835 if (status != STATUS_CMD_OK) { 2836 return (-1); 2837 } 2838 2839 return (0); 2840 } 2841 2842 int 2843 umass_read16(struct umass_softc *sc, uint64_t startsector, uint16_t blocksize, 2844 unsigned int nsectors, unsigned char *buf) 2845 { 2846 struct scsicmd_read16_s cdb; 2847 uint8_t *data_buf = buf; 2848 uint32_t status; 2849 uint32_t res; 2850 uint32_t flag = 0; 2851 int ret; 2852 2853 if ((sc == NULL) || (sc->data_ccb == NULL)) { 2854 return (-1); 2855 } 2856 2857 if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize)) 2858 return (-1); 2859 2860 if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) { 2861 data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize)); 2862 if (data_buf == NULL) { 2863 PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__); 2864 return (-1); 2865 } 2866 flag = 1; 2867 } 2868 2869 (void)memset_s(&cdb, sizeof(struct scsicmd_read16_s), 0, sizeof(struct scsicmd_read16_s)); 2870 usbhost_readcdb16(startsector, blocksize, nsectors, &cdb); 2871 (void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_READ16_SIZEOF); 2872 res = umass_command_start(sc, DIR_IN, (void *)data_buf, blocksize * nsectors, 0, 2873 umass_cam_cb, sc->data_ccb); 2874 if (STATUS_CMD_OK != res) { 2875 if (flag == 1) 2876 free(data_buf); 2877 return (-1); 2878 } 2879 2880 if (flag == 1) { 2881 if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors - sc->data_ccb->csio.resid)) { 2882 ret = memcpy_s(buf, nsectors * blocksize, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid); 2883 } else { 2884 ret = ((nsectors * blocksize >= blocksize * nsectors - sc->data_ccb->csio.resid) ? 2885 LOS_ArchCopyToUser(buf, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid) : ERANGE_AND_RESET); 2886 } 2887 free(data_buf); 2888 if (ret != EOK) { 2889 return (-1); 2890 } 2891 } 2892 2893 status = sc->data_ccb->csio.status; 2894 if (status != STATUS_CMD_OK) { 2895 return (-1); 2896 } 2897 2898 return (0); 2899 } 2900 2901 int 2902 umass_write10(struct umass_softc *sc, size_t startsector, uint16_t blocksize, 2903 unsigned int nsectors, const unsigned char *buf) 2904 { 2905 struct scsicmd_write10_s cdb; 2906 uint8_t *data_buf = (uint8_t *)buf; 2907 uint32_t status; 2908 int32_t ret; 2909 uint32_t flag = 0; 2910 2911 if((sc == NULL) || (sc->data_ccb == NULL)) { 2912 return (-1); 2913 } 2914 2915 if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize)) 2916 return (-1); 2917 2918 if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) { 2919 data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize)); 2920 if (data_buf == NULL) { 2921 PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__); 2922 return (-1); 2923 } 2924 2925 if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors)) { 2926 (void)memcpy_s(data_buf, blocksize * nsectors, buf, blocksize * nsectors); 2927 } else { 2928 ret = LOS_ArchCopyFromUser(data_buf, buf, blocksize * nsectors); 2929 if (ret != 0) { 2930 free(data_buf); 2931 PRINT_ERR("copy failed!->%s %d\n", __FUNCTION__, __LINE__); 2932 return (-1); 2933 } 2934 } 2935 flag = 1; 2936 } 2937 2938 (void)memset_s(&cdb, sizeof(struct scsicmd_write10_s), 0, sizeof(struct scsicmd_write10_s)); 2939 usbhost_writecbw10(startsector, blocksize, nsectors, &cdb); 2940 (void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_WRITE10_SIZEOF); 2941 ret = umass_command_start(sc, DIR_OUT, (void *)data_buf, blocksize * nsectors, 1000, 2942 umass_cam_cb, sc->data_ccb); 2943 2944 if (flag == 1) { 2945 free(data_buf); 2946 } 2947 2948 status = sc->data_ccb->csio.status; 2949 if ((ret != STATUS_CMD_OK) || (status != STATUS_CMD_OK)) { 2950 return (-1); 2951 } 2952 2953 return (0); 2954 } 2955 2956 int 2957 umass_write16(struct umass_softc *sc, uint64_t startsector, uint16_t blocksize, 2958 unsigned int nsectors, const unsigned char *buf) 2959 { 2960 struct scsicmd_write16_s cdb; 2961 uint8_t *data_buf = (uint8_t *)buf; 2962 uint32_t status; 2963 int32_t res; 2964 int32_t ret; 2965 uint32_t flag = 0; 2966 2967 if((sc == NULL) || (sc->data_ccb == NULL)) { 2968 return (-1); 2969 } 2970 2971 if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize)) { 2972 return (-1); 2973 } 2974 2975 if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) 2976 { 2977 data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize)); 2978 if (data_buf == NULL) { 2979 PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__); 2980 return (-1); 2981 } 2982 2983 if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors)) { 2984 (void)memcpy_s(data_buf, blocksize * nsectors, buf, blocksize * nsectors); 2985 } else { 2986 ret = LOS_ArchCopyFromUser(data_buf, buf, blocksize * nsectors); 2987 if (ret != 0) { 2988 free(data_buf); 2989 PRINT_ERR("copy failed!->%s %d\n", __FUNCTION__, __LINE__); 2990 return (-1); 2991 } 2992 } 2993 flag = 1; 2994 } 2995 2996 (void)memset_s(&cdb, sizeof(struct scsicmd_write16_s), 0, sizeof(struct scsicmd_write16_s)); 2997 usbhost_writecbw16(startsector, blocksize, nsectors, &cdb); 2998 (void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_WRITE16_SIZEOF); 2999 res = umass_command_start(sc, DIR_OUT, (void *)data_buf, blocksize * nsectors, 1000, 3000 umass_cam_cb, sc->data_ccb); 3001 3002 if (flag == 1) 3003 { 3004 free(data_buf); 3005 } 3006 3007 status = sc->data_ccb->csio.status; 3008 if ((res != STATUS_CMD_OK) || (status != STATUS_CMD_OK)) { 3009 return (-1); 3010 } 3011 3012 return (0); 3013 } 3014 3015 int 3016 umass_inquiry(struct umass_softc *sc) 3017 { 3018 uint32_t status; 3019 int32_t ret; 3020 3021 if ((sc == NULL) || (sc->data_ccb == NULL)) { 3022 goto error; 3023 } 3024 3025 (void)umass_scsi_transform(sc, scsi_inquiry, SCSICMD_INQUIRY_SIZEOF); 3026 ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, SCSIRESP_INQUIRY_SIZEOF, 3027 1000, umass_cam_cb, sc->data_ccb); 3028 if (ret != STATUS_CMD_OK) { 3029 goto error; 3030 } 3031 3032 status = sc->data_ccb->csio.status; 3033 if (status != STATUS_CMD_OK) { 3034 PRINT_WARN("Failed to get the inquiry_status [status=%d].\n", status); 3035 goto error; 3036 } 3037 3038 ret = umass_scsi_inquiry_data(sc, sc->data_ccb->csio.data_ptr, SCSIRESP_INQUIRY_SIZEOF); 3039 if (ret == -1){ 3040 PRINT_WARN("Failed to get the scsi_inquiry data .\n"); 3041 goto error; 3042 }else if (ret == 1) { 3043 /* find Direct-access LUN */ 3044 return (0); 3045 } 3046 3047 error: 3048 return (-1); 3049 } 3050 3051 int 3052 umass_request_sense(struct umass_softc *sc) 3053 { 3054 uint32_t status; 3055 int32_t ret; 3056 if ((sc == NULL) || (sc->data_ccb == NULL)) { 3057 return (-1); 3058 } 3059 3060 (void)umass_scsi_transform(sc, scsi_request_sense, SCSICMD_REQUESTSENSE_SIZEOF); 3061 ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, SCSIRESP_FIXEDSENSEDATA_SIZEOF, 3062 1000, umass_cam_cb, sc->data_ccb); 3063 if (ret != STATUS_CMD_OK) { 3064 return (-1); 3065 } 3066 3067 status = sc->data_ccb->csio.status; 3068 if (status != STATUS_CMD_OK) { 3069 return (-1); 3070 } 3071 3072 return (0); 3073 } 3074 3075 void * 3076 umass_bind(void) 3077 { 3078 return ((void*)p_umsf); 3079 } 3080 3081 void 3082 umass_status(void) 3083 { 3084 struct umass_softc *sc = p_umsf; 3085 UINT8 cmd; 3086 UINT8 lun; 3087 UINT8 max; 3088 UINT8 speed; 3089 UINT8 phase; 3090 UINT8 state; 3091 UINT16 vid; 3092 UINT16 pid; 3093 UINT32 tag, residuce; 3094 3095 if (sc == NULL) { 3096 return; 3097 } 3098 3099 cmd = sc->sc_transfer.cmd_data[0]; 3100 lun = sc->sc_transfer.lun; 3101 max = sc->sc_maxlun + 1; 3102 speed = sc->sc_udev->speed; 3103 phase = sc->sc_last_xfer_index; 3104 state = USB_GET_STATE(sc->sc_xfer[phase]); 3105 vid = UGETW(sc->sc_udev->ddesc.idVendor); 3106 pid = UGETW(sc->sc_udev->ddesc.idProduct); 3107 tag = UGETDW(sc->cbw.dCBWTag); 3108 residuce = UGETDW(sc->csw.dCSWDataResidue); 3109 3110 dprintf("VID:%04X/PID:%04X/SPD:%02d",vid,pid,speed); 3111 if (sc->sc_transfer.ccb) { 3112 dprintf("/ST:%02d ",state); 3113 if (state == USB_ST_SETUP) { 3114 dprintf("[SP]"); 3115 } else if (state == USB_ST_TRANSFERRED) { 3116 dprintf("[TD]"); 3117 } 3118 dprintf("/cPHASE:%02d ",phase); 3119 } else { 3120 dprintf("/nPHASE:%02d ",phase); 3121 } 3122 if (phase == UMASS_T_BBB_COMMAND) { 3123 dprintf("[CBW]"); 3124 } else if (phase == UMASS_T_BBB_DATA_READ) { 3125 dprintf("[DATA]"); 3126 } else if (phase == UMASS_T_BBB_DATA_WRITE) { 3127 dprintf("[DATA]"); 3128 } else if (phase == UMASS_T_BBB_STATUS) { 3129 dprintf("[CSW]"); 3130 } else if (phase == UMASS_T_BBB_DATA_RD_CS) { 3131 dprintf("[STAL]"); 3132 } else if (phase == UMASS_T_BBB_DATA_WR_CS) { 3133 dprintf("[STAL]"); 3134 } 3135 dprintf("\n"); 3136 3137 dprintf("CL:%d/ML:%d/TG:%08X/RDU:%d/CMD:%X ",lun,max,tag,residuce,cmd); 3138 if (cmd == SCSI_CMD_READ10) { 3139 dprintf("[RD]\n"); 3140 } else if (cmd == SCSI_CMD_WRITE10) { 3141 dprintf("[WR]\n"); 3142 } else if (cmd == SCSI_CMD_INQUIRY) { 3143 dprintf("[INQ]\n"); 3144 } else if (cmd == SCSI_CMD_TESTUNITREADY) { 3145 dprintf("[TUR]\n"); 3146 } else if (cmd == SCSI_CMD_REQUESTSENSE) { 3147 dprintf("[RS]\n"); 3148 } else if (cmd == SCSI_CMD_READCAPACITY10) { 3149 dprintf("[RC]\n"); 3150 } else { 3151 dprintf("\n"); 3152 } 3153 } 3154 3155 static int 3156 umass_open(struct Vnode *filep) 3157 { 3158 (void)filep; 3159 return (0); 3160 } 3161 3162 static int 3163 umass_close(struct Vnode *filep) 3164 { 3165 (void)filep; 3166 return (0); 3167 } 3168 3169 static ssize_t 3170 umass_read(struct Vnode *umass_inode, unsigned char *buffer, 3171 uint64_t start_sector, unsigned int nsectors) 3172 { 3173 int status; 3174 struct umass_softc *sc = (struct umass_softc *)((struct drv_data*)umass_inode->data)->priv; 3175 3176 mtx_lock(&sc->sc_umass_mtx); 3177 if (sc->sc_super_disk == TRUE) { 3178 status = umass_read16(sc, start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer); 3179 } else { 3180 status = umass_read10(sc, (size_t)start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer); 3181 } 3182 mtx_unlock(&sc->sc_umass_mtx); 3183 3184 if(status) 3185 return (-1); 3186 else 3187 return ((ssize_t)nsectors); 3188 } 3189 3190 static ssize_t 3191 umass_write(struct Vnode *umass_inode, const unsigned char *buffer, 3192 uint64_t start_sector, unsigned int nsectors) 3193 { 3194 int status; 3195 struct umass_softc *sc = (struct umass_softc *)((struct drv_data*)umass_inode->data)->priv; 3196 3197 mtx_lock(&sc->sc_umass_mtx); 3198 if (sc->sc_super_disk == TRUE) { 3199 status = umass_write16(sc, start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer); 3200 } else { 3201 status = umass_write10(sc, (size_t)start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer); 3202 } 3203 mtx_unlock(&sc->sc_umass_mtx); 3204 3205 if(status) 3206 return (-1); 3207 else 3208 return ((ssize_t)nsectors); 3209 } 3210 3211 static int 3212 umass_geometry(struct Vnode *umass_inode, struct geometry *ugeometry) 3213 { 3214 struct umass_softc *sc; 3215 3216 if ((ugeometry == NULL) || (umass_inode == NULL)) 3217 return (-1); 3218 3219 sc = (struct umass_softc *)(struct umass_softc *)((struct drv_data*)umass_inode->data)->priv; 3220 3221 if (sc == NULL) 3222 return (-1); 3223 3224 mtx_lock(&sc->sc_umass_mtx); 3225 ugeometry->geo_available = true; 3226 ugeometry->geo_mediachanged = false; 3227 ugeometry->geo_writeenabled = true; 3228 ugeometry->geo_nsectors = sc->info.sectornum; 3229 ugeometry->geo_sectorsize = sc->info.sectorsize; 3230 mtx_unlock(&sc->sc_umass_mtx); 3231 3232 return (0); 3233 } 3234 3235 static int 3236 umass_ioctl(struct Vnode *umass_inode, int cmd, unsigned long arg) 3237 { 3238 (void)umass_inode; 3239 (void)cmd; 3240 (void)arg; 3241 return (0); 3242 } 3243 3244 const struct block_operations g_dev_umass_ops = { 3245 .open = umass_open, 3246 .close = umass_close, 3247 .read = umass_read, 3248 .write = umass_write, 3249 .geometry = umass_geometry, 3250 .ioctl = umass_ioctl, 3251 .unlink = NULL 3252 }; 3253 3254 static int 3255 umass_dev_is_ready(struct umass_softc *sc) 3256 { 3257 int lun; 3258 int ret; 3259 uint8_t valid_lun; 3260 3261 mtx_lock(&sc->sc_umass_mtx); 3262 for (lun = 0; lun <= sc->sc_maxlun; lun++) { 3263 sc->sc_transfer.lun = lun; 3264 if (umass_inquiry(sc) < 0) 3265 continue; 3266 3267 valid_lun = lun; 3268 ret = umass_test_unit_ready(sc); 3269 if(ret == 0) { 3270 sc->sc_transfer.lun = valid_lun; 3271 ret = umass_read_capacity(sc); 3272 if (ret < 0) { 3273 mtx_unlock(&sc->sc_umass_mtx); 3274 PRINT_ERR("umass read capacity fail!\n"); 3275 return (0); 3276 } 3277 mtx_unlock(&sc->sc_umass_mtx); 3278 return (1); 3279 } 3280 3281 ret = umass_request_sense(sc); 3282 if(ret < 0) { 3283 PRINT_ERR("Request sense fail!\n"); 3284 mtx_unlock(&sc->sc_umass_mtx); 3285 return (0); 3286 } 3287 } 3288 mtx_unlock(&sc->sc_umass_mtx); 3289 return (0); 3290 } 3291 3292 static int 3293 umass_attach_dev_sub(struct umass_softc *sc, unsigned int dev_unit) 3294 { 3295 int ret; 3296 int disk_id; 3297 char devname[MASS_NAME]= {0}; 3298 #if USB_HAVE_DEVICE_TOPOLOGY 3299 device_t dev; 3300 struct usb_device *udev; 3301 usbd_bt_node *cur_node; 3302 struct node_info parent_info; 3303 struct node_info cur_info; 3304 #endif 3305 3306 umass_dev_lock(dev_unit); 3307 3308 #if USB_HAVE_DEVICE_TOPOLOGY 3309 dev = sc->sc_dev; 3310 udev = sc->sc_udev; 3311 dev_quantity |= 1ull << (unsigned int)device_get_unit(dev); 3312 #endif 3313 3314 #if USB_SUPPORT_SD_HOT_PLUG 3315 if (!umass_dev_is_attached(dev_unit)) 3316 #endif 3317 { 3318 devunit_to_devname(dev_unit, devname); 3319 disk_id = los_alloc_diskid_byname(devname); 3320 OsSetUsbStatus(disk_id); 3321 ret = los_disk_init(devname, &g_dev_umass_ops, (void *)sc, disk_id, NULL); 3322 if (ret) { 3323 PRINT_ERR("umass_attach_dev : los_disk_init fail!\n"); 3324 goto error; 3325 } 3326 } 3327 #if USB_SUPPORT_SD_HOT_PLUG 3328 umass_dev_attach_flag_set(dev_unit); 3329 #endif 3330 3331 #if USB_HAVE_DEVICE_TOPOLOGY 3332 cur_info.nameunit = device_get_nameunit(dev); 3333 cur_info.port_no = udev->port_no; 3334 cur_node = usbd_create_bt_node(&cur_info); 3335 if (cur_node == NULL) { 3336 goto error; 3337 } 3338 3339 parent_info.nameunit = device_get_nameunit(device_get_parent(dev)); 3340 parent_info.port_no = udev->port_no; 3341 3342 (void)usbd_insert_bt_node(cur_node, hub_tree, &parent_info); 3343 #endif 3344 3345 umass_dev_unlock(dev_unit); 3346 return (0); 3347 3348 error: 3349 umass_dev_unlock(dev_unit); 3350 return (-1); 3351 } 3352 3353 static void 3354 umass_detach_dev_sub(struct umass_softc *sc, int dev_unit, int flag) 3355 { 3356 int disk_id; 3357 char devname[MASS_NAME]= {0}; 3358 #if USB_HAVE_DEVICE_TOPOLOGY 3359 struct node_info cur_info; 3360 struct node_info parent_info; 3361 device_t dev = NULL; 3362 struct usb_device *udev = NULL; 3363 #endif 3364 3365 umass_dev_lock(dev_unit); 3366 3367 #if USB_HAVE_DEVICE_TOPOLOGY 3368 dev = sc->sc_dev; 3369 udev = sc->sc_udev; 3370 #if USB_SUPPORT_SD_HOT_PLUG 3371 if (umass_dev_is_attached(dev_unit)) 3372 #endif 3373 { 3374 parent_info.nameunit = device_get_nameunit(device_get_parent(dev)); 3375 parent_info.port_no = udev->port_no; 3376 3377 cur_info.nameunit = device_get_nameunit(dev); 3378 cur_info.port_no = udev->port_no; 3379 (void)usbd_remove_bt_node(hub_tree, &parent_info, &cur_info); 3380 } 3381 #endif 3382 3383 #if USB_SUPPORT_SD_HOT_PLUG 3384 if (umass_dev_is_attached(dev_unit)) 3385 #endif 3386 { 3387 devunit_to_devname(dev_unit, devname); 3388 disk_id = los_get_diskid_byname(devname); 3389 (void)los_disk_deinit(disk_id); 3390 (void)OsClearUsbStatus(disk_id); 3391 } 3392 3393 if (flag == 0) { /* 0: This interface is called from umass_detach, or is called elsewhere. */ 3394 #if USB_SUPPORT_SD_HOT_PLUG 3395 umass_dev_delete(sc, dev_unit); 3396 #endif 3397 } 3398 3399 #if USB_HAVE_DEVICE_TOPOLOGY 3400 dev_quantity &= ~(1ull << (unsigned int)device_get_unit(dev)); 3401 #endif 3402 3403 umass_dev_unlock(dev_unit); 3404 } 3405 3406 #if USB_SUPPORT_SD_HOT_PLUG 3407 void 3408 umass_dev_status_check(UINTPTR arg) 3409 { 3410 (void)arg; 3411 int ret; 3412 int i; 3413 struct umass_dev_info *dev = g_umass_dev_array; 3414 struct umass_softc *sc; 3415 3416 while(1) { 3417 for (i = 0; i < MAX_DEVICE; i++) { 3418 umass_dev_lock(i); 3419 if (dev[i].used == 1) { 3420 sc = dev[i].sc; 3421 ret = umass_dev_is_ready(sc); 3422 if (ret == 0) { 3423 if (dev[i].attached == 1) { 3424 umass_detach_dev_sub(sc, dev[i].dev_unit, 1); 3425 dev[i].attached = 0; 3426 } 3427 umass_dev_unlock(i); 3428 continue; 3429 } 3430 3431 if (dev[i].attached == 1) { 3432 umass_dev_unlock(i); 3433 continue; 3434 } 3435 3436 ret = umass_attach_dev_sub(sc, dev[i].dev_unit); 3437 if (ret< 0) { 3438 umass_dev_unlock(i); 3439 PRINT_ERR("umass attach device sub failed!\n"); 3440 continue; 3441 } 3442 } 3443 umass_dev_unlock(i); 3444 } 3445 (void)LOS_Msleep(1000); 3446 } 3447 } 3448 3449 int 3450 umass_dev_is_attached(unsigned int dev_unit) 3451 { 3452 if (dev_unit >= MAX_DEVICE) { 3453 PRINT_ERR("%s %d, The device unit is wrong!\n", __FUNCTION__, __LINE__); 3454 return (-1); 3455 } 3456 3457 return (g_umass_dev_array[dev_unit].attached); 3458 } 3459 3460 static void 3461 umass_dev_add(struct umass_softc *sc, int dev_unit) 3462 { 3463 int id = dev_unit; 3464 3465 if (g_umass_dev_array[id].used == 1) { 3466 PRINT_ERR("The id of umass device array is used!, id=%d\n", dev_unit); 3467 return; 3468 } 3469 3470 g_umass_dev_array[id].sc = sc; 3471 g_umass_dev_array[id].dev_unit = dev_unit; 3472 g_umass_dev_array[id].used = 1; 3473 umass_dev_mtx_init(id, MTX_DEF | MTX_RECURSE); 3474 } 3475 3476 static void 3477 umass_dev_delete(struct umass_softc *sc, unsigned int dev_unit) 3478 { 3479 unsigned int id = dev_unit; 3480 3481 if (g_umass_dev_array[id].used == 0) { 3482 PRINT_ERR("The id of umass device array is not used!\n"); 3483 return; 3484 } 3485 3486 if (g_umass_dev_array[id].dev_unit == dev_unit && 3487 g_umass_dev_array[id].sc == sc) { 3488 g_umass_dev_array[id].used = 0; 3489 g_umass_dev_array[id].sc = NULL; 3490 g_umass_dev_array[id].attached = 0; 3491 umass_dev_mtx_destroy(id); 3492 } else { 3493 PRINT_ERR("Can not find the umass device!\n"); 3494 } 3495 } 3496 3497 static void 3498 umass_dev_attach_flag_set(int dev_unit) 3499 { 3500 g_umass_dev_array[dev_unit].attached = 1; 3501 } 3502 3503 static void 3504 umass_task_check(int flag) 3505 { 3506 int i; 3507 int ret; 3508 3509 for (i = 0; i < MAX_DEVICE; i++) { 3510 if (g_umass_dev_array[i].used) 3511 break; 3512 } 3513 3514 if (i == MAX_DEVICE) { 3515 if (flag == 0) { /* create task */ 3516 ret = usb_os_task_creat(&umass_taskid, (TSK_ENTRY_FUNC)umass_dev_status_check, 3517 LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO, "umass_task", 0); 3518 if (ret) { 3519 PRINT_ERR("Create umass task fail!\n"); 3520 return; 3521 } 3522 } else if (flag == 1) { /* delete task */ 3523 ret = usb_os_task_delete(umass_taskid); 3524 if (ret) { 3525 PRINT_ERR("Delete umass task fail!\n"); 3526 return; 3527 } 3528 } else { 3529 PRINT_ERR("%s flag error!\n", __FUNCTION__); 3530 } 3531 } 3532 } 3533 #endif 3534 3535 static void 3536 devunit_to_devname(unsigned int dev_unit, char *devname) 3537 { 3538 char name_suf; 3539 int ret; 3540 3541 #if USB_HAVE_DEVICE_TOPOLOGY 3542 if (!(0x1 & (dev_quantity >> dev_unit))) 3543 #else 3544 if (dev_unit >= MAX_DEVICE) 3545 #endif 3546 { 3547 dprintf("sorry, we don't support so many devices\n"); 3548 return; 3549 } 3550 3551 name_suf = 'a' + dev_unit; 3552 ret = snprintf_s(devname, MASS_NAME, MASS_NAME - 1, "%s%c", UMASS_ATTACH_PRENAME, name_suf); 3553 if (ret < 0) { 3554 usb_err("snprintf_s failed!, ret:%d\n", ret); 3555 return; 3556 } 3557 } 3558 static int32_t 3559 umass_attach_dev(struct umass_softc *sc, unsigned int dev_unit) 3560 { 3561 int ret; 3562 3563 if (dev_unit >= MAX_DEVICE) { 3564 PRINT_ERR("sorry, we don't support so many devices\n"); 3565 return (-1); 3566 } 3567 #if USB_SUPPORT_SD_HOT_PLUG 3568 umass_task_check(0); 3569 umass_dev_add(sc, dev_unit); 3570 #endif 3571 3572 ret = umass_dev_is_ready(sc); 3573 if (ret) { 3574 ret = umass_attach_dev_sub(sc, dev_unit); 3575 if (ret < 0) { 3576 #if USB_SUPPORT_SD_HOT_PLUG 3577 umass_dev_delete(sc, dev_unit); 3578 #endif 3579 PRINT_ERR("umass attach device fail!\n"); 3580 return (-1); 3581 } 3582 } 3583 3584 return (0); 3585 } 3586 3587 #if USB_HAVE_DEVICE_TOPOLOGY 3588 int 3589 umass_medium_probe(uint8_t medium, char *devname) 3590 { 3591 struct usbd_bt_node *node; 3592 uint8_t dev_unit; 3593 3594 if ((devname == NULL) || strlen(devname) > 7) { /* /dev/sd* */ 3595 return (-1); 3596 } 3597 3598 if ((medium < 1) || (medium > usbd_get_hub_quantity())) { 3599 return (-1); 3600 } 3601 3602 node = usbd_per_order_probe(hub_tree, "umass", &medium); 3603 if (node != NULL) { 3604 dev_unit = usbd_atoi(node->info.nameunit + 5); /* 5 = umass */ 3605 devunit_to_devname(dev_unit, devname); 3606 } else { 3607 return (-1); 3608 } 3609 return (0); 3610 } 3611 #endif 3612 3613