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