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