|
|
1.1 ! root 1: #include "grf.h" ! 2: #if NGRF > 0 ! 3: ! 4: /* Graphics routines for the AMIGA native custom chip set. */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/errno.h" ! 8: ! 9: #include "grfioctl.h" ! 10: #include "grfvar.h" ! 11: #include "grf_ccreg.h" ! 12: ! 13: #include "../include/cpu.h" ! 14: #include "../amiga/custom.h" ! 15: ! 16: ! 17: extern caddr_t CHIPMEMADDR; ! 18: extern caddr_t chipmem_steal (); ! 19: ! 20: struct ccfb ccfb = { ! 21: DEF_DISP_WIDTH, DEF_DISP_HEIGHT, DEF_DISP_X, DEF_DISP_Y, DEF_DISP_Z, ! 22: 0, ! 23: DEF_FB_WIDTH, DEF_FB_HEIGHT, DEF_FB_X, DEF_FB_Y, DEF_FB_Z, ! 24: DEF_COL0, DEF_COL1 ! 25: }; ! 26: ! 27: /* Initialize one copper list. We'll need two to make a nice interlaced display. */ ! 28: ! 29: /* maximum size needed for a copper list (4 planes hires laced) */ ! 30: #define COPENTS (4 * (2 * 4 + 2 + 1 + 2 + 2 + 2 + 16 * 1 + 1)) ! 31: ! 32: /* copper instructions */ ! 33: #define MOVE(cl, reg, val) \ ! 34: do { *cl++ = CUSTOM_OFS(reg); *cl++ = val; } while (0) ! 35: #define WAIT(cl, vp, hp, bfd, ve, he) \ ! 36: do { *cl++ = ((vp & 0xff)<<8)|(hp & 0xfe)|1; \ ! 37: *cl++ = (bfd<<15)|((ve & 0x7f)<<8)|(hp & 0xfe)|1; } while (0) ! 38: #define STOP(cl) \ ! 39: do { *cl++ = 0xffff; *cl++ = 0xffff; } while (0) ! 40: ! 41: static void ! 42: initcop (cop, othercop, shf, fb) ! 43: u_short *cop; ! 44: u_short *othercop; ! 45: int shf; ! 46: struct ccfb *fb; ! 47: { ! 48: long scrmem; ! 49: int i; ! 50: u_short c, strt, stop, *orig_cop = cop; ! 51: ! 52: /* get PA of display area */ ! 53: scrmem = (long) fb->fb - (long) CHIPMEMADDR; ! 54: ! 55: othercop = (u_short *) ((long)othercop - (long) CHIPMEMADDR); ! 56: ! 57: /* account for possible interlaced half-frame */ ! 58: if (shf) ! 59: scrmem += fb->fb_width >> 3; ! 60: ! 61: /* account for oversized framebuffers */ ! 62: scrmem += (fb->fb_x >> 3) + (fb->fb_y * (fb->fb_width >> 3)); ! 63: ! 64: /* initialize bitplane pointers for all planes */ ! 65: /* remember offset in copperlist to patch later */ ! 66: if (! fb->bplstart_off) ! 67: fb->bplstart_off = cop - orig_cop; ! 68: for (i = 0; i < fb->disp_z; i++) ! 69: { ! 70: MOVE (cop, bplpth(i), scrmem >> 16); ! 71: MOVE (cop, bplptl(i), scrmem & 0xffff); ! 72: scrmem += (fb->fb_width >> 3) * fb->fb_height; ! 73: } ! 74: ! 75: /* modulo is one line for interlaced displays, plus difference between ! 76: virtual and effective framebuffer size */ ! 77: MOVE (cop, bpl1mod, (fb->fb_width + (fb->fb_width - fb->disp_width)) >> 3); ! 78: MOVE (cop, bpl2mod, (fb->fb_width + (fb->fb_width - fb->disp_width)) >> 3); ! 79: ! 80: c = 0x8000 /* HIRES */ ! 81: | ((fb->disp_z & 7) << 12) /* bitplane use */ ! 82: | 0x0200 /* composite COLOR enable (whatever this is..) */ ! 83: | 0x0004; /* LACE */ ! 84: ! 85: MOVE (cop, bplcon0, c); ! 86: ! 87: /* these use pre-ECS register interpretation. Might want to go ECS ? */ ! 88: strt = (((fb->disp_y >> 1) & 0xff)<<8) | ((fb->disp_x >> 1) & 0xff); ! 89: MOVE (cop, diwstrt, strt); ! 90: stop = (((((fb->disp_y + fb->disp_height + 1-shf)>>1) & 0xff)<<8) ! 91: | (((fb->disp_x + fb->disp_width)>>1) & 0xff)); ! 92: MOVE (cop, diwstop, stop); ! 93: /* NOTE: default values for strt: 0x2c81, stop: 0xf4c1 */ ! 94: ! 95: /* these are from from HW-manual.. */ ! 96: strt = ((strt & 0xff) - 9) >> 1; ! 97: MOVE (cop, ddfstrt, strt); ! 98: stop = strt + (((fb->disp_width >> 4) - 2) << 2); ! 99: MOVE (cop, ddfstop, stop); ! 100: ! 101: /* setup interlaced display by constantly toggling between two copperlists */ ! 102: MOVE (cop, cop1lch, (long)othercop >> 16); ! 103: MOVE (cop, cop1lcl, (long)othercop & 0xffff); ! 104: ! 105: for (i = 0; i < (1 << fb->disp_z); i++) ! 106: MOVE (cop, color[i], fb->col[i]); ! 107: ! 108: /* wait forever */ ! 109: STOP (cop); ! 110: } ! 111: ! 112: ! 113: #ifdef DEBUG ! 114: void ! 115: dump_copperlist (cl) ! 116: u_int *cl; ! 117: { ! 118: while (*cl != 0xffffffff) ! 119: { ! 120: if (!(*cl & 0x00010000)) ! 121: printf ("MOVE (%x, %x)\t", *cl & 0xffff, *cl >> 16); ! 122: else ! 123: printf ("WAIT (%d, %d, %d, %d, %d)\t", *cl >> 24, (*cl & 0x00fe0000)>>16, ! 124: (*cl & 0x8000)>> 15, (*cl & 0x7f00)>>8, (*cl & 0xfe)); ! 125: cl++; ! 126: } ! 127: printf ("STOP ()\n"); ! 128: ! 129: } ! 130: #endif ! 131: ! 132: ! 133: /* ! 134: * Initialize hardware. ! 135: * Must point g_display at a grfinfo structure describing the hardware. ! 136: * Returns 0 if hardware not present, non-zero ow. ! 137: */ ! 138: cc_init(gp, ad) ! 139: struct grf_softc *gp; ! 140: struct amiga_device *ad; ! 141: { ! 142: register struct ccfb *fb = &ccfb; ! 143: struct grfinfo *gi = &gp->g_display; ! 144: u_char *fbp, save; ! 145: int fboff, fbsize; ! 146: int s; ! 147: ! 148: /* if already initialized, fail */ ! 149: if (fb->fb) ! 150: return 0; ! 151: ! 152: /* testing for the result is really redundant because chipmem_steal ! 153: panics if it runs out of memory.. */ ! 154: fbsize = (fb->fb_width >> 3) * fb->fb_height * fb->fb_z; ! 155: if (! (fb->fb = (u_char *) chipmem_steal (fbsize)) ! 156: || !(fb->cop1 = (u_short *) chipmem_steal (COPENTS)) ! 157: || !(fb->cop2 = (u_short *) chipmem_steal (COPENTS))) ! 158: return 0; ! 159: ! 160: /* clear the display. bzero only likes regions up to 64k, so call multiple times */ ! 161: for (fboff = 0; fboff < fbsize; fboff += 64*1024) ! 162: bzero (fb->fb + fboff, fbsize - fboff > 64*1024 ? 64*1024 : fbsize - fboff); ! 163: ! 164: initcop (fb->cop1, fb->cop2, 0, fb); ! 165: initcop (fb->cop2, fb->cop1, 1, fb); ! 166: ! 167: /* Make sure no ex-sprites are streaking down the screen */ ! 168: { ! 169: int i; ! 170: for(i = 0;i < 8;i++) ! 171: { ! 172: custom.spr[i].data = 0; ! 173: custom.spr[i].datb = 0; ! 174: } ! 175: } ! 176: ! 177: /* start the new display */ ! 178: /* disable these */ ! 179: custom.dmacon = (DMAF_BLTDONE | DMAF_BLTNZERO | DMAF_BLITHOG | DMAF_BLITTER ! 180: | DMAF_SPRITE | DMAF_DISK ! 181: | DMAF_AUD3 | DMAF_AUD2 | DMAF_AUD1 | DMAF_AUD0); ! 182: /* enable these */ ! 183: custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER; ! 184: ! 185: #if 0 ! 186: /* ok, this is a bit rough.. */ ! 187: s = splhigh (); ! 188: /* load a first guess copperlist, verify later whether we got the right ! 189: one */ ! 190: custom.cop1lc = (void *) ((long)fb->cop1 - (long) CHIPMEMADDR); ! 191: custom.copjmp1 = 0; ! 192: /* reset VBL */ ! 193: custom.intreq = INTF_VERTB; ! 194: /* wait for VBL */ ! 195: while (! (custom.intreqr & INTF_VERTB)) ; ! 196: /* reset VBL */ ! 197: custom.intreq = INTF_VERTB; ! 198: /* now, in a safe location, set correct copperlist based on longframe/shortframe ! 199: bit */ ! 200: if (custom.vposr & 0x8000) ! 201: { ! 202: custom.cop1lc = (void *) ((long)fb->cop1 - (long) CHIPMEMADDR); ! 203: custom.copjmp1 = 0; /* strobe it */ ! 204: } ! 205: else ! 206: { ! 207: custom.cop1lc = (void *) ((long)fb->cop2 - (long) CHIPMEMADDR); ! 208: custom.copjmp1 = 0; ! 209: } ! 210: /* wait for another VBL and reset int, then go back to previous int level */ ! 211: while (! (custom.intreqr & INTF_VERTB)) ; ! 212: custom.intreq = INTF_VERTB; ! 213: splx (s); ! 214: #else ! 215: s = splhigh(); ! 216: /* set up copper */ ! 217: custom.cop1lc = (void *) ((long)fb->cop1 - (long) CHIPMEMADDR); ! 218: custom.copjmp1 = 0; ! 219: ! 220: /* reset vertical blank interrupt */ ! 221: custom.intreq = INTF_VERTB; ! 222: ! 223: /* wait for vertical blank interrupt */ ! 224: while ((custom.intreqr & INTF_VERTB) != INTF_VERTB) ! 225: ; ! 226: ! 227: /* set bitplane pointers based on LOF/SHF bit */ ! 228: if (custom.vposr & 0x8000) ! 229: { ! 230: custom.cop1lc = (void *) ((long)fb->cop1 - (long) CHIPMEMADDR); ! 231: custom.copjmp1 = 0; ! 232: } ! 233: else ! 234: { ! 235: custom.cop1lc = (void *) ((long)fb->cop2 - (long) CHIPMEMADDR); ! 236: custom.copjmp1 = 0; ! 237: } ! 238: splx (s); ! 239: #endif ! 240: ! 241: /* tame the blitter. Copying one word onto itself should put it into ! 242: a consistent state. This is black magic... */ ! 243: custom.bltapt = ! 244: custom.bltbpt = ! 245: custom.bltcpt = ! 246: custom.bltdpt = 0; ! 247: custom.bltamod = ! 248: custom.bltbmod = ! 249: custom.bltcmod = ! 250: custom.bltdmod = 0; ! 251: custom.bltafwm = ! 252: custom.bltalwn = 0xffff; ! 253: custom.bltcon0 = 0x09f0; ! 254: custom.bltcon1 = 0; ! 255: custom.bltsize = 1; ! 256: ! 257: /* enable VBR interrupts. This is also done in the serial driver, but it ! 258: really belongs here.. */ ! 259: custom.intena = INTF_SETCLR | INTF_VERTB; ! 260: ! 261: #if 0 ! 262: #ifdef DEBUG ! 263: /* prove the display is up.. */ ! 264: for (fboff = 0; fboff < fbsize; fboff++) ! 265: { ! 266: fb->fb[fboff] = 0xff; ! 267: DELAY(10); ! 268: } ! 269: for (fboff = 0; fboff < fbsize; fboff++) ! 270: { ! 271: fb->fb[fboff] = 0; ! 272: DELAY(10); ! 273: } ! 274: #endif ! 275: #endif ! 276: ! 277: gi->gd_regaddr = (caddr_t) fb; /* XXX */ ! 278: gi->gd_regsize = 0; ! 279: ! 280: gi->gd_fbaddr = fb->fb - (u_char *) CHIPMEMADDR; ! 281: gi->gd_fbsize = fbsize; ! 282: ! 283: gi->gd_colors = 1 << fb->fb_z; ! 284: gi->gd_planes = fb->fb_z; ! 285: ! 286: gi->gd_fbwidth = fb->fb_width; ! 287: gi->gd_fbheight = fb->fb_height; ! 288: gi->gd_fbx = fb->fb_x; ! 289: gi->gd_fby = fb->fb_y; ! 290: gi->gd_dwidth = fb->disp_width; ! 291: gi->gd_dheight = fb->disp_height; ! 292: gi->gd_dx = fb->disp_x; ! 293: gi->gd_dy = fb->disp_y; ! 294: ! 295: gp->g_regkva = 0; /* builtin */ ! 296: gp->g_fbkva = fb->fb; ! 297: ! 298: return(1); ! 299: } ! 300: ! 301: cc_config(gp, di) ! 302: register struct grf_softc *gp; ! 303: struct grfdyninfo *di; ! 304: { ! 305: register struct ccfb *fb = &ccfb; ! 306: struct grfinfo *gi = &gp->g_display; ! 307: u_char *fbp, save; ! 308: int fboff, fbsize; ! 309: int s; ! 310: ! 311: /* bottom missing... */ ! 312: ! 313: } ! 314: ! 315: /* ! 316: * Change the mode of the display. ! 317: * Right now all we can do is grfon/grfoff. ! 318: * Return a UNIX error number or 0 for success. ! 319: */ ! 320: cc_mode(gp, cmd, arg) ! 321: register struct grf_softc *gp; ! 322: int cmd; ! 323: void *arg; ! 324: { ! 325: switch (cmd) ! 326: { ! 327: case GM_GRFON: ! 328: custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_COPPER; ! 329: return 0; ! 330: ! 331: case GM_GRFOFF: ! 332: custom.dmacon = DMAF_RASTER | DMAF_COPPER; ! 333: return 0; ! 334: ! 335: case GM_GRFCONFIG: ! 336: return cc_config (gp, (struct grfdyninfo *) arg); ! 337: ! 338: default: ! 339: break; ! 340: } ! 341: ! 342: return EINVAL; ! 343: } ! 344: ! 345: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.