Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Jul 2006 11:01:45 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 101747 for review
Message-ID:  <200607171101.k6HB1jVN074126@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=101747

Change 101747 by hselasky@hselasky_mini_itx on 2006/07/17 11:00:53

	Finished converting "ata-usb.c". Please test.

Affected files ...

.. //depot/projects/usb/src/sys/dev/ata/ata-usb.c#2 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/ata/ata-usb.c#2 (text) ====

@@ -24,34 +24,30 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_ata.h"
+
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ata/ata-usb.c,v 1.4 2006/03/31 08:09:05 sos Exp $");
-
-#include "opt_ata.h"
 #include <sys/param.h>
-#include <sys/conf.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/mutex.h>
+#include <sys/malloc.h>
 #include <sys/ata.h>
-#include <sys/bus.h>
-#include <sys/endian.h>
-#include <sys/sysctl.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
+#include <sys/bio.h>
 #include <sys/sema.h>
-#include <sys/taskqueue.h>
 #include <vm/uma.h>
-#include <machine/resource.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
+
+#include <dev/usb/usb_port.h>
 #include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_subr.h>
+#include <dev/usb/usb_quirks.h>
+
 #include <dev/ata/ata-all.h>
 #include <ata_if.h>
 
+__FBSDID("$FreeBSD: src/sys/dev/ata/ata-usb.c,v 1.4 2006/03/31 08:09:05 sos Exp $");
+
+#define ATAUSB_BULK_SIZE (1<<17) /* don't set this lower than (1 << 16) */
+
 /* Command Block Wrapper */
 struct bbb_cbw {
     u_int8_t	signature[4];
@@ -68,7 +64,7 @@
 #define		CBWCDBLENGTH     	16
 
     u_int8_t	cdb[CBWCDBLENGTH];
-};
+} UPACKED;
 
 /* Command Status Wrapper */
 struct bbb_csw {
@@ -81,89 +77,238 @@
 #define 	CSWSTATUS_GOOD   	0x0
 #define		CSWSTATUS_FAILED 	0x1
 #define		CSWSTATUS_PHASE  	0x2
-};
+} UPACKED;
 
 /* USB-ATA 'controller' softc */
 struct atausb_softc {
-    USBBASEDEVICE	dev;		/* base device */
-    usbd_interface_handle iface;	/* interface */
-    int			ifaceno;	/* interface number */
-    u_int8_t		bulkin;		/* endpoint address's */
-    u_int8_t		bulkout;	
-    u_int8_t		bulkirq;	
-    usbd_pipe_handle	bulkin_pipe;	/* pipe handle's */
-    usbd_pipe_handle	bulkout_pipe;
-    usbd_pipe_handle	bulkirq_pipe;
-    int			maxlun;
-    int			timeout;
-    struct ata_request	*ata_request;
-    usb_device_request_t usb_request;
     struct bbb_cbw	cbw;
     struct bbb_csw	csw;
+    struct mtx		locked_mtx;
+    struct usbd_memory_wait mem_wait;
+    struct __callout	watchdog; 
+
+    struct ata_channel *locked_ch;
+    struct ata_channel *restart_ch;
+    struct ata_request *ata_request;
+
+#define ATAUSB_T_BBB_RESET1        0
+#define ATAUSB_T_BBB_RESET2        1
+#define ATAUSB_T_BBB_RESET3        2
+#define ATAUSB_T_BBB_COMMAND       3
+#define ATAUSB_T_BBB_DATA_READ     4
+#define ATAUSB_T_BBB_DATA_WRITE    5
+#define ATAUSB_T_BBB_STATUS        6
+#define ATAUSB_T_BBB_INTERRUPT     7
+#define ATAUSB_T_BBB_I_CLEAR_STALL 8
+#define ATAUSB_T_MAX               9
+    struct usbd_xfer *  xfer[ATAUSB_T_MAX];
+    caddr_t		ata_data;
+    device_t		dev;
 
-#define ATAUSB_T_BBB_CBW		0
-#define ATAUSB_T_BBB_DATA		1
-#define ATAUSB_T_BBB_DCLEAR		2
-#define ATAUSB_T_BBB_CSW1		3
-#define ATAUSB_T_BBB_CSW2		4
-#define ATAUSB_T_BBB_SCLEAR		5
-#define ATAUSB_T_BBB_RESET1		6
-#define ATAUSB_T_BBB_RESET2		7
-#define ATAUSB_T_BBB_RESET3		8
-#define ATAUSB_T_MAX			9
-    usbd_xfer_handle	transfer[ATAUSB_T_MAX];
+    u_int32_t		timeout;
+    u_int32_t		ata_donecount;
+    u_int32_t		ata_bytecount;
 
-    int			state;
-#define	ATAUSB_S_ATTACH			0
-#define	ATAUSB_S_IDLE			1
-#define	ATAUSB_S_BBB_COMMAND		2
-#define	ATAUSB_S_BBB_DATA		3
-#define	ATAUSB_S_BBB_DCLEAR		4
-#define	ATAUSB_S_BBB_STATUS1		5
-#define	ATAUSB_S_BBB_SCLEAR		6
-#define	ATAUSB_S_BBB_STATUS2		7
-#define	ATAUSB_S_BBB_RESET1		8
-#define	ATAUSB_S_BBB_RESET2		9
-#define	ATAUSB_S_BBB_RESET3		10
-#define	ATAUSB_S_DETACH			11
+    u_int8_t		last_xfer_no;
+    u_int8_t		reset_count;
+    u_int8_t		usb_speed;
+    u_int8_t		intr_stall_cleared;
+    u_int8_t		maxlun;
+    u_int8_t		iface_no;
 
-    struct mtx		locked_mtx;
-    struct ata_channel	*locked_ch;
-    struct ata_channel	*restart_ch;
 };
 
