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