MFp4: //depot/projects/usb@155957

Make code more compliant with SuperSpeed USB and Wireless USB.

Submitted by: Hans Petter Selasky
This commit is contained in:
Andrew Thompson 2009-01-13 19:04:58 +00:00
parent 1697b02185
commit 0239859bda
6 changed files with 92 additions and 54 deletions

View file

@ -393,8 +393,14 @@ usb_linux_shutdown(device_t dev)
static uint16_t
usb_max_isoc_frames(struct usb_device *dev)
{
return ((usb2_get_speed(dev->bsd_udev) == USB_SPEED_HIGH) ?
USB_MAX_HIGH_SPEED_ISOC_FRAMES : USB_MAX_FULL_SPEED_ISOC_FRAMES);
; /* indent fix */
switch (usb2_get_speed(dev->bsd_udev)) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
return (USB_MAX_FULL_SPEED_ISOC_FRAMES);
default:
return (USB_MAX_HIGH_SPEED_ISOC_FRAMES);
}
}
/*------------------------------------------------------------------------*

View file

@ -75,18 +75,6 @@ static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t,
static void usb2_notify_addq(const char *type, struct usb2_device *);
static void usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t);
/* static structures */
static const uint8_t usb2_hub_speed_combs[USB_SPEED_MAX][USB_SPEED_MAX] = {
/* HUB *//* subdevice */
[USB_SPEED_HIGH][USB_SPEED_HIGH] = 1,
[USB_SPEED_HIGH][USB_SPEED_FULL] = 1,
[USB_SPEED_HIGH][USB_SPEED_LOW] = 1,
[USB_SPEED_FULL][USB_SPEED_FULL] = 1,
[USB_SPEED_FULL][USB_SPEED_LOW] = 1,
[USB_SPEED_LOW][USB_SPEED_LOW] = 1,
};
/* This variable is global to allow easy access to it: */
int usb2_template = 0;
@ -1364,21 +1352,10 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
udev->speed = speed;
udev->flags.usb2_mode = usb2_mode;
/* check speed combination */
/* speed combination should be checked by the parent HUB */
hub = udev->parent_hub;
if (hub) {
if (usb2_hub_speed_combs[hub->speed][speed] == 0) {
#if USB_DEBUG
printf("%s: the selected subdevice and HUB speed "
"combination is not supported %d/%d.\n",
__FUNCTION__, speed, hub->speed);
#endif
/* reject this combination */
err = USB_ERR_INVAL;
goto done;
}
}
/* search for our High Speed USB HUB, if any */
adev = udev;

View file

@ -157,12 +157,16 @@ ugen_open(struct usb2_fifo *f, int fflags, struct thread *td)
DPRINTFN(6, "flag=0x%x\n", fflags);
mtx_lock(f->priv_mtx);
if (usb2_get_speed(f->udev) == USB_SPEED_HIGH) {
f->nframes = UGEN_HW_FRAMES * 8;
f->bufsize = UGEN_BULK_HS_BUFFER_SIZE;
} else {
switch (usb2_get_speed(f->udev)) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
f->nframes = UGEN_HW_FRAMES;
f->bufsize = UGEN_BULK_FS_BUFFER_SIZE;
break;
default:
f->nframes = UGEN_HW_FRAMES * 8;
f->bufsize = UGEN_BULK_HS_BUFFER_SIZE;
break;
}
type = ed->bmAttributes & UE_XFERTYPE;

View file