-static int atausbdebug = 0;
+static const int atausbdebug = 0;
+
+/* prototypes */
+
+static device_probe_t atausb_probe;
+static device_attach_t atausb_attach;
+static device_detach_t atausb_detach;
+
+static void
+atausb_watchdog(void *arg);
+
+static void
+atausb_transfer_start(struct atausb_softc *sc, u_int8_t xfer_no);
+
+static void
+atausb_t_bbb_reset1_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_reset2_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_reset3_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_command_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_data_read_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_data_write_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_status_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_interrupt_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_t_bbb_i_clear_stall_callback(struct usbd_xfer *xfer);
+
+static void
+atausb_tr_error(struct usbd_xfer *xfer);
+
+static int
+ata_usbchannel_begin_transaction(struct ata_request *request);
+
+static int
+ata_usbchannel_end_transaction(struct ata_request *request);
 
-/* prototypes*/
-static usbd_status atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe, void *buffer, int buflen, int flags, usbd_xfer_handle xfer);
-static usbd_status atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer);
-static void atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer);
-static void atausb_bbb_reset(struct atausb_softc *sc);
-static int atausb_bbb_start(struct ata_request *request);
-static void atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err);
-int ata_usbchannel_begin_transaction(struct ata_request *request);
-int ata_usbchannel_end_transaction(struct ata_request *request);
+static device_probe_t ata_usbchannel_probe;
+static device_attach_t ata_usbchannel_attach;
+static device_detach_t ata_usbchannel_detach;
 
+static ata_setmode_t ata_usbchannel_setmode;
+static ata_locking_t ata_usbchannel_locking;
 
 /*
  * USB frontend part
  */
