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