1 /* $NetBSD: grf_rh.c,v 1.6 1995/02/16 21:57:36 chopps Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Markus Wild 5 * Copyright (c) 1994 Lutz Vieweg 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Lutz Vieweg. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include "grfrh.h" 34 #if NGRFRH > 0 35 36 /* 37 * Graphics routines for the Retina BLT Z3 board, 38 * using the NCR 77C32BLT VGA controller. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/errno.h> 43 #include <sys/ioctl.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 #include <machine/cpu.h> 47 #include <amiga/amiga/device.h> 48 #include <amiga/dev/grfioctl.h> 49 #include <amiga/dev/grfvar.h> 50 #include <amiga/dev/grf_rhreg.h> 51 #include <amiga/dev/zbusvar.h> 52 53 int rh_mondefok __P((struct MonDef *)); 54 55 u_short CompFQ __P((u_int fq)); 56 int rh_load_mon __P((struct grf_softc *gp, struct MonDef *md)); 57 int rh_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm)); 58 int rh_setvmode __P((struct grf_softc *gp, unsigned int mode, int txtonly)); 59 60 61 extern unsigned char kernel_font_8x8_width, kernel_font_8x8_height; 62 extern unsigned char kernel_font_8x8_lo, kernel_font_8x8_hi; 63 extern unsigned char kernel_font_8x8[]; 64 #ifdef KFONT_8X11 65 extern unsigned char kernel_font_8x11_width, kernel_font_8x11_height; 66 extern unsigned char kernel_font_8x11_lo, kernel_font_8x11_hi; 67 extern unsigned char kernel_font_8x11[]; 68 #endif 69 70 /* 71 * This driver for the MacroSystem Retina board was only possible, 72 * because MacroSystem provided information about the pecularities 73 * of the board. THANKS! Competition in Europe among gfx board 74 * manufacturers is rather tough, so Lutz Vieweg, who wrote the 75 * initial driver, has made an agreement with MS not to document 76 * the driver source (see also his comment below). 77 * -> ALL comments after 78 * -> "/* -------------- START OF CODE -------------- * /" 79 * -> have been added by myself (mw) from studying the publically 80 * -> available "NCR 77C32BLT" Data Manual 81 */ 82 /* 83 * This code offers low-level routines to access the Retina BLT Z3 84 * graphics-board manufactured by MS MacroSystem GmbH from within NetBSD 85 * for the Amiga. 86 * 87 * Thanks to MacroSystem for providing me with the neccessary information 88 * to create theese routines. The sparse documentation of this code 89 * results from the agreements between MS and me. 90 */ 91 92 93 94 #define MDF_DBL 1 95 #define MDF_LACE 2 96 #define MDF_CLKDIV2 4 97 98 99 /* -------------- START OF CODE -------------- */ 100 101 /* Convert big-endian long into little-endian long. */ 102 103 #define M2I(val) \ 104 asm volatile (" rorw #8,%0 ; \ 105 swap %0 ; \ 106 rorw #8,%0 ; " : "=d" (val) : "0" (val)); 107 108 #define M2INS(val) \ 109 asm volatile (" rorw #8,%0 ; \ 110 swap %0 ; \ 111 rorw #8,%0 ; \ 112 swap %0 ; " : "=d" (val) : "0" (val)); 113 114 #define ACM_OFFSET (0x00b00000) 115 #define LM_OFFSET (0x00c00000) 116 117 static unsigned char optab[] = { 118 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 119 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 120 }; 121 static char optabs[] = { 122 0, -1, -1, -1, -1, 0, -1, -1, 123 -1, -1, 0, -1, -1, -1, -1, 0 124 }; 125 126 void 127 RZ3DisableHWC(gp) 128 struct grf_softc *gp; 129 { 130 volatile void *ba = gp->g_regkva; 131 132 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, 0x00); 133 } 134 135 void 136 RZ3SetupHWC(gp, col1, col2, hsx, hsy, data) 137 struct grf_softc *gp; 138 unsigned char col1; 139 unsigned col2; 140 unsigned char hsx; 141 unsigned char hsy; 142 const unsigned long *data; 143 { 144 volatile unsigned char *ba = gp->g_regkva; 145 unsigned long *c = (unsigned long *)(ba + LM_OFFSET + HWC_MEM_OFF); 146 const unsigned long *s = data; 147 struct MonDef *MonitorDef = (struct MonDef *) gp->g_data; 148 short x = (HWC_MEM_SIZE / (4*4)) - 1; 149 /* copy only, if there is a data pointer. */ 150 if (data) do { 151 *c++ = *s++; 152 *c++ = *s++; 153 *c++ = *s++; 154 *c++ = *s++; 155 } while (x-- > 0); 156 157 WSeq(ba, SEQ_ID_CURSOR_COLOR1, col1); 158 WSeq(ba, SEQ_ID_CURSOR_COLOR0, col2); 159 if (MonitorDef->DEP < 16) 160 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x85); 161 else 162 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0xa5); 163 WSeq(ba, SEQ_ID_CURSOR_X_LOC_HI, 0x00); 164 WSeq(ba, SEQ_ID_CURSOR_X_LOC_LO, 0x00); 165 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_HI, 0x00); 166 WSeq(ba, SEQ_ID_CURSOR_Y_LOC_LO, 0x00); 167 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, hsx); 168 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, hsy); 169 WSeq(ba, SEQ_ID_CURSOR_STORE_HI, 0x00); 170 WSeq(ba, SEQ_ID_CURSOR_STORE_LO, ((HWC_MEM_OFF / 4) & 0x0000f)); 171 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_HI, (((HWC_MEM_OFF / 4) & 0xff000) >> 12)); 172 WSeq(ba, SEQ_ID_CURSOR_ST_OFF_LO, (((HWC_MEM_OFF / 4) & 0x00ff0) >> 4)); 173 WSeq(ba, SEQ_ID_CURSOR_PIXELMASK, 0xff); 174 } 175 176 void 177 RZ3AlphaErase (gp, xd, yd, w, h) 178 struct grf_softc *gp; 179 unsigned short xd; 180 unsigned short yd; 181 unsigned short w; 182 unsigned short h; 183 { 184 const struct MonDef * md = (struct MonDef *) gp->g_data; 185 RZ3AlphaCopy(gp, xd, yd+md->TY, xd, yd, w, h); 186 } 187 188 void 189 RZ3AlphaCopy (gp, xs, ys, xd, yd, w, h) 190 struct grf_softc *gp; 191 unsigned short xs; 192 unsigned short ys; 193 unsigned short xd; 194 unsigned short yd; 195 unsigned short w; 196 unsigned short h; 197 { 198 volatile unsigned char *ba = gp->g_regkva; 199 const struct MonDef *md = (struct MonDef *) gp->g_data; 200 volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET); 201 unsigned short mod; 202 203 xs *= 4; 204 ys *= 4; 205 xd *= 4; 206 yd *= 4; 207 w *= 4; 208 209 { 210 /* anyone got Windoze GDI opcodes handy?... */ 211 unsigned long tmp = 0x0000ca00; 212 *(acm + ACM_RASTEROP_ROTATION/4) = tmp; 213 } 214 215 mod = 0xc0c2; 216 217 { 218 unsigned long pat = 8 * PAT_MEM_OFF; 219 unsigned long dst = 8 * (xd + yd * md->TX); 220 221 unsigned long src = 8 * (xs + ys * md->TX); 222 223 if (xd > xs) { 224 mod &= ~0x8000; 225 src += 8 * (w - 1); 226 dst += 8 * (w - 1); 227 pat += 8 * 2; 228 } 229 if (yd > ys) { 230 mod &= ~0x4000; 231 src += 8 * (h - 1) * md->TX * 4; 232 dst += 8 * (h - 1) * md->TX * 4; 233 pat += 8 * 4; 234 } 235 236 M2I(src); 237 *(acm + ACM_SOURCE/4) = src; 238 239 M2I(pat); 240 *(acm + ACM_PATTERN/4) = pat; 241 242 M2I(dst); 243 *(acm + ACM_DESTINATION/4) = dst; 244 } 245 { 246 247 unsigned long tmp = mod << 16; 248 *(acm + ACM_CONTROL/4) = tmp; 249 } 250 { 251 252 unsigned long tmp = w | (h << 16); 253 M2I(tmp); 254 *(acm + ACM_BITMAP_DIMENSION/4) = tmp; 255 } 256 257 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; 258 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; 259 260 while ((*(((volatile unsigned char *)acm) + 261 (ACM_START_STATUS + 2)) & 1) == 0); 262 } 263 264 void 265 RZ3BitBlit (gp, gbb) 266 struct grf_softc *gp; 267 struct grf_bitblt * gbb; 268 { 269 volatile unsigned char *ba = gp->g_regkva; 270 volatile unsigned char *lm = ba + LM_OFFSET; 271 volatile unsigned long *acm = (unsigned long *) (ba + ACM_OFFSET); 272 const struct MonDef *md = (struct MonDef *) gp->g_data; 273 unsigned short mod; 274 275 { 276 unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF); 277 unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16); 278 *pt++ = tmp; 279 *pt = tmp; 280 } 281 282 { 283 284 unsigned long tmp = optab[ gbb->op ] << 8; 285 *(acm + ACM_RASTEROP_ROTATION/4) = tmp; 286 } 287 288 mod = 0xc0c2; 289 290 { 291 unsigned long pat = 8 * PAT_MEM_OFF; 292 unsigned long dst = 8 * (gbb->dst_x + gbb->dst_y * md->TX); 293 294 if (optabs[gbb->op]) { 295 unsigned long src = 8 * (gbb->src_x + gbb->src_y * md->TX); 296 297 if (gbb->dst_x > gbb->src_x) { 298 mod &= ~0x8000; 299 src += 8 * (gbb->w - 1); 300 dst += 8 * (gbb->w - 1); 301 pat += 8 * 2; 302 } 303 if (gbb->dst_y > gbb->src_y) { 304 mod &= ~0x4000; 305 src += 8 * (gbb->h - 1) * md->TX; 306 dst += 8 * (gbb->h - 1) * md->TX; 307 pat += 8 * 4; 308 } 309 310 M2I(src); 311 *(acm + ACM_SOURCE/4) = src; 312 } 313 314 M2I(pat); 315 *(acm + ACM_PATTERN/4) = pat; 316 317 M2I(dst); 318 *(acm + ACM_DESTINATION/4) = dst; 319 } 320 { 321 322 unsigned long tmp = mod << 16; 323 *(acm + ACM_CONTROL/4) = tmp; 324 } 325 { 326 unsigned long tmp = gbb->w | (gbb->h << 16); 327 M2I(tmp); 328 *(acm + ACM_BITMAP_DIMENSION/4) = tmp; 329 } 330 331 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; 332 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; 333 334 while ((*(((volatile unsigned char *)acm) + 335 (ACM_START_STATUS + 2)) & 1) == 0); 336 } 337 338 void 339 RZ3BitBlit16 (gp, gbb) 340 struct grf_softc *gp; 341 struct grf_bitblt * gbb; 342 { 343 volatile unsigned char *ba = gp->g_regkva; 344 volatile unsigned char *lm = ba + LM_OFFSET; 345 volatile unsigned long * acm = (unsigned long *) (ba + ACM_OFFSET); 346 const struct MonDef * md = (struct MonDef *) gp->g_data; 347 unsigned short mod; 348 349 { 350 unsigned long * pt = (unsigned long *) (lm + PAT_MEM_OFF); 351 unsigned long tmp = gbb->mask | ((unsigned long)gbb->mask << 16); 352 *pt++ = tmp; 353 *pt++ = tmp; 354 *pt++ = tmp; 355 *pt = tmp; 356 } 357 358 { 359 360 unsigned long tmp = optab[ gbb->op ] << 8; 361 *(acm + ACM_RASTEROP_ROTATION/4) = tmp; 362 } 363 364 mod = 0xc0c2; 365 366 { 367 unsigned long pat = 8 * PAT_MEM_OFF; 368 unsigned long dst = 8 * 2 * (gbb->dst_x + gbb->dst_y * md->TX); 369 370 if (optabs[gbb->op]) { 371 unsigned long src = 8 * 2 * (gbb->src_x + gbb->src_y * md->TX); 372 373 if (gbb->dst_x > gbb->src_x) { 374 mod &= ~0x8000; 375 src += 8 * 2 * (gbb->w); 376 dst += 8 * 2 * (gbb->w); 377 pat += 8 * 2 * 2; 378 } 379 if (gbb->dst_y > gbb->src_y) { 380 mod &= ~0x4000; 381 src += 8 * 2 * (gbb->h - 1) * md->TX; 382 dst += 8 * 2 * (gbb->h - 1) * md->TX; 383 pat += 8 * 4 * 2; 384 } 385 386 M2I(src); 387 *(acm + ACM_SOURCE/4) = src; 388 } 389 390 M2I(pat); 391 *(acm + ACM_PATTERN/4) = pat; 392 393 M2I(dst); 394 *(acm + ACM_DESTINATION/4) = dst; 395 } 396 { 397 398 unsigned long tmp = mod << 16; 399 *(acm + ACM_CONTROL/4) = tmp; 400 } 401 { 402 403 unsigned long tmp = gbb->w | (gbb->h << 16); 404 M2I(tmp); 405 *(acm + ACM_BITMAP_DIMENSION/4) = tmp; 406 } 407 408 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; 409 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; 410 411 while ((*(((volatile unsigned char *)acm) + 412 (ACM_START_STATUS+ 2)) & 1) == 0); 413 } 414 415 void 416 RZ3SetCursorPos (gp, pos) 417 struct grf_softc *gp; 418 unsigned short pos; 419 { 420 volatile unsigned char *ba = gp->g_regkva; 421 422 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, (unsigned char)pos); 423 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (unsigned char)(pos >> 8)); 424 425 } 426 427 void 428 RZ3LoadPalette (gp, pal, firstcol, colors) 429 struct grf_softc *gp; 430 unsigned char * pal; 431 unsigned char firstcol; 432 unsigned char colors; 433 { 434 volatile unsigned char *ba = gp->g_regkva; 435 436 if (colors == 0) 437 return; 438 439 vgaw(ba, VDAC_ADDRESS_W, firstcol); 440 441 { 442 443 short x = colors-1; 444 const unsigned char * col = pal; 445 do { 446 447 vgaw(ba, VDAC_DATA, (*col++ >> 2)); 448 vgaw(ba, VDAC_DATA, (*col++ >> 2)); 449 vgaw(ba, VDAC_DATA, (*col++ >> 2)); 450 451 } while (x-- > 0); 452 453 } 454 } 455 456 void 457 RZ3SetPalette (gp, colornum, red, green, blue) 458 struct grf_softc *gp; 459 unsigned char colornum; 460 unsigned char red, green, blue; 461 { 462 volatile unsigned char *ba = gp->g_regkva; 463 464 vgaw(ba, VDAC_ADDRESS_W, colornum); 465 466 vgaw(ba, VDAC_DATA, (red >> 2)); 467 vgaw(ba, VDAC_DATA, (green >> 2)); 468 vgaw(ba, VDAC_DATA, (blue >> 2)); 469 470 } 471 472 /* XXXXXXXXX !! */ 473 static unsigned short xpan; 474 static unsigned short ypan; 475 476 void 477 RZ3SetPanning (gp, xoff, yoff) 478 struct grf_softc *gp; 479 unsigned short xoff, yoff; 480 { 481 volatile unsigned char *ba = gp->g_regkva; 482 const struct MonDef * md = (struct MonDef *) gp->g_data; 483 unsigned long off; 484 485 xpan = xoff; 486 ypan = yoff; 487 488 489 if (md->DEP > 8) 490 xoff *= 2; 491 492 vgar(ba, ACT_ADDRESS_RESET); 493 WAttr(ba, ACT_ID_HOR_PEL_PANNING, (unsigned char)((xoff << 1) & 0x07)); 494 /* have the color lookup function normally again */ 495 vgaw(ba, ACT_ADDRESS_W, 0x20); 496 497 if (md->DEP == 8) 498 off = ((yoff * md->TX)/ 4) + (xoff >> 2); 499 else 500 off = ((yoff * md->TX * 2)/ 4) + (xoff >> 2); 501 502 WCrt(ba, CRT_ID_START_ADDR_LOW, ((unsigned char)off)); 503 504 off >>= 8; 505 506 WCrt(ba, CRT_ID_START_ADDR_HIGH, ((unsigned char)off)); 507 508 off >>= 8; 509 510 WCrt(ba, CRT_ID_EXT_START_ADDR, 511 ((RCrt(ba, CRT_ID_EXT_START_ADDR) & 0xf0) | (off & 0x0f))); 512 513 514 } 515 516 void 517 RZ3SetHWCloc (gp, x, y) 518 struct grf_softc *gp; 519 unsigned short x, y; 520 { 521 volatile unsigned char *ba = gp->g_regkva; 522 const struct MonDef *md = (struct MonDef *) gp->g_data; 523 volatile unsigned char *acm = ba + ACM_OFFSET; 524 525 if (x < xpan) 526 RZ3SetPanning(gp, x, ypan); 527 528 if (x >= (xpan+md->MW)) 529 RZ3SetPanning(gp, (1 + x - md->MW) , ypan); 530 531 if (y < ypan) 532 RZ3SetPanning(gp, xpan, y); 533 534 if (y >= (ypan+md->MH)) 535 RZ3SetPanning(gp, xpan, (1 + y - md->MH)); 536 537 x -= xpan; 538 y -= ypan; 539 540 *(acm + (ACM_CURSOR_POSITION+0)) = x & 0xff; 541 *(acm + (ACM_CURSOR_POSITION+1)) = x >> 8; 542 *(acm + (ACM_CURSOR_POSITION+2)) = y & 0xff; 543 *(acm + (ACM_CURSOR_POSITION+3)) = y >> 8; 544 } 545 546 u_short 547 CompFQ(fq) 548 u_int fq; 549 { 550 /* yuck... this sure could need some explanation.. */ 551 552 unsigned long f = fq; 553 long n2 = 3; 554 long abw = 0x7fffffff; 555 long n1 = 3; 556 unsigned long m; 557 unsigned short erg = 0; 558 559 f *= 8; 560 561 do { 562 563 if (f <= 250000000) 564 break; 565 f /= 2; 566 567 } while (n2-- > 0); 568 569 if (n2 < 0) 570 return(0); 571 572 573 do { 574 long tmp; 575 576 f = fq; 577 f >>= 3; 578 f <<= n2; 579 f >>= 7; 580 581 m = (f * n1) / (14318180/1024); 582 583 if (m > 129) 584 break; 585 586 tmp = (((m * 14318180) >> n2) / n1) - fq; 587 if (tmp < 0) 588 tmp = -tmp; 589 590 if (tmp < abw) { 591 abw = tmp; 592 erg = (((n2 << 5) | (n1-2)) << 8) | (m-2); 593 } 594 595 } while ( (++n1) <= 21); 596 597 return(erg); 598 } 599 600 int 601 rh_mondefok(mdp) 602 struct MonDef *mdp; 603 { 604 switch(mdp->DEP) { 605 case 8: 606 case 16: 607 return(1); 608 case 4: 609 if (mdp->FX == 4 || (mdp->FX >= 7 && mdp->FX <= 16)) 610 return(1); 611 /*FALLTHROUGH*/ 612 default: 613 return(0); 614 } 615 } 616 617 618 int 619 rh_load_mon(gp, md) 620 struct grf_softc *gp; 621 struct MonDef *md; 622 { 623 struct grfinfo *gi = &gp->g_display; 624 volatile unsigned char *ba; 625 volatile unsigned char *fb; 626 short FW, clksel, HDE, VDE; 627 unsigned short *c, z; 628 const unsigned char *f; 629 630 ba = gp->g_regkva;; 631 fb = gp->g_fbkva; 632 633 /* provide all needed information in grf device-independant 634 * locations */ 635 gp->g_data = (caddr_t) md; 636 gi->gd_regaddr = (caddr_t) kvtop (ba); 637 gi->gd_regsize = LM_OFFSET; 638 gi->gd_fbaddr = (caddr_t) kvtop (fb); 639 gi->gd_fbsize = MEMSIZE *1024*1024; 640 #ifdef BANKEDDEVPAGER 641 /* we're not using banks NO MORE! */ 642 gi->gd_bank_size = 0; 643 #endif 644 gi->gd_colors = 1 << md->DEP; 645 gi->gd_planes = md->DEP; 646 647 if (md->DEP == 4) { 648 gi->gd_fbwidth = md->MW; 649 gi->gd_fbheight = md->MH; 650 gi->gd_fbx = 0; 651 gi->gd_fby = 0; 652 gi->gd_dwidth = md->TX * md->FX; 653 gi->gd_dheight = md->TY * md->FY; 654 gi->gd_dx = 0; 655 gi->gd_dy = 0; 656 } else { 657 gi->gd_fbwidth = md->TX; 658 gi->gd_fbheight = md->TY; 659 gi->gd_fbx = 0; 660 gi->gd_fby = 0; 661 gi->gd_dwidth = md->MW; 662 gi->gd_dheight = md->MH; 663 gi->gd_dx = 0; 664 gi->gd_dy = 0; 665 } 666 667 FW =0; 668 if (md->DEP == 4) { /* XXX some text-mode! */ 669 switch (md->FX) { 670 case 4: 671 FW = 0; 672 break; 673 case 7: 674 FW = 1; 675 break; 676 case 8: 677 FW = 2; 678 break; 679 case 9: 680 FW = 3; 681 break; 682 case 10: 683 FW = 4; 684 break; 685 case 11: 686 FW = 5; 687 break; 688 case 12: 689 FW = 6; 690 break; 691 case 13: 692 FW = 7; 693 break; 694 case 14: 695 FW = 8; 696 break; 697 case 15: 698 FW = 9; 699 break; 700 case 16: 701 FW = 11; 702 break; 703 default: 704 return(0); 705 break; 706 } 707 } 708 709 if (md->DEP == 4) 710 HDE = (md->MW+md->FX-1)/md->FX; 711 else if (md->DEP == 8) 712 HDE = (md->MW+3)/4; 713 else if (md->DEP == 16) 714 HDE = (md->MW*2+3)/4; 715 716 VDE = md->MH-1; 717 718 clksel = 0; 719 720 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((clksel & 3) * 0x04)); 721 vgaw(ba, GREG_FEATURE_CONTROL_W, 0x00); 722 723 WSeq(ba, SEQ_ID_RESET, 0x00); 724 WSeq(ba, SEQ_ID_RESET, 0x03); 725 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01 | ((md->FLG & MDF_CLKDIV2)/ MDF_CLKDIV2 * 8)); 726 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); 727 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); 728 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x06); 729 WSeq(ba, SEQ_ID_RESET, 0x01); 730 WSeq(ba, SEQ_ID_RESET, 0x03); 731 732 WSeq(ba, SEQ_ID_EXTENDED_ENABLE, 0x05); 733 WSeq(ba, SEQ_ID_CURSOR_CONTROL, 0x00); 734 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); 735 WSeq(ba, SEQ_ID_PRIM_HOST_OFF_HI, 0x00); 736 WSeq(ba, SEQ_ID_LINEAR_0, 0x4a); 737 WSeq(ba, SEQ_ID_LINEAR_1, 0x00); 738 739 WSeq(ba, SEQ_ID_SEC_HOST_OFF_HI, 0x00); 740 WSeq(ba, SEQ_ID_SEC_HOST_OFF_LO, 0x00); 741 WSeq(ba, SEQ_ID_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); 742 WSeq(ba, SEQ_ID_EXT_CLOCK_MODE, 0x10 | (FW & 0x0f)); 743 WSeq(ba, SEQ_ID_EXT_VIDEO_ADDR, 0x03); 744 if (md->DEP == 4) { 745 /* 8bit pixel, no gfx byte path */ 746 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x00); 747 } else if (md->DEP == 8) { 748 /* 8bit pixel, gfx byte path */ 749 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x01); 750 } else if (md->DEP == 16) { 751 /* 16bit pixel, gfx byte path */ 752 WSeq(ba, SEQ_ID_EXT_PIXEL_CNTL, 0x11); 753 } 754 WSeq(ba, SEQ_ID_BUS_WIDTH_FEEDB, 0x04); 755 WSeq(ba, SEQ_ID_COLOR_EXP_WFG, 0x01); 756 WSeq(ba, SEQ_ID_COLOR_EXP_WBG, 0x00); 757 WSeq(ba, SEQ_ID_EXT_RW_CONTROL, 0x00); 758 WSeq(ba, SEQ_ID_MISC_FEATURE_SEL, (0x51 | (clksel & 8))); 759 WSeq(ba, SEQ_ID_COLOR_KEY_CNTL, 0x40); 760 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH0, 0x00); 761 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH1, 0x00); 762 WSeq(ba, SEQ_ID_COLOR_KEY_MATCH2, 0x00); 763 WSeq(ba, SEQ_ID_CRC_CONTROL, 0x00); 764 WSeq(ba, SEQ_ID_PERF_SELECT, 0x10); 765 WSeq(ba, SEQ_ID_ACM_APERTURE_1, 0x00); 766 WSeq(ba, SEQ_ID_ACM_APERTURE_2, 0x30); 767 WSeq(ba, SEQ_ID_ACM_APERTURE_3, 0x00); 768 WSeq(ba, SEQ_ID_MEMORY_MAP_CNTL, 0x07); 769 770 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x20); 771 WCrt(ba, CRT_ID_HOR_TOTAL, md->HT & 0xff); 772 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, (HDE-1) & 0xff); 773 WCrt(ba, CRT_ID_START_HOR_BLANK, md->HBS & 0xff); 774 WCrt(ba, CRT_ID_END_HOR_BLANK, (md->HBE & 0x1f) | 0x80); 775 776 WCrt(ba, CRT_ID_START_HOR_RETR, md->HSS & 0xff); 777 WCrt(ba, CRT_ID_END_HOR_RETR, 778 (md->HSE & 0x1f) | 779 ((md->HBE & 0x20)/ 0x20 * 0x80)); 780 WCrt(ba, CRT_ID_VER_TOTAL, (md->VT & 0xff)); 781 WCrt(ba, CRT_ID_OVERFLOW, 782 ((md->VSS & 0x200) / 0x200 * 0x80) | 783 ((VDE & 0x200) / 0x200 * 0x40) | 784 ((md->VT & 0x200) / 0x200 * 0x20) | 785 0x10 | 786 ((md->VBS & 0x100) / 0x100 * 8) | 787 ((md->VSS & 0x100) / 0x100 * 4) | 788 ((VDE & 0x100) / 0x100 * 2) | 789 ((md->VT & 0x100) / 0x100)); 790 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); 791 792 if (md->DEP == 4) { 793 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 794 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) | 795 0x40 | 796 ((md->VBS & 0x200)/0x200*0x20) | 797 ((md->FY-1) & 0x1f)); 798 } else { 799 WCrt(ba, CRT_ID_MAX_SCAN_LINE, 800 ((md->FLG & MDF_DBL)/ MDF_DBL * 0x80) | 801 0x40 | 802 ((md->VBS & 0x200)/0x200*0x20) | 803 (0 & 0x1f)); 804 } 805 806 /* I prefer "_" cursor to "block" cursor.. */ 807 #if 1 808 WCrt(ba, CRT_ID_CURSOR_START, (md->FY & 0x1f) - 2); 809 WCrt(ba, CRT_ID_CURSOR_END, (md->FY & 0x1f) - 1); 810 #else 811 WCrt(ba, CRT_ID_CURSOR_START, 0x00); 812 WCrt(ba, CRT_ID_CURSOR_END, md->FY & 0x1f); 813 #endif 814 815 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); 816 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); 817 818 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); 819 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); 820 821 WCrt(ba, CRT_ID_START_VER_RETR, md->VSS & 0xff); 822 WCrt(ba, CRT_ID_END_VER_RETR, (md->VSE & 0xf) | 0x80 | 0x20); 823 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE & 0xff); 824 825 if (md->DEP == 4) 826 WCrt(ba, CRT_ID_OFFSET, (HDE / 2) & 0xff); 827 else if (md->DEP == 8) 828 WCrt(ba, CRT_ID_OFFSET, (md->TX / 8) & 0xff); 829 else 830 WCrt(ba, CRT_ID_OFFSET, (md->TX / 4) & 0xff); 831 832 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->FY-1) & 0x1f); 833 WCrt(ba, CRT_ID_START_VER_BLANK, md->VBS & 0xff); 834 WCrt(ba, CRT_ID_END_VER_BLANK, md->VBE & 0xff); 835 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); 836 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); 837 838 WCrt(ba, CRT_ID_EXT_HOR_TIMING1, 839 0 | 0x20 | 840 ((md->FLG & MDF_LACE) / MDF_LACE * 0x10) | 841 ((md->HT & 0x100) / 0x100) | 842 (((HDE-1) & 0x100) / 0x100 * 2) | 843 ((md->HBS & 0x100) / 0x100 * 4) | 844 ((md->HSS & 0x100) / 0x100 * 8)); 845 846 if (md->DEP == 4) 847 WCrt(ba, CRT_ID_EXT_START_ADDR, 848 (((HDE / 2) & 0x100)/0x100 * 16)); 849 else if (md->DEP == 8) 850 WCrt(ba, CRT_ID_EXT_START_ADDR, 851 (((md->TX / 8) & 0x100)/0x100 * 16)); 852 else 853 WCrt(ba, CRT_ID_EXT_START_ADDR, 854 (((md->TX / 4) & 0x100)/0x100 * 16)); 855 856 WCrt(ba, CRT_ID_EXT_HOR_TIMING2, 857 ((md->HT & 0x200)/ 0x200) | 858 (((HDE-1) & 0x200)/ 0x200 * 2 ) | 859 ((md->HBS & 0x200)/ 0x200 * 4 ) | 860 ((md->HSS & 0x200)/ 0x200 * 8 ) | 861 ((md->HBE & 0xc0) / 0x40 * 16 ) | 862 ((md->HSE & 0x60) / 0x20 * 64)); 863 864 WCrt(ba, CRT_ID_EXT_VER_TIMING, 865 ((md->VSE & 0x10) / 0x10 * 0x80 ) | 866 ((md->VBE & 0x300)/ 0x100 * 0x20 ) | 867 0x10 | 868 ((md->VSS & 0x400)/ 0x400 * 8 ) | 869 ((md->VBS & 0x400)/ 0x400 * 4 ) | 870 ((VDE & 0x400)/ 0x400 * 2 ) | 871 ((md->VT & 0x400)/ 0x400)); 872 WCrt(ba, CRT_ID_MONITOR_POWER, 0x00); 873 874 { 875 unsigned short tmp = CompFQ(md->FQ); 876 WPLL(ba, 2 , tmp); 877 tmp = CompFQ(MEMCLK); 878 WPLL(ba,10 , tmp); 879 WPLL(ba,14 , 0x22); 880 } 881 882 WGfx(ba, GCT_ID_SET_RESET, 0x00); 883 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); 884 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); 885 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); 886 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); 887 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00); 888 if (md->DEP == 4) 889 WGfx(ba, GCT_ID_MISC, 0x04); 890 else 891 WGfx(ba, GCT_ID_MISC, 0x05); 892 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); 893 WGfx(ba, GCT_ID_BITMASK, 0xff); 894 895 vgar(ba, ACT_ADDRESS_RESET); 896 WAttr(ba, ACT_ID_PALETTE0 , 0x00); 897 WAttr(ba, ACT_ID_PALETTE1 , 0x01); 898 WAttr(ba, ACT_ID_PALETTE2 , 0x02); 899 WAttr(ba, ACT_ID_PALETTE3 , 0x03); 900 WAttr(ba, ACT_ID_PALETTE4 , 0x04); 901 WAttr(ba, ACT_ID_PALETTE5 , 0x05); 902 WAttr(ba, ACT_ID_PALETTE6 , 0x06); 903 WAttr(ba, ACT_ID_PALETTE7 , 0x07); 904 WAttr(ba, ACT_ID_PALETTE8 , 0x08); 905 WAttr(ba, ACT_ID_PALETTE9 , 0x09); 906 WAttr(ba, ACT_ID_PALETTE10, 0x0a); 907 WAttr(ba, ACT_ID_PALETTE11, 0x0b); 908 WAttr(ba, ACT_ID_PALETTE12, 0x0c); 909 WAttr(ba, ACT_ID_PALETTE13, 0x0d); 910 WAttr(ba, ACT_ID_PALETTE14, 0x0e); 911 WAttr(ba, ACT_ID_PALETTE15, 0x0f); 912 913 vgar(ba, ACT_ADDRESS_RESET); 914 if (md->DEP == 4) 915 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x08); 916 else 917 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x09); 918 919 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); 920 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); 921 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); 922 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); 923 924 vgar(ba, ACT_ADDRESS_RESET); 925 vgaw(ba, ACT_ADDRESS_W, 0x20); 926 927 vgaw(ba, VDAC_MASK, 0xff); 928 if (md->DEP < 16) 929 /* well... probably the PLL chip */ 930 vgaw(ba, 0x83c6, ((0 & 7) << 5)); 931 else if (md->DEP == 16) 932 /* well... */ 933 vgaw(ba, 0x83c6, ((3 & 7) << 5)); 934 vgaw(ba, VDAC_ADDRESS_W, 0x00); 935 936 if (md->DEP < 16) { 937 short x = 256-17; 938 unsigned char cl = 16; 939 RZ3LoadPalette(gp, md->PAL, 0, 16); 940 do { 941 vgaw(ba, VDAC_DATA, (cl >> 2)); 942 vgaw(ba, VDAC_DATA, (cl >> 2)); 943 vgaw(ba, VDAC_DATA, (cl >> 2)); 944 cl++; 945 } while (x-- > 0); 946 } 947 948 if (md->DEP == 4) { 949 { 950 struct grf_bitblt bb = { 951 GRFBBOPset, 952 0, 0, 953 0, 0, 954 md->TX*4, 2*md->TY, 955 EMPTY_ALPHA 956 }; 957 RZ3BitBlit(gp, &bb); 958 } 959 960 c = (unsigned short *)(ba + LM_OFFSET); 961 c += 2 * md->FLo*32; 962 c += 1; 963 f = md->FData; 964 for (z = md->FLo; z <= md->FHi; z++) { 965 short y = md->FY-1; 966 if (md->FX > 8){ 967 do { 968 *c = *((const unsigned short *)f); 969 c += 2; 970 f += 2; 971 } while (y-- > 0); 972 } else { 973 do { 974 *c = (*f++) << 8; 975 c += 2; 976 } while (y-- > 0); 977 } 978 979 c += 2 * (32-md->FY); 980 } 981 { 982 unsigned long * pt = (unsigned long *) (ba + LM_OFFSET + PAT_MEM_OFF); 983 unsigned long tmp = 0xffff0000; 984 *pt++ = tmp; 985 *pt = tmp; 986 } 987 988 WSeq(ba, SEQ_ID_MAP_MASK, 3); 989 990 c = (unsigned short *)(ba + LM_OFFSET); 991 c += (md->TX-6)*2; 992 { 993 /* it's show-time :-) */ 994 static unsigned short init_msg[6] = { 995 0x520a, 0x450b, 0x540c, 0x490d, 0x4e0e, 0x410f 996 }; 997 unsigned short * m = init_msg; 998 short x = 5; 999 do { 1000 *c = *m++; 1001 c += 2; 1002 } while (x-- > 0); 1003 } 1004 1005 return(1); 1006 } else if (md->DEP == 8) { 1007 struct grf_bitblt bb = { 1008 GRFBBOPset, 1009 0, 0, 1010 0, 0, 1011 md->TX, md->TY, 1012 0x0000 1013 }; 1014 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); 1015 1016 RZ3BitBlit(gp, &bb); 1017 1018 xpan = 0; 1019 ypan = 0; 1020 1021 return(1); 1022 } else if (md->DEP == 16) { 1023 struct grf_bitblt bb = { 1024 GRFBBOPset, 1025 0, 0, 1026 0, 0, 1027 md->TX, md->TY, 1028 0x0000 1029 }; 1030 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); 1031 1032 RZ3BitBlit16(gp, &bb); 1033 1034 xpan = 0; 1035 ypan = 0; 1036 1037 return(1); 1038 } else 1039 return(0); 1040 } 1041 1042 /* standard-palette definition */ 1043 1044 unsigned char RZ3StdPalette[16*3] = { 1045 /* R G B */ 1046 0, 0, 0, 1047 192,192,192, 1048 128, 0, 0, 1049 0,128, 0, 1050 0, 0,128, 1051 128,128, 0, 1052 0,128,128, 1053 128, 0,128, 1054 64, 64, 64, /* the higher 8 colors have more intensity for */ 1055 255,255,255, /* compatibility with standard attributes */ 1056 255, 0, 0, 1057 0,255, 0, 1058 0, 0,255, 1059 255,255, 0, 1060 0,255,255, 1061 255, 0,255 1062 }; 1063 1064 /* 1065 * The following structures are examples for monitor-definitions. To make one 1066 * of your own, first use "DefineMonitor" and create the 8-bit or 16-bit 1067 * monitor-mode of your dreams. Then save it, and make a structure from the 1068 * values provided in the file DefineMonitor stored - the labels in the comment 1069 * above the structure definition show where to put what value. 1070 * 1071 * If you want to use your definition for the text-mode, you'll need to adapt 1072 * your 8-bit monitor-definition to the font you want to use. Be FX the width of 1073 * the font, then the following modifications have to be applied to your values: 1074 * 1075 * HBS = (HBS * 4) / FX 1076 * HSS = (HSS * 4) / FX 1077 * HSE = (HSE * 4) / FX 1078 * HBE = (HBE * 4) / FX 1079 * HT = (HT * 4) / FX 1080 * 1081 * Make sure your maximum width (MW) and height (MH) are even multiples of 1082 * the fonts' width and height. 1083 * 1084 * You may use definitons created by the old DefineMonitor, but you'll get 1085 * better results with the new DefineMonitor supplied along with the Retin Z3. 1086 */ 1087 1088 /* 1089 * FQ FLG MW MH HBS HSS HSE HBE HT VBS VSS VSE VBE VT 1090 * Depth, PAL, TX, TY, XY,FontX, FontY, FontData, FLo, Fhi 1091 */ 1092 static struct MonDef monitor_defs[] = { 1093 /* Text-mode definitions */ 1094 1095 /* horizontal 31.5 kHz */ 1096 #ifdef KFONT_8X11 1097 { 50000000, 28, 640, 506, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 1098 4, RZ3StdPalette, 80, 46, 3680, 8, 11, kernel_font_8x11, 32, 255}, 1099 #else 1100 { 50000000, 28, 640, 512, 81, 86, 93, 98, 95, 513, 513, 521, 535, 535, 1101 4, RZ3StdPalette, 80, 64, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1102 #endif 1103 1104 /* horizontal 38kHz */ 1105 #ifdef KFONT_8X11 1106 { 75000000, 28, 768, 594, 97, 99,107,120,117, 601, 615, 625, 638, 638, 1107 4, RZ3StdPalette, 96, 54, 5184, 8, 11, kernel_font_8x11, 32, 255}, 1108 #else 1109 { 75000000, 28, 768, 600, 97, 99,107,120,117, 601, 615, 625, 638, 638, 1110 4, RZ3StdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1111 #endif 1112 1113 /* horizontal 64kHz */ 1114 #ifdef KFONT_8X11 1115 { 50000000, 24, 768, 594, 97,104,112,122,119, 601, 606, 616, 628, 628, 1116 4, RZ3StdPalette, 96, 54, 5184, 8, 8, kernel_font_8x8, 32, 255}, 1117 #else 1118 { 50000000, 24, 768, 600, 97,104,112,122,119, 601, 606, 616, 628, 628, 1119 4, RZ3StdPalette, 96, 75, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1120 #endif 1121 1122 /* 8-bit gfx-mode definitions */ 1123 1124 /* 1125 * IMPORTANT: the "logical" screen size can be up to 2048x2048 pixels, 1126 * independent from the "physical" screen size. If your code does NOT 1127 * support panning, please adjust the "logical" screen sizes below to 1128 * match the physical ones 1129 */ 1130 1131 /* 640 x 480, 8 Bit, 31862 Hz, 63 Hz */ 1132 { 26000000, 0, 640, 480, 161,175,188,200,199, 481, 483, 491, 502, 502, 1133 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1134 /* This is the logical ^ ^ screen size */ 1135 1136 /* 640 x 480, 8 Bit, 38366 Hz, 76 Hz */ 1137 { 31000000, 0, 640, 480, 161,169,182,198,197, 481, 482, 490, 502, 502, 1138 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1139 1140 /* 800 x 600, 8 Bit, 31620 Hz, 50 Hz (1950) */ 1141 { 32000000, 0, 800, 600, 201,202,218,249,248, 601, 602, 612, 628, 628, 1142 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1143 /* 800 x 600, 8 Bit, 38537 Hz, 61 Hz */ 1144 { 39000000, 0, 800, 600, 201,211,227,249,248, 601, 603, 613, 628, 628, 1145 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1146 1147 /* 1024 x 768, 8 Bit, 63862 Hz, 79 Hz */ 1148 { 82000000, 0, 1024, 768, 257,257,277,317,316, 769, 771, 784, 804, 804, 1149 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1150 1151 /* 1120 x 896, 8 Bit, 64000 Hz, 69 Hz */ 1152 { 97000000, 0, 1120, 896, 281,283,306,369,368, 897, 898, 913, 938, 938, 1153 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1154 1155 /* 1152 x 910, 8 Bit, 76177 Hz, 79 Hz */ 1156 {110000000, 0, 1152, 910, 289,310,333,357,356, 911, 923, 938, 953, 953, 1157 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1158 1159 /* 1184 x 848, 8 Bit, 73529 Hz, 82 Hz */ 1160 {110000000, 0, 1184, 848, 297,319,342,370,369, 849, 852, 866, 888, 888, 1161 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1162 1163 /* 1280 x 1024, 8 Bit, 64516 Hz, 60 Hz */ 1164 {104000000, 0, 1280,1024, 321,323,348,399,398,1025,1026,1043,1073,1073, 1165 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1166 1167 /* WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR 1168 HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 1169 MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! */ 1170 /* 1280 x 1024, 8 Bit, 75436 Hz, 70 Hz */ 1171 {121000000, 0, 1280,1024, 321,322,347,397,396,1025,1026,1043,1073,1073, 1172 8, RZ3StdPalette,1280,1024, 5120, 8, 8, kernel_font_8x8, 32, 255}, 1173 1174 1175 /* 16-bit gfx-mode definitions */ 1176 1177 /* 640 x 480, 16 Bit, 31795 Hz, 63 Hz */ 1178 { 51000000, 0, 640, 480, 321,344,369,397,396, 481, 482, 490, 502, 502, 1179 16, 0,1280, 1024, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1180 1181 /* 800 x 600, 16 Bit, 38500 Hz, 61 Hz */ 1182 { 77000000, 0, 800, 600, 401,418,449,496,495, 601, 602, 612, 628, 628, 1183 16, 0,1280, 1024, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1184 1185 /* 1024 x 768, 16 Bit, 42768 Hz, 53 Hz */ 1186 {110000000, 0, 1024, 768, 513,514,554,639,638, 769, 770, 783, 804, 804, 1187 16, 0,1280, 1024, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1188 1189 /* 864 x 648, 16 Bit, 50369 Hz, 74 Hz */ 1190 {109000000, 0, 864, 648, 433,434,468,537,536, 649, 650, 661, 678, 678, 1191 16, 0,1280, 1024, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1192 1193 /* 1194 * WARNING: THE FOLLOWING MONITOR MODE EXCEEDS THE 110-MHz LIMIT THE PROCESSOR 1195 * HAS BEEN SPECIFIED FOR. USE AT YOUR OWN RISK (AND THINK ABOUT 1196 * MOUNTING SOME COOLING DEVICE AT THE PROCESSOR AND RAMDAC)! 1197 */ 1198 /* 1024 x 768, 16 Bit, 48437 Hz, 60 Hz */ 1199 {124000000, 0, 1024, 768, 513,537,577,636,635, 769, 770, 783, 804, 804, 1200 16, 0,1280, 1024, 7200, 8, 8, kernel_font_8x8, 32, 255}, 1201 }; 1202 1203 static const char *monitor_descr[] = { 1204 #ifdef KFONT_8X11 1205 "80x46 (640x506) 31.5kHz", 1206 "96x54 (768x594) 38kHz", 1207 "96x54 (768x594) 64kHz", 1208 #else 1209 "80x64 (640x512) 31.5kHz", 1210 "96x75 (768x600) 38kHz", 1211 "96x75 (768x600) 64kHz", 1212 #endif 1213 1214 "GFX-8 (640x480) 31.5kHz", 1215 "GFX-8 (640x480) 38kHz", 1216 "GFX-8 (800x600) 31.6kHz", 1217 "GFX-8 (800x600) 38.5kHz", 1218 "GFX-8 (1024x768) 64kHz", 1219 "GFX-8 (1120x896) 64kHz", 1220 "GFX-8 (1152x910) 76kHz", 1221 "GFX-8 (1182x848) 73kHz", 1222 "GFX-8 (1280x1024) 64.5kHz", 1223 "GFX-8 (1280x1024) 75.5kHz ***EXCEEDS CHIP LIMIT!!!***", 1224 1225 "GFX-16 (640x480) 31.8kHz", 1226 "GFX-16 (800x600) 38.5kHz", 1227 "GFX-16 (1024x768) 42.8kHz", 1228 "GFX-16 (864x648) 50kHz", 1229 "GFX-16 (1024x768) 48.5kHz ***EXCEEDS CHIP LIMIT!!!***", 1230 }; 1231 1232 int rh_mon_max = sizeof (monitor_defs)/sizeof (monitor_defs[0]); 1233 1234 /* patchable */ 1235 int rh_default_mon = 0; 1236 int rh_default_gfx = 4; 1237 1238 static struct MonDef *current_mon; 1239 1240 int rh_mode __P((struct grf_softc *, int, void *, int, int)); 1241 void grfrhattach __P((struct device *, struct device *, void *)); 1242 int grfrhprint __P((void *, char *)); 1243 int grfrhmatch __P((struct device *, struct cfdata *, void *)); 1244 1245 struct cfdriver grfrhcd = { 1246 NULL, "grfrh", (cfmatch_t)grfrhmatch, grfrhattach, 1247 DV_DULL, sizeof(struct grf_softc), NULL, 0 1248 }; 1249 1250 static struct cfdata *cfdata; 1251 1252 int 1253 grfrhmatch(pdp, cfp, auxp) 1254 struct device *pdp; 1255 struct cfdata *cfp; 1256 void *auxp; 1257 { 1258 #ifdef RETINACONSOLE 1259 static int rhconunit = -1; 1260 #endif 1261 struct zbus_args *zap; 1262 1263 zap = auxp; 1264 1265 if (amiga_realconfig == 0) 1266 #ifdef RETINACONSOLE 1267 if (rhconunit != -1) 1268 #endif 1269 return(0); 1270 if (zap->manid != 18260 || zap->prodid != 16) 1271 return(0); 1272 #ifdef RETINACONSOLE 1273 if (amiga_realconfig == 0 || rhconunit != cfp->cf_unit) { 1274 #endif 1275 if ((unsigned)rh_default_mon >= rh_mon_max || 1276 monitor_defs[rh_default_mon].DEP == 8) 1277 rh_default_mon = 0; 1278 current_mon = monitor_defs + rh_default_mon; 1279 if (rh_mondefok(current_mon) == 0) 1280 return(0); 1281 #ifdef RETINACONSOLE 1282 if (amiga_realconfig == 0) { 1283 rhconunit = cfp->cf_unit; 1284 cfdata = cfp; 1285 } 1286 } 1287 #endif 1288 return(1); 1289 } 1290 1291 void 1292 grfrhattach(pdp, dp, auxp) 1293 struct device *pdp, *dp; 1294 void *auxp; 1295 { 1296 static struct grf_softc congrf; 1297 static int coninited; 1298 struct zbus_args *zap; 1299 struct grf_softc *gp; 1300 1301 zap = auxp; 1302 1303 if (dp == NULL) 1304 gp = &congrf; 1305 else 1306 gp = (struct grf_softc *)dp; 1307 if (dp != NULL && congrf.g_regkva != 0) { 1308 /* 1309 * inited earlier, just copy (not device struct) 1310 */ 1311 bcopy(&congrf.g_display, &gp->g_display, 1312 (char *)&gp[1] - (char *)&gp->g_display); 1313 } else { 1314 gp->g_regkva = (volatile caddr_t)zap->va; 1315 gp->g_fbkva = (volatile caddr_t)zap->va + LM_OFFSET; 1316 gp->g_unit = GRF_RETINAIII_UNIT; 1317 gp->g_mode = rh_mode; 1318 gp->g_conpri = grfrh_cnprobe(); 1319 gp->g_flags = GF_ALIVE; 1320 grfrh_iteinit(gp); 1321 (void)rh_load_mon(gp, current_mon); 1322 } 1323 if (dp != NULL) 1324 printf("\n"); 1325 /* 1326 * attach grf 1327 */ 1328 amiga_config_found(cfdata, &gp->g_device, gp, grfrhprint); 1329 } 1330 1331 int 1332 grfrhprint(auxp, pnp) 1333 void *auxp; 1334 char *pnp; 1335 { 1336 if (pnp) 1337 printf("ite at %s", pnp); 1338 return(UNCONF); 1339 } 1340 1341 int 1342 rh_getvmode(gp, vm) 1343 struct grf_softc *gp; 1344 struct grfvideo_mode *vm; 1345 { 1346 struct MonDef *md; 1347 1348 if (vm->mode_num && vm->mode_num > rh_mon_max) 1349 return(EINVAL); 1350 1351 if (! vm->mode_num) 1352 vm->mode_num = (current_mon - monitor_defs) + 1; 1353 1354 md = monitor_defs + (vm->mode_num - 1); 1355 strncpy (vm->mode_descr, monitor_descr + (vm->mode_num - 1), 1356 sizeof (vm->mode_descr)); 1357 vm->pixel_clock = md->FQ; 1358 vm->disp_width = md->MW; 1359 vm->disp_height = md->MH; 1360 vm->depth = md->DEP; 1361 vm->hblank_start = md->HBS; 1362 vm->hblank_stop = md->HBE; 1363 vm->hsync_start = md->HSS; 1364 vm->hsync_stop = md->HSE; 1365 vm->htotal = md->HT; 1366 vm->vblank_start = md->VBS; 1367 vm->vblank_stop = md->VBE; 1368 vm->vsync_start = md->VSS; 1369 vm->vsync_stop = md->VSE; 1370 vm->vtotal = md->VT; 1371 1372 return(0); 1373 } 1374 1375 1376 int 1377 rh_setvmode(gp, mode, txtonly) 1378 struct grf_softc *gp; 1379 unsigned mode; 1380 int txtonly; 1381 { 1382 struct MonDef *md; 1383 int error; 1384 1385 if (!mode || mode > rh_mon_max) 1386 return(EINVAL); 1387 1388 if (txtonly && monitor_defs[mode-1].DEP != 4) 1389 return(EINVAL); 1390 1391 current_mon = monitor_defs + (mode - 1); 1392 1393 error = rh_load_mon (gp, current_mon) ? 0 : EINVAL; 1394 1395 return(error); 1396 } 1397 1398 1399 /* 1400 * Change the mode of the display. 1401 * Return a UNIX error number or 0 for success. 1402 */ 1403 rh_mode(gp, cmd, arg, a2, a3) 1404 register struct grf_softc *gp; 1405 int cmd; 1406 void *arg; 1407 int a2, a3; 1408 { 1409 /* implement these later... */ 1410 1411 switch (cmd) { 1412 case GM_GRFON: 1413 rh_setvmode (gp, rh_default_gfx + 1, 0); 1414 return(0); 1415 1416 case GM_GRFOFF: 1417 rh_setvmode (gp, rh_default_mon + 1, 0); 1418 return(0); 1419 1420 case GM_GRFCONFIG: 1421 return(0); 1422 1423 case GM_GRFGETVMODE: 1424 return(rh_getvmode (gp, (struct grfvideo_mode *) arg)); 1425 1426 case GM_GRFSETVMODE: 1427 return(rh_setvmode (gp, *(unsigned *) arg, 1)); 1428 1429 case GM_GRFGETNUMVM: 1430 *(int *)arg = rh_mon_max; 1431 return(0); 1432 1433 #ifdef BANKEDDEVPAGER 1434 case GM_GRFGETBANK: 1435 case GM_GRFGETCURBANK: 1436 case GM_GRFSETBANK: 1437 return(EINVAL); 1438 #endif 1439 case GM_GRFIOCTL: 1440 return(rh_ioctl (gp, (u_long) arg, (caddr_t) a2)); 1441 1442 default: 1443 break; 1444 } 1445 1446 return(EINVAL); 1447 } 1448 1449 int 1450 rh_ioctl (gp, cmd, data) 1451 register struct grf_softc *gp; 1452 u_long cmd; 1453 void *data; 1454 { 1455 switch (cmd) { 1456 case GRFIOCGSPRITEPOS: 1457 return(rh_getspritepos (gp, (struct grf_position *) data)); 1458 1459 case GRFIOCSSPRITEPOS: 1460 return(rh_setspritepos (gp, (struct grf_position *) data)); 1461 1462 case GRFIOCSSPRITEINF: 1463 return(rh_setspriteinfo (gp, (struct grf_spriteinfo *) data)); 1464 1465 case GRFIOCGSPRITEINF: 1466 return(rh_getspriteinfo (gp, (struct grf_spriteinfo *) data)); 1467 1468 case GRFIOCGSPRITEMAX: 1469 return(rh_getspritemax (gp, (struct grf_position *) data)); 1470 1471 case GRFIOCGETCMAP: 1472 return(rh_getcmap (gp, (struct grf_colormap *) data)); 1473 1474 case GRFIOCPUTCMAP: 1475 return(rh_putcmap (gp, (struct grf_colormap *) data)); 1476 1477 case GRFIOCBITBLT: 1478 return(rh_bitblt (gp, (struct grf_bitblt *) data)); 1479 } 1480 1481 return(EINVAL); 1482 } 1483 1484 1485 int 1486 rh_getcmap (gfp, cmap) 1487 struct grf_softc *gfp; 1488 struct grf_colormap *cmap; 1489 { 1490 volatile unsigned char *ba; 1491 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1492 short x; 1493 int error; 1494 1495 if (cmap->count == 0 || cmap->index >= 256) 1496 return 0; 1497 1498 if (cmap->index + cmap->count > 256) 1499 cmap->count = 256 - cmap->index; 1500 1501 ba = gfp->g_regkva; 1502 /* first read colors out of the chip, then copyout to userspace */ 1503 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1504 x = cmap->count - 1; 1505 rp = red + cmap->index; 1506 gp = green + cmap->index; 1507 bp = blue + cmap->index; 1508 do { 1509 *rp++ = vgar (ba, VDAC_DATA) << 2; 1510 *gp++ = vgar (ba, VDAC_DATA) << 2; 1511 *bp++ = vgar (ba, VDAC_DATA) << 2; 1512 } while (x-- > 0); 1513 1514 if (!(error = copyout (red + cmap->index, cmap->red, cmap->count)) 1515 && !(error = copyout (green + cmap->index, cmap->green, cmap->count)) 1516 && !(error = copyout (blue + cmap->index, cmap->blue, cmap->count))) 1517 return(0); 1518 1519 return(error); 1520 } 1521 1522 int 1523 rh_putcmap (gfp, cmap) 1524 struct grf_softc *gfp; 1525 struct grf_colormap *cmap; 1526 { 1527 volatile unsigned char *ba; 1528 u_char red[256], green[256], blue[256], *rp, *gp, *bp; 1529 short x; 1530 int error; 1531 1532 if (cmap->count == 0 || cmap->index >= 256) 1533 return(0); 1534 1535 if (cmap->index + cmap->count > 256) 1536 cmap->count = 256 - cmap->index; 1537 1538 /* first copy the colors into kernelspace */ 1539 if (!(error = copyin (cmap->red, red + cmap->index, cmap->count)) 1540 && !(error = copyin (cmap->green, green + cmap->index, cmap->count)) 1541 && !(error = copyin (cmap->blue, blue + cmap->index, cmap->count))) { 1542 /* argl.. LoadPalette wants a different format, so do it like with 1543 * Retina2.. */ 1544 ba = gfp->g_regkva; 1545 vgaw (ba, VDAC_ADDRESS_W, cmap->index); 1546 x = cmap->count - 1; 1547 rp = red + cmap->index; 1548 gp = green + cmap->index; 1549 bp = blue + cmap->index; 1550 do { 1551 vgaw (ba, VDAC_DATA, *rp++ >> 2); 1552 vgaw (ba, VDAC_DATA, *gp++ >> 2); 1553 vgaw (ba, VDAC_DATA, *bp++ >> 2); 1554 } while (x-- > 0); 1555 return(0); 1556 } 1557 else 1558 return(error); 1559 } 1560 1561 int 1562 rh_getspritepos (gp, pos) 1563 struct grf_softc *gp; 1564 struct grf_position *pos; 1565 { 1566 volatile unsigned char *acm = gp->g_regkva + ACM_OFFSET; 1567 1568 pos->x = acm[ACM_CURSOR_POSITION + 0] + 1569 (acm[ACM_CURSOR_POSITION + 1] << 8); 1570 pos->y = acm[ACM_CURSOR_POSITION + 2] + 1571 (acm[ACM_CURSOR_POSITION + 3] << 8); 1572 1573 pos->x += xpan; 1574 pos->y += ypan; 1575 1576 return(0); 1577 } 1578 1579 int 1580 rh_setspritepos (gp, pos) 1581 struct grf_softc *gp; 1582 struct grf_position *pos; 1583 { 1584 RZ3SetHWCloc (gp, pos->x, pos->y); 1585 return(0); 1586 } 1587 1588 int 1589 rh_getspriteinfo (gp, info) 1590 struct grf_softc *gp; 1591 struct grf_spriteinfo *info; 1592 { 1593 volatile unsigned char *ba, *fb; 1594 1595 ba = gp->g_regkva; 1596 fb = gp->g_fbkva; 1597 if (info->set & GRFSPRSET_ENABLE) 1598 info->enable = RSeq (ba, SEQ_ID_CURSOR_CONTROL) & 0x01; 1599 if (info->set & GRFSPRSET_POS) 1600 rh_getspritepos (gp, &info->pos); 1601 if (info->set & GRFSPRSET_HOT) { 1602 info->hot.x = RSeq (ba, SEQ_ID_CURSOR_X_INDEX) & 0x3f; 1603 info->hot.y = RSeq (ba, SEQ_ID_CURSOR_Y_INDEX) & 0x7f; 1604 } 1605 if (info->set & GRFSPRSET_CMAP) { 1606 struct grf_colormap cmap; 1607 int index; 1608 cmap.index = 0; 1609 cmap.count = 256; 1610 rh_getcmap (gp, &cmap); 1611 index = RSeq (ba, SEQ_ID_CURSOR_COLOR0); 1612 info->cmap.red[0] = cmap.red[index]; 1613 info->cmap.green[0] = cmap.green[index]; 1614 info->cmap.blue[0] = cmap.blue[index]; 1615 index = RSeq (ba, SEQ_ID_CURSOR_COLOR1); 1616 info->cmap.red[1] = cmap.red[index]; 1617 info->cmap.green[1] = cmap.green[index]; 1618 info->cmap.blue[1] = cmap.blue[index]; 1619 } 1620 if (info->set & GRFSPRSET_SHAPE) { 1621 u_char image[128], mask[128]; 1622 volatile u_long *hwp; 1623 u_char *imp, *mp; 1624 short row; 1625 1626 /* sprite bitmap is WEIRD in this chip.. see grf_rhvar.h 1627 * for an explanation. To convert to "our" format, the 1628 * following holds: 1629 * col2 = !image & mask 1630 * col1 = image & mask 1631 * transp = !mask 1632 * and thus: 1633 * image = col1 1634 * mask = col1 | col2 1635 * hope I got these bool-eqs right below.. 1636 */ 1637 1638 info->size.x = 64; 1639 info->size.y = 64; 1640 for (row = 0, hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF), 1641 mp = mask, imp = image; 1642 row < 64; 1643 row++) { 1644 u_long bp10, bp20, bp11, bp21; 1645 bp10 = *hwp++; 1646 bp20 = *hwp++; 1647 bp11 = *hwp++; 1648 bp21 = *hwp++; 1649 M2I (bp10); 1650 M2I (bp20); 1651 M2I (bp11); 1652 M2I (bp21); 1653 *imp++ = (~bp10) & bp11; 1654 *imp++ = (~bp20) & bp21; 1655 *mp++ = (~bp10) | (bp10 & ~bp11); 1656 *mp++ = (~bp20) & (bp20 & ~bp21); 1657 } 1658 copyout (image, info->image, sizeof (image)); 1659 copyout (mask, info->mask, sizeof (mask)); 1660 } 1661 return(0); 1662 } 1663 1664 int 1665 rh_setspriteinfo (gp, info) 1666 struct grf_softc *gp; 1667 struct grf_spriteinfo *info; 1668 { 1669 volatile unsigned char *ba, *fb; 1670 u_char control; 1671 1672 ba = gp->g_regkva; 1673 fb = gp->g_fbkva; 1674 1675 if (info->set & GRFSPRSET_SHAPE) { 1676 /* 1677 * For an explanation of these weird actions here, see above 1678 * when reading the shape. We set the shape directly into 1679 * the video memory, there's no reason to keep 1k on the 1680 * kernel stack just as template 1681 */ 1682 u_char *image, *mask; 1683 volatile u_long *hwp; 1684 u_char *imp, *mp; 1685 short row; 1686 1687 if (info->size.y > 64) 1688 info->size.y = 64; 1689 if (info->size.x > 64) 1690 info->size.x = 64; 1691 1692 if (info->size.x < 32) 1693 info->size.x = 32; 1694 1695 image = malloc(HWC_MEM_SIZE, M_TEMP, M_WAITOK); 1696 mask = image + HWC_MEM_SIZE/2; 1697 1698 copyin(info->image, image, info->size.y * info->size.x / 8); 1699 copyin(info->mask, mask, info->size.y * info->size.x / 8); 1700 1701 hwp = (u_long *)(ba + LM_OFFSET + HWC_MEM_OFF); 1702 1703 /* 1704 * setting it is slightly more difficult, because we can't 1705 * force the application to not pass a *smaller* than 1706 * supported bitmap 1707 */ 1708 1709 for (row = 0, mp = mask, imp = image; 1710 row < info->size.y; 1711 row++) { 1712 u_long im1, im2, m1, m2; 1713 1714 im1 = *(unsigned long *)imp; 1715 imp += 4; 1716 m1 = *(unsigned long *)mp; 1717 mp += 4; 1718 if (info->size.x > 32) { 1719 im2 = *(unsigned long *)imp; 1720 imp += 4; 1721 m2 = *(unsigned long *)mp; 1722 mp += 4; 1723 } 1724 else 1725 im2 = m2 = 0; 1726 1727 M2I(im1); 1728 M2I(im2); 1729 M2I(m1); 1730 M2I(m2); 1731 1732 *hwp++ = ~m1; 1733 *hwp++ = ~m2; 1734 *hwp++ = m1 & im1; 1735 *hwp++ = m2 & im2; 1736 } 1737 for (; row < 64; row++) { 1738 *hwp++ = 0xffffffff; 1739 *hwp++ = 0xffffffff; 1740 *hwp++ = 0x00000000; 1741 *hwp++ = 0x00000000; 1742 } 1743 1744 free(image, M_TEMP); 1745 RZ3SetupHWC(gp, 1, 0, 0, 0, 0); 1746 } 1747 if (info->set & GRFSPRSET_CMAP) { 1748 /* hey cheat a bit here.. XXX */ 1749 WSeq(ba, SEQ_ID_CURSOR_COLOR0, 0); 1750 WSeq(ba, SEQ_ID_CURSOR_COLOR1, 1); 1751 } 1752 if (info->set & GRFSPRSET_ENABLE) { 1753 if (info->enable) 1754 control = 0x85; 1755 else 1756 control = 0; 1757 WSeq(ba, SEQ_ID_CURSOR_CONTROL, control); 1758 } 1759 if (info->set & GRFSPRSET_POS) 1760 rh_setspritepos(gp, &info->pos); 1761 if (info->set & GRFSPRSET_HOT) { 1762 WSeq(ba, SEQ_ID_CURSOR_X_INDEX, info->hot.x & 0x3f); 1763 WSeq(ba, SEQ_ID_CURSOR_Y_INDEX, info->hot.y & 0x7f); 1764 } 1765 1766 return(0); 1767 } 1768 1769 int 1770 rh_getspritemax (gp, pos) 1771 struct grf_softc *gp; 1772 struct grf_position *pos; 1773 { 1774 pos->x = 64; 1775 pos->y = 64; 1776 1777 return(0); 1778 } 1779 1780 1781 int 1782 rh_bitblt (gp, bb) 1783 struct grf_softc *gp; 1784 struct grf_bitblt *bb; 1785 { 1786 struct MonDef *md = (struct MonDef *)gp->g_data; 1787 if (md->DEP < 16) 1788 RZ3BitBlit(gp, bb); 1789 else 1790 RZ3BitBlit16(gp, bb); 1791 } 1792 #endif /* NGRF */ 1793