1 /* $NetBSD: grfabs_et.c,v 1.34 2010/04/13 11:31:11 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Leo Weppelman. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Most of the lower-level et4000 stuff was derived from: 30 * .../amiga/dev/grf_et.c 31 * 32 * Which was copyrighted by: 33 * Copyright (c) 1996 Tobias Abt 34 * Copyright (c) 1995 Ezra Story 35 * Copyright (c) 1995 Kari Mettinen 36 * Copyright (c) 1994 Markus Wild 37 * Copyright (c) 1994 Lutz Vieweg 38 * 39 * Thanks guys! 40 * 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: grfabs_et.c,v 1.34 2010/04/13 11:31:11 tsutsui Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/queue.h> 48 #include <sys/malloc.h> 49 #include <sys/device.h> 50 #include <sys/systm.h> 51 52 #include <uvm/uvm_extern.h> 53 54 /* 55 * For PCI probing... 56 */ 57 #include <dev/pci/pcireg.h> 58 #include <dev/pci/pcivar.h> 59 #include <dev/pci/pcidevs.h> 60 61 #include <machine/iomap.h> 62 #include <machine/video.h> 63 #include <machine/mfp.h> 64 #include <machine/cpu.h> 65 #include <atari/atari/device.h> 66 #include <atari/dev/grfioctl.h> 67 #include <atari/dev/grfabs_reg.h> 68 #include <atari/dev/grfabs_et.h> 69 #include <atari/dev/grf_etreg.h> 70 71 #define SAVEBUF_SIZE (32*1024 + sizeof(save_area_t)) 72 73 /* 74 * Allow a 16Kb io-region and a 4MB frame buffer to be mapped. This 75 * is more or less required by the XFree server. 76 */ 77 #define REG_MAPPABLE (16 * 1024) 78 #define FRAME_MAPPABLE (4 * 1024 * 1024) 79 #define VGA_MAPPABLE (128 * 1024) 80 #define VGA_BASE 0xa0000 81 82 /* 83 * Linear memory base, near the end of the pci area 84 */ 85 #define PCI_LINMEMBASE 0x0e000000 86 87 /* 88 * Function decls 89 */ 90 static void init_view(view_t *, bmap_t *, dmode_t *, box_t *); 91 static colormap_t *alloc_colormap(dmode_t *); 92 static void et_display_view(view_t *); 93 static view_t *et_alloc_view(dmode_t *, dimen_t *, u_char); 94 static void et_free_view(view_t *); 95 static void et_loadmode(struct grfvideo_mode *, et_sv_reg_t *); 96 static void et_remove_view(view_t *); 97 static void et_save_view(view_t *); 98 static int et_use_colormap(view_t *, colormap_t *); 99 100 /* 101 * Our function switch table 102 */ 103 struct grfabs_sw et_vid_sw = { 104 et_display_view, 105 et_alloc_view, 106 et_free_view, 107 et_remove_view, 108 et_save_view, 109 et_use_colormap 110 }; 111 112 static struct grfvideo_mode hw_modes[] = { 113 { 114 0, "", 22450000, /* num, descr, pix-clock */ 115 640, 400, 4, /* width, height, depth */ 116 632/8, 672/8, 688/8, 808/8, 768/8,/* HBS, HBE, HSS, HSE, HT */ 117 399, 450, 408, 413, 449 /* VBS, VBE, VSS, VSE, VT */ 118 }, 119 { 120 0, "", 25175000, /* num, descr, pix-clock */ 121 640, 480, 4, /* width, height, depth */ 122 632/8, 672/8, 688/8, 752/8, 752/8,/* HBS, HBE, HSS, HSE, HT */ 123 481, 522, 490, 498, 522 /* VBS, VBE, VSS, VSE, VT */ 124 } 125 }; 126 127 static dmode_t vid_modes[] = { 128 { { NULL, NULL }, 129 "640x400", { 640, 400 }, 1, (void*)&hw_modes[0], &et_vid_sw }, 130 { { NULL, NULL }, 131 "640x480", { 640, 480 }, 1, (void*)&hw_modes[1], &et_vid_sw }, 132 { { NULL, NULL }, NULL, } 133 }; 134 135 #define ET_NUMCLOCKS 32 136 137 static u_int et_clockfreqs[ET_NUMCLOCKS] = { 138 6293750, 7080500, 7875000, 8125000, 139 9000000, 9375000, 10000000, 11225000, 140 12587500, 14161000, 15750000, 16250000, 141 18000000, 18750000, 20000000, 22450000, 142 25175000, 28322000, 31500000, 32500000, 143 36000000, 37500000, 40000000, 44900000, 144 50350000, 56644000, 63000000, 65000000, 145 72000000, 75000000, 80000000, 89800000 146 }; 147 148 static bmap_t con_bm; /* XXX */ 149 150 struct grfabs_et_priv { 151 pcitag_t pci_tag; 152 void *regkva; 153 void *memkva; 154 u_int linbase; 155 int regsz; 156 int memsz; 157 int board_type; 158 } et_priv; 159 160 /* 161 * Board types: 162 */ 163 #define BT_ET4000 1 164 #define BT_ET6000 2 165 166 /* 167 * XXX: called from ite console init routine. 168 * Initialize list of posible video modes. 169 */ 170 void 171 et_probe_video(MODES *modelp) 172 { 173 dmode_t *dm; 174 int i; 175 176 for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) { 177 LIST_INSERT_HEAD(modelp, dm, link); 178 } 179 } 180 181 static void 182 et_display_view(view_t *v) 183 { 184 dmode_t *dm = v->mode; 185 bmap_t *bm = v->bitmap; 186 int sv_size; 187 u_short *src, *dst; 188 save_area_t *sa; 189 190 if (dm->current_view && (dm->current_view != v)) { 191 /* 192 * Mark current view for this mode as no longer displayed 193 */ 194 dm->current_view->flags &= ~VF_DISPLAY; 195 } 196 dm->current_view = v; 197 v->flags |= VF_DISPLAY; 198 199 if ((sa = (save_area_t*)v->save_area) == NULL) 200 return; /* XXX: Can't happen.... */ 201 202 /* 203 * Restore register settings and turn the plane pointer 204 * to the card-memory 205 */ 206 et_hwrest(&sa->sv_regs); 207 bm->plane = et_priv.memkva; 208 209 et_use_colormap(v, v->colormap); 210 211 /* 212 * Copy the backing store to card-memory 213 */ 214 sv_size = sa->fb_size; 215 src = sa->sv_fb; 216 dst = (u_short *)bm->plane; 217 while (sv_size--) 218 *dst++ = *src++; 219 } 220 221 void 222 et_remove_view(view_t *v) 223 { 224 dmode_t *mode = v->mode; 225 226 if (mode->current_view == v) { 227 #if 0 228 if (v->flags & VF_DISPLAY) 229 panic("Cannot shutdown display"); /* XXX */ 230 #endif 231 mode->current_view = NULL; 232 } 233 v->flags &= ~VF_DISPLAY; 234 } 235 236 void 237 et_save_view(view_t *v) 238 { 239 bmap_t *bm = v->bitmap; 240 u_char font_height; 241 int sv_size; 242 u_short *src, *dst; 243 save_area_t *sa; 244 volatile u_char *ba; 245 246 if (!atari_realconfig) 247 return; 248 249 ba = et_priv.regkva; 250 251 if (RGfx(ba, GCT_ID_MISC) & 1) { 252 #if 0 /* XXX: Can't use printf here.... */ 253 printf("et_save_view: Don't know how to save" 254 " a graphics mode\n"); 255 #endif 256 return; 257 } 258 if (v->save_area == NULL) 259 v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_NOWAIT); 260 261 /* 262 * Calculate the size of the copy 263 */ 264 font_height = RCrt(ba, CRT_ID_MAX_ROW_ADDRESS) & 0x1f; 265 sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1)); 266 sv_size = min(SAVEBUF_SIZE, sv_size); 267 268 /* 269 * Save all we need to know.... 270 */ 271 sa = (save_area_t *)v->save_area; 272 et_hwsave(&sa->sv_regs); 273 sa->fb_size = sv_size; 274 src = (u_short *)bm->plane; 275 dst = sa->sv_fb; 276 while (sv_size--) 277 *dst++ = *src++; 278 bm->plane = (u_char *)sa->sv_fb; 279 } 280 281 void 282 et_free_view(view_t *v) 283 { 284 285 if (v) { 286 et_remove_view(v); 287 if (v->colormap != &gra_con_cmap) 288 free(v->colormap, M_DEVBUF); 289 if (v->save_area != NULL) 290 free(v->save_area, M_DEVBUF); 291 if (v != &gra_con_view) { 292 free(v->bitmap, M_DEVBUF); 293 free(v, M_DEVBUF); 294 } 295 } 296 } 297 298 static int 299 et_use_colormap(view_t *v, colormap_t *cm) 300 { 301 return (0); /* XXX: Nothing here for now... */ 302 } 303 304 static view_t * 305 et_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth) 306 { 307 view_t *v; 308 bmap_t *bm; 309 box_t box; 310 save_area_t *sa; 311 312 if (!atari_realconfig) { 313 v = &gra_con_view; 314 bm = &con_bm; 315 } else { 316 v = malloc(sizeof(*v), M_DEVBUF, M_WAITOK); 317 bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK); 318 } 319 v->bitmap = bm; 320 321 /* 322 * Initialize the bitmap 323 */ 324 bm->plane = et_priv.memkva; 325 bm->vga_address = (void *)kvtop(et_priv.memkva); 326 bm->vga_base = VGA_BASE; 327 bm->hw_address = (void *)(PCI_MEM_PHYS | et_priv.linbase); 328 bm->lin_base = et_priv.linbase; 329 bm->regs = et_priv.regkva; 330 bm->hw_regs = (void *)kvtop(et_priv.regkva); 331 bm->reg_size = REG_MAPPABLE; 332 bm->phys_mappable = FRAME_MAPPABLE; 333 bm->vga_mappable = VGA_MAPPABLE; 334 335 bm->bytes_per_row = (mode->size.width * depth) / NBBY; 336 bm->rows = mode->size.height; 337 bm->depth = depth; 338 339 /* 340 * Allocate a save_area. 341 * Note: If atari_realconfig is false, no save area is (can be) 342 * allocated. This means that the plane is the video memory, 343 * which is what's wanted in this case. 344 */ 345 if (atari_realconfig) { 346 v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK); 347 sa = (save_area_t*)v->save_area; 348 sa->fb_size = 0; 349 bm->plane = (u_char *)sa->sv_fb; 350 et_loadmode(mode->data, &sa->sv_regs); 351 } else 352 v->save_area = NULL; 353 354 v->colormap = alloc_colormap(mode); 355 if (v->colormap) { 356 INIT_BOX(&box,0,0,mode->size.width,mode->size.height); 357 init_view(v, bm, mode, &box); 358 return (v); 359 } 360 if (v != &gra_con_view) { 361 free(v, M_DEVBUF); 362 free(bm, M_DEVBUF); 363 } 364 return (NULL); 365 } 366 367 static void 368 init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox) 369 { 370 v->bitmap = bm; 371 v->mode = mode; 372 v->flags = 0; 373 memcpy(&v->display, dbox, sizeof(box_t)); 374 } 375 376 /* XXX: No more than a stub... */ 377 static colormap_t * 378 alloc_colormap(dmode_t *dm) 379 { 380 colormap_t *cm; 381 int i; 382 383 cm = &gra_con_cmap; 384 cm->entry = gra_con_colors; 385 386 cm->first = 0; 387 cm->size = 2; 388 389 for (i = 0; i < 2; i++) 390 cm->entry[i] = gra_def_color16[i % 16]; 391 return (cm); 392 } 393 394 /* 395 * Go look for a VGA card on the PCI-bus. This search is a 396 * stripped down version of the PCI-probe. It only looks on 397 * bus0 for et4000/et6000 cards. The first card found is used. 398 */ 399 int 400 et_probe_card(void) 401 { 402 pci_chipset_tag_t pc = NULL; /* XXX */ 403 pcitag_t tag; 404 int device, found, id, maxndevs; 405 406 found = 0; 407 tag = 0; 408 id = 0; 409 maxndevs = pci_bus_maxdevs(pc, 0); 410 411 for (device = 0; !found && (device < maxndevs); device++) { 412 413 tag = pci_make_tag(pc, 0, device, 0); 414 id = pci_conf_read(pc, tag, PCI_ID_REG); 415 if (id == 0 || id == 0xffffffff) 416 continue; 417 switch (PCI_PRODUCT(id)) { 418 case PCI_PRODUCT_TSENG_ET6000: 419 case PCI_PRODUCT_TSENG_ET4000_W32P_A: 420 case PCI_PRODUCT_TSENG_ET4000_W32P_B: 421 case PCI_PRODUCT_TSENG_ET4000_W32P_C: 422 case PCI_PRODUCT_TSENG_ET4000_W32P_D: 423 found = 1; 424 break; 425 default: 426 break; 427 } 428 } 429 if (!found) 430 return (0); 431 432 if (PCI_PRODUCT(id) == PCI_PRODUCT_TSENG_ET6000) 433 et_priv.board_type = BT_ET6000; 434 else { 435 #ifdef ET4000_HAS_2MB_MEM 436 volatile u_char *ba; 437 #endif 438 439 et_priv.board_type = BT_ET4000; 440 441 #ifdef ET4000_HAS_2MB_MEM 442 /* set KEY to access the tseng private registers */ 443 ba = (volatile void *)pci_io_addr; 444 vgaw(ba, GREG_HERCULESCOMPAT, 0x03); 445 vgaw(ba, GREG_DISPMODECONTROL, 0xa0); 446 447 /* enable memory interleave */ 448 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0xa0); 449 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x89); 450 #endif 451 } 452 453 et_priv.pci_tag = tag; 454 455 /* 456 * The things below are setup in atari_init.c 457 */ 458 et_priv.regkva = (void *)pci_io_addr; 459 et_priv.memkva = (void *)pci_mem_addr; 460 et_priv.linbase = PCI_LINMEMBASE; /* XXX pci_conf_read??? */ 461 et_priv.memsz = PCI_VGA_SIZE; 462 et_priv.regsz = PCI_IO_SIZE; 463 464 if (!atari_realconfig) { 465 et_loadmode(&hw_modes[0], NULL); 466 return (1); 467 } 468 469 return (1); 470 } 471 472 static void 473 et_loadmode(struct grfvideo_mode *mode, et_sv_reg_t *regs) 474 { 475 unsigned short HDE, VDE; 476 int lace, dblscan; 477 int uplim, lowlim; 478 int i; 479 unsigned char clock, tmp; 480 volatile u_char *ba; 481 et_sv_reg_t loc_regs; 482 483 if (regs == NULL) 484 regs = &loc_regs; 485 486 ba = et_priv.regkva; 487 HDE = mode->disp_width / 8 - 1; 488 VDE = mode->disp_height - 1; 489 490 /* figure out whether lace or dblscan is needed */ 491 492 uplim = mode->disp_height + (mode->disp_height / 4); 493 lowlim = mode->disp_height - (mode->disp_height / 4); 494 lace = (((mode->vtotal * 2) > lowlim) 495 && ((mode->vtotal * 2) < uplim)) ? 1 : 0; 496 dblscan = (((mode->vtotal / 2) > lowlim) 497 && ((mode->vtotal / 2) < uplim)) ? 1 : 0; 498 499 /* adjustments */ 500 if (lace) 501 VDE /= 2; 502 503 regs->misc_output = 0x23; /* Page 0, Color mode */ 504 regs->seg_sel = 0x00; 505 regs->state_ctl = 0x00; 506 507 regs->seq[SEQ_ID_RESET] = 0x03; /* reset off */ 508 regs->seq[SEQ_ID_CLOCKING_MODE] = 0x21; /* Turn off screen */ 509 regs->seq[SEQ_ID_MAP_MASK] = 0xff; /* CPU writes all planes*/ 510 regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0 */ 511 regs->seq[SEQ_ID_MEMORY_MODE] = 0x0e; /* Seq. Memory mode */ 512 513 /* 514 * Set the clock... 515 */ 516 for (clock = ET_NUMCLOCKS-1; clock > 0; clock--) { 517 if (et_clockfreqs[clock] <= mode->pixel_clock) 518 break; 519 } 520 regs->misc_output |= (clock & 3) << 2; 521 regs->aux_mode = 0xb4 | ((clock & 8) << 3); 522 regs->compat_6845 = (clock & 4) ? 0x0a : 0x08; 523 524 /* 525 * The display parameters... 526 */ 527 regs->crt[CRT_ID_HOR_TOTAL] = mode->htotal; 528 regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start) 529 ? mode->hblank_stop - 1 530 : HDE); 531 regs->crt[CRT_ID_START_HOR_BLANK] = mode->hblank_start; 532 regs->crt[CRT_ID_END_HOR_BLANK] = (mode->hblank_stop & 0x1f) | 0x80; 533 regs->crt[CRT_ID_START_HOR_RETR] = mode->hsync_start; 534 regs->crt[CRT_ID_END_HOR_RETR] = (mode->hsync_stop & 0x1f) 535 | ((mode->hblank_stop & 0x20) 536 ? 0x80 : 0x00); 537 regs->crt[CRT_ID_VER_TOTAL] = mode->vtotal; 538 regs->crt[CRT_ID_START_VER_RETR] = mode->vsync_start; 539 regs->crt[CRT_ID_END_VER_RETR] = (mode->vsync_stop & 0x0f) | 0x30; 540 regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE; 541 regs->crt[CRT_ID_START_VER_BLANK] = mode->vblank_start; 542 regs->crt[CRT_ID_END_VER_BLANK] = mode->vblank_stop; 543 regs->crt[CRT_ID_MODE_CONTROL] = 0xab; 544 regs->crt[CRT_ID_START_ADDR_HIGH] = 0x00; 545 regs->crt[CRT_ID_START_ADDR_LOW] = 0x00; 546 regs->crt[CRT_ID_LINE_COMPARE] = 0xff; 547 regs->crt[CRT_ID_UNDERLINE_LOC] = 0x00; 548 regs->crt[CRT_ID_PRESET_ROW_SCAN] = 0x00; 549 regs->crt[CRT_ID_OFFSET] = mode->disp_width/16; 550 regs->crt[CRT_ID_MAX_ROW_ADDRESS] = 551 0x40 | 552 (dblscan ? 0x80 : 0x00) | 553 ((mode->vblank_start & 0x200) ? 0x20 : 0x00); 554 regs->crt[CRT_ID_OVERFLOW] = 555 0x10 | 556 ((mode->vtotal & 0x100) ? 0x01 : 0x00) | 557 ((VDE & 0x100) ? 0x02 : 0x00) | 558 ((mode->vsync_start & 0x100) ? 0x04 : 0x00) | 559 ((mode->vblank_start & 0x100) ? 0x08 : 0x00) | 560 ((mode->vtotal & 0x200) ? 0x20 : 0x00) | 561 ((VDE & 0x200) ? 0x40 : 0x00) | 562 ((mode->vsync_start & 0x200) ? 0x80 : 0x00); 563 regs->overfl_high = 564 0x10 | 565 ((mode->vblank_start & 0x400) ? 0x01 : 0x00) | 566 ((mode->vtotal & 0x400) ? 0x02 : 0x00) | 567 ((VDE & 0x400) ? 0x04 : 0x00) | 568 ((mode->vsync_start & 0x400) ? 0x08 : 0x00) | 569 (lace ? 0x80 : 0x00); 570 regs->hor_overfl = 571 ((mode->htotal & 0x100) ? 0x01 : 0x00) | 572 ((mode->hblank_start & 0x100) ? 0x04 : 0x00) | 573 ((mode->hsync_start & 0x100) ? 0x10 : 0x00); 574 575 regs->grf[GCT_ID_SET_RESET] = 0x00; 576 regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00; 577 regs->grf[GCT_ID_COLOR_COMPARE] = 0x00; 578 regs->grf[GCT_ID_DATA_ROTATE] = 0x00; 579 regs->grf[GCT_ID_READ_MAP_SELECT] = 0x00; 580 regs->grf[GCT_ID_GRAPHICS_MODE] = mode->depth == 1 ? 0x00: 0x40; 581 regs->grf[GCT_ID_MISC] = 0x01; 582 regs->grf[GCT_ID_COLOR_XCARE] = 0x0f; 583 regs->grf[GCT_ID_BITMASK] = 0xff; 584 585 for (i = 0; i < 0x10; i++) 586 regs->attr[i] = i; 587 regs->attr[ACT_ID_ATTR_MODE_CNTL] = 0x01; 588 regs->attr[ACT_ID_OVERSCAN_COLOR] = 0x00; 589 regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f; 590 regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00; 591 regs->attr[ACT_ID_COLOR_SELECT] = 0x00; 592 regs->attr[ACT_ID_MISCELLANEOUS] = 0x00; 593 594 /* 595 * XXX: This works for depth == 4. I need some better docs 596 * to fix the other modes.... 597 */ 598 /* 599 * What we need would be probe functions for RAMDAC/clock chip 600 */ 601 vgar(ba, VDAC_ADDRESS); /* clear old state */ 602 vgar(ba, VDAC_MASK); 603 vgar(ba, VDAC_MASK); 604 vgar(ba, VDAC_MASK); 605 vgar(ba, VDAC_MASK); 606 607 vgaw(ba, VDAC_MASK, 0); /* set to palette */ 608 vgar(ba, VDAC_ADDRESS); /* clear state */ 609 610 vgaw(ba, VDAC_MASK, 0xff); 611 /* 612 * End of depth stuff 613 */ 614 615 /* 616 * Compute Hsync & Vsync polarity 617 * Note: This seems to be some kind of a black art :-( 618 */ 619 tmp = regs->misc_output & 0x3f; 620 #if 1 /* This is according to my BW monitor & Xfree... */ 621 if (VDE < 400) 622 tmp |= 0x40; /* -hsync +vsync */ 623 else if (VDE < 480) 624 tmp |= 0xc0; /* -hsync -vsync */ 625 #else /* This is according to my color monitor.... */ 626 if (VDE < 400) 627 tmp |= 0x00; /* +hsync +vsync */ 628 else if (VDE < 480) 629 tmp |= 0x80; /* +hsync -vsync */ 630 #endif 631 /* I'm unable to try the rest.... */ 632 regs->misc_output = tmp; 633 634 if (regs == &loc_regs) 635 et_hwrest(regs); 636 } 637 638 void 639 et_hwsave(et_sv_reg_t *et_regs) 640 { 641 volatile u_char *ba; 642 int i, s; 643 644 ba = et_priv.regkva; 645 646 s = splhigh(); 647 648 /* 649 * General VGA registers 650 */ 651 et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R); 652 for (i = 0; i < 25; i++) 653 et_regs->crt[i] = RCrt(ba, i); 654 for (i = 0; i < 21; i++) 655 et_regs->attr[i] = RAttr(ba, i | 0x20); 656 for (i = 0; i < 9; i++) 657 et_regs->grf[i] = RGfx(ba, i); 658 for (i = 0; i < 5; i++) 659 et_regs->seq[i] = RSeq(ba, i); 660 661 /* 662 * ET4000 extensions 663 */ 664 et_regs->ext_start = RCrt(ba, CTR_ID_EXT_START); 665 et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT); 666 et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH); 667 et_regs->hor_overfl = RCrt(ba, CRT_ID_HOR_OVERFLOW); 668 et_regs->state_ctl = RSeq(ba, SEQ_ID_STATE_CONTROL); 669 et_regs->aux_mode = RSeq(ba, SEQ_ID_AUXILIARY_MODE); 670 et_regs->seg_sel = vgar(ba, GREG_SEGMENTSELECT); 671 672 splx(s); 673 } 674 675 void 676 et_hwrest(et_sv_reg_t *et_regs) 677 { 678 volatile u_char *ba; 679 int i, s; 680 681 ba = et_priv.regkva; 682 683 s = splhigh(); 684 685 vgaw(ba, GREG_SEGMENTSELECT, 0); 686 vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output); 687 688 /* 689 * General VGA registers 690 */ 691 WSeq(ba, SEQ_ID_RESET, 0x01); 692 for (i = 1; i < 5; i++) 693 WSeq(ba, i, et_regs->seq[i]); 694 WSeq(ba, SEQ_ID_RESET, 0x03); 695 696 /* 697 * Make sure we're allowed to write all crt-registers 698 */ 699 WCrt(ba, CRT_ID_END_VER_RETR, 700 et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f); 701 for (i = 0; i < 25; i++) 702 WCrt(ba, i, et_regs->crt[i]); 703 for (i = 0; i < 9; i++) 704 WGfx(ba, i, et_regs->grf[i]); 705 for (i = 0; i < 21; i++) 706 WAttr(ba, i | 0x20, et_regs->attr[i]); 707 708 /* 709 * ET4000 extensions 710 */ 711 WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl); 712 WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode); 713 WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start); 714 WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845); 715 WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high); 716 WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl); 717 vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel); 718 719 i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20; 720 WSeq(ba, SEQ_ID_CLOCKING_MODE, i); 721 722 splx(s); 723 } 724