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