Johannes: The current implementation of the Change-Port-Reset bits for the root hub in uhci-hub.c is totally bogus. This patch fixes it.
Of course, it's not really necessary to implement those bits at all -- the UHCI driver works fine right now with a broken implementation. Maybe you would prefer to remove the support entirely. But if you want to keep it and the patch looks good, please ask Greg to apply it. Alan Stern # This is a BitKeeper generated patch for the following project: # Project Name: greg k-h's linux 2.5 USB kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1656 -> 1.1657 # drivers/usb/host/uhci-hub.c 1.3 -> 1.4 # drivers/usb/host/uhci-hcd.h 1.14 -> 1.15 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/07/22 [EMAIL PROTECTED] 1.1657 # Implement the Change-Port-Reset root hub flags correctly. # -------------------------------------------- # diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h --- a/drivers/usb/host/uhci-hcd.h Tue Jul 22 11:27:13 2003 +++ b/drivers/usb/host/uhci-hcd.h Tue Jul 22 11:27:13 2003 @@ -341,6 +341,7 @@ enum uhci_state state; /* FIXME: needs a spinlock */ unsigned long state_end; /* Time of next transition */ int resume_detect; /* Need a Global Resume */ + unsigned long c_p_r; /* Change-Port-Reset bits */ /* Main list of URB's currently controlled by this HC */ spinlock_t urb_list_lock; diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c --- a/drivers/usb/host/uhci-hub.c Tue Jul 22 11:27:13 2003 +++ b/drivers/usb/host/uhci-hub.c Tue Jul 22 11:27:13 2003 @@ -32,7 +32,9 @@ *buf = 0; for (i = 0; i < uhci->rh_numports; i++) { - *buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); + *buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 || + test_bit(i, &uhci->c_p_r) + ? (1 << (i + 1)) : 0); len = (i + 1) / 8 + 1; } @@ -42,14 +44,14 @@ #define OK(x) len = (x); break #define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ + status = inw(io_addr + USBPORTSC1 + 2 * wIndex); \ status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + outw(status, io_addr + USBPORTSC1 + 2 * wIndex) #define SET_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ + status = inw(io_addr + USBPORTSC1 + 2 * wIndex); \ status = (status & 0xfff5) | (x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + outw(status, io_addr + USBPORTSC1 + 2 * wIndex) /* size of returned buffer is part of USB spec */ @@ -57,13 +59,12 @@ u16 wIndex, char *buf, u16 wLength) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int i, status, retval = 0, len = 0; + int status, retval = 0, len = 0; unsigned int io_addr = uhci->io_addr; __u16 cstatus; - char c_p_r[8]; - for (i = 0; i < 8; i++) - c_p_r[i] = 0; + /* Convert wIndex to origin 0; if it was 0, it will wrap around */ + --wIndex; switch (typeReq) { /* Request Destination: @@ -78,11 +79,11 @@ *(__u32 *)buf = cpu_to_le32(0); OK(4); /* hub power */ case GetPortStatus: - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); + status = inw(io_addr + USBPORTSC1 + 2 * wIndex); cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | ((status & USBPORTSC_PEC) >> (3 - 1)) | - (c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | + (!!test_bit(wIndex, &uhci->c_p_r) << (0 + 4)); + status = (status & USBPORTSC_CCS) | ((status & USBPORTSC_PE) >> (2 - 1)) | ((status & USBPORTSC_SUSP) >> (12 - 2)) | ((status & USBPORTSC_PR) >> (9 - 4)) | @@ -110,7 +111,7 @@ } break; case SetPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (wIndex >= uhci->rh_numports) goto err; switch (wValue) { @@ -120,7 +121,7 @@ case USB_PORT_FEAT_RESET: SET_RH_PORTSTAT(USBPORTSC_PR); mdelay(50); /* USB v1.1 7.1.7.3 */ - c_p_r[wIndex - 1] = 1; + set_bit(wIndex, &uhci->c_p_r); CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); SET_RH_PORTSTAT(USBPORTSC_PE); @@ -137,7 +138,7 @@ } break; case ClearPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (wIndex >= uhci->rh_numports) goto err; switch (wValue) { @@ -161,7 +162,7 @@ case USB_PORT_FEAT_C_OVER_CURRENT: OK(0); /* port power over current */ case USB_PORT_FEAT_C_RESET: - c_p_r[wIndex - 1] = 0; + clear_bit(wIndex, &uhci->c_p_r); OK(0); default: goto err; ------------------------------------------------------- This SF.net email is sponsored by: VM Ware With VMware you can run multiple operating systems on a single machine. WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel