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