|
|
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.