From 680c3ddbd277eb67b4cf4f1ad380c6d745657fea Mon Sep 17 00:00:00 2001 From: thorpej Date: Thu, 6 May 1999 19:24:47 +0000 Subject: [PATCH] Completely rewrite how cninit() determines which keyboard to use with the console. New algorithm: * if stdin == keyboard, and parent of keyboard == adb, use ADB. * else, must be a USB keyboard. Search backwards though the parents until the USB controller is located. Determine its location in the PCI domain, and which type of controller it is, and tell that controller that it has the console input device. The USB code will then attach the first USB keyboard as the console input device during autoconfiguration. The iMac and Blue and White G3 consoles are fully functional now! --- sys/arch/macppc/macppc/machdep.c | 224 ++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 7 deletions(-) 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) {