-USB_DECLARE_DRIVER(atausb);
+
+struct usbd_config atausb_config[ATAUSB_T_MAX] = {
+
+    [ATAUSB_T_BBB_RESET1] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &atausb_t_bbb_reset1_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [ATAUSB_T_BBB_RESET2] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &atausb_t_bbb_reset2_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [ATAUSB_T_BBB_RESET3] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &atausb_t_bbb_reset3_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [ATAUSB_T_BBB_COMMAND] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = sizeof(struct bbb_cbw),
+      .flags     = USBD_USE_DMA,
+      .callback  = &atausb_t_bbb_command_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [ATAUSB_T_BBB_DATA_READ] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = ATAUSB_BULK_SIZE,
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .callback  = &atausb_t_bbb_data_read_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [ATAUSB_T_BBB_DATA_WRITE] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = ATAUSB_BULK_SIZE,
+      .flags     = USBD_USE_DMA,
+      .callback  = &atausb_t_bbb_data_write_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [ATAUSB_T_BBB_STATUS] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = sizeof(struct bbb_csw),
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .callback  = &atausb_t_bbb_status_callback,
+      .timeout   = 5000, /* ms */
+    },
+
+    /*
+     * the following endpoints are only
+     * present on CBI devices:
+     */
+
+    [ATAUSB_T_BBB_INTERRUPT] = {
+      .type      = UE_INTERRUPT,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .bufsize   = 0, /* use wMaxPacketSize */
+      .callback  = &atausb_t_bbb_interrupt_callback,
+    },
+
+    [ATAUSB_T_BBB_I_CLEAR_STALL] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .flags     = USBD_USE_DMA,
+      .bufsize   = sizeof(usb_device_request_t),
+      .callback  = &atausb_t_bbb_i_clear_stall_callback,
+      .timeout   = 5000, /* ms */
+    },
+};
+
+static devclass_t atausb_devclass;
+
+static device_method_t atausb_methods[] = {
+    DEVMETHOD(device_probe, atausb_probe),
+    DEVMETHOD(device_attach, atausb_attach),
+    DEVMETHOD(device_detach, atausb_detach),
+    { 0, 0 }
+};
+
+static driver_t atausb_driver = {
+    .name    = "atausb",
+    .methods = atausb_methods,
+    .size    = sizeof(struct atausb_softc),
+};
+
 DRIVER_MODULE(atausb, uhub, atausb_driver, atausb_devclass, 0, 0);
+MODULE_DEPEND(atausb, usb, 1, 1, 1);
 MODULE_VERSION(atausb, 1);
 
 static int
