Author: thompsa
Date: Mon Feb 23 21:07:20 2009
New Revision: 188955
URL: http://svn.freebsd.org/changeset/base/188955

Log:
  Move two missed usb drivers out to the graveyard location under 
sys/legacy/dev.

Added:
  head/sys/legacy/dev/ata/
  head/sys/legacy/dev/ata/ata-usb.c   (props changed)
     - copied unchanged from r188941, head/sys/dev/ata/ata-usb.c
  head/sys/legacy/dev/sound/
  head/sys/legacy/dev/sound/usb/
  head/sys/legacy/dev/sound/usb/uaudio.c   (props changed)
     - copied unchanged from r188941, head/sys/dev/sound/usb/uaudio.c
  head/sys/legacy/dev/sound/usb/uaudio.h   (props changed)
     - copied unchanged from r188941, head/sys/dev/sound/usb/uaudio.h
  head/sys/legacy/dev/sound/usb/uaudio_pcm.c   (props changed)
     - copied unchanged from r188941, head/sys/dev/sound/usb/uaudio_pcm.c
  head/sys/legacy/dev/sound/usb/uaudioreg.h   (props changed)
     - copied unchanged from r188941, head/sys/dev/sound/usb/uaudioreg.h
Deleted:
  head/sys/dev/ata/ata-usb.c
  head/sys/dev/sound/usb/uaudio.c
  head/sys/dev/sound/usb/uaudio.h
  head/sys/dev/sound/usb/uaudio_pcm.c
  head/sys/dev/sound/usb/uaudioreg.h
Modified:
  head/sys/conf/files

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Mon Feb 23 20:56:27 2009        (r188954)
+++ head/sys/conf/files Mon Feb 23 21:07:20 2009        (r188955)
@@ -502,7 +502,7 @@ dev/ata/chipsets/ata-sis.c  optional ata 
 dev/ata/chipsets/ata-via.c     optional ata pci | atavia
 dev/ata/ata-disk.c             optional atadisk
 dev/ata/ata-raid.c             optional ataraid
-dev/ata/ata-usb.c              optional atausb ousb
+legacy/dev/ata/ata-usb.c       optional atausb ousb
 dev/ata/atapi-cd.c             optional atapicd
 dev/ata/atapi-fd.c             optional atapifd
 dev/ata/atapi-tape.c           optional atapist
@@ -1394,8 +1394,8 @@ dev/sound/pcm/sndstat.c           optional sound
 dev/sound/pcm/sound.c          optional sound
 dev/sound/pcm/vchan.c          optional sound
 #dev/sound/usb/upcm.c          optional snd_upcm ousb
-dev/sound/usb/uaudio.c         optional snd_uaudio ousb
-dev/sound/usb/uaudio_pcm.c     optional snd_uaudio ousb
+legacy/dev/sound/usb/uaudio.c          optional snd_uaudio ousb
+legacy/dev/sound/usb/uaudio_pcm.c      optional snd_uaudio ousb
 dev/sound/midi/midi.c          optional sound
 dev/sound/midi/mpu401.c                optional sound
 dev/sound/midi/mpu_if.m                optional sound

