1 /* $NetBSD: consinit.c,v 1.9 2012/08/10 14:52:26 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.9 2012/08/10 14:52:26 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 void 99 prom_cnprobe(struct consdev *cd) 100 { 101 #if NPCONS > 0 102 extern const struct cdevsw pcons_cdevsw; 103 104 cd->cn_dev = makedev(cdevsw_lookup_major(&pcons_cdevsw), 0); 105 cd->cn_pri = CN_INTERNAL; 106 #endif 107 } 108 109 int 110 prom_cngetc(dev_t dev) 111 { 112 int ch; 113 #ifdef DDB 114 static int nplus = 0; 115 #endif 116 117 ch = prom_getchar(); 118 #ifdef DDB 119 if (ch == '+') { 120 if (nplus++ > 3) Debugger(); 121 } else nplus = 0; 122 #endif 123 return ch; 124 } 125 126 static void 127 prom_cninit(struct consdev *cn) 128 { 129 } 130 131 /* 132 * PROM console output putchar. 133 */ 134 static void 135 prom_cnputc(dev_t dev, int c) 136 { 137 int s; 138 139 s = splhigh(); 140 prom_putchar(c); 141 splx(s); 142 } 143 144 void 145 prom_cnpollc(dev_t dev, int on) 146 { 147 if (on) { 148 /* Entering debugger. */ 149 #if NFB > 0 150 fb_unblank(); 151 #endif 152 } else { 153 /* Resuming kernel. */ 154 } 155 #if NPCONS > 0 156 pcons_cnpollc(dev, on); 157 #endif 158 } 159 160 /*****************************************************************/ 161 162 #ifdef DEBUG 163 #define DBPRINT(x) prom_printf x 164 #else 165 #define DBPRINT(x) 166 #endif 167 168 #ifdef notyet /* PROM_OBP_V2 */ 169 void 170 prom_get_device_args(const char *prop, char *dev, unsigned int dev_sz, 171 char *args, unsigned int args_sz) 172 { 173 char *cp, buffer[128]; 174 175 getpropstringA(prom_findroot(), (char *)prop, buffer, sizeof buffer); 176 177 /* 178 * Extract device-specific arguments from a PROM device path (if any) 179 */ 180 cp = buffer + strlen(buffer); 181 while (cp >= buffer) { 182 if (*cp == ':') { 183 strncpy(args, cp+1, args_sz); 184 *cp = '\0'; 185 strncpy(dev, buffer, dev_sz); 186 break; 187 } 188 cp--; 189 } 190 } 191 #endif /* PROM_OBP_V2 */ 192 193 /* 194 * This function replaces sys/dev/cninit.c 195 * Determine which device is the console using 196 * the PROM "input source" and "output sink". 197 */ 198 void 199 consinit(void) 200 { 201 #ifdef notyet /* PROM_OBP_V2 */ 202 char buffer[128]; 203 #endif /* PROM_OBP_V2 */ 204 const char *consname = "unknown"; 205 #if KGDB 206 #if NZS > 0 207 extern const struct cdevsw zstty_cdevsw; 208 #endif 209 #endif 210 211 DBPRINT(("consinit()\r\n")); 212 if (cn_tab != &consdev_prom) return; 213 214 switch(prom_version()) { 215 #ifdef PROM_OLDMON 216 case PROM_OLDMON: 217 case PROM_OBP_V0: 218 switch(prom_stdin()) { 219 case PROMDEV_KBD: 220 consname = "keyboard/display"; 221 break; 222 case PROMDEV_TTYA: 223 consname = "ttya"; 224 break; 225 case PROMDEV_TTYB: 226 consname = "ttyb"; 227 break; 228 } 229 break; 230 #endif /* PROM_OLDMON */ 231 232 #ifdef notyet /* PROM_OBP_V2 */ 233 case PROM_OBP_V2: 234 case PROM_OBP_V3: 235 case PROM_OPENFIRM: 236 237 /* Save PROM arguments for device matching */ 238 prom_get_device_args("stdin-path", 239 buffer, 240 sizeof(buffer), 241 prom_stdin_args, 242 sizeof(prom_stdin_args)); 243 prom_get_device_args("stdout-path", 244 buffer, 245 sizeof(buffer), 246 prom_stdout_args, 247 sizeof(prom_stdout_args)); 248 249 /* 250 * Translate the STDIO package instance (`ihandle') -- that 251 * the PROM has already opened for us -- to a device tree 252 * node (i.e. a `phandle'). 253 */ 254 DBPRINT(("stdin instance = %x\r\n", prom_stdin())); 255 if ((prom_stdin_node = prom_instance_to_package(prom_stdin())) == 0) { 256 printf("WARNING: no PROM stdin\n"); 257 } 258 DBPRINT(("stdin package = %x\r\n", prom_stdin_node)); 259 260 DBPRINT(("stdout instance = %x\r\n", prom_stdout())); 261 if ((prom_stdout_node = prom_instance_to_package(prom_stdout())) == 0) { 262 printf("WARNING: no PROM stdout\n"); 263 } 264 DBPRINT(("stdout package = %x\r\n", prom_stdout_node)); 265 DBPRINT(("buffer @ %p\r\n", buffer)); 266 267 if (prom_stdin_node && prom_node_has_property(prom_stdin_node, "keyboard")) { 268 #if NKBD == 0 269 printf("cninit: kdb/display not configured\n"); 270 #endif 271 consname = "keyboard/display"; 272 } else if (prom_stdout_node) 273 consname = buffer; 274 #endif /* PROM_OBP_V2 */ 275 } 276 printf("console is %s\n", consname); 277 278 /* Initialize PROM console */ 279 (*cn_tab->cn_probe)(cn_tab); 280 (*cn_tab->cn_init)(cn_tab); 281 282 #ifdef KGDB 283 /* Set up KGDB */ 284 #if NZS > 0 285 if (cdevsw_lookup(kgdb_dev) == &zstty_cdevsw) 286 zs_kgdb_init(); 287 #endif /* NZS > 0 */ 288 #endif /* KGDB */ 289 } 290 291