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