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