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