diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index 0e190ce90090..38aba4ab9b30 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.42 1999/04/29 05:15:30 tsubai Exp $ */ +/* $NetBSD: machdep.c,v 1.43 1999/05/06 19:24:47 thorpej Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -90,6 +90,23 @@ #include #include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include vm_map_t exec_map = NULL; vm_map_t mb_map = NULL; @@ -1082,10 +1099,14 @@ mapiodev(pa, len) } #include "akbd.h" +#include "ukbd.h" +#include "uhci.h" +#include "ohci.h" #include "ofb.h" #include "ite.h" #include "zstty.h" + int console_node = -1; void @@ -1096,6 +1117,12 @@ cninit() int stdout; char type[16]; + /* + * Initialize the PCI chipsets; can't map configuration + * space registers yet! + */ + pci_init(0); + l = OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); if (l != sizeof(stdout)) goto nocons; @@ -1110,16 +1137,199 @@ cninit() #if NOFB > 0 if (strcmp(type, "display") == 0) { + u_int32_t pciclass, reg, bus, device, function; + const char *usbstr; + int stdin, i; + pcitag_t tag; + + /* + * Attach the console output now (so we can see + * debugging messages, if any). + */ + ofb_cnattach(); + + /* + * We must determine which keyboard type we have. + */ + l = OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)); + if (l != sizeof(stdin)) { + printf("WARNING: no `stdin' property in /chosen\n"); + return; + } + + node = OF_instance_to_package(stdout); + bzero(type, sizeof(type)); + l = OF_getprop(node, "name", type, sizeof(type)); + if (l == -1 || l >= sizeof(type) - 1) { + printf("WARNING: bad `name' property for stdin\n"); + return; + } + + if (strcmp(type, "keyboard") != 0) { + printf("WARNING: stdin is not a keyboard: %s\n", + type); + return; + } + + node = OF_parent(node); + bzero(type, sizeof(type)); + l = OF_getprop(node, "name", type, sizeof(type)); + if (l == -1 || l >= sizeof(type) - 1) { + printf("WARNING: bad `name' property keyboard " + "parent\n"); + return; + } + + if (strcmp(type, "adb") == 0) { + printf("console keyboard type: ADB\n"); #if NAKBD > 0 - akbd_cnattach(); + akbd_cnattach(); +#else + panic("akbd support not in kernel"); #endif -#if 0 - ukbd_cnattach(); + return; + } + + /* + * We're not an ADB keyboard; must be USB. The parent + * node is pointing at the root hub. We need to traverse + * back until we find the USB controller. + */ + while (strcmp(type, "usb") != 0) { + node = OF_parent(node); + if (node == 0) { + printf("WARNING: unable to find USB " + "controller\n"); + return; + } + bzero(type, sizeof(type)); + l = OF_getprop(node, "name", type, sizeof(type)); + if (l == -1 || l >= sizeof(type) - 1) { + printf("WARNING: bad `name' property " + "searching for USB controller\n"); + return; + } + } + + /* + * `node' is now pointing at the USB controller. + * We must determine the type and location of this + * controller. + */ + if (OF_getprop(node, "class-code", &pciclass, sizeof(pciclass)) + != sizeof(pciclass)) { + printf("WARNING: unable to get PCI class code of " + "USB controller\n"); + return; + } + + /* + * The first address cell of the `reg' property will contain + * bus/device/function information. + */ + if (OF_getprop(node, "reg", ®, sizeof(reg)) <= 0) { + printf("WARNING: unable to get PCI location of " + "USB controller\n"); + return; + } + + if (PCI_CLASS(pciclass) != PCI_CLASS_SERIALBUS) { + printf("WARNING: USB controller is not `serial bus' " + "class\n"); + return; + } + + if (PCI_SUBCLASS(pciclass) != PCI_SUBCLASS_SERIALBUS_USB) { + printf("WARNING: USB controller is not `usb' " + "subclass\n"); + return; + } + + switch (PCI_INTERFACE(pciclass)) { + case PCI_INTERFACE_UHCI: + usbstr = "UHCI"; + break; + + case PCI_INTERFACE_OHCI: + usbstr = "OHCI"; + break; + + default: + printf("WARNING: unknown USB controller interface\n"); + return; + } + + bus = (reg & OFW_PCI_PHYS_HI_BUSMASK) >> + OFW_PCI_PHYS_HI_BUSSHIFT; + device = (reg & OFW_PCI_PHYS_HI_DEVICEMASK) >> + OFW_PCI_PHYS_HI_DEVICESHIFT; + function = (reg & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> + OFW_PCI_PHYS_HI_FUNCTIONSHIFT; + + printf("console keyboard type: USB on %s at %d,%d,%d\n", + usbstr, bus, device, function); + + /* + * Locate the PCI bridge we're on, and create the tag + * for the USB driver. + */ + for (i = 0; i < sizeof(pci_bridges) / sizeof(pci_bridges[0]); + i++) { + if (pci_bridges[i].present && + pci_bridges[i].bus == bus) + break; + } + if (i == sizeof(pci_bridges) / sizeof(pci_bridges[0])) { + printf("WARNING: can't locate USB controller's " + "PCI bridge\n"); + return; + } + + tag = pci_make_tag(pci_bridges[i].pc, bus, device, function); + +#if NUKBD > 0 + /* + * XXX We can't attach the USB keyboard just yet. We + * XXX must defer it until autoconfiguration, because + * XXX the USB code must be able to use memory allocation, + * XXX DMA, etc. + * XXX + * XXX THIS SHOULD BE FIXED SOME DAY! + */ +#else + panic("ukbd support not in kernel"); #endif - ofb_cnattach(); /* XXX error check? */ - return; + + switch (PCI_INTERFACE(pciclass)) { + case PCI_INTERFACE_UHCI: +#if NUHCI > 0 + { + extern void uhci_pci_has_console __P((pcitag_t)); + + uhci_pci_has_console(tag); + } +#else + panic("uhci support not in kernel"); +#endif + break; + + case PCI_INTERFACE_OHCI: +#if NOHCI > 0 + { + extern void ohci_pci_has_console __P((pcitag_t)); + + ohci_pci_has_console(tag); + } +#else + panic("ohci support not in kernel"); +#endif + break; + + default: + panic("cninit: impossible"); + } } -#endif +#endif /* NOFB > 0 */ #if NITE > 0 if (strcmp(type, "display") == 0) {