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