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