On Thursday 24 Feb 2005 22:15, David Brownell wrote:
> 
> If you can find some approach that works reliably, I think the right way
> to package it would be by defining a new quirk flag and kicking in the
> logic that's needed on your chip.  Then set that flag when the PCI probe
> detects this particular PCI vendor/product and this revision (or older).
> 
> That way if someone sticks a "modern" CardBus controller into that laptop,
> this workaround would only apply to the built-in controller.
> 

OK, here's what I've come up with. ohci-pci.c::ohci_pci_start() is the only
place I can find where I can get access to both the pci_dev, to get at its
vendor and device fields, and the usb_device, to get the chipset revision
from ->descriptor.bcdDevice. Furthermore, ohci_run must have completed
before ->descriptor.bcdDevice has been loaded with the chipset revision.

I've tried it out on my laptop and I see the "enabled...quirk" message when
it boots or I bounce the usb drivers, but not when I insert the cardbus USB2
adapter (which also has ohci). The usb system on the laptop appears still to
be fully functional, but I'll give it a bit of stress testing this evening.

Comments, advice, corrections etc welcome. For the extremely unlikely case
that it's OK as it stands:

Signed-off-by: Chris Clayton <[EMAIL PROTECTED]>

diff -ur linux-2.6.11-rc4.orig/drivers/usb/host/ohci-pci.c 
linux-2.6.11-rc4/drivers/usb/host/ohci-pci.c
--- linux-2.6.11-rc4.orig/drivers/usb/host/ohci-pci.c   2005-02-13 
03:07:01.000000000 +0000
+++ linux-2.6.11-rc4/drivers/usb/host/ohci-pci.c        2005-02-27 
16:29:30.000000000 +0000
@@ -44,9 +44,10 @@
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             ret;
+       struct usb_device *udev;
+       struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 
        if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) {
-               struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 
                /* AMD 756, for most chips (early revs), corrupts register
                 * values on read ... so enable the vendor workaround.
@@ -97,6 +98,19 @@
                ohci_stop (hcd);
                return ret;
        }
+
+       /* Check for Compaq's ZFMicro chipset, which needs some short 
+        * delays when urbs are unlinked in ochi-q.c::finish_unlinks()
+        */
+#define ZFMICRO_MAX_REV 0x0206
+       udev = hcd->self.root_hub;
+       if (pdev->vendor == PCI_VENDOR_ID_COMPAQ
+                       && pdev->device  == 0xa0f8 
+                       && udev->descriptor.bcdDevice <= ZFMICRO_MAX_REV) {
+               ohci->flags |= OHCI_QUIRK_ZFMICRO;
+               ohci_info (ohci, "enabled Compaq ZFMicro chipset quirk\n");
+       }
+
        return 0;
 }
 
diff -ur linux-2.6.11-rc4.orig/drivers/usb/host/ohci-q.c 
linux-2.6.11-rc4/drivers/usb/host/ohci-q.c
--- linux-2.6.11-rc4.orig/drivers/usb/host/ohci-q.c     2005-02-13 
03:07:40.000000000 +0000
+++ linux-2.6.11-rc4/drivers/usb/host/ohci-q.c  2005-02-26 12:46:01.000000000 
+0000
@@ -1018,6 +1018,8 @@
 
                if (ohci->ed_controltail) {
                        command |= OHCI_CLF;
+                       if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+                               mdelay(1);
                        if (!(ohci->hc_control & OHCI_CTRL_CLE)) {
                                control |= OHCI_CTRL_CLE;
                                ohci_writel (ohci, 0,
@@ -1026,6 +1028,8 @@
                }
                if (ohci->ed_bulktail) {
                        command |= OHCI_BLF;
+                       if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+                               mdelay(1);
                        if (!(ohci->hc_control & OHCI_CTRL_BLE)) {
                                control |= OHCI_CTRL_BLE;
                                ohci_writel (ohci, 0,
@@ -1036,12 +1040,17 @@
                /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
                if (control) {
                        ohci->hc_control |= control;
+                       if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+                               mdelay(1);
                        ohci_writel (ohci, ohci->hc_control,
                                        &ohci->regs->control);   
                }
-               if (command)
+               if (command) {
+                       if (ohci->flags & OHCI_QUIRK_ZFMICRO)
+                               mdelay(1);
                        ohci_writel (ohci, command, &ohci->regs->cmdstatus);   
-       }
+               }
+       }
 }
 
 
diff -ur linux-2.6.11-rc4.orig/drivers/usb/host/ohci.h 
linux-2.6.11-rc4/drivers/usb/host/ohci.h
--- linux-2.6.11-rc4.orig/drivers/usb/host/ohci.h       2005-02-13 
03:07:50.000000000 +0000
+++ linux-2.6.11-rc4/drivers/usb/host/ohci.h    2005-02-26 12:46:01.000000000 
+0000
@@ -396,6 +396,7 @@
 #define        OHCI_QUIRK_SUPERIO      0x02                    /* natsemi */
 #define        OHCI_QUIRK_INITRESET    0x04                    /* SiS, OPTi, 
... */
 #define        OHCI_BIG_ENDIAN         0x08                    /* big endian 
HC */
+#define        OHCI_QUIRK_ZFMICRO      0x10                    /* Compaq 
ZFMicro chipset*/
        // there are also chip quirks/bugs in init logic
 
 };


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to