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