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