summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usbdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/usbdi.c')
-rw-r--r--sys/dev/usb/usbdi.c661
1 files changed, 367 insertions, 294 deletions
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 72207f9..c7aa594 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi.c,v 1.37 1999/09/11 08:19:27 augustss Exp $ */
+/* $NetBSD: usbdi.c,v 1.47 1999/10/13 23:46:10 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -46,10 +46,16 @@
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/conf.h>
+#include "usb_if.h"
+#if defined(DIAGNOSTIC) && defined(__i386__)
+#include <machine/cpu.h>
+#endif
#endif
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <machine/bus.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -60,7 +66,7 @@
#if defined(__FreeBSD__)
#include "usb_if.h"
#endif
-
+
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) logprintf x
#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
@@ -71,22 +77,47 @@ extern int usbdebug;
#endif
static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
-void usbd_do_request_async_cb
- __P((usbd_request_handle, usbd_private_handle, usbd_status));
-void usbd_start_next __P((usbd_pipe_handle pipe));
+static void usbd_do_request_async_cb
+ __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
+static void usbd_start_next __P((usbd_pipe_handle pipe));
+
+static SIMPLEQ_HEAD(, usbd_xfer) usbd_free_requests =
+ SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests);
+
+static int usbd_nbuses = 0;
-static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests
- = SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests);
+void
+usbd_init()
+{
+ usbd_nbuses++;
+}
-static __inline int usbd_reqh_isread __P((usbd_request_handle reqh));
+void
+usbd_finish()
+{
+ usbd_xfer_handle xfer;
+
+ if (--usbd_nbuses == 0) {
+ /* Last controller is gone, free all requests. */
+ for (;;) {
+ xfer = SIMPLEQ_FIRST(&usbd_free_requests);
+ if (xfer == NULL)
+ break;
+ SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, xfer, next);
+ free(xfer, M_USB);
+ }
+ }
+}
+
+static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer));
static __inline int
-usbd_reqh_isread(reqh)
- usbd_request_handle reqh;
+usbd_xfer_isread(xfer)
+ usbd_xfer_handle xfer;
{
- if (reqh->rqflags & URQ_REQUEST)
- return (reqh->request.bmRequestType & UT_READ);
+ if (xfer->rqflags & URQ_REQUEST)
+ return (xfer->request.bmRequestType & UT_READ);
else
- return (reqh->pipe->endpoint->edesc->bEndpointAddress &
+ return (xfer->pipe->endpoint->edesc->bEndpointAddress &
UE_DIR_IN);
}
@@ -97,13 +128,13 @@ void
usbd_dump_queue(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
printf("usbd_dump_queue: pipe=%p\n", pipe);
- for (reqh = SIMPLEQ_FIRST(&pipe->queue);
- reqh;
- reqh = SIMPLEQ_NEXT(reqh, next)) {
- printf(" reqh=%p\n", reqh);
+ for (xfer = SIMPLEQ_FIRST(&pipe->queue);
+ xfer;
+ xfer = SIMPLEQ_NEXT(xfer, next)) {
+ printf(" xfer=%p\n", xfer);
}
}
#endif
@@ -117,7 +148,7 @@ usbd_open_pipe(iface, address, flags, pipe)
{
usbd_pipe_handle p;
struct usbd_endpoint *ep;
- usbd_status r;
+ usbd_status err;
int i;
for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
@@ -130,9 +161,9 @@ usbd_open_pipe(iface, address, flags, pipe)
if ((flags & USBD_EXCLUSIVE_USE) &&
ep->refcnt != 0)
return (USBD_IN_USE);
- r = usbd_setup_pipe(iface->device, iface, ep, &p);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_setup_pipe(iface->device, iface, ep, &p);
+ if (err)
+ return (err);
LIST_INSERT_HEAD(&iface->pipes, p, next);
*pipe = p;
return (USBD_NORMAL_COMPLETION);
@@ -149,35 +180,35 @@ usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
u_int32_t length;
usbd_callback cb;
{
- usbd_status r;
- usbd_request_handle reqh;
+ usbd_status err;
+ usbd_xfer_handle xfer;
usbd_pipe_handle ipipe;
- r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- reqh = usbd_alloc_request(iface->device);
- if (reqh == 0) {
- r = USBD_NOMEM;
+ err = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
+ if (err)
+ return (err);
+ xfer = usbd_alloc_request(iface->device);
+ if (xfer == NULL) {
+ err = USBD_NOMEM;
goto bad1;
}
- usbd_setup_request(reqh, ipipe, priv, buffer, length, flags,
+ usbd_setup_request(xfer, ipipe, priv, buffer, length, flags,
USBD_NO_TIMEOUT, cb);
- ipipe->intrreqh = reqh;
+ ipipe->intrxfer = xfer;
ipipe->repeat = 1;
- r = usbd_transfer(reqh);
+ err = usbd_transfer(xfer);
*pipe = ipipe;
- if (r != USBD_IN_PROGRESS)
+ if (err != USBD_IN_PROGRESS)
goto bad2;
return (USBD_NORMAL_COMPLETION);
bad2:
- ipipe->intrreqh = 0;
+ ipipe->intrxfer = NULL;
ipipe->repeat = 0;
- usbd_free_request(reqh);
+ usbd_free_request(xfer);
bad1:
usbd_close_pipe(ipipe);
- return r;
+ return (err);
}
usbd_status
@@ -185,7 +216,7 @@ usbd_close_pipe(pipe)
usbd_pipe_handle pipe;
{
#ifdef DIAGNOSTIC
- if (pipe == 0) {
+ if (pipe == NULL) {
printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
@@ -198,175 +229,185 @@ usbd_close_pipe(pipe)
LIST_REMOVE(pipe, next);
pipe->endpoint->refcnt--;
pipe->methods->close(pipe);
- if (pipe->intrreqh)
- usbd_free_request(pipe->intrreqh);
+ if (pipe->intrxfer != NULL)
+ usbd_free_request(pipe->intrxfer);
free(pipe, M_USB);
return (USBD_NORMAL_COMPLETION);
}
usbd_status
-usbd_transfer(reqh)
- usbd_request_handle reqh;
+usbd_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
- usbd_status r;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usb_dma_t *dmap = &xfer->dmabuf;
+ usbd_status err;
u_int size;
int s;
- DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
- reqh, reqh->flags, pipe, pipe->running));
+ DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
+ xfer, xfer->flags, pipe, pipe->running));
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
#endif
- reqh->done = 0;
+ xfer->done = 0;
- size = reqh->length;
- /* If there is no buffer, allocate one and copy data. */
- if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) {
- usb_dma_t *dmap = &reqh->dmabuf;
+ size = xfer->length;
+ /* If there is no buffer, allocate one. */
+ if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
struct usbd_bus *bus = pipe->device->bus;
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_AUTO_DMABUF)
+ if (xfer->rqflags & URQ_AUTO_DMABUF)
printf("usbd_transfer: has old buffer!\n");
#endif
- r = bus->methods->allocm(bus, dmap, size);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- reqh->rqflags |= URQ_AUTO_DMABUF;
-
- /* finally copy data if going out */
- if (!usbd_reqh_isread(reqh))
- memcpy(KERNADDR(dmap), reqh->buffer, size);
+ err = bus->methods->allocm(bus, dmap, size);
+ if (err)
+ return (err);
+ xfer->rqflags |= URQ_AUTO_DMABUF;
}
- r = pipe->methods->transfer(reqh);
+ /* Copy data if going out. */
+ if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
+ !usbd_xfer_isread(xfer))
+ memcpy(KERNADDR(dmap), xfer->buffer, size);
+
+ err = pipe->methods->transfer(xfer);
- if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) {
+ if (err != USBD_IN_PROGRESS && err) {
/* The transfer has not been queued, so free buffer. */
- if (reqh->rqflags & URQ_AUTO_DMABUF) {
+ if (xfer->rqflags & URQ_AUTO_DMABUF) {
struct usbd_bus *bus = pipe->device->bus;
- bus->methods->freem(bus, &reqh->dmabuf);
- reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ bus->methods->freem(bus, &xfer->dmabuf);
+ xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
}
- if (!(reqh->flags & USBD_SYNCHRONOUS))
- return (r);
+ if (!(xfer->flags & USBD_SYNCHRONOUS))
+ return (err);
/* Sync transfer, wait for completion. */
- if (r != USBD_IN_PROGRESS)
- return (r);
+ if (err != USBD_IN_PROGRESS)
+ return (err);
s = splusb();
- if (!reqh->done) {
+ if (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done\n");
- tsleep(reqh, PRIBIO, "usbsyn", 0);
+ tsleep(xfer, PRIBIO, "usbsyn", 0);
}
splx(s);
- return (reqh->status);
+ return (xfer->status);
}
/* Like usbd_transfer(), but waits for completion. */
usbd_status
-usbd_sync_transfer(reqh)
- usbd_request_handle reqh;
+usbd_sync_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- reqh->flags |= USBD_SYNCHRONOUS;
- return (usbd_transfer(reqh));
+ xfer->flags |= USBD_SYNCHRONOUS;
+ return (usbd_transfer(xfer));
}
void *
-usbd_alloc_buffer(reqh, size)
- usbd_request_handle reqh;
+usbd_alloc_buffer(xfer, size)
+ usbd_xfer_handle xfer;
u_int32_t size;
{
- struct usbd_bus *bus = reqh->device->bus;
- usbd_status r;
+ struct usbd_bus *bus = xfer->device->bus;
+ usbd_status err;
- r = bus->methods->allocm(bus, &reqh->dmabuf, size);
- if (r != USBD_NORMAL_COMPLETION)
+ err = bus->methods->allocm(bus, &xfer->dmabuf, size);
+ if (err)
return (0);
- reqh->rqflags |= URQ_DEV_DMABUF;
- return (KERNADDR(&reqh->dmabuf));
+ xfer->rqflags |= URQ_DEV_DMABUF;
+ return (KERNADDR(&xfer->dmabuf));
}
void
-usbd_free_buffer(reqh)
- usbd_request_handle reqh;
+usbd_free_buffer(xfer)
+ usbd_xfer_handle xfer;
{
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
+ if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
printf("usbd_free_buffer: no buffer\n");
return;
}
#endif
- reqh->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
- reqh->device->bus->methods->freem(reqh->device->bus, &reqh->dmabuf);
+ xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
+ xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
}
-usbd_request_handle
+void *
+usbd_get_buffer(xfer)
+ usbd_xfer_handle xfer;
+{
+ if (!(xfer->rqflags & URQ_DEV_DMABUF))
+ return (0);
+ return (KERNADDR(&xfer->dmabuf));
+}
+
+usbd_xfer_handle
usbd_alloc_request(dev)
usbd_device_handle dev;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
- reqh = SIMPLEQ_FIRST(&usbd_free_requests);
- if (reqh)
- SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
+ xfer = SIMPLEQ_FIRST(&usbd_free_requests);
+ if (xfer != NULL)
+ SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, xfer, next);
else
- reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
- if (!reqh)
+ xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ if (xfer == NULL)
return (0);
- memset(reqh, 0, sizeof *reqh);
- reqh->device = dev;
- DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh));
- return (reqh);
+ memset(xfer, 0, sizeof *xfer);
+ xfer->device = dev;
+ DPRINTFN(5,("usbd_alloc_request() = %p\n", xfer));
+ return (xfer);
}
usbd_status
-usbd_free_request(reqh)
- usbd_request_handle reqh;
+usbd_free_request(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTFN(5,("usbd_free_request: %p\n", reqh));
- if (reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
- usbd_free_buffer(reqh);
- SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
+ DPRINTFN(5,("usbd_free_request: %p\n", xfer));
+ if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
+ usbd_free_buffer(xfer);
+ SIMPLEQ_INSERT_HEAD(&usbd_free_requests, xfer, next);
return (USBD_NORMAL_COMPLETION);
}
void
-usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
- usbd_request_handle reqh;
+usbd_setup_request(xfer, pipe, priv, buffer, length, flags, timeout, callback)
+ usbd_xfer_handle xfer;
usbd_pipe_handle pipe;
usbd_private_handle priv;
void *buffer;
u_int32_t length;
u_int16_t flags;
u_int32_t timeout;
- void (*callback) __P((usbd_request_handle,
+ void (*callback) __P((usbd_xfer_handle,
usbd_private_handle,
usbd_status));
{
- reqh->pipe = pipe;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = timeout;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->rqflags &= ~URQ_REQUEST;
- reqh->nframes = 0;
+ xfer->pipe = pipe;
+ xfer->priv = priv;
+ xfer->buffer = buffer;
+ xfer->length = length;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = timeout;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->rqflags &= ~URQ_REQUEST;
+ xfer->nframes = 0;
}
void
-usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
+usbd_setup_default_request(xfer, dev, priv, timeout, req, buffer,
length, flags, callback)
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
usbd_device_handle dev;
usbd_private_handle priv;
u_int32_t timeout;
@@ -374,63 +415,64 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
void *buffer;
u_int32_t length;
u_int16_t flags;
- void (*callback) __P((usbd_request_handle,
+ void (*callback) __P((usbd_xfer_handle,
usbd_private_handle,
usbd_status));
{
- reqh->pipe = dev->default_pipe;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = timeout;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->request = *req;
- reqh->rqflags |= URQ_REQUEST;
- reqh->nframes = 0;
+ xfer->pipe = dev->default_pipe;
+ xfer->priv = priv;
+ xfer->buffer = buffer;
+ xfer->length = length;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = timeout;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->request = *req;
+ xfer->rqflags |= URQ_REQUEST;
+ xfer->nframes = 0;
}
void
-usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, callback)
- usbd_request_handle reqh;
+usbd_setup_isoc_request(xfer, pipe, priv, frlengths, nframes, flags, callback)
+ usbd_xfer_handle xfer;
usbd_pipe_handle pipe;
usbd_private_handle priv;
u_int16_t *frlengths;
u_int32_t nframes;
+ u_int16_t flags;
usbd_callback callback;
{
- reqh->pipe = pipe;
- reqh->priv = priv;
- reqh->buffer = 0;
- reqh->length = 0;
- reqh->actlen = 0;
- reqh->flags = 0;
- reqh->timeout = USBD_NO_TIMEOUT;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->rqflags &= ~URQ_REQUEST;
- reqh->frlengths = frlengths;
- reqh->nframes = nframes;
+ xfer->pipe = pipe;
+ xfer->priv = priv;
+ xfer->buffer = 0;
+ xfer->length = 0;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = USBD_NO_TIMEOUT;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->rqflags &= ~URQ_REQUEST;
+ xfer->frlengths = frlengths;
+ xfer->nframes = nframes;
}
void
-usbd_get_request_status(reqh, priv, buffer, count, status)
- usbd_request_handle reqh;
+usbd_get_request_status(xfer, priv, buffer, count, status)
+ usbd_xfer_handle xfer;
usbd_private_handle *priv;
void **buffer;
u_int32_t *count;
usbd_status *status;
{
- if (priv)
- *priv = reqh->priv;
- if (buffer)
- *buffer = reqh->buffer;
- if (count)
- *count = reqh->actlen;
- if (status)
- *status = reqh->status;
+ if (priv != NULL)
+ *priv = xfer->priv;
+ if (buffer != NULL)
+ *buffer = xfer->buffer;
+ if (count != NULL)
+ *count = xfer->actlen;
+ if (status != NULL)
+ *status = xfer->status;
}
usb_config_descriptor_t *
@@ -468,19 +510,19 @@ usbd_status
usbd_abort_pipe(pipe)
usbd_pipe_handle pipe;
{
- usbd_status r;
+ usbd_status err;
int s;
#ifdef DIAGNOSTIC
- if (pipe == 0) {
+ if (pipe == NULL) {
printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
#endif
s = splusb();
- r = usbd_ar_pipe(pipe);
+ err = usbd_ar_pipe(pipe);
splx(s);
- return (r);
+ return (err);
}
usbd_status
@@ -489,7 +531,7 @@ usbd_clear_endpoint_stall(pipe)
{
usbd_device_handle dev = pipe->device;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
@@ -504,15 +546,15 @@ usbd_clear_endpoint_stall(pipe)
USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
- r = usbd_do_request(dev, &req, 0);
+ err = usbd_do_request(dev, &req, 0);
#if 0
XXX should we do this?
- if (r == USBD_NORMAL_COMPLETION) {
+ if (!err) {
pipe->state = USBD_PIPE_ACTIVE;
/* XXX activate pipe */
}
#endif
- return (r);
+ return (err);
}
usbd_status
@@ -521,7 +563,7 @@ usbd_clear_endpoint_stall_async(pipe)
{
usbd_device_handle dev = pipe->device;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
pipe->methods->cleartoggle(pipe);
@@ -530,8 +572,8 @@ usbd_clear_endpoint_stall_async(pipe)
USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
- r = usbd_do_request_async(dev, &req, 0);
- return (r);
+ err = usbd_do_request_async(dev, &req, 0);
+ return (err);
}
usbd_status
@@ -548,7 +590,7 @@ usbd_interface_count(dev, count)
usbd_device_handle dev;
u_int8_t *count;
{
- if (!dev->cdesc)
+ if (dev->cdesc == NULL)
return (USBD_NOT_CONFIGURED);
*count = dev->cdesc->bNumInterface;
return (USBD_NORMAL_COMPLETION);
@@ -569,7 +611,7 @@ usbd_device2interface_handle(dev, ifaceno, iface)
u_int8_t ifaceno;
usbd_interface_handle *iface;
{
- if (!dev->cdesc)
+ if (dev->cdesc == NULL)
return (USBD_NOT_CONFIGURED);
if (ifaceno >= dev->cdesc->bNumInterface)
return (USBD_INVAL);
@@ -591,7 +633,7 @@ usbd_set_interface(iface, altidx)
int altidx;
{
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
if (LIST_FIRST(&iface->pipes) != 0)
return (USBD_IN_USE);
@@ -601,16 +643,16 @@ usbd_set_interface(iface, altidx)
iface->endpoints = 0;
iface->idesc = 0;
- r = usbd_fill_iface_data(iface->device, iface->index, altidx);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_fill_iface_data(iface->device, iface->index, altidx);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_INTERFACE;
req.bRequest = UR_SET_INTERFACE;
USETW(req.wValue, iface->idesc->bAlternateSetting);
USETW(req.wIndex, iface->idesc->bInterfaceNumber);
USETW(req.wLength, 0);
- return usbd_do_request(iface->device, &req, 0);
+ return (usbd_do_request(iface->device, &req, 0));
}
int
@@ -652,7 +694,7 @@ usbd_get_interface(iface, aiface)
USETW(req.wValue, 0);
USETW(req.wIndex, iface->idesc->bInterfaceNumber);
USETW(req.wLength, 1);
- return usbd_do_request(iface->device, &req, aiface);
+ return (usbd_do_request(iface->device, &req, aiface));
}
/*** Internal routines ***/
@@ -662,143 +704,167 @@ static usbd_status
usbd_ar_pipe(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
+
+ SPLUSBCHECK;
DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
#endif
- while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
- DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n",
- pipe, reqh, pipe->methods));
+ pipe->repeat = 0;
+ while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
+ DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
+ pipe, xfer, pipe->methods));
/* Make the HC abort it (and invoke the callback). */
- pipe->methods->abort(reqh);
+ pipe->methods->abort(xfer);
/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
}
return (USBD_NORMAL_COMPLETION);
}
+/* Called at splusb() */
void
-usb_transfer_complete(reqh)
- usbd_request_handle reqh;
+usb_transfer_complete(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usb_dma_t *dmap = &xfer->dmabuf;
+ int repeat = pipe->repeat;
int polling;
- DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n",
- pipe, reqh, reqh->actlen));
+ SPLUSBCHECK;
+
+ DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
+ "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
#ifdef DIAGNOSTIC
- if (!pipe) {
- printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
+ if (pipe == NULL) {
+ printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
return;
}
#endif
-
polling = pipe->device->bus->use_polling;
/* XXXX */
if (polling)
pipe->running = 0;
- /* if we allocated the buffer in usbd_transfer() we free it here. */
- if (reqh->rqflags & URQ_AUTO_DMABUF) {
- usb_dma_t *dmap = &reqh->dmabuf;
+ if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
+ usbd_xfer_isread(xfer)) {
+#ifdef DIAGNOSTIC
+ if (xfer->actlen > xfer->length) {
+ printf("usb_transfer_complete: actlen > len %d > %d\n",
+ xfer->actlen, xfer->length);
+ xfer->actlen = xfer->length;
+ }
+#endif
+ memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
+ }
- if (usbd_reqh_isread(reqh))
- memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
- if (!pipe->repeat) {
+ /* if we allocated the buffer in usbd_transfer() we free it here. */
+ if (xfer->rqflags & URQ_AUTO_DMABUF) {
+ if (!repeat) {
struct usbd_bus *bus = pipe->device->bus;
bus->methods->freem(bus, dmap);
- reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
}
- if (pipe->methods->done)
- pipe->methods->done(reqh);
-
- /* Remove request from queue. */
- if ( reqh == SIMPLEQ_FIRST(&pipe->queue) )
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
- else
- DPRINTF(("XXX duplicated call to usb_transfer_complete\n"));
+ if (pipe->methods->done != NULL)
+ pipe->methods->done(xfer);
+ if (!repeat) {
+ /* Remove request from queue. */
+#ifdef DIAGNOSTIC
+ if (xfer != SIMPLEQ_FIRST(&pipe->queue))
+ printf("usb_transfer_complete: bad dequeue %p != %p\n",
+ xfer, SIMPLEQ_FIRST(&pipe->queue));
+#endif
+ SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
+ }
/* Count completed transfers. */
++pipe->device->bus->stats.requests
[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
- reqh->done = 1;
- if (reqh->status == USBD_NORMAL_COMPLETION &&
- reqh->actlen < reqh->length &&
- !(reqh->flags & USBD_SHORT_XFER_OK)) {
- DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
- reqh->actlen, reqh->length));
- reqh->status = USBD_SHORT_XFER;
+ xfer->done = 1;
+ if (xfer->status == USBD_NORMAL_COMPLETION &&
+ xfer->actlen < xfer->length &&
+ !(xfer->flags & USBD_SHORT_XFER_OK)) {
+ DPRINTFN(-1, ("usbd_transfer_cb: short transfer %d<%d\n",
+ xfer->actlen, xfer->length));
+ xfer->status = USBD_SHORT_XFER;
}
- if (reqh->callback)
- reqh->callback(reqh, reqh->priv, reqh->status);
+ if (xfer->callback)
+ xfer->callback(xfer, xfer->priv, xfer->status);
- if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
- wakeup(reqh);
+ if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
+ wakeup(xfer);
- if (!pipe->repeat &&
- reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT)
- usbd_start_next(pipe);
+ if (!repeat) {
+ /* XXX should we stop the queue on all errors? */
+ if (xfer->status == USBD_CANCELLED ||
+ xfer->status == USBD_TIMEOUT)
+ pipe->running = 0;
+ else
+ usbd_start_next(pipe);
+ }
}
usbd_status
-usb_insert_transfer(reqh)
- usbd_request_handle reqh;
+usb_insert_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
- usbd_status r;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usbd_status err;
int s;
- DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe,
- pipe->running));
+ DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
+ pipe, pipe->running, xfer->timeout));
s = splusb();
- SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
+ SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
if (pipe->running)
- r = USBD_IN_PROGRESS;
+ err = USBD_IN_PROGRESS;
else {
pipe->running = 1;
- r = USBD_NORMAL_COMPLETION;
+ err = USBD_NORMAL_COMPLETION;
}
splx(s);
- return (r);
+ return (err);
}
+/* Called at splusb() */
void
usbd_start_next(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
+
+ SPLUSBCHECK;
- DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
-
#ifdef DIAGNOSTIC
- if (!pipe) {
- printf("usbd_start_next: pipe == 0\n");
+ if (pipe == NULL) {
+ printf("usbd_start_next: pipe == NULL\n");
return;
}
- if (!pipe->methods || !pipe->methods->start) {
- printf("usbd_start_next: no start method\n");
+ if (pipe->methods == NULL || pipe->methods->start == NULL) {
+ printf("usbd_start_next: pipe=%p no start method\n", pipe);
return;
}
#endif
/* Get next request in queue. */
- reqh = SIMPLEQ_FIRST(&pipe->queue);
- DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
- if (!reqh)
+ xfer = SIMPLEQ_FIRST(&pipe->queue);
+ DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
+ if (xfer == NULL) {
pipe->running = 0;
- else {
- r = pipe->methods->start(reqh);
- if (r != USBD_IN_PROGRESS) {
- printf("usbd_start_next: error=%d\n", r);
+ } else {
+ err = pipe->methods->start(xfer);
+ if (err != USBD_IN_PROGRESS) {
+ printf("usbd_start_next: error=%d\n", err);
pipe->running = 0;
/* XXX do what? */
}
@@ -822,35 +888,39 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
u_int16_t flags;
int *actlen;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
#ifdef DIAGNOSTIC
- if (!curproc) {
+#if defined(__i386__)
+ KASSERT(intr_nesting_level == 0,
+ ("ohci_abort_req in interrupt context"));
+#endif
+ if (dev->bus->intr_context) {
printf("usbd_do_request: not in process context\n");
return (USBD_INVAL);
}
#endif
- reqh = usbd_alloc_request(dev);
- if (reqh == 0)
+ xfer = usbd_alloc_request(dev);
+ if (xfer == NULL)
return (USBD_NOMEM);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
+ usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
data, UGETW(req->wLength), flags, 0);
- r = usbd_sync_transfer(reqh);
+ err = usbd_sync_transfer(xfer);
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
+ if (xfer->actlen > xfer->length)
DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
"%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- dev->address, reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen));
+ dev->address, xfer->request.bmRequestType,
+ xfer->request.bRequest, UGETW(xfer->request.wValue),
+ UGETW(xfer->request.wIndex),
+ UGETW(xfer->request.wLength),
+ xfer->length, xfer->actlen));
#endif
- if (actlen)
- *actlen = reqh->actlen;
- if (r == USBD_STALLED) {
+ if (actlen != NULL)
+ *actlen = xfer->actlen;
+ if (err == USBD_STALLED) {
/*
* The control endpoint has stalled. Control endpoints
* should not halt, but some may do so anyway so clear
@@ -859,18 +929,18 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
usb_device_request_t treq;
usb_status_t status;
u_int16_t s;
- usbd_status nr;
+ usbd_status nerr;
treq.bmRequestType = UT_READ_ENDPOINT;
treq.bRequest = UR_GET_STATUS;
USETW(treq.wValue, 0);
USETW(treq.wIndex, 0);
USETW(treq.wLength, sizeof(usb_status_t));
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
&treq, &status,sizeof(usb_status_t),
0, 0);
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
+ nerr = usbd_sync_transfer(xfer);
+ if (nerr)
goto bad;
s = UGETW(status.wStatus);
DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
@@ -881,36 +951,36 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
USETW(treq.wValue, UF_ENDPOINT_HALT);
USETW(treq.wIndex, 0);
USETW(treq.wLength, 0);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
&treq, &status, 0, 0, 0);
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
+ nerr = usbd_sync_transfer(xfer);
+ if (nerr)
goto bad;
}
bad:
- usbd_free_request(reqh);
- return (r);
+ usbd_free_request(xfer);
+ return (err);
}
void
-usbd_do_request_async_cb(reqh, priv, status)
- usbd_request_handle reqh;
+usbd_do_request_async_cb(xfer, priv, status)
+ usbd_xfer_handle xfer;
usbd_private_handle priv;
usbd_status status;
{
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
+ if (xfer->actlen > xfer->length)
DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
"%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- reqh->pipe->device->address,
- reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen));
+ xfer->pipe->device->address,
+ xfer->request.bmRequestType,
+ xfer->request.bRequest, UGETW(xfer->request.wValue),
+ UGETW(xfer->request.wIndex),
+ UGETW(xfer->request.wLength),
+ xfer->length, xfer->actlen));
#endif
- usbd_free_request(reqh);
+ usbd_free_request(xfer);
}
/*
@@ -923,19 +993,18 @@ usbd_do_request_async(dev, req, data)
usb_device_request_t *req;
void *data;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
- reqh = usbd_alloc_request(dev);
- if (reqh == 0)
+ xfer = usbd_alloc_request(dev);
+ if (xfer == NULL)
return (USBD_NOMEM);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), 0,
- usbd_do_request_async_cb);
- r = usbd_transfer(reqh);
- if (r != USBD_IN_PROGRESS) {
- usbd_free_request(reqh);
- return (r);
+ usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
+ data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
+ err = usbd_transfer(xfer);
+ if (err != USBD_IN_PROGRESS) {
+ usbd_free_request(xfer);
+ return (err);
}
return (USBD_NORMAL_COMPLETION);
}
@@ -964,7 +1033,10 @@ usbd_set_polling(iface, on)
usbd_interface_handle iface;
int on;
{
- iface->device->bus->use_polling = on;
+ if (on)
+ iface->device->bus->use_polling++;
+ else
+ iface->device->bus->use_polling--;
}
@@ -989,7 +1061,8 @@ int
usbd_driver_load(module_t mod, int what, void *arg)
{
/* XXX should implement something like a function that removes all generic devices */
-
- return 0; /* nothing to do by us */
+
+ return (0);
}
+
#endif
OpenPOWER on IntegriCloud