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