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
rcons_cnputc(c)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
rcons_output(tp)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
rcons_bell(fb)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
rcons_belltmr(p)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
rcons_a2int(cp,deflt)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
rcons_init(fb)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