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