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