Copied: head/sys/legacy/dev/ata/ata-usb.c (from r188941, 
head/sys/dev/ata/ata-usb.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/legacy/dev/ata/ata-usb.c   Mon Feb 23 21:07:20 2009        
(r188955, copy of r188941, head/sys/dev/ata/ata-usb.c)
@@ -0,0 +1,970 @@
+/*-
+ * Copyright (c) 2006 - 2008 S�ren Schmidt <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#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/ata.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/module.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/ata/ata-all.h>
+#include <ata_if.h>
+
+/* Command Block Wrapper */
+struct bbb_cbw {
+    u_int8_t   signature[4];
+#define                CBWSIGNATURE            0x43425355
+
+    u_int8_t   tag[4];
+    u_int8_t   transfer_length[4];
+    u_int8_t   flags;
+#define                CBWFLAGS_OUT            0x00
+#define                CBWFLAGS_IN             0x80
+
+    u_int8_t   lun;
+    u_int8_t   length;
+#define                CBWCDBLENGTH            16
+
+    u_int8_t   cdb[CBWCDBLENGTH];
+};
+
+/* Command Status Wrapper */
+struct bbb_csw {
+    u_int8_t   signature[4];
+#define                CSWSIGNATURE            0x53425355
+
+    u_int8_t   tag[4];
+    u_int8_t   residue[4];
+    u_int8_t    status;
+#define        CSWSTATUS_GOOD          0x0
+#define                CSWSTATUS_FAILED        0x1
+#define                CSWSTATUS_PHASE         0x2
+};
+
+/* USB-ATA 'controller' softc */
+struct atausb_softc {
+    device_t           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;
+
+#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];
+
+    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
+
+    struct mtx         locked_mtx;
+    struct ata_channel *locked_ch;
+    struct ata_channel *restart_ch;
+};
+
+static int atausbdebug = 0;
+
+/* 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);
+
+
+/*
+ * USB frontend part
+ */
+USB_DECLARE_DRIVER(atausb);
+DRIVER_MODULE(atausb, uhub, atausb_driver, atausb_devclass, 0, 0);
+MODULE_VERSION(atausb, 1);
+
+static int
+atausb_match(device_t dev)
+{
+    struct usb_attach_arg *uaa = device_get_ivars(dev);
+    usb_interface_descriptor_t *id;
+
+    if (uaa->iface == NULL)
+       return UMATCH_NONE;
+
+    id = usbd_get_interface_descriptor(uaa->iface);
+    if (!id || id->bInterfaceClass != UICLASS_MASS)
+       return UMATCH_NONE;
+
+    switch (id->bInterfaceSubClass) {
+    case UISUBCLASS_QIC157:
+    case UISUBCLASS_RBC:
+    case UISUBCLASS_SCSI:
+    case UISUBCLASS_SFF8020I:
+    case UISUBCLASS_SFF8070I:
+    case UISUBCLASS_UFI:
+       switch (id->bInterfaceProtocol) {
+       case UIPROTO_MASS_CBI:
+       case UIPROTO_MASS_CBI_I:
+       case UIPROTO_MASS_BBB:
+       case UIPROTO_MASS_BBB_OLD:
+           return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
+       default:
+           return UMATCH_IFACECLASS_IFACESUBCLASS;
+       }
+       break;
+    default:
+       return UMATCH_IFACECLASS;
+    }
+}
+
+static int
+atausb_attach(device_t dev)
+{
+    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;
+    usb_device_request_t request;
+    device_t child;
+    char devinfo[1024], *proto, *subclass;
+    u_int8_t maxlun;
+    int err, i;
+
+    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); 
+
+    id = usbd_get_interface_descriptor(sc->iface);
+    switch (id->bInterfaceProtocol) {
+    case UIPROTO_MASS_BBB:
+    case UIPROTO_MASS_BBB_OLD:
+           proto = "Bulk-Only";
+           break;
+    case UIPROTO_MASS_CBI:
+           proto = "CBI";
+           break;
+    case UIPROTO_MASS_CBI_I:
+           proto = "CBI with CCI";
+           break;
+    default:
+           proto = "Unknown";
+    }
+    switch (id->bInterfaceSubClass) {
+    case UISUBCLASS_RBC:
+           subclass = "RBC";
+           break;
+    case UISUBCLASS_QIC157:
+    case UISUBCLASS_SFF8020I:
+    case UISUBCLASS_SFF8070I:
+           subclass = "ATAPI";
+           break;
+    case UISUBCLASS_SCSI:
+           subclass = "SCSI";
+           break;
+    case UISUBCLASS_UFI:
+           subclass = "UFI";
+           break;
+    default:
+           subclass = "Unknown";
+    }
+    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);
+       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;
+       }
+    }
+    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;
+    USETW(request.wValue, 0);
+    USETW(request.wIndex, sc->ifaceno);
+    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);
+       sc->maxlun = maxlun;
+       break;
+    default:
+       if (bootverbose)
+           device_printf(sc->dev, "get maxlun not supported %s\n",
+       usbd_errstr(err));
+    }
+
+    /* ata channels are children to this USB control device */
+    for (i = 0; i <= sc->maxlun; i++) {
+       if ((child = device_add_child(sc->dev, "ata",
+               devclass_find_free_unit(ata_devclass, 2))) == NULL) {
+           device_printf(sc->dev, "failed to add ata child device\n");
+       } else
+           device_set_ivars(child, (void *)(intptr_t)i);
+    }
+    bus_generic_attach(sc->dev);
+    return 0;
+}
+
+static int
+atausb_detach(device_t dev)
+{
+    struct atausb_softc *sc = device_get_softc(dev);
+    usbd_device_handle udev;
+    device_t *children;
+    int nchildren, i;
+
+    /* signal that device is going away */
+    sc->state = ATAUSB_S_DETACH;
+
+    /* 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 (!device_get_children(dev, &children, &nchildren)) {
+        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]);
+
+    /* 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);
+
+    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)
+{
+    usbd_status err;
+
+    if (sc->state == ATAUSB_S_DETACH)
+       return USBD_NOT_STARTED;
+
+    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;
+    }
+    return USBD_NORMAL_COMPLETION;
+}
+
+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)
+{
+    usbd_status err;
+
+    if (sc->state == ATAUSB_S_DETACH)
+       return USBD_NOT_STARTED;
+
+    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;
+    }
+    return USBD_NORMAL_COMPLETION;
+}
+
+static void
+atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt,
+                  usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer)
+{
+    usbd_device_handle udev;
+
+    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);
+}
+
+
+/*
+ * Bulk-Only transport part
+ */
+static void
+atausb_bbb_reset(struct atausb_softc *sc)
+{
+    usbd_device_handle udev;
+
+    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]);
+}
+
+static int
+atausb_bbb_start(struct ata_request *request)
+{
+    struct atausb_softc *sc = 
+       device_get_softc(device_get_parent(request->parent));
+    struct ata_channel *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 */
+    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;
+    }
+    return ATA_OP_CONTINUES;
+}
+
+static void
+atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv,
+                usbd_status err)
+{
+    struct atausb_softc *sc = (struct atausb_softc *)priv;
+    struct ata_request *request = sc->ata_request;
+    usbd_xfer_handle next_xfer;
+
+    //device_printf(sc->dev, "BBB state %d: %s\n", sc->state, 
usbd_errstr(err));
+
+    if (sc->state == ATAUSB_S_DETACH) {
+        device_printf(sc->dev, "WARNING - device has been removed\n");
+       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;
+       }
+
+       /* 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 */
+
+    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);
+           if (err) {
+                if (atausbdebug)
+                   device_printf(sc->dev, "data %s count %d failed: %s\n",
+                                 (request->flags & ATA_R_READ?"read":"write"),
+                                 request->bytecount, usbd_errstr(err));
+               if (err == USBD_STALLED) {
+                   atausb_clear_stall(sc,
+                                      (request->flags & ATA_R_READ ?
+                                       sc->bulkin : sc->bulkout),
+                                      (request->flags & ATA_R_READ ?
+                                       sc->bulkin_pipe : sc->bulkout_pipe),
+                                      ATAUSB_S_BBB_DCLEAR,
+                                      sc->transfer[ATAUSB_T_BBB_DCLEAR]);
+               }
+               else {
+                   request->result = EIO;
+                   atausb_bbb_reset(sc);
+               }
+               return;
+           }
+       }
+       /* FALLTHROUGH */
+
+    case ATAUSB_S_BBB_DCLEAR:  /* stall clear after data phase */
+    case ATAUSB_S_BBB_SCLEAR:  /* stall clear after status phase */
+       if (err) {
+            if (atausbdebug)
+               device_printf(sc->dev, "bulk%s stall clear failed %s\n",
+                             (request->flags & ATA_R_READ ? "in" : "out"),
+                             usbd_errstr(err));
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+
+       if (sc->state == ATAUSB_S_BBB_COMMAND ||
+           sc->state == ATAUSB_S_BBB_DATA ||
+           sc->state == ATAUSB_S_BBB_DCLEAR) {
+           /* first attempt on status transport phase setup transfer */
+           sc->state = ATAUSB_S_BBB_STATUS1;
+           next_xfer = sc->transfer[ATAUSB_T_BBB_CSW1];
+       }
+       else {
+           /* second attempt of fetching status */
+           sc->state = ATAUSB_S_BBB_STATUS2;
+           next_xfer = sc->transfer[ATAUSB_T_BBB_CSW2];
+       }
+       if (atausb_start(sc, sc->bulkin_pipe, &sc->csw, sizeof(struct bbb_csw),
+                        USBD_SHORT_XFER_OK, next_xfer)) {
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+       }
+       return;
+
+    case ATAUSB_S_BBB_STATUS1: /* status transfer first attempt */
+    case ATAUSB_S_BBB_STATUS2: /* status transfer second attempt */
+       if (err) {
+            if (atausbdebug)
+               device_printf(sc->dev, "cannot get CSW, %s%s\n",
+                             usbd_errstr(err),
+                             sc->state == ATAUSB_S_BBB_STATUS1 ? ", retry":"");
+           if (sc->state == ATAUSB_S_BBB_STATUS1) {
+               atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
+                                  ATAUSB_S_BBB_SCLEAR,
+                                  sc->transfer[ATAUSB_T_BBB_SCLEAR]);
+           }
+           else {
+               request->result = EIO;
+               atausb_bbb_reset(sc);
+           }
+           return;
+       }
+
+       int residue = UGETDW(sc->csw.residue);
+
+       if (!residue &&
+           (request->bytecount - request->donecount))
+           residue = request->bytecount - request->donecount;
+
+       /* check CSW and handle eventual error */
+       if (UGETDW(sc->csw.signature) != CSWSIGNATURE) {
+            if (atausbdebug)
+               device_printf(sc->dev, "bad CSW signature 0x%08x != 0x%08x\n",
+                             UGETDW(sc->csw.signature), CSWSIGNATURE);
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+       else if (UGETDW(sc->csw.tag) != UGETDW(sc->cbw.tag)) {
+            if (atausbdebug)
+               device_printf(sc->dev, "bad CSW tag %d != %d\n",
+                             UGETDW(sc->csw.tag), UGETDW(sc->cbw.tag));
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+       else if (sc->csw.status > CSWSTATUS_PHASE) {
+            if (atausbdebug)
+               device_printf(sc->dev, "bad CSW status %d > %d\n",
+                             sc->csw.status, CSWSTATUS_PHASE);
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+       else if (sc->csw.status == CSWSTATUS_PHASE) {
+            if (atausbdebug)
+               device_printf(sc->dev, "phase error residue = %d\n", residue);
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+       else if (request->donecount > request->bytecount) {
+            if (atausbdebug)
+               device_printf(sc->dev, "buffer overrun %d > %d",
+                            request->donecount, request->bytecount);
+           request->result = EIO;
+           atausb_bbb_reset(sc);
+           return;
+       }
+       else if (sc->csw.status == CSWSTATUS_FAILED) {
+            if (atausbdebug)
+               device_printf(sc->dev, "CSWSTATUS_FAILED\n");
+           request->error = ATA_E_ATAPI_SENSE_MASK ;
+           sc->state = ATAUSB_S_IDLE;
+           ata_interrupt(device_get_softc(request->parent));
+           return;
+       }
+       else {
+           sc->state = ATAUSB_S_IDLE;
+           ata_interrupt(device_get_softc(request->parent));
+           return;
+       }
+       /* NOT REACHED */
+
+    case ATAUSB_S_BBB_RESET1:
+       if (err)
+            if (atausbdebug)
+               device_printf(sc->dev,
+                             "BBB reset failure: %s\n", usbd_errstr(err));
+       atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
+                          ATAUSB_S_BBB_RESET2,
+                          sc->transfer[ATAUSB_T_BBB_RESET2]);
+       return;
+
+    case ATAUSB_S_BBB_RESET2:
+       if (err)
+            if (atausbdebug)
+               device_printf(sc->dev, "BBB bulkin clear stall failure: %s\n",
+                             usbd_errstr(err));
+       atausb_clear_stall(sc, sc->bulkout, sc->bulkout_pipe,
+                          ATAUSB_S_BBB_RESET3,
+                          sc->transfer[ATAUSB_T_BBB_RESET3]);
+       return;
+
+    case ATAUSB_S_BBB_RESET3:
+       if (err)
+            if (atausbdebug)
+               device_printf(sc->dev, "BBB bulk-out clear stall failure: %s\n",
+                             usbd_errstr(err));
+       sc->state = ATAUSB_S_IDLE;
+       if (request) {
+           if (err)
+               request->result = ENXIO;
+           else
+               request->result = EIO;
+           ata_interrupt(device_get_softc(request->parent));
+       }
+       return;
+
+    default:
+        if (atausbdebug)
+           device_printf(sc->dev, "unknown state %d", sc->state);
+    }
+}
+
+
+/*
+ * ATA backend part
+ */
+struct atapi_inquiry {
+    u_int8_t    device_type;
+    u_int8_t    device_modifier;
+    u_int8_t    version;
+    u_int8_t    response_format;
+    u_int8_t    length;
+    u_int8_t    reserved[2];
+    u_int8_t    flags;
+    u_int8_t    vendor[8];
+    u_int8_t    product[16];
+    u_int8_t    revision[4];
+    //u_int8_t    crap[60];
+};
+
+int
+ata_usbchannel_begin_transaction(struct ata_request *request)
+{
+    struct atausb_softc *sc = 
+       device_get_softc(device_get_parent(request->parent));
+
+    if (atausbdebug > 1)
+       device_printf(request->dev, "begin_transaction %s\n",
+                     ata_cmd2str(request));
+
+    /* sanity just in case */
+    if (sc->state != ATAUSB_S_IDLE) {
+       printf("begin is busy (%d)\n", sc->state);
+       request->result = EBUSY;
+       return ATA_OP_FINISHED;
+    }
+
+    /* XXX SOS convert the request into the format used, only BBB for now*/
+    sc->ata_request = request;
+
+    /* ATA/ATAPI IDENTIFY needs special treatment */
+    if (!(request->flags & ATA_R_ATAPI)) {
+       if (request->u.ata.command != ATA_ATAPI_IDENTIFY) {
+           device_printf(request->dev,"%s unsupported\n",ata_cmd2str(request));
+           request->result = EIO;
+           return ATA_OP_FINISHED;
+       }
+       request->flags |= ATA_R_ATAPI;
+       bzero(request->u.atapi.ccb, 16);
+       request->u.atapi.ccb[0] = ATAPI_INQUIRY;
+       request->u.atapi.ccb[4] =  255; //sizeof(struct atapi_inquiry);
+       request->data += 256;   /* arbitrary offset into ata_param */
+       request->bytecount = 255; //sizeof(struct atapi_inquiry);
+    }
+    return atausb_bbb_start(request);
+}
+
+int
+ata_usbchannel_end_transaction(struct ata_request *request)
+{
+    if (atausbdebug > 1)
+       device_printf(request->dev, "end_transaction %s\n",
+                     ata_cmd2str(request));
+    
+    /* XXX SOS convert the request from the format used, only BBB for now*/
+
+    /* ATA/ATAPI IDENTIFY needs special treatment */
+    if ((request->flags & ATA_R_ATAPI) &&
+       (request->u.atapi.ccb[0] == ATAPI_INQUIRY)) {
+       struct ata_device *atadev = device_get_softc(request->dev);
+       struct atapi_inquiry *inquiry = (struct atapi_inquiry *)request->data;
+       u_int16_t *ptr;
+
+       /* convert inquiry data into simple ata_param like format */
+       atadev->param.config = ATA_PROTO_ATAPI | ATA_PROTO_ATAPI_12;
+       atadev->param.config |= (inquiry->device_type & 0x1f) << 8;
+       bzero(atadev->param.model, sizeof(atadev->param.model));
+       strncpy(atadev->param.model, inquiry->vendor, 8);
+       strcpy(atadev->param.model, "  ");
+       strncpy(atadev->param.model, inquiry->product, 16);
+       ptr = (u_int16_t*)(atadev->param.model + sizeof(atadev->param.model));
+       while (--ptr >= (u_int16_t*)atadev->param.model)
+           *ptr = ntohs(*ptr);
+       strncpy(atadev->param.revision, inquiry->revision, 4);
+       ptr=(u_int16_t*)(atadev->param.revision+sizeof(atadev->param.revision));
+       while (--ptr >= (u_int16_t*)atadev->param.revision)
+           *ptr = ntohs(*ptr);
+       request->result = 0;
+    }
+    return ATA_OP_FINISHED;
+}
+
+static int
+ata_usbchannel_probe(device_t dev)
+{
+    char buffer[32];
+
+    sprintf(buffer, "USB lun %d", (int)(intptr_t)device_get_ivars(dev));
+    device_set_desc_copy(dev, buffer);
+
+    return 0;
+}
+
+static int
+ata_usbchannel_attach(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+
+    if (ch->attached)
+       return (0);
+    ch->attached = 1;
+
+    /* initialize the softc basics */
+    ch->dev = dev;
+    ch->unit = (intptr_t)device_get_ivars(dev);
+    ch->state = ATA_IDLE;
+    ch->hw.begin_transaction = ata_usbchannel_begin_transaction;
+    ch->hw.end_transaction = ata_usbchannel_end_transaction;
+    ch->hw.status = NULL;
+    ch->hw.command = NULL;
+    bzero(&ch->state_mtx, sizeof(struct mtx));
+    mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF);
+    bzero(&ch->queue_mtx, sizeof(struct mtx));
+    mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF);
+    TAILQ_INIT(&ch->ata_queue);
+
+    /* XXX SOS reset the controller HW, the channel and device(s) */
+    //ATA_RESET(dev);
+
+    /* probe and attach device on this channel */
+    ch->devices = ATA_ATAPI_MASTER;
+    if (!ata_delayed_attach)
+        ata_identify(dev);
+    return 0;
+}
+
+static int
+ata_usbchannel_detach(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+    device_t *children;
+    int nchildren, i;
+
+    if (!ch->attached)
+       return (0);
+    ch->attached = 0;
+
+    /* detach & delete all children */
+    if (!device_get_children(dev, &children, &nchildren)) {
+        for (i = 0; i < nchildren; i++)
+            if (children[i])
+                device_delete_child(dev, children[i]);
+        free(children, M_TEMP);
+    }
+    mtx_destroy(&ch->state_mtx);
+    mtx_destroy(&ch->queue_mtx);
+    return 0;
+}
+
+static void
+ata_usbchannel_setmode(device_t parent, device_t dev)
+{
+    struct atausb_softc *sc = device_get_softc(GRANDPARENT(dev));
+    struct ata_device *atadev = device_get_softc(dev);
+    usbd_device_handle udev;
+
+    usbd_interface2device_handle(sc->iface, &udev);
+    if (usbd_get_speed(udev) == USB_SPEED_HIGH)
+       atadev->mode = ATA_USB2;
+    else
+       atadev->mode = ATA_USB1;
+}
+
+static int
+ata_usbchannel_locking(device_t dev, int flags)
+{
+    struct atausb_softc *sc = device_get_softc(device_get_parent(dev));
+    struct ata_channel *ch = device_get_softc(dev);
+    int res = -1;
+
+
+    mtx_lock(&sc->locked_mtx);
+    switch (flags) {
+    case ATA_LF_LOCK:
+       if (sc->locked_ch == NULL)
+           sc->locked_ch = ch;
+       if (sc->locked_ch != ch)
+           sc->restart_ch = ch;
+       break;
+
+    case ATA_LF_UNLOCK:
+       if (sc->locked_ch == ch) {
+           sc->locked_ch = NULL;
+           if (sc->restart_ch) {
+               ch = sc->restart_ch;
+               sc->restart_ch = NULL;
+               mtx_unlock(&sc->locked_mtx);
+               ata_start(ch->dev);
+               return res;
+           }
+       }
+       break;
+
+    case ATA_LF_WHICH:
+       break;
+    }
+    if (sc->locked_ch)
+       res = sc->locked_ch->unit;
+    mtx_unlock(&sc->locked_mtx);
+    return res;
+}
+
+static device_method_t ata_usbchannel_methods[] = {
+    /* device interface */
+    DEVMETHOD(device_probe,         ata_usbchannel_probe),
+    DEVMETHOD(device_attach,        ata_usbchannel_attach),
+    DEVMETHOD(device_detach,        ata_usbchannel_detach),
+
+    /* ATA methods */
+    DEVMETHOD(ata_setmode,        ata_usbchannel_setmode),
+    DEVMETHOD(ata_locking,        ata_usbchannel_locking),
+    //DEVMETHOD(ata_reset,        ata_usbchannel_reset),
+
+    { 0, 0 }
+};
+
+static driver_t ata_usbchannel_driver = {
+    "ata",
+    ata_usbchannel_methods,
+    sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, atausb, ata_usbchannel_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(atausb, ata, 1, 1, 1);

Copied: head/sys/legacy/dev/sound/usb/uaudio.c (from r188941, 
head/sys/dev/sound/usb/uaudio.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/legacy/dev/sound/usb/uaudio.c      Mon Feb 23 21:07:20 2009        
(r188955, copy of r188941, head/sys/dev/sound/usb/uaudio.c)
@@ -0,0 +1,4662 @@
+/*     $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */
+/*     $FreeBSD$ */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to