grf_ul.c revision 1.7.2.1 1 1.7.2.1 chopps /* $NetBSD: grf_ul.c,v 1.7.2.1 1995/11/10 19:29:54 chopps Exp $ */
2 1.1 chopps #define UL_DEBUG
3 1.1 chopps
4 1.1 chopps /*
5 1.1 chopps * Copyright (c) 1995 Ignatios Souvatzis
6 1.1 chopps * All rights reserved.
7 1.1 chopps *
8 1.1 chopps * Redistribution and use in source and binary forms, with or without
9 1.1 chopps * modification, are permitted provided that the following conditions
10 1.1 chopps * are met:
11 1.1 chopps * 1. Redistributions of source code must retain the above copyright
12 1.1 chopps * notice, this list of conditions and the following disclaimer.
13 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 chopps * notice, this list of conditions and the following disclaimer in the
15 1.1 chopps * documentation and/or other materials provided with the distribution.
16 1.1 chopps * 3. All advertising materials mentioning features or use of this software
17 1.1 chopps * must display the following acknowledgement:
18 1.1 chopps * This product includes software developed by Lutz Vieweg.
19 1.1 chopps * 4. The name of the author may not be used to endorse or promote products
20 1.1 chopps * derived from this software without specific prior written permission
21 1.1 chopps *
22 1.1 chopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 chopps * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 chopps * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 chopps * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 chopps * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 chopps * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 chopps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 chopps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 chopps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 chopps * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 chopps */
33 1.1 chopps #include "grful.h"
34 1.1 chopps #if NGRFUL > 0
35 1.1 chopps
36 1.1 chopps /* Graphics routines for the University of Lowell A2410 board,
37 1.1 chopps using the TMS34010 processor. */
38 1.1 chopps
39 1.1 chopps #include <sys/param.h>
40 1.3 chopps #include <sys/systm.h>
41 1.1 chopps #include <sys/errno.h>
42 1.1 chopps #include <sys/ioctl.h>
43 1.1 chopps #include <sys/device.h>
44 1.1 chopps #include <sys/malloc.h>
45 1.1 chopps #include <sys/syslog.h>
46 1.1 chopps
47 1.1 chopps #include <machine/cpu.h>
48 1.1 chopps
49 1.1 chopps #include <amiga/amiga/device.h>
50 1.1 chopps #include <amiga/amiga/isr.h>
51 1.1 chopps #include <amiga/dev/zbusvar.h>
52 1.1 chopps #include <amiga/dev/grfioctl.h>
53 1.1 chopps #include <amiga/dev/grfvar.h>
54 1.1 chopps #include <amiga/dev/grf_ulreg.h>
55 1.6 chopps
56 1.7.2.1 chopps extern u_int16_t tmscode[];
57 1.1 chopps
58 1.5 chopps int ul_ioctl __P((struct grf_softc *, u_long, void *, dev_t));
59 1.5 chopps int ul_getcmap __P((struct grf_softc *, struct grf_colormap *, dev_t));
60 1.5 chopps int ul_putcmap __P((struct grf_softc *, struct grf_colormap *, dev_t));
61 1.5 chopps int ul_bitblt __P((struct grf_softc *, struct grf_bitblt *, dev_t));
62 1.1 chopps
63 1.1 chopps /*
64 1.1 chopps * marked true early so that ulowell_cnprobe() can tell if we are alive.
65 1.1 chopps */
66 1.1 chopps int ulowell_inited;
67 1.1 chopps
68 1.1 chopps /* standard-palette definition */
69 1.1 chopps u_int8_t ul_std_palette[] = {
70 1.1 chopps 0,128, 0,128, 0,128, 0,128, 0,255, 0,255, 0,255, 0,255,
71 1.1 chopps 0, 0,128,128, 0, 0,128,128, 0, 0,255,255, 0, 0,255,255,
72 1.1 chopps 0, 0, 0, 0, 128,128,128,128, 0, 0, 0, 0, 255,255,255,255};
73 1.1 chopps
74 1.1 chopps u_int8_t ul_ovl_palette[] = {
75 1.1 chopps 128, 0, 0, 0,
76 1.1 chopps 128, 0, 0, 0,
77 1.1 chopps 128, 0, 0, 0};
78 1.1 chopps
79 1.2 chopps struct grfvideo_mode ul_monitor_defs[] = {
80 1.1 chopps
81 1.1 chopps /*
82 1.1 chopps * Horizontal values are given in TMS units, that is, for the
83 1.1 chopps * A2410 board, units of 16 pixels. The ioctl multiplies (when
84 1.7.2.1 chopps * exporting) or divides (when importing) them by 16 to conform to.
85 1.1 chopps *
86 1.7.2.1 chopps * XXX This used to be in units of 8 pixel times. We
87 1.7.2.1 chopps * must also change amiga/stand/grfconfig/grfconfig.c,
88 1.7.2.1 chopps * grf_{rt,rh,cl,cv}.c and egsgrfconfig (the latter to generate the
89 1.1 chopps * horizontal timings in units of pixels instead of 8 pixels.
90 1.1 chopps * You will also have to write warnings in BIG BOLD RED BLINKING
91 1.1 chopps * LETTERS all over the docs, and still people will fry their monitors.
92 1.1 chopps *
93 1.1 chopps * btw, the _totals are always sync_start+1, to compute the frequencies
94 1.1 chopps * correctly. (see TMS34010 manual)
95 1.1 chopps */
96 1.1 chopps
97 1.1 chopps /* 1024x768, 60Hz */
98 1.1 chopps {1, "1024x768", 66667000, 1024, 768, 8,
99 1.1 chopps 82, 18, 86, 12, 87, 794, 26, 797, 2, 798},
100 1.1 chopps
101 1.1 chopps /* 864x648, 70Hz */
102 1.1 chopps {2, "864x648", 50000000, 864, 648, 8,
103 1.1 chopps 61, 7, 65, 3, 66, 667, 19, 677, 4, 678},
104 1.1 chopps
105 1.1 chopps /* 800x600, 60Hz */
106 1.1 chopps {3, "800x600", 36000000, 800, 600, 8,
107 1.1 chopps 57, 7, 61, 3, 62, 619, 19, 629, 4, 630},
108 1.1 chopps
109 1.1 chopps /* 640x400, 60 Hz, interlaced */
110 1.1 chopps {4, "640x400I", 14318000, 640, 400, 8,
111 1.1 chopps 48, 8, 56, 3, 57, 239, 39, 262, 2, 240},
112 1.1 chopps
113 1.1 chopps /* 1024x768, 65Hz interlaced, s.th. is strange */
114 1.1 chopps {5, "1024x768?I", 44980000, 1024, 768, 8,
115 1.1 chopps 76, 12, 79, 3, 80, 512, 24, 533, 2, 534},
116 1.1 chopps
117 1.1 chopps /* 1024x1024, 60Hz */
118 1.1 chopps {6, "1024x1024", 80000000, 1024,1024, 8,
119 1.1 chopps 77, 13, 78, 5, 78,1051, 27,1054, 2,1055},
120 1.1 chopps
121 1.1 chopps /* 736x480, 60 Hz */
122 1.1 chopps {7, "736x480", 28636300, 736, 480, 8,
123 1.1 chopps 54, 8, 57, 3, 58, 503, 23, 514, 3, 515},
124 1.1 chopps };
125 1.1 chopps
126 1.2 chopps int ulowell_mon_max = sizeof (ul_monitor_defs)/sizeof (ul_monitor_defs[0]);
127 1.1 chopps
128 1.1 chopps /* option settable */
129 1.1 chopps #ifndef ULOWELL_OSC1
130 1.1 chopps #define ULOWELL_OSC1 36000000
131 1.1 chopps #endif
132 1.1 chopps
133 1.1 chopps #ifndef ULOWELL_OSC2
134 1.1 chopps #define ULOWELL_OSC2 66667000
135 1.1 chopps #endif
136 1.1 chopps
137 1.1 chopps #ifndef ULOWELL_DEFAULT_MON
138 1.1 chopps #define ULOWELL_DEFAULT_MON 1
139 1.1 chopps #endif
140 1.1 chopps
141 1.1 chopps /* patchable */
142 1.1 chopps int ulowell_default_mon = ULOWELL_DEFAULT_MON;
143 1.1 chopps int ulowell_default_gfx = ULOWELL_DEFAULT_MON;
144 1.1 chopps
145 1.1 chopps /*
146 1.1 chopps * yes, this should be per board. We don't pay service to multiple boards,
147 1.1 chopps * anyway.
148 1.1 chopps */
149 1.1 chopps
150 1.4 chopps u_long ulowell_clock[2] = { ULOWELL_OSC2, ULOWELL_OSC1 };
151 1.1 chopps
152 1.1 chopps static struct grfvideo_mode *current_mon;
153 1.1 chopps
154 1.1 chopps /*
155 1.1 chopps * We dont use ints at the moment, but will need this later to avoid
156 1.1 chopps * busy_waiting in gsp_write, and we use it for spurious int warnings.
157 1.1 chopps */
158 1.1 chopps
159 1.1 chopps static int
160 1.1 chopps ulisr(gp)
161 1.1 chopps struct grf_softc *gp;
162 1.1 chopps {
163 1.1 chopps struct gspregs *ba;
164 1.1 chopps u_int16_t thebits;
165 1.1 chopps
166 1.1 chopps if (gp == NULL)
167 1.1 chopps return 0;
168 1.1 chopps
169 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
170 1.1 chopps
171 1.1 chopps if (ba == NULL)
172 1.1 chopps return 0;
173 1.1 chopps
174 1.1 chopps thebits = ba->ctrl;
175 1.1 chopps if (thebits & INTOUT) {
176 1.1 chopps log(LOG_INFO, "grf4: got interrupt, ctrl=0x%4x\n", thebits);
177 1.1 chopps /* clear int */
178 1.1 chopps ba->ctrl = thebits & ~INTOUT;
179 1.1 chopps return 1;
180 1.1 chopps }
181 1.1 chopps return 0;
182 1.1 chopps }
183 1.1 chopps
184 1.1 chopps /*
185 1.1 chopps * used to query the ulowell board to see if its alive.
186 1.1 chopps * for the moment, a NOP.
187 1.1 chopps */
188 1.1 chopps int
189 1.1 chopps ulowell_alive(mdp)
190 1.1 chopps struct grfvideo_mode *mdp;
191 1.1 chopps {
192 1.1 chopps return 1;
193 1.1 chopps }
194 1.1 chopps
195 1.1 chopps /*
196 1.1 chopps * Load the (mostly) ite support code and the default colormaps.
197 1.1 chopps */
198 1.1 chopps static void
199 1.1 chopps ul_load_code(gp)
200 1.1 chopps struct grf_softc *gp;
201 1.1 chopps {
202 1.1 chopps struct grf_ul_softc *gup;
203 1.1 chopps struct gspregs *ba;
204 1.1 chopps struct grfinfo *gi;
205 1.1 chopps struct grf_colormap gcm;
206 1.1 chopps int i,j;
207 1.1 chopps
208 1.1 chopps gup = (struct grf_ul_softc *)gp;
209 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
210 1.1 chopps gi = &gp->g_display;
211 1.1 chopps
212 1.1 chopps gi->gd_regaddr = ztwopa((caddr_t)ba);
213 1.1 chopps gi->gd_regsize = sizeof(struct gspregs);
214 1.1 chopps gi->gd_fbaddr = NULL;
215 1.1 chopps gi->gd_fbsize = 0;
216 1.1 chopps gi->gd_fbwidth = 1024;
217 1.1 chopps gi->gd_fbheight = 1024;
218 1.1 chopps gi->gd_colors = 256;
219 1.1 chopps
220 1.5 chopps ba->ctrl = (ba->ctrl & ~INCR) | (LBL|INCW);
221 1.1 chopps ba->hstadrh = 0xC000;
222 1.1 chopps ba->hstadrl = 0x0080;
223 1.1 chopps ba->data = 0x0; /* disable screen refresh and video output */
224 1.1 chopps ba->data = 0xFFFC; /* screen refresh base address */
225 1.1 chopps ba->data = 0xFFFF; /* no display int possible */
226 1.1 chopps ba->data = 0x000C; /* CAS before RAS refresh each 64 local clks */
227 1.1 chopps
228 1.5 chopps ba->ctrl = (ba->ctrl & ~INCW) | LBL;
229 1.1 chopps ba->hstadrh = 0xfe80;
230 1.1 chopps ba->hstadrl = 0;
231 1.1 chopps ba->data = 4;
232 1.1 chopps ba->hstadrl = 0x20;
233 1.1 chopps ba->data = 0xFF; /* all color planes visible */
234 1.1 chopps
235 1.1 chopps ba->hstadrl = 0;
236 1.1 chopps ba->data = 5;
237 1.1 chopps ba->hstadrl = 0x20;
238 1.1 chopps ba->data = 0; /* no color planes blinking */
239 1.1 chopps
240 1.1 chopps ba->hstadrl = 0;
241 1.1 chopps ba->data = 6;
242 1.1 chopps ba->hstadrl = 0x20;
243 1.1 chopps ba->data = gup->gus_ovslct = 0x43;
244 1.1 chopps /* overlay visible, no overlay blinking, overlay color 0 transparent */
245 1.1 chopps
246 1.1 chopps ba->hstadrl = 0;
247 1.1 chopps ba->data = 7;
248 1.1 chopps ba->hstadrl = 0x20;
249 1.1 chopps ba->data = 0; /* voodoo */
250 1.1 chopps
251 1.1 chopps /* clear overlay planes */
252 1.1 chopps ba->ctrl |= INCW;
253 1.1 chopps ba->hstadrh = 0xff80;
254 1.1 chopps ba->hstadrl = 0x0000;
255 1.1 chopps for (i=0xff80000; i< 0xffa0000; ++i) {
256 1.1 chopps ba->data = 0;
257 1.1 chopps }
258 1.1 chopps
259 1.1 chopps /* download tms code */
260 1.1 chopps
261 1.1 chopps ba->ctrl = LBL | INCW | NMI | NMIM | HLT | CF;
262 1.1 chopps
263 1.1 chopps printf("\ndownloading TMS code");
264 1.5 chopps i=0;
265 1.5 chopps while ((j = tmscode[i++])) {
266 1.1 chopps printf(".");
267 1.5 chopps ba->hstadrh = tmscode[i++];
268 1.5 chopps ba->hstadrl = tmscode[i++];
269 1.5 chopps while (j-- > 0) {
270 1.5 chopps ba->data = tmscode[i++];
271 1.1 chopps }
272 1.1 chopps }
273 1.1 chopps
274 1.1 chopps /* font info was uploaded in ite_ul.c(ite_ulinit). */
275 1.1 chopps
276 1.5 chopps /* unflush cache, unhalt cpu -> nmi starts to run */
277 1.5 chopps ba->ctrl &= ~(HLT|CF);
278 1.1 chopps
279 1.1 chopps #if 0
280 1.1 chopps /* XXX load image palette with some initial values, slightly hacky */
281 1.1 chopps
282 1.1 chopps ba->hstadrh = 0xfe80;
283 1.1 chopps ba->hstadrl = 0x0000;
284 1.1 chopps ba->ctrl |= INCW;
285 1.1 chopps ba->data = 0;
286 1.1 chopps ba->ctrl &= ~INCW;
287 1.1 chopps
288 1.1 chopps for (i=0; i<16; ++i) {
289 1.1 chopps ba->data = gup->gus_imcmap[i+ 0] = ul_std_palette[i+ 0];
290 1.1 chopps ba->data = gup->gus_imcmap[i+256] = ul_std_palette[i+16];
291 1.1 chopps ba->data = gup->gus_imcmap[i+512] = ul_std_palette[i+32];
292 1.1 chopps }
293 1.1 chopps
294 1.1 chopps /*
295 1.1 chopps * XXX load shadow overlay palette with what the TMS code will load
296 1.1 chopps * into the real one some time after the TMS code is started above.
297 1.1 chopps * This is a rude hack.
298 1.1 chopps */
299 1.1 chopps bcopy(ul_ovl_palette, gup->gus_ovcmap, 3*4);
300 1.1 chopps #else
301 1.1 chopps /* XXX This version will work for the overlay, if our queue codes
302 1.1 chopps * initial conditions are set at load time (not start time).
303 1.1 chopps * It further assumes that ul_putcmap only uses the
304 1.1 chopps * GRFIMDEV/GRFOVDEV bits of the dev parameter.
305 1.1 chopps */
306 1.1 chopps
307 1.1 chopps gcm.index = 0;
308 1.1 chopps gcm.count = 16;
309 1.1 chopps gcm.red = ul_std_palette + 0;
310 1.1 chopps gcm.green = ul_std_palette + 16;
311 1.1 chopps gcm.blue = ul_std_palette + 32;
312 1.1 chopps ul_putcmap(gp, &gcm, GRFIMDEV);
313 1.1 chopps
314 1.1 chopps gcm.index = 0;
315 1.1 chopps gcm.count = 4;
316 1.1 chopps gcm.red = ul_ovl_palette + 0;
317 1.1 chopps gcm.green = ul_ovl_palette + 4;
318 1.1 chopps gcm.blue = ul_ovl_palette + 8;
319 1.1 chopps ul_putcmap(gp, &gcm, GRFOVDEV);
320 1.1 chopps #endif
321 1.1 chopps
322 1.1 chopps }
323 1.1 chopps
324 1.1 chopps static int
325 1.1 chopps ul_load_mon(gp, md)
326 1.1 chopps struct grf_softc *gp;
327 1.1 chopps struct grfvideo_mode *md;
328 1.1 chopps {
329 1.1 chopps struct grf_ul_softc *gup;
330 1.1 chopps struct grfinfo *gi;
331 1.1 chopps struct gspregs *ba;
332 1.1 chopps u_int16_t buf[8];
333 1.1 chopps
334 1.1 chopps gup = (struct grf_ul_softc *)gp;
335 1.1 chopps gi = &gp->g_display;
336 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
337 1.1 chopps
338 1.1 chopps gi->gd_dyn.gdi_fbx = 0;
339 1.1 chopps gi->gd_dyn.gdi_fby = 0;
340 1.1 chopps gi->gd_dyn.gdi_dwidth = md->disp_width;
341 1.1 chopps gi->gd_dyn.gdi_dheight = md->disp_height;
342 1.1 chopps gi->gd_dyn.gdi_dx = 0;
343 1.1 chopps gi->gd_dyn.gdi_dy = 0;
344 1.1 chopps
345 1.5 chopps ba->ctrl = (ba->ctrl & ~INCR) | (LBL|INCW);
346 1.1 chopps
347 1.1 chopps ba->hstadrh = 0xC000;
348 1.1 chopps ba->hstadrl = 0x0000;
349 1.1 chopps ba->data = md->hsync_stop;
350 1.1 chopps ba->data = md->hblank_stop;
351 1.1 chopps ba->data = md->hblank_start;
352 1.1 chopps ba->data = md->hsync_start;
353 1.1 chopps ba->data = md->vsync_stop;
354 1.1 chopps ba->data = md->vblank_stop;
355 1.1 chopps ba->data = md->vblank_start;
356 1.1 chopps ba->data = md->vsync_start;
357 1.1 chopps
358 1.1 chopps ba->ctrl &= ~INCW;
359 1.1 chopps ba->hstadrh = 0xFE90;
360 1.1 chopps ba->hstadrl = 0x0000;
361 1.1 chopps
362 1.1 chopps if (abs(md->pixel_clock - ulowell_clock[0]) >
363 1.1 chopps abs(md->pixel_clock - ulowell_clock[1])) {
364 1.1 chopps
365 1.5 chopps ba->data = (ba->data & 0xFC) | 2 | 1;
366 1.1 chopps md->pixel_clock = ulowell_clock[1];
367 1.1 chopps
368 1.1 chopps } else {
369 1.5 chopps ba->data = (ba->data & 0xFC) | 2 | 0;
370 1.1 chopps md->pixel_clock = ulowell_clock[0];
371 1.1 chopps }
372 1.1 chopps
373 1.1 chopps ba->ctrl |= LBL|INCW;
374 1.1 chopps ba->hstadrh = 0xC000;
375 1.1 chopps ba->hstadrl = 0x0080;
376 1.1 chopps ba->data = (md->vblank_start - md->vblank_stop == md->disp_height ?
377 1.1 chopps 0xf020 : 0xb020);
378 1.1 chopps
379 1.1 chopps /* I guess this should be in the yet unimplemented mode select ioctl */
380 1.1 chopps /* Hm.. maybe not. We always put the console on overlay plane no 0. */
381 1.1 chopps /* Anyway, this _IS_ called in the mode select ioctl. */
382 1.1 chopps
383 1.1 chopps /* ite support code parameters: */
384 1.1 chopps buf[0] = GCMD_MCHG;
385 1.1 chopps buf[1] = md->disp_width; /* display width */
386 1.1 chopps buf[2] = md->disp_height; /* display height */
387 1.1 chopps buf[3] = 0; /* LSW of frame buffer origin */
388 1.1 chopps buf[4] = 0xFF80; /* MSW of frame buffer origin */
389 1.1 chopps buf[5] = gi->gd_fbwidth * 1; /* frame buffer pitch */
390 1.1 chopps buf[6] = 1; /* frame buffer depth */
391 1.1 chopps gsp_write(ba, buf, 7);
392 1.1 chopps
393 1.1 chopps return(1);
394 1.1 chopps }
395 1.1 chopps
396 1.1 chopps int ul_mode __P((struct grf_softc *, int, void *, int , int));
397 1.1 chopps
398 1.1 chopps void grfulattach __P((struct device *, struct device *, void *));
399 1.1 chopps int grfulprint __P((void *, char *));
400 1.1 chopps int grfulmatch __P((struct device *, struct cfdata *, void *));
401 1.1 chopps
402 1.1 chopps struct cfdriver grfulcd = {
403 1.1 chopps NULL, "grful", (cfmatch_t)grfulmatch, grfulattach,
404 1.1 chopps DV_DULL, sizeof(struct grf_ul_softc), NULL, 0 };
405 1.1 chopps
406 1.1 chopps /*
407 1.1 chopps * only used in console init
408 1.1 chopps */
409 1.1 chopps static struct cfdata *cfdata;
410 1.1 chopps
411 1.1 chopps /*
412 1.1 chopps * we make sure to only init things once. this is somewhat
413 1.1 chopps * tricky regarding the console.
414 1.1 chopps */
415 1.1 chopps int
416 1.1 chopps grfulmatch(pdp, cfp, auxp)
417 1.1 chopps struct device *pdp;
418 1.1 chopps struct cfdata *cfp;
419 1.1 chopps void *auxp;
420 1.1 chopps {
421 1.1 chopps #ifdef ULOWELLCONSOLE
422 1.1 chopps static int ulconunit = -1;
423 1.1 chopps #endif
424 1.1 chopps struct zbus_args *zap;
425 1.1 chopps
426 1.1 chopps zap = auxp;
427 1.1 chopps
428 1.1 chopps /*
429 1.1 chopps * allow only one ulowell console
430 1.1 chopps */
431 1.1 chopps if (amiga_realconfig == 0)
432 1.1 chopps #ifdef ULOWELLCONSOLE
433 1.1 chopps if (ulconunit != -1)
434 1.1 chopps #endif
435 1.1 chopps return(0);
436 1.1 chopps
437 1.1 chopps if (zap->manid != 1030 || zap->prodid != 0)
438 1.1 chopps return(0);
439 1.1 chopps
440 1.1 chopps #ifdef ULOWELLCONSOLE
441 1.1 chopps if (amiga_realconfig == 0 || ulconunit != cfp->cf_unit) {
442 1.1 chopps #endif
443 1.1 chopps if ((unsigned)ulowell_default_mon >= ulowell_mon_max)
444 1.1 chopps ulowell_default_mon = 1;
445 1.1 chopps
446 1.2 chopps current_mon = ul_monitor_defs + ulowell_default_mon - 1;
447 1.1 chopps if (ulowell_alive(current_mon) == 0)
448 1.1 chopps return(0);
449 1.1 chopps #ifdef ULOWELLCONSOLE
450 1.1 chopps if (amiga_realconfig == 0) {
451 1.1 chopps ulconunit = cfp->cf_unit;
452 1.1 chopps cfdata = cfp;
453 1.1 chopps }
454 1.1 chopps }
455 1.1 chopps #endif
456 1.1 chopps return(1);
457 1.1 chopps }
458 1.1 chopps
459 1.1 chopps /*
460 1.1 chopps * attach to the grfbus (zbus)
461 1.1 chopps */
462 1.1 chopps void
463 1.1 chopps grfulattach(pdp, dp, auxp)
464 1.1 chopps struct device *pdp, *dp;
465 1.1 chopps void *auxp;
466 1.1 chopps {
467 1.1 chopps static struct grf_ul_softc congrf;
468 1.1 chopps struct zbus_args *zap;
469 1.1 chopps struct grf_softc *gp;
470 1.1 chopps struct grf_ul_softc *gup;
471 1.1 chopps
472 1.1 chopps zap = auxp;
473 1.1 chopps
474 1.1 chopps if (dp == NULL)
475 1.1 chopps gup = &congrf;
476 1.1 chopps else
477 1.1 chopps gup = (struct grf_ul_softc *)dp;
478 1.1 chopps
479 1.1 chopps gp = &gup->gus_sc;
480 1.1 chopps
481 1.1 chopps if (dp != NULL && congrf.gus_sc.g_regkva != 0) {
482 1.1 chopps /*
483 1.1 chopps * inited earlier, just copy (not device struct)
484 1.1 chopps */
485 1.1 chopps bcopy(&congrf.gus_sc.g_display, &gp->g_display,
486 1.1 chopps (char *)&gup->gus_isr - (char *)&gp->g_display);
487 1.1 chopps
488 1.1 chopps /* ...and transfer the isr */
489 1.1 chopps gup->gus_isr.isr_ipl = 2;
490 1.1 chopps gup->gus_isr.isr_intr = ulisr;
491 1.1 chopps gup->gus_isr.isr_arg = (void *)gp;
492 1.1 chopps /*
493 1.1 chopps * To make sure ints are always catched, first add new isr
494 1.1 chopps * then remove old:
495 1.1 chopps */
496 1.1 chopps add_isr(&gup->gus_isr);
497 1.1 chopps remove_isr(&congrf.gus_isr);
498 1.1 chopps } else {
499 1.1 chopps gp->g_regkva = (caddr_t)zap->va;
500 1.1 chopps gp->g_fbkva = NULL;
501 1.1 chopps gp->g_unit = GRF_ULOWELL_UNIT;
502 1.1 chopps gp->g_flags = GF_ALIVE;
503 1.1 chopps gp->g_mode = ul_mode;
504 1.1 chopps gp->g_conpri = grful_cnprobe();
505 1.1 chopps gp->g_data = NULL;
506 1.1 chopps
507 1.1 chopps gup->gus_isr.isr_ipl = 2;
508 1.1 chopps gup->gus_isr.isr_intr = ulisr;
509 1.1 chopps gup->gus_isr.isr_arg = (void *)gp;
510 1.1 chopps add_isr(&gup->gus_isr);
511 1.1 chopps
512 1.1 chopps (void)ul_load_code(gp);
513 1.1 chopps (void)ul_load_mon(gp, current_mon);
514 1.1 chopps grful_iteinit(gp);
515 1.1 chopps }
516 1.1 chopps if (dp != NULL)
517 1.1 chopps printf("\n");
518 1.1 chopps /*
519 1.1 chopps * attach grf
520 1.1 chopps */
521 1.1 chopps amiga_config_found(cfdata, &gp->g_device, gp, grfulprint);
522 1.1 chopps }
523 1.1 chopps
524 1.1 chopps int
525 1.1 chopps grfulprint(auxp, pnp)
526 1.1 chopps void *auxp;
527 1.1 chopps char *pnp;
528 1.1 chopps {
529 1.1 chopps if (pnp)
530 1.1 chopps printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
531 1.1 chopps pnp);
532 1.1 chopps return(UNCONF);
533 1.1 chopps }
534 1.1 chopps
535 1.1 chopps static int
536 1.1 chopps ul_getvmode (gp, vm)
537 1.1 chopps struct grf_softc *gp;
538 1.1 chopps struct grfvideo_mode *vm;
539 1.1 chopps {
540 1.1 chopps struct grfvideo_mode *md;
541 1.1 chopps
542 1.1 chopps if (vm->mode_num && vm->mode_num > ulowell_mon_max)
543 1.1 chopps return EINVAL;
544 1.1 chopps
545 1.1 chopps if (! vm->mode_num)
546 1.2 chopps vm->mode_num = current_mon - ul_monitor_defs + 1;
547 1.1 chopps
548 1.2 chopps md = ul_monitor_defs + vm->mode_num - 1;
549 1.3 chopps strncpy (vm->mode_descr, md->mode_descr,
550 1.1 chopps sizeof (vm->mode_descr));
551 1.1 chopps
552 1.1 chopps /* XXX should tell TMS to measure it */
553 1.1 chopps vm->pixel_clock = md->pixel_clock;
554 1.1 chopps vm->disp_width = md->disp_width;
555 1.1 chopps vm->disp_height = md->disp_height;
556 1.1 chopps vm->depth = md->depth;
557 1.1 chopps
558 1.7.2.1 chopps vm->hblank_start = (md->hblank_start - md->hblank_stop) * 16;
559 1.7.2.1 chopps vm->hblank_stop = (md->htotal - 1) * 16;
560 1.7.2.1 chopps vm->hsync_start = (md->hsync_start - md->hblank_stop) * 16;
561 1.7.2.1 chopps vm->hsync_stop = (md->hsync_stop + md->htotal - md->hblank_stop) * 16;
562 1.7.2.1 chopps vm->htotal = md->htotal * 16;
563 1.1 chopps
564 1.7 chopps vm->vblank_start = md->vblank_start - md->vblank_stop;
565 1.7 chopps vm->vblank_stop = md->vtotal - 1;
566 1.7 chopps vm->vsync_start = md->vsync_start - md->vblank_stop;
567 1.7 chopps vm->vsync_stop = md->vsync_stop + md->vtotal - md->vblank_stop;
568 1.1 chopps vm->vtotal = md->vtotal;
569 1.1 chopps
570 1.1 chopps return 0;
571 1.1 chopps }
572 1.1 chopps
573 1.1 chopps
574 1.1 chopps static int
575 1.1 chopps ul_setvmode (gp, mode)
576 1.1 chopps struct grf_softc *gp;
577 1.1 chopps unsigned mode;
578 1.1 chopps {
579 1.1 chopps struct grf_ul_softc *gup;
580 1.1 chopps struct gspregs *ba;
581 1.1 chopps int error;
582 1.1 chopps
583 1.1 chopps if (!mode || mode > ulowell_mon_max)
584 1.1 chopps return EINVAL;
585 1.1 chopps
586 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
587 1.1 chopps gup = (struct grf_ul_softc *)gp;
588 1.2 chopps current_mon = ul_monitor_defs + mode - 1;
589 1.1 chopps
590 1.1 chopps error = ul_load_mon (gp, current_mon) ? 0 : EINVAL;
591 1.1 chopps
592 1.1 chopps return error;
593 1.1 chopps }
594 1.1 chopps
595 1.1 chopps /*
596 1.1 chopps * Set the frame buffer or overlay planes on or off.
597 1.1 chopps * Always succeeds.
598 1.1 chopps */
599 1.1 chopps
600 1.1 chopps static __inline void
601 1.1 chopps ul_setfb(gp, cmd)
602 1.1 chopps struct grf_softc *gp;
603 1.1 chopps int cmd;
604 1.1 chopps {
605 1.1 chopps struct grf_ul_softc *gup;
606 1.1 chopps struct gspregs *ba;
607 1.1 chopps
608 1.1 chopps gup = (struct grf_ul_softc *)gp;
609 1.1 chopps
610 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
611 1.1 chopps ba->ctrl = LBL;
612 1.1 chopps ba->hstadrh = 0xfe80;
613 1.1 chopps ba->hstadrl = 0x0000;
614 1.1 chopps ba->data = 6;
615 1.1 chopps ba->hstadrl = 0x0020;
616 1.1 chopps
617 1.1 chopps switch (cmd) {
618 1.1 chopps case GM_GRFON:
619 1.1 chopps gup->gus_ovslct |= 0x40;
620 1.1 chopps break;
621 1.1 chopps case GM_GRFOFF:
622 1.1 chopps gup->gus_ovslct &= ~0x40;
623 1.1 chopps break;
624 1.1 chopps case GM_GRFOVON:
625 1.1 chopps gup->gus_ovslct |= 3;
626 1.1 chopps break;
627 1.1 chopps case GM_GRFOVOFF:
628 1.1 chopps gup->gus_ovslct &= ~3;
629 1.1 chopps break;
630 1.1 chopps }
631 1.1 chopps ba->data = gup->gus_ovslct;
632 1.1 chopps }
633 1.1 chopps
634 1.1 chopps /*
635 1.1 chopps * Change the mode of the display.
636 1.1 chopps * Return a UNIX error number or 0 for success.
637 1.1 chopps */
638 1.1 chopps int
639 1.1 chopps ul_mode(gp, cmd, arg, a2, a3)
640 1.1 chopps struct grf_softc *gp;
641 1.1 chopps int cmd;
642 1.1 chopps void *arg;
643 1.1 chopps int a2, a3;
644 1.1 chopps {
645 1.1 chopps int i;
646 1.1 chopps struct grfdyninfo *gd;
647 1.1 chopps
648 1.1 chopps switch (cmd) {
649 1.1 chopps case GM_GRFON:
650 1.1 chopps case GM_GRFOFF:
651 1.1 chopps case GM_GRFOVON:
652 1.1 chopps case GM_GRFOVOFF:
653 1.1 chopps ul_setfb (gp, cmd);
654 1.1 chopps return 0;
655 1.1 chopps
656 1.1 chopps case GM_GRFCONFIG:
657 1.1 chopps gd = (struct grfdyninfo *)arg;
658 1.1 chopps for (i=0; i<ulowell_mon_max; ++i) {
659 1.2 chopps if (ul_monitor_defs[i].disp_width == gd->gdi_dwidth &&
660 1.2 chopps ul_monitor_defs[i].disp_height == gd->gdi_dheight)
661 1.1 chopps return ul_setvmode(gp, i+1);
662 1.1 chopps }
663 1.1 chopps return EINVAL;
664 1.1 chopps
665 1.1 chopps case GM_GRFGETVMODE:
666 1.1 chopps return ul_getvmode (gp, (struct grfvideo_mode *) arg);
667 1.1 chopps
668 1.1 chopps case GM_GRFSETVMODE:
669 1.1 chopps return ul_setvmode (gp, *(unsigned *) arg);
670 1.1 chopps
671 1.1 chopps case GM_GRFGETNUMVM:
672 1.1 chopps *(int *)arg = ulowell_mon_max;
673 1.1 chopps return 0;
674 1.1 chopps
675 1.1 chopps case GM_GRFIOCTL:
676 1.1 chopps return ul_ioctl (gp, (u_long)arg, (void *)a2, (dev_t)a3);
677 1.1 chopps
678 1.1 chopps default:
679 1.1 chopps break;
680 1.1 chopps }
681 1.1 chopps
682 1.1 chopps return EINVAL;
683 1.1 chopps }
684 1.1 chopps
685 1.1 chopps int
686 1.1 chopps ul_ioctl (gp, cmd, data, dev)
687 1.1 chopps register struct grf_softc *gp;
688 1.1 chopps u_long cmd;
689 1.1 chopps void *data;
690 1.1 chopps dev_t dev;
691 1.1 chopps {
692 1.1 chopps switch (cmd) {
693 1.1 chopps #if 0
694 1.1 chopps /*
695 1.1 chopps * XXX we have no hardware sprites, but might implement them
696 1.1 chopps * later in TMS code.
697 1.1 chopps */
698 1.1 chopps
699 1.1 chopps case GRFIOCGSPRITEPOS:
700 1.1 chopps return ul_getspritepos (gp, (struct grf_position *) data);
701 1.1 chopps
702 1.1 chopps case GRFIOCSSPRITEPOS:
703 1.1 chopps return ul_setspritepos (gp, (struct grf_position *) data);
704 1.1 chopps
705 1.1 chopps case GRFIOCSSPRITEINF:
706 1.1 chopps return ul_setspriteinfo (gp, (struct grf_spriteinfo *) data);
707 1.1 chopps
708 1.1 chopps case GRFIOCGSPRITEINF:
709 1.1 chopps return ul_getspriteinfo (gp, (struct grf_spriteinfo *) data);
710 1.1 chopps
711 1.1 chopps case GRFIOCGSPRITEMAX:
712 1.1 chopps return ul_getspritemax (gp, (struct grf_position *) data);
713 1.1 chopps
714 1.1 chopps #endif
715 1.1 chopps
716 1.1 chopps case GRFIOCGETCMAP:
717 1.1 chopps return ul_getcmap (gp, (struct grf_colormap *) data, dev);
718 1.1 chopps
719 1.1 chopps case GRFIOCPUTCMAP:
720 1.1 chopps return ul_putcmap (gp, (struct grf_colormap *) data, dev);
721 1.1 chopps
722 1.1 chopps case GRFIOCBITBLT:
723 1.1 chopps return ul_bitblt (gp, (struct grf_bitblt *) data, dev);
724 1.1 chopps }
725 1.1 chopps
726 1.1 chopps return EINVAL;
727 1.1 chopps }
728 1.1 chopps
729 1.1 chopps int
730 1.1 chopps ul_getcmap (gp, cmap, dev)
731 1.1 chopps struct grf_softc *gp;
732 1.1 chopps struct grf_colormap *cmap;
733 1.1 chopps dev_t dev;
734 1.1 chopps {
735 1.1 chopps struct grf_ul_softc *gup;
736 1.1 chopps u_int8_t *mymap;
737 1.5 chopps int mxidx, error;
738 1.1 chopps
739 1.1 chopps gup = (struct grf_ul_softc *)gp;
740 1.1 chopps
741 1.1 chopps if (minor(dev) & GRFIMDEV) {
742 1.1 chopps mxidx = 256;
743 1.1 chopps mymap = gup->gus_imcmap;
744 1.1 chopps } else {
745 1.1 chopps mxidx = 4;
746 1.1 chopps mymap = gup->gus_ovcmap;
747 1.1 chopps }
748 1.1 chopps
749 1.1 chopps if (cmap->count == 0 || cmap->index >= mxidx)
750 1.1 chopps return 0;
751 1.1 chopps
752 1.1 chopps if (cmap->index + cmap->count > mxidx)
753 1.1 chopps cmap->count = mxidx - cmap->index;
754 1.1 chopps
755 1.1 chopps /* just copyout from the shadow color map */
756 1.1 chopps
757 1.1 chopps if ((error = copyout(mymap + cmap->index, cmap->red, cmap->count))
758 1.1 chopps
759 1.1 chopps || (error = copyout(mymap + mxidx + cmap->index, cmap->green,
760 1.1 chopps cmap->count))
761 1.1 chopps
762 1.1 chopps || (error = copyout(mymap + mxidx * 2 + cmap->index, cmap->blue,
763 1.1 chopps cmap->count)))
764 1.1 chopps
765 1.1 chopps return(error);
766 1.1 chopps
767 1.1 chopps return(0);
768 1.1 chopps }
769 1.1 chopps
770 1.1 chopps int
771 1.1 chopps ul_putcmap (gp, cmap, dev)
772 1.1 chopps struct grf_softc *gp;
773 1.1 chopps struct grf_colormap *cmap;
774 1.1 chopps dev_t dev;
775 1.1 chopps {
776 1.1 chopps struct grf_ul_softc *gup;
777 1.1 chopps struct gspregs *ba;
778 1.1 chopps u_int16_t cmd[8];
779 1.1 chopps int x, mxidx, error;
780 1.1 chopps u_int8_t *mymap;
781 1.1 chopps
782 1.1 chopps gup = (struct grf_ul_softc *)gp;
783 1.1 chopps
784 1.1 chopps if (minor(dev) & GRFIMDEV) {
785 1.1 chopps mxidx = 256;
786 1.1 chopps mymap = gup->gus_imcmap;
787 1.1 chopps } else {
788 1.1 chopps mxidx = 4;
789 1.1 chopps mymap = gup->gus_ovcmap;
790 1.1 chopps }
791 1.1 chopps
792 1.1 chopps if (cmap->count == 0 || cmap->index >= mxidx)
793 1.1 chopps return 0;
794 1.1 chopps
795 1.1 chopps if (cmap->index + cmap->count > mxidx)
796 1.1 chopps cmap->count = mxidx - cmap->index;
797 1.1 chopps
798 1.1 chopps /* first copyin to our shadow color map */
799 1.1 chopps
800 1.1 chopps if ((error = copyin(cmap->red, mymap + cmap->index, cmap->count))
801 1.1 chopps
802 1.1 chopps || (error = copyin(cmap->green, mymap + cmap->index + mxidx,
803 1.1 chopps cmap->count))
804 1.1 chopps
805 1.1 chopps || (error = copyin(cmap->blue, mymap + cmap->index + mxidx*2,
806 1.1 chopps cmap->count)))
807 1.1 chopps
808 1.1 chopps return error;
809 1.1 chopps
810 1.1 chopps
811 1.1 chopps /* then write from there to the hardware */
812 1.1 chopps ba = (struct gspregs *)gp->g_regkva;
813 1.1 chopps if (mxidx > 4) {
814 1.1 chopps /* image color map: we can write, with a hack, directly */
815 1.1 chopps ba->ctrl = LBL;
816 1.1 chopps ba->hstadrh = 0xfe80;
817 1.1 chopps ba->hstadrl = 0x0000;
818 1.1 chopps ba->ctrl |= INCW;
819 1.1 chopps ba->data = cmap->index;
820 1.1 chopps ba->ctrl &= ~INCW;
821 1.1 chopps
822 1.1 chopps for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
823 1.1 chopps ba->data = (u_int16_t) mymap[x];
824 1.1 chopps ba->data = (u_int16_t) mymap[x + mxidx];
825 1.1 chopps ba->data = (u_int16_t) mymap[x + mxidx * 2];
826 1.1 chopps }
827 1.1 chopps } else {
828 1.1 chopps
829 1.1 chopps /* overlay planes color map: have to call tms to do it */
830 1.1 chopps cmd[0] = GCMD_CMAP;
831 1.1 chopps cmd[1] = 1;
832 1.1 chopps for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
833 1.1 chopps cmd[2] = x;
834 1.1 chopps cmd[3] = mymap[x];
835 1.1 chopps cmd[4] = mymap[x + mxidx];
836 1.1 chopps cmd[5] = mymap[x + mxidx * 2];
837 1.1 chopps gsp_write(ba, cmd, 6);
838 1.1 chopps }
839 1.1 chopps }
840 1.1 chopps return 0;
841 1.1 chopps }
842 1.1 chopps
843 1.1 chopps /*
844 1.1 chopps * !!! THIS AREA UNDER CONSTRUCTION !!!
845 1.1 chopps */
846 1.1 chopps int ul_BltOpMap[16] = {
847 1.1 chopps 3, 1, 2, 0, 11, 9, 10, 8,
848 1.1 chopps 7, 5, 6, 4, 15, 13, 14, 12
849 1.1 chopps };
850 1.1 chopps
851 1.1 chopps int
852 1.1 chopps ul_bitblt (gp, bb, dev)
853 1.1 chopps struct grf_softc *gp;
854 1.1 chopps struct grf_bitblt *bb;
855 1.1 chopps dev_t dev;
856 1.1 chopps {
857 1.1 chopps /* XXX not yet implemented, but pretty trivial */
858 1.1 chopps return EINVAL;
859 1.1 chopps }
860 1.1 chopps
861 1.1 chopps void
862 1.1 chopps gsp_write(gsp, ptr, size)
863 1.1 chopps struct gspregs *gsp;
864 1.1 chopps u_short *ptr;
865 1.1 chopps size_t size;
866 1.1 chopps {
867 1.1 chopps u_short put, new_put, next, oc;
868 1.1 chopps u_long put_hi, oa;
869 1.1 chopps size_t n;
870 1.1 chopps
871 1.1 chopps if (size == 0 || size > 8)
872 1.1 chopps return;
873 1.1 chopps
874 1.1 chopps n = size;
875 1.1 chopps
876 1.1 chopps oc = gsp->ctrl;
877 1.1 chopps oa = GSPGETHADRS(gsp);
878 1.1 chopps
879 1.5 chopps gsp->ctrl = (oc & ~INCR) | LBL | INCW;
880 1.5 chopps GSPSETHADRS(gsp, GSP_MODE_ADRS);
881 1.1 chopps gsp->data &= ~GMODE_FLUSH;
882 1.1 chopps
883 1.5 chopps GSPSETHADRS(gsp, PUT_HI_PTR_ADRS);
884 1.1 chopps put_hi = gsp->data << 16;
885 1.1 chopps
886 1.5 chopps GSPSETHADRS(gsp, PUT_PTR_ADRS);
887 1.1 chopps put = gsp->data;
888 1.1 chopps new_put = put + (8<<4);
889 1.1 chopps
890 1.5 chopps GSPSETHADRS(gsp, GET_PTR_ADRS);
891 1.1 chopps next = gsp->data;
892 1.1 chopps
893 1.1 chopps while (next == new_put) {
894 1.1 chopps /*
895 1.1 chopps * we should use an intr. here. unfortunately, we already
896 1.1 chopps * are called from an interupt and can't use tsleep.
897 1.1 chopps * so we do busy waiting, at least for the moment.
898 1.1 chopps */
899 1.1 chopps
900 1.1 chopps GSPSETHADRS(gsp,GET_PTR_ADRS);
901 1.1 chopps next = gsp->data;
902 1.1 chopps }
903 1.1 chopps
904 1.1 chopps GSPSETHADRS(gsp,put|put_hi);
905 1.1 chopps gsp->data = *ptr++ | 8<<4;
906 1.1 chopps while ( --n > 0) {
907 1.1 chopps gsp->data = *ptr++;
908 1.1 chopps }
909 1.1 chopps
910 1.1 chopps GSPSETHADRS(gsp,PUT_PTR_ADRS);
911 1.1 chopps gsp->data = new_put;
912 1.1 chopps GSPSETHADRS(gsp,oa);
913 1.1 chopps gsp->ctrl = oc;
914 1.1 chopps
915 1.1 chopps return;
916 1.1 chopps }
917 1.1 chopps
918 1.1 chopps #endif /* NGRF */
919