1 /* $NetBSD: consinit.c,v 1.7 2009/12/27 08:41:50 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 Matthew Fredette 5 * Copyright (c) 1999 Eduardo E. Horvath 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.7 2009/12/27 08:41:50 tsutsui Exp $"); 34 35 #include "opt_ddb.h" 36 #include "opt_kgdb.h" 37 #include "pcons.h" 38 #include "kbd.h" 39 #include "zs.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/conf.h> 44 #include <sys/device.h> 45 #include <sys/file.h> 46 #include <sys/ioctl.h> 47 #include <sys/kernel.h> 48 #include <sys/proc.h> 49 #include <sys/tty.h> 50 #include <sys/time.h> 51 #include <sys/syslog.h> 52 #include <sys/kgdb.h> 53 54 #include <machine/autoconf.h> 55 #include <machine/promlib.h> 56 #include <machine/cpu.h> 57 #include <machine/eeprom.h> 58 #include <machine/psl.h> 59 #include <machine/z8530var.h> 60 61 #include <dev/cons.h> 62 63 #include <sun2/dev/cons.h> 64 65 static void prom_cnprobe(struct consdev *); 66 static void prom_cninit(struct consdev *); 67 int prom_cngetc(dev_t); 68 static void prom_cnputc(dev_t, int); 69 static void prom_cnpollc(dev_t, int); 70 static void prom_cnputc(dev_t, int); 71 72 #ifdef PROM_OBP_V2 73 /* 74 * The following several variables are related to 75 * the configuration process, and are used in initializing 76 * the machine. 77 */ 78 int prom_stdin_node; /* node ID of ROM's console input device */ 79 int prom_stdout_node; /* node ID of ROM's console output device */ 80 char prom_stdin_args[16]; 81 char prom_stdout_args[16]; 82 #endif /* PROM_OBP_V2 */ 83 84 /* 85 * The console is set to this one initially, 86 * which lets us use the PROM until consinit() 87 * is called to select a real console. 88 */ 89 struct consdev consdev_prom = { 90 prom_cnprobe, 91 prom_cninit, 92 prom_cngetc, 93 prom_cnputc, 94 prom_cnpollc, 95 NULL, 96 }; 97 98 /* 99 * The console table pointer is statically initialized 100 * to point to the PROM (output only) table, so that 101 * early calls to printf will work. 102 */ 103 struct consdev *cn_tab = &consdev_prom; 104 105 void 106 prom_cnprobe(struct consdev *cd) 107 { 108 #if NPCONS > 0 109 extern const struct cdevsw pcons_cdevsw; 110 111 cd->cn_dev = makedev(cdevsw_lookup_major(&pcons_cdevsw), 0); 112 cd->cn_pri = CN_INTERNAL; 113 #endif 114 } 115 116 int 117 prom_cngetc(dev_t dev) 118 { 119 int ch; 120 #ifdef DDB 121 static int nplus = 0; 122 #endif 123 124 ch = prom_getchar(); 125 #ifdef DDB 126 if (ch == '+') { 127 if (nplus++ > 3) Debugger(); 128 } else nplus = 0; 129 #endif 130 return ch; 131 } 132 133 static void 134 prom_cninit(struct consdev *cn) 135 { 136 } 137 138 /* 139 * PROM console output putchar. 140 */ 141 static void 142 prom_cnputc(dev_t dev, int c) 143 { 144 int s; 145 146 s = splhigh(); 147 prom_putchar(c); 148 splx(s); 149 } 150 151 void 152 prom_cnpollc(dev_t dev, int on) 153 { 154 if (on) { 155 /* Entering debugger. */ 156 #if NFB > 0 157 fb_unblank(); 158 #endif 159 } else { 160 /* Resuming kernel. */ 161 } 162 #if NPCONS > 0 163 pcons_cnpollc(dev, on); 164 #endif 165 } 166 167 /*****************************************************************/ 168 169 #ifdef DEBUG 170 #define DBPRINT(x) prom_printf x 171 #else 172 #define DBPRINT(x) 173 #endif 174 175 #ifdef notyet /* PROM_OBP_V2 */ 176 void 177 prom_get_device_args(const char *prop, char *dev, unsigned int dev_sz, 178 char *args, unsigned int args_sz) 179 { 180 char *cp, buffer[128]; 181 182 getpropstringA(prom_findroot(), (char *)prop, buffer, sizeof buffer); 183 184 /* 185 * Extract device-specific arguments from a PROM device path (if any) 186 */ 187 cp = buffer + strlen(buffer); 188 while (cp >= buffer) { 189 if (*cp == ':') { 190 strncpy(args, cp+1, args_sz); 191 *cp = '\0'; 192 strncpy(dev, buffer, dev_sz); 193 break; 194 } 195 cp--; 196 } 197 } 198 #endif /* PROM_OBP_V2 */ 199 200 /* 201 * This function replaces sys/dev/cninit.c 202 * Determine which device is the console using 203 * the PROM "input source" and "output sink". 204 */ 205 void 206 consinit(void) 207 { 208 #ifdef notyet /* PROM_OBP_V2 */ 209 char buffer[128]; 210 #endif /* PROM_OBP_V2 */ 211 const char *consname = "unknown"; 212 #if KGDB 213 #if NZS > 0 214 extern const struct cdevsw zstty_cdevsw; 215 #endif 216 #endif 217 218 DBPRINT(("consinit()\r\n")); 219 if (cn_tab != &consdev_prom) return; 220 221 switch(prom_version()) { 222 #ifdef PROM_OLDMON 223 case PROM_OLDMON: 224 case PROM_OBP_V0: 225 switch(prom_stdin()) { 226 case PROMDEV_KBD: 227 consname = "keyboard/display"; 228 break; 229 case PROMDEV_TTYA: 230 consname = "ttya"; 231 break; 232 case PROMDEV_TTYB: 233 consname = "ttyb"; 234 break; 235 } 236 break; 237 #endif /* PROM_OLDMON */ 238 239 #ifdef notyet /* PROM_OBP_V2 */ 240 case PROM_OBP_V2: 241 case PROM_OBP_V3: 242 case PROM_OPENFIRM: 243 244 /* Save PROM arguments for device matching */ 245 prom_get_device_args("stdin-path", 246 buffer, 247 sizeof(buffer), 248 prom_stdin_args, 249 sizeof(prom_stdin_args)); 250 prom_get_device_args("stdout-path", 251 buffer, 252 sizeof(buffer), 253 prom_stdout_args, 254 sizeof(prom_stdout_args)); 255 256 /* 257 * Translate the STDIO package instance (`ihandle') -- that 258 * the PROM has already opened for us -- to a device tree 259 * node (i.e. a `phandle'). 260 */ 261 DBPRINT(("stdin instance = %x\r\n", prom_stdin())); 262 if ((prom_stdin_node = prom_instance_to_package(prom_stdin())) == 0) { 263 printf("WARNING: no PROM stdin\n"); 264 } 265 DBPRINT(("stdin package = %x\r\n", prom_stdin_node)); 266 267 DBPRINT(("stdout instance = %x\r\n", prom_stdout())); 268 if ((prom_stdout_node = prom_instance_to_package(prom_stdout())) == 0) { 269 printf("WARNING: no PROM stdout\n"); 270 } 271 DBPRINT(("stdout package = %x\r\n", prom_stdout_node)); 272 DBPRINT(("buffer @ %p\r\n", buffer)); 273 274 if (prom_stdin_node && prom_node_has_property(prom_stdin_node, "keyboard")) { 275 #if NKBD == 0 276 printf("cninit: kdb/display not configured\n"); 277 #endif 278 consname = "keyboard/display"; 279 } else if (prom_stdout_node) 280 consname = buffer; 281 #endif /* PROM_OBP_V2 */ 282 } 283 printf("console is %s\n", consname); 284 285 /* Initialize PROM console */ 286 (*cn_tab->cn_probe)(cn_tab); 287 (*cn_tab->cn_init)(cn_tab); 288 289 #ifdef KGDB 290 /* Set up KGDB */ 291 #if NZS > 0 292 if (cdevsw_lookup(kgdb_dev) == &zstty_cdevsw) 293 zs_kgdb_init(); 294 #endif /* NZS > 0 */ 295 #endif /* KGDB */ 296 } 297 298