grf_et.c revision 1.3 1 /* $NetBSD: grf_et.c,v 1.3 1996/06/09 13:21:10 veego Exp $ */
2
3 /*
4 * Copyright (c) 1996 Tobias Abt
5 * Copyright (c) 1995 Ezra Story
6 * Copyright (c) 1995 Kari Mettinen
7 * Copyright (c) 1994 Markus Wild
8 * Copyright (c) 1994 Lutz Vieweg
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Lutz Vieweg.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 #include "grfet.h"
37 #if NGRFET > 0
38
39 /*
40 * Graphics routines for Tseng ET4000 (&W32) boards,
41 *
42 * This code offers low-level routines to access Tseng ET4000
43 * graphics-boards from within NetBSD for the Amiga.
44 * No warranties for any kind of function at all - this
45 * code may crash your hardware and scratch your harddisk. Use at your
46 * own risk. Freely distributable.
47 *
48 * Modified for Tseng ET4000 from
49 * Kari Mettinen's Cirrus driver by Tobias Abt
50 *
51 *
52 * TODO:
53 *
54 */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/errno.h>
59 #include <sys/ioctl.h>
60 #include <sys/device.h>
61 #include <sys/malloc.h>
62
63 #include <machine/cpu.h>
64 #include <dev/cons.h>
65 #ifdef TSENGCONSOLE
66 #include <amiga/dev/itevar.h>
67 #endif
68 #include <amiga/amiga/device.h>
69 #include <amiga/dev/grfioctl.h>
70 #include <amiga/dev/grfvar.h>
71 #include <amiga/dev/grf_etreg.h>
72 #include <amiga/dev/zbusvar.h>
73
74 int et_mondefok __P((struct grfvideo_mode *gv));
75 void et_boardinit __P((struct grf_softc *gp));
76 static void et_CompFQ __P((u_int fq, u_char *num, u_char *denom));
77 int et_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
78 int et_setvmode __P((struct grf_softc *gp, unsigned int mode));
79 int et_toggle __P((struct grf_softc *gp, unsigned short));
80 int et_getcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
81 int et_putcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
82 #ifndef TSENGCONSOLE
83 void et_off __P((struct grf_softc *gp));
84 #endif
85 void et_inittextmode __P((struct grf_softc *gp));
86 int et_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data));
87 int et_getmousepos __P((struct grf_softc *gp, struct grf_position *data));
88 void et_writesprpos __P((volatile char *ba, short x, short y));
89 int et_setmousepos __P((struct grf_softc *gp, struct grf_position *data));
90 static int et_setspriteinfo __P((struct grf_softc *gp,
91 struct grf_spriteinfo *data));
92 int et_getspriteinfo __P((struct grf_softc *gp,
93 struct grf_spriteinfo *data));
94 static int et_getspritemax __P((struct grf_softc *gp,
95 struct grf_position *data));
96 int et_setmonitor __P((struct grf_softc *gp, struct grfvideo_mode *gv));
97 int et_blank __P((struct grf_softc *gp, int *on));
98 static int et_getControllerType __P((struct grf_softc *gp));
99 static int et_getDACType __P((struct grf_softc *gp));
100
101 int grfetmatch __P((struct device *, void *, void *));
102 void grfetattach __P((struct device *, struct device *, void *));
103 int grfetprint __P((void *, char *));
104 void et_memset __P((unsigned char *d, unsigned char c, int l));
105
106 /*
107 * Graphics display definitions.
108 * These are filled by 'grfconfig' using GRFIOCSETMON.
109 */
110 #define monitor_def_max 8
111 static struct grfvideo_mode monitor_def[8] = {
112 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
113 };
114 static struct grfvideo_mode *monitor_current = &monitor_def[0];
115
116 /* Console display definition.
117 * Default hardcoded text mode. This grf_et is set up to
118 * use one text mode only, and this is it. You may use
119 * grfconfig to change the mode after boot.
120 */
121 /* Console font */
122 #ifdef KFONT_8X11
123 #define TSENGFONT kernel_font_8x11
124 #define TSENGFONTY 11
125 #else
126 #define TSENGFONT kernel_font_8x8
127 #define TSENGFONTY 8
128 #endif
129 extern unsigned char TSENGFONT[];
130
131 struct grfettext_mode etconsole_mode = {
132 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
133 481, 521, 491, 493, 525},
134 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
135 };
136
137 /* Console colors */
138 unsigned char etconscolors[3][3] = { /* background, foreground, hilite */
139 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
140 };
141
142 int ettype = 0; /* oMniBus, Domino or Merlin */
143 int etctype = 0; /* ET4000 or ETW32 */
144 int etdtype = 0; /* Type of DAC (see grf_etregs.h) */
145
146 char etcmap_shift = 0; /* 6 or 8 bit cmap entries */
147 unsigned char pass_toggle; /* passthru status tracker */
148
149 unsigned char Merlin_switch = 0;
150
151 /*
152 * Because all Tseng-boards have 2 configdev entries, one for
153 * framebuffer mem and the other for regs, we have to hold onto
154 * the pointers globally until we match on both. This and 'ettype'
155 * are the primary obsticles to multiple board support, but if you
156 * have multiple boards you have bigger problems than grf_et.
157 */
158 static void *et_fbaddr = 0; /* framebuffer */
159 static void *et_regaddr = 0; /* registers */
160 static int et_fbsize; /* framebuffer size */
161
162 /* current sprite info, if you add support for multiple boards
163 * make this an array or something
164 */
165 struct grf_spriteinfo et_cursprite;
166
167 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
168 * you add multiple board support
169 */
170 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
171 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
172
173 /* standard driver stuff */
174 struct cfattach grfet_ca = {
175 sizeof(struct grf_softc), grfetmatch, grfetattach
176 };
177
178 struct cfdriver grfet_cd = {
179 NULL, "grfet", DV_DULL, NULL, 0
180 };
181
182 static struct cfdata *cfdata;
183
184 int
185 grfetmatch(pdp, match, auxp)
186 struct device *pdp;
187 void *match, *auxp;
188 {
189 #ifdef TSENGCONSOLE
190 struct cfdata *cfp = match;
191 #endif
192 struct zbus_args *zap;
193 static int regprod, fbprod;
194
195 zap = auxp;
196
197 #ifndef TSENGCONSOLE
198 if (amiga_realconfig == 0)
199 return (0);
200 #endif
201
202 /* Grab the first board we encounter as the preferred one. This will
203 * allow one board to work in a multiple Tseng board system, but not
204 * multiple boards at the same time. */
205 if (ettype == 0) {
206 switch (zap->manid) {
207 case OMNIBUS:
208 if (zap->prodid != 0)
209 return (0);
210 regprod = 0;
211 fbprod = 0;
212 break;
213 case DOMINO:
214 if (zap->prodid != 2 && zap->prodid != 1)
215 return (0);
216 regprod = 2;
217 fbprod = 1;
218 break;
219 case MERLIN:
220 if (zap->prodid != 3 && zap->prodid != 4)
221 return (0);
222 regprod = 4;
223 fbprod = 3;
224 break;
225 default:
226 return (0);
227 }
228 ettype = zap->manid;
229 } else {
230 if (ettype != zap->manid) {
231 return (0);
232 }
233 }
234
235 /* Configure either registers or framebuffer in any order */
236 /* as said before, oMniBus does not support ProdID */
237 if (ettype == OMNIBUS) {
238 if (zap->size == 64 * 1024) {
239 /* register area */
240 et_regaddr = zap->va;
241 } else {
242 /* memory area */
243 et_fbaddr = zap->va;
244 et_fbsize = zap->size;
245 }
246 } else {
247 if (zap->prodid == regprod) {
248 et_regaddr = zap->va;
249 } else {
250 if (zap->prodid == fbprod) {
251 et_fbaddr = zap->va;
252 et_fbsize = zap->size;
253 } else {
254 return (0);
255 }
256 }
257 }
258
259 #ifdef TSENGCONSOLE
260 if (amiga_realconfig == 0) {
261 cfdata = cfp;
262 }
263 #endif
264
265 return (1);
266 }
267
268
269 void
270 grfetattach(pdp, dp, auxp)
271 struct device *pdp, *dp;
272 void *auxp;
273 {
274 static struct grf_softc congrf;
275 struct zbus_args *zap;
276 struct grf_softc *gp;
277 static char attachflag = 0;
278
279 zap = auxp;
280
281 printf("\n");
282
283 /* make sure both halves have matched */
284 if (!et_regaddr || !et_fbaddr)
285 return;
286
287 /* do all that messy console/grf stuff */
288 if (dp == NULL)
289 gp = &congrf;
290 else
291 gp = (struct grf_softc *) dp;
292
293 if (dp != NULL && congrf.g_regkva != 0) {
294 /*
295 * inited earlier, just copy (not device struct)
296 */
297 bcopy(&congrf.g_display, &gp->g_display,
298 (char *) &gp[1] - (char *) &gp->g_display);
299 } else {
300 gp->g_regkva = (volatile caddr_t) et_regaddr;
301 gp->g_fbkva = (volatile caddr_t) et_fbaddr;
302
303 gp->g_unit = GRF_ET4000_UNIT;
304 gp->g_mode = et_mode;
305 gp->g_conpri = grfet_cnprobe();
306 gp->g_flags = GF_ALIVE;
307
308 /* wakeup the board */
309 et_boardinit(gp);
310
311 #ifdef TSENGCONSOLE
312 grfet_iteinit(gp);
313 (void) et_load_mon(gp, &etconsole_mode);
314 #endif
315 }
316
317 /*
318 * attach grf (once)
319 */
320 if (amiga_config_found(cfdata, &gp->g_device, gp, grfetprint)) {
321 attachflag = 1;
322 printf("grfet: %dMB ", et_fbsize / 0x100000);
323 switch (ettype) {
324 case OMNIBUS:
325 printf("oMniBus");
326 break;
327 case DOMINO:
328 printf("Domino");
329 break;
330 case MERLIN:
331 printf("Merlin");
332 break;
333 }
334 printf(" with ");
335 switch (etctype) {
336 case ET4000:
337 printf("Tseng ET4000");
338 break;
339 case ETW32:
340 printf("Tseng ETW32");
341 break;
342 }
343 printf(" and ");
344 switch (etdtype) {
345 case SIERRA11483:
346 printf("Sierra SC11483 DAC");
347 break;
348 case SIERRA15025:
349 printf("Sierra SC15025 DAC");
350 break;
351 case MUSICDAC:
352 printf("MUSIC DAC");
353 break;
354 case MERLINDAC:
355 printf("BrookTree DAC");
356 break;
357 }
358 printf(" being used\n");
359 } else {
360 if (!attachflag)
361 printf("grfet unattached!!\n");
362 }
363 }
364
365
366 int
367 grfetprint(auxp, pnp)
368 void *auxp;
369 char *pnp;
370 {
371 if (pnp)
372 printf("ite at %s: ", pnp);
373 return (UNCONF);
374 }
375
376
377 void
378 et_boardinit(gp)
379 struct grf_softc *gp;
380 {
381 unsigned char *ba = gp->g_regkva;
382 int x;
383
384 /* wakeup board and flip passthru OFF */
385
386 RegWakeup(ba);
387 RegOnpass(ba);
388
389 if (ettype == MERLIN) {
390 /* Merlin needs some special initialisations */
391 vgaw(ba, MERLIN_SWITCH_REG, 0);
392 delay(20000);
393 vgaw(ba, MERLIN_SWITCH_REG, 8);
394 delay(20000);
395 vgaw(ba, MERLIN_SWITCH_REG, 0);
396 delay(20000);
397 vgaw(ba, MERLIN_VDAC_DATA, 1);
398
399 vgaw(ba, MERLIN_VDAC_INDEX, 0x00);
400 vgaw(ba, MERLIN_VDAC_SPRITE, 0xff);
401 vgaw(ba, MERLIN_VDAC_INDEX, 0x01);
402 vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f);
403 vgaw(ba, MERLIN_VDAC_INDEX, 0x02);
404 vgaw(ba, MERLIN_VDAC_SPRITE, 0x42);
405 vgaw(ba, MERLIN_VDAC_INDEX, 0x03);
406 vgaw(ba, MERLIN_VDAC_SPRITE, 0x00);
407
408 vgaw(ba, MERLIN_VDAC_DATA, 0);
409 }
410
411
412 /* setup initial unchanging parameters */
413
414 vgaw(ba, GREG_HERCULESCOMPAT + ((ettype == DOMINO) ? 0x0fff : 0), 0x03);
415 vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
416 vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
417
418 if (ettype == DOMINO)
419 {
420 vgaw(ba, CRT_ADDRESS, CRT_ID_VIDEO_CONFIG1);
421 vgaw(ba, CRT_ADDRESS_W + 0x0fff,
422 0xc0 | vgar(ba, CRT_ADDRESS_R + 0x0fff));
423 }
424
425 WSeq(ba, SEQ_ID_RESET, 0x03);
426 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
427 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
428 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
429 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
430 /* WSeq(ba, SEQ_ID_TS_STATE_CONTROL, 0x00); */
431 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
432
433 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
434 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
435 WCrt(ba, CRT_ID_CURSOR_END, 0x08);
436 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
437 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
438 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
439 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
440
441 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
442 WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
443 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
444 /* ET4000 special */
445 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
446 WCrt(ba, CTR_ID_EXT_START, 0x00);
447 WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
448 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
449 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); /* assume ZorroII first */
450
451 if (iszthreepa(ba)) {
452 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) |
453 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24 )
454 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* ZorroIII */
455 }
456
457 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
458
459 WGfx(ba, GCT_ID_SET_RESET, 0x00);
460 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
461 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
462 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
463 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
464 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
465 WGfx(ba, GCT_ID_MISC, 0x01);
466 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
467 WGfx(ba, GCT_ID_BITMASK, 0xff);
468
469 vgaw(ba, GREG_SEGMENTSELECT, 0x00);
470
471 for (x = 0; x < 0x10; x++)
472 WAttr(ba, x, x);
473 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
474 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
475 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
476 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
477 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
478 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
479
480 vgaw(ba, VDAC_MASK, 0xff);
481 delay(200000);
482 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
483
484 /* colors initially set to greyscale */
485
486 switch(ettype) {
487 case MERLIN:
488 vgaw(ba, MERLIN_VDAC_INDEX, 0);
489 for (x = 255; x >= 0; x--) {
490 vgaw(ba, MERLIN_VDAC_COLORS, x);
491 vgaw(ba, MERLIN_VDAC_COLORS, x);
492 vgaw(ba, MERLIN_VDAC_COLORS, x);
493 }
494 break;
495 default:
496 vgaw(ba, VDAC_ADDRESS_W, 0);
497 for (x = 255; x >= 0; x--) {
498 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
499 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
500 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
501 }
502 break;
503 }
504 /* set sprite bitmap pointers */
505 /* should work like that */
506 et_cursprite.image = et_imageptr;
507 et_cursprite.mask = et_maskptr;
508 et_cursprite.cmap.red = et_sprred;
509 et_cursprite.cmap.green = et_sprgreen;
510 et_cursprite.cmap.blue = et_sprblue;
511
512 /* card spezific initialisations */
513 switch(ettype) {
514 case OMNIBUS:
515 etctype = et_getControllerType(gp);
516 etdtype = et_getDACType(gp);
517 break;
518 case MERLIN:
519 etctype = ETW32;
520 etdtype = MERLINDAC;
521 break;
522 case DOMINO:
523 etctype = ET4000;
524 etdtype = SIERRA11483;
525 break;
526 }
527 }
528
529
530 int
531 et_getvmode(gp, vm)
532 struct grf_softc *gp;
533 struct grfvideo_mode *vm;
534 {
535 struct grfvideo_mode *gv;
536
537 #ifdef TSENGCONSOLE
538 /* Handle grabbing console mode */
539 if (vm->mode_num == 255) {
540 bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
541 /* XXX so grfconfig can tell us the correct text dimensions. */
542 vm->depth = etconsole_mode.fy;
543 } else
544 #endif
545 {
546 if (vm->mode_num == 0)
547 vm->mode_num = (monitor_current - monitor_def) + 1;
548 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
549 return (EINVAL);
550 gv = monitor_def + (vm->mode_num - 1);
551 if (gv->mode_num == 0)
552 return (EINVAL);
553
554 bcopy(gv, vm, sizeof(struct grfvideo_mode));
555 }
556
557 /* adjust internal values to pixel values */
558
559 vm->hblank_start *= 8;
560 vm->hblank_stop *= 8;
561 vm->hsync_start *= 8;
562 vm->hsync_stop *= 8;
563 vm->htotal *= 8;
564
565 return (0);
566 }
567
568
569 int
570 et_setvmode(gp, mode)
571 struct grf_softc *gp;
572 unsigned mode;
573 {
574 if (!mode || (mode > monitor_def_max) ||
575 monitor_def[mode - 1].mode_num == 0)
576 return (EINVAL);
577
578 monitor_current = monitor_def + (mode - 1);
579
580 return (0);
581 }
582
583
584 #ifndef TSENGCONSOLE
585 void
586 et_off(gp)
587 struct grf_softc *gp;
588 {
589 char *ba = gp->g_regkva;
590
591 RegOnpass(ba);
592 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
593 }
594 #endif
595
596
597 int
598 et_blank(gp, on)
599 struct grf_softc *gp;
600 int *on;
601 {
602 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? 0x01 : 0x21);
603
604 return(0);
605 }
606
607
608 /*
609 * Change the mode of the display.
610 * Return a UNIX error number or 0 for success.
611 */
612 int
613 et_mode(gp, cmd, arg, a2, a3)
614 register struct grf_softc *gp;
615 u_long cmd;
616 void *arg;
617 u_long a2;
618 int a3;
619 {
620 int error;
621
622 switch (cmd) {
623 case GM_GRFON:
624 error = et_load_mon(gp,
625 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
626 return (error);
627
628 case GM_GRFOFF:
629 #ifndef TSENGCONSOLE
630 et_off(gp);
631 #else
632 et_load_mon(gp, &etconsole_mode);
633 #endif
634 return (0);
635
636 case GM_GRFCONFIG:
637 return (0);
638
639 case GM_GRFGETVMODE:
640 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
641
642 case GM_GRFSETVMODE:
643 error = et_setvmode(gp, *(unsigned *) arg);
644 if (!error && (gp->g_flags & GF_GRFON))
645 et_load_mon(gp,
646 (struct grfettext_mode *) monitor_current);
647 return (error);
648
649 case GM_GRFGETNUMVM:
650 *(int *) arg = monitor_def_max;
651 return (0);
652
653 case GM_GRFIOCTL:
654 return (et_ioctl(gp, a2, arg));
655
656 default:
657 break;
658 }
659
660 return (EINVAL);
661 }
662
663
664 int
665 et_ioctl(gp, cmd, data)
666 register struct grf_softc *gp;
667 u_long cmd;
668 void *data;
669 {
670 switch (cmd) {
671 case GRFIOCGSPRITEPOS:
672 return (et_getmousepos(gp, (struct grf_position *) data));
673
674 case GRFIOCSSPRITEPOS:
675 return (et_setmousepos(gp, (struct grf_position *) data));
676
677 case GRFIOCSSPRITEINF:
678 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
679
680 case GRFIOCGSPRITEINF:
681 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
682
683 case GRFIOCGSPRITEMAX:
684 return (et_getspritemax(gp, (struct grf_position *) data));
685
686 case GRFIOCGETCMAP:
687 return (et_getcmap(gp, (struct grf_colormap *) data));
688
689 case GRFIOCPUTCMAP:
690 return (et_putcmap(gp, (struct grf_colormap *) data));
691
692 case GRFIOCBITBLT:
693 break;
694
695 case GRFTOGGLE:
696 return (et_toggle(gp, 0));
697
698 case GRFIOCSETMON:
699 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
700
701 case GRFIOCBLANK:
702 return (et_blank(gp, (int *)data));
703 }
704 return (EINVAL);
705 }
706
707
708 int
709 et_getmousepos(gp, data)
710 struct grf_softc *gp;
711 struct grf_position *data;
712 {
713 data->x = et_cursprite.pos.x;
714 data->y = et_cursprite.pos.y;
715
716 return (0);
717 }
718
719
720 void
721 et_writesprpos(ba, x, y)
722 volatile char *ba;
723 short x;
724 short y;
725 {
726 }
727
728
729 int
730 et_setmousepos(gp, data)
731 struct grf_softc *gp;
732 struct grf_position *data;
733 {
734 volatile char *ba = gp->g_regkva;
735 short rx, ry, prx, pry;
736
737 /* no movement */
738 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
739 return (0);
740
741 /* current and previous real coordinates */
742 rx = data->x - et_cursprite.hot.x;
743 ry = data->y - et_cursprite.hot.y;
744 prx = et_cursprite.pos.x - et_cursprite.hot.x;
745 pry = et_cursprite.pos.y - et_cursprite.hot.y;
746
747 /* if we are/were on an edge, create (un)shifted bitmap --
748 * ripped out optimization (not extremely worthwhile,
749 * and kind of buggy anyhow).
750 */
751
752 /* do movement, save position */
753 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
754 et_cursprite.pos.x = data->x;
755 et_cursprite.pos.y = data->y;
756
757 return (0);
758 }
759
760
761 int
762 et_getspriteinfo(gp, data)
763 struct grf_softc *gp;
764 struct grf_spriteinfo *data;
765 {
766
767 return(EINVAL);
768 }
769
770
771 static int
772 et_setspriteinfo(gp, data)
773 struct grf_softc *gp;
774 struct grf_spriteinfo *data;
775 {
776
777 return(EINVAL);
778 }
779
780
781 static int
782 et_getspritemax(gp, data)
783 struct grf_softc *gp;
784 struct grf_position *data;
785 {
786
787 return(EINVAL);
788 }
789
790
791 int
792 et_setmonitor(gp, gv)
793 struct grf_softc *gp;
794 struct grfvideo_mode *gv;
795 {
796 struct grfvideo_mode *md;
797
798 if (!et_mondefok(gv))
799 return(EINVAL);
800
801 #ifdef TSENGCONSOLE
802 /* handle interactive setting of console mode */
803 if (gv->mode_num == 255) {
804 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
805 etconsole_mode.gv.hblank_start /= 8;
806 etconsole_mode.gv.hblank_stop /= 8;
807 etconsole_mode.gv.hsync_start /= 8;
808 etconsole_mode.gv.hsync_stop /= 8;
809 etconsole_mode.gv.htotal /= 8;
810 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
811 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
812 if (!(gp->g_flags & GF_GRFON))
813 et_load_mon(gp, &etconsole_mode);
814 ite_reinit(gp->g_itedev);
815 return (0);
816 }
817 #endif
818
819 md = monitor_def + (gv->mode_num - 1);
820 bcopy(gv, md, sizeof(struct grfvideo_mode));
821
822 /* adjust pixel oriented values to internal rep. */
823
824 md->hblank_start /= 8;
825 md->hblank_stop /= 8;
826 md->hsync_start /= 8;
827 md->hsync_stop /= 8;
828 md->htotal /= 8;
829
830 return (0);
831 }
832
833
834 int
835 et_getcmap(gfp, cmap)
836 struct grf_softc *gfp;
837 struct grf_colormap *cmap;
838 {
839 volatile unsigned char *ba;
840 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
841 short x;
842 int error;
843
844 if (cmap->count == 0 || cmap->index >= 256)
845 return 0;
846
847 if (cmap->index + cmap->count > 256)
848 cmap->count = 256 - cmap->index;
849
850 ba = gfp->g_regkva;
851 /* first read colors out of the chip, then copyout to userspace */
852 x = cmap->count - 1;
853
854 rp = red + cmap->index;
855 gp = green + cmap->index;
856 bp = blue + cmap->index;
857
858 switch(ettype) {
859 case MERLIN:
860 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
861 do {
862 *rp++ = vgar(ba, MERLIN_VDAC_COLORS);
863 *gp++ = vgar(ba, MERLIN_VDAC_COLORS);
864 *bp++ = vgar(ba, MERLIN_VDAC_COLORS);
865 } while (x-- > 0);
866 break;
867 default:
868 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index);
869 do {
870 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
871 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
872 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
873 } while (x-- > 0);
874 break;
875 }
876
877 error = copyout(red + cmap->index, cmap->red, cmap->count);
878 if (!error)
879 error = copyout(green + cmap->index, cmap->green, cmap->count);
880 if (!error)
881 error = copyout(blue + cmap->index, cmap->blue, cmap->count);
882
883 return (error);
884 }
885
886
887 int
888 et_putcmap(gfp, cmap)
889 struct grf_softc *gfp;
890 struct grf_colormap *cmap;
891 {
892 volatile unsigned char *ba;
893 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
894 short x;
895 int error;
896
897 if (cmap->count == 0 || cmap->index >= 256)
898 return (0);
899
900 if (cmap->index + cmap->count > 256)
901 cmap->count = 256 - cmap->index;
902
903 /* first copy the colors into kernelspace */
904 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
905 return (error);
906
907 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
908 return (error);
909
910 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
911 return (error);
912
913 ba = gfp->g_regkva;
914 x = cmap->count - 1;
915
916 rp = red + cmap->index;
917 gp = green + cmap->index;
918 bp = blue + cmap->index;
919
920 switch(ettype){
921 case MERLIN:
922 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
923 do {
924 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
925 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
926 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
927 } while (x-- > 0);
928 break;
929 default:
930 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
931 do {
932 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
933 *rp++ >> etcmap_shift);
934 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
935 *gp++ >> etcmap_shift);
936 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
937 *bp++ >> etcmap_shift);
938 } while (x-- > 0);
939 break;
940 }
941
942 return (0);
943 }
944
945
946 int
947 et_toggle(gp, wopp)
948 struct grf_softc *gp;
949 unsigned short wopp; /* don't need that one yet, ill */
950 {
951 volatile unsigned char *ba;
952
953 ba = gp->g_regkva;
954
955 if (pass_toggle) {
956 RegOffpass(ba);
957 } else {
958 RegOnpass(ba);
959 }
960 return (0);
961 }
962
963
964 #define ET_NUMCLOCKS 32
965
966 static u_char et_clocks[ET_NUMCLOCKS] = {
967 0, 1, 6, 2, 3, 7, 4, 5,
968 0, 1, 6, 2, 3, 7, 4, 5,
969 0, 1, 6, 2, 3, 7, 4, 5,
970 0, 1, 6, 2, 3, 7, 4, 5
971 };
972
973 static u_char et_clockdividers[ET_NUMCLOCKS] = {
974 3, 3, 3, 3, 3, 3, 3, 3,
975 2, 2, 2, 2, 2, 2, 2, 2,
976 1, 1, 1, 1, 1, 1, 1, 1,
977 0, 0, 0, 0, 0, 0, 0, 0
978 };
979
980 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
981 6293750, 7080500, 7875000, 8125000,
982 9000000, 9375000, 10000000, 11225000,
983 12587500, 14161000, 15750000, 16250000,
984 18000000, 18750000, 20000000, 22450000,
985 25175000, 28322000, 31500000, 32500000,
986 36000000, 37500000, 40000000, 44900000,
987 50350000, 56644000, 63000000, 65000000,
988 72000000, 75000000, 80000000, 89800000
989 };
990
991
992 static void
993 et_CompFQ(fq, num, denom)
994 u_int fq;
995 u_char *num;
996 u_char *denom;
997 {
998 int i;
999
1000 for (i=0; i < ET_NUMCLOCKS;) {
1001 if (fq <= et_clockfreqs[i++]) {
1002 break;
1003 }
1004 }
1005
1006 *num = et_clocks[--i];
1007 *denom = et_clockdividers[i];
1008
1009 return;
1010 }
1011
1012
1013 int
1014 et_mondefok(gv)
1015 struct grfvideo_mode *gv;
1016 {
1017
1018 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1019 if (gv->mode_num != 255 || gv->depth != 4)
1020 return(0);
1021
1022 switch (gv->depth) {
1023 case 4:
1024 if (gv->mode_num != 255)
1025 return(0);
1026 case 1:
1027 case 8:
1028 case 15:
1029 case 16:
1030 case 24:
1031 break;
1032 default:
1033 return (0);
1034 }
1035 return (1);
1036 }
1037
1038
1039 int
1040 et_load_mon(gp, md)
1041 struct grf_softc *gp;
1042 struct grfettext_mode *md;
1043 {
1044 struct grfvideo_mode *gv;
1045 struct grfinfo *gi;
1046 volatile unsigned char *ba;
1047 unsigned char num0, denom0;
1048 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1049 VSE, VT;
1050 char LACE, DBLSCAN, TEXT;
1051 unsigned char seq;
1052 int uplim, lowlim;
1053
1054 /* identity */
1055 gv = &md->gv;
1056 TEXT = (gv->depth == 4);
1057
1058 if (!et_mondefok(gv)) {
1059 printf("mondef not ok\n");
1060 return (0);
1061 }
1062 ba = gp->g_regkva;
1063
1064 /* provide all needed information in grf device-independant locations */
1065 gp->g_data = (caddr_t) gv;
1066 gi = &gp->g_display;
1067 gi->gd_regaddr = (caddr_t) ztwopa(ba);
1068 gi->gd_regsize = 64 * 1024;
1069 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
1070 gi->gd_fbsize = et_fbsize;
1071 gi->gd_colors = 1 << gv->depth;
1072 gi->gd_planes = gv->depth;
1073 gi->gd_fbwidth = gv->disp_width;
1074 gi->gd_fbheight = gv->disp_height;
1075 gi->gd_fbx = 0;
1076 gi->gd_fby = 0;
1077 if (TEXT) {
1078 gi->gd_dwidth = md->fx * md->cols;
1079 gi->gd_dheight = md->fy * md->rows;
1080 } else {
1081 gi->gd_dwidth = gv->disp_width;
1082 gi->gd_dheight = gv->disp_height;
1083 }
1084 gi->gd_dx = 0;
1085 gi->gd_dy = 0;
1086
1087 /* get display mode parameters */
1088
1089 HBS = gv->hblank_start;
1090 HBE = gv->hblank_stop;
1091 HSS = gv->hsync_start;
1092 HSE = gv->hsync_stop;
1093 HT = gv->htotal;
1094 VBS = gv->vblank_start;
1095 VSS = gv->vsync_start;
1096 VSE = gv->vsync_stop;
1097 VBE = gv->vblank_stop;
1098 VT = gv->vtotal;
1099
1100 if (TEXT)
1101 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1102 else
1103 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1104 VDE = gv->disp_height - 1;
1105
1106 /* figure out whether lace or dblscan is needed */
1107
1108 uplim = gv->disp_height + (gv->disp_height / 4);
1109 lowlim = gv->disp_height - (gv->disp_height / 4);
1110 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1111 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1112
1113 /* adjustments */
1114
1115 if (LACE)
1116 VDE /= 2;
1117
1118 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1119
1120 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1121 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1122 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1123
1124 /* Set clock */
1125
1126 et_CompFQ( gv->pixel_clock, &num0, &denom0);
1127
1128 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
1129 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1130 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
1131 switch(denom0) {
1132 case 0:
1133 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1134 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1135 break;
1136 case 1:
1137 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1138 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1139 break;
1140 case 2:
1141 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1142 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1143 break;
1144 case 3:
1145 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1146 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1147 break;
1148 }
1149 /* load display parameters into board */
1150
1151 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1152 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1153 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1154 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1155 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1156 WCrt(ba, CRT_ID_END_HOR_RETR,
1157 (HSE & 0x1f) |
1158 ((HBE & 0x20) ? 0x80 : 0x00));
1159 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1160 WCrt(ba, CRT_ID_OVERFLOW,
1161 0x10 |
1162 ((VT & 0x100) ? 0x01 : 0x00) |
1163 ((VDE & 0x100) ? 0x02 : 0x00) |
1164 ((VSS & 0x100) ? 0x04 : 0x00) |
1165 ((VBS & 0x100) ? 0x08 : 0x00) |
1166 ((VT & 0x200) ? 0x20 : 0x00) |
1167 ((VDE & 0x200) ? 0x40 : 0x00) |
1168 ((VSS & 0x200) ? 0x80 : 0x00));
1169
1170 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1171 0x40 | /* TEXT ? 0x00 ??? */
1172 (DBLSCAN ? 0x80 : 0x00) |
1173 ((VBS & 0x200) ? 0x20 : 0x00) |
1174 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1175
1176 WCrt(ba, CRT_ID_MODE_CONTROL,
1177 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1178
1179 /* text cursor */
1180
1181 if (TEXT) {
1182 #if ET_ULCURSOR
1183 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1184 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1185 #else
1186 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1187 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1188 #endif
1189 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1190 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1191 }
1192
1193 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1194 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1195
1196 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1197 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1198
1199 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1200 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1201 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1202 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1203 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1204
1205 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1206
1207 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1208 ((VBS & 0x400) ? 0x01 : 0x00) |
1209 ((VT & 0x400) ? 0x02 : 0x00) |
1210 ((VDE & 0x400) ? 0x04 : 0x00) |
1211 ((VSS & 0x400) ? 0x08 : 0x00) |
1212 0x10 |
1213 (LACE ? 0x80 : 0x00));
1214
1215 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1216 ((HT & 0x100) ? 0x01 : 0x00) |
1217 ((HBS & 0x100) ? 0x04 : 0x00) |
1218 ((HSS & 0x100) ? 0x10 : 0x00)
1219 );
1220
1221 /* depth dependent stuff */
1222
1223 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1224 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1225 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1226
1227 vgaw(ba, VDAC_MASK, 0xff);
1228 vgar(ba, VDAC_MASK);
1229 vgar(ba, VDAC_MASK);
1230 vgar(ba, VDAC_MASK);
1231 vgar(ba, VDAC_MASK);
1232 switch (gv->depth) {
1233 case 1:
1234 case 4: /* text */
1235 switch(etdtype) {
1236 case SIERRA11483:
1237 case SIERRA15025:
1238 case MUSICDAC:
1239 vgaw(ba, VDAC_MASK, 0);
1240 break;
1241 case MERLINDAC:
1242 setMerlinDACmode(ba, 0);
1243 break;
1244 }
1245 HDE = gv->disp_width / 16;
1246 break;
1247 case 8:
1248 switch(etdtype) {
1249 case SIERRA11483:
1250 case SIERRA15025:
1251 case MUSICDAC:
1252 vgaw(ba, VDAC_MASK, 0);
1253 break;
1254 case MERLINDAC:
1255 setMerlinDACmode(ba, 0);
1256 break;
1257 }
1258 HDE = gv->disp_width / 8;
1259 break;
1260 case 15:
1261 switch(etdtype) {
1262 case SIERRA11483:
1263 case SIERRA15025:
1264 case MUSICDAC:
1265 vgaw(ba, VDAC_MASK, 0xa0);
1266 break;
1267 case MERLINDAC:
1268 setMerlinDACmode(ba, 0xa0);
1269 break;
1270 }
1271 HDE = gv->disp_width / 4;
1272 break;
1273 case 16:
1274 switch(etdtype) {
1275 case SIERRA11483:
1276 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1277 break;
1278 case SIERRA15025:
1279 vgaw(ba, VDAC_MASK, 0xe0);
1280 break;
1281 case MUSICDAC:
1282 vgaw(ba, VDAC_MASK, 0xc0);
1283 break;
1284 case MERLINDAC:
1285 setMerlinDACmode(ba, 0xe0);
1286 break;
1287 }
1288 HDE = gv->disp_width / 4;
1289 break;
1290 case 24:
1291 switch(etdtype) {
1292 case SIERRA11483:
1293 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1294 break;
1295 case SIERRA15025:
1296 vgaw(ba, VDAC_MASK, 0xe1);
1297 break;
1298 case MUSICDAC:
1299 vgaw(ba, VDAC_MASK, 0xe0);
1300 break;
1301 case MERLINDAC:
1302 setMerlinDACmode(ba, 0xf0);
1303 break;
1304 }
1305 HDE = (gv->disp_width / 8) * 3;
1306 break;
1307 case 32:
1308 switch(etdtype) {
1309 case SIERRA11483:
1310 case MUSICDAC:
1311 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1312 break;
1313 case SIERRA15025:
1314 vgaw(ba, VDAC_MASK, 0x61);
1315 break;
1316 case MERLINDAC:
1317 setMerlinDACmode(ba, 0xb0);
1318 break;
1319 }
1320 HDE = gv->disp_width / 2;
1321 break;
1322 }
1323 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1324 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1325 (gv->depth == 1) ? 0x01 : 0x0f);
1326
1327 WCrt(ba, CRT_ID_OFFSET, HDE);
1328
1329 /* text initialization */
1330 if (TEXT) {
1331 et_inittextmode(gp);
1332 }
1333
1334 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1335
1336 /* Pass-through */
1337 RegOffpass(ba);
1338
1339 return (1);
1340 }
1341
1342
1343 void
1344 et_inittextmode(gp)
1345 struct grf_softc *gp;
1346 {
1347 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1348 volatile unsigned char *ba = gp->g_regkva;
1349 unsigned char *fb = gp->g_fbkva;
1350 unsigned char *c, *f, y;
1351 unsigned short z;
1352
1353
1354 /*
1355 * load text font into beginning of display memory. Each character
1356 * cell is 32 bytes long (enough for 4 planes)
1357 */
1358
1359 SetTextPlane(ba, 0x02);
1360 et_memset(fb, 0, 256 * 32);
1361 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1362 f = tm->fdata;
1363 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1364 for (y = 0; y < tm->fy; y++)
1365 *c++ = *f++;
1366
1367 /* clear out text/attr planes (three screens worth) */
1368
1369 SetTextPlane(ba, 0x01);
1370 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1371 SetTextPlane(ba, 0x00);
1372 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1373
1374 /* print out a little init msg */
1375
1376 c = (unsigned char *) (fb) + (tm->cols - 16);
1377 strcpy(c, "TSENG");
1378 c[6] = 0x20;
1379
1380 /* set colors (B&W) */
1381
1382 switch(ettype) {
1383 case MERLIN:
1384 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1385 for (z = 0; z < 256; z++) {
1386 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1387
1388 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1389 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1390 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1391 }
1392 break;
1393 default:
1394 vgaw(ba, VDAC_ADDRESS_W, 0);
1395 for (z = 0; z < 256; z++) {
1396 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1397
1398 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1399 etconscolors[y][0] >> etcmap_shift);
1400 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1401 etconscolors[y][1] >> etcmap_shift);
1402 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1403 etconscolors[y][2] >> etcmap_shift);
1404 }
1405 break;
1406 }
1407 }
1408
1409
1410 void
1411 et_memset(d, c, l)
1412 unsigned char *d;
1413 unsigned char c;
1414 int l;
1415 {
1416 for (; l > 0; l--)
1417 *d++ = c;
1418 }
1419
1420
1421 static int
1422 et_getControllerType(gp)
1423 struct grf_softc * gp;
1424 {
1425 unsigned char *ba = gp->g_regkva; /* register base */
1426 unsigned char *mem = gp->g_fbkva; /* memory base */
1427 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1428
1429 *mem = 0;
1430
1431 /* make ACL visible */
1432 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1433 WIma(ba, IMA_PORTCONTROL, 0x01);
1434
1435 *((unsigned long *)mmu) = 0;
1436 *(mem + 0x13) = 0x38;
1437
1438 *mmu = 0xff;
1439
1440 /* hide ACL */
1441 WIma(ba, IMA_PORTCONTROL, 0x00);
1442 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1443
1444 return((*mem == 0xff) ? ETW32 : ET4000);
1445 }
1446
1447
1448 static int
1449 et_getDACType(gp)
1450 struct grf_softc * gp;
1451 {
1452 unsigned char *ba = gp->g_regkva;
1453 union {
1454 int tt;
1455 char cc[4];
1456 } check;
1457
1458 /* check for Sierra SC 15025 */
1459
1460 /* We MUST do 4 HW reads to switch into command mode */
1461 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1462 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1463
1464 vgaw(ba, VDAC_XINDEX, 9);
1465 check.cc[0] = vgar(ba, VDAC_XDATA);
1466 vgaw(ba, VDAC_XINDEX, 10);
1467 check.cc[1] = vgar(ba, VDAC_XDATA);
1468 vgaw(ba, VDAC_XINDEX, 11);
1469 check.cc[2] = vgar(ba, VDAC_XDATA);
1470 vgaw(ba, VDAC_XINDEX, 12);
1471 check.cc[3] = vgar(ba, VDAC_XDATA);
1472
1473 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1474 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1475
1476 if (check.tt == 0x533ab141) {
1477 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1478 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1479
1480 /* switch to 8 bits per color */
1481 vgaw(ba, VDAC_XINDEX, 8);
1482 vgaw(ba, VDAC_XDATA, 1);
1483 /* do not shift color values */
1484 etcmap_shift = 0;
1485
1486 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1487 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1488
1489 vgaw(ba, VDAC_MASK, 0xff);
1490 return (SIERRA15025);
1491 }
1492
1493 /* check for MUSIC DAC */
1494
1495 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1496 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1497
1498 vgaw(ba, VDAC_XINDEX, 0x01);
1499 if (vgar(ba, VDAC_XDATA) == 0x01) {
1500 /* shift color values by 2 */
1501 etcmap_shift = 2;
1502
1503 vgaw(ba, VDAC_MASK, 0xff);
1504 return (MUSICDAC);
1505 }
1506
1507 /*
1508 * nothing else found, so let us pretend it is a stupid
1509 * Sierra SC 11483
1510 */
1511
1512 /* shift color values by 2 */
1513 etcmap_shift = 2;
1514
1515 vgaw(ba, VDAC_MASK, 0xff);
1516 return (SIERRA11483);
1517 }
1518
1519 #endif /* NGRFET */
1520