grf_et.c revision 1.25 1 /* $NetBSD: grf_et.c,v 1.25 2007/08/20 19:23:50 is Exp $ */
2
3 /*
4 * Copyright (c) 1997 Klaus Burkert
5 * Copyright (c) 1996 Tobias Abt
6 * Copyright (c) 1995 Ezra Story
7 * Copyright (c) 1995 Kari Mettinen
8 * Copyright (c) 1994 Markus Wild
9 * Copyright (c) 1994 Lutz Vieweg
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by Lutz Vieweg.
23 * 4. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37 #include "opt_amigacons.h"
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: grf_et.c,v 1.25 2007/08/20 19:23:50 is 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(volatile 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 void *) et_regaddr;
299 gp->g_fbkva = (volatile void *) 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 volatile 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(__UNVOLATILE(gp->g_fbkva))) &&
542 et_fbsize == 0x400000)
543 et_fbsize = 0x200000;
544 etctype = ETW32;
545 etdtype = MERLINDAC;
546 break;
547 case DOMINO:
548 etctype = ET4000;
549 etdtype = et_getDACType(gp);
550 break;
551 }
552 }
553
554
555 int
556 et_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
557 {
558 struct grfvideo_mode *gv;
559
560 #ifdef TSENGCONSOLE
561 /* Handle grabbing console mode */
562 if (vm->mode_num == 255) {
563 bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
564 /* XXX so grfconfig can tell us the correct text dimensions. */
565 vm->depth = etconsole_mode.fy;
566 } else
567 #endif
568 {
569 if (vm->mode_num == 0)
570 vm->mode_num = (monitor_current - monitor_def) + 1;
571 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
572 return (EINVAL);
573 gv = monitor_def + (vm->mode_num - 1);
574 if (gv->mode_num == 0)
575 return (EINVAL);
576
577 bcopy(gv, vm, sizeof(struct grfvideo_mode));
578 }
579
580 /* adjust internal values to pixel values */
581
582 vm->hblank_start *= 8;
583 vm->hsync_start *= 8;
584 vm->hsync_stop *= 8;
585 vm->htotal *= 8;
586
587 return (0);
588 }
589
590
591 int
592 et_setvmode(struct grf_softc *gp, unsigned mode)
593 {
594 if (!mode || (mode > monitor_def_max) ||
595 monitor_def[mode - 1].mode_num == 0)
596 return (EINVAL);
597
598 monitor_current = monitor_def + (mode - 1);
599
600 return (0);
601 }
602
603
604 #ifndef TSENGCONSOLE
605 void
606 et_off(struct grf_softc *gp)
607 {
608 char *ba = gp->g_regkva;
609
610 RegOnpass(ba);
611 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
612 }
613 #endif
614
615
616 int
617 et_blank(struct grf_softc *gp, int *on)
618 {
619 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? 0x01 : 0x21);
620 return(0);
621 }
622
623
624 /*
625 * Change the mode of the display.
626 * Return a UNIX error number or 0 for success.
627 */
628 int
629 et_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
630 int a3)
631 {
632 int error;
633
634 switch (cmd) {
635 case GM_GRFON:
636 error = et_load_mon(gp,
637 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
638 return (error);
639
640 case GM_GRFOFF:
641 #ifndef TSENGCONSOLE
642 et_off(gp);
643 #else
644 et_load_mon(gp, &etconsole_mode);
645 #endif
646 return (0);
647
648 case GM_GRFCONFIG:
649 return (0);
650
651 case GM_GRFGETVMODE:
652 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
653
654 case GM_GRFSETVMODE:
655 error = et_setvmode(gp, *(unsigned *) arg);
656 if (!error && (gp->g_flags & GF_GRFON))
657 et_load_mon(gp,
658 (struct grfettext_mode *) monitor_current);
659 return (error);
660
661 case GM_GRFGETNUMVM:
662 *(int *) arg = monitor_def_max;
663 return (0);
664
665 case GM_GRFIOCTL:
666 return (et_ioctl(gp, a2, arg));
667
668 default:
669 break;
670 }
671
672 return (EPASSTHROUGH);
673 }
674
675
676 int
677 et_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
678 {
679 switch (cmd) {
680 case GRFIOCGSPRITEPOS:
681 return (et_getmousepos(gp, (struct grf_position *) data));
682
683 case GRFIOCSSPRITEPOS:
684 return (et_setmousepos(gp, (struct grf_position *) data));
685
686 case GRFIOCSSPRITEINF:
687 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
688
689 case GRFIOCGSPRITEINF:
690 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
691
692 case GRFIOCGSPRITEMAX:
693 return (et_getspritemax(gp, (struct grf_position *) data));
694
695 case GRFIOCGETCMAP:
696 return (et_getcmap(gp, (struct grf_colormap *) data));
697
698 case GRFIOCPUTCMAP:
699 return (et_putcmap(gp, (struct grf_colormap *) data));
700
701 case GRFIOCBITBLT:
702 break;
703
704 case GRFTOGGLE:
705 return (et_toggle(gp, 0));
706
707 case GRFIOCSETMON:
708 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
709
710 case GRFIOCBLANK:
711 return (et_blank(gp, (int *)data));
712 }
713 return (EPASSTHROUGH);
714 }
715
716
717 int
718 et_getmousepos(struct grf_softc *gp, struct grf_position *data)
719 {
720 data->x = et_cursprite.pos.x;
721 data->y = et_cursprite.pos.y;
722
723 return (0);
724 }
725
726
727 void
728 et_writesprpos(volatile char *ba, short x, short y)
729 {
730 }
731
732
733 int
734 et_setmousepos(struct grf_softc *gp, struct grf_position *data)
735 {
736 volatile char *ba = gp->g_regkva;
737 short rx, ry, prx, pry;
738
739 /* no movement */
740 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
741 return (0);
742
743 /* current and previous real coordinates */
744 rx = data->x - et_cursprite.hot.x;
745 ry = data->y - et_cursprite.hot.y;
746 prx = et_cursprite.pos.x - et_cursprite.hot.x;
747 pry = et_cursprite.pos.y - et_cursprite.hot.y;
748
749 /* if we are/were on an edge, create (un)shifted bitmap --
750 * ripped out optimization (not extremely worthwhile,
751 * and kind of buggy anyhow).
752 */
753
754 /* do movement, save position */
755 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
756 et_cursprite.pos.x = data->x;
757 et_cursprite.pos.y = data->y;
758
759 return (0);
760 }
761
762
763 int
764 et_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
765 {
766
767 return(EINVAL);
768 }
769
770
771 static int
772 et_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
773 {
774
775 return(EINVAL);
776 }
777
778
779 static int
780 et_getspritemax(struct grf_softc *gp, struct grf_position *data)
781 {
782
783 return(EINVAL);
784 }
785
786
787 int
788 et_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
789 {
790 struct grfvideo_mode *md;
791
792 if (!et_mondefok(gv))
793 return(EINVAL);
794
795 #ifdef TSENGCONSOLE
796 /* handle interactive setting of console mode */
797 if (gv->mode_num == 255) {
798 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
799 etconsole_mode.gv.hblank_start /= 8;
800 etconsole_mode.gv.hsync_start /= 8;
801 etconsole_mode.gv.hsync_stop /= 8;
802 etconsole_mode.gv.htotal /= 8;
803 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
804 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
805 if (!(gp->g_flags & GF_GRFON))
806 et_load_mon(gp, &etconsole_mode);
807 ite_reinit(gp->g_itedev);
808 return (0);
809 }
810 #endif
811
812 md = monitor_def + (gv->mode_num - 1);
813 bcopy(gv, md, sizeof(struct grfvideo_mode));
814
815 /* adjust pixel oriented values to internal rep. */
816
817 md->hblank_start /= 8;
818 md->hsync_start /= 8;
819 md->hsync_stop /= 8;
820 md->htotal /= 8;
821
822 return (0);
823 }
824
825
826 int
827 et_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
828 {
829 volatile unsigned char *ba;
830 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
831 short x;
832 int error;
833
834 if (cmap->count == 0 || cmap->index >= 256)
835 return 0;
836
837 if (cmap->count > 256 - cmap->index)
838 cmap->count = 256 - cmap->index;
839
840 ba = gfp->g_regkva;
841 /* first read colors out of the chip, then copyout to userspace */
842 x = cmap->count - 1;
843
844 rp = red + cmap->index;
845 gp = green + cmap->index;
846 bp = blue + cmap->index;
847
848 switch(ettype) {
849 case MERLIN:
850 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
851 do {
852 *rp++ = vgar(ba, MERLIN_VDAC_COLORS);
853 *gp++ = vgar(ba, MERLIN_VDAC_COLORS);
854 *bp++ = vgar(ba, MERLIN_VDAC_COLORS);
855 } while (x-- > 0);
856 break;
857 default:
858 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index);
859 do {
860 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
861 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
862 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
863 } while (x-- > 0);
864 break;
865 }
866
867 error = copyout(red + cmap->index, cmap->red, cmap->count);
868 if (!error)
869 error = copyout(green + cmap->index, cmap->green, cmap->count);
870 if (!error)
871 error = copyout(blue + cmap->index, cmap->blue, cmap->count);
872
873 return (error);
874 }
875
876
877 int
878 et_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
879 {
880 volatile unsigned char *ba;
881 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
882 short x;
883 int error;
884
885 if (cmap->count == 0 || cmap->index >= 256)
886 return (0);
887
888 if (cmap->count > 256 - cmap->index)
889 cmap->count = 256 - cmap->index;
890
891 /* first copy the colors into kernelspace */
892 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
893 return (error);
894
895 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
896 return (error);
897
898 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
899 return (error);
900
901 ba = gfp->g_regkva;
902 x = cmap->count - 1;
903
904 rp = red + cmap->index;
905 gp = green + cmap->index;
906 bp = blue + cmap->index;
907
908 switch(ettype){
909 case MERLIN:
910 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
911 do {
912 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
913 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
914 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
915 } while (x-- > 0);
916 break;
917 default:
918 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
919 do {
920 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
921 *rp++ >> etcmap_shift);
922 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
923 *gp++ >> etcmap_shift);
924 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
925 *bp++ >> etcmap_shift);
926 } while (x-- > 0);
927 break;
928 }
929
930 return (0);
931 }
932
933
934 int
935 et_toggle(struct grf_softc *gp, unsigned short wopp)
936 /* (variable wopp) don't need that one yet, ill */
937 {
938 volatile unsigned char *ba;
939
940 ba = gp->g_regkva;
941
942 if (pass_toggle) {
943 RegOffpass(ba);
944 } else {
945 RegOnpass(ba);
946 }
947 return (0);
948 }
949
950
951 #define ET_NUMCLOCKS 32
952
953 static u_char et_clocks[ET_NUMCLOCKS] = {
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 0, 1, 6, 2, 3, 7, 4, 5
958 };
959
960 static u_char et_clockdividers[ET_NUMCLOCKS] = {
961 3, 3, 3, 3, 3, 3, 3, 3,
962 2, 2, 2, 2, 2, 2, 2, 2,
963 1, 1, 1, 1, 1, 1, 1, 1,
964 0, 0, 0, 0, 0, 0, 0, 0
965 };
966
967 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
968 6293750, 7080500, 7875000, 8125000,
969 9000000, 9375000, 10000000, 11225000,
970 12587500, 14161000, 15750000, 16250000,
971 18000000, 18750000, 20000000, 22450000,
972 25175000, 28322000, 31500000, 32500000,
973 36000000, 37500000, 40000000, 44900000,
974 50350000, 56644000, 63000000, 65000000,
975 72000000, 75000000, 80000000, 89800000
976 };
977
978
979 static void
980 et_CompFQ(u_int fq, u_char *num, u_char *denom)
981 {
982 int i;
983
984 for (i=0; i < ET_NUMCLOCKS;) {
985 if (fq <= et_clockfreqs[i++]) {
986 break;
987 }
988 }
989
990 *num = et_clocks[--i];
991 *denom = et_clockdividers[i];
992
993 return;
994 }
995
996
997 int
998 et_mondefok(struct grfvideo_mode *gv)
999 {
1000 unsigned long maxpix;
1001
1002 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1003 if (gv->mode_num != 255 || gv->depth != 4)
1004 return(0);
1005
1006 switch (gv->depth) {
1007 case 4:
1008 if (gv->mode_num != 255)
1009 return(0);
1010 case 1:
1011 case 8:
1012 maxpix = 85000000;
1013 break;
1014 case 15:
1015 case 16:
1016 maxpix = 45000000;
1017 break;
1018 case 24:
1019 maxpix = 28000000;
1020 break;
1021 case 32:
1022 maxpix = 21000000;
1023 break;
1024 default:
1025 printf("grfet: Illegal depth in mode %d\n",
1026 (int) gv->mode_num);
1027 return (0);
1028 }
1029
1030 if (gv->pixel_clock > maxpix) {
1031 printf("grfet: Pixelclock too high in mode %d\n",
1032 (int) gv->mode_num);
1033 return (0);
1034 }
1035
1036 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1037 printf("grfet: sync-on-green is not supported\n");
1038 return (0);
1039 }
1040
1041 return (1);
1042 }
1043
1044
1045 int
1046 et_load_mon(struct grf_softc *gp, struct grfettext_mode *md)
1047 {
1048 struct grfvideo_mode *gv;
1049 struct grfinfo *gi;
1050 volatile unsigned char *ba;
1051 unsigned char num0, denom0;
1052 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1053 VSE, VT;
1054 unsigned char hvsync_pulse, seq;
1055 char TEXT;
1056 int hmul;
1057
1058 /* identity */
1059 gv = &md->gv;
1060 TEXT = (gv->depth == 4);
1061
1062 if (!et_mondefok(gv)) {
1063 printf("grfet: Monitor definition not ok\n");
1064 return (0);
1065 }
1066
1067 ba = gp->g_regkva;
1068
1069 /* provide all needed information in grf device-independent locations */
1070 gp->g_data = (void *) gv;
1071 gi = &gp->g_display;
1072 gi->gd_regaddr = ztwopa(__UNVOLATILE(ba));
1073 gi->gd_regsize = 64 * 1024;
1074 gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(gp->g_fbkva));
1075 gi->gd_fbsize = et_fbsize;
1076 gi->gd_colors = 1 << gv->depth;
1077 gi->gd_planes = gv->depth;
1078 gi->gd_fbwidth = gv->disp_width;
1079 gi->gd_fbheight = gv->disp_height;
1080 gi->gd_fbx = 0;
1081 gi->gd_fby = 0;
1082 if (TEXT) {
1083 gi->gd_dwidth = md->fx * md->cols;
1084 gi->gd_dheight = md->fy * md->rows;
1085 } else {
1086 gi->gd_dwidth = gv->disp_width;
1087 gi->gd_dheight = gv->disp_height;
1088 }
1089 gi->gd_dx = 0;
1090 gi->gd_dy = 0;
1091
1092 /* get display mode parameters */
1093
1094 HBS = gv->hblank_start;
1095 HSS = gv->hsync_start;
1096 HSE = gv->hsync_stop;
1097 HBE = gv->htotal - 1;
1098 HT = gv->htotal;
1099 VBS = gv->vblank_start;
1100 VSS = gv->vsync_start;
1101 VSE = gv->vsync_stop;
1102 VBE = gv->vtotal - 1;
1103 VT = gv->vtotal;
1104
1105 if (TEXT)
1106 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1107 else
1108 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1109 VDE = gv->disp_height - 1;
1110
1111 /* adjustments (crest) */
1112 switch (gv->depth) {
1113 case 15:
1114 case 16:
1115 hmul = 2;
1116 break;
1117 case 24:
1118 hmul = 3;
1119 break;
1120 case 32:
1121 hmul = 4;
1122 break;
1123 default:
1124 hmul = 1;
1125 break;
1126 }
1127
1128 HDE *= hmul;
1129 HBS *= hmul;
1130 HSS *= hmul;
1131 HSE *= hmul;
1132 HBE *= hmul;
1133 HT *= hmul;
1134
1135 if (gv->disp_flags & GRF_FLAGS_LACE) {
1136 VDE /= 2;
1137 VT = VT + 1;
1138 }
1139
1140 if (gv->disp_flags & GRF_FLAGS_DBLSCAN) {
1141 VDE *= 2;
1142 VBS *= 2;
1143 VSS *= 2;
1144 VSE *= 2;
1145 VBE *= 2;
1146 VT *= 2;
1147 }
1148
1149 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1150
1151 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1152 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1153 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1154
1155 /* Set clock */
1156 et_CompFQ( gv->pixel_clock * hmul, &num0, &denom0);
1157
1158 /* Horizontal/Vertical Sync Pulse */
1159 hvsync_pulse = 0xe3;
1160 if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1161 hvsync_pulse &= ~0x40;
1162 else
1163 hvsync_pulse |= 0x40;
1164 if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1165 hvsync_pulse &= ~0x80;
1166 else
1167 hvsync_pulse |= 0x80;
1168
1169 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse | ((num0 & 3) << 2));
1170 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1171 seq = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1172 switch(denom0) {
1173 case 0:
1174 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1175 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1176 break;
1177 case 1:
1178 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1179 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1180 break;
1181 case 2:
1182 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1183 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1184 break;
1185 case 3:
1186 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1187 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1188 break;
1189 }
1190
1191 /* load display parameters into board */
1192 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1193 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1194 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1195 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);
1196 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1197 WCrt(ba, CRT_ID_END_HOR_RETR,
1198 (HSE & 0x1f) |
1199 ((HBE & 0x20) ? 0x80 : 0x00));
1200 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1201 WCrt(ba, CRT_ID_OVERFLOW,
1202 0x10 |
1203 ((VT & 0x100) ? 0x01 : 0x00) |
1204 ((VDE & 0x100) ? 0x02 : 0x00) |
1205 ((VSS & 0x100) ? 0x04 : 0x00) |
1206 ((VBS & 0x100) ? 0x08 : 0x00) |
1207 ((VT & 0x200) ? 0x20 : 0x00) |
1208 ((VDE & 0x200) ? 0x40 : 0x00) |
1209 ((VSS & 0x200) ? 0x80 : 0x00));
1210
1211 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1212 0x40 | /* splitscreen not visible */
1213 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1214 ((VBS & 0x200) ? 0x20 : 0x00) |
1215 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1216
1217 WCrt(ba, CRT_ID_MODE_CONTROL,
1218 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1219
1220 /* text cursor */
1221 if (TEXT) {
1222 #if ET_ULCURSOR
1223 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1224 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1225 #else
1226 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1227 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1228 #endif
1229 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1230 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1231 }
1232
1233 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1234 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1235
1236 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1237 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1238
1239 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1240 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1241 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1242 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1243 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1244
1245 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1246
1247 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1248 ((VBS & 0x400) ? 0x01 : 0x00) |
1249 ((VT & 0x400) ? 0x02 : 0x00) |
1250 ((VDE & 0x400) ? 0x04 : 0x00) |
1251 ((VSS & 0x400) ? 0x08 : 0x00) |
1252 0x10 |
1253 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x80 : 0x00));
1254
1255 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1256 ((HT & 0x100) ? 0x01 : 0x00) |
1257 ((HBS & 0x100) ? 0x04 : 0x00) |
1258 ((HSS & 0x100) ? 0x10 : 0x00)
1259 );
1260
1261 /* depth dependent stuff */
1262
1263 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1264 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1265 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1266
1267 vgaw(ba, VDAC_MASK, 0xff);
1268 vgar(ba, VDAC_MASK);
1269 vgar(ba, VDAC_MASK);
1270 vgar(ba, VDAC_MASK);
1271 vgar(ba, VDAC_MASK);
1272 switch (gv->depth) {
1273 case 1:
1274 case 4: /* text */
1275 switch(etdtype) {
1276 case SIERRA11483:
1277 case SIERRA15025:
1278 case MUSICDAC:
1279 vgaw(ba, VDAC_MASK, 0);
1280 break;
1281 case ATT20C491:
1282 vgaw(ba, VDAC_MASK, 0x02);
1283 break;
1284 case MERLINDAC:
1285 setMerlinDACmode(ba, 0);
1286 break;
1287 }
1288 HDE = gv->disp_width / 16;
1289 break;
1290 case 8:
1291 switch(etdtype) {
1292 case SIERRA11483:
1293 case SIERRA15025:
1294 case MUSICDAC:
1295 vgaw(ba, VDAC_MASK, 0);
1296 break;
1297 case ATT20C491:
1298 vgaw(ba, VDAC_MASK, 0x02);
1299 break;
1300 case MERLINDAC:
1301 setMerlinDACmode(ba, 0);
1302 break;
1303 }
1304 HDE = gv->disp_width / 8;
1305 break;
1306 case 15:
1307 switch(etdtype) {
1308 case SIERRA11483:
1309 case SIERRA15025:
1310 case MUSICDAC:
1311 case ATT20C491:
1312 vgaw(ba, VDAC_MASK, 0xa0);
1313 break;
1314 case MERLINDAC:
1315 setMerlinDACmode(ba, 0xa0);
1316 break;
1317 }
1318 HDE = gv->disp_width / 4;
1319 break;
1320 case 16:
1321 switch(etdtype) {
1322 case SIERRA11483:
1323 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1324 break;
1325 case SIERRA15025:
1326 vgaw(ba, VDAC_MASK, 0xe0);
1327 break;
1328 case MUSICDAC:
1329 case ATT20C491:
1330 vgaw(ba, VDAC_MASK, 0xc0);
1331 break;
1332 case MERLINDAC:
1333 setMerlinDACmode(ba, 0xe0);
1334 break;
1335 }
1336 HDE = gv->disp_width / 4;
1337 break;
1338 case 24:
1339 switch(etdtype) {
1340 case SIERRA11483:
1341 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1342 break;
1343 case SIERRA15025:
1344 vgaw(ba, VDAC_MASK, 0xe1);
1345 break;
1346 case MUSICDAC:
1347 case ATT20C491:
1348 vgaw(ba, VDAC_MASK, 0xe0);
1349 break;
1350 case MERLINDAC:
1351 setMerlinDACmode(ba, 0xf0);
1352 break;
1353 }
1354 HDE = (gv->disp_width / 8) * 3;
1355 break;
1356 case 32:
1357 switch(etdtype) {
1358 case SIERRA11483:
1359 case MUSICDAC:
1360 case ATT20C491:
1361 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1362 break;
1363 case SIERRA15025:
1364 vgaw(ba, VDAC_MASK, 0x61);
1365 break;
1366 case MERLINDAC:
1367 setMerlinDACmode(ba, 0xb0);
1368 break;
1369 }
1370 HDE = gv->disp_width / 2;
1371 break;
1372 }
1373 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1374 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1375 (gv->depth == 1) ? 0x01 : 0x0f);
1376
1377 WCrt(ba, CRT_ID_OFFSET, HDE);
1378 vgaw(ba, CRT_ADDRESS, CRT_ID_HOR_OVERFLOW);
1379 vgaw(ba, CRT_ADDRESS_W,
1380 (vgar(ba, CRT_ADDRESS_R) & 0x7f)
1381 | ((HDE & 0x100) ? 0x80: 0x00));
1382
1383 /* text initialization */
1384 if (TEXT) {
1385 et_inittextmode(gp);
1386 }
1387
1388 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1389
1390 /* Pass-through */
1391 RegOffpass(ba);
1392
1393 return (1);
1394 }
1395
1396
1397 void
1398 et_inittextmode(struct grf_softc *gp)
1399 {
1400 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1401 volatile unsigned char *ba = gp->g_regkva;
1402 volatile unsigned char *fb = gp->g_fbkva;
1403 volatile unsigned char *c;
1404 unsigned char *f, y;
1405 unsigned short z;
1406
1407
1408 /*
1409 * load text font into beginning of display memory. Each character
1410 * cell is 32 bytes long (enough for 4 planes)
1411 */
1412
1413 SetTextPlane(ba, 0x02);
1414 et_memset(fb, 0, 256 * 32);
1415 c = fb + (32 * tm->fdstart);
1416 f = tm->fdata;
1417 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1418 for (y = 0; y < tm->fy; y++)
1419 *c++ = *f++;
1420
1421 /* clear out text/attr planes (three screens worth) */
1422
1423 SetTextPlane(ba, 0x01);
1424 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1425 SetTextPlane(ba, 0x00);
1426 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1427
1428 /* print out a little init msg */
1429
1430 c = fb + (tm->cols - 16);
1431 strcpy(__UNVOLATILE(c), "TSENG");
1432 c[5] = 0x20;
1433
1434 /* set colors (B&W) */
1435
1436 switch(ettype) {
1437 case MERLIN:
1438 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1439 for (z = 0; z < 256; z++) {
1440 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1441
1442 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1443 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1444 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1445 }
1446 break;
1447 default:
1448 vgaw(ba, VDAC_ADDRESS_W, 0);
1449 for (z = 0; z < 256; z++) {
1450 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1451
1452 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1453 etconscolors[y][0] >> etcmap_shift);
1454 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1455 etconscolors[y][1] >> etcmap_shift);
1456 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1457 etconscolors[y][2] >> etcmap_shift);
1458 }
1459 break;
1460 }
1461 }
1462
1463
1464 void
1465 et_memset(volatile unsigned char *d, unsigned char c, int l)
1466 {
1467 for (; l > 0; l--)
1468 *d++ = c;
1469 }
1470
1471
1472 static int
1473 et_getControllerType(struct grf_softc *gp)
1474 {
1475 volatile unsigned char *ba = gp->g_regkva; /* register base */
1476 volatile unsigned char *mem = gp->g_fbkva; /* memory base */
1477 volatile unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1478
1479 *mem = 0;
1480
1481 /* make ACL visible */
1482 if (ettype == MERLIN) {
1483 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xbb);
1484 } else {
1485 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1486 }
1487
1488 WIma(ba, IMA_PORTCONTROL, 0x01);
1489
1490 *((volatile unsigned long *)mmu) = 0;
1491 *(mem + 0x13) = 0x38;
1492
1493 *mmu = 0xff;
1494
1495 /* hide ACL */
1496 WIma(ba, IMA_PORTCONTROL, 0x00);
1497
1498 if (ettype == MERLIN) {
1499 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93);
1500 } else {
1501 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1502 }
1503 return ((*mem == 0xff) ? ETW32 : ET4000);
1504 }
1505
1506
1507 static int
1508 et_getDACType(struct grf_softc *gp)
1509 {
1510 volatile unsigned char *ba = gp->g_regkva;
1511 union {
1512 int tt;
1513 char cc[4];
1514 } check;
1515
1516 /* check for Sierra SC 15025 */
1517
1518 /* We MUST do 4 HW reads to switch into command mode */
1519 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1520 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1521
1522 vgaw(ba, VDAC_XINDEX, 9);
1523 check.cc[0] = vgar(ba, VDAC_XDATA);
1524 vgaw(ba, VDAC_XINDEX, 10);
1525 check.cc[1] = vgar(ba, VDAC_XDATA);
1526 vgaw(ba, VDAC_XINDEX, 11);
1527 check.cc[2] = vgar(ba, VDAC_XDATA);
1528 vgaw(ba, VDAC_XINDEX, 12);
1529 check.cc[3] = vgar(ba, VDAC_XDATA);
1530
1531 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1532 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1533
1534 if (check.tt == 0x533ab141) {
1535 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1536 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1537
1538 /* switch to 8 bits per color */
1539 vgaw(ba, VDAC_XINDEX, 8);
1540 vgaw(ba, VDAC_XDATA, 1);
1541 /* do not shift color values */
1542 etcmap_shift = 0;
1543
1544 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1545 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1546
1547 vgaw(ba, VDAC_MASK, 0xff);
1548 return (SIERRA15025);
1549 }
1550
1551 /* check for MUSIC DAC */
1552
1553 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1554 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1555
1556 vgaw(ba, VDAC_XINDEX, 0x01);
1557 if (vgar(ba, VDAC_XDATA) == 0x01) {
1558 /* shift color values by 2 */
1559 etcmap_shift = 2;
1560
1561 vgaw(ba, VDAC_MASK, 0xff);
1562 return (MUSICDAC);
1563 }
1564
1565 /* check for AT&T ATT20c491 DAC (crest) */
1566 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1567 vgaw(ba, HDR, 0xff);
1568 vgaw(ba, VDAC_MASK, 0x01);
1569 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1570 if (vgar(ba, HDR) == 0xff) {
1571 /* do not shift color values */
1572 etcmap_shift = 0;
1573
1574 vgaw(ba, VDAC_MASK, 0xff);
1575 return (ATT20C491);
1576 }
1577
1578 /* restore PowerUp settings (crest) */
1579 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1580 vgaw(ba, HDR, 0x00);
1581
1582 /*
1583 * nothing else found, so let us pretend it is a stupid
1584 * Sierra SC 11483
1585 */
1586
1587 /* shift color values by 2 */
1588 etcmap_shift = 2;
1589
1590 vgaw(ba, VDAC_MASK, 0xff);
1591 return (SIERRA11483);
1592 }
1593
1594 #endif /* NGRFET */
1595