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