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