umass.c revision 1.96.2.4
11.96.2.4Sskrll/* $NetBSD: umass.c,v 1.96.2.4 2005/01/17 19:31:53 skrll Exp $ */ 21.96.2.1Sskrll 31.96.2.1Sskrll/* 41.96.2.1Sskrll * Copyright (c) 2003 The NetBSD Foundation, Inc. 51.96.2.1Sskrll * All rights reserved. 61.96.2.1Sskrll * 71.96.2.1Sskrll * This code is derived from software contributed to The NetBSD Foundation 81.96.2.1Sskrll * by Charles M. Hannum. 91.96.2.1Sskrll * 101.96.2.1Sskrll * Redistribution and use in source and binary forms, with or without 111.96.2.1Sskrll * modification, are permitted provided that the following conditions 121.96.2.1Sskrll * are met: 131.96.2.1Sskrll * 1. Redistributions of source code must retain the above copyright 141.96.2.1Sskrll * notice, this list of conditions and the following disclaimer. 151.96.2.1Sskrll * 2. Redistributions in binary form must reproduce the above copyright 161.96.2.1Sskrll * notice, this list of conditions and the following disclaimer in the 171.96.2.1Sskrll * documentation and/or other materials provided with the distribution. 181.96.2.1Sskrll * 3. All advertising materials mentioning features or use of this software 191.96.2.1Sskrll * must display the following acknowledgement: 201.96.2.1Sskrll * This product includes software developed by the NetBSD 211.96.2.1Sskrll * Foundation, Inc. and its contributors. 221.96.2.1Sskrll * 4. Neither the name of The NetBSD Foundation nor the names of its 231.96.2.1Sskrll * contributors may be used to endorse or promote products derived 241.96.2.1Sskrll * from this software without specific prior written permission. 251.96.2.1Sskrll * 261.96.2.1Sskrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 271.96.2.1Sskrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 281.96.2.1Sskrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 291.96.2.1Sskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 301.96.2.1Sskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 311.96.2.1Sskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 321.96.2.1Sskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 331.96.2.1Sskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 341.96.2.1Sskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 351.96.2.1Sskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 361.96.2.1Sskrll * POSSIBILITY OF SUCH DAMAGE. 371.96.2.1Sskrll */ 381.96.2.1Sskrll 391.1Sthorpej/*- 401.1Sthorpej * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, 411.28Saugustss * Nick Hibma <n_hibma@freebsd.org> 421.1Sthorpej * All rights reserved. 431.1Sthorpej * 441.1Sthorpej * Redistribution and use in source and binary forms, with or without 451.1Sthorpej * modification, are permitted provided that the following conditions 461.1Sthorpej * are met: 471.1Sthorpej * 1. Redistributions of source code must retain the above copyright 481.1Sthorpej * notice, this list of conditions and the following disclaimer. 491.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 501.1Sthorpej * notice, this list of conditions and the following disclaimer in the 511.1Sthorpej * documentation and/or other materials provided with the distribution. 521.1Sthorpej * 531.1Sthorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 541.1Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 551.1Sthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 561.1Sthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 571.1Sthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 581.1Sthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 591.1Sthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 601.1Sthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 611.1Sthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 621.1Sthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 631.1Sthorpej * SUCH DAMAGE. 641.1Sthorpej * 651.28Saugustss * $FreeBSD: src/sys/dev/usb/umass.c,v 1.13 2000/03/26 01:39:12 n_hibma Exp $ 661.28Saugustss */ 671.28Saugustss 681.28Saugustss/* 691.47Saugustss * Universal Serial Bus Mass Storage Class specs: 701.96.2.1Sskrll * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf 711.96.2.1Sskrll * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf 721.96.2.1Sskrll * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf 731.96.2.1Sskrll * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf 741.28Saugustss */ 751.28Saugustss 761.28Saugustss/* 771.96.2.1Sskrll * Ported to NetBSD by Lennart Augustsson <augustss@NetBSD.org>. 781.90Spooka * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>. 791.1Sthorpej */ 801.1Sthorpej 811.1Sthorpej/* 821.28Saugustss * The driver handles 3 Wire Protocols 831.28Saugustss * - Command/Bulk/Interrupt (CBI) 841.28Saugustss * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI) 851.28Saugustss * - Mass Storage Bulk-Only (BBB) 861.28Saugustss * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases) 871.28Saugustss * 881.28Saugustss * Over these wire protocols it handles the following command protocols 891.28Saugustss * - SCSI 901.54Saugustss * - 8070 (ATA/ATAPI for rewritable removable media) 911.54Saugustss * - UFI (USB Floppy Interface) 921.1Sthorpej * 931.54Saugustss * 8070i is a transformed version of the SCSI command set. UFI is a transformed 941.88Saugustss * version of the 8070i command set. The sc->transform method is used to 951.54Saugustss * convert the commands into the appropriate format (if at all necessary). 961.54Saugustss * For example, ATAPI requires all commands to be 12 bytes in length amongst 971.54Saugustss * other things. 981.3Sthorpej * 991.28Saugustss * The source code below is marked and can be split into a number of pieces 1001.28Saugustss * (in this order): 1011.3Sthorpej * 1021.28Saugustss * - probe/attach/detach 1031.28Saugustss * - generic transfer routines 1041.28Saugustss * - BBB 1051.28Saugustss * - CBI 1061.28Saugustss * - CBI_I (in addition to functions from CBI) 1071.28Saugustss * - CAM (Common Access Method) 1081.28Saugustss * - SCSI 1091.28Saugustss * - UFI 1101.28Saugustss * - 8070i 1111.3Sthorpej * 1121.28Saugustss * The protocols are implemented using a state machine, for the transfers as 1131.28Saugustss * well as for the resets. The state machine is contained in umass_*_state. 1141.28Saugustss * The state machine is started through either umass_*_transfer or 1151.28Saugustss * umass_*_reset. 1161.28Saugustss * 1171.28Saugustss * The reason for doing this is a) CAM performs a lot better this way and b) it 1181.28Saugustss * avoids using tsleep from interrupt context (for example after a failed 1191.28Saugustss * transfer). 1201.1Sthorpej */ 1211.1Sthorpej 1221.28Saugustss/* 1231.28Saugustss * The SCSI related part of this driver has been derived from the 1241.28Saugustss * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@freebsd.org). 1251.1Sthorpej * 1261.28Saugustss * The CAM layer uses so called actions which are messages sent to the host 1271.28Saugustss * adapter for completion. The actions come in through umass_cam_action. The 1281.28Saugustss * appropriate block of routines is called depending on the transport protocol 1291.28Saugustss * in use. When the transfer has finished, these routines call 1301.28Saugustss * umass_cam_cb again to complete the CAM command. 1311.1Sthorpej */ 1321.64Slukem 1331.64Slukem#include <sys/cdefs.h> 1341.96.2.4Sskrll__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.96.2.4 2005/01/17 19:31:53 skrll Exp $"); 1351.1Sthorpej 1361.29Senami#include "atapibus.h" 1371.79Saugustss#include "scsibus.h" 1381.80Saugustss#include "wd.h" 1391.29Senami 1401.1Sthorpej#include <sys/param.h> 1411.1Sthorpej#include <sys/systm.h> 1421.1Sthorpej#include <sys/kernel.h> 1431.28Saugustss#include <sys/conf.h> 1441.28Saugustss#if defined(__NetBSD__) || defined(__OpenBSD__) 1451.28Saugustss#include <sys/buf.h> 1461.28Saugustss#include <sys/device.h> 1471.1Sthorpej#include <sys/malloc.h> 1481.28Saugustss#undef KASSERT 1491.28Saugustss#define KASSERT(cond, msg) 1501.28Saugustss#elif defined(__FreeBSD__) 1511.28Saugustss#include <sys/module.h> 1521.28Saugustss#include <sys/bus.h> 1531.28Saugustss#include <machine/clock.h> 1541.28Saugustss#endif 1551.1Sthorpej 1561.1Sthorpej#include <dev/usb/usb.h> 1571.1Sthorpej#include <dev/usb/usbdi.h> 1581.1Sthorpej#include <dev/usb/usbdi_util.h> 1591.28Saugustss#include <dev/usb/usbdevs.h> 1601.1Sthorpej 1611.56Saugustss#include <dev/usb/umassvar.h> 1621.78Sgehenna#include <dev/usb/umass_quirks.h> 1631.79Saugustss#include <dev/usb/umass_scsipi.h> 1641.80Saugustss#include <dev/usb/umass_isdata.h> 1651.28Saugustss 1661.96.2.1Sskrll#include <dev/scsipi/scsipi_all.h> 1671.96.2.1Sskrll#include <dev/scsipi/scsipiconf.h> 1681.96.2.1Sskrll 1691.28Saugustss 1701.28Saugustss#ifdef UMASS_DEBUG 1711.57Saugustssint umassdebug = 0; 1721.57Saugustss 1731.28Saugustsschar *states[TSTATE_STATES+1] = { 1741.28Saugustss /* should be kept in sync with the list at transfer_state */ 1751.28Saugustss "Idle", 1761.28Saugustss "BBB CBW", 1771.28Saugustss "BBB Data", 1781.28Saugustss "BBB Data bulk-in/-out clear stall", 1791.28Saugustss "BBB CSW, 1st attempt", 1801.28Saugustss "BBB CSW bulk-in clear stall", 1811.28Saugustss "BBB CSW, 2nd attempt", 1821.28Saugustss "BBB Reset", 1831.28Saugustss "BBB bulk-in clear stall", 1841.28Saugustss "BBB bulk-out clear stall", 1851.28Saugustss "CBI Command", 1861.28Saugustss "CBI Data", 1871.28Saugustss "CBI Status", 1881.28Saugustss "CBI Data bulk-in/-out clear stall", 1891.28Saugustss "CBI Status intr-in clear stall", 1901.28Saugustss "CBI Reset", 1911.28Saugustss "CBI bulk-in clear stall", 1921.28Saugustss "CBI bulk-out clear stall", 1931.28Saugustss NULL 1941.28Saugustss}; 1951.28Saugustss#endif 1961.1Sthorpej 1971.28Saugustss/* USB device probe/attach/detach functions */ 1981.1SthorpejUSB_DECLARE_DRIVER(umass); 1991.38SaugustssStatic void umass_disco(struct umass_softc *sc); 2001.1Sthorpej 2011.28Saugustss/* generic transfer functions */ 2021.38SaugustssStatic usbd_status umass_setup_transfer(struct umass_softc *sc, 2031.1Sthorpej usbd_pipe_handle pipe, 2041.28Saugustss void *buffer, int buflen, int flags, 2051.38Saugustss usbd_xfer_handle xfer); 2061.38SaugustssStatic usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc, 2071.28Saugustss usb_device_request_t *req, 2081.88Saugustss void *buffer, int buflen, int flags, 2091.38Saugustss usbd_xfer_handle xfer); 2101.73SgehennaStatic void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt, 2111.70Sgehenna usbd_xfer_handle xfer); 2121.29Senami#if 0 2131.38SaugustssStatic void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv); 2141.29Senami#endif 2151.1Sthorpej 2161.1Sthorpej/* Bulk-Only related functions */ 2171.75SgehennaStatic void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *, 2181.75Sgehenna int, int, u_int, umass_callback, void *); 2191.75SgehennaStatic void umass_bbb_reset(struct umass_softc *, int); 2201.75SgehennaStatic void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status); 2211.28Saugustss 2221.75Sgehennausbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *); 2231.28Saugustss 2241.28Saugustss/* CBI related functions */ 2251.88SaugustssStatic void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *, 2261.75Sgehenna int, int, u_int, umass_callback, void *); 2271.75SgehennaStatic void umass_cbi_reset(struct umass_softc *, int); 2281.75SgehennaStatic void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status); 2291.75Sgehenna 2301.75SgehennaStatic int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle); 2311.75Sgehenna 2321.75Sgehennaconst struct umass_wire_methods umass_bbb_methods = { 2331.75Sgehenna umass_bbb_transfer, 2341.75Sgehenna umass_bbb_reset, 2351.75Sgehenna umass_bbb_state 2361.75Sgehenna}; 2371.75Sgehenna 2381.75Sgehennaconst struct umass_wire_methods umass_cbi_methods = { 2391.75Sgehenna umass_cbi_transfer, 2401.75Sgehenna umass_cbi_reset, 2411.75Sgehenna umass_cbi_state 2421.75Sgehenna}; 2431.28Saugustss 2441.28Saugustss#ifdef UMASS_DEBUG 2451.28Saugustss/* General debugging functions */ 2461.38SaugustssStatic void umass_bbb_dump_cbw(struct umass_softc *sc, 2471.38Saugustss umass_bbb_cbw_t *cbw); 2481.38SaugustssStatic void umass_bbb_dump_csw(struct umass_softc *sc, 2491.38Saugustss umass_bbb_csw_t *csw); 2501.38SaugustssStatic void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, 2511.38Saugustss int buflen, int printlen); 2521.28Saugustss#endif 2531.28Saugustss 2541.28Saugustss 2551.28Saugustss/* 2561.28Saugustss * USB device probe/attach/detach 2571.28Saugustss */ 2581.28Saugustss 2591.78SgehennaUSB_MATCH(umass) 2601.28Saugustss{ 2611.78Sgehenna USB_MATCH_START(umass, uaa); 2621.78Sgehenna const struct umass_quirk *quirk; 2631.28Saugustss usb_interface_descriptor_t *id; 2641.28Saugustss 2651.78Sgehenna if (uaa->iface == NULL) 2661.78Sgehenna return (UMATCH_NONE); 2671.28Saugustss 2681.78Sgehenna quirk = umass_lookup(uaa->vendor, uaa->product); 2691.78Sgehenna if (quirk != NULL) 2701.78Sgehenna return (quirk->uq_match); 2711.40Saugustss 2721.78Sgehenna id = usbd_get_interface_descriptor(uaa->iface); 2731.28Saugustss if (id == NULL || id->bInterfaceClass != UICLASS_MASS) 2741.28Saugustss return (UMATCH_NONE); 2751.1Sthorpej 2761.78Sgehenna switch (id->bInterfaceSubClass) { 2771.78Sgehenna case UISUBCLASS_RBC: 2781.78Sgehenna case UISUBCLASS_SFF8020I: 2791.78Sgehenna case UISUBCLASS_QIC157: 2801.28Saugustss case UISUBCLASS_UFI: 2811.28Saugustss case UISUBCLASS_SFF8070I: 2821.78Sgehenna case UISUBCLASS_SCSI: 2831.40Saugustss break; 2841.28Saugustss default: 2851.78Sgehenna return (UMATCH_IFACECLASS); 2861.28Saugustss } 2871.28Saugustss 2881.78Sgehenna switch (id->bInterfaceProtocol) { 2891.78Sgehenna case UIPROTO_MASS_CBI_I: 2901.28Saugustss case UIPROTO_MASS_CBI: 2911.78Sgehenna case UIPROTO_MASS_BBB_OLD: 2921.28Saugustss case UIPROTO_MASS_BBB: 2931.28Saugustss break; 2941.28Saugustss default: 2951.78Sgehenna return (UMATCH_IFACECLASS_IFACESUBCLASS); 2961.28Saugustss } 2971.1Sthorpej 2981.78Sgehenna return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 2991.1Sthorpej} 3001.1Sthorpej 3011.1SthorpejUSB_ATTACH(umass) 3021.1Sthorpej{ 3031.1Sthorpej USB_ATTACH_START(umass, sc, uaa); 3041.78Sgehenna const struct umass_quirk *quirk; 3051.1Sthorpej usb_interface_descriptor_t *id; 3061.1Sthorpej usb_endpoint_descriptor_t *ed; 3071.78Sgehenna const char *sWire, *sCommand; 3081.1Sthorpej char devinfo[1024]; 3091.78Sgehenna usbd_status err; 3101.79Saugustss int i, bno, error; 3111.1Sthorpej 3121.96.2.1Sskrll usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo)); 3131.1Sthorpej USB_ATTACH_SETUP; 3141.1Sthorpej 3151.78Sgehenna sc->sc_udev = uaa->device; 3161.76Sgehenna sc->sc_iface = uaa->iface; 3171.76Sgehenna sc->sc_ifaceno = uaa->ifaceno; 3181.28Saugustss 3191.78Sgehenna quirk = umass_lookup(uaa->vendor, uaa->product); 3201.78Sgehenna if (quirk != NULL) { 3211.78Sgehenna sc->sc_wire = quirk->uq_wire; 3221.78Sgehenna sc->sc_cmd = quirk->uq_cmd; 3231.78Sgehenna sc->sc_quirks = quirk->uq_flags; 3241.82Saugustss sc->sc_busquirks = quirk->uq_busquirks; 3251.78Sgehenna 3261.78Sgehenna if (quirk->uq_fixup != NULL) 3271.78Sgehenna (*quirk->uq_fixup)(sc); 3281.78Sgehenna } else { 3291.78Sgehenna sc->sc_wire = UMASS_WPROTO_UNSPEC; 3301.78Sgehenna sc->sc_cmd = UMASS_CPROTO_UNSPEC; 3311.78Sgehenna sc->sc_quirks = 0; 3321.82Saugustss sc->sc_busquirks = 0; 3331.78Sgehenna } 3341.78Sgehenna 3351.78Sgehenna id = usbd_get_interface_descriptor(sc->sc_iface); 3361.78Sgehenna if (id == NULL) 3371.40Saugustss USB_ATTACH_ERROR_RETURN; 3381.78Sgehenna 3391.78Sgehenna if (sc->sc_wire == UMASS_WPROTO_UNSPEC) { 3401.78Sgehenna switch (id->bInterfaceProtocol) { 3411.78Sgehenna case UIPROTO_MASS_CBI: 3421.78Sgehenna sc->sc_wire = UMASS_WPROTO_CBI; 3431.78Sgehenna break; 3441.78Sgehenna case UIPROTO_MASS_CBI_I: 3451.78Sgehenna sc->sc_wire = UMASS_WPROTO_CBI_I; 3461.78Sgehenna break; 3471.78Sgehenna case UIPROTO_MASS_BBB: 3481.78Sgehenna case UIPROTO_MASS_BBB_OLD: 3491.78Sgehenna sc->sc_wire = UMASS_WPROTO_BBB; 3501.78Sgehenna break; 3511.78Sgehenna default: 3521.78Sgehenna DPRINTF(UDMASS_GEN, 3531.78Sgehenna ("%s: Unsupported wire protocol %u\n", 3541.78Sgehenna USBDEVNAME(sc->sc_dev), 3551.78Sgehenna id->bInterfaceProtocol)); 3561.78Sgehenna USB_ATTACH_ERROR_RETURN; 3571.78Sgehenna } 3581.40Saugustss } 3591.28Saugustss 3601.78Sgehenna if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) { 3611.78Sgehenna switch (id->bInterfaceSubClass) { 3621.78Sgehenna case UISUBCLASS_SCSI: 3631.78Sgehenna sc->sc_cmd = UMASS_CPROTO_SCSI; 3641.78Sgehenna break; 3651.78Sgehenna case UISUBCLASS_UFI: 3661.78Sgehenna sc->sc_cmd = UMASS_CPROTO_UFI; 3671.78Sgehenna break; 3681.78Sgehenna case UISUBCLASS_SFF8020I: 3691.78Sgehenna case UISUBCLASS_SFF8070I: 3701.78Sgehenna case UISUBCLASS_QIC157: 3711.78Sgehenna sc->sc_cmd = UMASS_CPROTO_ATAPI; 3721.78Sgehenna break; 3731.78Sgehenna case UISUBCLASS_RBC: 3741.78Sgehenna sc->sc_cmd = UMASS_CPROTO_RBC; 3751.78Sgehenna break; 3761.78Sgehenna default: 3771.78Sgehenna DPRINTF(UDMASS_GEN, 3781.78Sgehenna ("%s: Unsupported command protocol %u\n", 3791.78Sgehenna USBDEVNAME(sc->sc_dev), 3801.78Sgehenna id->bInterfaceSubClass)); 3811.51Stsutsui USB_ATTACH_ERROR_RETURN; 3821.78Sgehenna } 3831.78Sgehenna } 3841.17Sthorpej 3851.28Saugustss printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 3861.17Sthorpej 3871.78Sgehenna switch (sc->sc_wire) { 3881.78Sgehenna case UMASS_WPROTO_CBI: 3891.78Sgehenna sWire = "CBI"; 3901.32Saugustss break; 3911.78Sgehenna case UMASS_WPROTO_CBI_I: 3921.78Sgehenna sWire = "CBI with CCI"; 3931.28Saugustss break; 3941.78Sgehenna case UMASS_WPROTO_BBB: 3951.78Sgehenna sWire = "Bulk-Only"; 3961.28Saugustss break; 3971.17Sthorpej default: 3981.78Sgehenna sWire = "unknown"; 3991.28Saugustss break; 4001.17Sthorpej } 4011.78Sgehenna 4021.78Sgehenna switch (sc->sc_cmd) { 4031.78Sgehenna case UMASS_CPROTO_RBC: 4041.78Sgehenna sCommand = "RBC"; 4051.78Sgehenna break; 4061.78Sgehenna case UMASS_CPROTO_SCSI: 4071.78Sgehenna sCommand = "SCSI"; 4081.28Saugustss break; 4091.78Sgehenna case UMASS_CPROTO_UFI: 4101.78Sgehenna sCommand = "UFI"; 4111.28Saugustss break; 4121.78Sgehenna case UMASS_CPROTO_ATAPI: 4131.78Sgehenna sCommand = "ATAPI"; 4141.32Saugustss break; 4151.80Saugustss case UMASS_CPROTO_ISD_ATA: 4161.80Saugustss sCommand = "ISD-ATA"; 4171.80Saugustss break; 4181.17Sthorpej default: 4191.78Sgehenna sCommand = "unknown"; 4201.32Saugustss break; 4211.17Sthorpej } 4221.78Sgehenna 4231.78Sgehenna printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sCommand, 4241.78Sgehenna sWire); 4251.1Sthorpej 4261.96.2.1Sskrll if (quirk != NULL && quirk->uq_init != NULL) { 4271.96.2.1Sskrll err = (*quirk->uq_init)(sc); 4281.96.2.1Sskrll if (err) { 4291.96.2.1Sskrll printf("%s: quirk init failed\n", 4301.96.2.1Sskrll USBDEVNAME(sc->sc_dev)); 4311.96.2.1Sskrll umass_disco(sc); 4321.96.2.1Sskrll USB_ATTACH_ERROR_RETURN; 4331.96.2.1Sskrll } 4341.96.2.1Sskrll } 4351.96.2.1Sskrll 4361.1Sthorpej /* 4371.28Saugustss * In addition to the Control endpoint the following endpoints 4381.28Saugustss * are required: 4391.28Saugustss * a) bulk-in endpoint. 4401.28Saugustss * b) bulk-out endpoint. 4411.28Saugustss * and for Control/Bulk/Interrupt with CCI (CBI_I) 4421.28Saugustss * c) intr-in 4431.1Sthorpej * 4441.1Sthorpej * The endpoint addresses are not fixed, so we have to read them 4451.1Sthorpej * from the device descriptors of the current interface. 4461.1Sthorpej */ 4471.1Sthorpej for (i = 0 ; i < id->bNumEndpoints ; i++) { 4481.76Sgehenna ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 4491.78Sgehenna if (ed == NULL) { 4501.1Sthorpej printf("%s: could not read endpoint descriptor\n", 4511.1Sthorpej USBDEVNAME(sc->sc_dev)); 4521.1Sthorpej USB_ATTACH_ERROR_RETURN; 4531.1Sthorpej } 4541.11Saugustss if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN 4551.1Sthorpej && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { 4561.73Sgehenna sc->sc_epaddr[UMASS_BULKIN] = ed->bEndpointAddress; 4571.11Saugustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT 4581.1Sthorpej && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { 4591.73Sgehenna sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress; 4601.78Sgehenna } else if (sc->sc_wire == UMASS_WPROTO_CBI_I 4611.28Saugustss && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN 4621.28Saugustss && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { 4631.73Sgehenna sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress; 4641.28Saugustss#ifdef UMASS_DEBUG 4651.28Saugustss if (UGETW(ed->wMaxPacketSize) > 2) { 4661.28Saugustss DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n", 4671.28Saugustss USBDEVNAME(sc->sc_dev), 4681.28Saugustss UGETW(ed->wMaxPacketSize))); 4691.28Saugustss } 4701.28Saugustss#endif 4711.1Sthorpej } 4721.1Sthorpej } 4731.1Sthorpej 4741.28Saugustss /* check whether we found all the endpoints we need */ 4751.73Sgehenna if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] || 4761.78Sgehenna (sc->sc_wire == UMASS_WPROTO_CBI_I && 4771.78Sgehenna !sc->sc_epaddr[UMASS_INTRIN])) { 4781.96.2.1Sskrll printf("%s: endpoint not found %u/%u/%u\n", 4791.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN], 4801.96.2.1Sskrll sc->sc_epaddr[UMASS_BULKOUT], 4811.96.2.1Sskrll sc->sc_epaddr[UMASS_INTRIN]); 4821.28Saugustss USB_ATTACH_ERROR_RETURN; 4831.28Saugustss } 4841.28Saugustss 4851.7Sthorpej /* 4861.7Sthorpej * Get the maximum LUN supported by the device. 4871.7Sthorpej */ 4881.96.2.1Sskrll if (sc->sc_wire == UMASS_WPROTO_BBB) { 4891.28Saugustss err = umass_bbb_get_max_lun(sc, &sc->maxlun); 4901.28Saugustss if (err) { 4911.28Saugustss printf("%s: unable to get Max Lun: %s\n", 4921.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 4931.28Saugustss USB_ATTACH_ERROR_RETURN; 4941.28Saugustss } 4951.96.2.1Sskrll if (sc->maxlun > 0) 4961.96.2.1Sskrll sc->sc_busquirks |= PQUIRK_FORCELUNS; 4971.28Saugustss } else { 4981.28Saugustss sc->maxlun = 0; 4991.7Sthorpej } 5001.7Sthorpej 5011.1Sthorpej /* Open the bulk-in and -out pipe */ 5021.96.2.1Sskrll DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKOUT\n", 5031.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_iface, 5041.96.2.1Sskrll sc->sc_epaddr[UMASS_BULKOUT])); 5051.76Sgehenna err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT], 5061.73Sgehenna USBD_EXCLUSIVE_USE, 5071.73Sgehenna &sc->sc_pipe[UMASS_BULKOUT]); 5081.1Sthorpej if (err) { 5091.96.2.1Sskrll printf("%s: cannot open %u-out pipe (bulk)\n", 5101.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKOUT]); 5111.28Saugustss umass_disco(sc); 5121.1Sthorpej USB_ATTACH_ERROR_RETURN; 5131.1Sthorpej } 5141.96.2.1Sskrll DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for BULKIN\n", 5151.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_iface, 5161.96.2.1Sskrll sc->sc_epaddr[UMASS_BULKIN])); 5171.76Sgehenna err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN], 5181.73Sgehenna USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]); 5191.1Sthorpej if (err) { 5201.96.2.1Sskrll printf("%s: could not open %u-in pipe (bulk)\n", 5211.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN]); 5221.28Saugustss umass_disco(sc); 5231.1Sthorpej USB_ATTACH_ERROR_RETURN; 5241.1Sthorpej } 5251.88Saugustss /* 5261.28Saugustss * Open the intr-in pipe if the protocol is CBI with CCI. 5271.28Saugustss * Note: early versions of the Zip drive do have an interrupt pipe, but 5281.28Saugustss * this pipe is unused 5291.28Saugustss * 5301.28Saugustss * We do not open the interrupt pipe as an interrupt pipe, but as a 5311.28Saugustss * normal bulk endpoint. We send an IN transfer down the wire at the 5321.28Saugustss * appropriate time, because we know exactly when to expect data on 5331.28Saugustss * that endpoint. This saves bandwidth, but more important, makes the 5341.28Saugustss * code for handling the data on that endpoint simpler. No data 5351.28Saugustss * arriving concurrently. 5361.28Saugustss */ 5371.78Sgehenna if (sc->sc_wire == UMASS_WPROTO_CBI_I) { 5381.96.2.1Sskrll DPRINTF(UDMASS_USB, ("%s: opening iface %p epaddr %d for INTRIN\n", 5391.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->sc_iface, 5401.96.2.1Sskrll sc->sc_epaddr[UMASS_INTRIN])); 5411.76Sgehenna err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN], 5421.73Sgehenna USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]); 5431.28Saugustss if (err) { 5441.96.2.1Sskrll printf("%s: couldn't open %u-in (intr)\n", 5451.96.2.1Sskrll USBDEVNAME(sc->sc_dev), 5461.96.2.1Sskrll sc->sc_epaddr[UMASS_INTRIN]); 5471.28Saugustss umass_disco(sc); 5481.28Saugustss USB_ATTACH_ERROR_RETURN; 5491.28Saugustss } 5501.28Saugustss } 5511.28Saugustss 5521.28Saugustss /* initialisation of generic part */ 5531.28Saugustss sc->transfer_state = TSTATE_IDLE; 5541.28Saugustss 5551.28Saugustss /* request a sufficient number of xfer handles */ 5561.28Saugustss for (i = 0; i < XFER_NR; i++) { 5571.28Saugustss sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device); 5581.92Stron if (sc->transfer_xfer[i] == NULL) { 5591.96.2.1Sskrll printf("%s: Out of memory\n", 5601.96.2.1Sskrll USBDEVNAME(sc->sc_dev)); 5611.28Saugustss umass_disco(sc); 5621.28Saugustss USB_ATTACH_ERROR_RETURN; 5631.28Saugustss } 5641.28Saugustss } 5651.28Saugustss /* Allocate buffer for data transfer (it's huge). */ 5661.78Sgehenna switch (sc->sc_wire) { 5671.78Sgehenna case UMASS_WPROTO_BBB: 5681.28Saugustss bno = XFER_BBB_DATA; 5691.28Saugustss goto dalloc; 5701.78Sgehenna case UMASS_WPROTO_CBI: 5711.28Saugustss bno = XFER_CBI_DATA; 5721.28Saugustss goto dalloc; 5731.78Sgehenna case UMASS_WPROTO_CBI_I: 5741.28Saugustss bno = XFER_CBI_DATA; 5751.28Saugustss dalloc: 5761.88Saugustss sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno], 5771.28Saugustss UMASS_MAX_TRANSFER_SIZE); 5781.28Saugustss if (sc->data_buffer == NULL) { 5791.96.2.1Sskrll printf("%s: no buffer memory\n", 5801.96.2.1Sskrll USBDEVNAME(sc->sc_dev)); 5811.28Saugustss umass_disco(sc); 5821.28Saugustss USB_ATTACH_ERROR_RETURN; 5831.28Saugustss } 5841.28Saugustss break; 5851.28Saugustss default: 5861.28Saugustss break; 5871.28Saugustss } 5881.1Sthorpej 5891.28Saugustss /* Initialise the wire protocol specific methods */ 5901.78Sgehenna switch (sc->sc_wire) { 5911.78Sgehenna case UMASS_WPROTO_BBB: 5921.75Sgehenna sc->sc_methods = &umass_bbb_methods; 5931.78Sgehenna break; 5941.78Sgehenna case UMASS_WPROTO_CBI: 5951.78Sgehenna case UMASS_WPROTO_CBI_I: 5961.75Sgehenna sc->sc_methods = &umass_cbi_methods; 5971.78Sgehenna break; 5981.78Sgehenna default: 5991.78Sgehenna umass_disco(sc); 6001.78Sgehenna USB_ATTACH_ERROR_RETURN; 6011.28Saugustss } 6021.28Saugustss 6031.79Saugustss error = 0; 6041.79Saugustss switch (sc->sc_cmd) { 6051.79Saugustss case UMASS_CPROTO_RBC: 6061.79Saugustss case UMASS_CPROTO_SCSI: 6071.79Saugustss#if NSCSIBUS > 0 6081.79Saugustss error = umass_scsi_attach(sc); 6091.79Saugustss#else 6101.96Sdsainty printf("%s: scsibus not configured\n", USBDEVNAME(sc->sc_dev)); 6111.79Saugustss#endif 6121.79Saugustss break; 6131.79Saugustss 6141.79Saugustss case UMASS_CPROTO_UFI: 6151.79Saugustss case UMASS_CPROTO_ATAPI: 6161.79Saugustss#if NATAPIBUS > 0 6171.79Saugustss error = umass_atapi_attach(sc); 6181.79Saugustss#else 6191.96Sdsainty printf("%s: atapibus not configured\n", 6201.96Sdsainty USBDEVNAME(sc->sc_dev)); 6211.80Saugustss#endif 6221.80Saugustss break; 6231.80Saugustss 6241.80Saugustss case UMASS_CPROTO_ISD_ATA: 6251.80Saugustss#if NWD > 0 6261.80Saugustss error = umass_isdata_attach(sc); 6271.80Saugustss#else 6281.80Saugustss printf("%s: isdata not configured\n", USBDEVNAME(sc->sc_dev)); 6291.79Saugustss#endif 6301.79Saugustss break; 6311.79Saugustss 6321.79Saugustss default: 6331.79Saugustss printf("%s: command protocol=0x%x not supported\n", 6341.79Saugustss USBDEVNAME(sc->sc_dev), sc->sc_cmd); 6351.28Saugustss umass_disco(sc); 6361.28Saugustss USB_ATTACH_ERROR_RETURN; 6371.28Saugustss } 6381.79Saugustss if (error) { 6391.79Saugustss printf("%s: bus attach failed\n", USBDEVNAME(sc->sc_dev)); 6401.79Saugustss umass_disco(sc); 6411.79Saugustss USB_ATTACH_ERROR_RETURN; 6421.79Saugustss } 6431.79Saugustss 6441.79Saugustss usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 6451.79Saugustss USBDEV(sc->sc_dev)); 6461.1Sthorpej 6471.28Saugustss DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev))); 6481.28Saugustss 6491.1Sthorpej USB_ATTACH_SUCCESS_RETURN; 6501.1Sthorpej} 6511.1Sthorpej 6521.28SaugustssUSB_DETACH(umass) 6531.28Saugustss{ 6541.28Saugustss USB_DETACH_START(umass, sc); 6551.96.2.1Sskrll struct umassbus_softc *scbus; 6561.95Saugustss int rv = 0, i, s; 6571.1Sthorpej 6581.28Saugustss DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev))); 6591.28Saugustss 6601.28Saugustss /* Abort the pipes to wake up any waiting processes. */ 6611.73Sgehenna for (i = 0 ; i < UMASS_NEP ; i++) { 6621.96.2.4Sskrll if (sc->sc_pipe[i] != NULL) 6631.73Sgehenna usbd_abort_pipe(sc->sc_pipe[i]); 6641.73Sgehenna } 6651.28Saugustss 6661.42Saugustss /* Do we really need reference counting? Perhaps in ioctl() */ 6671.28Saugustss s = splusb(); 6681.28Saugustss if (--sc->sc_refcnt >= 0) { 6691.95Saugustss#ifdef DIAGNOSTIC 6701.95Saugustss printf("%s: waiting for refcnt\n", USBDEVNAME(sc->sc_dev)); 6711.95Saugustss#endif 6721.28Saugustss /* Wait for processes to go away. */ 6731.28Saugustss usb_detach_wait(USBDEV(sc->sc_dev)); 6741.28Saugustss } 6751.28Saugustss splx(s); 6761.28Saugustss 6771.96.2.1Sskrll scbus = sc->bus; 6781.79Saugustss if (scbus != NULL) { 6791.79Saugustss if (scbus->sc_child != NULL) 6801.79Saugustss rv = config_detach(scbus->sc_child, flags); 6811.79Saugustss free(scbus, M_DEVBUF); 6821.79Saugustss sc->bus = NULL; 6831.79Saugustss } 6841.56Saugustss 6851.28Saugustss if (rv != 0) 6861.28Saugustss return (rv); 6871.28Saugustss 6881.28Saugustss umass_disco(sc); 6891.28Saugustss 6901.28Saugustss usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 6911.28Saugustss USBDEV(sc->sc_dev)); 6921.28Saugustss 6931.79Saugustss return (rv); 6941.79Saugustss} 6951.79Saugustss 6961.79Saugustssint 6971.79Saugustssumass_activate(struct device *dev, enum devact act) 6981.79Saugustss{ 6991.79Saugustss struct umass_softc *sc = (struct umass_softc *)dev; 7001.79Saugustss struct umassbus_softc *scbus = sc->bus; 7011.79Saugustss int rv = 0; 7021.79Saugustss 7031.79Saugustss DPRINTF(UDMASS_USB, ("%s: umass_activate: %d\n", 7041.79Saugustss USBDEVNAME(sc->sc_dev), act)); 7051.79Saugustss 7061.79Saugustss switch (act) { 7071.79Saugustss case DVACT_ACTIVATE: 7081.79Saugustss rv = EOPNOTSUPP; 7091.79Saugustss break; 7101.79Saugustss 7111.79Saugustss case DVACT_DEACTIVATE: 7121.79Saugustss sc->sc_dying = 1; 7131.84Saugustss if (scbus == NULL || scbus->sc_child == NULL) 7141.79Saugustss break; 7151.79Saugustss rv = config_deactivate(scbus->sc_child); 7161.79Saugustss DPRINTF(UDMASS_USB, ("%s: umass_activate: child " 7171.79Saugustss "returned %d\n", USBDEVNAME(sc->sc_dev), rv)); 7181.79Saugustss break; 7191.79Saugustss } 7201.79Saugustss return (rv); 7211.28Saugustss} 7221.28Saugustss 7231.28SaugustssStatic void 7241.38Saugustssumass_disco(struct umass_softc *sc) 7251.88Saugustss{ 7261.28Saugustss int i; 7271.28Saugustss 7281.28Saugustss DPRINTF(UDMASS_GEN, ("umass_disco\n")); 7291.28Saugustss 7301.28Saugustss /* Free the xfers. */ 7311.28Saugustss for (i = 0; i < XFER_NR; i++) 7321.28Saugustss if (sc->transfer_xfer[i] != NULL) { 7331.28Saugustss usbd_free_xfer(sc->transfer_xfer[i]); 7341.28Saugustss sc->transfer_xfer[i] = NULL; 7351.28Saugustss } 7361.28Saugustss 7371.28Saugustss /* Remove all the pipes. */ 7381.73Sgehenna for (i = 0 ; i < UMASS_NEP ; i++) { 7391.93Stoshii if (sc->sc_pipe[i] != NULL) { 7401.73Sgehenna usbd_close_pipe(sc->sc_pipe[i]); 7411.93Stoshii sc->sc_pipe[i] = NULL; 7421.93Stoshii } 7431.73Sgehenna } 7441.28Saugustss} 7451.1Sthorpej 7461.28Saugustss/* 7471.28Saugustss * Generic functions to handle transfers 7481.28Saugustss */ 7491.9Sthorpej 7501.28SaugustssStatic usbd_status 7511.28Saugustssumass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, 7521.28Saugustss void *buffer, int buflen, int flags, 7531.28Saugustss usbd_xfer_handle xfer) 7541.28Saugustss{ 7551.28Saugustss usbd_status err; 7561.9Sthorpej 7571.28Saugustss if (sc->sc_dying) 7581.28Saugustss return (USBD_IOERROR); 7591.18Saugustss 7601.28Saugustss /* Initialiase a USB transfer and then schedule it */ 7611.18Saugustss 7621.28Saugustss usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen, 7631.75Sgehenna flags | sc->sc_xfer_flags, sc->timeout, sc->sc_methods->wire_state); 7641.18Saugustss 7651.28Saugustss err = usbd_transfer(xfer); 7661.28Saugustss DPRINTF(UDMASS_XFER,("%s: start xfer buffer=%p buflen=%d flags=0x%x " 7671.28Saugustss "timeout=%d\n", USBDEVNAME(sc->sc_dev), 7681.28Saugustss buffer, buflen, flags | sc->sc_xfer_flags, sc->timeout)); 7691.28Saugustss if (err && err != USBD_IN_PROGRESS) { 7701.28Saugustss DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n", 7711.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err))); 7721.28Saugustss return (err); 7731.9Sthorpej } 7741.24Saugustss 7751.28Saugustss return (USBD_NORMAL_COMPLETION); 7761.1Sthorpej} 7771.1Sthorpej 7781.1Sthorpej 7791.28SaugustssStatic usbd_status 7801.74Sgehennaumass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req, 7811.74Sgehenna void *buffer, int buflen, int flags, usbd_xfer_handle xfer) 7821.1Sthorpej{ 7831.1Sthorpej usbd_status err; 7841.1Sthorpej 7851.28Saugustss if (sc->sc_dying) 7861.28Saugustss return (USBD_IOERROR); 7871.1Sthorpej 7881.28Saugustss /* Initialiase a USB control transfer and then schedule it */ 7891.1Sthorpej 7901.75Sgehenna usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc, sc->timeout, 7911.75Sgehenna req, buffer, buflen, flags, sc->sc_methods->wire_state); 7921.1Sthorpej 7931.28Saugustss err = usbd_transfer(xfer); 7941.28Saugustss if (err && err != USBD_IN_PROGRESS) { 7951.28Saugustss DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n", 7961.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err))); 7971.1Sthorpej 7981.28Saugustss /* do not reset, as this would make us loop */ 7991.28Saugustss return (err); 8001.28Saugustss } 8011.1Sthorpej 8021.28Saugustss return (USBD_NORMAL_COMPLETION); 8031.1Sthorpej} 8041.1Sthorpej 8051.28SaugustssStatic void 8061.73Sgehennaumass_clear_endpoint_stall(struct umass_softc *sc, int endpt, 8071.73Sgehenna usbd_xfer_handle xfer) 8081.7Sthorpej{ 8091.28Saugustss if (sc->sc_dying) 8101.28Saugustss return; 8111.1Sthorpej 8121.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n", 8131.85Saugustss USBDEVNAME(sc->sc_dev), sc->sc_epaddr[endpt])); 8141.7Sthorpej 8151.73Sgehenna usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]); 8161.7Sthorpej 8171.78Sgehenna sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT; 8181.78Sgehenna sc->sc_req.bRequest = UR_CLEAR_FEATURE; 8191.78Sgehenna USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT); 8201.78Sgehenna USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]); 8211.78Sgehenna USETW(sc->sc_req.wLength, 0); 8221.78Sgehenna umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer); 8231.28Saugustss} 8241.15Sthorpej 8251.29Senami#if 0 8261.28SaugustssStatic void 8271.28Saugustssumass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv) 8281.28Saugustss{ 8291.28Saugustss sc->transfer_cb = cb; 8301.28Saugustss sc->transfer_priv = priv; 8311.1Sthorpej 8321.28Saugustss /* The reset is a forced reset, so no error (yet) */ 8331.28Saugustss sc->reset(sc, STATUS_CMD_OK); 8341.7Sthorpej} 8351.29Senami#endif 8361.1Sthorpej 8371.28Saugustss/* 8381.28Saugustss * Bulk protocol specific functions 8391.28Saugustss */ 8401.28Saugustss 8411.28SaugustssStatic void 8421.28Saugustssumass_bbb_reset(struct umass_softc *sc, int status) 8431.1Sthorpej{ 8441.78Sgehenna KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, 8451.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n", 8461.78Sgehenna sc->sc_wire)); 8471.28Saugustss 8481.28Saugustss if (sc->sc_dying) 8491.28Saugustss return; 8501.1Sthorpej 8511.1Sthorpej /* 8521.1Sthorpej * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class) 8531.1Sthorpej * 8541.1Sthorpej * For Reset Recovery the host shall issue in the following order: 8551.1Sthorpej * a) a Bulk-Only Mass Storage Reset 8561.1Sthorpej * b) a Clear Feature HALT to the Bulk-In endpoint 8571.1Sthorpej * c) a Clear Feature HALT to the Bulk-Out endpoint 8581.28Saugustss * 8591.28Saugustss * This is done in 3 steps, states: 8601.28Saugustss * TSTATE_BBB_RESET1 8611.28Saugustss * TSTATE_BBB_RESET2 8621.28Saugustss * TSTATE_BBB_RESET3 8631.28Saugustss * 8641.28Saugustss * If the reset doesn't succeed, the device should be port reset. 8651.1Sthorpej */ 8661.1Sthorpej 8671.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n", 8681.1Sthorpej USBDEVNAME(sc->sc_dev))); 8691.88Saugustss 8701.28Saugustss sc->transfer_state = TSTATE_BBB_RESET1; 8711.28Saugustss sc->transfer_status = status; 8721.1Sthorpej 8731.28Saugustss /* reset is a class specific interface write */ 8741.78Sgehenna sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 8751.78Sgehenna sc->sc_req.bRequest = UR_BBB_RESET; 8761.78Sgehenna USETW(sc->sc_req.wValue, 0); 8771.78Sgehenna USETW(sc->sc_req.wIndex, sc->sc_ifaceno); 8781.78Sgehenna USETW(sc->sc_req.wLength, 0); 8791.78Sgehenna umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, 8801.28Saugustss sc->transfer_xfer[XFER_BBB_RESET1]); 8811.28Saugustss} 8821.28Saugustss 8831.28SaugustssStatic void 8841.28Saugustssumass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, 8851.67Saugustss void *data, int datalen, int dir, u_int timeout, 8861.75Sgehenna umass_callback cb, void *priv) 8871.28Saugustss{ 8881.28Saugustss static int dCBWtag = 42; /* unique for CBW of transfer */ 8891.1Sthorpej 8901.28Saugustss DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n", 8911.87Saugustss USBDEVNAME(sc->sc_dev), *(u_char *)cmd)); 8921.1Sthorpej 8931.78Sgehenna KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, 8941.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n", 8951.78Sgehenna sc->sc_wire)); 8961.1Sthorpej 8971.96.2.1Sskrll if (sc->sc_dying) 8981.96.2.1Sskrll return; 8991.96.2.1Sskrll 9001.67Saugustss /* Be a little generous. */ 9011.67Saugustss sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; 9021.67Saugustss 9031.1Sthorpej /* 9041.28Saugustss * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly 9051.28Saugustss * a data phase of datalen bytes from/to the device and finally a 9061.28Saugustss * csw read phase. 9071.28Saugustss * If the data direction was inbound a maximum of datalen bytes 9081.28Saugustss * is stored in the buffer pointed to by data. 9091.28Saugustss * 9101.28Saugustss * umass_bbb_transfer initialises the transfer and lets the state 9111.88Saugustss * machine in umass_bbb_state handle the completion. It uses the 9121.28Saugustss * following states: 9131.28Saugustss * TSTATE_BBB_COMMAND 9141.28Saugustss * -> TSTATE_BBB_DATA 9151.28Saugustss * -> TSTATE_BBB_STATUS 9161.28Saugustss * -> TSTATE_BBB_STATUS2 9171.28Saugustss * -> TSTATE_BBB_IDLE 9181.28Saugustss * 9191.28Saugustss * An error in any of those states will invoke 9201.28Saugustss * umass_bbb_reset. 9211.1Sthorpej */ 9221.1Sthorpej 9231.1Sthorpej /* check the given arguments */ 9241.28Saugustss KASSERT(datalen == 0 || data != NULL, 9251.28Saugustss ("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev))); 9261.28Saugustss KASSERT(cmdlen <= CBWCDBLENGTH, 9271.28Saugustss ("%s: cmdlen exceeds CDB length in CBW (%d > %d)", 9281.28Saugustss USBDEVNAME(sc->sc_dev), cmdlen, CBWCDBLENGTH)); 9291.28Saugustss KASSERT(dir == DIR_NONE || datalen > 0, 9301.28Saugustss ("%s: datalen == 0 while direction is not NONE\n", 9311.1Sthorpej USBDEVNAME(sc->sc_dev))); 9321.28Saugustss KASSERT(datalen == 0 || dir != DIR_NONE, 9331.28Saugustss ("%s: direction is NONE while datalen is not zero\n", 9341.28Saugustss USBDEVNAME(sc->sc_dev))); 9351.28Saugustss KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE, 9361.28Saugustss ("%s: CBW struct does not have the right size (%d vs. %d)\n", 9371.28Saugustss USBDEVNAME(sc->sc_dev), 9381.28Saugustss sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE)); 9391.28Saugustss KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE, 9401.28Saugustss ("%s: CSW struct does not have the right size (%d vs. %d)\n", 9411.28Saugustss USBDEVNAME(sc->sc_dev), 9421.28Saugustss sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE)); 9431.1Sthorpej 9441.1Sthorpej /* 9451.28Saugustss * Determine the direction of the data transfer and the length. 9461.1Sthorpej * 9471.1Sthorpej * dCBWDataTransferLength (datalen) : 9481.1Sthorpej * This field indicates the number of bytes of data that the host 9491.1Sthorpej * intends to transfer on the IN or OUT Bulk endpoint(as indicated by 9501.1Sthorpej * the Direction bit) during the execution of this command. If this 9511.1Sthorpej * field is set to 0, the device will expect that no data will be 9521.1Sthorpej * transferred IN or OUT during this command, regardless of the value 9531.1Sthorpej * of the Direction bit defined in dCBWFlags. 9541.1Sthorpej * 9551.1Sthorpej * dCBWFlags (dir) : 9561.1Sthorpej * The bits of the Flags field are defined as follows: 9571.28Saugustss * Bits 0-6 reserved 9581.28Saugustss * Bit 7 Direction - this bit shall be ignored if the 9591.28Saugustss * dCBWDataTransferLength field is zero. 9601.28Saugustss * 0 = data Out from host to device 9611.28Saugustss * 1 = data In from device to host 9621.1Sthorpej */ 9631.1Sthorpej 9641.28Saugustss /* Fill in the Command Block Wrapper */ 9651.28Saugustss USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); 9661.28Saugustss USETDW(sc->cbw.dCBWTag, dCBWtag); 9671.28Saugustss dCBWtag++; /* cannot be done in macro (it will be done 4 times) */ 9681.28Saugustss USETDW(sc->cbw.dCBWDataTransferLength, datalen); 9691.28Saugustss /* DIR_NONE is treated as DIR_OUT (0x00) */ 9701.28Saugustss sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT); 9711.28Saugustss sc->cbw.bCBWLUN = lun; 9721.28Saugustss sc->cbw.bCDBLength = cmdlen; 9731.69Sgehenna memcpy(sc->cbw.CBWCDB, cmd, cmdlen); 9741.28Saugustss 9751.28Saugustss DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); 9761.28Saugustss 9771.28Saugustss /* store the details for the data transfer phase */ 9781.28Saugustss sc->transfer_dir = dir; 9791.28Saugustss sc->transfer_data = data; 9801.28Saugustss sc->transfer_datalen = datalen; 9811.28Saugustss sc->transfer_actlen = 0; 9821.28Saugustss sc->transfer_cb = cb; 9831.28Saugustss sc->transfer_priv = priv; 9841.28Saugustss sc->transfer_status = STATUS_CMD_OK; 9851.1Sthorpej 9861.28Saugustss /* move from idle to the command state */ 9871.28Saugustss sc->transfer_state = TSTATE_BBB_COMMAND; 9881.1Sthorpej 9891.1Sthorpej /* Send the CBW from host to device via bulk-out endpoint. */ 9901.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], 9911.28Saugustss &sc->cbw, UMASS_BBB_CBW_SIZE, 0, 9921.28Saugustss sc->transfer_xfer[XFER_BBB_CBW])) { 9931.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 9941.1Sthorpej } 9951.28Saugustss} 9961.28Saugustss 9971.1Sthorpej 9981.28SaugustssStatic void 9991.28Saugustssumass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, 10001.28Saugustss usbd_status err) 10011.28Saugustss{ 10021.28Saugustss struct umass_softc *sc = (struct umass_softc *) priv; 10031.28Saugustss usbd_xfer_handle next_xfer; 10041.28Saugustss 10051.78Sgehenna KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, 10061.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n", 10071.78Sgehenna sc->sc_wire)); 10081.28Saugustss 10091.28Saugustss if (sc->sc_dying) 10101.28Saugustss return; 10111.1Sthorpej 10121.1Sthorpej /* 10131.28Saugustss * State handling for BBB transfers. 10141.28Saugustss * 10151.28Saugustss * The subroutine is rather long. It steps through the states given in 10161.28Saugustss * Annex A of the Bulk-Only specification. 10171.28Saugustss * Each state first does the error handling of the previous transfer 10181.28Saugustss * and then prepares the next transfer. 10191.28Saugustss * Each transfer is done asynchroneously so after the request/transfer 10201.28Saugustss * has been submitted you will find a 'return;'. 10211.1Sthorpej */ 10221.1Sthorpej 10231.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n", 10241.28Saugustss USBDEVNAME(sc->sc_dev), sc->transfer_state, 10251.28Saugustss states[sc->transfer_state], xfer, usbd_errstr(err))); 10261.28Saugustss 10271.28Saugustss switch (sc->transfer_state) { 10281.28Saugustss 10291.28Saugustss /***** Bulk Transfer *****/ 10301.28Saugustss case TSTATE_BBB_COMMAND: 10311.28Saugustss /* Command transport phase, error handling */ 10321.28Saugustss if (err) { 10331.28Saugustss DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n", 10341.28Saugustss USBDEVNAME(sc->sc_dev))); 10351.28Saugustss /* If the device detects that the CBW is invalid, then 10361.28Saugustss * the device may STALL both bulk endpoints and require 10371.28Saugustss * a Bulk-Reset 10381.28Saugustss */ 10391.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 10401.28Saugustss return; 10411.28Saugustss } 10421.28Saugustss 10431.28Saugustss /* Data transport phase, setup transfer */ 10441.28Saugustss sc->transfer_state = TSTATE_BBB_DATA; 10451.28Saugustss if (sc->transfer_dir == DIR_IN) { 10461.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], 10471.28Saugustss sc->data_buffer, sc->transfer_datalen, 10481.28Saugustss USBD_SHORT_XFER_OK | USBD_NO_COPY, 10491.28Saugustss sc->transfer_xfer[XFER_BBB_DATA])) 10501.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 10511.28Saugustss 10521.28Saugustss return; 10531.28Saugustss } else if (sc->transfer_dir == DIR_OUT) { 10541.88Saugustss memcpy(sc->data_buffer, sc->transfer_data, 10551.28Saugustss sc->transfer_datalen); 10561.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], 10571.28Saugustss sc->data_buffer, sc->transfer_datalen, 10581.28Saugustss USBD_NO_COPY,/* fixed length transfer */ 10591.28Saugustss sc->transfer_xfer[XFER_BBB_DATA])) 10601.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 10611.1Sthorpej 10621.28Saugustss return; 10631.28Saugustss } else { 10641.28Saugustss DPRINTF(UDMASS_BBB, ("%s: no data phase\n", 10651.28Saugustss USBDEVNAME(sc->sc_dev))); 10661.28Saugustss } 10671.1Sthorpej 10681.28Saugustss /* FALLTHROUGH if no data phase, err == 0 */ 10691.28Saugustss case TSTATE_BBB_DATA: 10701.96.2.1Sskrll /* Command transport phase error handling (ignored if no data 10711.28Saugustss * phase (fallthrough from previous state)) */ 10721.28Saugustss if (sc->transfer_dir != DIR_NONE) { 10731.28Saugustss /* retrieve the length of the transfer that was done */ 10741.28Saugustss usbd_get_xfer_status(xfer, NULL, NULL, 10751.96.2.1Sskrll &sc->transfer_actlen, NULL); 10761.96.2.1Sskrll DPRINTF(UDMASS_BBB, ("%s: BBB_DATA actlen=%d\n", 10771.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->transfer_actlen)); 10781.28Saugustss 10791.28Saugustss if (err) { 10801.65Saugustss DPRINTF(UDMASS_BBB, ("%s: Data-%s %d failed, " 10811.28Saugustss "%s\n", USBDEVNAME(sc->sc_dev), 10821.28Saugustss (sc->transfer_dir == DIR_IN?"in":"out"), 10831.28Saugustss sc->transfer_datalen,usbd_errstr(err))); 10841.28Saugustss 10851.28Saugustss if (err == USBD_STALLED) { 10861.70Sgehenna sc->transfer_state = TSTATE_BBB_DCLEAR; 10871.28Saugustss umass_clear_endpoint_stall(sc, 10881.28Saugustss (sc->transfer_dir == DIR_IN? 10891.73Sgehenna UMASS_BULKIN:UMASS_BULKOUT), 10901.28Saugustss sc->transfer_xfer[XFER_BBB_DCLEAR]); 10911.28Saugustss } else { 10921.28Saugustss /* Unless the error is a pipe stall the 10931.28Saugustss * error is fatal. 10941.28Saugustss */ 10951.28Saugustss umass_bbb_reset(sc,STATUS_WIRE_FAILED); 10961.28Saugustss } 10971.96.2.1Sskrll return; 10981.28Saugustss } 10991.28Saugustss } 11001.1Sthorpej 11011.96.2.1Sskrll /* FALLTHROUGH, err == 0 (no data phase or successful) */ 11021.96.2.1Sskrll case TSTATE_BBB_DCLEAR: /* stall clear after data phase */ 11031.28Saugustss if (sc->transfer_dir == DIR_IN) 11041.28Saugustss memcpy(sc->transfer_data, sc->data_buffer, 11051.28Saugustss sc->transfer_actlen); 11061.28Saugustss 11071.28Saugustss DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN) 11081.28Saugustss umass_dump_buffer(sc, sc->transfer_data, 11091.28Saugustss sc->transfer_datalen, 48)); 11101.28Saugustss 11111.94Swiz /* FALLTHROUGH, err == 0 (no data phase or successful) */ 11121.28Saugustss case TSTATE_BBB_SCLEAR: /* stall clear after status phase */ 11131.28Saugustss /* Reading of CSW after bulk stall condition in data phase 11141.28Saugustss * (TSTATE_BBB_DATA2) or bulk-in stall condition after 11151.28Saugustss * reading CSW (TSTATE_BBB_SCLEAR). 11161.94Swiz * In the case of no data phase or successful data phase, 11171.28Saugustss * err == 0 and the following if block is passed. 11181.28Saugustss */ 11191.28Saugustss if (err) { /* should not occur */ 11201.96.2.1Sskrll printf("%s: BBB bulk-%s stall clear failed, %s\n", 11211.96.2.1Sskrll USBDEVNAME(sc->sc_dev), 11221.96.2.1Sskrll (sc->transfer_dir == DIR_IN? "in":"out"), 11231.96.2.1Sskrll usbd_errstr(err)); 11241.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 11251.28Saugustss return; 11261.28Saugustss } 11271.88Saugustss 11281.28Saugustss /* Status transport phase, setup transfer */ 11291.28Saugustss if (sc->transfer_state == TSTATE_BBB_COMMAND || 11301.28Saugustss sc->transfer_state == TSTATE_BBB_DATA || 11311.28Saugustss sc->transfer_state == TSTATE_BBB_DCLEAR) { 11321.94Swiz /* After no data phase, successful data phase and 11331.28Saugustss * after clearing bulk-in/-out stall condition 11341.28Saugustss */ 11351.28Saugustss sc->transfer_state = TSTATE_BBB_STATUS1; 11361.28Saugustss next_xfer = sc->transfer_xfer[XFER_BBB_CSW1]; 11371.28Saugustss } else { 11381.28Saugustss /* After first attempt of fetching CSW */ 11391.28Saugustss sc->transfer_state = TSTATE_BBB_STATUS2; 11401.28Saugustss next_xfer = sc->transfer_xfer[XFER_BBB_CSW2]; 11411.1Sthorpej } 11421.1Sthorpej 11431.28Saugustss /* Read the Command Status Wrapper via bulk-in endpoint. */ 11441.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], 11451.73Sgehenna &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) { 11461.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 11471.28Saugustss return; 11481.28Saugustss } 11491.1Sthorpej 11501.28Saugustss return; 11511.28Saugustss case TSTATE_BBB_STATUS1: /* first attempt */ 11521.28Saugustss case TSTATE_BBB_STATUS2: /* second attempt */ 11531.28Saugustss /* Status transfer, error handling */ 11541.1Sthorpej if (err) { 11551.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n", 11561.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err), 11571.28Saugustss (sc->transfer_state == TSTATE_BBB_STATUS1? 11581.28Saugustss ", retrying":""))); 11591.28Saugustss 11601.28Saugustss /* If this was the first attempt at fetching the CSW 11611.28Saugustss * retry it, otherwise fail. 11621.28Saugustss */ 11631.28Saugustss if (sc->transfer_state == TSTATE_BBB_STATUS1) { 11641.70Sgehenna sc->transfer_state = TSTATE_BBB_SCLEAR; 11651.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_BULKIN, 11661.66Saugustss sc->transfer_xfer[XFER_BBB_SCLEAR]); 11671.28Saugustss return; 11681.28Saugustss } else { 11691.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 11701.28Saugustss return; 11711.28Saugustss } 11721.28Saugustss } 11731.28Saugustss 11741.28Saugustss DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); 11751.68Saugustss 11761.68Saugustss /* Translate weird command-status signatures. */ 11771.78Sgehenna if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) && 11781.68Saugustss UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1) 11791.68Saugustss USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); 11801.91Serh 11811.91Serh /* Translate invalid command-status tags */ 11821.91Serh if (sc->sc_quirks & UMASS_QUIRK_WRONG_CSWTAG) 11831.91Serh USETDW(sc->csw.dCSWTag, UGETDW(sc->cbw.dCBWTag)); 11841.28Saugustss 11851.28Saugustss /* Check CSW and handle any error */ 11861.28Saugustss if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { 11871.28Saugustss /* Invalid CSW: Wrong signature or wrong tag might 11881.28Saugustss * indicate that the device is confused -> reset it. 11891.28Saugustss */ 11901.28Saugustss printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n", 11911.28Saugustss USBDEVNAME(sc->sc_dev), 11921.28Saugustss UGETDW(sc->csw.dCSWSignature), 11931.28Saugustss CSWSIGNATURE); 11941.28Saugustss 11951.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 11961.28Saugustss return; 11971.28Saugustss } else if (UGETDW(sc->csw.dCSWTag) 11981.28Saugustss != UGETDW(sc->cbw.dCBWTag)) { 11991.28Saugustss printf("%s: Invalid CSW: tag %d should be %d\n", 12001.28Saugustss USBDEVNAME(sc->sc_dev), 12011.28Saugustss UGETDW(sc->csw.dCSWTag), 12021.28Saugustss UGETDW(sc->cbw.dCBWTag)); 12031.28Saugustss 12041.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 12051.28Saugustss return; 12061.28Saugustss 12071.28Saugustss /* CSW is valid here */ 12081.28Saugustss } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) { 12091.28Saugustss printf("%s: Invalid CSW: status %d > %d\n", 12101.28Saugustss USBDEVNAME(sc->sc_dev), 12111.28Saugustss sc->csw.bCSWStatus, 12121.28Saugustss CSWSTATUS_PHASE); 12131.28Saugustss 12141.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 12151.28Saugustss return; 12161.28Saugustss } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) { 12171.28Saugustss printf("%s: Phase Error, residue = %d\n", 12181.28Saugustss USBDEVNAME(sc->sc_dev), 12191.28Saugustss UGETDW(sc->csw.dCSWDataResidue)); 12201.88Saugustss 12211.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 12221.28Saugustss return; 12231.28Saugustss 12241.28Saugustss } else if (sc->transfer_actlen > sc->transfer_datalen) { 12251.28Saugustss /* Buffer overrun! Don't let this go by unnoticed */ 12261.89Sprovos panic("%s: transferred %d bytes instead of %d bytes", 12271.28Saugustss USBDEVNAME(sc->sc_dev), 12281.28Saugustss sc->transfer_actlen, sc->transfer_datalen); 12291.62Saugustss#if 0 12301.28Saugustss } else if (sc->transfer_datalen - sc->transfer_actlen 12311.28Saugustss != UGETDW(sc->csw.dCSWDataResidue)) { 12321.28Saugustss DPRINTF(UDMASS_BBB, ("%s: actlen=%d != residue=%d\n", 12331.1Sthorpej USBDEVNAME(sc->sc_dev), 12341.28Saugustss sc->transfer_datalen - sc->transfer_actlen, 12351.28Saugustss UGETDW(sc->csw.dCSWDataResidue))); 12361.28Saugustss 12371.28Saugustss umass_bbb_reset(sc, STATUS_WIRE_FAILED); 12381.28Saugustss return; 12391.62Saugustss#endif 12401.28Saugustss } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { 12411.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n", 12421.1Sthorpej USBDEVNAME(sc->sc_dev), 12431.28Saugustss UGETDW(sc->csw.dCSWDataResidue))); 12441.28Saugustss 12451.28Saugustss /* SCSI command failed but transfer was succesful */ 12461.28Saugustss sc->transfer_state = TSTATE_IDLE; 12471.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 12481.28Saugustss UGETDW(sc->csw.dCSWDataResidue), 12491.28Saugustss STATUS_CMD_FAILED); 12501.28Saugustss 12511.28Saugustss return; 12521.28Saugustss 12531.28Saugustss } else { /* success */ 12541.28Saugustss sc->transfer_state = TSTATE_IDLE; 12551.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 12561.28Saugustss UGETDW(sc->csw.dCSWDataResidue), 12571.28Saugustss STATUS_CMD_OK); 12581.28Saugustss 12591.28Saugustss return; 12601.1Sthorpej } 12611.1Sthorpej 12621.28Saugustss /***** Bulk Reset *****/ 12631.28Saugustss case TSTATE_BBB_RESET1: 12641.28Saugustss if (err) 12651.28Saugustss printf("%s: BBB reset failed, %s\n", 12661.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 12671.28Saugustss 12681.70Sgehenna sc->transfer_state = TSTATE_BBB_RESET2; 12691.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_BULKIN, 12701.28Saugustss sc->transfer_xfer[XFER_BBB_RESET2]); 12711.28Saugustss 12721.28Saugustss return; 12731.28Saugustss case TSTATE_BBB_RESET2: 12741.28Saugustss if (err) /* should not occur */ 12751.28Saugustss printf("%s: BBB bulk-in clear stall failed, %s\n", 12761.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 12771.28Saugustss /* no error recovery, otherwise we end up in a loop */ 12781.28Saugustss 12791.70Sgehenna sc->transfer_state = TSTATE_BBB_RESET3; 12801.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_BULKOUT, 12811.28Saugustss sc->transfer_xfer[XFER_BBB_RESET3]); 12821.28Saugustss 12831.28Saugustss return; 12841.28Saugustss case TSTATE_BBB_RESET3: 12851.28Saugustss if (err) /* should not occur */ 12861.28Saugustss printf("%s: BBB bulk-out clear stall failed, %s\n", 12871.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 12881.28Saugustss /* no error recovery, otherwise we end up in a loop */ 12891.28Saugustss 12901.28Saugustss sc->transfer_state = TSTATE_IDLE; 12911.28Saugustss if (sc->transfer_priv) { 12921.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 12931.28Saugustss sc->transfer_datalen, 12941.28Saugustss sc->transfer_status); 12951.28Saugustss } 12961.1Sthorpej 12971.28Saugustss return; 12981.1Sthorpej 12991.28Saugustss /***** Default *****/ 13001.28Saugustss default: 13011.89Sprovos panic("%s: Unknown state %d", 13021.28Saugustss USBDEVNAME(sc->sc_dev), sc->transfer_state); 13031.28Saugustss } 13041.1Sthorpej} 13051.1Sthorpej 13061.1Sthorpej/* 13071.28Saugustss * Command/Bulk/Interrupt (CBI) specific functions 13081.1Sthorpej */ 13091.1Sthorpej 13101.28SaugustssStatic int 13111.28Saugustssumass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, 13121.28Saugustss usbd_xfer_handle xfer) 13131.1Sthorpej{ 13141.78Sgehenna KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), 13151.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n", 13161.78Sgehenna sc->sc_wire)); 13171.78Sgehenna 13181.78Sgehenna sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 13191.78Sgehenna sc->sc_req.bRequest = UR_CBI_ADSC; 13201.78Sgehenna USETW(sc->sc_req.wValue, 0); 13211.78Sgehenna USETW(sc->sc_req.wIndex, sc->sc_ifaceno); 13221.78Sgehenna USETW(sc->sc_req.wLength, buflen); 13231.78Sgehenna return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer, 13241.28Saugustss buflen, 0, xfer); 13251.28Saugustss} 13261.28Saugustss 13271.1Sthorpej 13281.28SaugustssStatic void 13291.28Saugustssumass_cbi_reset(struct umass_softc *sc, int status) 13301.28Saugustss{ 13311.28Saugustss int i; 13321.28Saugustss# define SEND_DIAGNOSTIC_CMDLEN 12 13331.1Sthorpej 13341.78Sgehenna KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), 13351.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n", 13361.78Sgehenna sc->sc_wire)); 13371.15Sthorpej 13381.28Saugustss if (sc->sc_dying) 13391.28Saugustss return; 13401.28Saugustss 13411.28Saugustss /* 13421.28Saugustss * Command Block Reset Protocol 13431.88Saugustss * 13441.28Saugustss * First send a reset request to the device. Then clear 13451.28Saugustss * any possibly stalled bulk endpoints. 13461.28Saugustss 13471.28Saugustss * This is done in 3 steps, states: 13481.28Saugustss * TSTATE_CBI_RESET1 13491.28Saugustss * TSTATE_CBI_RESET2 13501.28Saugustss * TSTATE_CBI_RESET3 13511.28Saugustss * 13521.28Saugustss * If the reset doesn't succeed, the device should be port reset. 13531.28Saugustss */ 13541.28Saugustss 13551.28Saugustss DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n", 13561.28Saugustss USBDEVNAME(sc->sc_dev))); 13571.88Saugustss 13581.28Saugustss KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN, 13591.28Saugustss ("%s: CBL struct is too small (%d < %d)\n", 13601.28Saugustss USBDEVNAME(sc->sc_dev), 13611.28Saugustss sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN)); 13621.28Saugustss 13631.28Saugustss sc->transfer_state = TSTATE_CBI_RESET1; 13641.28Saugustss sc->transfer_status = status; 13651.28Saugustss 13661.28Saugustss /* The 0x1d code is the SEND DIAGNOSTIC command. To distingiush between 13671.28Saugustss * the two the last 10 bytes of the cbl is filled with 0xff (section 13681.28Saugustss * 2.2 of the CBI spec). 13691.28Saugustss */ 13701.28Saugustss sc->cbl[0] = 0x1d; /* Command Block Reset */ 13711.28Saugustss sc->cbl[1] = 0x04; 13721.28Saugustss for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++) 13731.28Saugustss sc->cbl[i] = 0xff; 13741.28Saugustss 13751.28Saugustss umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, 13761.28Saugustss sc->transfer_xfer[XFER_CBI_RESET1]); 13771.28Saugustss /* XXX if the command fails we should reset the port on the bub */ 13781.28Saugustss} 13791.28Saugustss 13801.28SaugustssStatic void 13811.28Saugustssumass_cbi_transfer(struct umass_softc *sc, int lun, 13821.67Saugustss void *cmd, int cmdlen, void *data, int datalen, int dir, 13831.75Sgehenna u_int timeout, umass_callback cb, void *priv) 13841.28Saugustss{ 13851.28Saugustss DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n", 13861.87Saugustss USBDEVNAME(sc->sc_dev), *(u_char *)cmd, datalen)); 13871.28Saugustss 13881.78Sgehenna KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), 13891.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n", 13901.78Sgehenna sc->sc_wire)); 13911.28Saugustss 13921.28Saugustss if (sc->sc_dying) 13931.28Saugustss return; 13941.67Saugustss 13951.67Saugustss /* Be a little generous. */ 13961.67Saugustss sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; 13971.28Saugustss 13981.28Saugustss /* 13991.28Saugustss * Do a CBI transfer with cmdlen bytes from cmd, possibly 14001.28Saugustss * a data phase of datalen bytes from/to the device and finally a 14011.28Saugustss * csw read phase. 14021.28Saugustss * If the data direction was inbound a maximum of datalen bytes 14031.28Saugustss * is stored in the buffer pointed to by data. 14041.28Saugustss * 14051.28Saugustss * umass_cbi_transfer initialises the transfer and lets the state 14061.88Saugustss * machine in umass_cbi_state handle the completion. It uses the 14071.28Saugustss * following states: 14081.28Saugustss * TSTATE_CBI_COMMAND 14091.28Saugustss * -> XXX fill in 14101.28Saugustss * 14111.28Saugustss * An error in any of those states will invoke 14121.28Saugustss * umass_cbi_reset. 14131.28Saugustss */ 14141.28Saugustss 14151.28Saugustss /* check the given arguments */ 14161.28Saugustss KASSERT(datalen == 0 || data != NULL, 14171.28Saugustss ("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev))); 14181.28Saugustss KASSERT(datalen == 0 || dir != DIR_NONE, 14191.28Saugustss ("%s: direction is NONE while datalen is not zero\n", 14201.28Saugustss USBDEVNAME(sc->sc_dev))); 14211.28Saugustss 14221.28Saugustss /* store the details for the data transfer phase */ 14231.28Saugustss sc->transfer_dir = dir; 14241.28Saugustss sc->transfer_data = data; 14251.28Saugustss sc->transfer_datalen = datalen; 14261.28Saugustss sc->transfer_actlen = 0; 14271.28Saugustss sc->transfer_cb = cb; 14281.28Saugustss sc->transfer_priv = priv; 14291.28Saugustss sc->transfer_status = STATUS_CMD_OK; 14301.28Saugustss 14311.28Saugustss /* move from idle to the command state */ 14321.28Saugustss sc->transfer_state = TSTATE_CBI_COMMAND; 14331.28Saugustss 14341.28Saugustss /* Send the Command Block from host to device via control endpoint. */ 14351.28Saugustss if (umass_cbi_adsc(sc, cmd, cmdlen, sc->transfer_xfer[XFER_CBI_CB])) 14361.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 14371.28Saugustss} 14381.28Saugustss 14391.28SaugustssStatic void 14401.28Saugustssumass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, 14411.28Saugustss usbd_status err) 14421.28Saugustss{ 14431.28Saugustss struct umass_softc *sc = (struct umass_softc *) priv; 14441.28Saugustss 14451.78Sgehenna KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), 14461.78Sgehenna ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n", 14471.78Sgehenna sc->sc_wire)); 14481.28Saugustss 14491.28Saugustss if (sc->sc_dying) 14501.28Saugustss return; 14511.28Saugustss 14521.28Saugustss /* 14531.28Saugustss * State handling for CBI transfers. 14541.28Saugustss */ 14551.28Saugustss 14561.28Saugustss DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n", 14571.28Saugustss USBDEVNAME(sc->sc_dev), sc->transfer_state, 14581.28Saugustss states[sc->transfer_state], xfer, usbd_errstr(err))); 14591.28Saugustss 14601.28Saugustss switch (sc->transfer_state) { 14611.28Saugustss 14621.28Saugustss /***** CBI Transfer *****/ 14631.28Saugustss case TSTATE_CBI_COMMAND: 14641.28Saugustss if (err == USBD_STALLED) { 14651.28Saugustss DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n", 14661.28Saugustss USBDEVNAME(sc->sc_dev))); 14671.28Saugustss /* Status transport by control pipe (section 2.3.2.1). 14681.28Saugustss * The command contained in the command block failed. 14691.28Saugustss * 14701.28Saugustss * The control pipe has already been unstalled by the 14711.28Saugustss * USB stack. 14721.28Saugustss * Section 2.4.3.1.1 states that the bulk in endpoints 14731.28Saugustss * should not stalled at this point. 14741.28Saugustss */ 14751.28Saugustss 14761.28Saugustss sc->transfer_state = TSTATE_IDLE; 14771.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 14781.28Saugustss sc->transfer_datalen, 14791.28Saugustss STATUS_CMD_FAILED); 14801.28Saugustss 14811.28Saugustss return; 14821.28Saugustss } else if (err) { 14831.28Saugustss DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n", 14841.28Saugustss USBDEVNAME(sc->sc_dev))); 14851.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 14861.28Saugustss return; 14871.28Saugustss } 14881.88Saugustss 14891.96.2.1Sskrll /* Data transport phase, setup transfer */ 14901.28Saugustss sc->transfer_state = TSTATE_CBI_DATA; 14911.28Saugustss if (sc->transfer_dir == DIR_IN) { 14921.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], 14931.96.2.1Sskrll sc->data_buffer, sc->transfer_datalen, 14941.28Saugustss USBD_SHORT_XFER_OK | USBD_NO_COPY, 14951.28Saugustss sc->transfer_xfer[XFER_CBI_DATA])) 14961.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 14971.28Saugustss 14981.96.2.1Sskrll return; 14991.28Saugustss } else if (sc->transfer_dir == DIR_OUT) { 15001.88Saugustss memcpy(sc->data_buffer, sc->transfer_data, 15011.28Saugustss sc->transfer_datalen); 15021.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], 15031.96.2.1Sskrll sc->data_buffer, sc->transfer_datalen, 15041.28Saugustss USBD_NO_COPY,/* fixed length transfer */ 15051.28Saugustss sc->transfer_xfer[XFER_CBI_DATA])) 15061.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 15071.28Saugustss 15081.96.2.1Sskrll return; 15091.28Saugustss } else { 15101.28Saugustss DPRINTF(UDMASS_CBI, ("%s: no data phase\n", 15111.28Saugustss USBDEVNAME(sc->sc_dev))); 15121.28Saugustss } 15131.28Saugustss 15141.96.2.1Sskrll /* FALLTHROUGH if no data phase, err == 0 */ 15151.28Saugustss case TSTATE_CBI_DATA: 15161.96.2.1Sskrll /* Command transport phase error handling (ignored if no data 15171.96.2.1Sskrll * phase (fallthrough from previous state)) */ 15181.96.2.1Sskrll if (sc->transfer_dir != DIR_NONE) { 15191.96.2.1Sskrll /* retrieve the length of the transfer that was done */ 15201.96.2.1Sskrll usbd_get_xfer_status(xfer, NULL, NULL, 15211.96.2.1Sskrll &sc->transfer_actlen, NULL); 15221.96.2.1Sskrll DPRINTF(UDMASS_CBI, ("%s: CBI_DATA actlen=%d\n", 15231.96.2.1Sskrll USBDEVNAME(sc->sc_dev), sc->transfer_actlen)); 15241.28Saugustss 15251.96.2.1Sskrll if (err) { 15261.96.2.1Sskrll DPRINTF(UDMASS_CBI, ("%s: Data-%s %d failed, " 15271.96.2.1Sskrll "%s\n", USBDEVNAME(sc->sc_dev), 15281.96.2.1Sskrll (sc->transfer_dir == DIR_IN?"in":"out"), 15291.96.2.1Sskrll sc->transfer_datalen,usbd_errstr(err))); 15301.28Saugustss 15311.96.2.1Sskrll if (err == USBD_STALLED) { 15321.96.2.1Sskrll sc->transfer_state = TSTATE_CBI_DCLEAR; 15331.96.2.1Sskrll umass_clear_endpoint_stall(sc, 15341.96.2.1Sskrll (sc->transfer_dir == DIR_IN? 15351.96.2.1Sskrll UMASS_BULKIN:UMASS_BULKOUT), 15361.28Saugustss sc->transfer_xfer[XFER_CBI_DCLEAR]); 15371.96.2.1Sskrll } else { 15381.96.2.1Sskrll /* Unless the error is a pipe stall the 15391.96.2.1Sskrll * error is fatal. 15401.96.2.1Sskrll */ 15411.96.2.1Sskrll umass_cbi_reset(sc, STATUS_WIRE_FAILED); 15421.96.2.1Sskrll } 15431.96.2.1Sskrll return; 15441.28Saugustss } 15451.28Saugustss } 15461.28Saugustss 15471.28Saugustss if (sc->transfer_dir == DIR_IN) 15481.28Saugustss memcpy(sc->transfer_data, sc->data_buffer, 15491.28Saugustss sc->transfer_actlen); 15501.28Saugustss 15511.28Saugustss DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN) 15521.28Saugustss umass_dump_buffer(sc, sc->transfer_data, 15531.28Saugustss sc->transfer_actlen, 48)); 15541.28Saugustss 15551.96.2.1Sskrll /* Status phase */ 15561.78Sgehenna if (sc->sc_wire == UMASS_WPROTO_CBI_I) { 15571.28Saugustss sc->transfer_state = TSTATE_CBI_STATUS; 15581.28Saugustss memset(&sc->sbl, 0, sizeof(sc->sbl)); 15591.73Sgehenna if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN], 15601.28Saugustss &sc->sbl, sizeof(sc->sbl), 15611.28Saugustss 0, /* fixed length transfer */ 15621.96.2.1Sskrll sc->transfer_xfer[XFER_CBI_STATUS])) 15631.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 15641.28Saugustss } else { 15651.28Saugustss /* No command completion interrupt. Request 15661.28Saugustss * sense to get status of command. 15671.28Saugustss */ 15681.28Saugustss sc->transfer_state = TSTATE_IDLE; 15691.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 15701.28Saugustss sc->transfer_datalen - sc->transfer_actlen, 15711.28Saugustss STATUS_CMD_UNKNOWN); 15721.28Saugustss } 15731.28Saugustss return; 15741.28Saugustss 15751.28Saugustss case TSTATE_CBI_STATUS: 15761.28Saugustss if (err) { 15771.28Saugustss DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n", 15781.28Saugustss USBDEVNAME(sc->sc_dev))); 15791.28Saugustss /* Status transport by interrupt pipe (section 2.3.2.2). 15801.28Saugustss */ 15811.28Saugustss 15821.28Saugustss if (err == USBD_STALLED) { 15831.70Sgehenna sc->transfer_state = TSTATE_CBI_SCLEAR; 15841.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_INTRIN, 15851.28Saugustss sc->transfer_xfer[XFER_CBI_SCLEAR]); 15861.28Saugustss } else { 15871.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 15881.28Saugustss } 15891.28Saugustss return; 15901.28Saugustss } 15911.28Saugustss 15921.28Saugustss /* Dissect the information in the buffer */ 15931.28Saugustss 15941.96.2.1Sskrll { 15951.96.2.1Sskrll u_int32_t actlen; 15961.96.2.1Sskrll usbd_get_xfer_status(xfer,NULL,NULL,&actlen,NULL); 15971.96.2.1Sskrll DPRINTF(UDMASS_CBI, ("%s: CBI_STATUS actlen=%d\n", 15981.96.2.1Sskrll USBDEVNAME(sc->sc_dev), actlen)); 15991.96.2.1Sskrll if (actlen != 2) 16001.96.2.1Sskrll break; 16011.96.2.1Sskrll } 16021.96.2.1Sskrll 16031.78Sgehenna if (sc->sc_cmd == UMASS_CPROTO_UFI) { 16041.28Saugustss int status; 16051.88Saugustss 16061.28Saugustss /* Section 3.4.3.1.3 specifies that the UFI command 16071.28Saugustss * protocol returns an ASC and ASCQ in the interrupt 16081.28Saugustss * data block. 16091.28Saugustss */ 16101.28Saugustss 16111.28Saugustss DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, " 16121.28Saugustss "ASCQ = 0x%02x\n", 16131.28Saugustss USBDEVNAME(sc->sc_dev), 16141.28Saugustss sc->sbl.ufi.asc, sc->sbl.ufi.ascq)); 16151.28Saugustss 16161.96.2.1Sskrll if ((sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) || 16171.96.2.1Sskrll sc->sc_sense) 16181.28Saugustss status = STATUS_CMD_OK; 16191.28Saugustss else 16201.28Saugustss status = STATUS_CMD_FAILED; 16211.28Saugustss 16221.96.2.1Sskrll /* No autosense, command successful */ 16231.96.2.1Sskrll sc->transfer_state = TSTATE_IDLE; 16241.96.2.1Sskrll sc->transfer_cb(sc, sc->transfer_priv, 16251.96.2.1Sskrll sc->transfer_datalen - sc->transfer_actlen, status); 16261.28Saugustss } else { 16271.96.2.1Sskrll int status; 16281.96.2.1Sskrll 16291.28Saugustss /* Command Interrupt Data Block */ 16301.96.2.1Sskrll 16311.28Saugustss DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n", 16321.28Saugustss USBDEVNAME(sc->sc_dev), 16331.28Saugustss sc->sbl.common.type, sc->sbl.common.value)); 16341.28Saugustss 16351.28Saugustss if (sc->sbl.common.type == IDB_TYPE_CCI) { 16361.96.2.1Sskrll switch (sc->sbl.common.value & IDB_VALUE_STATUS_MASK) { 16371.96.2.1Sskrll case IDB_VALUE_PASS: 16381.96.2.1Sskrll status = STATUS_CMD_OK; 16391.96.2.1Sskrll break; 16401.96.2.1Sskrll case IDB_VALUE_FAIL: 16411.96.2.1Sskrll case IDB_VALUE_PERSISTENT: 16421.96.2.1Sskrll status = STATUS_CMD_FAILED; 16431.96.2.1Sskrll break; 16441.96.2.1Sskrll case IDB_VALUE_PHASE: 16451.96.2.1Sskrll default: /* XXX: gcc */ 16461.96.2.1Sskrll status = STATUS_WIRE_FAILED; 16471.96.2.1Sskrll break; 16481.28Saugustss } 16491.28Saugustss 16501.28Saugustss sc->transfer_state = TSTATE_IDLE; 16511.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 16521.96.2.1Sskrll sc->transfer_datalen - sc->transfer_actlen, status); 16531.28Saugustss } 16541.28Saugustss } 16551.28Saugustss return; 16561.28Saugustss 16571.28Saugustss case TSTATE_CBI_DCLEAR: 16581.28Saugustss if (err) { /* should not occur */ 16591.96.2.1Sskrll printf("%s: CBI bulk-%s stall clear failed, %s\n", 16601.96.2.1Sskrll USBDEVNAME(sc->sc_dev), 16611.96.2.1Sskrll (sc->transfer_dir == DIR_IN? "in":"out"), 16621.96.2.1Sskrll usbd_errstr(err)); 16631.28Saugustss umass_cbi_reset(sc, STATUS_WIRE_FAILED); 16641.96.2.1Sskrll } else { 16651.96.2.1Sskrll sc->transfer_state = TSTATE_IDLE; 16661.96.2.1Sskrll sc->transfer_cb(sc, sc->transfer_priv, 16671.96.2.1Sskrll sc->transfer_datalen, STATUS_CMD_FAILED); 16681.28Saugustss } 16691.28Saugustss return; 16701.28Saugustss 16711.28Saugustss case TSTATE_CBI_SCLEAR: 16721.96.2.1Sskrll if (err) { /* should not occur */ 16731.28Saugustss printf("%s: CBI intr-in stall clear failed, %s\n", 16741.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 16751.96.2.1Sskrll umass_cbi_reset(sc, STATUS_WIRE_FAILED); 16761.96.2.1Sskrll } else { 16771.96.2.1Sskrll sc->transfer_state = TSTATE_IDLE; 16781.96.2.1Sskrll sc->transfer_cb(sc, sc->transfer_priv, 16791.96.2.1Sskrll sc->transfer_datalen, STATUS_CMD_FAILED); 16801.96.2.1Sskrll } 16811.28Saugustss return; 16821.28Saugustss 16831.28Saugustss /***** CBI Reset *****/ 16841.28Saugustss case TSTATE_CBI_RESET1: 16851.28Saugustss if (err) 16861.28Saugustss printf("%s: CBI reset failed, %s\n", 16871.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 16881.28Saugustss 16891.70Sgehenna sc->transfer_state = TSTATE_CBI_RESET2; 16901.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_BULKIN, 16911.28Saugustss sc->transfer_xfer[XFER_CBI_RESET2]); 16921.28Saugustss 16931.28Saugustss return; 16941.28Saugustss case TSTATE_CBI_RESET2: 16951.28Saugustss if (err) /* should not occur */ 16961.28Saugustss printf("%s: CBI bulk-in stall clear failed, %s\n", 16971.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 16981.28Saugustss /* no error recovery, otherwise we end up in a loop */ 16991.28Saugustss 17001.70Sgehenna sc->transfer_state = TSTATE_CBI_RESET3; 17011.73Sgehenna umass_clear_endpoint_stall(sc, UMASS_BULKOUT, 17021.28Saugustss sc->transfer_xfer[XFER_CBI_RESET3]); 17031.28Saugustss 17041.28Saugustss return; 17051.28Saugustss case TSTATE_CBI_RESET3: 17061.28Saugustss if (err) /* should not occur */ 17071.28Saugustss printf("%s: CBI bulk-out stall clear failed, %s\n", 17081.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 17091.28Saugustss /* no error recovery, otherwise we end up in a loop */ 17101.28Saugustss 17111.28Saugustss sc->transfer_state = TSTATE_IDLE; 17121.28Saugustss if (sc->transfer_priv) { 17131.28Saugustss sc->transfer_cb(sc, sc->transfer_priv, 17141.28Saugustss sc->transfer_datalen, 17151.28Saugustss sc->transfer_status); 17161.28Saugustss } 17171.28Saugustss 17181.28Saugustss return; 17191.28Saugustss 17201.28Saugustss 17211.28Saugustss /***** Default *****/ 17221.28Saugustss default: 17231.89Sprovos panic("%s: Unknown state %d", 17241.28Saugustss USBDEVNAME(sc->sc_dev), sc->transfer_state); 17251.28Saugustss } 17261.28Saugustss} 17271.28Saugustss 17281.28Saugustssusbd_status 17291.28Saugustssumass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun) 17301.28Saugustss{ 17311.28Saugustss usb_device_request_t req; 17321.28Saugustss usbd_status err; 17331.28Saugustss 17341.28Saugustss *maxlun = 0; /* Default to 0. */ 17351.28Saugustss 17361.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Get Max Lun\n", USBDEVNAME(sc->sc_dev))); 17371.28Saugustss 17381.28Saugustss /* The Get Max Lun command is a class-specific request. */ 17391.28Saugustss req.bmRequestType = UT_READ_CLASS_INTERFACE; 17401.28Saugustss req.bRequest = UR_BBB_GET_MAX_LUN; 17411.28Saugustss USETW(req.wValue, 0); 17421.76Sgehenna USETW(req.wIndex, sc->sc_ifaceno); 17431.28Saugustss USETW(req.wLength, 1); 17441.28Saugustss 17451.96.2.1Sskrll err = usbd_do_request_flags(sc->sc_udev, &req, maxlun, 17461.96.2.1Sskrll USBD_SHORT_XFER_OK, 0, USBD_DEFAULT_TIMEOUT); 17471.28Saugustss switch (err) { 17481.28Saugustss case USBD_NORMAL_COMPLETION: 17491.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Max Lun %d\n", 17501.28Saugustss USBDEVNAME(sc->sc_dev), *maxlun)); 17511.28Saugustss break; 17521.28Saugustss 17531.28Saugustss case USBD_STALLED: 17541.28Saugustss /* 17551.28Saugustss * Device doesn't support Get Max Lun request. 17561.28Saugustss */ 17571.28Saugustss err = USBD_NORMAL_COMPLETION; 17581.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Get Max Lun not supported\n", 17591.28Saugustss USBDEVNAME(sc->sc_dev))); 17601.28Saugustss break; 17611.28Saugustss 17621.28Saugustss case USBD_SHORT_XFER: 17631.28Saugustss /* 17641.28Saugustss * XXX This must mean Get Max Lun is not supported, too! 17651.28Saugustss */ 17661.28Saugustss err = USBD_NORMAL_COMPLETION; 17671.28Saugustss DPRINTF(UDMASS_BBB, ("%s: Get Max Lun SHORT_XFER\n", 17681.28Saugustss USBDEVNAME(sc->sc_dev))); 17691.28Saugustss break; 17701.28Saugustss 17711.28Saugustss default: 17721.28Saugustss printf("%s: Get Max Lun failed: %s\n", 17731.28Saugustss USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 17741.28Saugustss /* XXX Should we port_reset the device? */ 17751.28Saugustss break; 17761.28Saugustss } 17771.28Saugustss 17781.28Saugustss return (err); 17791.28Saugustss} 17801.28Saugustss 17811.28Saugustss 17821.28Saugustss 17831.28Saugustss 17841.28Saugustss#ifdef UMASS_DEBUG 17851.28SaugustssStatic void 17861.28Saugustssumass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) 17871.28Saugustss{ 17881.28Saugustss int clen = cbw->bCDBLength; 17891.28Saugustss int dlen = UGETDW(cbw->dCBWDataTransferLength); 17901.28Saugustss u_int8_t *c = cbw->CBWCDB; 17911.28Saugustss int tag = UGETDW(cbw->dCBWTag); 17921.28Saugustss int flags = cbw->bCBWFlags; 17931.28Saugustss 17941.83Saugustss DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmdlen=%d " 17951.83Saugustss "(0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%s), " 17961.28Saugustss "data = %d bytes, dir = %s\n", 17971.28Saugustss USBDEVNAME(sc->sc_dev), tag, clen, 17981.83Saugustss c[0], c[1], c[2], c[3], c[4], c[5], 17991.83Saugustss c[6], c[7], c[8], c[9], 18001.83Saugustss (clen > 10? "...":""), 18011.28Saugustss dlen, (flags == CBWFLAGS_IN? "in": 18021.28Saugustss (flags == CBWFLAGS_OUT? "out":"<invalid>")))); 18031.28Saugustss} 18041.28Saugustss 18051.28SaugustssStatic void 18061.28Saugustssumass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw) 18071.28Saugustss{ 18081.28Saugustss int sig = UGETDW(csw->dCSWSignature); 18091.96.2.1Sskrll int tag = UGETDW(csw->dCSWTag); 18101.28Saugustss int res = UGETDW(csw->dCSWDataResidue); 18111.28Saugustss int status = csw->bCSWStatus; 18121.28Saugustss 18131.28Saugustss DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, " 18141.28Saugustss "res = %d, status = 0x%02x (%s)\n", USBDEVNAME(sc->sc_dev), 18151.28Saugustss tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"), 18161.28Saugustss tag, res, 18171.28Saugustss status, (status == CSWSTATUS_GOOD? "good": 18181.28Saugustss (status == CSWSTATUS_FAILED? "failed": 18191.28Saugustss (status == CSWSTATUS_PHASE? "phase":"<invalid>"))))); 18201.28Saugustss} 18211.28Saugustss 18221.28SaugustssStatic void 18231.28Saugustssumass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen, 18241.28Saugustss int printlen) 18251.28Saugustss{ 18261.28Saugustss int i, j; 18271.28Saugustss char s1[40]; 18281.28Saugustss char s2[40]; 18291.28Saugustss char s3[5]; 18301.28Saugustss 18311.28Saugustss s1[0] = '\0'; 18321.28Saugustss s3[0] = '\0'; 18331.28Saugustss 18341.96.2.1Sskrll snprintf(s2, sizeof(s2), " buffer=%p, buflen=%d", buffer, buflen); 18351.28Saugustss for (i = 0; i < buflen && i < printlen; i++) { 18361.28Saugustss j = i % 16; 18371.28Saugustss if (j == 0 && i != 0) { 18381.28Saugustss DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n", 18391.28Saugustss USBDEVNAME(sc->sc_dev), s1, s2)); 18401.28Saugustss s2[0] = '\0'; 18411.28Saugustss } 18421.96.2.1Sskrll snprintf(&s1[j * 2], sizeof(s1) - j * 2, "%02x", 18431.96.2.1Sskrll buffer[i] & 0xff); 18441.28Saugustss } 18451.28Saugustss if (buflen > printlen) 18461.96.2.1Sskrll snprintf(s3, sizeof(s3), " ..."); 18471.28Saugustss DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n", 18481.28Saugustss USBDEVNAME(sc->sc_dev), s1, s2, s3)); 18491.28Saugustss} 18501.28Saugustss#endif 1851