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

Reply via email to