ok, I got it fixed.

Heres my theory of what went wrong:

My (broken) BIOS does not know how to hand over the ehci host
controller. Therefore the timeout.
Additionally when 'HiSpeed' is selected it turns on several System 
Management Interupts in the ehci host controller and won't turn them 
off when the kernel requests the handover.
Later, when the kernel sets the CF bit the host controller issues a 
SMI to notify the BIOS of the ownership change of mouse and keyboard 
from ohci to the ehci host controller. The BIOS does not seem to like 
this and the kernel/BIOS freezes.
My fix simply clears all SMI_ENABLE bits in the USBLEGCTLSTS register 
when the BIOS does not acknowledge the handover. This violates the 
spec, because the USBLEGCTLSTS register is supposed to be used by the 
BIOS, not the OS.
Still I'm wondering why the controller worked with Linux since I could
not find a similar piece of code in the Linux kernel.
The diff is attached. Further down you find my first attempt to fix
this by porting the writelock part from linux. I don't know whether
OpenBSD needs this.


cheers, 

Christopher



Index: dev/pci/ehci_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ehci_pci.c,v
retrieving revision 1.18
diff -u -p -r1.18 ehci_pci.c
--- dev/pci/ehci_pci.c  24 Jul 2009 03:18:58 -0000      1.18
+++ dev/pci/ehci_pci.c  8 Mar 2010 14:17:48 -0000
@@ -294,9 +294,26 @@ ehci_pci_takecontroller(struct ehci_pci_
                                        break;
                                DELAY(1000);
                        }
-                       if (legsup & EHCI_LEGSUP_BIOSOWNED)
-                               printf("%s: timed out waiting for BIOS\n",
+                       if (legsup & EHCI_LEGSUP_BIOSOWNED) {
+                               /*
+                                * The BIOS on the Asus K8S-MV/P does not
+                                * release the semaphore in time and won't
+                                * turn of System management interrupts.
+                                * It will get confused by the SMIs caused
+                                * by port changes when the CF bit goes up.
+                                * Therefore we do the job of the BIOS and
+                                * turn off SMIs. The SMI control bits
+                                * are bits 0-15 at register eecp+0x04.
+                                * See the intel EHCI spec.
+                                */
+                               printf("%s: timed out waiting for BIOS"
+                                       " - at least disable all SMIs.\n",
                                    sc->sc.sc_bus.bdev.dv_xname);
+                               legsup = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                                       eecp + 0x04);
+                               pci_conf_write(sc->sc_pc, sc->sc_tag,
+                                       eecp + 0x04, legsup & 0xffff0000);
+                       }
                }
        }
 }



====================================================================
The folling diff is ported from the linux kernel.
It did not help my chipset, but didn't break anything either.

Index: dev/usb/usb.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb.h,v
retrieving revision 1.35
diff -u -p -r1.35 usb.h
--- dev/usb/usb.h       1 Mar 2010 23:35:56 -0000       1.35
+++ dev/usb/usb.h       8 Mar 2010 14:11:01 -0000
@@ -688,3 +688,6 @@ struct usb_event {
 #define USB_SET_CM_OVER_DATA   _IOW ('U', 131, int)
 
 #endif /* _USB_H_ */
+
+/* see ehci.c, usb_subr.h and usbdi.c */
+extern struct rwlock ehci_cf_port_reset_rwlock;
Index: dev/usb/usbdi.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.38
diff -u -p -r1.38 usbdi.c
--- dev/usb/usbdi.c     5 Mar 2010 17:28:54 -0000       1.38
+++ dev/usb/usbdi.c     8 Mar 2010 14:11:03 -0000
@@ -67,12 +67,16 @@ usbd_status usbd_open_pipe_ival(usbd_int
 int usbd_nbuses = 0;
 
 struct rwlock usbpalock;
+struct rwlock ehci_cf_port_reset_rwlock;
 
 void
 usbd_init(void)
 {
-       if (usbd_nbuses == 0)
+       if (usbd_nbuses == 0) {
                rw_init(&usbpalock, "usbpalock");
+               rw_init(&ehci_cf_port_reset_rwlock,
+                       "ehci_cf_port_reset_rwlock");
+       }
        usbd_nbuses++;
 }
 
Index: dev/usb/ehci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.106
diff -u -p -r1.106 ehci.c
--- dev/usb/ehci.c      26 Nov 2009 12:27:48 -0000      1.106
+++ dev/usb/ehci.c      8 Mar 2010 14:10:58 -0000
@@ -502,7 +502,25 @@ ehci_init(ehci_softc_t *sc)
            EHCI_CMD_PSE |
            EHCI_CMD_RS);
 
-       /* Take over port ownership */
+       /* Take over port ownership
+         *      
+         * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+         * are explicitly handed to companion controller(s), so no TT is
+         * involved with the root hub.  (Except where one is integrated,
+         * and there's no companion controller unless maybe for USB OTG.)
+         *              
+         * Turning on the CF flag will transfer ownership of all ports
+         * from the companions to the EHCI controller.  If any of the
+         * companions are in the middle of a port reset at the time, it
+         * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
+         * guarantees that no resets are in progress.  After we set CF,
+         * a short delay lets the hardware catch up; new resets shouldn't
+         * be started before the port switching actions could complete.
+        * 
+        * This explanation is taken from the Linux kernel 2.6.33
+        * drivers/usb/host/ehci-hcd.c by David Brownell
+         */   
+       rw_enter_write(&ehci_cf_port_reset_rwlock);
        EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF);
 
        for (i = 0; i < 100; i++) {
@@ -511,6 +529,7 @@ ehci_init(ehci_softc_t *sc)
                if (!hcr)
                        break;
        }
+       rw_exit_write(&ehci_cf_port_reset_rwlock);
        if (hcr) {
                printf("%s: run timeout\n", sc->sc_bus.bdev.dv_xname);
                return (USBD_IOERROR);
Index: dev/usb/usb_subr.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.73
diff -u -p -r1.73 usb_subr.c
--- dev/usb/usb_subr.c  14 Jan 2009 21:02:57 -0000      1.73
+++ dev/usb/usb_subr.c  8 Mar 2010 14:11:03 -0000
@@ -399,11 +399,12 @@ usbd_reset_port(usbd_device_handle dev, 
        USETW(req.wValue, UHF_PORT_RESET);
        USETW(req.wIndex, port);
        USETW(req.wLength, 0);
+       rw_enter_write(&ehci_cf_port_reset_rwlock);
        err = usbd_do_request(dev, &req, 0);
        DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
                    port, usbd_errstr(err)));
        if (err)
-               return (err);
+               goto done;
        n = 10;
        do {
                /* Wait for device to recover from reset. */
@@ -412,14 +413,18 @@ usbd_reset_port(usbd_device_handle dev, 
                if (err) {
                        DPRINTF(("usbd_reset_port: get status failed %d\n",
                                 err));
-                       return (err);
+                       goto done;
                }
                /* If the device disappeared, just give up. */
-               if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
-                       return (USBD_NORMAL_COMPLETION);
+               if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) {
+                       err = USBD_NORMAL_COMPLETION;
+                       goto done;
+               }
        } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
-       if (n == 0)
-               return (USBD_TIMEOUT);
+       if (n == 0) {
+               err = USBD_TIMEOUT;
+               goto done;
+       }
        err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
 #ifdef USB_DEBUG
        if (err)
@@ -429,6 +434,9 @@ usbd_reset_port(usbd_device_handle dev, 
 
        /* Wait for the device to recover from reset. */
        usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
+
+done:
+       rw_exit_write(&ehci_cf_port_reset_rwlock);
        return (err);
 }
 

====================================================================
And finaly my dmesg with both diffs in the kernel:

OpenBSD 4.7 (sys) #30: Mon Mar  8 15:19:55 CET 2010
    madro...@pundit:/var/obj/sys
