1 /* $OpenBSD: vga.c,v 1.50 2009/03/29 21:53:52 sthen Exp $ */ 2 /* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 6 * Copyright (c) 1992-1998 S�ren Schmidt 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer as 14 * the first lines of this file unmodified. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 /* 34 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 35 * All rights reserved. 36 * 37 * Author: Chris G. Demetriou 38 * 39 * Permission to use, copy, modify and distribute this software and 40 * its documentation is hereby granted, provided that both the copyright 41 * notice and this permission notice appear in all copies of the 42 * software, derivative works or modified versions, and any portions 43 * thereof, and that both notices appear in supporting documentation. 44 * 45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 48 * 49 * Carnegie Mellon requests users of this software to return to 50 * 51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 52 * School of Computer Science 53 * Carnegie Mellon University 54 * Pittsburgh PA 15213-3890 55 * 56 * any improvements or extensions that they make and grant Carnegie the 57 * rights to redistribute these changes. 58 */ 59 60 #include "vga.h" 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/kernel.h> 65 #include <sys/device.h> 66 #include <sys/malloc.h> 67 #include <sys/queue.h> 68 #include <machine/bus.h> 69 70 #include <dev/ic/mc6845reg.h> 71 #include <dev/ic/pcdisplayvar.h> 72 #include <dev/ic/vgareg.h> 73 #include <dev/ic/vgavar.h> 74 75 #include <dev/wscons/wsdisplayvar.h> 76 #include <dev/wscons/wsconsio.h> 77 #include <dev/wscons/unicode.h> 78 79 #include <dev/ic/pcdisplay.h> 80 81 static struct vgafont { 82 char name[WSFONT_NAME_SIZE]; 83 int height; 84 int encoding; 85 #ifdef notyet 86 int firstchar, numchars; 87 #endif 88 int slot; 89 } vga_builtinfont = { 90 "builtin", 91 16, 92 WSDISPLAY_FONTENC_IBM, 93 #ifdef notyet 94 0, 256, 95 #endif 96 0 97 }; 98 99 struct vgascreen { 100 struct pcdisplayscreen pcs; 101 102 LIST_ENTRY(vgascreen) next; 103 104 struct vga_config *cfg; 105 106 /* videostate */ 107 struct vgafont *fontset1, *fontset2; 108 /* font data */ 109 110 int mindispoffset, maxdispoffset; 111 int vga_rollover; 112 }; 113 114 int vgaconsole, vga_console_type, vga_console_attached; 115 struct vgascreen vga_console_screen; 116 struct vga_config vga_console_vc; 117 118 int vga_selectfont(struct vga_config *, struct vgascreen *, 119 const char *, const char *); 120 void vga_init_screen(struct vga_config *, struct vgascreen *, 121 const struct wsscreen_descr *, int, long *); 122 void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t); 123 void vga_setfont(struct vga_config *, struct vgascreen *); 124 125 int vga_mapchar(void *, int, unsigned int *); 126 void vga_putchar(void *, int, int, u_int, long); 127 int vga_alloc_attr(void *, int, int, int, long *); 128 void vga_copyrows(void *, int, int, int); 129 void vga_unpack_attr(void *, long, int *, int *, int *); 130 131 int displaysubmatch(struct device *, void *, void *); 132 133 static const struct wsdisplay_emulops vga_emulops = { 134 pcdisplay_cursor, 135 vga_mapchar, 136 vga_putchar, 137 pcdisplay_copycols, 138 pcdisplay_erasecols, 139 vga_copyrows, 140 pcdisplay_eraserows, 141 vga_alloc_attr, 142 vga_unpack_attr 143 }; 144 145 /* 146 * translate WS(=ANSI) color codes to standard pc ones 147 */ 148 static const unsigned char fgansitopc[] = { 149 #ifdef __alpha__ 150 /* 151 * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!! 152 * XXX We should probably not bother with this 153 * XXX (reinitialize the palette registers). 154 */ 155 FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED, 156 FG_MAGENTA, FG_BROWN, FG_LIGHTGREY 157 #else 158 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, 159 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY 160 #endif 161 }, bgansitopc[] = { 162 #ifdef __alpha__ 163 BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED, 164 BG_MAGENTA, BG_BROWN, BG_LIGHTGREY 165 #else 166 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, 167 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY 168 #endif 169 }; 170 171 /* 172 * translate standard pc color codes to WS(=ANSI) ones 173 */ 174 static const u_int8_t pctoansi[] = { 175 #ifdef __alpha__ 176 WSCOL_BLACK, WSCOL_RED, WSCOL_GREEN, WSCOL_BROWN, 177 WSCOL_BLUE, WSCOL_MAGENTA, WSCOL_CYAN, WSCOL_WHITE 178 #else 179 WSCOL_BLACK, WSCOL_BLUE, WSCOL_GREEN, WSCOL_CYAN, 180 WSCOL_RED, WSCOL_MAGENTA, WSCOL_BROWN, WSCOL_WHITE 181 #endif 182 }; 183 184 185 const struct wsscreen_descr vga_stdscreen = { 186 "80x25", 80, 25, 187 &vga_emulops, 188 8, 16, 189 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK 190 }, vga_stdscreen_mono = { 191 "80x25", 80, 25, 192 &vga_emulops, 193 8, 16, 194 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE 195 }, vga_stdscreen_bf = { 196 "80x25bf", 80, 25, 197 &vga_emulops, 198 8, 16, 199 WSSCREEN_WSCOLORS | WSSCREEN_BLINK 200 }, vga_40lscreen = { 201 "80x40", 80, 40, 202 &vga_emulops, 203 8, 10, 204 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK 205 }, vga_40lscreen_mono = { 206 "80x40", 80, 40, 207 &vga_emulops, 208 8, 10, 209 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE 210 }, vga_40lscreen_bf = { 211 "80x40bf", 80, 40, 212 &vga_emulops, 213 8, 10, 214 WSSCREEN_WSCOLORS | WSSCREEN_BLINK 215 }, vga_50lscreen = { 216 "80x50", 80, 50, 217 &vga_emulops, 218 8, 8, 219 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK 220 }, vga_50lscreen_mono = { 221 "80x50", 80, 50, 222 &vga_emulops, 223 8, 8, 224 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE 225 }, vga_50lscreen_bf = { 226 "80x50bf", 80, 50, 227 &vga_emulops, 228 8, 8, 229 WSSCREEN_WSCOLORS | WSSCREEN_BLINK 230 }; 231 232 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT)) 233 234 const struct wsscreen_descr *_vga_scrlist[] = { 235 &vga_stdscreen, 236 &vga_stdscreen_bf, 237 &vga_40lscreen, 238 &vga_40lscreen_bf, 239 &vga_50lscreen, 240 &vga_50lscreen_bf, 241 /* XXX other formats, graphics screen? */ 242 }, *_vga_scrlist_mono[] = { 243 &vga_stdscreen_mono, 244 &vga_40lscreen_mono, 245 &vga_50lscreen_mono, 246 /* XXX other formats, graphics screen? */ 247 }; 248 249 const struct wsscreen_list vga_screenlist = { 250 sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *), 251 _vga_scrlist 252 }, vga_screenlist_mono = { 253 sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *), 254 _vga_scrlist_mono 255 }; 256 257 int vga_ioctl(void *, u_long, caddr_t, int, struct proc *); 258 paddr_t vga_mmap(void *, off_t, int); 259 int vga_alloc_screen(void *, const struct wsscreen_descr *, 260 void **, int *, int *, long *); 261 void vga_free_screen(void *, void *); 262 int vga_show_screen(void *, void *, int, 263 void (*) (void *, int, int), void *); 264 int vga_load_font(void *, void *, struct wsdisplay_font *); 265 void vga_scrollback(void *, void *, int); 266 void vga_burner(void *v, u_int on, u_int flags); 267 int vga_getchar(void *, int, int, struct wsdisplay_charcell *); 268 269 void vga_doswitch(struct vga_config *); 270 271 const struct wsdisplay_accessops vga_accessops = { 272 vga_ioctl, 273 vga_mmap, 274 vga_alloc_screen, 275 vga_free_screen, 276 vga_show_screen, 277 vga_load_font, 278 vga_scrollback, 279 vga_getchar, 280 vga_burner 281 }; 282 283 /* 284 * The following functions implement back-end configuration grabbing 285 * and attachment. 286 */ 287 int 288 vga_common_probe(iot, memt) 289 bus_space_tag_t iot, memt; 290 { 291 bus_space_handle_t ioh_vga, ioh_6845, memh; 292 u_int8_t regval; 293 u_int16_t vgadata; 294 int gotio_vga, gotio_6845, gotmem, mono, rv; 295 int dispoffset; 296 297 gotio_vga = gotio_6845 = gotmem = rv = 0; 298 299 if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga)) 300 goto bad; 301 gotio_vga = 1; 302 303 /* read "misc output register" */ 304 regval = bus_space_read_1(iot, ioh_vga, 0xc); 305 mono = !(regval & 1); 306 307 if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845)) 308 goto bad; 309 gotio_6845 = 1; 310 311 if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh)) 312 goto bad; 313 gotmem = 1; 314 315 dispoffset = (mono ? 0x10000 : 0x18000); 316 317 vgadata = bus_space_read_2(memt, memh, dispoffset); 318 bus_space_write_2(memt, memh, dispoffset, 0xa55a); 319 if (bus_space_read_2(memt, memh, dispoffset) != 0xa55a) 320 goto bad; 321 bus_space_write_2(memt, memh, dispoffset, vgadata); 322 323 /* 324 * check if this is really a VGA 325 * (try to write "Color Select" register as XFree86 does) 326 * XXX check before if at least EGA? 327 */ 328 /* reset state */ 329 (void) bus_space_read_1(iot, ioh_6845, 10); 330 bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX, 331 20 | 0x20); /* colselect | enable */ 332 regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR); 333 /* toggle the implemented bits */ 334 bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f); 335 bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX, 336 20 | 0x20); 337 /* read back */ 338 if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR) != (regval ^ 0x0f)) 339 goto bad; 340 /* restore contents */ 341 bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval); 342 343 rv = 1; 344 bad: 345 if (gotio_vga) 346 bus_space_unmap(iot, ioh_vga, 0x10); 347 if (gotio_6845) 348 bus_space_unmap(iot, ioh_6845, 0x10); 349 if (gotmem) 350 bus_space_unmap(memt, memh, 0x20000); 351 352 return (rv); 353 } 354 355 /* 356 * We want at least ASCII 32..127 be present in the 357 * first font slot. 358 */ 359 #define vga_valid_primary_font(f) \ 360 (f->encoding == WSDISPLAY_FONTENC_IBM || \ 361 f->encoding == WSDISPLAY_FONTENC_ISO) 362 363 int 364 vga_selectfont(vc, scr, name1, name2) 365 struct vga_config *vc; 366 struct vgascreen *scr; 367 const char *name1, *name2; /* NULL: take first found */ 368 { 369 const struct wsscreen_descr *type = scr->pcs.type; 370 struct vgafont *f1, *f2; 371 int i; 372 373 f1 = f2 = 0; 374 375 for (i = 0; i < 8; i++) { 376 struct vgafont *f = vc->vc_fonts[i]; 377 if (!f || f->height != type->fontheight) 378 continue; 379 if (!f1 && 380 vga_valid_primary_font(f) && 381 (!name1 || !*name1 || 382 !strncmp(name1, f->name, WSFONT_NAME_SIZE))) { 383 f1 = f; 384 continue; 385 } 386 if (!f2 && 387 VGA_SCREEN_CANTWOFONTS(type) && 388 (!name2 || !*name2 || 389 !strncmp(name2, f->name, WSFONT_NAME_SIZE))) { 390 f2 = f; 391 continue; 392 } 393 } 394 395 /* 396 * The request fails if no primary font was found, 397 * or if a second font was requested but not found. 398 */ 399 if (f1 && (!name2 || !*name2 || f2)) { 400 #ifdef VGAFONTDEBUG 401 if (scr != &vga_console_screen || vga_console_attached) { 402 printf("vga (%s): font1=%s (slot %d)", type->name, 403 f1->name, f1->slot); 404 if (f2) 405 printf(", font2=%s (slot %d)", 406 f2->name, f2->slot); 407 printf("\n"); 408 } 409 #endif 410 scr->fontset1 = f1; 411 scr->fontset2 = f2; 412 return (0); 413 } 414 return (ENXIO); 415 } 416 417 void 418 vga_init_screen(vc, scr, type, existing, attrp) 419 struct vga_config *vc; 420 struct vgascreen *scr; 421 const struct wsscreen_descr *type; 422 int existing; 423 long *attrp; 424 { 425 int cpos; 426 int res; 427 428 scr->cfg = vc; 429 scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl; 430 scr->pcs.type = type; 431 scr->pcs.active = 0; 432 scr->mindispoffset = 0; 433 scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2; 434 435 if (existing) { 436 cpos = vga_6845_read(&vc->hdl, cursorh) << 8; 437 cpos |= vga_6845_read(&vc->hdl, cursorl); 438 439 /* make sure we have a valid cursor position */ 440 if (cpos < 0 || cpos >= type->nrows * type->ncols) 441 cpos = 0; 442 443 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9; 444 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1; 445 446 /* make sure we have a valid memory offset */ 447 if (scr->pcs.dispoffset < scr->mindispoffset || 448 scr->pcs.dispoffset > scr->maxdispoffset) 449 scr->pcs.dispoffset = scr->mindispoffset; 450 } else { 451 cpos = 0; 452 scr->pcs.dispoffset = scr->mindispoffset; 453 } 454 scr->pcs.visibleoffset = scr->pcs.dispoffset; 455 scr->vga_rollover = 0; 456 457 scr->pcs.vc_crow = cpos / type->ncols; 458 scr->pcs.vc_ccol = cpos % type->ncols; 459 pcdisplay_cursor_init(&scr->pcs, existing); 460 461 #ifdef __alpha__ 462 if (!vc->hdl.vh_mono) 463 /* 464 * DEC firmware uses a blue background. 465 */ 466 res = vga_alloc_attr(scr, WSCOL_WHITE, WSCOL_BLUE, 467 WSATTR_WSCOLORS, attrp); 468 else 469 #endif 470 res = vga_alloc_attr(scr, 0, 0, 0, attrp); 471 #ifdef DIAGNOSTIC 472 if (res) 473 panic("vga_init_screen: attribute botch"); 474 #endif 475 476 scr->pcs.mem = NULL; 477 478 scr->fontset1 = scr->fontset2 = 0; 479 if (vga_selectfont(vc, scr, 0, 0)) { 480 if (scr == &vga_console_screen) 481 panic("vga_init_screen: no font"); 482 else 483 printf("vga_init_screen: no font\n"); 484 } 485 486 vc->nscreens++; 487 LIST_INSERT_HEAD(&vc->screens, scr, next); 488 } 489 490 void 491 vga_init(vc, iot, memt) 492 struct vga_config *vc; 493 bus_space_tag_t iot, memt; 494 { 495 struct vga_handle *vh = &vc->hdl; 496 u_int8_t mor; 497 int i; 498 499 vh->vh_iot = iot; 500 vh->vh_memt = memt; 501 502 if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga)) 503 panic("vga_common_setup: can't map vga i/o"); 504 505 /* read "misc output register" */ 506 mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc); 507 vh->vh_mono = !(mor & 1); 508 509 if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0, 510 &vh->vh_ioh_6845)) 511 panic("vga_common_setup: can't map 6845 i/o"); 512 513 if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh)) 514 panic("vga_common_setup: can't map mem space"); 515 516 if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh, 517 (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, 518 &vh->vh_memh)) 519 panic("vga_common_setup: mem subrange failed"); 520 521 vc->nscreens = 0; 522 LIST_INIT(&vc->screens); 523 vc->active = NULL; 524 vc->currenttype = vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen; 525 #if 0 526 callout_init(&vc->vc_switch_callout); 527 #endif 528 529 vc->vc_fonts[0] = &vga_builtinfont; 530 for (i = 1; i < 8; i++) 531 vc->vc_fonts[i] = 0; 532 533 vc->currentfontset1 = vc->currentfontset2 = 0; 534 535 vga_save_palette(vc); 536 } 537 538 void 539 vga_common_attach(self, iot, memt, type) 540 struct device *self; 541 bus_space_tag_t iot, memt; 542 int type; 543 { 544 vga_extended_attach(self, iot, memt, type, NULL); 545 } 546 547 void 548 vga_extended_attach(self, iot, memt, type, map) 549 struct device *self; 550 bus_space_tag_t iot, memt; 551 int type; 552 paddr_t (*map)(void *, off_t, int); 553 { 554 int console; 555 struct vga_config *vc; 556 struct wsemuldisplaydev_attach_args aa; 557 558 console = vga_is_console(iot, type); 559 560 if (console) { 561 vc = &vga_console_vc; 562 vga_console_attached = 1; 563 } else { 564 vc = malloc(sizeof(*vc), M_DEVBUF, M_NOWAIT | M_ZERO); 565 if (vc == NULL) 566 return; 567 vga_init(vc, iot, memt); 568 } 569 570 vc->vc_softc = self; 571 vc->vc_type = type; 572 vc->vc_mmap = map; 573 574 aa.console = console; 575 aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist); 576 aa.accessops = &vga_accessops; 577 aa.accesscookie = vc; 578 aa.defaultscreens = 0; 579 580 config_found_sm(self, &aa, wsemuldisplaydevprint, displaysubmatch); 581 } 582 583 int 584 displaysubmatch(struct device *parent, void *match, void *aux) 585 { 586 extern struct cfdriver wsdisplay_cd; 587 struct cfdata *cf = match; 588 589 /* only allow wsdisplay to attach */ 590 if (cf->cf_driver == &wsdisplay_cd) 591 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 592 return (0); 593 } 594 595 int 596 vga_cnattach(iot, memt, type, check) 597 bus_space_tag_t iot, memt; 598 int type, check; 599 { 600 long defattr; 601 const struct wsscreen_descr *scr; 602 603 if (check && !vga_common_probe(iot, memt)) 604 return (ENXIO); 605 606 /* set up bus-independent VGA configuration */ 607 vga_init(&vga_console_vc, iot, memt); 608 scr = vga_console_vc.currenttype; 609 vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr); 610 611 vga_console_screen.pcs.active = 1; 612 vga_console_vc.active = &vga_console_screen; 613 614 wsdisplay_cnattach(scr, &vga_console_screen, 615 vga_console_screen.pcs.vc_ccol, 616 vga_console_screen.pcs.vc_crow, 617 defattr); 618 619 vgaconsole = 1; 620 vga_console_type = type; 621 return (0); 622 } 623 624 int 625 vga_is_console(iot, type) 626 bus_space_tag_t iot; 627 int type; 628 { 629 if (vgaconsole && 630 !vga_console_attached && 631 iot == vga_console_vc.hdl.vh_iot && 632 (vga_console_type == -1 || (type == vga_console_type))) 633 return (1); 634 return (0); 635 } 636 637 int 638 vga_ioctl(v, cmd, data, flag, p) 639 void *v; 640 u_long cmd; 641 caddr_t data; 642 int flag; 643 struct proc *p; 644 { 645 struct vga_config *vc = v; 646 int mode; 647 #if NVGA_PCI > 0 648 int error; 649 650 if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA && 651 (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY) 652 return (error); 653 #endif 654 655 switch (cmd) { 656 case WSDISPLAYIO_GTYPE: 657 *(int *)data = vc->vc_type; 658 /* XXX should get detailed hardware information here */ 659 break; 660 661 case WSDISPLAYIO_SMODE: 662 mode = *(u_int *)data; 663 if (mode == WSDISPLAYIO_MODE_EMUL) 664 vga_restore_palette(vc); 665 break; 666 667 case WSDISPLAYIO_GVIDEO: 668 case WSDISPLAYIO_SVIDEO: 669 break; 670 671 case WSDISPLAYIO_GINFO: 672 case WSDISPLAYIO_GETCMAP: 673 case WSDISPLAYIO_PUTCMAP: 674 case WSDISPLAYIO_GCURPOS: 675 case WSDISPLAYIO_SCURPOS: 676 case WSDISPLAYIO_GCURMAX: 677 case WSDISPLAYIO_GCURSOR: 678 case WSDISPLAYIO_SCURSOR: 679 default: 680 /* NONE of these operations are by the generic VGA driver. */ 681 return ENOTTY; 682 } 683 684 return (0); 685 } 686 687 paddr_t 688 vga_mmap(v, offset, prot) 689 void *v; 690 off_t offset; 691 int prot; 692 { 693 struct vga_config *vc = v; 694 695 if (vc->vc_mmap != NULL) 696 return (*vc->vc_mmap)(v, offset, prot); 697 698 return -1; 699 } 700 701 int 702 vga_alloc_screen(v, type, cookiep, curxp, curyp, defattrp) 703 void *v; 704 const struct wsscreen_descr *type; 705 void **cookiep; 706 int *curxp, *curyp; 707 long *defattrp; 708 { 709 struct vga_config *vc = v; 710 struct vgascreen *scr; 711 712 if (vc->nscreens == 1) { 713 /* 714 * When allocating the second screen, get backing store 715 * for the first one too. 716 * XXX We could be more clever and use video RAM. 717 */ 718 LIST_FIRST(&vc->screens)->pcs.mem = 719 malloc(type->ncols * type->nrows * 2, M_DEVBUF, M_WAITOK); 720 } 721 722 scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK); 723 vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp); 724 725 if (vc->nscreens == 1) { 726 scr->pcs.active = 1; 727 vc->active = scr; 728 vc->currenttype = type; 729 } else { 730 scr->pcs.mem = malloc(type->ncols * type->nrows * 2, 731 M_DEVBUF, M_WAITOK); 732 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp); 733 } 734 735 *cookiep = scr; 736 *curxp = scr->pcs.vc_ccol; 737 *curyp = scr->pcs.vc_crow; 738 739 return (0); 740 } 741 742 void 743 vga_free_screen(v, cookie) 744 void *v; 745 void *cookie; 746 { 747 struct vgascreen *vs = cookie; 748 struct vga_config *vc = vs->cfg; 749 750 LIST_REMOVE(vs, next); 751 vc->nscreens--; 752 if (vs != &vga_console_screen) { 753 /* 754 * deallocating the one but last screen 755 * removes backing store for the last one 756 */ 757 if (vc->nscreens == 1) 758 free(LIST_FIRST(&vc->screens)->pcs.mem, M_DEVBUF); 759 760 /* Last screen has no backing store */ 761 if (vc->nscreens != 0) 762 free(vs->pcs.mem, M_DEVBUF); 763 764 free(vs, M_DEVBUF); 765 } else 766 panic("vga_free_screen: console"); 767 768 if (vc->active == vs) 769 vc->active = NULL; 770 } 771 772 void 773 vga_setfont(vc, scr) 774 struct vga_config *vc; 775 struct vgascreen *scr; 776 { 777 int fontslot1, fontslot2; 778 779 fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0); 780 fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1); 781 if (vc->currentfontset1 != fontslot1 || 782 vc->currentfontset2 != fontslot2) { 783 vga_setfontset(&vc->hdl, fontslot1, fontslot2); 784 vc->currentfontset1 = fontslot1; 785 vc->currentfontset2 = fontslot2; 786 } 787 } 788 789 int 790 vga_show_screen(v, cookie, waitok, cb, cbarg) 791 void *v; 792 void *cookie; 793 int waitok; 794 void (*cb)(void *, int, int); 795 void *cbarg; 796 { 797 struct vgascreen *scr = cookie, *oldscr; 798 struct vga_config *vc = scr->cfg; 799 800 oldscr = vc->active; /* can be NULL! */ 801 if (scr == oldscr) { 802 return (0); 803 } 804 805 vc->wantedscreen = cookie; 806 vc->switchcb = cb; 807 vc->switchcbarg = cbarg; 808 if (cb) { 809 timeout_set(&vc->vc_switch_timeout, 810 (void(*)(void *))vga_doswitch, vc); 811 timeout_add(&vc->vc_switch_timeout, 0); 812 return (EAGAIN); 813 } 814 815 vga_doswitch(vc); 816 return (0); 817 } 818 819 void 820 vga_doswitch(vc) 821 struct vga_config *vc; 822 { 823 struct vgascreen *scr, *oldscr; 824 struct vga_handle *vh = &vc->hdl; 825 const struct wsscreen_descr *type; 826 827 scr = vc->wantedscreen; 828 if (!scr) { 829 printf("vga_doswitch: disappeared\n"); 830 (*vc->switchcb)(vc->switchcbarg, EIO, 0); 831 return; 832 } 833 type = scr->pcs.type; 834 oldscr = vc->active; /* can be NULL! */ 835 #ifdef DIAGNOSTIC 836 if (oldscr) { 837 if (!oldscr->pcs.active) 838 panic("vga_show_screen: not active"); 839 if (oldscr->pcs.type != vc->currenttype) 840 panic("vga_show_screen: bad type"); 841 } 842 #endif 843 if (scr == oldscr) { 844 return; 845 } 846 #ifdef DIAGNOSTIC 847 if (scr->pcs.active) 848 panic("vga_show_screen: active"); 849 #endif 850 851 scr->vga_rollover = 0; 852 853 if (oldscr) { 854 const struct wsscreen_descr *oldtype = oldscr->pcs.type; 855 856 oldscr->pcs.active = 0; 857 bus_space_read_region_2(vh->vh_memt, vh->vh_memh, 858 oldscr->pcs.dispoffset, oldscr->pcs.mem, 859 oldtype->ncols * oldtype->nrows); 860 } 861 862 if (vc->currenttype != type) { 863 vga_setscreentype(vh, type); 864 vc->currenttype = type; 865 } 866 867 vga_setfont(vc, scr); 868 vga_restore_palette(vc); 869 870 scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset; 871 if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) { 872 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9); 873 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1); 874 } 875 876 bus_space_write_region_2(vh->vh_memt, vh->vh_memh, 877 scr->pcs.dispoffset, scr->pcs.mem, 878 type->ncols * type->nrows); 879 scr->pcs.active = 1; 880 881 vc->active = scr; 882 883 pcdisplay_cursor_reset(&scr->pcs); 884 pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron, 885 scr->pcs.vc_crow, scr->pcs.vc_ccol); 886 887 vc->wantedscreen = 0; 888 if (vc->switchcb) 889 (*vc->switchcb)(vc->switchcbarg, 0, 0); 890 } 891 892 int 893 vga_load_font(v, cookie, data) 894 void *v; 895 void *cookie; 896 struct wsdisplay_font *data; 897 { 898 struct vga_config *vc = v; 899 struct vgascreen *scr = cookie; 900 char *name2; 901 int res, slot; 902 struct vgafont *f; 903 904 if (scr) { 905 if ((name2 = data->name) != NULL) { 906 while (*name2 && *name2 != ',') 907 name2++; 908 if (*name2) 909 *name2++ = '\0'; 910 } 911 res = vga_selectfont(vc, scr, data->name, name2); 912 if (!res) 913 vga_setfont(vc, scr); 914 return (res); 915 } 916 917 if (data->fontwidth != 8 || data->stride != 1) 918 return (EINVAL); /* XXX 1 byte per line */ 919 if (data->firstchar != 0 || data->numchars != 256) 920 return (EINVAL); 921 #ifndef WSCONS_SUPPORT_PCVTFONTS 922 if (data->encoding == WSDISPLAY_FONTENC_PCVT) { 923 printf("vga: pcvt font support not built in, see vga(4)\n"); 924 return (EINVAL); 925 } 926 #endif 927 928 if (data->index < 0) { 929 for (slot = 0; slot < 8; slot++) 930 if (!vc->vc_fonts[slot]) 931 break; 932 } else 933 slot = data->index; 934 935 if (slot >= 8) 936 return (ENOSPC); 937 938 if (vc->vc_fonts[slot] != NULL) 939 return (EEXIST); 940 f = malloc(sizeof(struct vgafont), M_DEVBUF, M_WAITOK | M_CANFAIL); 941 if (f == NULL) 942 return (ENOMEM); 943 strlcpy(f->name, data->name, sizeof(f->name)); 944 f->height = data->fontheight; 945 f->encoding = data->encoding; 946 #ifdef notyet 947 f->firstchar = data->firstchar; 948 f->numchars = data->numchars; 949 #endif 950 #ifdef VGAFONTDEBUG 951 printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name, 952 f->height, f->encoding, slot); 953 #endif 954 vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data); 955 f->slot = slot; 956 vc->vc_fonts[slot] = f; 957 data->cookie = f; 958 data->index = slot; 959 960 return (0); 961 } 962 963 void 964 vga_scrollback(v, cookie, lines) 965 void *v; 966 void *cookie; 967 int lines; 968 { 969 struct vga_config *vc = v; 970 struct vgascreen *scr = cookie; 971 struct vga_handle *vh = &vc->hdl; 972 973 if (lines == 0) { 974 if (scr->pcs.visibleoffset == scr->pcs.dispoffset) 975 return; 976 977 scr->pcs.visibleoffset = scr->pcs.dispoffset; /* reset */ 978 } 979 else { 980 int vga_scr_end; 981 int margin = scr->pcs.type->ncols * 2; 982 int ul, we, p, st; 983 984 vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols * 985 scr->pcs.type->nrows * 2); 986 if (scr->vga_rollover > vga_scr_end + margin) { 987 ul = vga_scr_end; 988 we = scr->vga_rollover + scr->pcs.type->ncols * 2; 989 } else { 990 ul = 0; 991 we = 0x8000; 992 } 993 p = (scr->pcs.visibleoffset - ul + we) % we + lines * 994 (scr->pcs.type->ncols * 2); 995 st = (scr->pcs.dispoffset - ul + we) % we; 996 if (p < margin) 997 p = 0; 998 if (p > st - margin) 999 p = st; 1000 scr->pcs.visibleoffset = (p + ul) % we; 1001 } 1002 1003 /* update visible position */ 1004 vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9); 1005 vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1); 1006 } 1007 1008 int 1009 vga_alloc_attr(id, fg, bg, flags, attrp) 1010 void *id; 1011 int fg, bg; 1012 int flags; 1013 long *attrp; 1014 { 1015 struct vgascreen *scr = id; 1016 struct vga_config *vc = scr->cfg; 1017 1018 if (vc->hdl.vh_mono) { 1019 if (flags & WSATTR_WSCOLORS) 1020 return (EINVAL); 1021 if (flags & WSATTR_REVERSE) 1022 *attrp = 0x70; 1023 else 1024 *attrp = 0x07; 1025 if (flags & WSATTR_UNDERLINE) 1026 *attrp |= FG_UNDERLINE; 1027 if (flags & WSATTR_HILIT) 1028 *attrp |= FG_INTENSE; 1029 } else { 1030 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE)) 1031 return (EINVAL); 1032 if (flags & WSATTR_WSCOLORS) 1033 *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7]; 1034 else 1035 *attrp = 7; 1036 if ((flags & WSATTR_HILIT) || (fg & 8) || (bg & 8)) 1037 *attrp += 8; 1038 } 1039 if (flags & WSATTR_BLINK) 1040 *attrp |= FG_BLINK; 1041 return (0); 1042 } 1043 1044 void 1045 vga_unpack_attr(id, attr, fg, bg, ul) 1046 void *id; 1047 long attr; 1048 int *fg, *bg, *ul; 1049 { 1050 struct vgascreen *scr = id; 1051 struct vga_config *vc = scr->cfg; 1052 1053 if (vc->hdl.vh_mono) { 1054 *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE : WSCOL_BLACK; 1055 *bg = attr & 0x70 ? WSCOL_WHITE : WSCOL_BLACK; 1056 if (ul != NULL) 1057 *ul = *fg != WSCOL_WHITE && (attr & 0x01) ? 1 : 0; 1058 } else { 1059 *fg = pctoansi[attr & 0x07]; 1060 *bg = pctoansi[(attr & 0x70) >> 4]; 1061 if (ul != NULL) 1062 *ul = 0; 1063 } 1064 if (attr & FG_INTENSE) 1065 *fg += 8; 1066 } 1067 1068 void 1069 vga_copyrows(id, srcrow, dstrow, nrows) 1070 void *id; 1071 int srcrow, dstrow, nrows; 1072 { 1073 struct vgascreen *scr = id; 1074 bus_space_tag_t memt = scr->pcs.hdl->ph_memt; 1075 bus_space_handle_t memh = scr->pcs.hdl->ph_memh; 1076 int ncols = scr->pcs.type->ncols; 1077 bus_size_t srcoff, dstoff; 1078 1079 srcoff = srcrow * ncols + 0; 1080 dstoff = dstrow * ncols + 0; 1081 1082 if (scr->pcs.active) { 1083 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) { 1084 #ifdef PCDISPLAY_SOFTCURSOR 1085 int cursoron = scr->pcs.cursoron; 1086 1087 if (cursoron) 1088 pcdisplay_cursor(&scr->pcs, 0, 1089 scr->pcs.vc_crow, scr->pcs.vc_ccol); 1090 #endif 1091 /* scroll up whole screen */ 1092 if ((scr->pcs.dispoffset + srcrow * ncols * 2) 1093 <= scr->maxdispoffset) { 1094 scr->pcs.dispoffset += srcrow * ncols * 2; 1095 } else { 1096 bus_space_copy_2(memt, memh, 1097 scr->pcs.dispoffset + srcoff * 2, 1098 memh, scr->mindispoffset, 1099 nrows * ncols); 1100 scr->vga_rollover = scr->pcs.dispoffset; 1101 scr->pcs.dispoffset = scr->mindispoffset; 1102 } 1103 scr->pcs.visibleoffset = scr->pcs.dispoffset; 1104 vga_6845_write(&scr->cfg->hdl, startadrh, 1105 scr->pcs.dispoffset >> 9); 1106 vga_6845_write(&scr->cfg->hdl, startadrl, 1107 scr->pcs.dispoffset >> 1); 1108 #ifdef PCDISPLAY_SOFTCURSOR 1109 if (cursoron) 1110 pcdisplay_cursor(&scr->pcs, 1, 1111 scr->pcs.vc_crow, scr->pcs.vc_ccol); 1112 #endif 1113 } else { 1114 bus_space_copy_2(memt, memh, 1115 scr->pcs.dispoffset + srcoff * 2, 1116 memh, scr->pcs.dispoffset + dstoff * 2, 1117 nrows * ncols); 1118 } 1119 } else 1120 bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff], 1121 nrows * ncols * 2); 1122 } 1123 1124 #ifdef WSCONS_SUPPORT_PCVTFONTS 1125 1126 #define NOTYET 0xffff 1127 static u_int16_t pcvt_unichars[0xa0] = { 1128 /* 0 */ _e006U, 1129 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1130 NOTYET, 1131 0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */ 1132 0x240a, /* SYMBOL FOR LINE FEED */ 1133 0x240b, /* SYMBOL FOR VERTICAL TABULATION */ 1134 0x240c, /* SYMBOL FOR FORM FEED */ 1135 0x240d, /* SYMBOL FOR CARRIAGE RETURN */ 1136 NOTYET, NOTYET, 1137 /* 1 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1138 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1139 /* 2 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1140 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1141 /* 3 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1142 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, 1143 /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */ 1144 0x03c8, /* GREEK SMALL LETTER PSI */ 1145 0x2202, /* PARTIAL DIFFERENTIAL */ 1146 0x03bb, /* GREEK SMALL LETTER LAMDA */ 1147 0x03b9, /* GREEK SMALL LETTER IOTA */ 1148 0x03b7, /* GREEK SMALL LETTER ETA */ 1149 0x03b5, /* GREEK SMALL LETTER EPSILON */ 1150 0x03c7, /* GREEK SMALL LETTER CHI */ 1151 0x2228, /* LOGICAL OR */ 1152 0x2227, /* LOGICAL AND */ 1153 0x222a, /* UNION */ 1154 0x2283, /* SUPERSET OF */ 1155 0x2282, /* SUBSET OF */ 1156 0x03a5, /* GREEK CAPITAL LETTER UPSILON */ 1157 0x039e, /* GREEK CAPITAL LETTER XI */ 1158 0x03a8, /* GREEK CAPITAL LETTER PSI */ 1159 /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */ 1160 0x21d2, /* RIGHTWARDS DOUBLE ARROW */ 1161 0x21d4, /* LEFT RIGHT DOUBLE ARROW */ 1162 0x039b, /* GREEK CAPITAL LETTER LAMDA */ 1163 0x0398, /* GREEK CAPITAL LETTER THETA */ 1164 0x2243, /* ASYMPTOTICALLY EQUAL TO */ 1165 0x2207, /* NABLA */ 1166 0x2206, /* INCREMENT */ 1167 0x221d, /* PROPORTIONAL TO */ 1168 0x2234, /* THEREFORE */ 1169 0x222b, /* INTEGRAL */ 1170 0x2215, /* DIVISION SLASH */ 1171 0x2216, /* SET MINUS */ 1172 _e00eU, 1173 _e00dU, 1174 _e00bU, 1175 /* 6 */ _e00cU, 1176 _e007U, 1177 _e008U, 1178 _e009U, 1179 _e00aU, 1180 0x221a, /* SQUARE ROOT */ 1181 0x03c9, /* GREEK SMALL LETTER OMEGA */ 1182 0x00a5, /* YEN SIGN */ 1183 0x03be, /* GREEK SMALL LETTER XI */ 1184 0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */ 1185 0x00fe, /* LATIN SMALL LETTER THORN */ 1186 0x00f0, /* LATIN SMALL LETTER ETH */ 1187 0x00de, /* LATIN CAPITAL LETTER THORN */ 1188 0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */ 1189 0x00d7, /* MULTIPLICATION SIGN */ 1190 0x00d0, /* LATIN CAPITAL LETTER ETH */ 1191 /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */ 1192 0x00b8, /* CEDILLA */ 1193 0x00b4, /* ACUTE ACCENT */ 1194 0x00af, /* MACRON */ 1195 0x00ae, /* REGISTERED SIGN */ 1196 0x00ad, /* SOFT HYPHEN */ 1197 0x00ac, /* NOT SIGN */ 1198 0x00a8, /* DIAERESIS */ 1199 0x2260, /* NOT EQUAL TO */ 1200 _e005U, 1201 _e004U, 1202 _e003U, 1203 _e002U, 1204 _e001U, 1205 0x03c5, /* GREEK SMALL LETTER UPSILON */ 1206 0x00f8, /* LATIN SMALL LETTER O WITH STROKE */ 1207 /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */ 1208 0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */ 1209 0x00e3, /* LATIN SMALL LETTER A WITH TILDE */ 1210 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ 1211 0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ 1212 0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */ 1213 0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */ 1214 0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */ 1215 0x0152, /* LATIN CAPITAL LIGATURE OE */ 1216 0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */ 1217 0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ 1218 0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */ 1219 0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */ 1220 0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ 1221 0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ 1222 0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */ 1223 /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */ 1224 0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ 1225 0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ 1226 0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */ 1227 0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */ 1228 0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ 1229 0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */ 1230 0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */ 1231 0x00b9, /* SUPERSCRIPT ONE */ 1232 0x00b7, /* MIDDLE DOT */ 1233 0x03b6, /* GREEK SMALL LETTER ZETA */ 1234 0x00b3, /* SUPERSCRIPT THREE */ 1235 0x00a9, /* COPYRIGHT SIGN */ 1236 0x00a4, /* CURRENCY SIGN */ 1237 0x03ba, /* GREEK SMALL LETTER KAPPA */ 1238 _e000U 1239 }; 1240 1241 int vga_pcvt_mapchar(int, unsigned int *); 1242 1243 int 1244 vga_pcvt_mapchar(uni, index) 1245 int uni; 1246 unsigned int *index; 1247 { 1248 int i; 1249 1250 for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */ 1251 if (uni == pcvt_unichars[i]) { 1252 *index = i; 1253 return (5); 1254 } 1255 *index = 0x99; /* middle dot */ 1256 return (0); 1257 } 1258 1259 #endif /* WSCONS_SUPPORT_PCVTFONTS */ 1260 1261 int _vga_mapchar(void *, struct vgafont *, int, unsigned int *); 1262 1263 int 1264 _vga_mapchar(id, font, uni, index) 1265 void *id; 1266 struct vgafont *font; 1267 int uni; 1268 unsigned int *index; 1269 { 1270 1271 switch (font->encoding) { 1272 case WSDISPLAY_FONTENC_ISO: 1273 if (uni < 256) { 1274 *index = uni; 1275 return (5); 1276 } else { 1277 *index = ' '; 1278 return (0); 1279 } 1280 break; 1281 case WSDISPLAY_FONTENC_IBM: 1282 return (pcdisplay_mapchar(id, uni, index)); 1283 #ifdef WSCONS_SUPPORT_PCVTFONTS 1284 case WSDISPLAY_FONTENC_PCVT: 1285 return (vga_pcvt_mapchar(uni, index)); 1286 #endif 1287 default: 1288 #ifdef VGAFONTDEBUG 1289 printf("_vga_mapchar: encoding=%d\n", font->encoding); 1290 #endif 1291 *index = ' '; 1292 return (0); 1293 } 1294 } 1295 1296 int 1297 vga_mapchar(id, uni, index) 1298 void *id; 1299 int uni; 1300 unsigned int *index; 1301 { 1302 struct vgascreen *scr = id; 1303 unsigned int idx1, idx2; 1304 int res1, res2; 1305 1306 res1 = 0; 1307 idx1 = ' '; /* space */ 1308 if (scr->fontset1) 1309 res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1); 1310 res2 = -1; 1311 if (scr->fontset2) { 1312 KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type)); 1313 res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2); 1314 } 1315 if (res2 >= res1) { 1316 *index = idx2 | 0x0800; /* attribute bit 3 */ 1317 return (res2); 1318 } 1319 *index = idx1; 1320 return (res1); 1321 } 1322 1323 void 1324 vga_putchar(c, row, col, uc, attr) 1325 void *c; 1326 int row; 1327 int col; 1328 u_int uc; 1329 long attr; 1330 { 1331 struct vgascreen *scr = c; 1332 1333 if (scr->pcs.visibleoffset != scr->pcs.dispoffset) 1334 vga_scrollback(scr->cfg, scr, 0); 1335 1336 pcdisplay_putchar(c, row, col, uc, attr); 1337 } 1338 1339 void 1340 vga_burner(v, on, flags) 1341 void *v; 1342 u_int on, flags; 1343 { 1344 struct vga_config *vc = v; 1345 struct vga_handle *vh = &vc->hdl; 1346 u_int8_t r; 1347 int s; 1348 1349 s = splhigh(); 1350 vga_ts_write(vh, syncreset, 0x01); 1351 if (on) { 1352 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20)); 1353 r = vga_6845_read(vh, mode) | 0x80; 1354 DELAY(10000); 1355 vga_6845_write(vh, mode, r); 1356 } else { 1357 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20)); 1358 if (flags & WSDISPLAY_BURN_VBLANK) { 1359 r = vga_6845_read(vh, mode) & ~0x80; 1360 DELAY(10000); 1361 vga_6845_write(vh, mode, r); 1362 } 1363 } 1364 vga_ts_write(vh, syncreset, 0x03); 1365 splx(s); 1366 } 1367 1368 int 1369 vga_getchar(c, row, col, cell) 1370 void *c; 1371 int row, col; 1372 struct wsdisplay_charcell *cell; 1373 { 1374 struct vga_config *vc = c; 1375 1376 return (pcdisplay_getchar(vc->active, row, col, cell)); 1377 } 1378 1379 void 1380 vga_save_palette(struct vga_config *vc) 1381 { 1382 struct vga_handle *vh = &vc->hdl; 1383 uint i; 1384 uint8_t *palette = vc->vc_palette; 1385 1386 if (vh->vh_mono) 1387 return; 1388 1389 vga_raw_write(vh, VGA_DAC_MASK, 0xff); 1390 vga_raw_write(vh, VGA_DAC_READ, 0x00); 1391 for (i = 0; i < 3 * 256; i++) 1392 *palette++ = vga_raw_read(vh, VGA_DAC_DATA); 1393 1394 vga_raw_read(vh, 0x0a); /* reset flip/flop */ 1395 } 1396 1397 void 1398 vga_restore_palette(struct vga_config *vc) 1399 { 1400 struct vga_handle *vh = &vc->hdl; 1401 uint i; 1402 uint8_t *palette = vc->vc_palette; 1403 1404 if (vh->vh_mono) 1405 return; 1406 1407 vga_raw_write(vh, VGA_DAC_MASK, 0xff); 1408 vga_raw_write(vh, VGA_DAC_WRITE, 0x00); 1409 for (i = 0; i < 3 * 256; i++) 1410 vga_raw_write(vh, VGA_DAC_DATA, *palette++); 1411 1412 vga_raw_read(vh, 0x0a); /* reset flip/flop */ 1413 1414 vga_enable(vh); 1415 } 1416 1417 struct cfdriver vga_cd = { 1418 NULL, "vga", DV_DULL 1419 }; 1420