-atausb_match(device_t dev)
+atausb_probe(device_t dev)
 {
     struct usb_attach_arg *uaa = device_get_ivars(dev);
     usb_interface_descriptor_t *id;
 
-    if (uaa->iface == NULL)
+    if (uaa->iface == NULL) {
 	return UMATCH_NONE;
+    }
 
     id = usbd_get_interface_descriptor(uaa->iface);
-    if (!id || id->bInterfaceClass != UICLASS_MASS)
+    if ((!id) || (id->bInterfaceClass != UICLASS_MASS)) {
 	return UMATCH_NONE;
+    }
 
     switch (id->bInterfaceSubClass) {
     case UISUBCLASS_QIC157:
@@ -193,27 +338,26 @@
     struct atausb_softc *sc = device_get_softc(dev);
     struct usb_attach_arg *uaa = device_get_ivars(dev);
     usb_interface_descriptor_t *id;
-    usb_endpoint_descriptor_t *ed;
-    usbd_device_handle udev;
+    const char *proto, *subclass;
     usb_device_request_t request;
-    char devinfo[1024], *proto, *subclass;
+    u_int16_t i;
     u_int8_t maxlun;
-    int err, i;
+    u_int8_t has_intr;
+    int err;
+
+    usbd_set_desc(dev, uaa->device);
 
     sc->dev = dev;
-    usbd_devinfo(uaa->device, 0, devinfo);
-    device_set_desc_copy(dev, devinfo);
-    sc->bulkin = sc->bulkout = sc->bulkirq = -1;
-    sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL;
-    sc->iface = uaa->iface;
-    sc->ifaceno = uaa->ifaceno;
     sc->maxlun = 0;
-    sc->timeout = 5000;
     sc->locked_ch = NULL;
     sc->restart_ch = NULL;
-    mtx_init(&sc->locked_mtx, "ATAUSB lock", NULL, MTX_DEF); 
+    sc->usb_speed = usbd_get_speed(uaa->device);
+    mtx_init(&(sc->locked_mtx), "ATAUSB lock", NULL, MTX_DEF); 
+
+    __callout_init_mtx(&(sc->watchdog),
+		       &(sc->locked_mtx), CALLOUT_RETURNUNLOCKED);
 
-    id = usbd_get_interface_descriptor(sc->iface);
+    id = usbd_get_interface_descriptor(uaa->iface);
     switch (id->bInterfaceProtocol) {
     case UIPROTO_MASS_BBB:
     case UIPROTO_MASS_BBB_OLD:
@@ -228,6 +372,7 @@
     default:
 	    proto = "Unknown";
     }
+
     switch (id->bInterfaceSubClass) {
     case UISUBCLASS_RBC:
 	    subclass = "RBC";
@@ -246,93 +391,44 @@
     default:
 	    subclass = "Unknown";
     }
+
+    has_intr = (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I);
+    sc->iface_no = id->bInterfaceNumber;
+
     device_printf(dev, "using %s over %s\n", subclass, proto);
     if (strcmp(proto, "Bulk-Only") ||
-	(strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI")))
-	return ENXIO;
-
-    for (i = 0 ; i < id->bNumEndpoints ; i++) {
-	if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) {
-	    device_printf(sc->dev, "could not read endpoint descriptor\n");
-	    return ENXIO;
-	}
-	if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-	    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
-	    sc->bulkin = ed->bEndpointAddress;
-	}
-	if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
-	           (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
-	    sc->bulkout = ed->bEndpointAddress;
-	}
-	if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I &&
-	           UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-	           (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
-	    sc->bulkirq = ed->bEndpointAddress;
-	}
-    }
-
-    /* check whether we found at least the endpoints we need */
-    if (!sc->bulkin || !sc->bulkout) {
-	device_printf(sc->dev, "needed endpoints not found (%d,%d)\n",
-		      sc->bulkin, sc->bulkout);
-	atausb_detach(dev);
+	(strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) {
 	return ENXIO;
     }
 
-    /* open the pipes */
-    if (usbd_open_pipe(sc->iface, sc->bulkout,
-		       USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) {
-	device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout);
-	atausb_detach(dev);
-	return ENXIO;
-    }
-    if (usbd_open_pipe(sc->iface, sc->bulkin,
-		       USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) {
-	device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin);
-	atausb_detach(dev);
-	return ENXIO;
-    }
-    if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) {
-	if (usbd_open_pipe(sc->iface, sc->bulkirq,
-			   USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) {
-	    device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n",
-	    		  sc->bulkirq);
-	    atausb_detach(dev);
-	    return ENXIO;
-	}
+    err = usbd_transfer_setup(uaa->device, uaa->iface_index, sc->xfer, 
+			      atausb_config, 
+			      has_intr ? ATAUSB_T_MAX : (ATAUSB_T_MAX-2), sc, 
+			      &(sc->locked_mtx), &(sc->mem_wait));
+    if (err) {
+        device_printf(sc->dev, "could not setup required "
+		      "transfers, %s\n", usbd_errstr(err));
+	goto detach;
     }
-    sc->state = ATAUSB_S_ATTACH;
 
-    /* alloc needed number of transfer handles */
-    for (i = 0; i < ATAUSB_T_MAX; i++) {
-	sc->transfer[i] = usbd_alloc_xfer(uaa->device);
-	if (!sc->transfer[i]) {
-	    device_printf(sc->dev, "out of memory\n");
-	    atausb_detach(dev);
-	    return ENXIO;
-	}
-    }
-
-    /* driver is ready to process requests here */
-    sc->state = ATAUSB_S_IDLE;
-
     /* get number of devices so we can add matching channels */
-    usbd_interface2device_handle(sc->iface, &udev);
     request.bmRequestType = UT_READ_CLASS_INTERFACE;
-    request.bRequest = 0xfe; //GET_MAX_LUN;
+    request.bRequest = 0xfe; /* GET_MAX_LUN; */
     USETW(request.wValue, 0);
-    USETW(request.wIndex, sc->ifaceno);
+    USETW(request.wIndex, sc->iface_no);
     USETW(request.wLength, sizeof(maxlun));
-    switch ((err = usbd_do_request(udev, &request, &maxlun))) {
-    case USBD_NORMAL_COMPLETION:
-	if (bootverbose)
-	    device_printf(sc->dev, "maxlun=%d\n", maxlun);
+    err = usbd_do_request(uaa->device, &request, &maxlun);
+
+    if (err) {
+        if (bootverbose) {
+	    device_printf(sc->dev, "get maxlun not supported %s\n",
+			  usbd_errstr(err));
+	}
+    } else {
 	sc->maxlun = maxlun;
-	break;
-    default:
-	if (bootverbose)
-	    device_printf(sc->dev, "get maxlun not supported %s\n",
-	usbd_errstr(err));
+	if (bootverbose) {
+	    device_printf(sc->dev, "maxlun=%d\n", sc->maxlun);
+	}
     }
 
     /* ata channels are children to this USB control device */
@@ -340,403 +436,469 @@
 	if (!device_add_child(sc->dev, "ata",
 			      devclass_find_free_unit(ata_devclass, 2))) {
 	    device_printf(sc->dev, "failed to attach ata child device\n");
-	    atausb_detach(dev);
-	    return ENXIO;
+	    goto detach;
 	}
     }
     bus_generic_attach(sc->dev);
+
+    /* start the watchdog */
+
+    mtx_lock(&(sc->locked_mtx));
+
+    atausb_watchdog(sc);
+
     return 0;
+
+ detach:
+    atausb_detach(dev);
+    return ENXIO;
 }
 
 static int
-atausb_detach(device_ptr_t dev)
+atausb_detach(device_t dev)
 {
     struct atausb_softc *sc = device_get_softc(dev);
-    usbd_device_handle udev;
     device_t *children;
     int nchildren, i;
 
+    mtx_lock(&(sc->locked_mtx));
+
+    /* stop watchdog */
+    __callout_stop(&(sc->watchdog));
+
     /* signal that device is going away */
-    sc->state = ATAUSB_S_DETACH;
+    sc->last_xfer_no = ATAUSB_T_MAX;
+
+    /* stop all transfers, if any */
+    for (i = 0; i < ATAUSB_T_MAX; i++) {
+        if (sc->xfer[i]) {
+	    usbd_transfer_stop(sc->xfer[i]);
+	}
+    }
+
+    mtx_unlock(&(sc->locked_mtx));
 
-    /* abort all the pipes in case there are active transfers */
-    usbd_interface2device_handle(sc->iface, &udev);
-    usbd_abort_default_pipe(udev);
-    if (sc->bulkout_pipe)
-        usbd_abort_pipe(sc->bulkout_pipe);
-    if (sc->bulkin_pipe)
-        usbd_abort_pipe(sc->bulkin_pipe);
-    if (sc->bulkirq_pipe)
-        usbd_abort_pipe(sc->bulkirq_pipe);
+    /* detach & delete all children, if any */
 
-    /* detach & delete all children */
     if (!device_get_children(dev, &children, &nchildren)) {
-        for (i = 0; i < nchildren; i++)
+        for (i = 0; i < nchildren; i++) {
             device_delete_child(dev, children[i]);
+	}
         free(children, M_TEMP);
     }
 
-    /* free the transfers */
-    for (i = 0; i < ATAUSB_T_MAX; i++)
-	if (sc->transfer[i])
-	    usbd_free_xfer(sc->transfer[i]);
+    usbd_transfer_unsetup(sc->xfer, ATAUSB_T_MAX);
 
-    /* remove all the pipes */
-    if (sc->bulkout_pipe)
-        usbd_close_pipe(sc->bulkout_pipe);
-    if (sc->bulkin_pipe)
-        usbd_close_pipe(sc->bulkin_pipe);
-    if (sc->bulkirq_pipe)
-        usbd_close_pipe(sc->bulkirq_pipe);
+    usbd_transfer_drain(&(sc->mem_wait), &(sc->locked_mtx));
 
     mtx_destroy(&sc->locked_mtx);
     return 0;
 }
 
-
-/*
- * Generic USB transfer routines 
- */
-static usbd_status
-atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe,
-	     void *buffer, int buflen, int flags, usbd_xfer_handle xfer)
+static void
+atausb_watchdog(void *arg)
 {
-    usbd_status err;
+    struct atausb_softc *sc = arg;
 
-    if (sc->state == ATAUSB_S_DETACH)
-	return USBD_NOT_STARTED;
+    mtx_assert(&(sc->locked_mtx), MA_OWNED);
 
-    usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen, flags,
-		    sc->timeout, atausb_bbb_finish);
-    err = usbd_transfer(xfer);
-    if (err && (err != USBD_IN_PROGRESS)) {
-	if (atausbdebug)
-	    device_printf(sc->dev, "failed to setup transfer, %s\n",
-		          usbd_errstr(err));
-	return err;
+    if (sc->xfer[ATAUSB_T_BBB_INTERRUPT]) {
+        /* start the interrupt pipe, in case it stopped */
+        usbd_transfer_start(sc->xfer[ATAUSB_T_BBB_INTERRUPT]);
     }
-    return USBD_NORMAL_COMPLETION;
+
+    __callout_reset(&(sc->watchdog), 
+		    hz, &atausb_watchdog, sc);
+
+    mtx_unlock(&(sc->locked_mtx));
+    return;
+}
+
+static void
+atausb_transfer_start(struct atausb_softc *sc, u_int8_t xfer_no)
+{
+#if 0
+    device_printf(sc->dev, "BBB transfer %d\n", xfer_no);
+#endif
+    sc->last_xfer_no = xfer_no;
+    usbd_transfer_start(sc->xfer[xfer_no]);
+    return;
 }
 
-static usbd_status
-atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev,
-	 	 usb_device_request_t *req, void *buffer, int buflen, int flags,
- 		 usbd_xfer_handle xfer)
+static void
+atausb_t_bbb_reset1_callback(struct usbd_xfer *xfer)
 {
-    usbd_status err;
+    struct atausb_softc *sc = xfer->priv_sc;
+    usb_device_request_t req;
+
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
 
-    if (sc->state == ATAUSB_S_DETACH)
-	return USBD_NOT_STARTED;
+ tr_transferred:
+    atausb_transfer_start(sc, ATAUSB_T_BBB_RESET2);
+    return;
 
-    usbd_setup_default_xfer(xfer, udev, (void *)sc, sc->timeout, req,
-   			    buffer, buflen, flags, atausb_bbb_finish);
-    err = usbd_transfer(xfer);
-    if (err && (err != USBD_IN_PROGRESS)) {
-	if (atausbdebug)
-	    device_printf(sc->dev, "failed to setup ctl transfer, %s\n",
-	                  usbd_errstr(err));
-	return err;
+ tr_setup:
+    if (sc->reset_count >= 16) {
+        device_printf(sc->dev, "timeout: giving up reset!\n");
+	return;
     }
-    return USBD_NORMAL_COMPLETION;
+
+    sc->reset_count ++;
+
+    req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+    req.bRequest = 0xff; /* bulk-only reset */
+    USETW(req.wValue, 0);
+    USETW(req.wIndex, sc->iface_no);
+    USETW(req.wLength, 0);
+
+    usbd_copy_in(&(xfer->buf_data), 0, &req, sizeof(req));
+
+    usbd_start_hardware(xfer);
+    return;
 }
 
 static void
-atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt,
-		   usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer)
+atausb_t_bbb_reset2_callback(struct usbd_xfer *xfer)
 {
-    usbd_device_handle udev;
+    struct atausb_softc *sc = xfer->priv_sc;
+
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
+
+ tr_transferred:
+    atausb_transfer_start(sc, ATAUSB_T_BBB_RESET3);
+    return;
 
-    if (atausbdebug)
-	device_printf(sc->dev, "clear endpoint 0x%02x stall\n", endpt);
-    usbd_interface2device_handle(sc->iface, &udev);
-    sc->state = state;
-    usbd_clear_endpoint_toggle(pipe);
-    sc->usb_request.bmRequestType = UT_WRITE_ENDPOINT;
-    sc->usb_request.bRequest = UR_CLEAR_FEATURE;
-    USETW(sc->usb_request.wValue, UF_ENDPOINT_HALT);
-    USETW(sc->usb_request.wIndex, endpt);
-    USETW(sc->usb_request.wLength, 0);
-    atausb_ctl_start(sc, udev, &sc->usb_request, NULL, 0, 0, xfer);
+ tr_setup:
+    usbd_clear_stall_tr_setup(xfer, sc->xfer[ATAUSB_T_BBB_DATA_READ]);
+    usbd_clear_stall_tr_transferred(xfer, sc->xfer[ATAUSB_T_BBB_DATA_READ]);
+    return;
 }
 
