aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2011-02-28 17:23:15 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2011-02-28 17:23:15 +0000
commit1c49736857cfe0b562e2f1e100ab2307e882a9e6 (patch)
tree47ed63016899826a83fbbc10b56bb53c1b6d65cd /sys
parent898899d9ddbd15925a9d3c6b1da0d426dbc6351b (diff)
downloadsrc-1c49736857cfe0b562e2f1e100ab2307e882a9e6.tar.gz
src-1c49736857cfe0b562e2f1e100ab2307e882a9e6.zip
- Add support for software pre-scaling of ISOCHRONOUS transfers.
MFC after: 14 days Approved by: thompsa (mentor)
Notes
Notes: svn path=/head/; revision=219100
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/usb_generic.c15
-rw-r--r--sys/dev/usb/usb_ioctl.h5
-rw-r--r--sys/dev/usb/usb_transfer.c2
-rw-r--r--sys/dev/usb/usbdi.h10
4 files changed, 29 insertions, 3 deletions
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index da9b1d8ac055..8f197531bc46 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -1397,6 +1397,7 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
uint8_t iface_index;
uint8_t isread;
uint8_t ep_index;
+ uint8_t pre_scale;
u.addr = addr;
@@ -1448,6 +1449,12 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
if (u.popen->max_bufsize > USB_FS_MAX_BUFSIZE) {
u.popen->max_bufsize = USB_FS_MAX_BUFSIZE;
}
+ if (u.popen->max_frames & USB_FS_MAX_FRAMES_PRE_SCALE) {
+ pre_scale = 1;
+ u.popen->max_frames &= ~USB_FS_MAX_FRAMES_PRE_SCALE;
+ } else {
+ pre_scale = 0;
+ }
if (u.popen->max_frames > USB_FS_MAX_FRAMES) {
u.popen->max_frames = USB_FS_MAX_FRAMES;
break;
@@ -1468,13 +1475,15 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
}
iface_index = ep->iface_index;
- bzero(usb_config, sizeof(usb_config));
+ memset(usb_config, 0, sizeof(usb_config));
usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
usb_config[0].interval = USB_DEFAULT_INTERVAL;
usb_config[0].flags.proxy_buffer = 1;
+ if (pre_scale != 0)
+ usb_config[0].flags.pre_scale_frames = 1;
usb_config[0].callback = &ugen_ctrl_fs_callback;
usb_config[0].timeout = 0; /* no timeout */
usb_config[0].frames = u.popen->max_frames;
@@ -1516,6 +1525,10 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
f->fs_xfer[u.popen->ep_index]->max_frame_size;
u.popen->max_bufsize =
f->fs_xfer[u.popen->ep_index]->max_data_length;
+ /* update number of frames */
+ u.popen->max_frames =
+ f->fs_xfer[u.popen->ep_index]->nframes;
+ /* store index of endpoint */
f->fs_xfer[u.popen->ep_index]->priv_fifo =
((uint8_t *)0) + u.popen->ep_index;
} else {
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index 8fe55e18bd2a..452de94a7ab4 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -183,8 +183,9 @@ struct usb_fs_uninit {
struct usb_fs_open {
#define USB_FS_MAX_BUFSIZE (1 << 18)
uint32_t max_bufsize;
-#define USB_FS_MAX_FRAMES (1 << 12)
- uint32_t max_frames;
+#define USB_FS_MAX_FRAMES (1U << 12)
+#define USB_FS_MAX_FRAMES_PRE_SCALE (1U << 31) /* for ISOCHRONOUS transfers */
+ uint32_t max_frames; /* read and write */
uint16_t max_packet_length; /* read only */
uint8_t dev_index; /* currently unused */
uint8_t ep_index;
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 3a77c36d9b48..8dd9d1d27ac6 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -471,6 +471,8 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
xfer->fps_shift--;
if (xfer->fps_shift > 3)
xfer->fps_shift = 3;
+ if (xfer->flags.pre_scale_frames != 0)
+ xfer->nframes <<= (3 - xfer->fps_shift);
break;
}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 6d4a911b0d13..b88a65557aac 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -195,6 +195,16 @@ struct usb_xfer_flags {
uint8_t stall_pipe:1; /* set if the endpoint belonging to
* this USB transfer should be stalled
* before starting this transfer! */
+ uint8_t pre_scale_frames:1; /* "usb_config->frames" is
+ * assumed to give the
+ * buffering time in
+ * milliseconds and is
+ * converted into the nearest
+ * number of frames when the
+ * USB transfer is setup. This
+ * option only has effect for
+ * ISOCHRONOUS transfers.
+ */
};
/*