@ -372,18 +372,38 @@ repeat:
/*
* Figure out the device speed
*/
speed =
(sc->sc_st.port_status & UPS_HIGH_SPEED) ? USB_SPEED_HIGH :
(sc->sc_st.port_status & UPS_LOW_SPEED) ? USB_SPEED_LOW : USB_SPEED_FULL;
switch (udev->speed) {
case USB_SPEED_HIGH:
if (sc->sc_st.port_status & UPS_HIGH_SPEED)
speed = USB_SPEED_HIGH;
else if (sc->sc_st.port_status & UPS_LOW_SPEED)
speed = USB_SPEED_LOW;
else
speed = USB_SPEED_FULL;
break;
case USB_SPEED_FULL:
if (sc->sc_st.port_status & UPS_LOW_SPEED)
speed = USB_SPEED_LOW;
else
speed = USB_SPEED_FULL;
break;
case USB_SPEED_LOW:
speed = USB_SPEED_LOW;
break;
default:
/* same speed like parent */
speed = udev->speed;
break;
}
/*
* Figure out the device mode
*
* NOTE: This part is currently FreeBSD specific.
*/
usb2_mode =
(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE) ?
USB_MODE_DEVICE : USB_MODE_HOST;
if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
usb2_mode = USB_MODE_DEVICE;
else
usb2_mode = USB_MODE_HOST;
/* need to create a new child */
@ -1049,17 +1069,16 @@ usb2_intr_schedule_adjust(struct usb2_device *udev, int16_t len, uint8_t slot)
{
struct usb2_bus *bus = udev->bus;
struct usb2_hub *hub;
uint8_t speed;
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
if (usb2_get_speed(udev) == USB_SPEED_HIGH) {
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
slot = usb2_intr_find_best_slot(bus->uframe_usage, 0,
USB_HS_MICRO_FRAMES_MAX);
}
bus->uframe_usage[slot] += len;
} else {
if (usb2_get_speed(udev) == USB_SPEED_LOW) {
speed = usb2_get_speed(udev);
switch (speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
if (speed == USB_SPEED_LOW) {
len *= 8;
}
/*
@ -1076,6 +1095,14 @@ usb2_intr_schedule_adjust(struct usb2_device *udev, int16_t len, uint8_t slot)
}
hub->uframe_usage[slot] += len;
bus->uframe_usage[slot] += len;
break;
default:
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
slot = usb2_intr_find_best_slot(bus->uframe_usage, 0,
USB_HS_MICRO_FRAMES_MAX);
}
bus->uframe_usage[slot] += len;
break;
}
return (slot);
}

View file

@ -63,6 +63,7 @@ static const struct usb2_std_packet_size
[USB_SPEED_FULL] = {.range = {0, 64}},
[USB_SPEED_HIGH] = {.range = {0, 1024}},
[USB_SPEED_VARIABLE] = {.range = {0, 1024}},
[USB_SPEED_SUPER] = {.range = {0, 1024}},
},
[UE_CONTROL] = {
@ -70,6 +71,7 @@ static const struct usb2_std_packet_size
[USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
[USB_SPEED_HIGH] = {.fixed = {64, 64, 64, 64}},
[USB_SPEED_VARIABLE] = {.fixed = {512, 512, 512, 512}},
[USB_SPEED_SUPER] = {.fixed = {512, 512, 512, 512}},
},
[UE_BULK] = {
@ -77,6 +79,7 @@ static const struct usb2_std_packet_size
[USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
[USB_SPEED_HIGH] = {.fixed = {512, 512, 512, 512}},
[USB_SPEED_VARIABLE] = {.fixed = {512, 512, 1024, 1536}},
[USB_SPEED_SUPER] = {.fixed = {1024, 1024, 1024, 1024}},
},
[UE_ISOCHRONOUS] = {
@ -84,6 +87,7 @@ static const struct usb2_std_packet_size
[USB_SPEED_FULL] = {.range = {0, 1023}},
[USB_SPEED_HIGH] = {.range = {0, 1024}},
[USB_SPEED_VARIABLE] = {.range = {0, 3584}},
[USB_SPEED_SUPER] = {.range = {0, 1024}},
},
};
@ -413,10 +417,14 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
*/
xfer->timeout = 1000 / 4;
}
if (parm->speed == USB_SPEED_HIGH) {
frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
} else {
switch (parm->speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
frame_limit = USB_MAX_FS_ISOC_FRAMES_PER_XFER;
break;
default:
frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
break;
}
if (xfer->nframes > frame_limit) {
@ -446,13 +454,29 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
xfer->interval = edesc->bInterval;
if (parm->speed == USB_SPEED_HIGH) {
xfer->interval /= 8; /* 125us -> 1ms */
switch (parm->speed) {
case USB_SPEED_SUPER:
case USB_SPEED_VARIABLE:
/* 125us -> 1ms */
if (xfer->interval < 4)
xfer->interval = 1;
else if (xfer->interval > 16)
xfer->interval = (1<<(16-4));
else
xfer->interval =
(1 << (xfer->interval-4));
break;
case USB_SPEED_HIGH:
/* 125us -> 1ms */
xfer->interval /= 8;
break;
default:
break;
}
if (xfer->interval == 0) {
/*
* one millisecond is the smallest
* interval
* One millisecond is the smallest
* interval we support:
*/
xfer->interval = 1;
}

View file

@ -602,12 +602,12 @@ struct usb2_port_status {
#define UPS_SUSPEND 0x0004
#define UPS_OVERCURRENT_INDICATOR 0x0008
#define UPS_RESET 0x0010
#define UPS_PORT_MODE_DEVICE 0x0020 /* currently FreeBSD specific */
#define UPS_PORT_POWER 0x0100
#define UPS_LOW_SPEED 0x0200
#define UPS_HIGH_SPEED 0x0400
#define UPS_PORT_TEST 0x0800
#define UPS_PORT_INDICATOR 0x1000
#define UPS_PORT_MODE_DEVICE 0x8000 /* currently FreeBSD specific */
uWord wPortChange;
#define UPS_C_CONNECT_STATUS 0x0001
#define UPS_C_PORT_ENABLED 0x0002