real mem = 1071841280 (1022MB)
avail mem = 1031888896 (984MB)
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.3 @ 0xf04b0 (57 entries)
bios0: vendor American Megatrends Inc. version "0603" date 03/31/2006
bios0: ASUSTeK Computer INC. K8S-MV-P
acpi0 at bios0: rev 2
acpi0: tables DSDT FACP APIC OEMB
acpi0: wakeup devices PS2K(S4) PS2M(S4) EUSB(S4) USB_(S4) USB2(S4) USB3(S4) 
AC97(S4) MC97(S4) PCI1(S4) PCI2(S4) MAC_(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: AMD Sempron(tm) Processor 3000+, 1795.71 MHz
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,NXE,MMXX,FFXSR,LONG,3DNOW2,3DNOW
cpu0: 64KB 64b/line 2-way I-cache, 64KB 64b/line 2-way D-cache, 128KB 64b/line 
16-way L2 cache
cpu0: ITLB 32 4KB entries fully associative, 8 4MB entries fully associative
cpu0: DTLB 32 4KB entries fully associative, 8 4MB entries fully associative
cpu0: AMD erratum 89 present, BIOS upgrade may be required
cpu0: apic clock running at 199MHz
ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 14, 24 pins
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus 1 (P0P1)
acpiprt2 at acpi0: bus 2 (P0P6)
acpiprt3 at acpi0: bus 3 (P0P7)
acpicpu0 at acpi0: PSS
aibs0 at acpi0
acpibtn0 at acpi0: PWRB
cpu0: Cool'n'Quiet K8 1795 MHz: speeds: 1800 1000 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "SiS 760 PCI" rev 0x03
agp at pchb0 not configured
ppb0 at pci0 dev 1 function 0 "SiS 86C202 VGA" rev 0x00
pci1 at ppb0 bus 1
vga1 at pci1 dev 0 function 0 "NVIDIA GeForce FX 5200" rev 0xa1
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
pcib0 at pci0 dev 2 function 0 "SiS 965 ISA" rev 0x48
pciide0 at pci0 dev 2 function 5 "SiS 5513 EIDE" rev 0x01: 760: DMA, channel 0 
wired to compatibility, channel 1 wired to compatibility
atapiscsi0 at pciide0 channel 0 drive 0
scsibus0 at atapiscsi0: 2 targets
cd0 at scsibus0 targ 0 lun 0: <TSSTcorp, DVD-ROM SH-D162C, TS04> ATAPI 5/cdrom 
removable
cd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 disabled (no drives)
auich0 at pci0 dev 2 function 7 "SiS 7012 AC97" rev 0xa0: apic 1 int 18 (irq 
11), SiS7012 AC97
ac97: codec id 0x41445368 (Analog Devices AD1888)
ac97: codec features headphone, 20 bit DAC, No 3D Stereo
audio0 at auich0
ohci0 at pci0 dev 3 function 0 "SiS 5597/5598 USB" rev 0x0f: apic 1 int 20 (irq 
5), version 1.0, legacy support
ohci1 at pci0 dev 3 function 1 "SiS 5597/5598 USB" rev 0x0f: apic 1 int 21 (irq 
10), version 1.0, legacy support
ohci2 at pci0 dev 3 function 2 "SiS 5597/5598 USB" rev 0x0f: apic 1 int 22 (irq 
5), version 1.0, legacy support
ehci0 at pci0 dev 3 function 3 "SiS 7002 USB" rev 0x00: apic 1 int 23 (irq 10)
ehci0: timed out waiting for BIOS - at least disable all SMIs.
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "SiS EHCI root hub" rev 2.00/1.00 addr 1
sgb0 at pci0 dev 4 function 0 "SiS 190" rev 0x00invalid EEPROM signature (0)
: apic 1 int 19 (irq 5), address 00:15:f2:64:0c:83
rlphy0 at sgb0 phy 1: RTL8201L 10/100 PHY, rev. 1
pciide1 at pci0 dev 5 function 0 "SiS 182 SATA" rev 0x01: DMA
pciide1: using apic 1 int 17 (irq 10) for native-PCI interrupt
wd0 at pciide1 channel 0 drive 0: <SAMSUNG SP2504C>
wd0: 16-sector PIO, LBA48, 238475MB, 488397168 sectors
wd0(pciide1:0:0): using PIO mode 4, Ultra-DMA mode 6
ppb1 at pci0 dev 6 function 0 "SiS PCI-PCI" rev 0x00
pci2 at ppb1 bus 2
ppb2 at pci0 dev 7 function 0 "SiS PCI-PCI" rev 0x00
pci3 at ppb2 bus 3
pchb1 at pci0 dev 24 function 0 "AMD AMD64 0Fh HyperTransport" rev 0x00
pchb2 at pci0 dev 24 function 1 "AMD AMD64 0Fh Address Map" rev 0x00
pchb3 at pci0 dev 24 function 2 "AMD AMD64 0Fh DRAM Cfg" rev 0x00
kate0 at pci0 dev 24 function 3 "AMD AMD64 0Fh Misc Cfg" rev 0x00
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
pckbc0 at isa0 port 0x60/5
pcppi0 at isa0 port 0x61
midi0 at pcppi0: <PC speaker>
spkr0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
wbsio0 at isa0 port 0x2e/2: W83627EHF rev 0x54
lm1 at wbsio0 port 0x290/8: W83627EHF-A
usb1 at ohci0: USB revision 1.0
uhub1 at usb1 "SiS OHCI root hub" rev 1.00/1.00 addr 1
usb2 at ohci1: USB revision 1.0
uhub2 at usb2 "SiS OHCI root hub" rev 1.00/1.00 addr 1
usb3 at ohci2: USB revision 1.0
uhub3 at usb3 "SiS OHCI root hub" rev 1.00/1.00 addr 1
mtrr: Pentium Pro MTRR support
uhidev0 at uhub1 port 2 configuration 1 interface 0 "Sun Microsystems Type 6 
Keyboard" rev 1.10/2.00 addr 2
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 modifier keys, 6 key codes, country code 33
wskbd0 at ukbd0: console keyboard, using wsdisplay0
uhidev1 at uhub3 port 1 configuration 1 interface 0 "Logitech USB Optical 
Mouse" rev 2.00/43.01 addr 2
uhidev1: iclass 3/1
ums0 at uhidev1: 3 buttons, Z dir
wsmouse0 at ums0 mux 0
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
root on wd0a swap on wd0b dump on wd0b
splassert: if_up: want 5 have 7

Reply via email to