grf_ul.c revision 1.10 1 /* $NetBSD: grf_ul.c,v 1.10 1995/12/27 07:24:27 chopps 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 bt478 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 *, struct cfdata *, void *));
432
433 struct cfdriver grfulcd = {
434 NULL, "grful", (cfmatch_t)grfulmatch, grfulattach,
435 DV_DULL, sizeof(struct grf_ul_softc), NULL, 0 };
436
437 /*
438 * only used in console init
439 */
440 static struct cfdata *cfdata;
441
442 /*
443 * we make sure to only init things once. this is somewhat
444 * tricky regarding the console.
445 */
446 int
447 grfulmatch(pdp, cfp, auxp)
448 struct device *pdp;
449 struct cfdata *cfp;
450 void *auxp;
451 {
452 #ifdef ULOWELLCONSOLE
453 static int ulconunit = -1;
454 #endif
455 struct zbus_args *zap;
456
457 zap = auxp;
458
459 /*
460 * allow only one ulowell console
461 */
462 if (amiga_realconfig == 0)
463 #ifdef ULOWELLCONSOLE
464 if (ulconunit != -1)
465 #endif
466 return(0);
467
468 if (zap->manid != 1030 || zap->prodid != 0)
469 return(0);
470
471 #ifdef ULOWELLCONSOLE
472 if (amiga_realconfig == 0 || ulconunit != cfp->cf_unit) {
473 #endif
474 if ((unsigned)ulowell_default_mon >= ulowell_mon_max)
475 ulowell_default_mon = 1;
476
477 current_mon = ul_monitor_defs + ulowell_default_mon - 1;
478 if (ulowell_alive(current_mon) == 0)
479 return(0);
480 #ifdef ULOWELLCONSOLE
481 if (amiga_realconfig == 0) {
482 ulconunit = cfp->cf_unit;
483 cfdata = cfp;
484 }
485 }
486 #endif
487 return(1);
488 }
489
490 /*
491 * attach to the grfbus (zbus)
492 */
493 void
494 grfulattach(pdp, dp, auxp)
495 struct device *pdp, *dp;
496 void *auxp;
497 {
498 static struct grf_ul_softc congrf;
499 struct zbus_args *zap;
500 struct grf_softc *gp;
501 struct grf_ul_softc *gup;
502
503 zap = auxp;
504
505 if (dp == NULL)
506 gup = &congrf;
507 else
508 gup = (struct grf_ul_softc *)dp;
509
510 gp = &gup->gus_sc;
511
512 if (dp != NULL && congrf.gus_sc.g_regkva != 0) {
513 /*
514 * inited earlier, just copy (not device struct)
515 */
516 bcopy(&congrf.gus_sc.g_display, &gp->g_display,
517 (char *)&gup->gus_isr - (char *)&gp->g_display);
518
519 /* ...and transfer the isr */
520 gup->gus_isr.isr_ipl = 2;
521 gup->gus_isr.isr_intr = ulisr;
522 gup->gus_isr.isr_arg = (void *)gp;
523 /*
524 * To make sure ints are always catched, first add new isr
525 * then remove old:
526 */
527 add_isr(&gup->gus_isr);
528 remove_isr(&congrf.gus_isr);
529 } else {
530 gp->g_regkva = (caddr_t)zap->va;
531 gp->g_fbkva = NULL;
532 gp->g_unit = GRF_ULOWELL_UNIT;
533 gp->g_flags = GF_ALIVE;
534 gp->g_mode = ul_mode;
535 gp->g_conpri = grful_cnprobe();
536 gp->g_data = NULL;
537
538 gup->gus_isr.isr_ipl = 2;
539 gup->gus_isr.isr_intr = ulisr;
540 gup->gus_isr.isr_arg = (void *)gp;
541 add_isr(&gup->gus_isr);
542
543 (void)ul_load_code(gp);
544 (void)ul_load_mon(gp, current_mon);
545 grful_iteinit(gp);
546 }
547 if (dp != NULL)
548 printf("\n");
549 /*
550 * attach grf
551 */
552 amiga_config_found(cfdata, &gp->g_device, gp, grfulprint);
553 }
554
555 int
556 grfulprint(auxp, pnp)
557 void *auxp;
558 char *pnp;
559 {
560 if (pnp)
561 printf("grf%d at %s", ((struct grf_softc *)auxp)->g_unit,
562 pnp);
563 return(UNCONF);
564 }
565
566 static int
567 ul_getvmode (gp, vm)
568 struct grf_softc *gp;
569 struct grfvideo_mode *vm;
570 {
571 struct grfvideo_mode *md;
572
573 if (vm->mode_num && vm->mode_num > ulowell_mon_max)
574 return EINVAL;
575
576 if (! vm->mode_num)
577 vm->mode_num = current_mon - ul_monitor_defs + 1;
578
579 md = ul_monitor_defs + vm->mode_num - 1;
580 strncpy (vm->mode_descr, md->mode_descr,
581 sizeof (vm->mode_descr));
582
583 /* XXX should tell TMS to measure it */
584 vm->pixel_clock = md->pixel_clock;
585 vm->disp_width = md->disp_width;
586 vm->disp_height = md->disp_height;
587 vm->depth = md->depth;
588
589 vm->hblank_start = (md->hblank_start - md->hblank_stop) * 16;
590 vm->hblank_stop = (md->htotal - 1) * 16;
591 vm->hsync_start = (md->hsync_start - md->hblank_stop) * 16;
592 vm->hsync_stop = (md->hsync_stop + md->htotal - md->hblank_stop) * 16;
593 vm->htotal = md->htotal * 16;
594
595 vm->vblank_start = md->vblank_start - md->vblank_stop;
596 vm->vblank_stop = md->vtotal - 1;
597 vm->vsync_start = md->vsync_start - md->vblank_stop;
598 vm->vsync_stop = md->vsync_stop + md->vtotal - md->vblank_stop;
599 vm->vtotal = md->vtotal;
600
601 return 0;
602 }
603
604
605 static int
606 ul_setvmode (gp, mode)
607 struct grf_softc *gp;
608 unsigned mode;
609 {
610 struct grf_ul_softc *gup;
611 struct gspregs *ba;
612 int error;
613
614 if (!mode || mode > ulowell_mon_max)
615 return EINVAL;
616
617 ba = (struct gspregs *)gp->g_regkva;
618 gup = (struct grf_ul_softc *)gp;
619 current_mon = ul_monitor_defs + mode - 1;
620
621 error = ul_load_mon (gp, current_mon) ? 0 : EINVAL;
622
623 return error;
624 }
625
626 /*
627 * Set the frame buffer or overlay planes on or off.
628 * Always succeeds.
629 */
630
631 static __inline void
632 ul_setfb(gp, cmd)
633 struct grf_softc *gp;
634 int cmd;
635 {
636 struct grf_ul_softc *gup;
637 struct gspregs *ba;
638
639 gup = (struct grf_ul_softc *)gp;
640
641 ba = (struct gspregs *)gp->g_regkva;
642 ba->ctrl = LBL;
643 ba->hstadrh = 0xfe80;
644 ba->hstadrl = 0x0000;
645 ba->data = 6;
646 ba->hstadrl = 0x0020;
647
648 switch (cmd) {
649 case GM_GRFON:
650 gup->gus_ovslct |= 0x40;
651 break;
652 case GM_GRFOFF:
653 gup->gus_ovslct &= ~0x40;
654 break;
655 case GM_GRFOVON:
656 gup->gus_ovslct |= 3;
657 break;
658 case GM_GRFOVOFF:
659 gup->gus_ovslct &= ~3;
660 break;
661 }
662 ba->data = gup->gus_ovslct;
663 }
664
665 /*
666 * Change the mode of the display.
667 * Return a UNIX error number or 0 for success.
668 */
669 int
670 ul_mode(gp, cmd, arg, a2, a3)
671 struct grf_softc *gp;
672 int cmd;
673 void *arg;
674 int a2, a3;
675 {
676 int i;
677 struct grfdyninfo *gd;
678
679 switch (cmd) {
680 case GM_GRFON:
681 case GM_GRFOFF:
682 case GM_GRFOVON:
683 case GM_GRFOVOFF:
684 ul_setfb (gp, cmd);
685 return 0;
686
687 case GM_GRFCONFIG:
688 gd = (struct grfdyninfo *)arg;
689 for (i=0; i<ulowell_mon_max; ++i) {
690 if (ul_monitor_defs[i].disp_width == gd->gdi_dwidth &&
691 ul_monitor_defs[i].disp_height == gd->gdi_dheight)
692 return ul_setvmode(gp, i+1);
693 }
694 return EINVAL;
695
696 case GM_GRFGETVMODE:
697 return ul_getvmode (gp, (struct grfvideo_mode *) arg);
698
699 case GM_GRFSETVMODE:
700 return ul_setvmode (gp, *(unsigned *) arg);
701
702 case GM_GRFGETNUMVM:
703 *(int *)arg = ulowell_mon_max;
704 return 0;
705
706 case GM_GRFIOCTL:
707 return ul_ioctl (gp, (u_long)arg, (void *)a2, (dev_t)a3);
708
709 default:
710 break;
711 }
712
713 return EINVAL;
714 }
715
716 int
717 ul_ioctl (gp, cmd, data, dev)
718 register struct grf_softc *gp;
719 u_long cmd;
720 void *data;
721 dev_t dev;
722 {
723 switch (cmd) {
724 #if 0
725 /*
726 * XXX we have no hardware sprites, but might implement them
727 * later in TMS code.
728 */
729
730 case GRFIOCGSPRITEPOS:
731 return ul_getspritepos (gp, (struct grf_position *) data);
732
733 case GRFIOCSSPRITEPOS:
734 return ul_setspritepos (gp, (struct grf_position *) data);
735
736 case GRFIOCSSPRITEINF:
737 return ul_setspriteinfo (gp, (struct grf_spriteinfo *) data);
738
739 case GRFIOCGSPRITEINF:
740 return ul_getspriteinfo (gp, (struct grf_spriteinfo *) data);
741
742 case GRFIOCGSPRITEMAX:
743 return ul_getspritemax (gp, (struct grf_position *) data);
744
745 #endif
746
747 case GRFIOCGETCMAP:
748 return ul_getcmap (gp, (struct grf_colormap *) data, dev);
749
750 case GRFIOCPUTCMAP:
751 return ul_putcmap (gp, (struct grf_colormap *) data, dev);
752
753 case GRFIOCBITBLT:
754 return ul_bitblt (gp, (struct grf_bitblt *) data, dev);
755
756 case GRFIOCBLANK:
757 return ul_blank (gp, (int *) data, dev);
758 }
759
760 return EINVAL;
761 }
762
763 int
764 ul_getcmap (gp, cmap, dev)
765 struct grf_softc *gp;
766 struct grf_colormap *cmap;
767 dev_t dev;
768 {
769 struct grf_ul_softc *gup;
770 u_int8_t *mymap;
771 int mxidx, error;
772
773 gup = (struct grf_ul_softc *)gp;
774
775 if (minor(dev) & GRFIMDEV) {
776 mxidx = 256;
777 mymap = gup->gus_imcmap;
778 } else {
779 mxidx = 4;
780 mymap = gup->gus_ovcmap;
781 }
782
783 if (cmap->count == 0 || cmap->index >= mxidx)
784 return 0;
785
786 if (cmap->index + cmap->count > mxidx)
787 cmap->count = mxidx - cmap->index;
788
789 /* just copyout from the shadow color map */
790
791 if ((error = copyout(mymap + cmap->index, cmap->red, cmap->count))
792
793 || (error = copyout(mymap + mxidx + cmap->index, cmap->green,
794 cmap->count))
795
796 || (error = copyout(mymap + mxidx * 2 + cmap->index, cmap->blue,
797 cmap->count)))
798
799 return(error);
800
801 return(0);
802 }
803
804 int
805 ul_putcmap (gp, cmap, dev)
806 struct grf_softc *gp;
807 struct grf_colormap *cmap;
808 dev_t dev;
809 {
810 struct grf_ul_softc *gup;
811 struct gspregs *ba;
812 u_int16_t cmd[8];
813 int x, mxidx, error;
814 u_int8_t *mymap;
815
816 gup = (struct grf_ul_softc *)gp;
817
818 if (minor(dev) & GRFIMDEV) {
819 mxidx = 256;
820 mymap = gup->gus_imcmap;
821 } else {
822 mxidx = 4;
823 mymap = gup->gus_ovcmap;
824 }
825
826 if (cmap->count == 0 || cmap->index >= mxidx)
827 return 0;
828
829 if (cmap->index + cmap->count > mxidx)
830 cmap->count = mxidx - cmap->index;
831
832 /* first copyin to our shadow color map */
833
834 if ((error = copyin(cmap->red, mymap + cmap->index, cmap->count))
835
836 || (error = copyin(cmap->green, mymap + cmap->index + mxidx,
837 cmap->count))
838
839 || (error = copyin(cmap->blue, mymap + cmap->index + mxidx*2,
840 cmap->count)))
841
842 return error;
843
844
845 /* then write from there to the hardware */
846 ba = (struct gspregs *)gp->g_regkva;
847 /*
848 * XXX This is a bad thing to do.
849 * We should always use the gsp call, or have a means to arbitrate
850 * the usage of the BT478 index register. Else there might be a
851 * race condition (when writing both colormaps at nearly the same
852 * time), where one CPU changes the index register when the other
853 * one has not finished using it.
854 */
855 if (mxidx > 4) {
856 /* image color map: we can write, with a hack, directly */
857 ba->ctrl = LBL;
858 ba->hstadrh = 0xfe80;
859 ba->hstadrl = 0x0000;
860 ba->ctrl |= INCW;
861 ba->data = cmap->index;
862 ba->ctrl &= ~INCW;
863
864 for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
865 ba->data = (u_int16_t) mymap[x];
866 ba->data = (u_int16_t) mymap[x + mxidx];
867 ba->data = (u_int16_t) mymap[x + mxidx * 2];
868 }
869 } else {
870
871 /* overlay planes color map: have to call tms to do it */
872 cmd[0] = GCMD_CMAP;
873 cmd[1] = 1;
874 for (x=cmap->index; x < cmap->index + cmap->count; ++x) {
875 cmd[2] = x;
876 cmd[3] = mymap[x];
877 cmd[4] = mymap[x + mxidx];
878 cmd[5] = mymap[x + mxidx * 2];
879 gsp_write(ba, cmd, 6);
880 }
881 }
882 return 0;
883 }
884
885 int
886 ul_blank(gp, onoff, dev)
887 struct grf_softc *gp;
888 int *onoff;
889 dev_t dev;
890 {
891 struct gspregs *gsp;
892 gsp = (struct gspregs *)gp->g_regkva;
893 gsp->ctrl = (gsp->ctrl & ~(INCR|INCW) | LBL);
894 gsp->hstadrh = 0xC000;
895 gsp->hstadrl = 0x0080;
896 if (*onoff)
897 gsp->data |= 0x9000;
898 else
899 gsp->data &= ~0x9000;
900
901 return 0;
902 }
903 /*
904 * !!! THIS AREA UNDER CONSTRUCTION !!!
905 */
906 int ul_BltOpMap[16] = {
907 3, 1, 2, 0, 11, 9, 10, 8,
908 7, 5, 6, 4, 15, 13, 14, 12
909 };
910
911 int
912 ul_bitblt (gp, bb, dev)
913 struct grf_softc *gp;
914 struct grf_bitblt *bb;
915 dev_t dev;
916 {
917 /* XXX not yet implemented, but pretty trivial */
918 return EINVAL;
919 }
920
921 void
922 gsp_write(gsp, ptr, size)
923 struct gspregs *gsp;
924 u_short *ptr;
925 size_t size;
926 {
927 u_short put, new_put, next, oc;
928 u_long put_hi, oa;
929 size_t n;
930
931 if (size == 0 || size > 8)
932 return;
933
934 n = size;
935
936 oc = gsp->ctrl;
937 oa = GSPGETHADRS(gsp);
938
939 gsp->ctrl = (oc & ~INCR) | LBL | INCW;
940 GSPSETHADRS(gsp, GSP_MODE_ADRS);
941 gsp->data &= ~GMODE_FLUSH;
942
943 GSPSETHADRS(gsp, PUT_HI_PTR_ADRS);
944 put_hi = gsp->data << 16;
945
946 GSPSETHADRS(gsp, PUT_PTR_ADRS);
947 put = gsp->data;
948 new_put = put + (8<<4);
949
950 GSPSETHADRS(gsp, GET_PTR_ADRS);
951 next = gsp->data;
952
953 while (next == new_put) {
954 /*
955 * we should use an intr. here. unfortunately, we already
956 * are called from an interupt and can't use tsleep.
957 * so we do busy waiting, at least for the moment.
958 */
959
960 GSPSETHADRS(gsp,GET_PTR_ADRS);
961 next = gsp->data;
962 }
963
964 GSPSETHADRS(gsp,put|put_hi);
965 gsp->data = *ptr++ | 8<<4;
966 while ( --n > 0) {
967 gsp->data = *ptr++;
968 }
969
970 GSPSETHADRS(gsp,PUT_PTR_ADRS);
971 gsp->data = new_put;
972 GSPSETHADRS(gsp,oa);
973 gsp->ctrl = oc;
974
975 return;
976 }
977
978 #endif /* NGRF */
979