smg.c revision 1.13 1 /* $NetBSD: smg.c,v 1.13 1999/02/12 11:25:24 drochner Exp $ */
2 /*
3 * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed at Ludd, University of
17 * Lule}, Sweden and its contributors.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/device.h>
35 #include <sys/systm.h>
36 #include <sys/time.h>
37 #include <sys/malloc.h>
38 #include <sys/conf.h>
39 #include <sys/kernel.h>
40
41 #include <dev/cons.h>
42
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wscons/wscons_callbacks.h>
46
47 #include <machine/vsbus.h>
48 #include <machine/sid.h>
49 #include <machine/cpu.h>
50
51 #include "lkc.h"
52
53 #define SM_COLS 128 /* char width of screen */
54 #define SM_ROWS 57 /* rows of char on screen */
55 #define SM_CHEIGHT 15 /* lines a char consists of */
56 #define SM_NEXTROW (SM_COLS * SM_CHEIGHT)
57
58 static int smg_match __P((struct device *, struct cfdata *, void *));
59 static void smg_attach __P((struct device *, struct device *, void *));
60
61 struct smg_softc {
62 struct device ss_dev;
63 };
64
65 struct cfattach smg_ca = {
66 sizeof(struct smg_softc), smg_match, smg_attach,
67 };
68
69 static void smg_cursor __P((void *, int, int, int));
70 static int smg_mapchar __P((void *, int, unsigned int *));
71 static void smg_putchar __P((void *, int, int, u_int, long));
72 static void smg_copycols __P((void *, int, int, int,int));
73 static void smg_erasecols __P((void *, int, int, int, long));
74 static void smg_copyrows __P((void *, int, int, int));
75 static void smg_eraserows __P((void *, int, int, long));
76 static int smg_alloc_attr __P((void *, int, int, int, long *));
77
78 const struct wsdisplay_emulops smg_emulops = {
79 smg_cursor,
80 smg_mapchar,
81 smg_putchar,
82 smg_copycols,
83 smg_erasecols,
84 smg_copyrows,
85 smg_eraserows,
86 smg_alloc_attr
87 };
88
89 const struct wsscreen_descr smg_stdscreen = {
90 "128x57", SM_COLS, SM_ROWS,
91 &smg_emulops,
92 8, SM_CHEIGHT,
93 WSSCREEN_UNDERLINE|WSSCREEN_REVERSE,
94 };
95
96 const struct wsscreen_descr *_smg_scrlist[] = {
97 &smg_stdscreen,
98 };
99
100 const struct wsscreen_list smg_screenlist = {
101 sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *),
102 _smg_scrlist,
103 };
104
105 static caddr_t sm_addr;
106
107 extern char q_font[];
108 #define QCHAR(c) (c < 32 ? 32 : (c > 127 ? c - 66 : c - 32))
109 #define QFONT(c,line) q_font[QCHAR(c) * 15 + line]
110 #define SM_ADDR(row, col, line) \
111 sm_addr[col + (row * SM_CHEIGHT * SM_COLS) + line * SM_COLS]
112
113
114 static int smg_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
115 static int smg_mmap __P((void *, off_t, int));
116 static int smg_alloc_screen __P((void *, const struct wsscreen_descr *,
117 void **, int *, int *, long *));
118 static void smg_free_screen __P((void *, void *));
119 static void smg_show_screen __P((void *, void *));
120 static void smg_crsr_blink __P((void *));
121
122 const struct wsdisplay_accessops smg_accessops = {
123 smg_ioctl,
124 smg_mmap,
125 smg_alloc_screen,
126 smg_free_screen,
127 smg_show_screen,
128 0 /* load_font */
129 };
130
131 struct smg_screen {
132 int ss_curx;
133 int ss_cury;
134 u_char ss_image[SM_ROWS][SM_COLS]; /* Image of current screen */
135 u_char ss_attr[SM_ROWS][SM_COLS]; /* Reversed etc... */
136 };
137
138 static struct smg_screen smg_conscreen;
139 static struct smg_screen *curscr;
140
141 int
142 smg_match(parent, match, aux)
143 struct device *parent;
144 struct cfdata *match;
145 void *aux;
146 {
147 struct vsbus_attach_args *va = aux;
148
149 if (va->va_type != inr_vf)
150 return 0;
151
152 if (sm_addr == 0)
153 sm_addr = (caddr_t)vax_map_physmem(SMADDR, (SMSIZE/VAX_NBPG));
154 if (sm_addr == 0)
155 return 0;
156 return 1;
157 }
158
159 void
160 smg_attach(parent, self, aux)
161 struct device *parent, *self;
162 void *aux;
163 {
164 struct wsemuldisplaydev_attach_args aa;
165
166 printf("\n");
167 curscr = &smg_conscreen;
168 aa.console = !(vax_confdata & 0x20);
169 aa.scrdata = &smg_screenlist;
170 aa.accessops = &smg_accessops;
171 timeout(smg_crsr_blink, 0, hz/2);
172
173 config_found(self, &aa, wsemuldisplaydevprint);
174 }
175
176 static u_char *cursor;
177 static int cur_on;
178
179 static void
180 smg_crsr_blink(arg)
181 void *arg;
182 {
183 if (cur_on)
184 *cursor ^= 255;
185 timeout(smg_crsr_blink, 0, hz/2);
186 }
187
188 void
189 smg_cursor(id, on, row, col)
190 void *id;
191 int on, row, col;
192 {
193 struct smg_screen *ss = id;
194
195 if (ss == curscr) {
196 SM_ADDR(ss->ss_cury, ss->ss_curx, 14) =
197 QFONT(ss->ss_image[ss->ss_cury][ss->ss_curx], 14);
198 cursor = &SM_ADDR(row, col, 14);
199 if ((cur_on = on))
200 *cursor ^= 255;
201 }
202 ss->ss_curx = col;
203 ss->ss_cury = row;
204 }
205
206 unsigned int
207 smg_mapchar(id, uni, index)
208 void *id;
209 int uni;
210 unsigned int *index;
211 {
212 if (uni < 256) {
213 *index = uni;
214 return (5);
215 }
216 *index = ' ';
217 return (0);
218 }
219
220 static void
221 smg_putchar(id, row, col, c, attr)
222 void *id;
223 int row, col;
224 u_int c;
225 long attr;
226 {
227 struct smg_screen *ss = id;
228 int i;
229
230 c &= 0xff;
231
232 ss->ss_image[row][col] = c;
233 ss->ss_attr[row][col] = attr;
234 if (ss != curscr)
235 return;
236 for (i = 0; i < 15; i++) {
237 unsigned char ch = QFONT(c, i);
238
239 SM_ADDR(row, col, i) = (attr & WSATTR_REVERSE ? ~ch : ch);
240
241 }
242 if (attr & WSATTR_UNDERLINE)
243 SM_ADDR(row, col, 14) ^= SM_ADDR(row, col, 14);
244 }
245
246 /*
247 * copies columns inside a row.
248 */
249 static void
250 smg_copycols(id, row, srccol, dstcol, ncols)
251 void *id;
252 int row, srccol, dstcol, ncols;
253 {
254 struct smg_screen *ss = id;
255 int i;
256
257 bcopy(&ss->ss_image[row][srccol], &ss->ss_image[row][dstcol], ncols);
258 bcopy(&ss->ss_attr[row][srccol], &ss->ss_attr[row][dstcol], ncols);
259 if (ss != curscr)
260 return;
261 for (i = 0; i < SM_CHEIGHT; i++)
262 bcopy(&SM_ADDR(row,srccol, i), &SM_ADDR(row, dstcol, i),ncols);
263 }
264
265 /*
266 * Erases a bunch of chars inside one row.
267 */
268 static void
269 smg_erasecols(id, row, startcol, ncols, fillattr)
270 void *id;
271 int row, startcol, ncols;
272 long fillattr;
273 {
274 struct smg_screen *ss = id;
275 int i;
276
277 bzero(&ss->ss_image[row][startcol], ncols);
278 bzero(&ss->ss_attr[row][startcol], ncols);
279 if (ss != curscr)
280 return;
281 for (i = 0; i < SM_CHEIGHT; i++)
282 bzero(&SM_ADDR(row, startcol, i), ncols);
283 }
284
285 static void
286 smg_copyrows(id, srcrow, dstrow, nrows)
287 void *id;
288 int srcrow, dstrow, nrows;
289 {
290 struct smg_screen *ss = id;
291 int frows;
292
293 bcopy(&ss->ss_image[srcrow][0], &ss->ss_image[dstrow][0],
294 nrows * SM_COLS);
295 bcopy(&ss->ss_attr[srcrow][0], &ss->ss_attr[dstrow][0],
296 nrows * SM_COLS);
297 if (ss != curscr)
298 return;
299 if (nrows > 25) {
300 frows = nrows >> 1;
301 if (srcrow > dstrow) {
302 bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
303 &sm_addr[(dstrow * SM_NEXTROW)],
304 frows * SM_NEXTROW);
305 bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
306 &sm_addr[((dstrow + frows) * SM_NEXTROW)],
307 (nrows - frows) * SM_NEXTROW);
308 } else {
309 bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
310 &sm_addr[((dstrow + frows) * SM_NEXTROW)],
311 (nrows - frows) * SM_NEXTROW);
312 bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
313 &sm_addr[(dstrow * SM_NEXTROW)],
314 frows * SM_NEXTROW);
315 }
316 } else
317 bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
318 &sm_addr[(dstrow * SM_NEXTROW)], nrows * SM_NEXTROW);
319 }
320
321 static void
322 smg_eraserows(id, startrow, nrows, fillattr)
323 void *id;
324 int startrow, nrows;
325 long fillattr;
326 {
327 struct smg_screen *ss = id;
328 int frows;
329
330 bzero(&ss->ss_image[startrow][0], nrows * SM_COLS);
331 bzero(&ss->ss_attr[startrow][0], nrows * SM_COLS);
332 if (ss != curscr)
333 return;
334 if (nrows > 25) {
335 frows = nrows >> 1;
336 bzero(&sm_addr[(startrow * SM_NEXTROW)], frows * SM_NEXTROW);
337 bzero(&sm_addr[((startrow + frows) * SM_NEXTROW)],
338 (nrows - frows) * SM_NEXTROW);
339 } else
340 bzero(&sm_addr[(startrow * SM_NEXTROW)], nrows * SM_NEXTROW);
341 }
342
343 static int
344 smg_alloc_attr(id, fg, bg, flags, attrp)
345 void *id;
346 int fg, bg;
347 int flags;
348 long *attrp;
349 {
350 *attrp = flags;
351 return 0;
352 }
353
354 int
355 smg_ioctl(v, cmd, data, flag, p)
356 void *v;
357 u_long cmd;
358 caddr_t data;
359 int flag;
360 struct proc *p;
361 {
362 struct wsdisplay_fbinfo fb;
363
364 switch (cmd) {
365 case WSDISPLAYIO_GTYPE:
366 *(u_int *)data = WSDISPLAY_TYPE_PM_MONO;
367 break;
368
369 case WSDISPLAYIO_GINFO:
370 fb.height = 864;
371 fb.width = 1024;
372 return copyout(&fb, data, sizeof(struct wsdisplay_fbinfo));
373
374
375 default:
376 return -1;
377 }
378 return 0;
379 }
380
381 static int
382 smg_mmap(v, offset, prot)
383 void *v;
384 off_t offset;
385 int prot;
386 {
387 if (offset >= SMSIZE || offset < 0)
388 return -1;
389 return (SMADDR + offset) >> CLSHIFT;
390 }
391
392 int
393 smg_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
394 void *v;
395 const struct wsscreen_descr *type;
396 void **cookiep;
397 int *curxp, *curyp;
398 long *defattrp;
399 {
400 *cookiep = malloc(sizeof(struct smg_screen), M_DEVBUF, M_WAITOK);
401 bzero(*cookiep, sizeof(struct smg_screen));
402 *curxp = *curyp = *defattrp = 0;
403 return 0;
404 }
405
406 void
407 smg_free_screen(v, cookie)
408 void *v;
409 void *cookie;
410 {
411 }
412
413 void
414 smg_show_screen(v, cookie)
415 void *v;
416 void *cookie;
417 {
418 struct smg_screen *ss = cookie;
419 int row, col, line;
420
421 if (ss == curscr)
422 return;
423
424 for (row = 0; row < SM_ROWS; row++)
425 for (line = 0; line < SM_CHEIGHT; line++) {
426 for (col = 0; col < SM_COLS; col++) {
427 u_char s, c = ss->ss_image[row][col];
428
429 if (c < 32)
430 c = 32;
431 s = QFONT(c, line);
432 if (ss->ss_attr[row][col] & WSATTR_REVERSE)
433 s ^= 255;
434 SM_ADDR(row, col, line) = s;
435 }
436 if (ss->ss_attr[row][col] & WSATTR_UNDERLINE)
437 SM_ADDR(row, col, line) = 255;
438 }
439 cursor = &sm_addr[(ss->ss_cury * SM_CHEIGHT * SM_COLS) + ss->ss_curx +
440 ((SM_CHEIGHT - 1) * SM_COLS)];
441 curscr = ss;
442 }
443
444 cons_decl(smg);
445
446 #define WSCONSOLEMAJOR 68
447
448 void
449 smgcninit(cndev)
450 struct consdev *cndev;
451 {
452 extern void lkccninit __P((struct consdev *));
453 extern int lkccngetc __P((dev_t));
454 /* Clear screen */
455 memset(sm_addr, 0, 128*864);
456
457 curscr = &smg_conscreen;
458 wsdisplay_cnattach(&smg_stdscreen, &smg_conscreen, 0, 0, 0);
459 cn_tab->cn_dev = makedev(WSCONSOLEMAJOR, 0);
460 #if NLKC
461 lkccninit(cndev);
462 wsdisplay_set_cons_kbd(lkccngetc, nullcnpollc);
463 #endif
464 }
465
466 int smgprobe(void);
467 int
468 smgprobe()
469 {
470 switch (vax_boardtype) {
471 case VAX_BTYP_410:
472 case VAX_BTYP_420:
473 case VAX_BTYP_43:
474 if (vax_confdata & 0x20) /* doesn't use graphics console */
475 break;
476 sm_addr = (caddr_t)vax_map_physmem(SMADDR, (SMSIZE/VAX_NBPG));
477 if (sm_addr == 0)
478 return 0;
479
480 return 1;
481
482 default:
483 break;
484 }
485 return 0;
486 }
487