grf_ul.c revision 1.7.2.2 1 /* $NetBSD: grf_ul.c,v 1.7.2.2 1996/03/04 18:32:00 is 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 #if 1
277 /* XXX load image palette with some initial values, slightly hacky */
278
279 ba->hstadrh = 0xfe80;
280 ba->hstadrl = 0x0000;
281 ba->ctrl |= INCW;
282 ba->data = 0;
283 ba->ctrl &= ~INCW;
284
285 for (i=0; i<16; ++i) {
286 ba->data = gup->gus_imcmap[i+ 0] = ul_std_palette[i+ 0];
287 ba->data = gup->gus_imcmap[i+256] = ul_std_palette[i+16];
288 ba->data = gup->gus_imcmap[i+512] = ul_std_palette[i+32];
289 }
290
291 /*
292 * XXX load shadow overlay palette with what the TMS code will load
293 * into the real one some time after the TMS code is started below.
294 * This might be considered a rude hack.
295 */
296 bcopy(ul_ovl_palette, gup->gus_ovcmap, 3*4);
297
298 /*
299 * Unflush cache, unhalt cpu -> nmi starts to run. This MUST NOT BE
300 * DONE before the image color map initialization above, to guarantee
301 * the index register in the bt478 is not used by more than one CPU
302 * at once.
303 *
304 * XXX For the same reason, we'll have to rething ul_putcmap(). For
305 * details, look at comment there.
306 */
307 ba->ctrl &= ~(HLT|CF);
308
309 #else
310 /*
311 * XXX I wonder why this partially ever worked.
312 *
313 * This can't possibly work this way, as we are copyin()ing data in
314 * ul_putcmap.
315 *
316 * I guess this partially worked because SFC happened to point to
317 * to supervisor data space on 68030 machines coming from the old
318 * boot loader.
319 *
320 * While this looks more correct than the hack in the other part of the
321 * loop, we would have to do our own version of the loop through
322 * colormap entries, set up command buffer, and call gsp_write(), or
323 * factor out some code.
324 */
325
326 /*
327 * XXX This version will work for the overlay, if our queue codes
328 * initial conditions are set at load time (not start time).
329 * It further assumes that ul_putcmap only uses the
330 * GRFIMDEV/GRFOVDEV bits of the dev parameter.
331 */
332
333
334 /* unflush cache, unhalt cpu first -> nmi starts to run */
335 ba->ctrl &= ~(HLT|CF);
336
337 gcm.index = 0;
338 gcm.count = 16;
339 gcm.red = ul_std_palette + 0;
340 gcm.green = ul_std_palette + 16;
341 gcm.blue = ul_std_palette + 32;
342 ul_putcmap(gp, &gcm, GRFIMDEV);
343
344 gcm.index = 0;
345 gcm.count = 4;
346 gcm.red = ul_ovl_palette + 0;
347 gcm.green = ul_ovl_palette + 4;
348 gcm.blue = ul_ovl_palette + 8;
349 ul_putcmap(gp, &gcm, GRFOVDEV);
350 #endif
351
352 }
353
354 static int
355 ul_load_mon(gp, md)
356 struct grf_softc *gp;
357 struct grfvideo_mode *md;
358 {
359 struct grf_ul_softc *gup;
360 struct grfinfo *gi;
361 struct gspregs *ba;
362 u_int16_t buf[8];
363
364 gup = (struct grf_ul_softc *)gp;
365 gi = &gp->g_display;
366 ba = (struct gspregs *)gp->g_regkva;
367
368 gi->gd_dyn.gdi_fbx = 0;
369 gi->gd_dyn.gdi_fby = 0;
370 gi->gd_dyn.gdi_dwidth = md->disp_width;
371 gi->gd_dyn.gdi_dheight = md->disp_height;
372 gi->gd_dyn.gdi_dx = 0;
373 gi->gd_dyn.gdi_dy = 0;
374
375 ba->ctrl = (ba->ctrl & ~INCR) | (LBL|INCW);
376
377 ba->hstadrh = 0xC000;
378 ba->hstadrl = 0x0000;
379 ba->data = md->hsync_stop;
380 ba->data = md->hblank_stop;
381 ba->data = md->hblank_start;
382 ba->data = md->hsync_start;
383 ba->data = md->vsync_stop;
384 ba->data = md->vblank_stop;
385 ba->data = md->vblank_start;
386 ba->data = md->vsync_start;
387
388 ba->ctrl &= ~INCW;
389 ba->hstadrh = 0xFE90;
390 ba->hstadrl = 0x0000;
391
392 if (abs(md->pixel_clock - ulowell_clock[0]) >
393 abs(md->pixel_clock - ulowell_clock[1])) {
394
395 ba->data = (ba->data & 0xFC) | 2 | 1;
396 md->pixel_clock = ulowell_clock[1];
397
398 } else {
399 ba->data = (ba->data & 0xFC) | 2 | 0;
400 md->pixel_clock = ulowell_clock[0];
401 }
402
403 ba->ctrl |= LBL|INCW;
404 ba->hstadrh = 0xC000;
405 ba->hstadrl = 0x0080;
406 ba->data = (md->vblank_start - md->vblank_stop == md->disp_height ?
407 0xf020 : 0xb020);
408
409 /* I guess this should be in the yet unimplemented mode select ioctl */
410 /* Hm.. maybe not. We always put the console on overlay plane no 0. */
411 /* Anyway, this _IS_ called in the mode select ioctl. */
412
413 /* ite support code parameters: */
414 buf[0] = GCMD_MCHG;
415 buf[1] = md->disp_width; /* display width */
416 buf[2] = md->disp_height; /* display height */
417 buf[3] = 0; /* LSW of frame buffer origin */
418 buf[4] = 0xFF80; /* MSW of frame buffer origin */
419 buf[5] = gi->gd_fbwidth * 1; /* frame buffer pitch */
420 buf[6] = 1; /* frame buffer depth */
421 gsp_write(ba, buf, 7);
422
423 return(1);
424 }
425
426 int ul_mode __P((struct grf_softc *, int, void *, int , int));
427
428 void grfulattach __P((struct device *, struct device *, void *));
429 int grfulprint __P((void *, char *));
430 int grfulmatch __P((struct device *, struct cfdata *, void *));
431
432 struct cfdriver grfulcd = {
433 NULL, "grful", (cfmatch_t)grfulmatch, grfulattach,
434 DV_DULL, sizeof(struct grf_ul_softc), NULL, 0 };
435
436 /*
437 * only used in console init
438 */
439 static struct cfdata *cfdata;
440
441 /*
442 * we make sure to only init things once. this is somewhat
443 * tricky regarding the console.
444 */
445 int
446 grfulmatch(pdp, cfp, auxp)
447 struct device *pdp;
448 struct cfdata *cfp;
449 void *auxp;
450 {
451 #ifdef ULOWELLCONSOLE
452 static int ulconunit = -1;
453 #endif
454 struct zbus_args *zap;
455
456 zap = auxp;
457
458 /*
459 * allow only one ulowell console
460 */
461 if (amiga_realconfig == 0)
462 #ifdef ULOWELLCONSOLE
463 if (ulconunit != -1)
464 #endif
465 return(0);
466
467 if (zap->manid != 1030 || zap->prodid != 0)
468 return(0);
469
470 #ifdef ULOWELLCONSOLE
471 if (amiga_realconfig == 0 || ulconunit != cfp->cf_unit) {
472 #endif
473 if ((unsigned)ulowell_default_mon > ulowell_mon_max)
474 ulowell_default_mon = 1;
475
476 current_mon = ul_monitor_defs + ulowell_default_mon - 1;
477 if (ulowell_alive(current_mon) == 0)
478 return(0);
479 #ifdef ULOWELLCONSOLE
480 if (amiga_realconfig == 0) {
481 ulconunit = cfp->cf_unit;
482 cfdata = cfp;
483 }
484 }
485 #endif
486 return(1);
487 }
488
489 /*
490 * attach to the grfbus (zbus)
491 */
492 void
493 grfulattach(pdp, dp, auxp)
494 struct device *pdp, *dp;
495 void *auxp;
496 {
497 static struct grf_ul_softc congrf;
498 struct zbus_args *zap;
499 struct grf_softc *gp;
500 struct grf_ul_softc *gup;
501
502 zap = auxp;
503
504 if (dp == NULL)
505 gup = &congrf;
506 else
507 gup = (struct grf_ul_softc *)dp;
508
509 gp = &gup->gus_sc;
510
511 if (dp != NULL && congrf.gus_sc.g_regkva != 0) {
512 /*
513 * inited earlier, just copy (not device struct)
514 */
515 bcopy(&congrf.gus_sc.g_display, &gp->g_display,
516 (char *)&gup->gus_isr - (char *)&gp->g_display);
517
518 /* ...and transfer the isr */
519 gup->gus_isr.isr_ipl = 2;
520 gup->gus_isr.isr_intr = ulisr;
521 gup->gus_isr.isr_arg = (void *)gp;
522 /*
523 * To make sure ints are always catched, first add new isr
524 * then remove old:
525 */
526 add_isr(&gup->gus_isr);
527 remove_isr(&congrf.gus_isr);
528 } else {
529 gp->g_regkva = (caddr_t)zap->va;
530 gp->g_fbkva = NULL;
531 gp->g_unit = GRF_ULOWELL_UNIT;
532 gp->g_flags = GF_ALIVE;
533 gp->g_mode = ul_mode;
534 gp->g_conpri = grful_cnprobe();
535 gp->g_data = NULL;
536
537 gup->gus_isr.isr_ipl = 2;
538 gup->gus_isr.isr_intr = ulisr;
539 gup->gus_isr.isr_arg = (void *)gp;
540 add_isr(&gup->gus_isr);
541
542 (void)ul_load_code(gp);
543 (void)ul_load_mon(gp, current_mon);
544 grful_iteinit(gp);
545 }
546 if (dp != NULL)
547 printf("\n");
548 /*
549 * attach grf
550 */
551 amiga_config_found(cfdata, &gp->g_device, gp, grfulprint);
552 }
553
554 int
555 grfulprint(auxp, pnp)
556 void *auxp;
557 char *pnp;
558 {
559 if (pnp)
560 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
561 pnp);
562 return(UNCONF);
563 }
564
565 static int
566 ul_getvmode (gp, vm)
567 struct grf_softc *gp;
568 struct grfvideo_mode *vm;
569 {
570 struct grfvideo_mode *md;
571
572 if (vm->mode_num && vm->mode_num > ulowell_mon_max)
573 return EINVAL;
574
575 if (! vm->mode_num)
576 vm->mode_num = current_mon - ul_monitor_defs + 1;
577
578 md = ul_monitor_defs + vm->mode_num - 1;
579 strncpy (vm->mode_descr, md->mode_descr,
580 sizeof (vm->mode_descr));
581
582 /* XXX should tell TMS to measure it */
583 vm->pixel_clock = md->pixel_clock;
584 vm->disp_width = md->disp_width;
585 vm->disp_height = md->disp_height;
586 vm->depth = md->depth;
587
588 vm->hblank_start = (md->hblank_start - md->hblank_stop) * 16;
589 vm->hblank_stop = (md->htotal - 1) * 16;
590 vm->hsync_start = (md->hsync_start - md->hblank_stop) * 16;
591 vm->hsync_stop = (md->hsync_stop + md->htotal - md->hblank_stop) * 16;
592 vm->htotal = md->htotal * 16;
593
594 vm->vblank_start = md->vblank_start - md->vblank_stop;
595 vm->vblank_stop = md->vtotal - 1;
596 vm->vsync_start = md->vsync_start - md->vblank_stop;
597 vm->vsync_stop = md->vsync_stop + md->vtotal - md->vblank_stop;
598 vm->vtotal = md->vtotal;
599
600 return 0;
601 }
602
603
604 static int
605 ul_setvmode (gp, mode)
606 struct grf_softc *gp;
607 unsigned mode;
608 {
609 struct grf_ul_softc *gup;
610 struct gspregs *ba;
611 int error;
612
613 if (!mode || mode > ulowell_mon_max)
614 return EINVAL;
615
616 ba = (struct gspregs *)gp->g_regkva;
617 gup = (struct grf_ul_softc *)gp;
618 current_mon = ul_monitor_defs + mode - 1;
619
620 error = ul_load_mon (gp, current_mon) ? 0 : EINVAL;
621
622 return error;
623 }
624
625 /*
626 * Set the frame buffer or overlay planes on or off.
627 * Always succeeds.
628 */
629
630 static __inline void
631 ul_setfb(gp, cmd)
632 struct grf_softc *gp;
633 int cmd;
634 {
635 struct grf_ul_softc *gup;
636 struct gspregs *ba;
637
638 gup = (struct grf_ul_softc *)gp;
639
640 ba = (struct gspregs *)gp->g_regkva;
641 ba->ctrl = LBL;
642 ba->hstadrh = 0xfe80;
643 ba->hstadrl = 0x0000;
644 ba->data = 6;
645 ba->hstadrl = 0x0020;
646
647 switch (cmd) {
648 case GM_GRFON:
649 gup->gus_ovslct |= 0x40;
650 break;
651 case GM_GRFOFF:
652 gup->gus_ovslct &= ~0x40;
653 break;
654 case GM_GRFOVON:
655 gup->gus_ovslct |= 3;
656 break;
657 case GM_GRFOVOFF:
658 gup->gus_ovslct &= ~3;
659 break;
660 }
661 ba->data = gup->gus_ovslct;
662 }
663
664 /*
665 * Change the mode of the display.
666 * Return a UNIX error number or 0 for success.
667 */
668 int
669 ul_mode(gp, cmd, arg, a2, a3)
670 struct grf_softc *gp;
671 int cmd;
672 void *arg;
673 int a2, a3;
674 {
675 int i;
676 struct grfdyninfo *gd;
677
678 switch (cmd) {
679 case GM_GRFON:
680 case GM_GRFOFF:
681 case GM_GRFOVON:
682 case GM_GRFOVOFF:
683 ul_setfb (gp, cmd);
684 return 0;
685
686 case GM_GRFCONFIG:
687 gd = (struct grfdyninfo *)arg;
688 for (i=0; i<ulowell_mon_max; ++i) {
689 if (ul_monitor_defs[i].disp_width == gd->gdi_dwidth &&
690 ul_monitor_defs[i].disp_height == gd->gdi_dheight)
691 return ul_setvmode(gp, i+1);
692 }
693 return EINVAL;
694
695 case GM_GRFGETVMODE:
696 return ul_getvmode (gp, (struct grfvideo_mode *) arg);
697
698 case GM_GRFSETVMODE:
699 return ul_setvmode (gp, *(unsigned *) arg);
700
701 case GM_GRFGETNUMVM:
702 *(int *)arg = ulowell_mon_max;
703 return 0;
704
705 case GM_GRFIOCTL:
706 return ul_ioctl (gp, (u_long)arg, (void *)a2, (dev_t)a3);
707
708 default:
709 break;
710 }
711
712 return EINVAL;
713 }
714
715 int
716 ul_ioctl (gp, cmd, data, dev)
717 register struct grf_softc *gp;
718 u_long cmd;
719 void *data;
720 dev_t dev;
721 {
722 switch (cmd) {
723 #if 0
724 /*
725 * XXX we have no hardware sprites, but might implement them
726 * later in TMS code.
727 */
728
729 case GRFIOCGSPRITEPOS:
730 return ul_getspritepos (gp, (struct grf_position *) data);
731
732 case GRFIOCSSPRITEPOS:
733 return ul_setspritepos (gp, (struct grf_position *) data);
734
735 case GRFIOCSSPRITEINF:
736 return ul_setspriteinfo (gp, (struct grf_spriteinfo *) data);
737
738 case GRFIOCGSPRITEINF:
739 return ul_getspriteinfo (gp, (struct grf_spriteinfo *) data);
740
741 case GRFIOCGSPRITEMAX:
742 return ul_getspritemax (gp, (struct grf_position *) data);
743
744 #endif
745
746 case GRFIOCGETCMAP:
747 return ul_getcmap (gp, (struct grf_colormap *) data, dev);
748
749 case GRFIOCPUTCMAP:
750 return ul_putcmap (gp, (struct grf_colormap *) data, dev);
751
752 case GRFIOCBITBLT:
753 return ul_bitblt (gp, (struct grf_bitblt *) data, dev);
754 }
755
756 return EINVAL;
757 }
758
759 int
760 ul_getcmap (gp, cmap, dev)
761 struct grf_softc *gp;
762 struct grf_colormap *cmap;
763 dev_t dev;
764 {
765 struct grf_ul_softc *gup;
766 u_int8_t *mymap;
767 int mxidx, error;
768
769 gup = (struct grf_ul_softc *)gp;
770
771 if (minor(dev) & GRFIMDEV) {
772 mxidx = 256;
773 mymap = gup->gus_imcmap;
774 } else {
775 mxidx = 4;
776 mymap = gup->gus_ovcmap;
777 }
778
779 if (cmap->count == 0 || cmap->index >= mxidx)
780 return 0;
781
782 if (cmap->index + cmap->count > mxidx)
783 cmap->count = mxidx - cmap->index;
784
785 /* just copyout from the shadow color map */
786
787 if ((error = copyout(mymap + cmap->index, cmap->red, cmap->count))
788
789 || (error = copyout(mymap + mxidx + cmap->index, cmap->green,
790 cmap->count))
791
792 || (error = copyout(mymap + mxidx * 2 + cmap->index, cmap->blue,
793 cmap->count)))
794
795 return(error);
796
797 return(0);
798 }
799
800 int
801 ul_putcmap (gp, cmap, dev)
802 struct grf_softc *gp;
803 struct grf_colormap *cmap;
804 dev_t dev;
805 {
806 struct grf_ul_softc *gup;
807 struct gspregs *ba;
808 u_int16_t cmd[8];
809 int x, mxidx, error;
810 u_int8_t *mymap;
811
812 gup = (struct grf_ul_softc *)gp;
813
814 if (minor(dev) & GRFIMDEV) {
815 mxidx = 256;
816 mymap = gup->gus_imcmap;
817 } else {
818 mxidx = 4;
819 mymap = gup->gus_ovcmap;
820 }
821
822 if (cmap->count == 0 || cmap->index >= mxidx)
823 return 0;
824
825 if (cmap->index + cmap->count > mxidx)
826 cmap->count = mxidx - cmap->index;
827
828 /* first copyin to our shadow color map */
829
830 if ((error = copyin(cmap->red, mymap + cmap->index, cmap->count))
831
832 || (error = copyin(cmap->green, mymap + cmap->index + mxidx,
833 cmap->count))
834
835 || (error = copyin(cmap->blue, mymap + cmap->index + mxidx*2,
836 cmap->count)))
837
838 return error;
839
840
841 /* then write from there to the hardware */
842 ba = (struct gspregs *)gp->g_regkva;
843 if (mxidx > 4) {
844 /* image color map: we can write, with a hack, directly */
845 ba->ctrl = LBL;
846 ba->hstadrh = 0xfe80;
847 ba->hstadrl = 0x0000;
848 ba->ctrl |= INCW;
849 ba->data = cmap->index;
850 ba->ctrl &= ~INCW;
851
852 for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
853 ba->data = (u_int16_t) mymap[x];
854 ba->data = (u_int16_t) mymap[x + mxidx];
855 ba->data = (u_int16_t) mymap[x + mxidx * 2];
856 }
857 } else {
858
859 /* overlay planes color map: have to call tms to do it */
860 cmd[0] = GCMD_CMAP;
861 cmd[1] = 1;
862 for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
863 cmd[2] = x;
864 cmd[3] = mymap[x];
865 cmd[4] = mymap[x + mxidx];
866 cmd[5] = mymap[x + mxidx * 2];
867 gsp_write(ba, cmd, 6);
868 }
869 }
870 return 0;
871 }
872
873 /*
874 * !!! THIS AREA UNDER CONSTRUCTION !!!
875 */
876 int ul_BltOpMap[16] = {
877 3, 1, 2, 0, 11, 9, 10, 8,
878 7, 5, 6, 4, 15, 13, 14, 12
879 };
880
881 int
882 ul_bitblt (gp, bb, dev)
883 struct grf_softc *gp;
884 struct grf_bitblt *bb;
885 dev_t dev;
886 {
887 /* XXX not yet implemented, but pretty trivial */
888 return EINVAL;
889 }
890
891 void
892 gsp_write(gsp, ptr, size)
893 struct gspregs *gsp;
894 u_short *ptr;
895 size_t size;
896 {
897 u_short put, new_put, next, oc;
898 u_long put_hi, oa;
899 size_t n;
900
901 if (size == 0 || size > 8)
902 return;
903
904 n = size;
905
906 oc = gsp->ctrl;
907 oa = GSPGETHADRS(gsp);
908
909 gsp->ctrl = (oc & ~INCR) | LBL | INCW;
910 GSPSETHADRS(gsp, GSP_MODE_ADRS);
911 gsp->data &= ~GMODE_FLUSH;
912
913 GSPSETHADRS(gsp, PUT_HI_PTR_ADRS);
914 put_hi = gsp->data << 16;
915
916 GSPSETHADRS(gsp, PUT_PTR_ADRS);
917 put = gsp->data;
918 new_put = put + (8<<4);
919
920 GSPSETHADRS(gsp, GET_PTR_ADRS);
921 next = gsp->data;
922
923 while (next == new_put) {
924 /*
925 * we should use an intr. here. unfortunately, we already
926 * are called from an interupt and can't use tsleep.
927 * so we do busy waiting, at least for the moment.
928 */
929
930 GSPSETHADRS(gsp,GET_PTR_ADRS);
931 next = gsp->data;
932 }
933
934 GSPSETHADRS(gsp,put|put_hi);
935 gsp->data = *ptr++ | 8<<4;
936 while ( --n > 0) {
937 gsp->data = *ptr++;
938 }
939
940 GSPSETHADRS(gsp,PUT_PTR_ADRS);
941 gsp->data = new_put;
942 GSPSETHADRS(gsp,oa);
943 gsp->ctrl = oc;
944
945 return;
946 }
947
948 #endif /* NGRF */
949