From owner-p4-projects@FreeBSD.ORG Wed Aug 11 18:26:03 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 004691066066; Wed, 11 Aug 2010 18:26:02 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 331371065C02 for ; Wed, 11 Aug 2010 18:25:58 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id AD76D8FC13 for ; Wed, 11 Aug 2010 18:25:58 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id o7BIPwuK084041 for ; Wed, 11 Aug 2010 18:25:58 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o7BIPwa4084037 for perforce@freebsd.org; Wed, 11 Aug 2010 18:25:58 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 11 Aug 2010 18:25:58 GMT Message-Id: <201008111825.o7BIPwa4084037@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 182148 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Aug 2010 18:26:03 -0000 http://p4web.freebsd.org/@@182148?ac=10 Change 182148 by hselasky@hselasky_laptop001 on 2010/08/09 19:43:23 USB core: - changes needed for XHCI support (Super Speed USB) - compute fps_shift also for interrupt endpoints - add helper function to USB HUB driver to give information about number of HUB ports before the HUB driver gets attached. - add new USB method that allows the USB controller driver to track the state of the USB devices. - correct some Super Speed burst computations. - add missing state changes in the re-enumerate function Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_controller.h#27 edit .. //depot/projects/usb/src/sys/dev/usb/usb_device.c#78 edit .. //depot/projects/usb/src/sys/dev/usb/usb_device.h#41 edit .. //depot/projects/usb/src/sys/dev/usb/usb_hub.c#56 edit .. //depot/projects/usb/src/sys/dev/usb/usb_hub.h#18 edit .. //depot/projects/usb/src/sys/dev/usb/usb_request.c#43 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#185 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_controller.h#27 (text+ko) ==== @@ -126,6 +126,8 @@ void (*start_dma_delay) (struct usb_xfer *); + void (*device_state_change) (struct usb_device *); + /* Optional for host mode */ usb_error_t (*set_address) (struct usb_device *, struct mtx *, uint16_t); ==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#78 (text+ko) ==== @@ -1560,7 +1560,6 @@ udev->bus = bus; udev->address = USB_START_ADDR; /* default value */ udev->plugtime = (usb_ticks_t)ticks; - usb_set_device_state(udev, USB_STATE_POWERED); /* * We need to force the power mode to "on" because there are plenty * of USB devices out there that do not work very well with @@ -1637,6 +1636,8 @@ goto done; } } + /* set powered device state after device init is complete */ + usb_set_device_state(udev, USB_STATE_POWERED); if (udev->flags.usb_mode == USB_MODE_HOST) { @@ -2616,6 +2617,17 @@ DPRINTF("udev %p state %s -> %s\n", udev, usb_statestr(udev->state), usb_statestr(state)); udev->state = state; + + if (udev->bus->methods->device_state_change != NULL) + (udev->bus->methods->device_state_change) (udev); +} + +enum usb_dev_state +usb_get_device_state(struct usb_device *udev) +{ + if (udev == NULL) + return (USB_STATE_DETACHED); + return (udev->state); } uint8_t ==== //depot/projects/usb/src/sys/dev/usb/usb_device.h#41 (text+ko) ==== @@ -215,8 +215,9 @@ void usb_linux_free_device(struct usb_device *dev); uint8_t usb_peer_can_wakeup(struct usb_device *udev); struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep); -void usb_set_device_state(struct usb_device *udev, - enum usb_dev_state state); +void usb_set_device_state(struct usb_device *, enum usb_dev_state); +enum usb_dev_state usb_get_device_state(struct usb_device *); + void usbd_enum_lock(struct usb_device *); void usbd_enum_unlock(struct usb_device *); void usbd_sr_lock(struct usb_device *); ==== //depot/projects/usb/src/sys/dev/usb/usb_hub.c#56 (text+ko) ==== @@ -805,6 +805,67 @@ return (ENXIO); } +/* NOTE: The information returned by this function can be wrong. */ +usb_error_t +uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt) +{ + struct usb_hub_descriptor hubdesc20; + struct usb_hub_ss_descriptor hubdesc30; + usb_error_t err; + uint8_t nports; + uint8_t tt; + + if (udev->ddesc.bDeviceClass != UDCLASS_HUB) + return (USB_ERR_INVAL); + + nports = 0; + tt = 0; + + switch (udev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + /* assuming that there is one port */ + err = usbd_req_get_hub_descriptor(udev, NULL, &hubdesc20, 1); + if (err) { + DPRINTFN(0, "getting USB 2.0 HUB descriptor failed," + "error=%s\n", usbd_errstr(err)); + break; + } + nports = hubdesc20.bNbrPorts; + if (nports > 127) + nports = 127; + + if (udev->speed == USB_SPEED_HIGH) + tt = (UGETW(hubdesc20.wHubCharacteristics) >> 5) & 3; + break; + + case USB_SPEED_SUPER: + err = usbd_req_get_ss_hub_descriptor(udev, NULL, &hubdesc30, 1); + if (err) { + DPRINTFN(0, "Getting USB 3.0 HUB descriptor failed," + "error=%s\n", usbd_errstr(err)); + break; + } + nports = hubdesc30.bNbrPorts; + if (nports > 16) + nports = 16; + break; + + default: + err = USB_ERR_INVAL; + break; + } + + if (pnports != NULL) + *pnports = nports; + + if (ptt != NULL) + *ptt = tt; + + return (err); +} + static int uhub_attach(device_t dev) { ==== //depot/projects/usb/src/sys/dev/usb/usb_hub.h#18 (text+ko) ==== @@ -78,5 +78,6 @@ void usb_bus_power_update(struct usb_bus *bus); void usb_bus_powerd(struct usb_bus *bus); void uhub_root_intr(struct usb_bus *, const uint8_t *, uint8_t); +usb_error_t uhub_query_info(struct usb_device *, uint8_t *, uint8_t *); #endif /* _USB_HUB_H_ */ ==== //depot/projects/usb/src/sys/dev/usb/usb_request.c#43 (text+ko) ==== @@ -1858,6 +1858,7 @@ old_addr, usbd_errstr(err)); goto done; } + /* * After that the port has been reset our device should be at * address zero: @@ -1867,6 +1868,9 @@ /* reset "bMaxPacketSize" */ udev->ddesc.bMaxPacketSize = USB_MAX_IPACKET; + /* reset USB state */ + usb_set_device_state(udev, USB_STATE_POWERED); + /* * Restore device address: */ @@ -1898,6 +1902,9 @@ /* restore address */ if (udev->address == USB_START_ADDR) udev->address = old_addr; + /* update state, if successful */ + if (err == 0) + usb_set_device_state(udev, USB_STATE_ADDRESSED); return (err); } ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#185 (text+ko) ==== @@ -315,6 +315,7 @@ }; struct usb_xfer *xfer = parm->curr_xfer; const struct usb_config *setup = parm->curr_setup; + struct usb_endpoint_ss_comp_descriptor *ecomp; struct usb_endpoint_descriptor *edesc; struct usb_std_packet_size std_size; usb_frcount_t n_frlengths; @@ -322,7 +323,6 @@ usb_frcount_t x; uint8_t type; uint8_t zmps; - uint8_t mult; /* * Sanity check. The following parameters must be initialized before @@ -335,6 +335,7 @@ goto done; } edesc = xfer->endpoint->edesc; + ecomp = xfer->endpoint->ecomp; type = (edesc->bmAttributes & UE_XFERTYPE); @@ -353,41 +354,48 @@ switch (parm->speed) { case USB_SPEED_HIGH: - xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3; - /* check for invalid max packet count */ - if (xfer->max_packet_count > 3) - xfer->max_packet_count = 3; + switch (type) { + case UE_ISOCHRONOUS: + case UE_INTERRUPT: + xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3; + + /* check for invalid max packet count */ + if (xfer->max_packet_count > 3) + xfer->max_packet_count = 3; + break; + default: + break; + } xfer->max_packet_size &= 0x7FF; break; - case USB_SPEED_SUPER: xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3; - mult = 1; + + if (ecomp != NULL) + xfer->max_packet_count += ecomp->bMaxBurst; - /* compute additional bMaxBurst */ - if (xfer->endpoint->ecomp != NULL) { - xfer->max_packet_count += - xfer->endpoint->ecomp->bMaxBurst; + if ((xfer->max_packet_count == 0) || + (xfer->max_packet_count > 16)) + xfer->max_packet_count = 16; - if (type == UE_ISOCHRONOUS) { - mult += - (xfer->endpoint->ecomp->bmAttributes & 3); - } - } + switch (type) { + case UE_CONTROL: + xfer->max_packet_count = 1; + break; + case UE_ISOCHRONOUS: + if (ecomp != NULL) { + uint8_t mult; - xfer->max_packet_count *= mult; + mult = (ecomp->bmAttributes & 3) + 1; + if (mult > 3) + mult = 3; - /* check for invalid max packet count */ - if (type == UE_ISOCHRONOUS) { - if ((xfer->max_packet_count == 0) || - (xfer->max_packet_count > (16 * 3))) - xfer->max_packet_count = (16 * 3); - } else { - if ((xfer->max_packet_count == 0) || - (xfer->max_packet_count > (16 * 1))) - xfer->max_packet_count = (16 * 1); + xfer->max_packet_count *= mult; + } + break; + default: + break; } - xfer->max_packet_size &= 0x7FF; break; default: @@ -484,41 +492,57 @@ } else { /* - * if a value is specified use that else check the endpoint - * descriptor + * If a value is specified use that else check the + * endpoint descriptor! */ - if (xfer->interval == 0) { + if (type == UE_INTERRUPT) { + + uint32_t temp; - if (type == UE_INTERRUPT) { + if (xfer->interval == 0) { xfer->interval = edesc->bInterval; switch (parm->speed) { - case USB_SPEED_SUPER: - case USB_SPEED_VARIABLE: + case USB_SPEED_LOW: + case USB_SPEED_FULL: + break; + default: /* 125us -> 1ms */ if (xfer->interval < 4) xfer->interval = 1; else if (xfer->interval > 16) - xfer->interval = (1<<(16-4)); + xfer->interval = (1 << (16 - 4)); else xfer->interval = - (1 << (xfer->interval-4)); + (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 we support: - */ - xfer->interval = 1; - } + } + + if (xfer->interval == 0) { + /* + * One millisecond is the smallest + * interval we support: + */ + xfer->interval = 1; + } + + xfer->fps_shift = 0; + temp = 1; + + while ((temp != 0) && (temp < xfer->interval)) { + xfer->fps_shift++; + temp *= 2; + } + + switch (parm->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + break; + default: + xfer->fps_shift += 3; + break; } } }