xref: /original-bsd/sys/sparc/rcons/rcons_kern.c (revision 95ecee29)
1 /*
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)rcons_kern.c	8.2 (Berkeley) 09/27/93
17  *
18  * from: $Header: rcons_kern.c,v 1.29 93/09/27 00:52:02 torek Exp $
19  */
20 
21 #include <sys/param.h>
22 #include <sys/device.h>
23 #include <sys/fbio.h>
24 #include <sys/kernel.h>
25 #include <sys/systm.h>
26 #include <sys/ioctl.h>
27 #include <sys/tty.h>
28 
29 #include <machine/fbvar.h>
30 #include <machine/autoconf.h>
31 
32 #include <sparc/dev/kbd.h>
33 
34 #include <sparc/rcons/raster.h>
35 
36 extern struct tty *fbconstty;
37 
38 static void rcons_belltmr(void *);
39 
40 extern void rcons_puts(struct fbdevice *, char *, int);
41 extern void rcons_font(struct fbdevice *);
42 
43 extern int (*v_putc)();
44 extern void ttrstrt(void *);
45 
46 static struct fbdevice *myfbdevicep;
47 
48 static void
49 rcons_cnputc(c)
50 	int c;
51 {
52 	char buf[1];
53 
54 	if (c == '\n')
55 		rcons_puts(myfbdevicep, "\r\n", 2);
56 	else {
57 		buf[0] = c;
58 		rcons_puts(myfbdevicep, buf, 1);
59 	}
60 }
61 
62 static void
63 rcons_output(tp)
64 	register struct tty *tp;
65 {
66 	register int s, n, i;
67 	char buf[OBUFSIZ];
68 
69 	s = spltty();
70 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
71 		splx(s);
72 		return;
73 	}
74 	tp->t_state |= TS_BUSY;
75 	splx(s);
76 	n = q_to_b(&tp->t_outq, buf, sizeof(buf));
77 	for (i = 0; i < n; ++i)
78 		buf[i] &= 0177;		/* strip parity (argh) */
79 	rcons_puts(myfbdevicep, buf, n);
80 
81 	s = spltty();
82 	tp->t_state &= ~TS_BUSY;
83 	/* Come back if there's more to do */
84 	if (tp->t_outq.c_cc) {
85 		tp->t_state |= TS_TIMEOUT;
86 		timeout(ttrstrt, tp, 1);
87 	}
88 	if (tp->t_outq.c_cc <= tp->t_lowat) {
89 		if (tp->t_state&TS_ASLEEP) {
90 			tp->t_state &= ~TS_ASLEEP;
91 			wakeup((caddr_t)&tp->t_outq);
92 		}
93 		selwakeup(&tp->t_wsel);
94 	}
95 	splx(s);
96 }
97 
98 /* Ring the console bell */
99 void
100 rcons_bell(fb)
101 	register struct fbdevice *fb;
102 {
103 	register int i, s;
104 
105 	if (fb->fb_bits & FB_VISBELL) {
106 		/* invert the screen twice */
107 		for (i = 0; i < 2; ++i)
108 			raster_op(fb->fb_sp, 0, 0,
109 			    fb->fb_sp->width, fb->fb_sp->height,
110 			    RAS_INVERT, (struct raster *) 0, 0, 0);
111 	}
112 
113 	s = splhigh();
114 	if (fb->fb_belldepth++) {
115 		if (fb->fb_belldepth > 3)
116 			fb->fb_belldepth = 3;
117 		splx(s);
118 	} else {
119 		fb->fb_ringing = 1;
120 		splx(s);
121 		(void) kbd_docmd(KBD_CMD_BELL, 0);
122 		/* XXX Chris doesn't like the following divide */
123 		timeout(rcons_belltmr, fb, hz/10);
124 	}
125 }
126 
127 /* Bell timer service routine */
128 static void
129 rcons_belltmr(p)
130 	void *p;
131 {
132 	register struct fbdevice *fb = p;
133 	register int s = splhigh(), i;
134 
135 	if (fb->fb_ringing) {
136 		fb->fb_ringing = 0;
137 		i = --fb->fb_belldepth;
138 		splx(s);
139 		(void) kbd_docmd(KBD_CMD_NOBELL, 0);
140 		if (i != 0)
141 			/* XXX Chris doesn't like the following divide */
142 			timeout(rcons_belltmr, fb, hz/30);
143 	} else {
144 		fb->fb_ringing = 1;
145 		splx(s);
146 		(void) kbd_docmd(KBD_CMD_BELL, 0);
147 		timeout(rcons_belltmr, fb, hz/10);
148 	}
149 }
150 
151 static int
152 rcons_a2int(cp, deflt)
153 	register char *cp;
154 	register int deflt;
155 {
156 	register int i = 0;
157 
158 	if (*cp == '\0')
159 		return (deflt);
160 	while (*cp != '\0')
161 		i = i * 10 + *cp++ - '0';
162 	return (i);
163 }
164 
165 void
166 rcons_init(fb)
167 	register struct fbdevice *fb;
168 {
169 	/* XXX this should go away */
170 	static struct raster xxxraster;
171 	register struct raster *rp = fb->fb_sp = &xxxraster;
172 	register struct fbtype *ft = &fb->fb_type;
173 	register struct winsize *ws;
174 	register int i;
175 	static int row, col;
176 
177 	myfbdevicep = fb;
178 
179 	fb->fb_maxcol =
180 	    rcons_a2int(getpropstring(optionsnode, "screen-#columns"), 80);
181 	fb->fb_maxrow =
182 	    rcons_a2int(getpropstring(optionsnode, "screen-#rows"), 34);
183 
184 	/* XXX mostly duplicates of data in other places */
185 	rp->width = ft->fb_width;
186 	rp->height = ft->fb_height;
187 	rp->depth = ft->fb_depth;
188 	if (fb->fb_linebytes & 0x3) {
189 		printf("rcons_init: linebytes assumption botched (0x%x)\n",
190 		    fb->fb_linebytes);
191 		return;
192 	}
193 	rp->linelongs = fb->fb_linebytes >> 2;
194 	rp->pixels = (u_long *)fb->fb_pixels;
195 
196 	fb->fb_ras_blank = RAS_CLEAR;
197 
198 	/* Setup the static font */
199 	rcons_font(fb);
200 
201 	/* Impose upper bounds on fb_max{row,col} */
202 	i = ft->fb_height / fb->fb_font->height;
203 	if (fb->fb_maxrow > i)
204 		fb->fb_maxrow = i;
205 	i = ft->fb_width / fb->fb_font->width;
206 	if (fb->fb_maxcol > i)
207 		fb->fb_maxcol = i;
208 
209 	/* Let the system know how big the console is */
210 	ws = &fbconstty->t_winsize;
211 	ws->ws_row = fb->fb_maxrow;
212 	ws->ws_col = fb->fb_maxcol;
213 	ws->ws_xpixel = ft->fb_width;
214 	ws->ws_ypixel = ft->fb_height;
215 
216 	/* Center emulator screen (but align x origin to 32 bits) */
217 	fb->fb_xorigin =
218 	    ((ft->fb_width - fb->fb_maxcol * fb->fb_font->width) / 2) & ~0x1f;
219 	fb->fb_yorigin =
220 	    (ft->fb_height - fb->fb_maxrow * fb->fb_font->height) / 2;
221 
222 	/* Emulator width and height used for scrolling */
223 	fb->fb_emuwidth = fb->fb_maxcol * fb->fb_font->width;
224 	if (fb->fb_emuwidth & 0x1f) {
225 		/* Pad to 32 bits */
226 		i = (fb->fb_emuwidth + 0x1f) & ~0x1f;
227 		/* Make sure emulator width isn't too wide */
228 		if (fb->fb_xorigin + i <= ft->fb_width)
229 			fb->fb_emuwidth = i;
230 	}
231 	fb->fb_emuheight = fb->fb_maxrow * fb->fb_font->height;
232 
233 	/* Determine addresses of prom emulator row and column */
234 	if (romgetcursoraddr(&fb->fb_row, &fb->fb_col)) {
235 		/* Can't find addresses; use private copies */
236 		fb->fb_row = &row;
237 		fb->fb_col = &col;
238 		row = col = 0;
239 		rcons_clear2eop(fb);	/* clear the display */
240 		rcons_cursor(fb);	/* and draw the initial cursor */
241 	} else {
242 		/* Prom emulator cursor is currently visible */
243 		fb->fb_bits |= FB_CURSOR;
244 	}
245 
246 	/* Initialization done; hook us up */
247 	v_putc = (int (*)())rcons_cnputc;
248 	fbconstty->t_oproc = rcons_output;
249 	fbconstty->t_stop = (void (*)()) nullop;
250 }
251