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