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