This source file includes following definitions.
- umass_match
- umass_attach
- umass_detach
- umass_activate
- umass_disco
- umass_polled_transfer
- umass_setup_transfer
- umass_setup_ctrl_transfer
- umass_adjust_transfer
- umass_clear_endpoint_stall
- umass_reset
- umass_bbb_reset
- umass_bbb_transfer
- umass_bbb_state
- umass_cbi_adsc
- umass_cbi_reset
- umass_cbi_transfer
- umass_cbi_state
- umass_bbb_get_max_lun
- umass_bbb_dump_cbw
- umass_bbb_dump_csw
- umass_dump_buffer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 #include "atapiscsi.h"
135
136 #include <sys/param.h>
137 #include <sys/systm.h>
138 #include <sys/kernel.h>
139 #include <sys/conf.h>
140 #include <sys/buf.h>
141 #include <sys/device.h>
142 #include <sys/malloc.h>
143 #include <sys/timeout.h>
144 #undef KASSERT
145 #define KASSERT(cond, msg)
146 #include <machine/bus.h>
147
148 #include <scsi/scsi_all.h>
149
150 #include <dev/usb/usb.h>
151 #include <dev/usb/usbdi.h>
152 #include <dev/usb/usbdi_util.h>
153 #include <dev/usb/usbdivar.h>
154 #include <dev/usb/usbdevs.h>
155
156 #include <dev/usb/umassvar.h>
157 #include <dev/usb/umass_quirks.h>
158 #include <dev/usb/umass_scsi.h>
159
160
161 #ifdef UMASS_DEBUG
162 int umassdebug = 0;
163
164 char *states[TSTATE_STATES+1] = {
165
166 "Idle",
167 "BBB CBW",
168 "BBB Data",
169 "BBB Data bulk-in/-out clear stall",
170 "BBB CSW, 1st attempt",
171 "BBB CSW bulk-in clear stall",
172 "BBB CSW, 2nd attempt",
173 "BBB Reset",
174 "BBB bulk-in clear stall",
175 "BBB bulk-out clear stall",
176 "CBI Command",
177 "CBI Data",
178 "CBI Status",
179 "CBI Data bulk-in/-out clear stall",
180 "CBI Status intr-in clear stall",
181 "CBI Reset",
182 "CBI bulk-in clear stall",
183 "CBI bulk-out clear stall",
184 NULL
185 };
186 #endif
187
188
189 int umass_match(struct device *, void *, void *);
190 void umass_attach(struct device *, struct device *, void *);
191 int umass_detach(struct device *, int);
192 int umass_activate(struct device *, enum devact);
193
194 struct cfdriver umass_cd = {
195 NULL, "umass", DV_DULL
196 };
197
198 const struct cfattach umass_ca = {
199 sizeof(struct umass_softc),
200 umass_match,
201 umass_attach,
202 umass_detach,
203 umass_activate,
204 };
205 void umass_disco(struct umass_softc *sc);
206
207
208 usbd_status umass_polled_transfer(struct umass_softc *sc,
209 usbd_xfer_handle xfer);
210 usbd_status umass_setup_transfer(struct umass_softc *sc,
211 usbd_pipe_handle pipe,
212 void *buffer, int buflen, int flags,
213 usbd_xfer_handle xfer);
214 usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc,
215 usb_device_request_t *req,
216 void *buffer, int buflen, int flags,
217 usbd_xfer_handle xfer);
218 void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
219 usbd_xfer_handle xfer);
220 void umass_adjust_transfer(struct umass_softc *);
221 #if 0
222 void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv);
223 #endif
224
225
226 void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *,
227 int, int, u_int, umass_callback, void *);
228 void umass_bbb_reset(struct umass_softc *, int);
229 void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
230
231 usbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *);
232
233
234 void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *,
235 int, int, u_int, umass_callback, void *);
236 void umass_cbi_reset(struct umass_softc *, int);
237 void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
238
239 int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle);
240
241 const struct umass_wire_methods umass_bbb_methods = {
242 umass_bbb_transfer,
243 umass_bbb_reset,
244 umass_bbb_state
245 };
246
247 const struct umass_wire_methods umass_cbi_methods = {
248 umass_cbi_transfer,
249 umass_cbi_reset,
250 umass_cbi_state
251 };
252
253 #ifdef UMASS_DEBUG
254
255 void umass_bbb_dump_cbw(struct umass_softc *sc,
256 umass_bbb_cbw_t *cbw);
257 void umass_bbb_dump_csw(struct umass_softc *sc,
258 umass_bbb_csw_t *csw);
259 void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer,
260 int buflen, int printlen);
261 #endif
262
263
264
265
266
267
268 int
269 umass_match(struct device *parent, void *match, void *aux)
270 {
271 struct usb_attach_arg *uaa = aux;
272 const struct umass_quirk *quirk;
273 usb_interface_descriptor_t *id;
274
275 if (uaa->iface == NULL)
276 return (UMATCH_NONE);
277
278 quirk = umass_lookup(uaa->vendor, uaa->product);
279 if (quirk != NULL)
280 return (quirk->uq_match);
281
282 id = usbd_get_interface_descriptor(uaa->iface);
283 if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
284 return (UMATCH_NONE);
285
286 switch (id->bInterfaceSubClass) {
287 case UISUBCLASS_RBC:
288 case UISUBCLASS_SFF8020I:
289 case UISUBCLASS_QIC157:
290 case UISUBCLASS_UFI:
291 case UISUBCLASS_SFF8070I:
292 case UISUBCLASS_SCSI:
293 break;
294 default:
295 return (UMATCH_IFACECLASS);
296 }
297
298 switch (id->bInterfaceProtocol) {
299 case UIPROTO_MASS_CBI_I:
300 case UIPROTO_MASS_CBI:
301 case UIPROTO_MASS_BBB_OLD:
302 case UIPROTO_MASS_BBB:
303 break;
304 default:
305 return (UMATCH_IFACECLASS_IFACESUBCLASS);
306 }
307
308 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
309 }
310
311 void
312 umass_attach(struct device *parent, struct device *self, void *aux)
313 {
314 struct umass_softc *sc = (struct umass_softc *)self;
315 struct usb_attach_arg *uaa = aux;
316 const struct umass_quirk *quirk;
317 usb_interface_descriptor_t *id;
318 usb_endpoint_descriptor_t *ed;
319 const char *sWire, *sCommand;
320 char *devinfop;
321 usbd_status err;
322 int i, bno, error;
323
324 devinfop = usbd_devinfo_alloc(uaa->device, 0);
325 printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
326 usbd_devinfo_free(devinfop);
327
328 sc->sc_udev = uaa->device;
329 sc->sc_iface = uaa->iface;
330 sc->sc_ifaceno = uaa->ifaceno;
331
332 quirk = umass_lookup(uaa->vendor, uaa->product);
333 if (quirk != NULL) {
334 sc->sc_wire = quirk->uq_wire;
335 sc->sc_cmd = quirk->uq_cmd;
336 sc->sc_quirks = quirk->uq_flags;
337 sc->sc_busquirks = quirk->uq_busquirks;
338
339 if (quirk->uq_fixup != NULL)
340 (*quirk->uq_fixup)(sc);
341 } else {
342 sc->sc_wire = UMASS_WPROTO_UNSPEC;
343 sc->sc_cmd = UMASS_CPROTO_UNSPEC;
344 sc->sc_quirks = 0;
345 sc->sc_busquirks = 0;
346 }
347
348 id = usbd_get_interface_descriptor(sc->sc_iface);
349 if (id == NULL)
350 return;
351
352 if (sc->sc_wire == UMASS_WPROTO_UNSPEC) {
353 switch (id->bInterfaceProtocol) {
354 case UIPROTO_MASS_CBI:
355 sc->sc_wire = UMASS_WPROTO_CBI;
356 break;
357 case UIPROTO_MASS_CBI_I:
358 sc->sc_wire = UMASS_WPROTO_CBI_I;
359 break;
360 case UIPROTO_MASS_BBB:
361 case UIPROTO_MASS_BBB_OLD:
362 sc->sc_wire = UMASS_WPROTO_BBB;
363 break;
364 default:
365 DPRINTF(UDMASS_GEN,
366 ("%s: Unsupported wire protocol %u\n",
367 sc->sc_dev.dv_xname,
368 id->bInterfaceProtocol));
369 return;
370 }
371 }
372
373 if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) {
374 switch (id->bInterfaceSubClass) {
375 case UISUBCLASS_SCSI:
376 sc->sc_cmd = UMASS_CPROTO_SCSI;
377 break;
378 case UISUBCLASS_UFI:
379 sc->sc_cmd = UMASS_CPROTO_UFI;
380 break;
381 case UISUBCLASS_SFF8020I:
382 case UISUBCLASS_SFF8070I:
383 case UISUBCLASS_QIC157:
384 sc->sc_cmd = UMASS_CPROTO_ATAPI;
385 break;
386 case UISUBCLASS_RBC:
387 sc->sc_cmd = UMASS_CPROTO_RBC;
388 break;
389 default:
390 DPRINTF(UDMASS_GEN,
391 ("%s: Unsupported command protocol %u\n",
392 sc->sc_dev.dv_xname,
393 id->bInterfaceSubClass));
394 return;
395 }
396 }
397
398 switch (sc->sc_wire) {
399 case UMASS_WPROTO_CBI:
400 sWire = "CBI";
401 break;
402 case UMASS_WPROTO_CBI_I:
403 sWire = "CBI with CCI";
404 break;
405 case UMASS_WPROTO_BBB:
406 sWire = "Bulk-Only";
407 break;
408 default:
409 sWire = "unknown";
410 break;
411 }
412
413 switch (sc->sc_cmd) {
414 case UMASS_CPROTO_RBC:
415 sCommand = "RBC";
416 break;
417 case UMASS_CPROTO_SCSI:
418 sCommand = "SCSI";
419 break;
420 case UMASS_CPROTO_UFI:
421 sCommand = "UFI";
422 break;
423 case UMASS_CPROTO_ATAPI:
424 sCommand = "ATAPI";
425 break;
426 case UMASS_CPROTO_ISD_ATA:
427 sCommand = "ISD-ATA";
428 break;
429 default:
430 sCommand = "unknown";
431 break;
432 }
433
434 printf("%s: using %s over %s\n", sc->sc_dev.dv_xname, sCommand,
435 sWire);
436
437 if (quirk != NULL && quirk->uq_init != NULL) {
438 err = (*quirk->uq_init)(sc);
439 if (err) {
440 umass_disco(sc);
441 return;
442 }
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456 for (i = 0 ; i < id->bNumEndpoints ; i++) {
457 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
458 if (ed == NULL) {
459 printf("%s: could not read endpoint descriptor\n",
460 sc->sc_dev.dv_xname);
461 return;
462 }
463 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
464 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
465 sc->sc_epaddr[UMASS_BULKIN] = ed->bEndpointAddress;
466 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
467 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
468 sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress;
469 } else if (sc->sc_wire == UMASS_WPROTO_CBI_I
470 && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
471 && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
472 sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress;
473 #ifdef UMASS_DEBUG
474 if (UGETW(ed->wMaxPacketSize) > 2) {
475 DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n",
476 sc->sc_dev.dv_xname,
477 UGETW(ed->wMaxPacketSize)));
478 }
479 #endif
480 }
481 }
482
483
484 if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] ||
485 (sc->sc_wire == UMASS_WPROTO_CBI_I &&
486 !sc->sc_epaddr[UMASS_INTRIN])) {
487 DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n",
488 sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKIN],
489 sc->sc_epaddr[UMASS_BULKOUT],
490 sc->sc_epaddr[UMASS_INTRIN]));
491 return;
492 }
493
494
495
496
497 if (sc->sc_wire == UMASS_WPROTO_BBB) {
498 err = umass_bbb_get_max_lun(sc, &sc->maxlun);
499 if (err) {
500 printf("%s: unable to get Max Lun: %s\n",
501 sc->sc_dev.dv_xname, usbd_errstr(err));
502 return;
503 }
504 } else {
505 sc->maxlun = 0;
506 }
507
508
509 DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKOUT\n",
510 sc->sc_dev.dv_xname, sc->sc_iface,
511 sc->sc_epaddr[UMASS_BULKOUT]));
512 err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT],
513 USBD_EXCLUSIVE_USE,
514 &sc->sc_pipe[UMASS_BULKOUT]);
515 if (err) {
516 DPRINTF(UDMASS_USB, ("%s: cannot open %u-out pipe (bulk)\n",
517 sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKOUT]));
518 umass_disco(sc);
519 return;
520 }
521 DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKIN\n",
522 sc->sc_dev.dv_xname, sc->sc_iface,
523 sc->sc_epaddr[UMASS_BULKIN]));
524 err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN],
525 USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]);
526 if (err) {
527 DPRINTF(UDMASS_USB, ("%s: could not open %u-in pipe (bulk)\n",
528 sc->sc_dev.dv_xname, sc->sc_epaddr[UMASS_BULKIN]));
529 umass_disco(sc);
530 return;
531 }
532
533
534
535
536
537
538
539
540
541
542
543
544 if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
545 DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for INTRIN\n",
546 sc->sc_dev.dv_xname, sc->sc_iface,
547 sc->sc_epaddr[UMASS_INTRIN]));
548 err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN],
549 USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
550 if (err) {
551 DPRINTF(UDMASS_USB, ("%s: couldn't open %u-in (intr)\n",
552 sc->sc_dev.dv_xname,
553 sc->sc_epaddr[UMASS_INTRIN]));
554 umass_disco(sc);
555 return;
556 }
557 }
558
559
560 sc->transfer_state = TSTATE_IDLE;
561
562
563 for (i = 0; i < XFER_NR; i++) {
564 sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device);
565 if (sc->transfer_xfer[i] == NULL) {
566 DPRINTF(UDMASS_USB, ("%s: Out of memory\n",
567 sc->sc_dev.dv_xname));
568 umass_disco(sc);
569 return;
570 }
571 }
572
573 switch (sc->sc_wire) {
574 case UMASS_WPROTO_BBB:
575 bno = XFER_BBB_DATA;
576 goto dalloc;
577 case UMASS_WPROTO_CBI:
578 bno = XFER_CBI_DATA;
579 goto dalloc;
580 case UMASS_WPROTO_CBI_I:
581 bno = XFER_CBI_DATA;
582 dalloc:
583 sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
584 UMASS_MAX_TRANSFER_SIZE);
585 if (sc->data_buffer == NULL) {
586 umass_disco(sc);
587 return;
588 }
589 break;
590 default:
591 break;
592 }
593
594
595 switch (sc->sc_wire) {
596 case UMASS_WPROTO_BBB:
597 sc->sc_methods = &umass_bbb_methods;
598 break;
599 case UMASS_WPROTO_CBI:
600 case UMASS_WPROTO_CBI_I:
601 sc->sc_methods = &umass_cbi_methods;
602 break;
603 default:
604 umass_disco(sc);
605 return;
606 }
607
608 error = 0;
609 switch (sc->sc_cmd) {
610 case UMASS_CPROTO_RBC:
611 case UMASS_CPROTO_SCSI:
612 error = umass_scsi_attach(sc);
613 break;
614
615 case UMASS_CPROTO_UFI:
616 case UMASS_CPROTO_ATAPI:
617 #if (NATAPIBUS > 0) || (NATAPISCSI > 0)
618 error = umass_atapi_attach(sc);
619 #else
620 printf("%s: atapiscsi not configured\n", sc->sc_dev.dv_xname);
621 #endif
622 break;
623
624 case UMASS_CPROTO_ISD_ATA:
625 printf("%s: isdata not configured\n", sc->sc_dev.dv_xname);
626 break;
627
628 default:
629 printf("%s: command protocol=0x%x not supported\n",
630 sc->sc_dev.dv_xname, sc->sc_cmd);
631 umass_disco(sc);
632 return;
633 }
634 if (error) {
635 printf("%s: bus attach failed\n", sc->sc_dev.dv_xname);
636 umass_disco(sc);
637 return;
638 }
639
640 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
641 &sc->sc_dev);
642
643 DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", sc->sc_dev.dv_xname));
644 }
645
646 int
647 umass_detach(struct device *self, int flags)
648 {
649 struct umass_softc *sc = (struct umass_softc *)self;
650 struct umassbus_softc *scbus;
651 int rv = 0, i, s;
652
653 DPRINTF(UDMASS_USB, ("%s: detached\n", sc->sc_dev.dv_xname));
654
655
656 for (i = 0 ; i < UMASS_NEP ; i++) {
657 if (sc->sc_pipe[i] != NULL) {
658 usbd_abort_pipe(sc->sc_pipe[i]);
659 sc->sc_pipe[i] = NULL;
660 }
661 }
662
663
664 s = splusb();
665 if (--sc->sc_refcnt >= 0) {
666 #ifdef DIAGNOSTIC
667 printf("%s: waiting for refcnt\n", sc->sc_dev.dv_xname);
668 #endif
669
670 usb_detach_wait(&sc->sc_dev);
671 }
672 splx(s);
673
674 scbus = sc->bus;
675 if (scbus != NULL) {
676 if (scbus->sc_child != NULL)
677 rv = config_detach(scbus->sc_child, flags);
678 free(scbus, M_DEVBUF);
679 sc->bus = NULL;
680 }
681
682 if (rv != 0)
683 return (rv);
684
685 umass_disco(sc);
686
687 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
688 &sc->sc_dev);
689
690 return (rv);
691 }
692
693 int
694 umass_activate(struct device *dev, enum devact act)
695 {
696 struct umass_softc *sc = (struct umass_softc *)dev;
697 struct umassbus_softc *scbus = sc->bus;
698 int rv = 0;
699
700 DPRINTF(UDMASS_USB, ("%s: umass_activate: %d\n",
701 sc->sc_dev.dv_xname, act));
702
703 switch (act) {
704 case DVACT_ACTIVATE:
705 break;
706
707 case DVACT_DEACTIVATE:
708 sc->sc_dying = 1;
709 if (scbus == NULL || scbus->sc_child == NULL)
710 break;
711 rv = config_deactivate(scbus->sc_child);
712 DPRINTF(UDMASS_USB, ("%s: umass_activate: child "
713 "returned %d\n", sc->sc_dev.dv_xname, rv));
714 break;
715 }
716 return (rv);
717 }
718
719 void
720 umass_disco(struct umass_softc *sc)
721 {
722 int i;
723
724 DPRINTF(UDMASS_GEN, ("umass_disco\n"));
725
726
727 for (i = 0; i < XFER_NR; i++)
728 if (sc->transfer_xfer[i] != NULL) {
729 usbd_free_xfer(sc->transfer_xfer[i]);
730 sc->transfer_xfer[i] = NULL;
731 }
732
733
734 for (i = 0 ; i < UMASS_NEP ; i++) {
735 if (sc->sc_pipe[i] != NULL) {
736 usbd_close_pipe(sc->sc_pipe[i]);
737 sc->sc_pipe[i] = NULL;
738 }
739 }
740 }
741
742
743
744
745
746 usbd_status
747 umass_polled_transfer(struct umass_softc *sc, usbd_xfer_handle xfer)
748 {
749 usbd_status err;
750
751 if (sc->sc_dying)
752 return (USBD_IOERROR);
753
754
755
756
757
758
759
760
761 if (sc->polling_depth) {
762 if (sc->next_polled_xfer)
763 panic("%s: got polled xfer %p, but %p already "
764 "pending\n", sc->sc_dev.dv_xname, xfer,
765 sc->next_polled_xfer);
766
767 DPRINTF(UDMASS_XFER, ("%s: saving polled xfer %p\n",
768 sc->sc_dev.dv_xname, xfer));
769 sc->next_polled_xfer = xfer;
770
771 return (USBD_IN_PROGRESS);
772 }
773
774 sc->polling_depth++;
775
776 start_next_xfer:
777 DPRINTF(UDMASS_XFER, ("%s: start polled xfer %p\n",
778 sc->sc_dev.dv_xname, xfer));
779 err = usbd_transfer(xfer);
780 if (err && err != USBD_IN_PROGRESS && sc->next_polled_xfer == NULL) {
781 DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n",
782 sc->sc_dev.dv_xname, usbd_errstr(err)));
783 sc->polling_depth--;
784 return (err);
785 }
786
787 if (err && err != USBD_IN_PROGRESS) {
788 DPRINTF(UDMASS_XFER, ("umass_polled_xfer %p has error %s\n",
789 xfer, usbd_errstr(err)));
790 }
791
792 if (sc->next_polled_xfer != NULL) {
793 DPRINTF(UDMASS_XFER, ("umass_polled_xfer running next "
794 "transaction %p\n", sc->next_polled_xfer));
795 xfer = sc->next_polled_xfer;
796 sc->next_polled_xfer = NULL;
797 goto start_next_xfer;
798 }
799
800 sc->polling_depth--;
801
802 return (USBD_NORMAL_COMPLETION);
803 }
804
805 usbd_status
806 umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe,
807 void *buffer, int buflen, int flags,
808 usbd_xfer_handle xfer)
809 {
810 usbd_status err;
811
812 if (sc->sc_dying)
813 return (USBD_IOERROR);
814
815
816
817 usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen,
818 flags | sc->sc_xfer_flags, sc->timeout, sc->sc_methods->wire_state);
819
820 if (sc->sc_udev->bus->use_polling) {
821 DPRINTF(UDMASS_XFER,("%s: start polled xfer buffer=%p "
822 "buflen=%d flags=0x%x timeout=%d\n", sc->sc_dev.dv_xname,
823 buffer, buflen, flags | sc->sc_xfer_flags, sc->timeout));
824 err = umass_polled_transfer(sc, xfer);
825 } else {
826 err = usbd_transfer(xfer);
827 DPRINTF(UDMASS_XFER,("%s: start xfer buffer=%p buflen=%d "
828 "flags=0x%x timeout=%d\n", sc->sc_dev.dv_xname,
829 buffer, buflen, flags | sc->sc_xfer_flags, sc->timeout));
830 }
831 if (err && err != USBD_IN_PROGRESS) {
832 DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n",
833 sc->sc_dev.dv_xname, usbd_errstr(err)));
834 return (err);
835 }
836
837 return (USBD_NORMAL_COMPLETION);
838 }
839
840
841 usbd_status
842 umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req,
843 void *buffer, int buflen, int flags, usbd_xfer_handle xfer)
844 {
845 usbd_status err;
846
847 if (sc->sc_dying)
848 return (USBD_IOERROR);
849
850
851
852 usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc,
853 USBD_DEFAULT_TIMEOUT, req, buffer, buflen, flags,
854 sc->sc_methods->wire_state);
855
856 if (sc->sc_udev->bus->use_polling) {
857 DPRINTF(UDMASS_XFER,("%s: start polled ctrl xfer buffer=%p "
858 "buflen=%d flags=0x%x\n", sc->sc_dev.dv_xname, buffer,
859 buflen, flags));
860 err = umass_polled_transfer(sc, xfer);
861 } else {
862 DPRINTF(UDMASS_XFER,("%s: start ctrl xfer buffer=%p buflen=%d "
863 "flags=0x%x\n", sc->sc_dev.dv_xname, buffer, buflen,
864 flags));
865 err = usbd_transfer(xfer);
866 }
867 if (err && err != USBD_IN_PROGRESS) {
868 DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n",
869 sc->sc_dev.dv_xname, usbd_errstr(err)));
870
871
872 return (err);
873 }
874
875 return (USBD_NORMAL_COMPLETION);
876 }
877
878 void
879 umass_adjust_transfer(struct umass_softc *sc)
880 {
881 switch (sc->sc_cmd) {
882 case UMASS_CPROTO_UFI:
883 sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
884
885 switch (sc->cbw.CBWCDB[0]) {
886 case INQUIRY:
887 if (sc->transfer_datalen > 36) {
888 sc->transfer_datalen = 36;
889 sc->cbw.CBWCDB[4] = 36;
890 }
891 break;
892 case MODE_SENSE_BIG:
893 if (sc->transfer_datalen > 8) {
894 sc->transfer_datalen = 8;
895 sc->cbw.CBWCDB[7] = 0;
896 sc->cbw.CBWCDB[8] = 8;
897 }
898 break;
899 case REQUEST_SENSE:
900 if (sc->transfer_datalen > 18) {
901 sc->transfer_datalen = 18;
902 sc->cbw.CBWCDB[4] = 18;
903 }
904 break;
905 }
906 break;
907 case UMASS_CPROTO_ATAPI:
908 sc->cbw.bCDBLength = UFI_COMMAND_LENGTH;
909 break;
910 }
911 }
912
913 void
914 umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
915 usbd_xfer_handle xfer)
916 {
917 if (sc->sc_dying)
918 return;
919
920 DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n",
921 sc->sc_dev.dv_xname, sc->sc_epaddr[endpt]));
922
923 usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]);
924
925 sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT;
926 sc->sc_req.bRequest = UR_CLEAR_FEATURE;
927 USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
928 USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
929 USETW(sc->sc_req.wLength, 0);
930 umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
931 }
932
933 #if 0
934 void
935 umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
936 {
937 sc->transfer_cb = cb;
938 sc->transfer_priv = priv;
939
940
941 sc->reset(sc, STATUS_CMD_OK);
942 }
943 #endif
944
945
946
947
948
949 void
950 umass_bbb_reset(struct umass_softc *sc, int status)
951 {
952 KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
953 ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
954 sc->sc_wire));
955
956 if (sc->sc_dying)
957 return;
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975 DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n",
976 sc->sc_dev.dv_xname));
977
978 sc->transfer_state = TSTATE_BBB_RESET1;
979 sc->transfer_status = status;
980
981
982 sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
983 sc->sc_req.bRequest = UR_BBB_RESET;
984 USETW(sc->sc_req.wValue, 0);
985 USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
986 USETW(sc->sc_req.wLength, 0);
987 umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
988 sc->transfer_xfer[XFER_BBB_RESET1]);
989 }
990
991 void
992 umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
993 void *data, int datalen, int dir, u_int timeout,
994 umass_callback cb, void *priv)
995 {
996 static int dCBWtag = 42;
997 usbd_status err;
998
999 DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n",
1000 sc->sc_dev.dv_xname, *(u_char *)cmd));
1001
1002 KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
1003 ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
1004 sc->sc_wire));
1005
1006 if (sc->sc_dying) {
1007 sc->polled_xfer_status = USBD_IOERROR;
1008 return;
1009 }
1010
1011
1012 sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 KASSERT(datalen == 0 || data != NULL,
1036 ("%s: datalen > 0, but no buffer",sc->sc_dev.dv_xname));
1037 KASSERT(cmdlen <= CBWCDBLENGTH,
1038 ("%s: cmdlen exceeds CDB length in CBW (%d > %d)",
1039 sc->sc_dev.dv_xname, cmdlen, CBWCDBLENGTH));
1040 KASSERT(dir == DIR_NONE || datalen > 0,
1041 ("%s: datalen == 0 while direction is not NONE\n",
1042 sc->sc_dev.dv_xname));
1043 KASSERT(datalen == 0 || dir != DIR_NONE,
1044 ("%s: direction is NONE while datalen is not zero\n",
1045 sc->sc_dev.dv_xname));
1046 KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE,
1047 ("%s: CBW struct does not have the right size (%d vs. %d)\n",
1048 sc->sc_dev.dv_xname,
1049 sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE));
1050 KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE,
1051 ("%s: CSW struct does not have the right size (%d vs. %d)\n",
1052 sc->sc_dev.dv_xname,
1053 sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE));
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076 USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
1077 USETDW(sc->cbw.dCBWTag, dCBWtag);
1078 dCBWtag++;
1079 USETDW(sc->cbw.dCBWDataTransferLength, datalen);
1080
1081 sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT);
1082 sc->cbw.bCBWLUN = lun;
1083 sc->cbw.bCDBLength = cmdlen;
1084 bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
1085 memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
1086
1087 DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw));
1088
1089
1090 sc->transfer_dir = dir;
1091 sc->transfer_data = data;
1092 sc->transfer_datalen = datalen;
1093 sc->transfer_actlen = 0;
1094 sc->transfer_cb = cb;
1095 sc->transfer_priv = priv;
1096 sc->transfer_status = STATUS_CMD_OK;
1097
1098
1099 sc->transfer_state = TSTATE_BBB_COMMAND;
1100
1101
1102 umass_adjust_transfer(sc);
1103 if ((err = umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
1104 &sc->cbw, UMASS_BBB_CBW_SIZE, 0,
1105 sc->transfer_xfer[XFER_BBB_CBW])))
1106 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1107
1108 if (sc->sc_udev->bus->use_polling)
1109 sc->polled_xfer_status = err;
1110 }
1111
1112 void
1113 umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
1114 usbd_status err)
1115 {
1116 struct umass_softc *sc = (struct umass_softc *) priv;
1117 usbd_xfer_handle next_xfer;
1118
1119 KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
1120 ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n",
1121 sc->sc_wire));
1122
1123 if (sc->sc_dying)
1124 return;
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n",
1138 sc->sc_dev.dv_xname, sc->transfer_state,
1139 states[sc->transfer_state], xfer, usbd_errstr(err)));
1140
1141 switch (sc->transfer_state) {
1142
1143
1144 case TSTATE_BBB_COMMAND:
1145
1146 if (err) {
1147 DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n",
1148 sc->sc_dev.dv_xname));
1149
1150
1151
1152
1153 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1154 return;
1155 }
1156
1157
1158 sc->transfer_state = TSTATE_BBB_DATA;
1159 if (sc->transfer_dir == DIR_IN) {
1160 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
1161 sc->data_buffer, sc->transfer_datalen,
1162 USBD_SHORT_XFER_OK | USBD_NO_COPY,
1163 sc->transfer_xfer[XFER_BBB_DATA]))
1164 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1165
1166 return;
1167 } else if (sc->transfer_dir == DIR_OUT) {
1168 memcpy(sc->data_buffer, sc->transfer_data,
1169 sc->transfer_datalen);
1170 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
1171 sc->data_buffer, sc->transfer_datalen,
1172 USBD_NO_COPY,
1173 sc->transfer_xfer[XFER_BBB_DATA]))
1174 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1175
1176 return;
1177 } else {
1178 DPRINTF(UDMASS_BBB, ("%s: no data phase\n",
1179 sc->sc_dev.dv_xname));
1180 }
1181
1182
1183 case TSTATE_BBB_DATA:
1184
1185
1186 if (sc->transfer_dir != DIR_NONE) {
1187
1188 usbd_get_xfer_status(xfer, NULL, NULL,
1189 &sc->transfer_actlen, NULL);
1190 DPRINTF(UDMASS_BBB, ("%s: BBB_DATA actlen=%d\n",
1191 sc->sc_dev.dv_xname, sc->transfer_actlen));
1192
1193 if (err) {
1194 DPRINTF(UDMASS_BBB, ("%s: Data-%s %d failed, "
1195 "%s\n", sc->sc_dev.dv_xname,
1196 (sc->transfer_dir == DIR_IN?"in":"out"),
1197 sc->transfer_datalen,usbd_errstr(err)));
1198
1199 if (err == USBD_STALLED) {
1200 sc->transfer_state = TSTATE_BBB_DCLEAR;
1201 umass_clear_endpoint_stall(sc,
1202 (sc->transfer_dir == DIR_IN?
1203 UMASS_BULKIN:UMASS_BULKOUT),
1204 sc->transfer_xfer[XFER_BBB_DCLEAR]);
1205 } else {
1206
1207
1208
1209 umass_bbb_reset(sc,STATUS_WIRE_FAILED);
1210 }
1211 return;
1212 }
1213 }
1214
1215
1216 case TSTATE_BBB_DCLEAR:
1217 if (sc->transfer_dir == DIR_IN)
1218 memcpy(sc->transfer_data, sc->data_buffer,
1219 sc->transfer_actlen);
1220
1221 DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN)
1222 umass_dump_buffer(sc, sc->transfer_data,
1223 sc->transfer_datalen, 48));
1224
1225
1226 case TSTATE_BBB_SCLEAR:
1227
1228
1229
1230
1231
1232
1233 if (err) {
1234 printf("%s: BBB bulk-%s stall clear failed, %s\n",
1235 sc->sc_dev.dv_xname,
1236 (sc->transfer_dir == DIR_IN? "in":"out"),
1237 usbd_errstr(err));
1238 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1239 return;
1240 }
1241
1242
1243 if (sc->transfer_state == TSTATE_BBB_COMMAND ||
1244 sc->transfer_state == TSTATE_BBB_DATA ||
1245 sc->transfer_state == TSTATE_BBB_DCLEAR) {
1246
1247
1248
1249 sc->transfer_state = TSTATE_BBB_STATUS1;
1250 next_xfer = sc->transfer_xfer[XFER_BBB_CSW1];
1251 } else {
1252
1253 sc->transfer_state = TSTATE_BBB_STATUS2;
1254 next_xfer = sc->transfer_xfer[XFER_BBB_CSW2];
1255 }
1256
1257
1258 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
1259 &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) {
1260 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1261 return;
1262 }
1263
1264 return;
1265 case TSTATE_BBB_STATUS1:
1266 case TSTATE_BBB_STATUS2:
1267
1268 if (err) {
1269 DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n",
1270 sc->sc_dev.dv_xname, usbd_errstr(err),
1271 (sc->transfer_state == TSTATE_BBB_STATUS1?
1272 ", retrying":"")));
1273
1274
1275
1276
1277 if (sc->transfer_state == TSTATE_BBB_STATUS1) {
1278 sc->transfer_state = TSTATE_BBB_SCLEAR;
1279 umass_clear_endpoint_stall(sc, UMASS_BULKIN,
1280 sc->transfer_xfer[XFER_BBB_SCLEAR]);
1281 return;
1282 } else {
1283 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1284 return;
1285 }
1286 }
1287
1288 DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
1289
1290
1291 if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) &&
1292 UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1)
1293 USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
1294
1295
1296 if (sc->sc_quirks & UMASS_QUIRK_WRONG_CSWTAG)
1297 USETDW(sc->csw.dCSWTag, UGETDW(sc->cbw.dCBWTag));
1298
1299
1300 if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) {
1301
1302
1303
1304 printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n",
1305 sc->sc_dev.dv_xname,
1306 UGETDW(sc->csw.dCSWSignature),
1307 CSWSIGNATURE);
1308
1309 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1310 return;
1311 } else if (UGETDW(sc->csw.dCSWTag)
1312 != UGETDW(sc->cbw.dCBWTag)) {
1313 printf("%s: Invalid CSW: tag %d should be %d\n",
1314 sc->sc_dev.dv_xname,
1315 UGETDW(sc->csw.dCSWTag),
1316 UGETDW(sc->cbw.dCBWTag));
1317
1318 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1319 return;
1320
1321
1322 } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) {
1323 printf("%s: Invalid CSW: status %d > %d\n",
1324 sc->sc_dev.dv_xname,
1325 sc->csw.bCSWStatus,
1326 CSWSTATUS_PHASE);
1327
1328 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1329 return;
1330 } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) {
1331 printf("%s: Phase Error, residue = %d\n",
1332 sc->sc_dev.dv_xname,
1333 UGETDW(sc->csw.dCSWDataResidue));
1334
1335 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1336 return;
1337
1338 } else if (sc->transfer_actlen > sc->transfer_datalen) {
1339
1340 panic("%s: transferred %d bytes instead of %d bytes",
1341 sc->sc_dev.dv_xname,
1342 sc->transfer_actlen, sc->transfer_datalen);
1343 #if 0
1344 } else if (sc->transfer_datalen - sc->transfer_actlen
1345 != UGETDW(sc->csw.dCSWDataResidue)) {
1346 DPRINTF(UDMASS_BBB, ("%s: actlen=%d != residue=%d\n",
1347 sc->sc_dev.dv_xname,
1348 sc->transfer_datalen - sc->transfer_actlen,
1349 UGETDW(sc->csw.dCSWDataResidue)));
1350
1351 umass_bbb_reset(sc, STATUS_WIRE_FAILED);
1352 return;
1353 #endif
1354 } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
1355 DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n",
1356 sc->sc_dev.dv_xname,
1357 UGETDW(sc->csw.dCSWDataResidue)));
1358
1359
1360 sc->transfer_state = TSTATE_IDLE;
1361 sc->transfer_cb(sc, sc->transfer_priv,
1362 UGETDW(sc->csw.dCSWDataResidue),
1363 STATUS_CMD_FAILED);
1364
1365 return;
1366
1367 } else {
1368 sc->transfer_state = TSTATE_IDLE;
1369 sc->transfer_cb(sc, sc->transfer_priv,
1370 UGETDW(sc->csw.dCSWDataResidue),
1371 STATUS_CMD_OK);
1372
1373 return;
1374 }
1375
1376
1377 case TSTATE_BBB_RESET1:
1378 if (err)
1379 printf("%s: BBB reset failed, %s\n",
1380 sc->sc_dev.dv_xname, usbd_errstr(err));
1381
1382 sc->transfer_state = TSTATE_BBB_RESET2;
1383 umass_clear_endpoint_stall(sc, UMASS_BULKIN,
1384 sc->transfer_xfer[XFER_BBB_RESET2]);
1385
1386 return;
1387 case TSTATE_BBB_RESET2:
1388 if (err)
1389 printf("%s: BBB bulk-in clear stall failed, %s\n",
1390 sc->sc_dev.dv_xname, usbd_errstr(err));
1391
1392
1393 sc->transfer_state = TSTATE_BBB_RESET3;
1394 umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
1395 sc->transfer_xfer[XFER_BBB_RESET3]);
1396
1397 return;
1398 case TSTATE_BBB_RESET3:
1399 if (err)
1400 printf("%s: BBB bulk-out clear stall failed, %s\n",
1401 sc->sc_dev.dv_xname, usbd_errstr(err));
1402
1403
1404 sc->transfer_state = TSTATE_IDLE;
1405 if (sc->transfer_priv) {
1406 sc->transfer_cb(sc, sc->transfer_priv,
1407 sc->transfer_datalen,
1408 sc->transfer_status);
1409 }
1410
1411 return;
1412
1413
1414 default:
1415 panic("%s: Unknown state %d",
1416 sc->sc_dev.dv_xname, sc->transfer_state);
1417 }
1418 }
1419
1420
1421
1422
1423
1424 int
1425 umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
1426 usbd_xfer_handle xfer)
1427 {
1428 KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
1429 ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n",
1430 sc->sc_wire));
1431
1432 sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1433 sc->sc_req.bRequest = UR_CBI_ADSC;
1434 USETW(sc->sc_req.wValue, 0);
1435 USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
1436 USETW(sc->sc_req.wLength, buflen);
1437 return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer,
1438 buflen, 0, xfer);
1439 }
1440
1441
1442 void
1443 umass_cbi_reset(struct umass_softc *sc, int status)
1444 {
1445 int i;
1446 # define SEND_DIAGNOSTIC_CMDLEN 12
1447
1448 KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
1449 ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
1450 sc->sc_wire));
1451
1452 if (sc->sc_dying)
1453 return;
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469 DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n",
1470 sc->sc_dev.dv_xname));
1471
1472 KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN,
1473 ("%s: CBL struct is too small (%d < %d)\n",
1474 sc->sc_dev.dv_xname,
1475 sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN));
1476
1477 sc->transfer_state = TSTATE_CBI_RESET1;
1478 sc->transfer_status = status;
1479
1480
1481
1482
1483
1484 sc->cbl[0] = 0x1d;
1485 sc->cbl[1] = 0x04;
1486 for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++)
1487 sc->cbl[i] = 0xff;
1488
1489 umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN,
1490 sc->transfer_xfer[XFER_CBI_RESET1]);
1491
1492 }
1493
1494 void
1495 umass_cbi_transfer(struct umass_softc *sc, int lun,
1496 void *cmd, int cmdlen, void *data, int datalen, int dir,
1497 u_int timeout, umass_callback cb, void *priv)
1498 {
1499 usbd_status err;
1500
1501 DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n",
1502 sc->sc_dev.dv_xname, *(u_char *)cmd, datalen));
1503
1504 KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
1505 ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
1506 sc->sc_wire));
1507
1508 if (sc->sc_dying) {
1509 sc->polled_xfer_status = USBD_IOERROR;
1510 return;
1511 }
1512
1513
1514 sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534 KASSERT(datalen == 0 || data != NULL,
1535 ("%s: datalen > 0, but no buffer",sc->sc_dev.dv_xname));
1536 KASSERT(datalen == 0 || dir != DIR_NONE,
1537 ("%s: direction is NONE while datalen is not zero\n",
1538 sc->sc_dev.dv_xname));
1539
1540
1541 sc->transfer_dir = dir;
1542 sc->transfer_data = data;
1543 sc->transfer_datalen = datalen;
1544 sc->transfer_actlen = 0;
1545 sc->transfer_cb = cb;
1546 sc->transfer_priv = priv;
1547 sc->transfer_status = STATUS_CMD_OK;
1548
1549
1550 sc->transfer_state = TSTATE_CBI_COMMAND;
1551
1552
1553 sc->cbw.bCDBLength = cmdlen;
1554 bzero(sc->cbw.CBWCDB, sizeof(sc->cbw.CBWCDB));
1555 memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
1556 umass_adjust_transfer(sc);
1557 if ((err = umass_cbi_adsc(sc, (void *)sc->cbw.CBWCDB, sc->cbw.bCDBLength,
1558 sc->transfer_xfer[XFER_CBI_CB])))
1559 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1560
1561 if (sc->sc_udev->bus->use_polling)
1562 sc->polled_xfer_status = err;
1563 }
1564
1565 void
1566 umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
1567 usbd_status err)
1568 {
1569 struct umass_softc *sc = (struct umass_softc *) priv;
1570
1571 KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
1572 ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n",
1573 sc->sc_wire));
1574
1575 if (sc->sc_dying)
1576 return;
1577
1578
1579
1580
1581
1582 DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n",
1583 sc->sc_dev.dv_xname, sc->transfer_state,
1584 states[sc->transfer_state], xfer, usbd_errstr(err)));
1585
1586 switch (sc->transfer_state) {
1587
1588
1589 case TSTATE_CBI_COMMAND:
1590 if (err == USBD_STALLED) {
1591 DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n",
1592 sc->sc_dev.dv_xname));
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602 sc->transfer_state = TSTATE_IDLE;
1603 sc->transfer_cb(sc, sc->transfer_priv,
1604 sc->transfer_datalen,
1605 STATUS_CMD_FAILED);
1606
1607 return;
1608 } else if (err) {
1609 DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n",
1610 sc->sc_dev.dv_xname));
1611 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1612 return;
1613 }
1614
1615
1616 sc->transfer_state = TSTATE_CBI_DATA;
1617 if (sc->transfer_dir == DIR_IN) {
1618 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
1619 sc->data_buffer, sc->transfer_datalen,
1620 USBD_SHORT_XFER_OK | USBD_NO_COPY,
1621 sc->transfer_xfer[XFER_CBI_DATA]))
1622 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1623
1624 return;
1625 } else if (sc->transfer_dir == DIR_OUT) {
1626 memcpy(sc->data_buffer, sc->transfer_data,
1627 sc->transfer_datalen);
1628 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
1629 sc->data_buffer, sc->transfer_datalen,
1630 USBD_NO_COPY,
1631 sc->transfer_xfer[XFER_CBI_DATA]))
1632 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1633
1634 return;
1635 } else {
1636 DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
1637 sc->sc_dev.dv_xname));
1638 }
1639
1640
1641 case TSTATE_CBI_DATA:
1642
1643
1644 if (sc->transfer_dir != DIR_NONE) {
1645
1646 usbd_get_xfer_status(xfer, NULL, NULL,
1647 &sc->transfer_actlen, NULL);
1648 DPRINTF(UDMASS_CBI, ("%s: CBI_DATA actlen=%d\n",
1649 sc->sc_dev.dv_xname, sc->transfer_actlen));
1650
1651 if (err) {
1652 DPRINTF(UDMASS_CBI, ("%s: Data-%s %d failed, "
1653 "%s\n", sc->sc_dev.dv_xname,
1654 (sc->transfer_dir == DIR_IN?"in":"out"),
1655 sc->transfer_datalen,usbd_errstr(err)));
1656
1657 if (err == USBD_STALLED) {
1658 sc->transfer_state = TSTATE_CBI_DCLEAR;
1659 umass_clear_endpoint_stall(sc,
1660 (sc->transfer_dir == DIR_IN?
1661 UMASS_BULKIN:UMASS_BULKOUT),
1662 sc->transfer_xfer[XFER_CBI_DCLEAR]);
1663 } else {
1664
1665
1666
1667 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1668 }
1669 return;
1670 }
1671 }
1672
1673 if (sc->transfer_dir == DIR_IN)
1674 memcpy(sc->transfer_data, sc->data_buffer,
1675 sc->transfer_actlen);
1676
1677 DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN)
1678 umass_dump_buffer(sc, sc->transfer_data,
1679 sc->transfer_actlen, 48));
1680
1681
1682 if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
1683 sc->transfer_state = TSTATE_CBI_STATUS;
1684 memset(&sc->sbl, 0, sizeof(sc->sbl));
1685 if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
1686 &sc->sbl, sizeof(sc->sbl),
1687 0,
1688 sc->transfer_xfer[XFER_CBI_STATUS]))
1689 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1690 } else {
1691
1692
1693
1694 sc->transfer_state = TSTATE_IDLE;
1695 sc->transfer_cb(sc, sc->transfer_priv,
1696 sc->transfer_datalen - sc->transfer_actlen,
1697 STATUS_CMD_UNKNOWN);
1698 }
1699 return;
1700
1701 case TSTATE_CBI_STATUS:
1702 if (err) {
1703 DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n",
1704 sc->sc_dev.dv_xname));
1705
1706
1707
1708 if (err == USBD_STALLED) {
1709 sc->transfer_state = TSTATE_CBI_SCLEAR;
1710 umass_clear_endpoint_stall(sc, UMASS_INTRIN,
1711 sc->transfer_xfer[XFER_CBI_SCLEAR]);
1712 } else {
1713 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1714 }
1715 return;
1716 }
1717
1718
1719
1720 {
1721 u_int32_t actlen;
1722 usbd_get_xfer_status(xfer, NULL, NULL, &actlen, NULL);
1723 DPRINTF(UDMASS_CBI, ("%s: CBI_STATUS actlen=%d\n",
1724 sc->sc_dev.dv_xname, actlen));
1725 if (actlen != 2)
1726 break;
1727 }
1728
1729 if (sc->sc_cmd == UMASS_CPROTO_UFI) {
1730 int status;
1731
1732
1733
1734
1735
1736
1737 DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, "
1738 "ASCQ = 0x%02x\n",
1739 sc->sc_dev.dv_xname,
1740 sc->sbl.ufi.asc, sc->sbl.ufi.ascq));
1741
1742 if ((sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) ||
1743 sc->sc_sense)
1744 status = STATUS_CMD_OK;
1745 else
1746 status = STATUS_CMD_FAILED;
1747
1748
1749 sc->transfer_state = TSTATE_IDLE;
1750 sc->transfer_cb(sc, sc->transfer_priv,
1751 sc->transfer_datalen - sc->transfer_actlen, status);
1752 } else {
1753 int status;
1754
1755
1756
1757 DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n",
1758 sc->sc_dev.dv_xname,
1759 sc->sbl.common.type, sc->sbl.common.value));
1760
1761 if (sc->sbl.common.type == IDB_TYPE_CCI) {
1762 switch (sc->sbl.common.value &
1763 IDB_VALUE_STATUS_MASK) {
1764 case IDB_VALUE_PASS:
1765 status = STATUS_CMD_OK;
1766 break;
1767 case IDB_VALUE_FAIL:
1768 case IDB_VALUE_PERSISTENT:
1769 status = STATUS_CMD_FAILED;
1770 break;
1771 case IDB_VALUE_PHASE:
1772 status = STATUS_WIRE_FAILED;
1773 break;
1774 }
1775
1776 sc->transfer_state = TSTATE_IDLE;
1777 sc->transfer_cb(sc, sc->transfer_priv,
1778 sc->transfer_datalen - sc->transfer_actlen,
1779 status);
1780 }
1781 }
1782 return;
1783
1784 case TSTATE_CBI_DCLEAR:
1785 if (err) {
1786 printf("%s: CBI bulk-in/out stall clear failed, %s\n",
1787 sc->sc_dev.dv_xname, usbd_errstr(err));
1788 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1789 } else {
1790 sc->transfer_state = TSTATE_IDLE;
1791 sc->transfer_cb(sc, sc->transfer_priv,
1792 sc->transfer_datalen, STATUS_CMD_FAILED);
1793 }
1794 return;
1795
1796 case TSTATE_CBI_SCLEAR:
1797 if (err) {
1798 printf("%s: CBI intr-in stall clear failed, %s\n",
1799 sc->sc_dev.dv_xname, usbd_errstr(err));
1800 umass_cbi_reset(sc, STATUS_WIRE_FAILED);
1801 } else {
1802 sc->transfer_state = TSTATE_IDLE;
1803 sc->transfer_cb(sc, sc->transfer_priv,
1804 sc->transfer_datalen, STATUS_CMD_FAILED);
1805 }
1806 return;
1807
1808
1809 case TSTATE_CBI_RESET1:
1810 if (err)
1811 printf("%s: CBI reset failed, %s\n",
1812 sc->sc_dev.dv_xname, usbd_errstr(err));
1813
1814 sc->transfer_state = TSTATE_CBI_RESET2;
1815 umass_clear_endpoint_stall(sc, UMASS_BULKIN,
1816 sc->transfer_xfer[XFER_CBI_RESET2]);
1817
1818 return;
1819 case TSTATE_CBI_RESET2:
1820 if (err)
1821 printf("%s: CBI bulk-in stall clear failed, %s\n",
1822 sc->sc_dev.dv_xname, usbd_errstr(err));
1823
1824
1825 sc->transfer_state = TSTATE_CBI_RESET3;
1826 umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
1827 sc->transfer_xfer[XFER_CBI_RESET3]);
1828
1829 return;
1830 case TSTATE_CBI_RESET3:
1831 if (err)
1832 printf("%s: CBI bulk-out stall clear failed, %s\n",
1833 sc->sc_dev.dv_xname, usbd_errstr(err));
1834
1835
1836 sc->transfer_state = TSTATE_IDLE;
1837 if (sc->transfer_priv) {
1838 sc->transfer_cb(sc, sc->transfer_priv,
1839 sc->transfer_datalen,
1840 sc->transfer_status);
1841 }
1842
1843 return;
1844
1845
1846
1847 default:
1848 panic("%s: Unknown state %d",
1849 sc->sc_dev.dv_xname, sc->transfer_state);
1850 }
1851 }
1852
1853 usbd_status
1854 umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun)
1855 {
1856 usb_device_request_t req;
1857 usbd_status err;
1858
1859 *maxlun = 0;
1860
1861 DPRINTF(UDMASS_BBB, ("%s: Get Max Lun\n", sc->sc_dev.dv_xname));
1862
1863
1864 req.bmRequestType = UT_READ_CLASS_INTERFACE;
1865 req.bRequest = UR_BBB_GET_MAX_LUN;
1866 USETW(req.wValue, 0);
1867 USETW(req.wIndex, sc->sc_ifaceno);
1868 USETW(req.wLength, 1);
1869
1870 err = usbd_do_request_flags(sc->sc_udev, &req, maxlun,
1871 USBD_SHORT_XFER_OK, 0, USBD_DEFAULT_TIMEOUT);
1872 switch (err) {
1873 case USBD_NORMAL_COMPLETION:
1874 DPRINTF(UDMASS_BBB, ("%s: Max Lun %d\n",
1875 sc->sc_dev.dv_xname, *maxlun));
1876 break;
1877
1878 case USBD_STALLED:
1879
1880
1881
1882 err = USBD_NORMAL_COMPLETION;
1883 DPRINTF(UDMASS_BBB, ("%s: Get Max Lun not supported\n",
1884 sc->sc_dev.dv_xname));
1885 break;
1886
1887 case USBD_SHORT_XFER:
1888
1889
1890
1891 err = USBD_NORMAL_COMPLETION;
1892 DPRINTF(UDMASS_BBB, ("%s: Get Max Lun SHORT_XFER\n",
1893 sc->sc_dev.dv_xname));
1894 break;
1895
1896 default:
1897 printf("%s: Get Max Lun failed: %s\n",
1898 sc->sc_dev.dv_xname, usbd_errstr(err));
1899
1900 break;
1901 }
1902
1903 return (err);
1904 }
1905
1906 #ifdef UMASS_DEBUG
1907 void
1908 umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw)
1909 {
1910 int clen = cbw->bCDBLength;
1911 int dlen = UGETDW(cbw->dCBWDataTransferLength);
1912 u_int8_t *c = cbw->CBWCDB;
1913 int tag = UGETDW(cbw->dCBWTag);
1914 int flags = cbw->bCBWFlags;
1915
1916 DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmdlen=%d "
1917 "(0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%s), "
1918 "data = %d bytes, dir = %s\n",
1919 sc->sc_dev.dv_xname, tag, clen,
1920 c[0], c[1], c[2], c[3], c[4], c[5],
1921 c[6], c[7], c[8], c[9],
1922 (clen > 10? "...":""),
1923 dlen, (flags == CBWFLAGS_IN? "in":
1924 (flags == CBWFLAGS_OUT? "out":"<invalid>"))));
1925 }
1926
1927 void
1928 umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw)
1929 {
1930 int sig = UGETDW(csw->dCSWSignature);
1931 int tag = UGETDW(csw->dCSWTag);
1932 int res = UGETDW(csw->dCSWDataResidue);
1933 int status = csw->bCSWStatus;
1934
1935 DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, "
1936 "res = %d, status = 0x%02x (%s)\n", sc->sc_dev.dv_xname,
1937 tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"),
1938 tag, res,
1939 status, (status == CSWSTATUS_GOOD? "good":
1940 (status == CSWSTATUS_FAILED? "failed":
1941 (status == CSWSTATUS_PHASE? "phase":"<invalid>")))));
1942 }
1943
1944 void
1945 umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen,
1946 int printlen)
1947 {
1948 int i, j;
1949 char s1[40];
1950 char s2[40];
1951 char s3[5];
1952
1953 s1[0] = '\0';
1954 s3[0] = '\0';
1955
1956 snprintf(s2, sizeof s2, " buffer=%p, buflen=%d", buffer, buflen);
1957 for (i = 0; i < buflen && i < printlen; i++) {
1958 j = i % 16;
1959 if (j == 0 && i != 0) {
1960 DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n",
1961 sc->sc_dev.dv_xname, s1, s2));
1962 s2[0] = '\0';
1963 }
1964 snprintf(&s1[j*2], sizeof s1 - j*2, "%02x", buffer[i] & 0xff);
1965 }
1966 if (buflen > printlen)
1967 snprintf(s3, sizeof s3, " ...");
1968 DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n",
1969 sc->sc_dev.dv_xname, s1, s2, s3));
1970 }
1971 #endif