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