xref: /netbsd/sys/arch/sun2/dev/kd.c (revision ae1f6b9e)
1*ae1f6b9eSfredette /*	$NetBSD: kd.c,v 1.1 2002/03/22 00:22:44 fredette Exp $	*/
2*ae1f6b9eSfredette 
3*ae1f6b9eSfredette /*-
4*ae1f6b9eSfredette  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5*ae1f6b9eSfredette  * All rights reserved.
6*ae1f6b9eSfredette  *
7*ae1f6b9eSfredette  * This code is derived from software contributed to The NetBSD Foundation
8*ae1f6b9eSfredette  * by Gordon W. Ross.
9*ae1f6b9eSfredette  *
10*ae1f6b9eSfredette  * Redistribution and use in source and binary forms, with or without
11*ae1f6b9eSfredette  * modification, are permitted provided that the following conditions
12*ae1f6b9eSfredette  * are met:
13*ae1f6b9eSfredette  * 1. Redistributions of source code must retain the above copyright
14*ae1f6b9eSfredette  *    notice, this list of conditions and the following disclaimer.
15*ae1f6b9eSfredette  * 2. Redistributions in binary form must reproduce the above copyright
16*ae1f6b9eSfredette  *    notice, this list of conditions and the following disclaimer in the
17*ae1f6b9eSfredette  *    documentation and/or other materials provided with the distribution.
18*ae1f6b9eSfredette  * 3. All advertising materials mentioning features or use of this software
19*ae1f6b9eSfredette  *    must display the following acknowledgement:
20*ae1f6b9eSfredette  *        This product includes software developed by the NetBSD
21*ae1f6b9eSfredette  *        Foundation, Inc. and its contributors.
22*ae1f6b9eSfredette  * 4. Neither the name of The NetBSD Foundation nor the names of its
23*ae1f6b9eSfredette  *    contributors may be used to endorse or promote products derived
24*ae1f6b9eSfredette  *    from this software without specific prior written permission.
25*ae1f6b9eSfredette  *
26*ae1f6b9eSfredette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27*ae1f6b9eSfredette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28*ae1f6b9eSfredette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29*ae1f6b9eSfredette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30*ae1f6b9eSfredette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31*ae1f6b9eSfredette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32*ae1f6b9eSfredette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33*ae1f6b9eSfredette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34*ae1f6b9eSfredette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35*ae1f6b9eSfredette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36*ae1f6b9eSfredette  * POSSIBILITY OF SUCH DAMAGE.
37*ae1f6b9eSfredette  */
38*ae1f6b9eSfredette 
39*ae1f6b9eSfredette /*
40*ae1f6b9eSfredette  * Keyboard/Display device.
41*ae1f6b9eSfredette  *
42*ae1f6b9eSfredette  * This driver exists simply to provide a tty device that
43*ae1f6b9eSfredette  * the indirect console driver can point to.
44*ae1f6b9eSfredette  * The kbd driver sends its input here.
45*ae1f6b9eSfredette  * Output goes to the screen via PROM printf.
46*ae1f6b9eSfredette  */
47*ae1f6b9eSfredette 
48*ae1f6b9eSfredette #include <sys/param.h>
49*ae1f6b9eSfredette #include <sys/proc.h>
50*ae1f6b9eSfredette #include <sys/systm.h>
51*ae1f6b9eSfredette #include <sys/ioctl.h>
52*ae1f6b9eSfredette #include <sys/tty.h>
53*ae1f6b9eSfredette #include <sys/file.h>
54*ae1f6b9eSfredette #include <sys/conf.h>
55*ae1f6b9eSfredette #include <sys/device.h>
56*ae1f6b9eSfredette 
57*ae1f6b9eSfredette #include <machine/promlib.h>
58*ae1f6b9eSfredette #include <machine/eeprom.h>
59*ae1f6b9eSfredette #include <machine/psl.h>
60*ae1f6b9eSfredette #include <machine/cpu.h>
61*ae1f6b9eSfredette #include <machine/kbd.h>
62*ae1f6b9eSfredette #include <machine/autoconf.h>
63*ae1f6b9eSfredette #include <machine/conf.h>
64*ae1f6b9eSfredette 
65*ae1f6b9eSfredette #ifdef RASTERCONSOLE
66*ae1f6b9eSfredette #include <dev/sun/fbio.h>
67*ae1f6b9eSfredette #include <machine/fbvar.h>
68*ae1f6b9eSfredette #endif
69*ae1f6b9eSfredette 
70*ae1f6b9eSfredette 
71*ae1f6b9eSfredette #include <dev/cons.h>
72*ae1f6b9eSfredette #include <dev/sun/event_var.h>
73*ae1f6b9eSfredette #include <dev/sun/kbd_xlate.h>
74*ae1f6b9eSfredette #include <dev/sun/kbdvar.h>
75*ae1f6b9eSfredette #include <sun2/dev/cons.h>
76*ae1f6b9eSfredette 
77*ae1f6b9eSfredette struct	tty *fbconstty = 0;	/* tty structure for frame buffer console */
78*ae1f6b9eSfredette 
79*ae1f6b9eSfredette #define	KDMAJOR 1
80*ae1f6b9eSfredette #define PUT_WSIZE	64
81*ae1f6b9eSfredette 
82*ae1f6b9eSfredette struct kd_softc {
83*ae1f6b9eSfredette 	struct	device kd_dev;		/* required first: base device */
84*ae1f6b9eSfredette 	struct  tty *kd_tty;
85*ae1f6b9eSfredette 	int rows, cols;
86*ae1f6b9eSfredette 
87*ae1f6b9eSfredette 	/* Console input hook */
88*ae1f6b9eSfredette 	struct cons_channel *kd_in;
89*ae1f6b9eSfredette };
90*ae1f6b9eSfredette 
91*ae1f6b9eSfredette /*
92*ae1f6b9eSfredette  * There is no point in pretending there might be
93*ae1f6b9eSfredette  * more than one keyboard/display device.
94*ae1f6b9eSfredette  */
95*ae1f6b9eSfredette static struct kd_softc kd_softc;
96*ae1f6b9eSfredette static int kd_is_console;
97*ae1f6b9eSfredette 
98*ae1f6b9eSfredette static int kdparam(struct tty *, struct termios *);
99*ae1f6b9eSfredette static void kdstart(struct tty *);
100*ae1f6b9eSfredette static void kd_init __P((struct kd_softc *));
101*ae1f6b9eSfredette static void kd_cons_input __P((int));
102*ae1f6b9eSfredette static int  kdcngetc __P((dev_t));
103*ae1f6b9eSfredette 
104*ae1f6b9eSfredette int	cons_ocount;		/* output byte count */
105*ae1f6b9eSfredette 
106*ae1f6b9eSfredette /*
107*ae1f6b9eSfredette  * This is called by kbd_attach()
108*ae1f6b9eSfredette  * XXX - Make this a proper child of kbd?
109*ae1f6b9eSfredette  */
110*ae1f6b9eSfredette void
111*ae1f6b9eSfredette kd_init(kd)
112*ae1f6b9eSfredette 	struct kd_softc *kd;
113*ae1f6b9eSfredette {
114*ae1f6b9eSfredette 	struct tty *tp;
115*ae1f6b9eSfredette #ifdef	PROM_OLDMON
116*ae1f6b9eSfredette 	struct eeprom *ep;
117*ae1f6b9eSfredette #endif
118*ae1f6b9eSfredette #ifdef	notyet /* PROM_OBP_V2 */
119*ae1f6b9eSfredette 	int i;
120*ae1f6b9eSfredette 	char *prop;
121*ae1f6b9eSfredette #endif
122*ae1f6b9eSfredette 
123*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
124*ae1f6b9eSfredette 
125*ae1f6b9eSfredette 	tp = ttymalloc();
126*ae1f6b9eSfredette 	tp->t_oproc = kdstart;
127*ae1f6b9eSfredette 	tp->t_param = kdparam;
128*ae1f6b9eSfredette 	tp->t_dev = makedev(KDMAJOR, 0);
129*ae1f6b9eSfredette 
130*ae1f6b9eSfredette 	tty_attach(tp);
131*ae1f6b9eSfredette 	kd->kd_tty = tp;
132*ae1f6b9eSfredette 
133*ae1f6b9eSfredette 	/*
134*ae1f6b9eSfredette 	 * get the console struct winsize.
135*ae1f6b9eSfredette 	 */
136*ae1f6b9eSfredette 	if (kd_is_console) {
137*ae1f6b9eSfredette 		fbconstty = tp;
138*ae1f6b9eSfredette #ifdef RASTERCONSOLE
139*ae1f6b9eSfredette 		kd->rows = fbrcons_rows();
140*ae1f6b9eSfredette 		kd->cols = fbrcons_cols();
141*ae1f6b9eSfredette 		rcons_ttyinit(tp);
142*ae1f6b9eSfredette #endif
143*ae1f6b9eSfredette 	}
144*ae1f6b9eSfredette 
145*ae1f6b9eSfredette 	/* else, consult the PROM */
146*ae1f6b9eSfredette 	switch (prom_version()) {
147*ae1f6b9eSfredette #ifdef	PROM_OLDMON
148*ae1f6b9eSfredette 	case PROM_OLDMON:
149*ae1f6b9eSfredette 		if ((ep = (struct eeprom *)eeprom_va) == NULL)
150*ae1f6b9eSfredette 			break;
151*ae1f6b9eSfredette 		if (kd->rows == 0)
152*ae1f6b9eSfredette 			kd->rows = (u_short)ep->eeTtyRows;
153*ae1f6b9eSfredette 		if (kd->cols == 0)
154*ae1f6b9eSfredette 			kd->cols = (u_short)ep->eeTtyCols;
155*ae1f6b9eSfredette 		break;
156*ae1f6b9eSfredette #endif	/* PROM_OLDMON */
157*ae1f6b9eSfredette #ifdef	notyet /* PROM_OBP_V2 */
158*ae1f6b9eSfredette 	case PROM_OBP_V0:
159*ae1f6b9eSfredette 	case PROM_OBP_V2:
160*ae1f6b9eSfredette 	case PROM_OBP_V3:
161*ae1f6b9eSfredette 	case PROM_OPENFIRM:
162*ae1f6b9eSfredette 
163*ae1f6b9eSfredette 		if (kd->rows == 0 &&
164*ae1f6b9eSfredette 		    (prop = PROM_getpropstring(optionsnode, "screen-#rows"))) {
165*ae1f6b9eSfredette 			i = 0;
166*ae1f6b9eSfredette 			while (*prop != '\0')
167*ae1f6b9eSfredette 				i = i * 10 + *prop++ - '0';
168*ae1f6b9eSfredette 			kd->rows = (unsigned short)i;
169*ae1f6b9eSfredette 		}
170*ae1f6b9eSfredette 		if (kd->cols == 0 &&
171*ae1f6b9eSfredette 		    (prop = PROM_getpropstring(optionsnode, "screen-#columns"))) {
172*ae1f6b9eSfredette 			i = 0;
173*ae1f6b9eSfredette 			while (*prop != '\0')
174*ae1f6b9eSfredette 				i = i * 10 + *prop++ - '0';
175*ae1f6b9eSfredette 			kd->cols = (unsigned short)i;
176*ae1f6b9eSfredette 		}
177*ae1f6b9eSfredette 		break;
178*ae1f6b9eSfredette #endif	/* PROM_OBP_V2 */
179*ae1f6b9eSfredette 	}
180*ae1f6b9eSfredette 	return;
181*ae1f6b9eSfredette }
182*ae1f6b9eSfredette 
183*ae1f6b9eSfredette struct tty *
184*ae1f6b9eSfredette kdtty(dev)
185*ae1f6b9eSfredette 	dev_t dev;
186*ae1f6b9eSfredette {
187*ae1f6b9eSfredette 	struct kd_softc *kd;
188*ae1f6b9eSfredette 
189*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
190*ae1f6b9eSfredette 	return (kd->kd_tty);
191*ae1f6b9eSfredette }
192*ae1f6b9eSfredette 
193*ae1f6b9eSfredette int
194*ae1f6b9eSfredette kdopen(dev, flag, mode, p)
195*ae1f6b9eSfredette 	dev_t dev;
196*ae1f6b9eSfredette 	int flag, mode;
197*ae1f6b9eSfredette 	struct proc *p;
198*ae1f6b9eSfredette {
199*ae1f6b9eSfredette 	struct kd_softc *kd;
200*ae1f6b9eSfredette 	int error, s, unit;
201*ae1f6b9eSfredette 	struct tty *tp;
202*ae1f6b9eSfredette static	int firstopen = 1;
203*ae1f6b9eSfredette 
204*ae1f6b9eSfredette 	unit = minor(dev);
205*ae1f6b9eSfredette 	if (unit != 0)
206*ae1f6b9eSfredette 		return ENXIO;
207*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
208*ae1f6b9eSfredette 
209*ae1f6b9eSfredette 	if (firstopen) {
210*ae1f6b9eSfredette 		kd_init(kd);
211*ae1f6b9eSfredette 		firstopen = 0;
212*ae1f6b9eSfredette 	}
213*ae1f6b9eSfredette 	tp = kd->kd_tty;
214*ae1f6b9eSfredette 
215*ae1f6b9eSfredette 	/* It's simpler to do this up here. */
216*ae1f6b9eSfredette 	if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE))
217*ae1f6b9eSfredette 	     ==             (TS_ISOPEN | TS_XCLUDE))
218*ae1f6b9eSfredette 	    && (p->p_ucred->cr_uid != 0) )
219*ae1f6b9eSfredette 	{
220*ae1f6b9eSfredette 		return (EBUSY);
221*ae1f6b9eSfredette 	}
222*ae1f6b9eSfredette 
223*ae1f6b9eSfredette 	s = spltty();
224*ae1f6b9eSfredette 
225*ae1f6b9eSfredette 	if ((tp->t_state & TS_ISOPEN) == 0) {
226*ae1f6b9eSfredette 		/* First open. */
227*ae1f6b9eSfredette 
228*ae1f6b9eSfredette 		/* Notify the input device that serves us */
229*ae1f6b9eSfredette 		struct cons_channel *cc = kd->kd_in;
230*ae1f6b9eSfredette 		if (cc != NULL &&
231*ae1f6b9eSfredette 		    (error = (*cc->cc_iopen)(cc)) != 0) {
232*ae1f6b9eSfredette 			splx(s);
233*ae1f6b9eSfredette 			return (error);
234*ae1f6b9eSfredette 		}
235*ae1f6b9eSfredette 
236*ae1f6b9eSfredette 		ttychars(tp);
237*ae1f6b9eSfredette 		tp->t_iflag = TTYDEF_IFLAG;
238*ae1f6b9eSfredette 		tp->t_oflag = TTYDEF_OFLAG;
239*ae1f6b9eSfredette 		tp->t_cflag = TTYDEF_CFLAG;
240*ae1f6b9eSfredette 		tp->t_lflag = TTYDEF_LFLAG;
241*ae1f6b9eSfredette 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
242*ae1f6b9eSfredette 		(void) kdparam(tp, &tp->t_termios);
243*ae1f6b9eSfredette 		ttsetwater(tp);
244*ae1f6b9eSfredette 		tp->t_winsize.ws_row = kd->rows;
245*ae1f6b9eSfredette 		tp->t_winsize.ws_col = kd->cols;
246*ae1f6b9eSfredette 		/* Flush pending input?  Clear translator? */
247*ae1f6b9eSfredette 		/* This (pseudo)device always has SOFTCAR */
248*ae1f6b9eSfredette 		tp->t_state |= TS_CARR_ON;
249*ae1f6b9eSfredette 	}
250*ae1f6b9eSfredette 
251*ae1f6b9eSfredette 	splx(s);
252*ae1f6b9eSfredette 
253*ae1f6b9eSfredette 	return ((*tp->t_linesw->l_open)(dev, tp));
254*ae1f6b9eSfredette }
255*ae1f6b9eSfredette 
256*ae1f6b9eSfredette int
257*ae1f6b9eSfredette kdclose(dev, flag, mode, p)
258*ae1f6b9eSfredette 	dev_t dev;
259*ae1f6b9eSfredette 	int flag, mode;
260*ae1f6b9eSfredette 	struct proc *p;
261*ae1f6b9eSfredette {
262*ae1f6b9eSfredette 	struct kd_softc *kd;
263*ae1f6b9eSfredette 	struct tty *tp;
264*ae1f6b9eSfredette 	struct cons_channel *cc;
265*ae1f6b9eSfredette 
266*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
267*ae1f6b9eSfredette 	tp = kd->kd_tty;
268*ae1f6b9eSfredette 
269*ae1f6b9eSfredette 	/* XXX This is for cons.c. */
270*ae1f6b9eSfredette 	if ((tp->t_state & TS_ISOPEN) == 0)
271*ae1f6b9eSfredette 		return 0;
272*ae1f6b9eSfredette 
273*ae1f6b9eSfredette 	(*tp->t_linesw->l_close)(tp, flag);
274*ae1f6b9eSfredette 	ttyclose(tp);
275*ae1f6b9eSfredette 
276*ae1f6b9eSfredette 	if ((cc = kd->kd_in) != NULL)
277*ae1f6b9eSfredette 		(void)(*cc->cc_iclose)(cc->cc_dev);
278*ae1f6b9eSfredette 
279*ae1f6b9eSfredette 	return (0);
280*ae1f6b9eSfredette }
281*ae1f6b9eSfredette 
282*ae1f6b9eSfredette int
283*ae1f6b9eSfredette kdread(dev, uio, flag)
284*ae1f6b9eSfredette 	dev_t dev;
285*ae1f6b9eSfredette 	struct uio *uio;
286*ae1f6b9eSfredette 	int flag;
287*ae1f6b9eSfredette {
288*ae1f6b9eSfredette 	struct kd_softc *kd;
289*ae1f6b9eSfredette 	struct tty *tp;
290*ae1f6b9eSfredette 
291*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
292*ae1f6b9eSfredette 	tp = kd->kd_tty;
293*ae1f6b9eSfredette 
294*ae1f6b9eSfredette 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
295*ae1f6b9eSfredette }
296*ae1f6b9eSfredette 
297*ae1f6b9eSfredette int
298*ae1f6b9eSfredette kdwrite(dev, uio, flag)
299*ae1f6b9eSfredette 	dev_t dev;
300*ae1f6b9eSfredette 	struct uio *uio;
301*ae1f6b9eSfredette 	int flag;
302*ae1f6b9eSfredette {
303*ae1f6b9eSfredette 	struct kd_softc *kd;
304*ae1f6b9eSfredette 	struct tty *tp;
305*ae1f6b9eSfredette 
306*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
307*ae1f6b9eSfredette 	tp = kd->kd_tty;
308*ae1f6b9eSfredette 
309*ae1f6b9eSfredette 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
310*ae1f6b9eSfredette }
311*ae1f6b9eSfredette 
312*ae1f6b9eSfredette int
313*ae1f6b9eSfredette kdpoll(dev, events, p)
314*ae1f6b9eSfredette 	dev_t dev;
315*ae1f6b9eSfredette 	int events;
316*ae1f6b9eSfredette 	struct proc *p;
317*ae1f6b9eSfredette {
318*ae1f6b9eSfredette 	struct kd_softc *kd;
319*ae1f6b9eSfredette 	struct tty *tp;
320*ae1f6b9eSfredette 
321*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
322*ae1f6b9eSfredette 	tp = kd->kd_tty;
323*ae1f6b9eSfredette 
324*ae1f6b9eSfredette 	return ((*tp->t_linesw->l_poll)(tp, events, p));
325*ae1f6b9eSfredette }
326*ae1f6b9eSfredette 
327*ae1f6b9eSfredette int
328*ae1f6b9eSfredette kdioctl(dev, cmd, data, flag, p)
329*ae1f6b9eSfredette 	dev_t dev;
330*ae1f6b9eSfredette 	u_long cmd;
331*ae1f6b9eSfredette 	caddr_t data;
332*ae1f6b9eSfredette 	int flag;
333*ae1f6b9eSfredette 	struct proc *p;
334*ae1f6b9eSfredette {
335*ae1f6b9eSfredette 	struct kd_softc *kd;
336*ae1f6b9eSfredette 	struct tty *tp;
337*ae1f6b9eSfredette 	int error;
338*ae1f6b9eSfredette 
339*ae1f6b9eSfredette 	kd = &kd_softc; 	/* XXX */
340*ae1f6b9eSfredette 	tp = kd->kd_tty;
341*ae1f6b9eSfredette 
342*ae1f6b9eSfredette 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
343*ae1f6b9eSfredette 	if (error != EPASSTHROUGH)
344*ae1f6b9eSfredette 		return error;
345*ae1f6b9eSfredette 
346*ae1f6b9eSfredette 	error = ttioctl(tp, cmd, data, flag, p);
347*ae1f6b9eSfredette 	if (error != EPASSTHROUGH)
348*ae1f6b9eSfredette 		return error;
349*ae1f6b9eSfredette 
350*ae1f6b9eSfredette 	/* Handle any ioctl commands specific to kbd/display. */
351*ae1f6b9eSfredette 	/* XXX - Send KB* ioctls to kbd module? */
352*ae1f6b9eSfredette 	/* XXX - Send FB* ioctls to fb module?  */
353*ae1f6b9eSfredette 
354*ae1f6b9eSfredette 	return EPASSTHROUGH;
355*ae1f6b9eSfredette }
356*ae1f6b9eSfredette 
357*ae1f6b9eSfredette void
358*ae1f6b9eSfredette kdstop(tp, flag)
359*ae1f6b9eSfredette 	struct tty *tp;
360*ae1f6b9eSfredette 	int flag;
361*ae1f6b9eSfredette {
362*ae1f6b9eSfredette 
363*ae1f6b9eSfredette }
364*ae1f6b9eSfredette 
365*ae1f6b9eSfredette 
366*ae1f6b9eSfredette static int
367*ae1f6b9eSfredette kdparam(tp, t)
368*ae1f6b9eSfredette 	struct tty *tp;
369*ae1f6b9eSfredette 	struct termios *t;
370*ae1f6b9eSfredette {
371*ae1f6b9eSfredette 	/* XXX - These are ignored... */
372*ae1f6b9eSfredette 	tp->t_ispeed = t->c_ispeed;
373*ae1f6b9eSfredette 	tp->t_ospeed = t->c_ospeed;
374*ae1f6b9eSfredette 	tp->t_cflag = t->c_cflag;
375*ae1f6b9eSfredette 	return 0;
376*ae1f6b9eSfredette }
377*ae1f6b9eSfredette 
378*ae1f6b9eSfredette 
379*ae1f6b9eSfredette static void kd_later(void*);
380*ae1f6b9eSfredette static void kd_putfb(struct tty *);
381*ae1f6b9eSfredette 
382*ae1f6b9eSfredette static void
383*ae1f6b9eSfredette kdstart(tp)
384*ae1f6b9eSfredette 	struct tty *tp;
385*ae1f6b9eSfredette {
386*ae1f6b9eSfredette 	struct clist *cl;
387*ae1f6b9eSfredette 	register int s;
388*ae1f6b9eSfredette 
389*ae1f6b9eSfredette 	s = spltty();
390*ae1f6b9eSfredette 	if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT))
391*ae1f6b9eSfredette 		goto out;
392*ae1f6b9eSfredette 
393*ae1f6b9eSfredette 	cl = &tp->t_outq;
394*ae1f6b9eSfredette 	if (cl->c_cc) {
395*ae1f6b9eSfredette 		if (kd_is_console) {
396*ae1f6b9eSfredette 			tp->t_state |= TS_BUSY;
397*ae1f6b9eSfredette 			if (is_spl0(s)) {
398*ae1f6b9eSfredette 				/* called at level zero - update screen now. */
399*ae1f6b9eSfredette 				(void) spllowersoftclock();
400*ae1f6b9eSfredette 				kd_putfb(tp);
401*ae1f6b9eSfredette 				(void) spltty();
402*ae1f6b9eSfredette 				tp->t_state &= ~TS_BUSY;
403*ae1f6b9eSfredette 			} else {
404*ae1f6b9eSfredette 				/* called at interrupt level - do it later */
405*ae1f6b9eSfredette 				callout_reset(&tp->t_rstrt_ch, 0,
406*ae1f6b9eSfredette 				    kd_later, tp);
407*ae1f6b9eSfredette 			}
408*ae1f6b9eSfredette 		} else {
409*ae1f6b9eSfredette 			/*
410*ae1f6b9eSfredette 			 * This driver uses the PROM for writing the screen,
411*ae1f6b9eSfredette 			 * and that only works if this is the console device.
412*ae1f6b9eSfredette 			 * If this is not the console, just flush the output.
413*ae1f6b9eSfredette 			 * Sorry.  (In that case, use xdm instead of getty.)
414*ae1f6b9eSfredette 			 */
415*ae1f6b9eSfredette 			ndflush(cl, cl->c_cc);
416*ae1f6b9eSfredette 		}
417*ae1f6b9eSfredette 	}
418*ae1f6b9eSfredette 	if (cl->c_cc <= tp->t_lowat) {
419*ae1f6b9eSfredette 		if (tp->t_state & TS_ASLEEP) {
420*ae1f6b9eSfredette 			tp->t_state &= ~TS_ASLEEP;
421*ae1f6b9eSfredette 			wakeup((caddr_t)cl);
422*ae1f6b9eSfredette 		}
423*ae1f6b9eSfredette 		selwakeup(&tp->t_wsel);
424*ae1f6b9eSfredette 	}
425*ae1f6b9eSfredette out:
426*ae1f6b9eSfredette 	splx(s);
427*ae1f6b9eSfredette }
428*ae1f6b9eSfredette 
429*ae1f6b9eSfredette /*
430*ae1f6b9eSfredette  * Timeout function to do delayed writes to the screen.
431*ae1f6b9eSfredette  * Called at splsoftclock when requested by kdstart.
432*ae1f6b9eSfredette  */
433*ae1f6b9eSfredette static void
434*ae1f6b9eSfredette kd_later(tpaddr)
435*ae1f6b9eSfredette 	void *tpaddr;
436*ae1f6b9eSfredette {
437*ae1f6b9eSfredette 	struct tty *tp = tpaddr;
438*ae1f6b9eSfredette 	register int s;
439*ae1f6b9eSfredette 
440*ae1f6b9eSfredette 	kd_putfb(tp);
441*ae1f6b9eSfredette 
442*ae1f6b9eSfredette 	s = spltty();
443*ae1f6b9eSfredette 	tp->t_state &= ~TS_BUSY;
444*ae1f6b9eSfredette 	(*tp->t_linesw->l_start)(tp);
445*ae1f6b9eSfredette 	splx(s);
446*ae1f6b9eSfredette }
447*ae1f6b9eSfredette 
448*ae1f6b9eSfredette /*
449*ae1f6b9eSfredette  * Put text on the screen using the PROM monitor.
450*ae1f6b9eSfredette  * This can take a while, so to avoid missing
451*ae1f6b9eSfredette  * interrupts, this is called at splsoftclock.
452*ae1f6b9eSfredette  */
453*ae1f6b9eSfredette static void
454*ae1f6b9eSfredette kd_putfb(tp)
455*ae1f6b9eSfredette 	struct tty *tp;
456*ae1f6b9eSfredette {
457*ae1f6b9eSfredette 	char buf[PUT_WSIZE];
458*ae1f6b9eSfredette 	struct clist *cl = &tp->t_outq;
459*ae1f6b9eSfredette 	char *p, *end;
460*ae1f6b9eSfredette 	int len;
461*ae1f6b9eSfredette 
462*ae1f6b9eSfredette 	while ((len = q_to_b(cl, buf, PUT_WSIZE-1)) > 0) {
463*ae1f6b9eSfredette 		/* PROM will barf if high bits are set. */
464*ae1f6b9eSfredette 		p = buf;
465*ae1f6b9eSfredette 		end = buf + len;
466*ae1f6b9eSfredette 		while (p < end)
467*ae1f6b9eSfredette 			*p++ &= 0x7f;
468*ae1f6b9eSfredette 		/* Now let the PROM print it. */
469*ae1f6b9eSfredette 		prom_putstr(buf, len);
470*ae1f6b9eSfredette 	}
471*ae1f6b9eSfredette }
472*ae1f6b9eSfredette 
473*ae1f6b9eSfredette /*
474*ae1f6b9eSfredette  * Default PROM-based console input stream
475*ae1f6b9eSfredette  */
476*ae1f6b9eSfredette static int kd_rom_iopen __P((struct cons_channel *));
477*ae1f6b9eSfredette static int kd_rom_iclose __P((struct cons_channel *));
478*ae1f6b9eSfredette 
479*ae1f6b9eSfredette static struct cons_channel prom_cons_channel;
480*ae1f6b9eSfredette 
481*ae1f6b9eSfredette int
482*ae1f6b9eSfredette kd_rom_iopen(cc)
483*ae1f6b9eSfredette 	struct cons_channel *cc;
484*ae1f6b9eSfredette {
485*ae1f6b9eSfredette 	return (0);
486*ae1f6b9eSfredette }
487*ae1f6b9eSfredette 
488*ae1f6b9eSfredette int
489*ae1f6b9eSfredette kd_rom_iclose(cc)
490*ae1f6b9eSfredette 	struct cons_channel *cc;
491*ae1f6b9eSfredette {
492*ae1f6b9eSfredette 	return (0);
493*ae1f6b9eSfredette }
494*ae1f6b9eSfredette 
495*ae1f6b9eSfredette /*
496*ae1f6b9eSfredette  * Our "interrupt" routine for input. This is called by
497*ae1f6b9eSfredette  * the keyboard driver (dev/sun/kbd.c) at spltty.
498*ae1f6b9eSfredette  */
499*ae1f6b9eSfredette void
500*ae1f6b9eSfredette kd_cons_input(c)
501*ae1f6b9eSfredette 	int c;
502*ae1f6b9eSfredette {
503*ae1f6b9eSfredette 	struct kd_softc *kd = &kd_softc;
504*ae1f6b9eSfredette 	struct tty *tp;
505*ae1f6b9eSfredette 
506*ae1f6b9eSfredette 	/* XXX: Make sure the device is open. */
507*ae1f6b9eSfredette 	tp = kd->kd_tty;
508*ae1f6b9eSfredette 	if (tp == NULL)
509*ae1f6b9eSfredette 		return;
510*ae1f6b9eSfredette 	if ((tp->t_state & TS_ISOPEN) == 0)
511*ae1f6b9eSfredette 		return;
512*ae1f6b9eSfredette 
513*ae1f6b9eSfredette 	(*tp->t_linesw->l_rint)(c, tp);
514*ae1f6b9eSfredette }
515*ae1f6b9eSfredette 
516*ae1f6b9eSfredette 
517*ae1f6b9eSfredette /****************************************************************
518*ae1f6b9eSfredette  * kd console support
519*ae1f6b9eSfredette  ****************************************************************/
520*ae1f6b9eSfredette 
521*ae1f6b9eSfredette /* The debugger gets its own key translation state. */
522*ae1f6b9eSfredette static struct kbd_state *kdcn_state;
523*ae1f6b9eSfredette 
524*ae1f6b9eSfredette static void kdcnprobe __P((struct consdev *));
525*ae1f6b9eSfredette static void kdcninit __P((struct consdev *));
526*ae1f6b9eSfredette static void kdcnputc __P((dev_t, int));
527*ae1f6b9eSfredette static void kdcnpollc __P((dev_t, int));
528*ae1f6b9eSfredette 
529*ae1f6b9eSfredette /* The keyboard driver uses cn_hw to access the real console driver */
530*ae1f6b9eSfredette extern struct consdev consdev_prom;
531*ae1f6b9eSfredette struct consdev consdev_kd = {
532*ae1f6b9eSfredette 	kdcnprobe,
533*ae1f6b9eSfredette 	kdcninit,
534*ae1f6b9eSfredette 	kdcngetc,
535*ae1f6b9eSfredette 	kdcnputc,
536*ae1f6b9eSfredette 	kdcnpollc,
537*ae1f6b9eSfredette 	NULL,
538*ae1f6b9eSfredette };
539*ae1f6b9eSfredette struct consdev *cn_hw = &consdev_kd;
540*ae1f6b9eSfredette 
541*ae1f6b9eSfredette void
542*ae1f6b9eSfredette cons_attach_input(cc, cn)
543*ae1f6b9eSfredette 	struct cons_channel *cc;
544*ae1f6b9eSfredette 	struct consdev *cn;
545*ae1f6b9eSfredette {
546*ae1f6b9eSfredette 	struct kd_softc *kd = &kd_softc;
547*ae1f6b9eSfredette 	struct kbd_softc *kds = cc->cc_dev;
548*ae1f6b9eSfredette 	struct kbd_state *ks;
549*ae1f6b9eSfredette 
550*ae1f6b9eSfredette 	/* Share the keyboard state */
551*ae1f6b9eSfredette 	kdcn_state = ks = &kds->k_state;
552*ae1f6b9eSfredette 
553*ae1f6b9eSfredette 	kd->kd_in = cc;
554*ae1f6b9eSfredette 	cc->cc_upstream = kd_cons_input;
555*ae1f6b9eSfredette 
556*ae1f6b9eSfredette 	/* Attach lower level. */
557*ae1f6b9eSfredette 	cn_hw->cn_dev = cn->cn_dev;
558*ae1f6b9eSfredette 	cn_hw->cn_pollc = cn->cn_pollc;
559*ae1f6b9eSfredette 	cn_hw->cn_getc = cn->cn_getc;
560*ae1f6b9eSfredette 
561*ae1f6b9eSfredette 	/* Attach us as console. */
562*ae1f6b9eSfredette 	cn_tab->cn_dev = makedev(KDMAJOR, 0);
563*ae1f6b9eSfredette 	cn_tab->cn_probe = kdcnprobe;
564*ae1f6b9eSfredette 	cn_tab->cn_init = kdcninit;
565*ae1f6b9eSfredette 	cn_tab->cn_getc = kdcngetc;
566*ae1f6b9eSfredette 	cn_tab->cn_pollc = kdcnpollc;
567*ae1f6b9eSfredette 	cn_tab->cn_pri = CN_INTERNAL;
568*ae1f6b9eSfredette 
569*ae1f6b9eSfredette 	/* Set up initial PROM input channel for /dev/console */
570*ae1f6b9eSfredette 	prom_cons_channel.cc_dev = NULL;
571*ae1f6b9eSfredette 	prom_cons_channel.cc_iopen = kd_rom_iopen;
572*ae1f6b9eSfredette 	prom_cons_channel.cc_iclose = kd_rom_iclose;
573*ae1f6b9eSfredette 
574*ae1f6b9eSfredette 	/* Indicate that it is OK to use the PROM fbwrite */
575*ae1f6b9eSfredette 	kd_is_console = 1;
576*ae1f6b9eSfredette }
577*ae1f6b9eSfredette 
578*ae1f6b9eSfredette 
579*ae1f6b9eSfredette void kd_attach_input(struct cons_channel *);
580*ae1f6b9eSfredette void
581*ae1f6b9eSfredette kd_attach_input(cc)
582*ae1f6b9eSfredette 	struct cons_channel *cc;
583*ae1f6b9eSfredette {
584*ae1f6b9eSfredette 	struct kd_softc *kd = &kd_softc;
585*ae1f6b9eSfredette 
586*ae1f6b9eSfredette 	kd->kd_in = cc;
587*ae1f6b9eSfredette 	cc->cc_upstream = kd_cons_input;
588*ae1f6b9eSfredette }
589*ae1f6b9eSfredette 
590*ae1f6b9eSfredette 
591*ae1f6b9eSfredette /* We never call this. */
592*ae1f6b9eSfredette static void
593*ae1f6b9eSfredette kdcnprobe(cn)
594*ae1f6b9eSfredette 	struct consdev *cn;
595*ae1f6b9eSfredette {
596*ae1f6b9eSfredette }
597*ae1f6b9eSfredette 
598*ae1f6b9eSfredette static void
599*ae1f6b9eSfredette kdcninit(cn)
600*ae1f6b9eSfredette 	struct consdev *cn;
601*ae1f6b9eSfredette {
602*ae1f6b9eSfredette #if 0
603*ae1f6b9eSfredette 	struct kbd_state *ks = kdcn_state;
604*ae1f6b9eSfredette 
605*ae1f6b9eSfredette 	cn->cn_dev = makedev(KDMAJOR, 0);
606*ae1f6b9eSfredette 	cn->cn_pri = CN_INTERNAL;
607*ae1f6b9eSfredette 
608*ae1f6b9eSfredette 	/* This prepares kbd_translate() */
609*ae1f6b9eSfredette 	ks->kbd_id = KBD_MIN_TYPE;
610*ae1f6b9eSfredette 	kbd_xlate_init(ks);
611*ae1f6b9eSfredette 
612*ae1f6b9eSfredette 	/* Set up initial PROM input channel for /dev/console */
613*ae1f6b9eSfredette 	prom_cons_channel.cc_dev = NULL;
614*ae1f6b9eSfredette 	prom_cons_channel.cc_iopen = kd_rom_iopen;
615*ae1f6b9eSfredette 	prom_cons_channel.cc_iclose = kd_rom_iclose;
616*ae1f6b9eSfredette 	cons_attach_input(&prom_cons_channel);
617*ae1f6b9eSfredette 
618*ae1f6b9eSfredette 	/* Indicate that it is OK to use the PROM fbwrite */
619*ae1f6b9eSfredette 	kd_is_console = 1;
620*ae1f6b9eSfredette #endif
621*ae1f6b9eSfredette }
622*ae1f6b9eSfredette 
623*ae1f6b9eSfredette static int
624*ae1f6b9eSfredette kdcngetc(dev)
625*ae1f6b9eSfredette 	dev_t dev;
626*ae1f6b9eSfredette {
627*ae1f6b9eSfredette 	struct kbd_state *ks = kdcn_state;
628*ae1f6b9eSfredette 	int code, class, data, keysym;
629*ae1f6b9eSfredette 	extern int prom_cngetc __P((dev_t));
630*ae1f6b9eSfredette 
631*ae1f6b9eSfredette 
632*ae1f6b9eSfredette 	if (cn_hw->cn_getc == prom_cngetc) return (*cn_hw->cn_getc)(dev);
633*ae1f6b9eSfredette 	for (;;) {
634*ae1f6b9eSfredette 		code = (*cn_hw->cn_getc)(dev);
635*ae1f6b9eSfredette 		keysym = kbd_code_to_keysym(ks, code);
636*ae1f6b9eSfredette 		class = KEYSYM_CLASS(keysym);
637*ae1f6b9eSfredette 
638*ae1f6b9eSfredette 		switch (class) {
639*ae1f6b9eSfredette 		case KEYSYM_ASCII:
640*ae1f6b9eSfredette 			goto out;
641*ae1f6b9eSfredette 
642*ae1f6b9eSfredette 		case KEYSYM_CLRMOD:
643*ae1f6b9eSfredette 		case KEYSYM_SETMOD:
644*ae1f6b9eSfredette 			data = (keysym & 0x1F);
645*ae1f6b9eSfredette 			/* Only allow ctrl or shift. */
646*ae1f6b9eSfredette 			if (data > KBMOD_SHIFT_R)
647*ae1f6b9eSfredette 				break;
648*ae1f6b9eSfredette 			data = 1 << data;
649*ae1f6b9eSfredette 			if (class == KEYSYM_SETMOD)
650*ae1f6b9eSfredette 				ks->kbd_modbits |= data;
651*ae1f6b9eSfredette 			else
652*ae1f6b9eSfredette 				ks->kbd_modbits &= ~data;
653*ae1f6b9eSfredette 			break;
654*ae1f6b9eSfredette 
655*ae1f6b9eSfredette 		case KEYSYM_ALL_UP:
656*ae1f6b9eSfredette 			/* No toggle keys here. */
657*ae1f6b9eSfredette 			ks->kbd_modbits = 0;
658*ae1f6b9eSfredette 			break;
659*ae1f6b9eSfredette 
660*ae1f6b9eSfredette 		default:	/* ignore all other keysyms */
661*ae1f6b9eSfredette 			break;
662*ae1f6b9eSfredette 		}
663*ae1f6b9eSfredette 	}
664*ae1f6b9eSfredette out:
665*ae1f6b9eSfredette 	return (keysym);
666*ae1f6b9eSfredette }
667*ae1f6b9eSfredette 
668*ae1f6b9eSfredette static void
669*ae1f6b9eSfredette kdcnputc(dev, c)
670*ae1f6b9eSfredette 	dev_t dev;
671*ae1f6b9eSfredette 	int c;
672*ae1f6b9eSfredette {
673*ae1f6b9eSfredette 	int s;
674*ae1f6b9eSfredette 
675*ae1f6b9eSfredette 	s = splhigh();
676*ae1f6b9eSfredette 	prom_putchar(c);
677*ae1f6b9eSfredette 	splx(s);
678*ae1f6b9eSfredette }
679*ae1f6b9eSfredette 
680*ae1f6b9eSfredette static void
681*ae1f6b9eSfredette kdcnpollc(dev, on)
682*ae1f6b9eSfredette 	dev_t dev;
683*ae1f6b9eSfredette 	int on;
684*ae1f6b9eSfredette {
685*ae1f6b9eSfredette 	struct kbd_state *ks = kdcn_state;
686*ae1f6b9eSfredette 
687*ae1f6b9eSfredette 	if (on) {
688*ae1f6b9eSfredette 		/* Entering debugger. */
689*ae1f6b9eSfredette #if NFB > 0
690*ae1f6b9eSfredette 		fb_unblank();
691*ae1f6b9eSfredette #endif
692*ae1f6b9eSfredette 		/* Clear shift keys too. */
693*ae1f6b9eSfredette 		ks->kbd_modbits = 0;
694*ae1f6b9eSfredette 	} else {
695*ae1f6b9eSfredette 		/* Resuming kernel. */
696*ae1f6b9eSfredette 	}
697*ae1f6b9eSfredette 	(*cn_hw->cn_pollc)(dev, on);
698*ae1f6b9eSfredette }
699