grf_et.c revision 1.7 1 /* $NetBSD: grf_et.c,v 1.7 1996/10/13 03:07:04 christos 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 *, const 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 const 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 > 0 ? 0x01 : 0x21);
603 return(0);
604 }
605
606
607 /*
608 * Change the mode of the display.
609 * Return a UNIX error number or 0 for success.
610 */
611 int
612 et_mode(gp, cmd, arg, a2, a3)
613 register struct grf_softc *gp;
614 u_long cmd;
615 void *arg;
616 u_long a2;
617 int a3;
618 {
619 int error;
620
621 switch (cmd) {
622 case GM_GRFON:
623 error = et_load_mon(gp,
624 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
625 return (error);
626
627 case GM_GRFOFF:
628 #ifndef TSENGCONSOLE
629 et_off(gp);
630 #else
631 et_load_mon(gp, &etconsole_mode);
632 #endif
633 return (0);
634
635 case GM_GRFCONFIG:
636 return (0);
637
638 case GM_GRFGETVMODE:
639 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
640
641 case GM_GRFSETVMODE:
642 error = et_setvmode(gp, *(unsigned *) arg);
643 if (!error && (gp->g_flags & GF_GRFON))
644 et_load_mon(gp,
645 (struct grfettext_mode *) monitor_current);
646 return (error);
647
648 case GM_GRFGETNUMVM:
649 *(int *) arg = monitor_def_max;
650 return (0);
651
652 case GM_GRFIOCTL:
653 return (et_ioctl(gp, a2, arg));
654
655 default:
656 break;
657 }
658
659 return (EINVAL);
660 }
661
662
663 int
664 et_ioctl(gp, cmd, data)
665 register struct grf_softc *gp;
666 u_long cmd;
667 void *data;
668 {
669 switch (cmd) {
670 case GRFIOCGSPRITEPOS:
671 return (et_getmousepos(gp, (struct grf_position *) data));
672
673 case GRFIOCSSPRITEPOS:
674 return (et_setmousepos(gp, (struct grf_position *) data));
675
676 case GRFIOCSSPRITEINF:
677 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
678
679 case GRFIOCGSPRITEINF:
680 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
681
682 case GRFIOCGSPRITEMAX:
683 return (et_getspritemax(gp, (struct grf_position *) data));
684
685 case GRFIOCGETCMAP:
686 return (et_getcmap(gp, (struct grf_colormap *) data));
687
688 case GRFIOCPUTCMAP:
689 return (et_putcmap(gp, (struct grf_colormap *) data));
690
691 case GRFIOCBITBLT:
692 break;
693
694 case GRFTOGGLE:
695 return (et_toggle(gp, 0));
696
697 case GRFIOCSETMON:
698 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
699
700 case GRFIOCBLANK:
701 return (et_blank(gp, (int *)data));
702 }
703 return (EINVAL);
704 }
705
706
707 int
708 et_getmousepos(gp, data)
709 struct grf_softc *gp;
710 struct grf_position *data;
711 {
712 data->x = et_cursprite.pos.x;
713 data->y = et_cursprite.pos.y;
714
715 return (0);
716 }
717
718
719 void
720 et_writesprpos(ba, x, y)
721 volatile char *ba;
722 short x;
723 short y;
724 {
725 }
726
727
728 int
729 et_setmousepos(gp, data)
730 struct grf_softc *gp;
731 struct grf_position *data;
732 {
733 volatile char *ba = gp->g_regkva;
734 short rx, ry, prx, pry;
735
736 /* no movement */
737 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
738 return (0);
739
740 /* current and previous real coordinates */
741 rx = data->x - et_cursprite.hot.x;
742 ry = data->y - et_cursprite.hot.y;
743 prx = et_cursprite.pos.x - et_cursprite.hot.x;
744 pry = et_cursprite.pos.y - et_cursprite.hot.y;
745
746 /* if we are/were on an edge, create (un)shifted bitmap --
747 * ripped out optimization (not extremely worthwhile,
748 * and kind of buggy anyhow).
749 */
750
751 /* do movement, save position */
752 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
753 et_cursprite.pos.x = data->x;
754 et_cursprite.pos.y = data->y;
755
756 return (0);
757 }
758
759
760 int
761 et_getspriteinfo(gp, data)
762 struct grf_softc *gp;
763 struct grf_spriteinfo *data;
764 {
765
766 return(EINVAL);
767 }
768
769
770 static int
771 et_setspriteinfo(gp, data)
772 struct grf_softc *gp;
773 struct grf_spriteinfo *data;
774 {
775
776 return(EINVAL);
777 }
778
779
780 static int
781 et_getspritemax(gp, data)
782 struct grf_softc *gp;
783 struct grf_position *data;
784 {
785
786 return(EINVAL);
787 }
788
789
790 int
791 et_setmonitor(gp, gv)
792 struct grf_softc *gp;
793 struct grfvideo_mode *gv;
794 {
795 struct grfvideo_mode *md;
796
797 if (!et_mondefok(gv))
798 return(EINVAL);
799
800 #ifdef TSENGCONSOLE
801 /* handle interactive setting of console mode */
802 if (gv->mode_num == 255) {
803 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
804 etconsole_mode.gv.hblank_start /= 8;
805 etconsole_mode.gv.hblank_stop /= 8;
806 etconsole_mode.gv.hsync_start /= 8;
807 etconsole_mode.gv.hsync_stop /= 8;
808 etconsole_mode.gv.htotal /= 8;
809 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
810 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
811 if (!(gp->g_flags & GF_GRFON))
812 et_load_mon(gp, &etconsole_mode);
813 ite_reinit(gp->g_itedev);
814 return (0);
815 }
816 #endif
817
818 md = monitor_def + (gv->mode_num - 1);
819 bcopy(gv, md, sizeof(struct grfvideo_mode));
820
821 /* adjust pixel oriented values to internal rep. */
822
823 md->hblank_start /= 8;
824 md->hblank_stop /= 8;
825 md->hsync_start /= 8;
826 md->hsync_stop /= 8;
827 md->htotal /= 8;
828
829 return (0);
830 }
831
832
833 int
834 et_getcmap(gfp, cmap)
835 struct grf_softc *gfp;
836 struct grf_colormap *cmap;
837 {
838 volatile unsigned char *ba;
839 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
840 short x;
841 int error;
842
843 if (cmap->count == 0 || cmap->index >= 256)
844 return 0;
845
846 if (cmap->index + cmap->count > 256)
847 cmap->count = 256 - cmap->index;
848
849 ba = gfp->g_regkva;
850 /* first read colors out of the chip, then copyout to userspace */
851 x = cmap->count - 1;
852
853 rp = red + cmap->index;
854 gp = green + cmap->index;
855 bp = blue + cmap->index;
856
857 switch(ettype) {
858 case MERLIN:
859 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
860 do {
861 *rp++ = vgar(ba, MERLIN_VDAC_COLORS);
862 *gp++ = vgar(ba, MERLIN_VDAC_COLORS);
863 *bp++ = vgar(ba, MERLIN_VDAC_COLORS);
864 } while (x-- > 0);
865 break;
866 default:
867 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index);
868 do {
869 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
870 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
871 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
872 } while (x-- > 0);
873 break;
874 }
875
876 error = copyout(red + cmap->index, cmap->red, cmap->count);
877 if (!error)
878 error = copyout(green + cmap->index, cmap->green, cmap->count);
879 if (!error)
880 error = copyout(blue + cmap->index, cmap->blue, cmap->count);
881
882 return (error);
883 }
884
885
886 int
887 et_putcmap(gfp, cmap)
888 struct grf_softc *gfp;
889 struct grf_colormap *cmap;
890 {
891 volatile unsigned char *ba;
892 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
893 short x;
894 int error;
895
896 if (cmap->count == 0 || cmap->index >= 256)
897 return (0);
898
899 if (cmap->index + cmap->count > 256)
900 cmap->count = 256 - cmap->index;
901
902 /* first copy the colors into kernelspace */
903 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
904 return (error);
905
906 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
907 return (error);
908
909 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
910 return (error);
911
912 ba = gfp->g_regkva;
913 x = cmap->count - 1;
914
915 rp = red + cmap->index;
916 gp = green + cmap->index;
917 bp = blue + cmap->index;
918
919 switch(ettype){
920 case MERLIN:
921 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
922 do {
923 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
924 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
925 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
926 } while (x-- > 0);
927 break;
928 default:
929 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
930 do {
931 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
932 *rp++ >> etcmap_shift);
933 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
934 *gp++ >> etcmap_shift);
935 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
936 *bp++ >> etcmap_shift);
937 } while (x-- > 0);
938 break;
939 }
940
941 return (0);
942 }
943
944
945 int
946 et_toggle(gp, wopp)
947 struct grf_softc *gp;
948 unsigned short wopp; /* don't need that one yet, ill */
949 {
950 volatile unsigned char *ba;
951
952 ba = gp->g_regkva;
953
954 if (pass_toggle) {
955 RegOffpass(ba);
956 } else {
957 RegOnpass(ba);
958 }
959 return (0);
960 }
961
962
963 #define ET_NUMCLOCKS 32
964
965 static u_char et_clocks[ET_NUMCLOCKS] = {
966 0, 1, 6, 2, 3, 7, 4, 5,
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 };
971
972 static u_char et_clockdividers[ET_NUMCLOCKS] = {
973 3, 3, 3, 3, 3, 3, 3, 3,
974 2, 2, 2, 2, 2, 2, 2, 2,
975 1, 1, 1, 1, 1, 1, 1, 1,
976 0, 0, 0, 0, 0, 0, 0, 0
977 };
978
979 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
980 6293750, 7080500, 7875000, 8125000,
981 9000000, 9375000, 10000000, 11225000,
982 12587500, 14161000, 15750000, 16250000,
983 18000000, 18750000, 20000000, 22450000,
984 25175000, 28322000, 31500000, 32500000,
985 36000000, 37500000, 40000000, 44900000,
986 50350000, 56644000, 63000000, 65000000,
987 72000000, 75000000, 80000000, 89800000
988 };
989
990
991 static void
992 et_CompFQ(fq, num, denom)
993 u_int fq;
994 u_char *num;
995 u_char *denom;
996 {
997 int i;
998
999 for (i=0; i < ET_NUMCLOCKS;) {
1000 if (fq <= et_clockfreqs[i++]) {
1001 break;
1002 }
1003 }
1004
1005 *num = et_clocks[--i];
1006 *denom = et_clockdividers[i];
1007
1008 return;
1009 }
1010
1011
1012 int
1013 et_mondefok(gv)
1014 struct grfvideo_mode *gv;
1015 {
1016
1017 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1018 if (gv->mode_num != 255 || gv->depth != 4)
1019 return(0);
1020
1021 switch (gv->depth) {
1022 case 4:
1023 if (gv->mode_num != 255)
1024 return(0);
1025 case 1:
1026 case 8:
1027 case 15:
1028 case 16:
1029 case 24:
1030 break;
1031 default:
1032 return (0);
1033 }
1034 return (1);
1035 }
1036
1037
1038 int
1039 et_load_mon(gp, md)
1040 struct grf_softc *gp;
1041 struct grfettext_mode *md;
1042 {
1043 struct grfvideo_mode *gv;
1044 struct grfinfo *gi;
1045 volatile unsigned char *ba;
1046 unsigned char num0, denom0;
1047 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1048 VSE, VT;
1049 char LACE, DBLSCAN, TEXT;
1050 unsigned char seq;
1051 int uplim, lowlim;
1052
1053 /* identity */
1054 gv = &md->gv;
1055 TEXT = (gv->depth == 4);
1056
1057 if (!et_mondefok(gv)) {
1058 printf("mondef not ok\n");
1059 return (0);
1060 }
1061 ba = gp->g_regkva;
1062
1063 /* provide all needed information in grf device-independant locations */
1064 gp->g_data = (caddr_t) gv;
1065 gi = &gp->g_display;
1066 gi->gd_regaddr = (caddr_t) ztwopa(ba);
1067 gi->gd_regsize = 64 * 1024;
1068 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
1069 gi->gd_fbsize = et_fbsize;
1070 gi->gd_colors = 1 << gv->depth;
1071 gi->gd_planes = gv->depth;
1072 gi->gd_fbwidth = gv->disp_width;
1073 gi->gd_fbheight = gv->disp_height;
1074 gi->gd_fbx = 0;
1075 gi->gd_fby = 0;
1076 if (TEXT) {
1077 gi->gd_dwidth = md->fx * md->cols;
1078 gi->gd_dheight = md->fy * md->rows;
1079 } else {
1080 gi->gd_dwidth = gv->disp_width;
1081 gi->gd_dheight = gv->disp_height;
1082 }
1083 gi->gd_dx = 0;
1084 gi->gd_dy = 0;
1085
1086 /* get display mode parameters */
1087
1088 HBS = gv->hblank_start;
1089 HBE = gv->hblank_stop;
1090 HSS = gv->hsync_start;
1091 HSE = gv->hsync_stop;
1092 HT = gv->htotal;
1093 VBS = gv->vblank_start;
1094 VSS = gv->vsync_start;
1095 VSE = gv->vsync_stop;
1096 VBE = gv->vblank_stop;
1097 VT = gv->vtotal;
1098
1099 if (TEXT)
1100 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1101 else
1102 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1103 VDE = gv->disp_height - 1;
1104
1105 /* figure out whether lace or dblscan is needed */
1106
1107 uplim = gv->disp_height + (gv->disp_height / 4);
1108 lowlim = gv->disp_height - (gv->disp_height / 4);
1109 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1110 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1111
1112 /* adjustments */
1113
1114 if (LACE)
1115 VDE /= 2;
1116
1117 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1118
1119 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1120 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1121 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1122
1123 /* Set clock */
1124
1125 et_CompFQ( gv->pixel_clock, &num0, &denom0);
1126
1127 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
1128 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1129 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
1130 switch(denom0) {
1131 case 0:
1132 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1133 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1134 break;
1135 case 1:
1136 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1137 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1138 break;
1139 case 2:
1140 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1141 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1142 break;
1143 case 3:
1144 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1145 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1146 break;
1147 }
1148 /* load display parameters into board */
1149
1150 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1151 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1152 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1153 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1154 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1155 WCrt(ba, CRT_ID_END_HOR_RETR,
1156 (HSE & 0x1f) |
1157 ((HBE & 0x20) ? 0x80 : 0x00));
1158 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1159 WCrt(ba, CRT_ID_OVERFLOW,
1160 0x10 |
1161 ((VT & 0x100) ? 0x01 : 0x00) |
1162 ((VDE & 0x100) ? 0x02 : 0x00) |
1163 ((VSS & 0x100) ? 0x04 : 0x00) |
1164 ((VBS & 0x100) ? 0x08 : 0x00) |
1165 ((VT & 0x200) ? 0x20 : 0x00) |
1166 ((VDE & 0x200) ? 0x40 : 0x00) |
1167 ((VSS & 0x200) ? 0x80 : 0x00));
1168
1169 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1170 0x40 | /* TEXT ? 0x00 ??? */
1171 (DBLSCAN ? 0x80 : 0x00) |
1172 ((VBS & 0x200) ? 0x20 : 0x00) |
1173 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1174
1175 WCrt(ba, CRT_ID_MODE_CONTROL,
1176 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1177
1178 /* text cursor */
1179
1180 if (TEXT) {
1181 #if ET_ULCURSOR
1182 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1183 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1184 #else
1185 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1186 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1187 #endif
1188 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1189 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1190 }
1191
1192 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1193 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1194
1195 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1196 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1197
1198 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1199 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1200 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1201 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1202 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1203
1204 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1205
1206 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1207 ((VBS & 0x400) ? 0x01 : 0x00) |
1208 ((VT & 0x400) ? 0x02 : 0x00) |
1209 ((VDE & 0x400) ? 0x04 : 0x00) |
1210 ((VSS & 0x400) ? 0x08 : 0x00) |
1211 0x10 |
1212 (LACE ? 0x80 : 0x00));
1213
1214 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1215 ((HT & 0x100) ? 0x01 : 0x00) |
1216 ((HBS & 0x100) ? 0x04 : 0x00) |
1217 ((HSS & 0x100) ? 0x10 : 0x00)
1218 );
1219
1220 /* depth dependent stuff */
1221
1222 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1223 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1224 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1225
1226 vgaw(ba, VDAC_MASK, 0xff);
1227 vgar(ba, VDAC_MASK);
1228 vgar(ba, VDAC_MASK);
1229 vgar(ba, VDAC_MASK);
1230 vgar(ba, VDAC_MASK);
1231 switch (gv->depth) {
1232 case 1:
1233 case 4: /* text */
1234 switch(etdtype) {
1235 case SIERRA11483:
1236 case SIERRA15025:
1237 case MUSICDAC:
1238 vgaw(ba, VDAC_MASK, 0);
1239 break;
1240 case MERLINDAC:
1241 setMerlinDACmode(ba, 0);
1242 break;
1243 }
1244 HDE = gv->disp_width / 16;
1245 break;
1246 case 8:
1247 switch(etdtype) {
1248 case SIERRA11483:
1249 case SIERRA15025:
1250 case MUSICDAC:
1251 vgaw(ba, VDAC_MASK, 0);
1252 break;
1253 case MERLINDAC:
1254 setMerlinDACmode(ba, 0);
1255 break;
1256 }
1257 HDE = gv->disp_width / 8;
1258 break;
1259 case 15:
1260 switch(etdtype) {
1261 case SIERRA11483:
1262 case SIERRA15025:
1263 case MUSICDAC:
1264 vgaw(ba, VDAC_MASK, 0xa0);
1265 break;
1266 case MERLINDAC:
1267 setMerlinDACmode(ba, 0xa0);
1268 break;
1269 }
1270 HDE = gv->disp_width / 4;
1271 break;
1272 case 16:
1273 switch(etdtype) {
1274 case SIERRA11483:
1275 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1276 break;
1277 case SIERRA15025:
1278 vgaw(ba, VDAC_MASK, 0xe0);
1279 break;
1280 case MUSICDAC:
1281 vgaw(ba, VDAC_MASK, 0xc0);
1282 break;
1283 case MERLINDAC:
1284 setMerlinDACmode(ba, 0xe0);
1285 break;
1286 }
1287 HDE = gv->disp_width / 4;
1288 break;
1289 case 24:
1290 switch(etdtype) {
1291 case SIERRA11483:
1292 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1293 break;
1294 case SIERRA15025:
1295 vgaw(ba, VDAC_MASK, 0xe1);
1296 break;
1297 case MUSICDAC:
1298 vgaw(ba, VDAC_MASK, 0xe0);
1299 break;
1300 case MERLINDAC:
1301 setMerlinDACmode(ba, 0xf0);
1302 break;
1303 }
1304 HDE = (gv->disp_width / 8) * 3;
1305 break;
1306 case 32:
1307 switch(etdtype) {
1308 case SIERRA11483:
1309 case MUSICDAC:
1310 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1311 break;
1312 case SIERRA15025:
1313 vgaw(ba, VDAC_MASK, 0x61);
1314 break;
1315 case MERLINDAC:
1316 setMerlinDACmode(ba, 0xb0);
1317 break;
1318 }
1319 HDE = gv->disp_width / 2;
1320 break;
1321 }
1322 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1323 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1324 (gv->depth == 1) ? 0x01 : 0x0f);
1325
1326 WCrt(ba, CRT_ID_OFFSET, HDE);
1327
1328 /* text initialization */
1329 if (TEXT) {
1330 et_inittextmode(gp);
1331 }
1332
1333 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1334
1335 /* Pass-through */
1336 RegOffpass(ba);
1337
1338 return (1);
1339 }
1340
1341
1342 void
1343 et_inittextmode(gp)
1344 struct grf_softc *gp;
1345 {
1346 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1347 volatile unsigned char *ba = gp->g_regkva;
1348 unsigned char *fb = gp->g_fbkva;
1349 unsigned char *c, *f, y;
1350 unsigned short z;
1351
1352
1353 /*
1354 * load text font into beginning of display memory. Each character
1355 * cell is 32 bytes long (enough for 4 planes)
1356 */
1357
1358 SetTextPlane(ba, 0x02);
1359 et_memset(fb, 0, 256 * 32);
1360 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1361 f = tm->fdata;
1362 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1363 for (y = 0; y < tm->fy; y++)
1364 *c++ = *f++;
1365
1366 /* clear out text/attr planes (three screens worth) */
1367
1368 SetTextPlane(ba, 0x01);
1369 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1370 SetTextPlane(ba, 0x00);
1371 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1372
1373 /* print out a little init msg */
1374
1375 c = (unsigned char *) (fb) + (tm->cols - 16);
1376 strcpy(c, "TSENG");
1377 c[6] = 0x20;
1378
1379 /* set colors (B&W) */
1380
1381 switch(ettype) {
1382 case MERLIN:
1383 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1384 for (z = 0; z < 256; z++) {
1385 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1386
1387 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1388 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1389 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1390 }
1391 break;
1392 default:
1393 vgaw(ba, VDAC_ADDRESS_W, 0);
1394 for (z = 0; z < 256; z++) {
1395 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1396
1397 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1398 etconscolors[y][0] >> etcmap_shift);
1399 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1400 etconscolors[y][1] >> etcmap_shift);
1401 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1402 etconscolors[y][2] >> etcmap_shift);
1403 }
1404 break;
1405 }
1406 }
1407
1408
1409 void
1410 et_memset(d, c, l)
1411 unsigned char *d;
1412 unsigned char c;
1413 int l;
1414 {
1415 for (; l > 0; l--)
1416 *d++ = c;
1417 }
1418
1419
1420 static int
1421 et_getControllerType(gp)
1422 struct grf_softc * gp;
1423 {
1424 unsigned char *ba = gp->g_regkva; /* register base */
1425 unsigned char *mem = gp->g_fbkva; /* memory base */
1426 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1427
1428 *mem = 0;
1429
1430 /* make ACL visible */
1431 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1432 WIma(ba, IMA_PORTCONTROL, 0x01);
1433
1434 *((unsigned long *)mmu) = 0;
1435 *(mem + 0x13) = 0x38;
1436
1437 *mmu = 0xff;
1438
1439 /* hide ACL */
1440 WIma(ba, IMA_PORTCONTROL, 0x00);
1441 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1442
1443 return((*mem == 0xff) ? ETW32 : ET4000);
1444 }
1445
1446
1447 static int
1448 et_getDACType(gp)
1449 struct grf_softc * gp;
1450 {
1451 unsigned char *ba = gp->g_regkva;
1452 union {
1453 int tt;
1454 char cc[4];
1455 } check;
1456
1457 /* check for Sierra SC 15025 */
1458
1459 /* We MUST do 4 HW reads to switch into command mode */
1460 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1461 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1462
1463 vgaw(ba, VDAC_XINDEX, 9);
1464 check.cc[0] = vgar(ba, VDAC_XDATA);
1465 vgaw(ba, VDAC_XINDEX, 10);
1466 check.cc[1] = vgar(ba, VDAC_XDATA);
1467 vgaw(ba, VDAC_XINDEX, 11);
1468 check.cc[2] = vgar(ba, VDAC_XDATA);
1469 vgaw(ba, VDAC_XINDEX, 12);
1470 check.cc[3] = vgar(ba, VDAC_XDATA);
1471
1472 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1473 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1474
1475 if (check.tt == 0x533ab141) {
1476 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1477 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1478
1479 /* switch to 8 bits per color */
1480 vgaw(ba, VDAC_XINDEX, 8);
1481 vgaw(ba, VDAC_XDATA, 1);
1482 /* do not shift color values */
1483 etcmap_shift = 0;
1484
1485 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1486 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1487
1488 vgaw(ba, VDAC_MASK, 0xff);
1489 return (SIERRA15025);
1490 }
1491
1492 /* check for MUSIC DAC */
1493
1494 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1495 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1496
1497 vgaw(ba, VDAC_XINDEX, 0x01);
1498 if (vgar(ba, VDAC_XDATA) == 0x01) {
1499 /* shift color values by 2 */
1500 etcmap_shift = 2;
1501
1502 vgaw(ba, VDAC_MASK, 0xff);
1503 return (MUSICDAC);
1504 }
1505
1506 /*
1507 * nothing else found, so let us pretend it is a stupid
1508 * Sierra SC 11483
1509 */
1510
1511 /* shift color values by 2 */
1512 etcmap_shift = 2;
1513
1514 vgaw(ba, VDAC_MASK, 0xff);
1515 return (SIERRA11483);
1516 }
1517
1518 #endif /* NGRFET */
1519