+static void
+atausb_t_bbb_reset3_callback(struct usbd_xfer *xfer)
+{
+    struct atausb_softc *sc = xfer->priv_sc;
+
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
+
+ tr_transferred:
+    atausb_transfer_start(sc, ATAUSB_T_BBB_COMMAND);
+    return;
 
-/*
- * Bulk-Only transport part
- */
+ tr_setup:
+    usbd_clear_stall_tr_setup(xfer, sc->xfer[ATAUSB_T_BBB_DATA_WRITE]);
+    usbd_clear_stall_tr_transferred(xfer, sc->xfer[ATAUSB_T_BBB_DATA_WRITE]);
+    return;
+}
+
 static void
-atausb_bbb_reset(struct atausb_softc *sc)
+atausb_t_bbb_command_callback(struct usbd_xfer *xfer)
 {
-    usbd_device_handle udev;
+    struct atausb_softc *sc = xfer->priv_sc;
+    struct ata_request *request = sc->ata_request;
+    struct ata_channel *ch;
+
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
+
+ tr_transferred:
+    atausb_transfer_start
+      (sc, ((request->flags & ATA_R_READ) ? ATAUSB_T_BBB_DATA_READ :
+	    (request->flags & ATA_R_WRITE) ? ATAUSB_T_BBB_DATA_WRITE :
+	    ATAUSB_T_BBB_STATUS));
+    return;
+
+ tr_setup:
+
+    sc->reset_count = 0;
+
+    if (request) {
+        ch = device_get_softc(request->parent);
+
+	sc->timeout = (request->timeout * 1000) + 5000;
+
+	USETDW(sc->cbw.signature, CBWSIGNATURE);
+	USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1);
+	USETDW(sc->cbw.transfer_length, request->bytecount);
+	sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT;
+	sc->cbw.lun = ch->unit;
+	sc->cbw.length = 16;
+	bzero(sc->cbw.cdb, 16);
+	bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */
+
+	usbd_copy_in(&(xfer->buf_data), 0, &(sc->cbw), sizeof(sc->cbw));
 
-    if (atausbdebug)
-	device_printf(sc->dev, "Bulk Reset\n");
-    sc->timeout = 5000;
-    sc->state = ATAUSB_S_BBB_RESET1;
-    usbd_interface2device_handle(sc->iface, &udev);
-    sc->usb_request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
-    sc->usb_request.bRequest = 0xff; /* bulk-only reset */
-    USETW(sc->usb_request.wValue, 0);
-    USETW(sc->usb_request.wIndex, sc->ifaceno);
-    USETW(sc->usb_request.wLength, 0);
-    atausb_ctl_start(sc, udev, &sc->usb_request, NULL,
-    		     0, 0, sc->transfer[ATAUSB_T_BBB_RESET1]);
+	usbd_start_hardware(xfer);
+    }
+    return;
 }
 
