1 /* $MirOS: src/sys/dev/ic/vga.c,v 1.8 2007/02/07 17:28:27 tg Exp $ */
2 /* $OpenBSD: vga.c,v 1.44 2007/02/06 22:03:23 miod Exp $ */
3 /* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */
4 
5 /*
6  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
7  * All rights reserved.
8  *
9  * Author: Chris G. Demetriou
10  *
11  * Permission to use, copy, modify and distribute this software and
12  * its documentation is hereby granted, provided that both the copyright
13  * notice and this permission notice appear in all copies of the
14  * software, derivative works or modified versions, and any portions
15  * thereof, and that both notices appear in supporting documentation.
16  *
17  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
18  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
19  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
20  *
21  * Carnegie Mellon requests users of this software to return to
22  *
23  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
24  *  School of Computer Science
25  *  Carnegie Mellon University
26  *  Pittsburgh PA 15213-3890
27  *
28  * any improvements or extensions that they make and grant Carnegie the
29  * rights to redistribute these changes.
30  */
31 
32 #include "vga.h"
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/device.h>
38 #include <sys/malloc.h>
39 #include <sys/queue.h>
40 #include <machine/bus.h>
41 
42 #include <dev/ic/mc6845reg.h>
43 #include <dev/ic/pcdisplayvar.h>
44 #include <dev/ic/vgareg.h>
45 #include <dev/ic/vgavar.h>
46 
47 #include <dev/wscons/wsdisplayvar.h>
48 #include <dev/wscons/wsconsio.h>
49 #include <dev/wscons/unicode.h>
50 
51 #include <dev/ic/pcdisplay.h>
52 
53 extern void (*panic_hook_display)(void);
54 
55 #if 0
56 #include "opt_wsdisplay_compat.h" /* for WSCONS_SUPPORT_PCVTFONTS */
57 #endif
58 
59 static struct vgafont {
60 	char name[WSFONT_NAME_SIZE];
61 	int height;
62 	int encoding;
63 #ifdef notyet
64 	int firstchar, numchars;
65 #endif
66 	int slot;
67 } vga_builtinfont = {
68 	"builtin",
69 	16,
70 	WSDISPLAY_FONTENC_IBM,
71 #ifdef notyet
72 	0, 256,
73 #endif
74 	0
75 };
76 
77 struct vgascreen {
78 	struct pcdisplayscreen pcs;
79 
80 	LIST_ENTRY(vgascreen) next;
81 
82 	struct vga_config *cfg;
83 
84 	/* videostate */
85 	struct vgafont *fontset1, *fontset2;
86 	/* font data */
87 	/* palette */
88 
89 	int mindispoffset, maxdispoffset;
90 	int vga_rollover;
91 };
92 
93 int vgaconsole, vga_console_type, vga_console_attached;
94 struct vgascreen vga_console_screen;
95 struct vga_config vga_console_vc;
96 
97 int	vga_selectfont(struct vga_config *, struct vgascreen *,
98     const char *, const char *);
99 void	vga_init_screen(struct vga_config *, struct vgascreen *,
100     const struct wsscreen_descr *, int, long *);
101 void	vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
102 void	vga_setfont(struct vga_config *, struct vgascreen *);
103 
104 int	vga_mapchar(void *, int, unsigned int *);
105 void	vga_putchar(void *, int, int, u_int, long);
106 int	vga_alloc_attr(void *, int, int, int, long *);
107 void	vga_copyrows(void *, int, int, int);
108 void	vga_unpack_attr(void *, long, int *, int *, int *);
109 
110 void	vga_panic_hook(void);
111 
112 static const struct wsdisplay_emulops vga_emulops = {
113 	pcdisplay_cursor,
114 	vga_mapchar,
115 	vga_putchar,
116 	pcdisplay_copycols,
117 	pcdisplay_erasecols,
118 	vga_copyrows,
119 	pcdisplay_eraserows,
120 	vga_alloc_attr,
121 	vga_unpack_attr
122 };
123 
124 /*
125  * translate WS(=ANSI) color codes to standard pc ones
126  */
127 static const unsigned char fgansitopc[] = {
128 #ifdef __alpha__
129 	/*
130 	 * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
131 	 * XXX We should probably not bother with this
132 	 * XXX (reinitialize the palette registers).
133 	 */
134 	FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
135 	FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
136 #else
137 	FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
138 	FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
139 #endif
140 }, bgansitopc[] = {
141 #ifdef __alpha__
142 	BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
143 	BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
144 #else
145 	BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
146 	BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
147 #endif
148 };
149 
150 /*
151  * translate standard pc color codes to WS(=ANSI) ones
152  */
153 static const u_int8_t pctoansi[] = {
154 #ifdef __alpha__
155 	WSCOL_BLACK, WSCOL_RED, WSCOL_GREEN, WSCOL_BROWN,
156 	WSCOL_BLUE, WSCOL_MAGENTA, WSCOL_CYAN, WSCOL_WHITE
157 #else
158 	WSCOL_BLACK, WSCOL_BLUE, WSCOL_GREEN, WSCOL_CYAN,
159 	WSCOL_RED, WSCOL_MAGENTA, WSCOL_BROWN, WSCOL_WHITE
160 #endif
161 };
162 
163 
164 const struct wsscreen_descr vga_stdscreen = {
165 	"80x25", 80, 25,
166 	&vga_emulops,
167 	8, 16,
168 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
169 }, vga_stdscreen_mono = {
170 	"80x25", 80, 25,
171 	&vga_emulops,
172 	8, 16,
173 	WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
174 }, vga_stdscreen_bf = {
175 	"80x25bf", 80, 25,
176 	&vga_emulops,
177 	8, 16,
178 	WSSCREEN_WSCOLORS | WSSCREEN_BLINK
179 }, vga_40lscreen = {
180 	"80x40", 80, 40,
181 	&vga_emulops,
182 	8, 10,
183 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
184 }, vga_40lscreen_mono = {
185 	"80x40", 80, 40,
186 	&vga_emulops,
187 	8, 10,
188 	WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
189 }, vga_40lscreen_bf = {
190 	"80x40bf", 80, 40,
191 	&vga_emulops,
192 	8, 10,
193 	WSSCREEN_WSCOLORS | WSSCREEN_BLINK
194 }, vga_50lscreen = {
195 	"80x50", 80, 50,
196 	&vga_emulops,
197 	8, 8,
198 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
199 }, vga_50lscreen_mono = {
200 	"80x50", 80, 50,
201 	&vga_emulops,
202 	8, 8,
203 	WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
204 }, vga_50lscreen_bf = {
205 	"80x50bf", 80, 50,
206 	&vga_emulops,
207 	8, 8,
208 	WSSCREEN_WSCOLORS | WSSCREEN_BLINK
209 };
210 
211 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
212 
213 const struct wsscreen_descr *_vga_scrlist[] = {
214 	&vga_stdscreen,
215 	&vga_stdscreen_bf,
216 	&vga_40lscreen,
217 	&vga_40lscreen_bf,
218 	&vga_50lscreen,
219 	&vga_50lscreen_bf,
220 	/* XXX other formats, graphics screen? */
221 }, *_vga_scrlist_mono[] = {
222 	&vga_stdscreen_mono,
223 	&vga_40lscreen_mono,
224 	&vga_50lscreen_mono,
225 	/* XXX other formats, graphics screen? */
226 };
227 
228 const struct wsscreen_list vga_screenlist = {
229 	sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
230 	_vga_scrlist
231 }, vga_screenlist_mono = {
232 	sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
233 	_vga_scrlist_mono
234 };
235 
236 int	vga_ioctl(void *, u_long, caddr_t, int, struct proc *);
237 paddr_t	vga_mmap(void *, off_t, int);
238 int	vga_alloc_screen(void *, const struct wsscreen_descr *,
239 			 void **, int *, int *, long *);
240 void	vga_free_screen(void *, void *);
241 int	vga_show_screen(void *, void *, int,
242 			void (*) (void *, int, int), void *);
243 int	vga_load_font(void *, void *, struct wsdisplay_font *);
244 int	vga_delete_font(void *, void *, int);
245 void	vga_scrollback(void *, void *, int);
246 void	vga_burner(void *v, u_int on, u_int flags);
247 int	vga_getchar(void *, int, int, struct wsdisplay_charcell *);
248 
249 void vga_doswitch(struct vga_config *);
250 
251 const struct wsdisplay_accessops vga_accessops = {
252 	vga_ioctl,
253 	vga_mmap,
254 	vga_alloc_screen,
255 	vga_free_screen,
256 	vga_show_screen,
257 	vga_load_font,
258 	vga_scrollback,
259 	vga_getchar,
260 	vga_burner,
261 	NULL,			/* pollc */
262 	vga_delete_font
263 };
264 
265 /*
266  * The following functions implement back-end configuration grabbing
267  * and attachment.
268  */
269 int
vga_common_probe(iot,memt)270 vga_common_probe(iot, memt)
271 	bus_space_tag_t iot, memt;
272 {
273 	bus_space_handle_t ioh_vga, ioh_6845, memh;
274 	u_int8_t regval;
275 	u_int16_t vgadata;
276 	int gotio_vga, gotio_6845, gotmem, mono, rv;
277 	int dispoffset;
278 
279 	gotio_vga = gotio_6845 = gotmem = rv = 0;
280 
281 	if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga))
282 		goto bad;
283 	gotio_vga = 1;
284 
285 	/* read "misc output register" */
286 	regval = bus_space_read_1(iot, ioh_vga, 0xc);
287 	mono = !(regval & 1);
288 
289 	if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845))
290 		goto bad;
291 	gotio_6845 = 1;
292 
293 	if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh))
294 		goto bad;
295 	gotmem = 1;
296 
297 	dispoffset = (mono ? 0x10000 : 0x18000);
298 
299 	vgadata = bus_space_read_2(memt, memh, dispoffset);
300 	bus_space_write_2(memt, memh, dispoffset, 0xa55a);
301 	if (bus_space_read_2(memt, memh, dispoffset) != 0xa55a)
302 		goto bad;
303 	bus_space_write_2(memt, memh, dispoffset, vgadata);
304 
305 	/*
306 	 * check if this is really a VGA
307 	 * (try to write "Color Select" register as XFree86 does)
308 	 * XXX check before if at least EGA?
309 	 */
310 	/* reset state */
311 	(void) bus_space_read_1(iot, ioh_6845, 10);
312 	bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
313 			  20 | 0x20); /* colselect | enable */
314 	regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR);
315 	/* toggle the implemented bits */
316 	bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f);
317 	bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
318 			  20 | 0x20);
319 	/* read back */
320 	if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR) != (regval ^ 0x0f))
321 		goto bad;
322 	/* restore contents */
323 	bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval);
324 
325 	rv = 1;
326 bad:
327 	if (gotio_vga)
328 		bus_space_unmap(iot, ioh_vga, 0x10);
329 	if (gotio_6845)
330 		bus_space_unmap(iot, ioh_6845, 0x10);
331 	if (gotmem)
332 		bus_space_unmap(memt, memh, 0x20000);
333 
334 	return (rv);
335 }
336 
337 /*
338  * We want at least ASCII 32..127 be present in the
339  * first font slot.
340  */
341 #define vga_valid_primary_font(f) \
342 	(f->encoding == WSDISPLAY_FONTENC_IBM || \
343 	f->encoding == WSDISPLAY_FONTENC_ISO)
344 
345 int
vga_selectfont(vc,scr,name1,name2)346 vga_selectfont(vc, scr, name1, name2)
347 	struct vga_config *vc;
348 	struct vgascreen *scr;
349 	const char *name1, *name2; /* NULL: take first found */
350 {
351 	const struct wsscreen_descr *type = scr->pcs.type;
352 	struct vgafont *f1, *f2;
353 	int i;
354 
355 	f1 = f2 = 0;
356 
357 	for (i = 0; i < 8; i++) {
358 		struct vgafont *f = vc->vc_fonts[i];
359 		if (!f || f->height != type->fontheight)
360 			continue;
361 		if (!f1 &&
362 		    vga_valid_primary_font(f) &&
363 		    (!name1 || !*name1 ||
364 		     !strncmp(name1, f->name, WSFONT_NAME_SIZE))) {
365 			f1 = f;
366 			continue;
367 		}
368 		if (!f2 &&
369 		    VGA_SCREEN_CANTWOFONTS(type) &&
370 		    (!name2 || !*name2 ||
371 		     !strncmp(name2, f->name, WSFONT_NAME_SIZE))) {
372 			f2 = f;
373 			continue;
374 		}
375 	}
376 
377 	/*
378 	 * The request fails if no primary font was found,
379 	 * or if a second font was requested but not found.
380 	 */
381 	if (f1 && (!name2 || !*name2 || f2)) {
382 #ifdef VGAFONTDEBUG
383 		if (scr != &vga_console_screen || vga_console_attached) {
384 			printf("vga (%s): font1=%s (slot %d)", type->name,
385 			       f1->name, f1->slot);
386 			if (f2)
387 				printf(", font2=%s (slot %d)",
388 				       f2->name, f2->slot);
389 			printf("\n");
390 		}
391 #endif
392 		scr->fontset1 = f1;
393 		scr->fontset2 = f2;
394 		return (0);
395 	}
396 	return (ENXIO);
397 }
398 
399 void
vga_init_screen(vc,scr,type,existing,attrp)400 vga_init_screen(vc, scr, type, existing, attrp)
401 	struct vga_config *vc;
402 	struct vgascreen *scr;
403 	const struct wsscreen_descr *type;
404 	int existing;
405 	long *attrp;
406 {
407 	int cpos;
408 	int res;
409 
410 	scr->cfg = vc;
411 	scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
412 	scr->pcs.type = type;
413 	scr->pcs.active = 0;
414 	scr->mindispoffset = 0;
415 	scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
416 
417 	if (existing) {
418 		cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
419 		cpos |= vga_6845_read(&vc->hdl, cursorl);
420 
421 		/* make sure we have a valid cursor position */
422 		if (cpos < 0 || cpos >= type->nrows * type->ncols)
423 			cpos = 0;
424 
425 		scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
426 		scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
427 
428 		/* make sure we have a valid memory offset */
429 		if (scr->pcs.dispoffset < scr->mindispoffset ||
430 		    scr->pcs.dispoffset > scr->maxdispoffset)
431 			scr->pcs.dispoffset = scr->mindispoffset;
432 	} else {
433 		cpos = 0;
434 		scr->pcs.dispoffset = scr->mindispoffset;
435 	}
436 	scr->pcs.visibleoffset = scr->pcs.dispoffset;
437 	scr->vga_rollover = 0;
438 
439 	scr->pcs.vc_crow = cpos / type->ncols;
440 	scr->pcs.vc_ccol = cpos % type->ncols;
441 	pcdisplay_cursor_init(&scr->pcs, existing);
442 
443 #ifdef __alpha__
444 	if (!vc->hdl.vh_mono)
445 		/*
446 		 * DEC firmware uses a blue background.
447 		 */
448 		res = vga_alloc_attr(scr, WSCOL_WHITE, WSCOL_BLUE,
449 				     WSATTR_WSCOLORS, attrp);
450 	else
451 #endif
452 	res = vga_alloc_attr(scr, 0, 0, 0, attrp);
453 #ifdef DIAGNOSTIC
454 	if (res)
455 		panic("vga_init_screen: attribute botch");
456 #endif
457 
458 	scr->pcs.mem = NULL;
459 
460 	scr->fontset1 = scr->fontset2 = 0;
461 	if (vga_selectfont(vc, scr, 0, 0)) {
462 		if (scr == &vga_console_screen)
463 			panic("vga_init_screen: no font");
464 		else
465 			printf("vga_init_screen: no font\n");
466 	}
467 
468 	vc->nscreens++;
469 	LIST_INSERT_HEAD(&vc->screens, scr, next);
470 }
471 
472 void
vga_init(vc,iot,memt)473 vga_init(vc, iot, memt)
474 	struct vga_config *vc;
475 	bus_space_tag_t iot, memt;
476 {
477 	struct vga_handle *vh = &vc->hdl;
478 	u_int8_t mor;
479 	int i;
480 
481         vh->vh_iot = iot;
482         vh->vh_memt = memt;
483 
484         if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
485                 panic("vga_common_setup: couldn't map vga io");
486 
487 	/* read "misc output register" */
488 	mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc);
489 	vh->vh_mono = !(mor & 1);
490 
491 	if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
492 			  &vh->vh_ioh_6845))
493                 panic("vga_common_setup: couldn't map 6845 io");
494 
495         if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
496                 panic("vga_common_setup: couldn't map memory");
497 
498         if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
499 				(vh->vh_mono ? 0x10000 : 0x18000), 0x8000,
500 				&vh->vh_memh))
501                 panic("vga_common_setup: mem subrange failed");
502 
503 	vc->nscreens = 0;
504 	LIST_INIT(&vc->screens);
505 	vc->active = NULL;
506 	vc->currenttype = vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen;
507 #if 0
508 	callout_init(&vc->vc_switch_callout);
509 #endif
510 
511 	vc->vc_fonts[0] = &vga_builtinfont;
512 	for (i = 1; i < 8; i++)
513 		vc->vc_fonts[i] = 0;
514 
515 	vc->currentfontset1 = vc->currentfontset2 = 0;
516 
517 	panic_hook_display = vga_panic_hook;
518 }
519 
520 void
vga_common_attach(self,iot,memt,type)521 vga_common_attach(self, iot, memt, type)
522 	struct device *self;
523 	bus_space_tag_t iot, memt;
524 	int type;
525 {
526 	vga_extended_attach(self, iot, memt, type, NULL);
527 }
528 
529 void
vga_extended_attach(self,iot,memt,type,map)530 vga_extended_attach(self, iot, memt, type, map)
531 	struct device *self;
532 	bus_space_tag_t iot, memt;
533 	int type;
534 	paddr_t (*map)(void *, off_t, int);
535 {
536 	int console;
537 	struct vga_config *vc;
538 	struct wsemuldisplaydev_attach_args aa;
539 
540 	console = vga_is_console(iot, type);
541 
542 	if (console) {
543 		vc = &vga_console_vc;
544 		vga_console_attached = 1;
545 	} else {
546 		vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_NOWAIT);
547 		if (vc == NULL)
548 			return;
549 		bzero(vc, sizeof(struct vga_config));
550 		vga_init(vc, iot, memt);
551 	}
552 
553 	vc->vc_softc = self;
554 	vc->vc_type = type;
555 	vc->vc_mmap = map;
556 
557 	aa.console = console;
558 	aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
559 	aa.accessops = &vga_accessops;
560 	aa.accesscookie = vc;
561 	aa.defaultscreens = 0;
562 
563         config_found(self, &aa, wsemuldisplaydevprint);
564 }
565 
566 int
vga_cnattach(iot,memt,type,check)567 vga_cnattach(iot, memt, type, check)
568 	bus_space_tag_t iot, memt;
569 	int type, check;
570 {
571 	long defattr;
572 	const struct wsscreen_descr *scr;
573 
574 	if (check && !vga_common_probe(iot, memt))
575 		return (ENXIO);
576 
577 	/* set up bus-independent VGA configuration */
578 	vga_init(&vga_console_vc, iot, memt);
579 	scr = vga_console_vc.currenttype;
580 	vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
581 
582 	vga_console_screen.pcs.active = 1;
583 	vga_console_vc.active = &vga_console_screen;
584 
585 	wsdisplay_cnattach(scr, &vga_console_screen,
586 			   vga_console_screen.pcs.vc_ccol,
587 			   vga_console_screen.pcs.vc_crow,
588 			   defattr);
589 
590 	vgaconsole = 1;
591 	vga_console_type = type;
592 	return (0);
593 }
594 
595 int
vga_is_console(iot,type)596 vga_is_console(iot, type)
597 	bus_space_tag_t iot;
598 	int type;
599 {
600 	if (vgaconsole &&
601 	    !vga_console_attached &&
602 	    iot == vga_console_vc.hdl.vh_iot &&
603 	    (vga_console_type == -1 || (type == vga_console_type)))
604 		return (1);
605 	return (0);
606 }
607 
608 int
vga_ioctl(v,cmd,data,flag,p)609 vga_ioctl(v, cmd, data, flag, p)
610 	void *v;
611 	u_long cmd;
612 	caddr_t data;
613 	int flag;
614 	struct proc *p;
615 {
616 	struct vga_config *vc = v;
617 #if NVGA_PCI > 0
618 	int error;
619 
620 	if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA &&
621 	    (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY)
622 		return (error);
623 #endif
624 
625 	switch (cmd) {
626 	case WSDISPLAYIO_GTYPE:
627 		*(int *)data = vc->vc_type;
628 		/* XXX should get detailed hardware information here */
629 		break;
630 
631 	case WSDISPLAYIO_GVIDEO:
632 	case WSDISPLAYIO_SVIDEO:
633 		break;
634 
635 	case WSDISPLAYIO_GINFO:
636 	case WSDISPLAYIO_GETCMAP:
637 	case WSDISPLAYIO_PUTCMAP:
638 	case WSDISPLAYIO_GCURPOS:
639 	case WSDISPLAYIO_SCURPOS:
640 	case WSDISPLAYIO_GCURMAX:
641 	case WSDISPLAYIO_GCURSOR:
642 	case WSDISPLAYIO_SCURSOR:
643 	default:
644 		/* NONE of these operations are by the generic VGA driver. */
645 		return ENOTTY;
646 	}
647 
648 	return (0);
649 }
650 
651 paddr_t
vga_mmap(v,offset,prot)652 vga_mmap(v, offset, prot)
653 	void *v;
654 	off_t offset;
655 	int prot;
656 {
657 	struct vga_config *vc = v;
658 
659 	if (vc->vc_mmap != NULL)
660 		return (*vc->vc_mmap)(v, offset, prot);
661 
662 	return -1;
663 }
664 
665 int
vga_alloc_screen(v,type,cookiep,curxp,curyp,defattrp)666 vga_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
667 	void *v;
668 	const struct wsscreen_descr *type;
669 	void **cookiep;
670 	int *curxp, *curyp;
671 	long *defattrp;
672 {
673 	struct vga_config *vc = v;
674 	struct vgascreen *scr;
675 
676 	if (vc->nscreens == 1) {
677 		/*
678 		 * When allocating the second screen, get backing store
679 		 * for the first one too.
680 		 * XXX We could be more clever and use video RAM.
681 		 */
682 		vc->screens.lh_first->pcs.mem =
683 		  malloc(type->ncols * type->nrows * 2, M_DEVBUF, M_WAITOK);
684 	}
685 
686 	scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
687 	vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
688 
689 	if (vc->nscreens == 1) {
690 		scr->pcs.active = 1;
691 		vc->active = scr;
692 		vc->currenttype = type;
693 	} else {
694 		scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
695 				      M_DEVBUF, M_WAITOK);
696 		pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
697 	}
698 
699 	*cookiep = scr;
700 	*curxp = scr->pcs.vc_ccol;
701 	*curyp = scr->pcs.vc_crow;
702 
703 	return (0);
704 }
705 
706 void
vga_free_screen(v,cookie)707 vga_free_screen(v, cookie)
708 	void *v;
709 	void *cookie;
710 {
711 	struct vgascreen *vs = cookie;
712 	struct vga_config *vc = vs->cfg;
713 
714 	LIST_REMOVE(vs, next);
715 	if (vs != &vga_console_screen)
716 		free(vs, M_DEVBUF);
717 	else
718 		panic("vga_free_screen: console");
719 
720 	if (vc->active == vs)
721 		vc->active = 0;
722 }
723 
724 void
vga_setfont(vc,scr)725 vga_setfont(vc, scr)
726 	struct vga_config *vc;
727 	struct vgascreen *scr;
728 {
729 	int fontslot1, fontslot2;
730 
731 	fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
732 	fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
733 	if (vc->currentfontset1 != fontslot1 ||
734 	    vc->currentfontset2 != fontslot2) {
735 		vga_setfontset(&vc->hdl, fontslot1, fontslot2);
736 		vc->currentfontset1 = fontslot1;
737 		vc->currentfontset2 = fontslot2;
738 	}
739 }
740 
741 int
vga_show_screen(v,cookie,waitok,cb,cbarg)742 vga_show_screen(v, cookie, waitok, cb, cbarg)
743 	void *v;
744 	void *cookie;
745 	int waitok;
746 	void (*cb)(void *, int, int);
747 	void *cbarg;
748 {
749 	struct vgascreen *scr = cookie, *oldscr;
750 	struct vga_config *vc = scr->cfg;
751 
752 	oldscr = vc->active; /* can be NULL! */
753 	if (scr == oldscr) {
754 		return (0);
755 	}
756 
757 	vc->wantedscreen = cookie;
758 	vc->switchcb = cb;
759 	vc->switchcbarg = cbarg;
760 	if (cb) {
761 		timeout_set(&vc->vc_switch_timeout,
762 		    (void(*)(void *))vga_doswitch, vc);
763 		timeout_add(&vc->vc_switch_timeout, 0);
764 		return (EAGAIN);
765 	}
766 
767 	vga_doswitch(vc);
768 	return (0);
769 }
770 
771 void
vga_doswitch(vc)772 vga_doswitch(vc)
773 	struct vga_config *vc;
774 {
775 	struct vgascreen *scr, *oldscr;
776 	struct vga_handle *vh = &vc->hdl;
777 	const struct wsscreen_descr *type;
778 
779 	scr = vc->wantedscreen;
780 	if (!scr) {
781 		printf("vga_doswitch: disappeared\n");
782 		(*vc->switchcb)(vc->switchcbarg, EIO, 0);
783 		return;
784 	}
785 	type = scr->pcs.type;
786 	oldscr = vc->active; /* can be NULL! */
787 #ifdef DIAGNOSTIC
788 	if (oldscr) {
789 		if (!oldscr->pcs.active)
790 			panic("vga_show_screen: not active");
791 		if (oldscr->pcs.type != vc->currenttype)
792 			panic("vga_show_screen: bad type");
793 	}
794 #endif
795 	if (scr == oldscr) {
796 		return;
797 	}
798 #ifdef DIAGNOSTIC
799 	if (scr->pcs.active)
800 		panic("vga_show_screen: active");
801 #endif
802 
803 	scr->vga_rollover = 0;
804 
805 	if (oldscr) {
806 		const struct wsscreen_descr *oldtype = oldscr->pcs.type;
807 
808 		oldscr->pcs.active = 0;
809 		bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
810 					oldscr->pcs.dispoffset, oldscr->pcs.mem,
811 					oldtype->ncols * oldtype->nrows);
812 	}
813 
814 	if (vc->currenttype != type) {
815 		vga_setscreentype(vh, type);
816 		vc->currenttype = type;
817 	}
818 
819 	vga_setfont(vc, scr);
820 	/* XXX switch colours! */
821 
822 	scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
823 	if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
824 		vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
825 		vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
826 	}
827 
828 	bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
829 				scr->pcs.dispoffset, scr->pcs.mem,
830 				type->ncols * type->nrows);
831 	scr->pcs.active = 1;
832 
833 	vc->active = scr;
834 
835 	pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
836 			 scr->pcs.vc_crow, scr->pcs.vc_ccol);
837 
838 	vc->wantedscreen = 0;
839 	if (vc->switchcb)
840 		(*vc->switchcb)(vc->switchcbarg, 0, 0);
841 }
842 
843 int
vga_load_font(v,cookie,data)844 vga_load_font(v, cookie, data)
845 	void *v;
846 	void *cookie;
847 	struct wsdisplay_font *data;
848 {
849 	struct vga_config *vc = v;
850 	struct vgascreen *scr = cookie;
851 	char *name2;
852 	int res, slot;
853 	struct vgafont *f;
854 
855 	if (scr) {
856 		if ((name2 = data->name) != NULL) {
857 			while (*name2 && *name2 != ',')
858 				name2++;
859 			if (*name2)
860 				*name2++ = '\0';
861 		}
862 		res = vga_selectfont(vc, scr, data->name, name2);
863 		if (!res)
864 			vga_setfont(vc, scr);
865 		return (res);
866 	}
867 
868 	if (data->fontwidth != 8 || data->stride != 1)
869 		return (EINVAL); /* XXX 1 byte per line */
870 	if (data->firstchar != 0 || data->numchars != 256)
871 		return (EINVAL);
872 #ifndef WSCONS_SUPPORT_PCVTFONTS
873 	if (data->encoding == WSDISPLAY_FONTENC_PCVT) {
874 		printf("vga: pcvt font support not built in, see vga(4)\n");
875 		return (EINVAL);
876 	}
877 #endif
878 
879 	if (data->index < 0) {
880 		for (slot = 0; slot < 8; slot++)
881 			if (!vc->vc_fonts[slot])
882 				break;
883 	} else
884 		slot = data->index;
885 
886 	if (slot >= 8)
887 		return (ENOSPC);
888 
889 	if (!vc->vc_fonts[slot])
890 		f = malloc(sizeof(struct vgafont), M_DEVBUF, M_WAITOK);
891 	if (!f)
892 		return (ENOMEM);
893 	strlcpy(f->name, data->name, sizeof(f->name));
894 	f->height = data->fontheight;
895 	f->encoding = data->encoding;
896 #ifdef notyet
897 	f->firstchar = data->firstchar;
898 	f->numchars = data->numchars;
899 #endif
900 #ifdef VGAFONTDEBUG
901 	printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name,
902 	       f->height, f->encoding, slot);
903 #endif
904 	vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data);
905 	f->slot = slot;
906 	vc->vc_fonts[slot] = f;
907 	data->cookie = f;
908 	data->index = slot;
909 
910 	return (0);
911 }
912 
913 int
vga_delete_font(v,cookie,idx)914 vga_delete_font(v, cookie, idx)
915 	void *v;
916 	void *cookie;
917 	int idx;
918 {
919 	struct vga_config *vc = v;
920 	struct vgascreen *scr;
921 	struct vgafont *f;
922 
923 	if (idx <= 0 || idx >= 8)
924 		return (EINVAL);
925 
926 	f = vc->vc_fonts[idx];
927 	LIST_FOREACH(scr, &vc->screens, next) {
928 		if (f == scr->fontset1 || f == scr->fontset2)
929 			return (EINVAL);
930 	}
931 
932 	free(f, M_DEVBUF);
933 	vc->vc_fonts[idx] = 0;
934 
935 	return 0;
936 }
937 
938 void
vga_scrollback(v,cookie,lines)939 vga_scrollback(v, cookie, lines)
940 	void *v;
941 	void *cookie;
942 	int lines;
943 {
944 	struct vga_config *vc = v;
945 	struct vgascreen *scr = cookie;
946 	struct vga_handle *vh = &vc->hdl;
947 
948 	if (lines == 0) {
949 		if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
950 			return;
951 
952 		scr->pcs.visibleoffset = scr->pcs.dispoffset;	/* reset */
953 	}
954 	else {
955 		int vga_scr_end;
956 		int margin = scr->pcs.type->ncols * 2;
957 		int ul, we, p, st;
958 
959 		vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
960 		    scr->pcs.type->nrows * 2);
961 		if (scr->vga_rollover > vga_scr_end + margin) {
962 			ul = vga_scr_end;
963 			we = scr->vga_rollover + scr->pcs.type->ncols * 2;
964 		} else {
965 			ul = 0;
966 			we = 0x8000;
967 		}
968 		p = (scr->pcs.visibleoffset - ul + we) % we + lines *
969 		    (scr->pcs.type->ncols * 2);
970 		st = (scr->pcs.dispoffset - ul + we) % we;
971 		if (p < margin)
972 			p = 0;
973 		if (p > st - margin)
974 			p = st;
975 		scr->pcs.visibleoffset = (p + ul) % we;
976 	}
977 
978 	/* update visible position */
979 	vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
980 	vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
981 }
982 
983 int
vga_alloc_attr(id,fg,bg,flags,attrp)984 vga_alloc_attr(id, fg, bg, flags, attrp)
985 	void *id;
986 	int fg, bg;
987 	int flags;
988 	long *attrp;
989 {
990 	struct vgascreen *scr = id;
991 	struct vga_config *vc = scr->cfg;
992 
993 	if (vc->hdl.vh_mono) {
994 		if (flags & WSATTR_WSCOLORS)
995 			return (EINVAL);
996 		if (flags & WSATTR_REVERSE)
997 			*attrp = 0x70;
998 		else
999 			*attrp = 0x07;
1000 		if (flags & WSATTR_UNDERLINE)
1001 			*attrp |= FG_UNDERLINE;
1002 		if (flags & WSATTR_HILIT)
1003 			*attrp |= FG_INTENSE;
1004 	} else {
1005 		if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
1006 			return (EINVAL);
1007 		if (flags & WSATTR_WSCOLORS)
1008 			*attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7];
1009 		else
1010 			*attrp = 7;
1011 		if ((flags & WSATTR_HILIT) || (fg & 8) || (bg & 8))
1012 			*attrp += 8;
1013 	}
1014 	if (flags & WSATTR_BLINK)
1015 		*attrp |= FG_BLINK;
1016 	return (0);
1017 }
1018 
1019 void
vga_unpack_attr(id,attr,fg,bg,flags)1020 vga_unpack_attr(id, attr, fg, bg, flags)
1021 	void *id;
1022 	long attr;
1023 	int *fg, *bg, *flags;
1024 {
1025 	struct vgascreen *scr = id;
1026 	struct vga_config *vc = scr->cfg;
1027 
1028 	if (vc->hdl.vh_mono) {
1029 		*fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE : WSCOL_BLACK;
1030 		*bg = attr & 0x70 ? WSCOL_WHITE : WSCOL_BLACK;
1031 		if (flags != NULL)
1032 			*flags = (*bg == WSCOL_WHITE ? WSATTR_REVERSE : 0) |
1033 			    (((attr & 0x01) && ((attr & 0x07) != 0x07)) ?
1034 			    WSATTR_UNDERLINE : 0);
1035 	} else {
1036 		*fg = pctoansi[attr & 0x07];
1037 		*bg = pctoansi[(attr & 0x70) >> 4];
1038 		if (flags != NULL)
1039 			*flags = 0;
1040 	}
1041 	if (attr & FG_BLINK && flags != NULL)
1042 		*flags |= WSATTR_BLINK;
1043 	if (attr & FG_INTENSE) {
1044 		*fg += 8;
1045 		if (flags != NULL)
1046 			*flags |= WSATTR_HILIT;
1047 	}
1048 }
1049 
1050 void
vga_copyrows(id,srcrow,dstrow,nrows)1051 vga_copyrows(id, srcrow, dstrow, nrows)
1052 	void *id;
1053 	int srcrow, dstrow, nrows;
1054 {
1055 	struct vgascreen *scr = id;
1056 	bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
1057 	bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
1058 	int ncols = scr->pcs.type->ncols;
1059 	bus_size_t srcoff, dstoff;
1060 
1061 	srcoff = srcrow * ncols + 0;
1062 	dstoff = dstrow * ncols + 0;
1063 
1064 	if (scr->pcs.active) {
1065 		if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
1066 #ifdef PCDISPLAY_SOFTCURSOR
1067 			int cursoron = scr->pcs.cursoron;
1068 
1069 			if (cursoron)
1070 				pcdisplay_cursor(&scr->pcs, 0,
1071 				    scr->pcs.vc_crow, scr->pcs.vc_ccol);
1072 #endif
1073 			/* scroll up whole screen */
1074 			if ((scr->pcs.dispoffset + srcrow * ncols * 2)
1075 			    <= scr->maxdispoffset) {
1076 				scr->pcs.dispoffset += srcrow * ncols * 2;
1077 			} else {
1078 				bus_space_copy_2(memt, memh,
1079 					scr->pcs.dispoffset + srcoff * 2,
1080 					memh, scr->mindispoffset,
1081 					nrows * ncols);
1082 				scr->vga_rollover = scr->pcs.dispoffset;
1083 				scr->pcs.dispoffset = scr->mindispoffset;
1084 			}
1085 			scr->pcs.visibleoffset = scr->pcs.dispoffset;
1086 			vga_6845_write(&scr->cfg->hdl, startadrh,
1087 				       scr->pcs.dispoffset >> 9);
1088 			vga_6845_write(&scr->cfg->hdl, startadrl,
1089 				       scr->pcs.dispoffset >> 1);
1090 #ifdef PCDISPLAY_SOFTCURSOR
1091 			if (cursoron)
1092 				pcdisplay_cursor(&scr->pcs, 1,
1093 				    scr->pcs.vc_crow, scr->pcs.vc_ccol);
1094 #endif
1095 		} else {
1096 			bus_space_copy_2(memt, memh,
1097 					scr->pcs.dispoffset + srcoff * 2,
1098 					memh, scr->pcs.dispoffset + dstoff * 2,
1099 					nrows * ncols);
1100 		}
1101 	} else
1102 		bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff],
1103 		      nrows * ncols * 2);
1104 }
1105 
1106 #ifdef WSCONS_SUPPORT_PCVTFONTS
1107 
1108 #define NOTYET 0xffff
1109 static u_int16_t pcvt_unichars[0xa0] = {
1110 /* 0 */	_e006U,
1111 	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1112 	NOTYET,
1113 	0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
1114 	0x240a, /* SYMBOL FOR LINE FEED */
1115 	0x240b, /* SYMBOL FOR VERTICAL TABULATION */
1116 	0x240c, /* SYMBOL FOR FORM FEED */
1117 	0x240d, /* SYMBOL FOR CARRIAGE RETURN */
1118 	NOTYET, NOTYET,
1119 /* 1 */	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1120 	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1121 /* 2 */	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1122 	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1123 /* 3 */	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1124 	NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1125 /* 4 */	0x03c1, /* GREEK SMALL LETTER RHO */
1126 	0x03c8, /* GREEK SMALL LETTER PSI */
1127 	0x2202, /* PARTIAL DIFFERENTIAL */
1128 	0x03bb, /* GREEK SMALL LETTER LAMDA */
1129 	0x03b9, /* GREEK SMALL LETTER IOTA */
1130 	0x03b7, /* GREEK SMALL LETTER ETA */
1131 	0x03b5, /* GREEK SMALL LETTER EPSILON */
1132 	0x03c7, /* GREEK SMALL LETTER CHI */
1133 	0x2228, /* LOGICAL OR */
1134 	0x2227, /* LOGICAL AND */
1135 	0x222a, /* UNION */
1136 	0x2283, /* SUPERSET OF */
1137 	0x2282, /* SUBSET OF */
1138 	0x03a5, /* GREEK CAPITAL LETTER UPSILON */
1139 	0x039e, /* GREEK CAPITAL LETTER XI */
1140 	0x03a8, /* GREEK CAPITAL LETTER PSI */
1141 /* 5 */	0x03a0, /* GREEK CAPITAL LETTER PI */
1142 	0x21d2, /* RIGHTWARDS DOUBLE ARROW */
1143 	0x21d4, /* LEFT RIGHT DOUBLE ARROW */
1144 	0x039b, /* GREEK CAPITAL LETTER LAMDA */
1145 	0x0398, /* GREEK CAPITAL LETTER THETA */
1146 	0x2243, /* ASYMPTOTICALLY EQUAL TO */
1147 	0x2207, /* NABLA */
1148 	0x2206, /* INCREMENT */
1149 	0x221d, /* PROPORTIONAL TO */
1150 	0x2234, /* THEREFORE */
1151 	0x222b, /* INTEGRAL */
1152 	0x2215, /* DIVISION SLASH */
1153 	0x2216, /* SET MINUS */
1154 	_e00eU,
1155 	_e00dU,
1156 	_e00bU,
1157 /* 6 */	_e00cU,
1158 	_e007U,
1159 	_e008U,
1160 	_e009U,
1161 	_e00aU,
1162 	0x221a, /* SQUARE ROOT */
1163 	0x03c9, /* GREEK SMALL LETTER OMEGA */
1164 	0x00a5, /* YEN SIGN */
1165 	0x03be, /* GREEK SMALL LETTER XI */
1166 	0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
1167 	0x00fe, /* LATIN SMALL LETTER THORN */
1168 	0x00f0, /* LATIN SMALL LETTER ETH */
1169 	0x00de, /* LATIN CAPITAL LETTER THORN */
1170 	0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
1171 	0x00d7, /* MULTIPLICATION SIGN */
1172 	0x00d0, /* LATIN CAPITAL LETTER ETH */
1173 /* 7 */	0x00be, /* VULGAR FRACTION THREE QUARTERS */
1174 	0x00b8, /* CEDILLA */
1175 	0x00b4, /* ACUTE ACCENT */
1176 	0x00af, /* MACRON */
1177 	0x00ae, /* REGISTERED SIGN */
1178 	0x00ad, /* SOFT HYPHEN */
1179 	0x00ac, /* NOT SIGN */
1180 	0x00a8, /* DIAERESIS */
1181 	0x2260, /* NOT EQUAL TO */
1182 	_e005U,
1183 	_e004U,
1184 	_e003U,
1185 	_e002U,
1186 	_e001U,
1187 	0x03c5, /* GREEK SMALL LETTER UPSILON */
1188 	0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
1189 /* 8 */	0x0153, /* LATIN SMALL LIGATURE OE */
1190 	0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
1191 	0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
1192 	0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1193 	0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1194 	0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
1195 	0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
1196 	0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
1197 	0x0152, /* LATIN CAPITAL LIGATURE OE */
1198 	0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
1199 	0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1200 	0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
1201 	0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
1202 	0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1203 	0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1204 	0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
1205 /* 9 */	0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
1206 	0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1207 	0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1208 	0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
1209 	0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
1210 	0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1211 	0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
1212 	0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
1213 	0x00b9, /* SUPERSCRIPT ONE */
1214 	0x00b7, /* MIDDLE DOT */
1215 	0x03b6, /* GREEK SMALL LETTER ZETA */
1216 	0x00b3, /* SUPERSCRIPT THREE */
1217 	0x00a9, /* COPYRIGHT SIGN */
1218 	0x00a4, /* CURRENCY SIGN */
1219 	0x03ba, /* GREEK SMALL LETTER KAPPA */
1220 	_e000U
1221 };
1222 
1223 int vga_pcvt_mapchar(int, unsigned int *);
1224 
1225 int
vga_pcvt_mapchar(uni,index)1226 vga_pcvt_mapchar(uni, index)
1227 	int uni;
1228 	unsigned int *index;
1229 {
1230 	int i;
1231 
1232 	for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */
1233 		if (uni == pcvt_unichars[i]) {
1234 			*index = i;
1235 			return (5);
1236 		}
1237 	*index = 0x99; /* middle dot */
1238 	return (0);
1239 }
1240 
1241 #endif /* WSCONS_SUPPORT_PCVTFONTS */
1242 
1243 int _vga_mapchar(void *, struct vgafont *, int, unsigned int *);
1244 
1245 int
_vga_mapchar(id,font,uni,index)1246 _vga_mapchar(id, font, uni, index)
1247 	void *id;
1248 	struct vgafont *font;
1249 	int uni;
1250 	unsigned int *index;
1251 {
1252 
1253 	switch (font->encoding) {
1254 	case WSDISPLAY_FONTENC_ISO:
1255 		if (uni < 256) {
1256 			*index = uni;
1257 			return (5);
1258 		} else {
1259 			*index = ' ';
1260 			return (0);
1261 		}
1262 		break;
1263 	case WSDISPLAY_FONTENC_IBM:
1264 		return (pcdisplay_mapchar(id, uni, index));
1265 #ifdef WSCONS_SUPPORT_PCVTFONTS
1266 	case WSDISPLAY_FONTENC_PCVT:
1267 		return (vga_pcvt_mapchar(uni, index));
1268 #endif
1269 	default:
1270 #ifdef VGAFONTDEBUG
1271 		printf("_vga_mapchar: encoding=%d\n", font->encoding);
1272 #endif
1273 		*index = ' ';
1274 		return (0);
1275 	}
1276 }
1277 
1278 int
vga_mapchar(id,uni,index)1279 vga_mapchar(id, uni, index)
1280 	void *id;
1281 	int uni;
1282 	unsigned int *index;
1283 {
1284 	struct vgascreen *scr = id;
1285 	unsigned int idx1, idx2;
1286 	int res1, res2;
1287 
1288 	res1 = 0;
1289 	idx1 = ' '; /* space */
1290 	if (scr->fontset1)
1291 		res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
1292 	res2 = -1;
1293 	if (scr->fontset2) {
1294 		KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
1295 		res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
1296 	}
1297 	if (res2 >= res1) {
1298 		*index = idx2 | 0x0800; /* attribute bit 3 */
1299 		return (res2);
1300 	}
1301 	*index = idx1;
1302 	return (res1);
1303 }
1304 
1305 void
vga_putchar(c,row,col,uc,attr)1306 vga_putchar(c, row, col, uc, attr)
1307 	void *c;
1308 	int row;
1309 	int col;
1310 	u_int uc;
1311 	long attr;
1312 {
1313 	struct vgascreen *scr = c;
1314 
1315 	if (scr->pcs.visibleoffset != scr->pcs.dispoffset)
1316 		vga_scrollback(scr->cfg, scr, 0);
1317 
1318 	pcdisplay_putchar(c, row, col, uc, attr);
1319 }
1320 
1321 void
vga_burner(v,on,flags)1322 vga_burner(v, on, flags)
1323 	void *v;
1324 	u_int on, flags;
1325 {
1326 	struct vga_config *vc = v;
1327 	struct vga_handle *vh = &vc->hdl;
1328 	u_int8_t r;
1329 	int s;
1330 
1331 	s = splhigh();
1332 	vga_ts_write(vh, syncreset, 0x01);
1333 	if (on) {
1334 		vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20));
1335 		r = vga_6845_read(vh, mode) | 0x80;
1336 		DELAY(10000);
1337 		vga_6845_write(vh, mode, r);
1338 	} else {
1339 		vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20));
1340 		if (flags & WSDISPLAY_BURN_VBLANK) {
1341 			r = vga_6845_read(vh, mode) & ~0x80;
1342 			DELAY(10000);
1343 			vga_6845_write(vh, mode, r);
1344 		}
1345 	}
1346 	vga_ts_write(vh, syncreset, 0x03);
1347 	splx(s);
1348 }
1349 
1350 int
vga_getchar(c,row,col,cell)1351 vga_getchar(c, row, col, cell)
1352 	void *c;
1353 	int row, col;
1354 	struct wsdisplay_charcell *cell;
1355 {
1356 	struct vga_config *vc = c;
1357 
1358 	return (pcdisplay_getchar(vc->active, row, col, cell));
1359 }
1360 
1361 void
vga_panic_hook(void)1362 vga_panic_hook(void)
1363 {
1364 	printf("vga_panic_hook: dummy\n");
1365 }
1366 
1367 struct cfdriver vga_cd = {
1368 	NULL, "vga", DV_DULL
1369 };
1370