1 1.27 macallan /* $NetBSD: ofw_consinit.c,v 1.27 2022/12/06 01:14:36 macallan Exp $ */ 2 1.2 garbled 3 1.2 garbled /*- 4 1.2 garbled * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 1.2 garbled * All rights reserved. 6 1.2 garbled * 7 1.2 garbled * This code is derived from software contributed to The NetBSD Foundation 8 1.2 garbled * by Tim Rightnour 9 1.2 garbled * 10 1.2 garbled * Redistribution and use in source and binary forms, with or without 11 1.2 garbled * modification, are permitted provided that the following conditions 12 1.2 garbled * are met: 13 1.2 garbled * 1. Redistributions of source code must retain the above copyright 14 1.2 garbled * notice, this list of conditions and the following disclaimer. 15 1.2 garbled * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 garbled * notice, this list of conditions and the following disclaimer in the 17 1.2 garbled * documentation and/or other materials provided with the distribution. 18 1.2 garbled * 19 1.2 garbled * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 garbled * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 garbled * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 garbled * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 garbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 garbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 garbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 garbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 garbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 garbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 garbled * POSSIBILITY OF SUCH DAMAGE. 30 1.2 garbled */ 31 1.2 garbled 32 1.2 garbled #include <sys/cdefs.h> 33 1.27 macallan __KERNEL_RCSID(0, "$NetBSD: ofw_consinit.c,v 1.27 2022/12/06 01:14:36 macallan Exp $"); 34 1.19 rin 35 1.19 rin #include "adb.h" 36 1.19 rin #include "adbkbd.h" 37 1.19 rin #include "akbd.h" 38 1.19 rin #include "isa.h" 39 1.19 rin #include "ofb.h" 40 1.19 rin #include "pckbc.h" 41 1.19 rin #include "ukbd.h" 42 1.19 rin #include "wsdisplay.h" 43 1.19 rin #include "zsc.h" 44 1.19 rin #include "zstty.h" 45 1.2 garbled 46 1.2 garbled #include <sys/param.h> 47 1.2 garbled #include <sys/buf.h> 48 1.2 garbled #include <sys/tty.h> 49 1.2 garbled 50 1.11 uebayasi #include <prop/proplib.h> 51 1.11 uebayasi 52 1.2 garbled #include <machine/autoconf.h> 53 1.2 garbled #include <machine/trap.h> 54 1.12 dyoung #include <sys/bus.h> 55 1.2 garbled 56 1.2 garbled #include <powerpc/ofw_cons.h> 57 1.20 thorpej #include <powerpc/ofw_machdep.h> 58 1.2 garbled 59 1.2 garbled #include <dev/cons.h> 60 1.2 garbled #include <dev/ofw/openfirm.h> 61 1.2 garbled 62 1.2 garbled #include <dev/wscons/wsksymvar.h> 63 1.2 garbled #include <dev/wscons/wscons_callbacks.h> 64 1.2 garbled 65 1.2 garbled #if NZSC > 0 66 1.2 garbled #include <machine/z8530var.h> 67 1.2 garbled #endif 68 1.2 garbled 69 1.2 garbled #if (NADB > 0) 70 1.2 garbled #include <macppc/dev/adbvar.h> 71 1.2 garbled #endif 72 1.2 garbled 73 1.2 garbled #if (NUKBD > 0) 74 1.2 garbled #include <dev/usb/ukbdvar.h> 75 1.2 garbled struct usb_kbd_ihandles { 76 1.2 garbled struct usb_kbd_ihandles *next; 77 1.2 garbled int ihandle; 78 1.2 garbled }; 79 1.2 garbled #endif 80 1.2 garbled 81 1.2 garbled #if (NZSTTY > 0) 82 1.2 garbled #include <dev/ic/z8530reg.h> 83 1.2 garbled extern struct consdev consdev_zs; 84 1.2 garbled #endif 85 1.2 garbled 86 1.2 garbled #if (NPCKBC > 0) 87 1.2 garbled #include <dev/isa/isareg.h> 88 1.2 garbled #include <dev/ic/i8042reg.h> 89 1.2 garbled #include <dev/ic/pckbcvar.h> 90 1.2 garbled #endif 91 1.2 garbled 92 1.26 macallan extern int console_node; 93 1.2 garbled 94 1.24 thorpej int ofkbd_ihandle = -1; 95 1.2 garbled 96 1.24 thorpej static void ofwoea_cnprobe_keyboard(void); 97 1.2 garbled 98 1.2 garbled /*#define OFDEBUG*/ 99 1.2 garbled 100 1.2 garbled #ifdef OFDEBUG 101 1.2 garbled 102 1.2 garbled #define OFPRINTF ofprint 103 1.2 garbled #else 104 1.2 garbled #define OFPRINTF while(0) printf 105 1.2 garbled #endif 106 1.2 garbled 107 1.25 martin bool ofwoea_use_serial_console; 108 1.24 thorpej static struct consdev *selected_serial_consdev; 109 1.24 thorpej 110 1.24 thorpej static int (*selected_keyboard)(void); 111 1.24 thorpej 112 1.24 thorpej /* XXX Gross. */ 113 1.24 thorpej #if NPCKBC > 0 114 1.24 thorpej static int 115 1.24 thorpej ofwoea_pckbd_cnattach(void) 116 1.24 thorpej { 117 1.24 thorpej return pckbc_cnattach(&genppc_isa_io_space_tag, IO_KBD, KBCMDP, 118 1.24 thorpej PCKBC_KBD_SLOT, 0); 119 1.24 thorpej } 120 1.24 thorpej #endif 121 1.24 thorpej 122 1.2 garbled void 123 1.24 thorpej ofwoea_cnprobe(void) 124 1.2 garbled { 125 1.6 garbled char name[32]; 126 1.2 garbled 127 1.2 garbled OFPRINTF("console node: %08x\n", console_node); 128 1.9 kiyohara 129 1.21 thorpej if (console_node == -1) 130 1.24 thorpej return; 131 1.2 garbled 132 1.6 garbled memset(name, 0, sizeof(name)); 133 1.6 garbled if (OF_getprop(console_node, "device_type", name, sizeof(name)) == -1) 134 1.24 thorpej return; 135 1.2 garbled 136 1.6 garbled OFPRINTF("console type: %s\n", name); 137 1.2 garbled 138 1.6 garbled if (strcmp(name, "serial") == 0) { 139 1.25 martin ofwoea_use_serial_console = true; 140 1.3 garbled #ifdef PMAC_G5 141 1.2 garbled /* The MMU hasn't been initialized yet, use failsafe for now */ 142 1.15 chs extern struct consdev failsafe_cons; 143 1.24 thorpej selected_serial_consdev = &failsafe_cons; 144 1.25 martin aprint_verbose("Early G5 console selected " 145 1.25 martin "(keeping OF console for now)\n"); 146 1.3 garbled return; 147 1.3 garbled #endif /* PMAC_G5 */ 148 1.3 garbled 149 1.3 garbled #if (NZSTTY > 0) && !defined(MAMBO) 150 1.2 garbled OF_getprop(console_node, "name", name, sizeof(name)); 151 1.2 garbled if (strcmp(name, "ch-a") == 0 || strcmp(name, "ch-b") == 0) { 152 1.24 thorpej selected_serial_consdev = &consdev_zs; 153 1.2 garbled } 154 1.2 garbled return; 155 1.2 garbled #endif /* NZTTY */ 156 1.2 garbled 157 1.20 thorpej /* fallback to OFW boot console (already set) */ 158 1.2 garbled return; 159 1.2 garbled } 160 1.24 thorpej 161 1.24 thorpej /* 162 1.24 thorpej * We're going to use a display console. Probe for the keyboard 163 1.24 thorpej * we'll use. 164 1.24 thorpej */ 165 1.24 thorpej ofwoea_cnprobe_keyboard(); 166 1.2 garbled } 167 1.2 garbled 168 1.24 thorpej /* 169 1.24 thorpej * XXX This routine is a complete disaster, filled with platform-specific 170 1.24 thorpej * XXX stuff. Fix, plz. 171 1.24 thorpej */ 172 1.2 garbled static void 173 1.24 thorpej ofwoea_cnprobe_keyboard(void) 174 1.2 garbled { 175 1.24 thorpej extern int ofw_stdin; 176 1.24 thorpej 177 1.24 thorpej int node, kstdin = ofw_stdin; 178 1.2 garbled char name[16]; 179 1.2 garbled #if (NAKBD > 0) || (NADBKBD > 0) 180 1.2 garbled int akbd; 181 1.2 garbled #endif 182 1.2 garbled #if NUKBD > 0 183 1.2 garbled struct usb_kbd_ihandles *ukbds; 184 1.2 garbled int ukbd; 185 1.2 garbled #endif 186 1.2 garbled 187 1.2 garbled /* 188 1.2 garbled * We must determine which keyboard type we have. 189 1.2 garbled */ 190 1.3 garbled node = OF_instance_to_package(kstdin); 191 1.2 garbled memset(name, 0, sizeof(name)); 192 1.2 garbled OF_getprop(node, "name", name, sizeof(name)); 193 1.2 garbled if (strcmp(name, "keyboard") != 0) { 194 1.27 macallan ofprint("WARNING: stdin is not a keyboard: %s\n", name); 195 1.2 garbled return; 196 1.2 garbled } 197 1.2 garbled 198 1.2 garbled memset(name, 0, sizeof(name)); 199 1.2 garbled OF_getprop(OF_parent(node), "name", name, sizeof(name)); 200 1.10 kiyohara #if NAKBD > 0 201 1.2 garbled if (strcmp(name, "adb") == 0) { 202 1.27 macallan ofprint("console keyboard type: ADB\n"); 203 1.24 thorpej selected_keyboard = akbd_cnattach; 204 1.2 garbled goto kbd_found; 205 1.2 garbled } 206 1.2 garbled #endif 207 1.2 garbled #if NADBKBD > 0 208 1.2 garbled if (strcmp(name, "adb") == 0) { 209 1.27 macallan ofprint("console keyboard type: ADB\n"); 210 1.24 thorpej selected_keyboard = adbkbd_cnattach; 211 1.2 garbled goto kbd_found; 212 1.2 garbled } 213 1.2 garbled #endif 214 1.2 garbled #if NPCKBC > 0 215 1.10 kiyohara if (strcmp(name, "isa") == 0) { 216 1.27 macallan ofprint("console keyboard type: PC Keyboard\n"); 217 1.24 thorpej selected_keyboard = ofwoea_pckbd_cnattach; 218 1.2 garbled goto kbd_found; 219 1.2 garbled } 220 1.2 garbled #endif 221 1.2 garbled 222 1.2 garbled /* 223 1.2 garbled * It is not obviously an ADB/PC keyboard. Could be USB, 224 1.2 garbled * or ADB on some firmware versions (e.g.: iBook G4) 225 1.2 garbled * This is not enough, we have a few more problems: 226 1.2 garbled * 227 1.2 garbled * (1) The stupid Macintosh firmware uses a 228 1.9 kiyohara * `psuedo-hid' (no typo) or `pseudo-hid', 229 1.9 kiyohara * which apparently merges all keyboards 230 1.9 kiyohara * input into a single input stream. 231 1.9 kiyohara * Because of this, we can't actually 232 1.9 kiyohara * determine which controller or keyboard 233 1.2 garbled * is really the console keyboard! 234 1.2 garbled * 235 1.2 garbled * (2) Even if we could, the keyboard can be USB, 236 1.9 kiyohara * and this requires a lot of the kernel to 237 1.2 garbled * be running in order for it to work. 238 1.2 garbled * 239 1.2 garbled * (3) If the keyboard is behind isa, we don't have enough 240 1.2 garbled * kernel setup to use it yet, so punt to the ofroutines. 241 1.2 garbled * 242 1.2 garbled * So, what we do is this: 243 1.2 garbled * 244 1.2 garbled * (1) First check for OpenFirmware implementation 245 1.9 kiyohara * that will not let us distinguish between 246 1.9 kiyohara * USB and ADB. In that situation, try attaching 247 1.9 kiyohara * anything as we can, and hope things get better 248 1.2 garbled * at autoconfiguration time. 249 1.2 garbled * 250 1.2 garbled * (2) Assume the keyboard is USB. 251 1.2 garbled * Tell the ukbd driver that it is the console. 252 1.2 garbled * At autoconfiguration time, it will attach the 253 1.2 garbled * first USB keyboard instance as the console 254 1.2 garbled * keyboard. 255 1.2 garbled * 256 1.2 garbled * (3) Until then, so that we have _something_, we 257 1.2 garbled * use the OpenFirmware I/O facilities to read 258 1.2 garbled * the keyboard. 259 1.2 garbled */ 260 1.2 garbled 261 1.2 garbled /* 262 1.9 kiyohara * stdin is /pseudo-hid/keyboard. There is no 263 1.2 garbled * `adb-kbd-ihandle or `usb-kbd-ihandles methods 264 1.2 garbled * available. Try attaching as ADB. 265 1.8 macallan * But only if ADB support is actually present. 266 1.2 garbled * 267 1.2 garbled * XXX This must be called before pmap_bootstrap(). 268 1.2 garbled */ 269 1.2 garbled if (strcmp(name, "pseudo-hid") == 0) { 270 1.8 macallan int adb_node; 271 1.8 macallan 272 1.8 macallan adb_node = OF_finddevice("/pci/mac-io/via-pmu/adb"); 273 1.8 macallan if (adb_node > 0) { 274 1.27 macallan ofprint("ADB support found\n"); 275 1.2 garbled #if NAKBD > 0 276 1.24 thorpej selected_keyboard = akbd_cnattach; 277 1.2 garbled #endif 278 1.2 garbled #if NADBKBD > 0 279 1.24 thorpej selected_keyboard = adbkbd_cnattach; 280 1.8 macallan #endif 281 1.8 macallan } else { 282 1.8 macallan /* must be USB */ 283 1.27 macallan ofprint("No ADB support present, assuming USB " 284 1.8 macallan "keyboard\n"); 285 1.8 macallan #if NUKBD > 0 286 1.24 thorpej selected_keyboard = ukbd_cnattach; 287 1.2 garbled #endif 288 1.8 macallan } 289 1.2 garbled goto kbd_found; 290 1.2 garbled } 291 1.2 garbled 292 1.2 garbled /* 293 1.2 garbled * stdin is /psuedo-hid/keyboard. Test `adb-kbd-ihandle and 294 1.2 garbled * `usb-kbd-ihandles to figure out the real keyboard(s). 295 1.2 garbled * 296 1.2 garbled * XXX This must be called before pmap_bootstrap(). 297 1.2 garbled */ 298 1.2 garbled 299 1.2 garbled #if NUKBD > 0 300 1.20 thorpej if (OF_call_method("`usb-kbd-ihandles", kstdin, 0, 1, &ukbds) >= 0 && 301 1.2 garbled ukbds != NULL && ukbds->ihandle != 0 && 302 1.2 garbled OF_instance_to_package(ukbds->ihandle) != -1) { 303 1.27 macallan ofprint("usb-kbd-ihandles matches\n"); 304 1.27 macallan ofprint("console keyboard type: USB\n"); 305 1.24 thorpej selected_keyboard = ukbd_cnattach; 306 1.2 garbled goto kbd_found; 307 1.2 garbled } 308 1.2 garbled /* Try old method name. */ 309 1.3 garbled if (OF_call_method("`usb-kbd-ihandle", kstdin, 0, 1, &ukbd) >= 0 && 310 1.2 garbled ukbd != 0 && 311 1.2 garbled OF_instance_to_package(ukbd) != -1) { 312 1.27 macallan ofprint("usb-kbd-ihandle matches\n"); 313 1.27 macallan ofprint("console keyboard type: USB\n"); 314 1.3 garbled kstdin = ukbd; 315 1.24 thorpej selected_keyboard = ukbd_cnattach; 316 1.2 garbled goto kbd_found; 317 1.2 garbled } 318 1.2 garbled #endif 319 1.2 garbled 320 1.2 garbled #if (NAKBD > 0) || (NADBKBD > 0) 321 1.3 garbled if (OF_call_method("`adb-kbd-ihandle", kstdin, 0, 1, &akbd) >= 0 && 322 1.2 garbled akbd != 0 && 323 1.2 garbled OF_instance_to_package(akbd) != -1) { 324 1.27 macallan ofprint("adb-kbd-ihandle matches\n"); 325 1.27 macallan ofprint("console keyboard type: ADB\n"); 326 1.3 garbled kstdin = akbd; 327 1.2 garbled #if NAKBD > 0 328 1.24 thorpej selected_keyboard = akbd_cnattach; 329 1.2 garbled #endif 330 1.2 garbled #if NADBKBD > 0 331 1.24 thorpej selected_keyboard = adbkbd_cnattach; 332 1.2 garbled #endif 333 1.2 garbled goto kbd_found; 334 1.2 garbled } 335 1.2 garbled #endif 336 1.2 garbled 337 1.2 garbled #if NUKBD > 0 338 1.2 garbled /* 339 1.2 garbled * XXX Old firmware does not have `usb-kbd-ihandles method. Assume 340 1.2 garbled * XXX USB keyboard anyway. 341 1.2 garbled */ 342 1.27 macallan ofprint("defaulting to USB..."); 343 1.27 macallan ofprint("console keyboard type: USB\n"); 344 1.24 thorpej selected_keyboard = ukbd_cnattach; 345 1.2 garbled goto kbd_found; 346 1.2 garbled #endif 347 1.2 garbled 348 1.2 garbled /* 349 1.2 garbled * No keyboard is found. Just return. 350 1.2 garbled */ 351 1.27 macallan ofprint("no console keyboard\n"); 352 1.2 garbled return; 353 1.2 garbled 354 1.24 thorpej kbd_found: 355 1.3 garbled ofkbd_ihandle = kstdin; 356 1.2 garbled } 357 1.2 garbled 358 1.2 garbled /* 359 1.2 garbled * Bootstrap console keyboard routines, using OpenFirmware I/O. 360 1.2 garbled */ 361 1.2 garbled int 362 1.2 garbled ofkbd_cngetc(dev_t dev) 363 1.2 garbled { 364 1.2 garbled u_char c = '\0'; 365 1.2 garbled int len; 366 1.2 garbled 367 1.24 thorpej KASSERT(ofkbd_ihandle != -1); 368 1.24 thorpej 369 1.2 garbled do { 370 1.2 garbled len = OF_read(ofkbd_ihandle, &c, 1); 371 1.2 garbled } while (len != 1); 372 1.2 garbled 373 1.2 garbled return c; 374 1.2 garbled } 375 1.2 garbled 376 1.2 garbled void 377 1.24 thorpej cninit(void) 378 1.24 thorpej { 379 1.25 martin if (ofwoea_use_serial_console) { 380 1.24 thorpej if (selected_serial_consdev != NULL) { 381 1.24 thorpej cn_tab = selected_serial_consdev; 382 1.24 thorpej (*cn_tab->cn_probe)(cn_tab); 383 1.24 thorpej (*cn_tab->cn_init)(cn_tab); 384 1.24 thorpej } 385 1.24 thorpej return; 386 1.24 thorpej } 387 1.24 thorpej 388 1.24 thorpej #if NWSDISPLAY > 0 389 1.24 thorpej rascons_cnattach(); 390 1.24 thorpej #endif 391 1.24 thorpej if (selected_keyboard != NULL) { 392 1.24 thorpej (*selected_keyboard)(); 393 1.24 thorpej 394 1.24 thorpej #if NWSDISPLAY > 0 395 1.24 thorpej /* 396 1.24 thorpej * XXX This is a little gross, but we don't get to call 397 1.24 thorpej * XXX wskbd_cnattach() twice. 398 1.24 thorpej */ 399 1.24 thorpej wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL); 400 1.24 thorpej #endif 401 1.24 thorpej } 402 1.24 thorpej } 403 1.24 thorpej 404 1.24 thorpej void 405 1.2 garbled ofwoea_consinit(void) 406 1.2 garbled { 407 1.2 garbled static int initted = 0; 408 1.2 garbled 409 1.2 garbled if (initted) 410 1.2 garbled return; 411 1.2 garbled 412 1.2 garbled initted = 1; 413 1.2 garbled cninit(); 414 1.2 garbled } 415