-static int
-atausb_bbb_start(struct ata_request *request)
+static void
+atausb_t_bbb_data_read_callback(struct usbd_xfer *xfer)
 {
-    struct atausb_softc *sc = 
-	device_get_softc(device_get_parent(request->parent));
-    struct ata_channel *ch = device_get_softc(request->parent);
+    struct atausb_softc *sc = xfer->priv_sc; 
+    u_int32_t max_bulk = (ATAUSB_BULK_SIZE - 
+			  (ATAUSB_BULK_SIZE % xfer->max_packet_size));
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
+
+ tr_transferred:
+
+    usbd_copy_out(&(xfer->buf_data), 0, 
+		  sc->ata_data, xfer->actlen);
+
+    sc->ata_bytecount -= xfer->actlen;
+    sc->ata_data += xfer->actlen;
+    sc->ata_donecount += xfer->actlen;
+
+    if (xfer->actlen < xfer->length) {
+        /* short transfer */
+        sc->ata_bytecount = 0;
+    }
+
+ tr_setup:
+    if (sc->ata_bytecount == 0) {
+        atausb_transfer_start(sc, ATAUSB_T_BBB_STATUS);
+	return;
+    }
 
-    sc->timeout = (request->timeout * 1000) + 5000;
-    USETDW(sc->cbw.signature, CBWSIGNATURE);
-    USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1);
-    USETDW(sc->cbw.transfer_length, request->bytecount);
-    sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT;
-    sc->cbw.lun = ch->unit;
-    sc->cbw.length = 16;
-    bzero(sc->cbw.cdb, 16);
-    bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */
-    sc->state = ATAUSB_S_BBB_COMMAND;
-    if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw),
-		     0, sc->transfer[ATAUSB_T_BBB_CBW])) {
-	request->result = EIO;
-        if (atausbdebug)
-	    device_printf(request->dev, "cannot setup USB transfer\n");
-        atausb_bbb_reset(sc);
-	return ATA_OP_FINISHED;
+    if (max_bulk > sc->ata_bytecount) {
+        max_bulk = sc->ata_bytecount;
     }
-    return ATA_OP_CONTINUES;
+
+    xfer->timeout = sc->timeout;
+    xfer->length = max_bulk;
+
+    usbd_start_hardware(xfer);
+    return;
 }
 
 static void
-atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv,
-		 usbd_status err)
+atausb_t_bbb_data_write_callback(struct usbd_xfer *xfer)
 {
-    struct atausb_softc *sc = (struct atausb_softc *)priv;
-    struct ata_request *request = sc->ata_request;
-    usbd_xfer_handle next_xfer;
+    struct atausb_softc *sc = xfer->priv_sc; 
+    u_int32_t max_bulk = (ATAUSB_BULK_SIZE - 
+			  (ATAUSB_BULK_SIZE % xfer->max_packet_size));
+    USBD_CHECK_STATUS(xfer);
+
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
+
+ tr_transferred:
+
+    sc->ata_bytecount -= xfer->actlen;
+    sc->ata_data += xfer->actlen;
+    sc->ata_donecount += xfer->actlen;
 
-    //device_printf(sc->dev, "BBB state %d: %s\n", sc->state, usbd_errstr(err));
+ tr_setup:
 
-    if (sc->state == ATAUSB_S_DETACH) {
-        device_printf(sc->dev, "WARNING - device has been removed\n");
+    if (sc->ata_bytecount == 0) {
+        atausb_transfer_start(sc, ATAUSB_T_BBB_STATUS);
 	return;
     }
 
-    switch (sc->state) {
-    case ATAUSB_S_BBB_COMMAND:	/* command transport phase */
-	if (err) {
-            if (atausbdebug)
-	        device_printf(sc->dev, "failed to send CBW\n");
-	    request->result = EIO;
-	    atausb_bbb_reset(sc);
-	    return;
-	}
+    if (max_bulk > sc->ata_bytecount) {
+        max_bulk = sc->ata_bytecount;
+    }
+
+    xfer->timeout = sc->timeout;
+    xfer->length = max_bulk;
+
+    usbd_copy_in(&(xfer->buf_data), 0, 
+		 sc->ata_data, max_bulk);
+
+    usbd_start_hardware(xfer);
+    return;
+}
+
+static void
+atausb_t_bbb_status_callback(struct usbd_xfer *xfer)
+{
+    struct atausb_softc *sc = xfer->priv_sc; 
+    struct ata_request *request = sc->ata_request;
+    u_int32_t residue;
+
+    USBD_CHECK_STATUS(xfer);
 
-	/* next is data transport phase, setup transfer */
-	sc->state = ATAUSB_S_BBB_DATA;
-	if (request->flags & ATA_R_READ) {
-	    if (atausb_start(sc, sc->bulkin_pipe,
-			     request->data, request->bytecount,
-			     USBD_SHORT_XFER_OK,
-			     sc->transfer[ATAUSB_T_BBB_DATA])) {
-	        request->result = EIO;
-		atausb_bbb_reset(sc);
-	    }
-	    return;
-	}
-	if (request->flags & ATA_R_WRITE) {
-	    if (atausb_start(sc, sc->bulkout_pipe,
-			     request->data, request->bytecount,
-			     0, sc->transfer[ATAUSB_T_BBB_DATA])) {
-	        request->result = EIO;
-		atausb_bbb_reset(sc);
-	    }
-	    return;
-	}
-	/* FALLTHROUGH */
+ tr_error:
+    atausb_tr_error(xfer);
+    return;
 
-    case ATAUSB_S_BBB_DATA:	/* data transport phase */
-	if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
-	    usbd_get_xfer_status(xfer, NULL, NULL, &request->donecount, NULL);

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607171101.k6HB1jVN074126>