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