x86: disables USB legacy stack
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 2 Sep 2014 18:47:59 +0000 (11:47 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 10 Sep 2014 03:15:27 +0000 (20:15 -0700)
Only for EHCI and UHCI.  You'll get a warning on OHCI.

kern/arch/x86/Kbuild
kern/arch/x86/init.c
kern/arch/x86/usb.c [new file with mode: 0644]
kern/arch/x86/usb.h [new file with mode: 0644]

index 6c65cae..bf44a8b 100644 (file)
@@ -28,6 +28,7 @@ obj-y                                         += smp_entry$(BITS).o
 obj-y                                          += time.o
 obj-y                                          += trap.o trap$(BITS).o
 obj-y                                          += trapentry$(BITS).o
+obj-y                                          += usb.o
 
 # Virtual machine support. Optional.
 obj-$(CONFIG_VM)                               += emulate.o
index 583ddde..fe9f7dd 100644 (file)
@@ -12,6 +12,7 @@
 #include <arch/init.h>
 #include <console.h>
 #include <monitor.h>
+#include <arch/usb.h>
 
 struct ancillary_state x86_default_fpu;
 uint32_t kerndate;
@@ -92,5 +93,6 @@ void arch_init()
 
        perfmon_init();
        cons_irq_init();
+       usb_disable_legacy();
        check_timing_stability();
 }
diff --git a/kern/arch/x86/usb.c b/kern/arch/x86/usb.c
new file mode 100644 (file)
index 0000000..1555bae
--- /dev/null
@@ -0,0 +1,95 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ *
+ * Adapted from usbehcipc.c and usbuhci.c
+ */
+
+#define Clegacy                                1
+#define CLbiossem                              2
+#define CLossem                                3
+#define CLcontrol                              4
+
+#include <arch/x86.h>
+#include <arch/pci.h>
+#include <trap.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <kmalloc.h>
+#include <time.h>
+#include <mm.h>
+
+static void ehci_disable_leg(struct pci_device *pcidev)
+{
+       int i, ptr, cap, sem;
+
+       //ptr = (ctlr->capio->capparms >> Ceecpshift) & Ceecpmask;
+       uintptr_t bar0 = pci_get_membar(pcidev, 0);
+       assert(bar0);
+       uintptr_t ehci_hcc_regs = vmap_pmem_nocache(bar0, pcidev->bar[0].mmio_sz);
+       uint32_t hccparams = read_mmreg32(ehci_hcc_regs + 0x08);
+       ptr = (hccparams >> 8) & ((1 << 8) - 1);
+
+       for(; ptr != 0; ptr = pcidev_read8(pcidev, ptr + 1)) {
+               if (ptr < 0x40 || (ptr & ~0xFC))
+                       break;
+               cap = pcidev_read8(pcidev, ptr);
+               if (cap != Clegacy)
+                       continue;
+               sem = pcidev_read8(pcidev, ptr + CLbiossem);
+               if (sem == 0)
+                       continue;
+               pcidev_write8(pcidev, ptr + CLossem, 1);
+               for (i = 0; i < 100; i++) {
+                       if (pcidev_read8(pcidev, ptr + CLbiossem) == 0)
+                               break;
+                       udelay(10);
+               }
+               if (i == 100)
+                       printk("PCI EHCI %x:%x:%x: bios timed out\n",
+                              pcidev->bus, pcidev->dev, pcidev->func);
+               /* bit 29 could be left on, in case we want to give it back */
+               pcidev_write32(pcidev, ptr + CLcontrol, 0);     /* no SMIs */
+               //ctlr->opio->config = 0;
+               //coherence();
+               printk("PCI EHCI %x:%x:%x: disabled legacy USB\n",
+                      pcidev->bus, pcidev->dev, pcidev->func);
+               return;
+       }
+       printk("PCI EHCI %x:%x:%x: couldn't find legacy capability\n",
+              pcidev->bus, pcidev->dev, pcidev->func);
+}
+
+static void uhci_disable_leg(struct pci_device *pcidev)
+{
+       pcidev_write16(pcidev, 0xc0, 0x2000);
+       printk("PCI UHCI %x:%x:%x: disabled legacy USB\n",
+              pcidev->bus, pcidev->dev, pcidev->func);
+}
+
+void usb_disable_legacy()
+{
+       struct pci_device *i;
+
+       STAILQ_FOREACH(i, &pci_devices, all_dev) {
+               if ((i->class == 0x0c) && (i->subclass == 0x03)) {
+                       switch (i->progif) {
+                               case 0x00:
+                                       uhci_disable_leg(i);
+                                       break;
+                               case 0x20:
+                                       ehci_disable_leg(i);
+                                       break;
+                               default:
+                                       /* TODO: ohci */
+                                       printk("PCI USB %x:%x:%x, unknown progif 0x%x\n",
+                                              i->bus, i->dev, i->func, i->progif);
+                       }
+               }
+       }
+}
diff --git a/kern/arch/x86/usb.h b/kern/arch/x86/usb.h
new file mode 100644 (file)
index 0000000..d958cee
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef ROS_KERN_ARCH_USB_H
+#define ROS_KERN_ARCH_USB_H
+
+void usb_disable_legacy();
+
+#endif /* ROS_KERN_ARCH_USB_H */