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