grf_et.c revision 1.8 1 /* $NetBSD: grf_et.c,v 1.8 1996/12/23 09:10:06 veego Exp $ */
2
3 /*
4 * Copyright (c) 1996 Tobias Abt
5 * Copyright (c) 1995 Ezra Story
6 * Copyright (c) 1995 Kari Mettinen
7 * Copyright (c) 1994 Markus Wild
8 * Copyright (c) 1994 Lutz Vieweg
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Lutz Vieweg.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 #include "grfet.h"
37 #if NGRFET > 0
38
39 /*
40 * Graphics routines for Tseng ET4000 (&W32) boards,
41 *
42 * This code offers low-level routines to access Tseng ET4000
43 * graphics-boards from within NetBSD for the Amiga.
44 * No warranties for any kind of function at all - this
45 * code may crash your hardware and scratch your harddisk. Use at your
46 * own risk. Freely distributable.
47 *
48 * Modified for Tseng ET4000 from
49 * Kari Mettinen's Cirrus driver by Tobias Abt
50 *
51 *
52 * TODO:
53 *
54 */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/errno.h>
59 #include <sys/ioctl.h>
60 #include <sys/device.h>
61 #include <sys/malloc.h>
62
63 #include <machine/cpu.h>
64 #include <dev/cons.h>
65 #ifdef TSENGCONSOLE
66 #include <amiga/dev/itevar.h>
67 #endif
68 #include <amiga/amiga/device.h>
69 #include <amiga/dev/grfioctl.h>
70 #include <amiga/dev/grfvar.h>
71 #include <amiga/dev/grf_etreg.h>
72 #include <amiga/dev/zbusvar.h>
73
74 int et_mondefok __P((struct grfvideo_mode *gv));
75 void et_boardinit __P((struct grf_softc *gp));
76 static void et_CompFQ __P((u_int fq, u_char *num, u_char *denom));
77 int et_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm));
78 int et_setvmode __P((struct grf_softc *gp, unsigned int mode));
79 int et_toggle __P((struct grf_softc *gp, unsigned short));
80 int et_getcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
81 int et_putcmap __P((struct grf_softc *gfp, struct grf_colormap *cmap));
82 #ifndef TSENGCONSOLE
83 void et_off __P((struct grf_softc *gp));
84 #endif
85 void et_inittextmode __P((struct grf_softc *gp));
86 int et_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data));
87 int et_getmousepos __P((struct grf_softc *gp, struct grf_position *data));
88 void et_writesprpos __P((volatile char *ba, short x, short y));
89 int et_setmousepos __P((struct grf_softc *gp, struct grf_position *data));
90 static int et_setspriteinfo __P((struct grf_softc *gp,
91 struct grf_spriteinfo *data));
92 int et_getspriteinfo __P((struct grf_softc *gp,
93 struct grf_spriteinfo *data));
94 static int et_getspritemax __P((struct grf_softc *gp,
95 struct grf_position *data));
96 int et_setmonitor __P((struct grf_softc *gp, struct grfvideo_mode *gv));
97 int et_blank __P((struct grf_softc *gp, int *on));
98 static int et_getControllerType __P((struct grf_softc *gp));
99 static int et_getDACType __P((struct grf_softc *gp));
100
101 int grfetmatch __P((struct device *, struct cfdata *, void *));
102 void grfetattach __P((struct device *, struct device *, void *));
103 int grfetprint __P((void *, const char *));
104 void et_memset __P((unsigned char *d, unsigned char c, int l));
105
106 /*
107 * Graphics display definitions.
108 * These are filled by 'grfconfig' using GRFIOCSETMON.
109 */
110 #define monitor_def_max 8
111 static struct grfvideo_mode monitor_def[8] = {
112 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
113 };
114 static struct grfvideo_mode *monitor_current = &monitor_def[0];
115
116 /* Console display definition.
117 * Default hardcoded text mode. This grf_et is set up to
118 * use one text mode only, and this is it. You may use
119 * grfconfig to change the mode after boot.
120 */
121 /* Console font */
122 #ifdef KFONT_8X11
123 #define TSENGFONT kernel_font_8x11
124 #define TSENGFONTY 11
125 #else
126 #define TSENGFONT kernel_font_8x8
127 #define TSENGFONTY 8
128 #endif
129 extern unsigned char TSENGFONT[];
130
131 struct grfettext_mode etconsole_mode = {
132 {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8,
133 481, 521, 491, 493, 525},
134 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
135 };
136
137 /* Console colors */
138 unsigned char etconscolors[3][3] = { /* background, foreground, hilite */
139 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
140 };
141
142 int ettype = 0; /* oMniBus, Domino or Merlin */
143 int etctype = 0; /* ET4000 or ETW32 */
144 int etdtype = 0; /* Type of DAC (see grf_etregs.h) */
145
146 char etcmap_shift = 0; /* 6 or 8 bit cmap entries */
147 unsigned char pass_toggle; /* passthru status tracker */
148
149 unsigned char Merlin_switch = 0;
150
151 /*
152 * Because all Tseng-boards have 2 configdev entries, one for
153 * framebuffer mem and the other for regs, we have to hold onto
154 * the pointers globally until we match on both. This and 'ettype'
155 * are the primary obsticles to multiple board support, but if you
156 * have multiple boards you have bigger problems than grf_et.
157 */
158 static void *et_fbaddr = 0; /* framebuffer */
159 static void *et_regaddr = 0; /* registers */
160 static int et_fbsize; /* framebuffer size */
161
162 /* current sprite info, if you add support for multiple boards
163 * make this an array or something
164 */
165 struct grf_spriteinfo et_cursprite;
166
167 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
168 * you add multiple board support
169 */
170 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
171 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
172
173 /* standard driver stuff */
174 struct cfattach grfet_ca = {
175 sizeof(struct grf_softc), grfetmatch, grfetattach
176 };
177
178 struct cfdriver grfet_cd = {
179 NULL, "grfet", DV_DULL, NULL, 0
180 };
181
182 static struct cfdata *cfdata;
183
184 int
185 grfetmatch(pdp, cfp, auxp)
186 struct device *pdp;
187 struct cfdata *cfp;
188 void *auxp;
189 {
190 struct zbus_args *zap;
191 static int regprod, 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 if (zap->prodid != 2 && zap->prodid != 1)
213 return (0);
214 regprod = 2;
215 fbprod = 1;
216 break;
217 case MERLIN:
218 if (zap->prodid != 3 && zap->prodid != 4)
219 return (0);
220 regprod = 4;
221 fbprod = 3;
222 break;
223 default:
224 return (0);
225 }
226 ettype = zap->manid;
227 } else {
228 if (ettype != zap->manid) {
229 return (0);
230 }
231 }
232
233 /* Configure either registers or framebuffer in any order */
234 /* as said before, oMniBus does not support ProdID */
235 if (ettype == OMNIBUS) {
236 if (zap->size == 64 * 1024) {
237 /* register area */
238 et_regaddr = zap->va;
239 } else {
240 /* memory area */
241 et_fbaddr = zap->va;
242 et_fbsize = zap->size;
243 }
244 } else {
245 if (zap->prodid == regprod) {
246 et_regaddr = zap->va;
247 } else {
248 if (zap->prodid == fbprod) {
249 et_fbaddr = zap->va;
250 et_fbsize = zap->size;
251 } else {
252 return (0);
253 }
254 }
255 }
256
257 #ifdef TSENGCONSOLE
258 if (amiga_realconfig == 0) {
259 cfdata = cfp;
260 }
261 #endif
262
263 return (1);
264 }
265
266
267 void
268 grfetattach(pdp, dp, auxp)
269 struct device *pdp, *dp;
270 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 DAC");
354 break;
355 }
356 printf(" being used\n");
357 } else {
358 if (!attachflag)
359 printf("grfet unattached!!\n");
360 }
361 }
362
363
364 int
365 grfetprint(auxp, pnp)
366 void *auxp;
367 const char *pnp;
368 {
369 if (pnp)
370 printf("ite at %s: ", pnp);
371 return (UNCONF);
372 }
373
374
375 void
376 et_boardinit(gp)
377 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_TS_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, 0x07);
440 WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
441 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
442 /* ET4000 special */
443 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
444 WCrt(ba, CTR_ID_EXT_START, 0x00);
445 WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
446 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
447 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); /* assume ZorroII first */
448
449 if (iszthreepa(ba)) {
450 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) |
451 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24 )
452 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* ZorroIII */
453 }
454
455 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
456
457 WGfx(ba, GCT_ID_SET_RESET, 0x00);
458 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
459 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
460 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
461 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
462 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
463 WGfx(ba, GCT_ID_MISC, 0x01);
464 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
465 WGfx(ba, GCT_ID_BITMASK, 0xff);
466
467 vgaw(ba, GREG_SEGMENTSELECT, 0x00);
468
469 for (x = 0; x < 0x10; x++)
470 WAttr(ba, x, x);
471 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
472 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
473 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
474 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
475 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
476 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
477
478 vgaw(ba, VDAC_MASK, 0xff);
479 delay(200000);
480 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
481
482 /* colors initially set to greyscale */
483
484 switch(ettype) {
485 case MERLIN:
486 vgaw(ba, MERLIN_VDAC_INDEX, 0);
487 for (x = 255; x >= 0; x--) {
488 vgaw(ba, MERLIN_VDAC_COLORS, x);
489 vgaw(ba, MERLIN_VDAC_COLORS, x);
490 vgaw(ba, MERLIN_VDAC_COLORS, x);
491 }
492 break;
493 default:
494 vgaw(ba, VDAC_ADDRESS_W, 0);
495 for (x = 255; x >= 0; x--) {
496 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
497 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
498 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
499 }
500 break;
501 }
502 /* set sprite bitmap pointers */
503 /* should work like that */
504 et_cursprite.image = et_imageptr;
505 et_cursprite.mask = et_maskptr;
506 et_cursprite.cmap.red = et_sprred;
507 et_cursprite.cmap.green = et_sprgreen;
508 et_cursprite.cmap.blue = et_sprblue;
509
510 /* card spezific initialisations */
511 switch(ettype) {
512 case OMNIBUS:
513 etctype = et_getControllerType(gp);
514 etdtype = et_getDACType(gp);
515 break;
516 case MERLIN:
517 etctype = ETW32;
518 etdtype = MERLINDAC;
519 break;
520 case DOMINO:
521 etctype = ET4000;
522 etdtype = SIERRA11483;
523 break;
524 }
525 }
526
527
528 int
529 et_getvmode(gp, vm)
530 struct grf_softc *gp;
531 struct grfvideo_mode *vm;
532 {
533 struct grfvideo_mode *gv;
534
535 #ifdef TSENGCONSOLE
536 /* Handle grabbing console mode */
537 if (vm->mode_num == 255) {
538 bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
539 /* XXX so grfconfig can tell us the correct text dimensions. */
540 vm->depth = etconsole_mode.fy;
541 } else
542 #endif
543 {
544 if (vm->mode_num == 0)
545 vm->mode_num = (monitor_current - monitor_def) + 1;
546 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
547 return (EINVAL);
548 gv = monitor_def + (vm->mode_num - 1);
549 if (gv->mode_num == 0)
550 return (EINVAL);
551
552 bcopy(gv, vm, sizeof(struct grfvideo_mode));
553 }
554
555 /* adjust internal values to pixel values */
556
557 vm->hblank_start *= 8;
558 vm->hblank_stop *= 8;
559 vm->hsync_start *= 8;
560 vm->hsync_stop *= 8;
561 vm->htotal *= 8;
562
563 return (0);
564 }
565
566
567 int
568 et_setvmode(gp, mode)
569 struct grf_softc *gp;
570 unsigned mode;
571 {
572 if (!mode || (mode > monitor_def_max) ||
573 monitor_def[mode - 1].mode_num == 0)
574 return (EINVAL);
575
576 monitor_current = monitor_def + (mode - 1);
577
578 return (0);
579 }
580
581
582 #ifndef TSENGCONSOLE
583 void
584 et_off(gp)
585 struct grf_softc *gp;
586 {
587 char *ba = gp->g_regkva;
588
589 RegOnpass(ba);
590 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
591 }
592 #endif
593
594
595 int
596 et_blank(gp, on)
597 struct grf_softc *gp;
598 int *on;
599 {
600 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on > 0 ? 0x01 : 0x21);
601 return(0);
602 }
603
604
605 /*
606 * Change the mode of the display.
607 * Return a UNIX error number or 0 for success.
608 */
609 int
610 et_mode(gp, cmd, arg, a2, a3)
611 register struct grf_softc *gp;
612 u_long cmd;
613 void *arg;
614 u_long a2;
615 int a3;
616 {
617 int error;
618
619 switch (cmd) {
620 case GM_GRFON:
621 error = et_load_mon(gp,
622 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
623 return (error);
624
625 case GM_GRFOFF:
626 #ifndef TSENGCONSOLE
627 et_off(gp);
628 #else
629 et_load_mon(gp, &etconsole_mode);
630 #endif
631 return (0);
632
633 case GM_GRFCONFIG:
634 return (0);
635
636 case GM_GRFGETVMODE:
637 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
638
639 case GM_GRFSETVMODE:
640 error = et_setvmode(gp, *(unsigned *) arg);
641 if (!error && (gp->g_flags & GF_GRFON))
642 et_load_mon(gp,
643 (struct grfettext_mode *) monitor_current);
644 return (error);
645
646 case GM_GRFGETNUMVM:
647 *(int *) arg = monitor_def_max;
648 return (0);
649
650 case GM_GRFIOCTL:
651 return (et_ioctl(gp, a2, arg));
652
653 default:
654 break;
655 }
656
657 return (EINVAL);
658 }
659
660
661 int
662 et_ioctl(gp, cmd, data)
663 register struct grf_softc *gp;
664 u_long cmd;
665 void *data;
666 {
667 switch (cmd) {
668 case GRFIOCGSPRITEPOS:
669 return (et_getmousepos(gp, (struct grf_position *) data));
670
671 case GRFIOCSSPRITEPOS:
672 return (et_setmousepos(gp, (struct grf_position *) data));
673
674 case GRFIOCSSPRITEINF:
675 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
676
677 case GRFIOCGSPRITEINF:
678 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
679
680 case GRFIOCGSPRITEMAX:
681 return (et_getspritemax(gp, (struct grf_position *) data));
682
683 case GRFIOCGETCMAP:
684 return (et_getcmap(gp, (struct grf_colormap *) data));
685
686 case GRFIOCPUTCMAP:
687 return (et_putcmap(gp, (struct grf_colormap *) data));
688
689 case GRFIOCBITBLT:
690 break;
691
692 case GRFTOGGLE:
693 return (et_toggle(gp, 0));
694
695 case GRFIOCSETMON:
696 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
697
698 case GRFIOCBLANK:
699 return (et_blank(gp, (int *)data));
700 }
701 return (EINVAL);
702 }
703
704
705 int
706 et_getmousepos(gp, data)
707 struct grf_softc *gp;
708 struct grf_position *data;
709 {
710 data->x = et_cursprite.pos.x;
711 data->y = et_cursprite.pos.y;
712
713 return (0);
714 }
715
716
717 void
718 et_writesprpos(ba, x, y)
719 volatile char *ba;
720 short x;
721 short y;
722 {
723 }
724
725
726 int
727 et_setmousepos(gp, data)
728 struct grf_softc *gp;
729 struct grf_position *data;
730 {
731 volatile char *ba = gp->g_regkva;
732 short rx, ry, prx, pry;
733
734 /* no movement */
735 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
736 return (0);
737
738 /* current and previous real coordinates */
739 rx = data->x - et_cursprite.hot.x;
740 ry = data->y - et_cursprite.hot.y;
741 prx = et_cursprite.pos.x - et_cursprite.hot.x;
742 pry = et_cursprite.pos.y - et_cursprite.hot.y;
743
744 /* if we are/were on an edge, create (un)shifted bitmap --
745 * ripped out optimization (not extremely worthwhile,
746 * and kind of buggy anyhow).
747 */
748
749 /* do movement, save position */
750 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
751 et_cursprite.pos.x = data->x;
752 et_cursprite.pos.y = data->y;
753
754 return (0);
755 }
756
757
758 int
759 et_getspriteinfo(gp, data)
760 struct grf_softc *gp;
761 struct grf_spriteinfo *data;
762 {
763
764 return(EINVAL);
765 }
766
767
768 static int
769 et_setspriteinfo(gp, data)
770 struct grf_softc *gp;
771 struct grf_spriteinfo *data;
772 {
773
774 return(EINVAL);
775 }
776
777
778 static int
779 et_getspritemax(gp, data)
780 struct grf_softc *gp;
781 struct grf_position *data;
782 {
783
784 return(EINVAL);
785 }
786
787
788 int
789 et_setmonitor(gp, gv)
790 struct grf_softc *gp;
791 struct grfvideo_mode *gv;
792 {
793 struct grfvideo_mode *md;
794
795 if (!et_mondefok(gv))
796 return(EINVAL);
797
798 #ifdef TSENGCONSOLE
799 /* handle interactive setting of console mode */
800 if (gv->mode_num == 255) {
801 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
802 etconsole_mode.gv.hblank_start /= 8;
803 etconsole_mode.gv.hblank_stop /= 8;
804 etconsole_mode.gv.hsync_start /= 8;
805 etconsole_mode.gv.hsync_stop /= 8;
806 etconsole_mode.gv.htotal /= 8;
807 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
808 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
809 if (!(gp->g_flags & GF_GRFON))
810 et_load_mon(gp, &etconsole_mode);
811 ite_reinit(gp->g_itedev);
812 return (0);
813 }
814 #endif
815
816 md = monitor_def + (gv->mode_num - 1);
817 bcopy(gv, md, sizeof(struct grfvideo_mode));
818
819 /* adjust pixel oriented values to internal rep. */
820
821 md->hblank_start /= 8;
822 md->hblank_stop /= 8;
823 md->hsync_start /= 8;
824 md->hsync_stop /= 8;
825 md->htotal /= 8;
826
827 return (0);
828 }
829
830
831 int
832 et_getcmap(gfp, cmap)
833 struct grf_softc *gfp;
834 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->index + cmap->count > 256)
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(gfp, cmap)
886 struct grf_softc *gfp;
887 struct grf_colormap *cmap;
888 {
889 volatile unsigned char *ba;
890 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
891 short x;
892 int error;
893
894 if (cmap->count == 0 || cmap->index >= 256)
895 return (0);
896
897 if (cmap->index + cmap->count > 256)
898 cmap->count = 256 - cmap->index;
899
900 /* first copy the colors into kernelspace */
901 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
902 return (error);
903
904 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
905 return (error);
906
907 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
908 return (error);
909
910 ba = gfp->g_regkva;
911 x = cmap->count - 1;
912
913 rp = red + cmap->index;
914 gp = green + cmap->index;
915 bp = blue + cmap->index;
916
917 switch(ettype){
918 case MERLIN:
919 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
920 do {
921 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
922 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
923 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
924 } while (x-- > 0);
925 break;
926 default:
927 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
928 do {
929 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
930 *rp++ >> etcmap_shift);
931 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
932 *gp++ >> etcmap_shift);
933 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
934 *bp++ >> etcmap_shift);
935 } while (x-- > 0);
936 break;
937 }
938
939 return (0);
940 }
941
942
943 int
944 et_toggle(gp, wopp)
945 struct grf_softc *gp;
946 unsigned short wopp; /* don't need that one yet, ill */
947 {
948 volatile unsigned char *ba;
949
950 ba = gp->g_regkva;
951
952 if (pass_toggle) {
953 RegOffpass(ba);
954 } else {
955 RegOnpass(ba);
956 }
957 return (0);
958 }
959
960
961 #define ET_NUMCLOCKS 32
962
963 static u_char et_clocks[ET_NUMCLOCKS] = {
964 0, 1, 6, 2, 3, 7, 4, 5,
965 0, 1, 6, 2, 3, 7, 4, 5,
966 0, 1, 6, 2, 3, 7, 4, 5,
967 0, 1, 6, 2, 3, 7, 4, 5
968 };
969
970 static u_char et_clockdividers[ET_NUMCLOCKS] = {
971 3, 3, 3, 3, 3, 3, 3, 3,
972 2, 2, 2, 2, 2, 2, 2, 2,
973 1, 1, 1, 1, 1, 1, 1, 1,
974 0, 0, 0, 0, 0, 0, 0, 0
975 };
976
977 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
978 6293750, 7080500, 7875000, 8125000,
979 9000000, 9375000, 10000000, 11225000,
980 12587500, 14161000, 15750000, 16250000,
981 18000000, 18750000, 20000000, 22450000,
982 25175000, 28322000, 31500000, 32500000,
983 36000000, 37500000, 40000000, 44900000,
984 50350000, 56644000, 63000000, 65000000,
985 72000000, 75000000, 80000000, 89800000
986 };
987
988
989 static void
990 et_CompFQ(fq, num, denom)
991 u_int fq;
992 u_char *num;
993 u_char *denom;
994 {
995 int i;
996
997 for (i=0; i < ET_NUMCLOCKS;) {
998 if (fq <= et_clockfreqs[i++]) {
999 break;
1000 }
1001 }
1002
1003 *num = et_clocks[--i];
1004 *denom = et_clockdividers[i];
1005
1006 return;
1007 }
1008
1009
1010 int
1011 et_mondefok(gv)
1012 struct grfvideo_mode *gv;
1013 {
1014
1015 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1016 if (gv->mode_num != 255 || gv->depth != 4)
1017 return(0);
1018
1019 switch (gv->depth) {
1020 case 4:
1021 if (gv->mode_num != 255)
1022 return(0);
1023 case 1:
1024 case 8:
1025 case 15:
1026 case 16:
1027 case 24:
1028 break;
1029 default:
1030 return (0);
1031 }
1032 return (1);
1033 }
1034
1035
1036 int
1037 et_load_mon(gp, md)
1038 struct grf_softc *gp;
1039 struct grfettext_mode *md;
1040 {
1041 struct grfvideo_mode *gv;
1042 struct grfinfo *gi;
1043 volatile unsigned char *ba;
1044 unsigned char num0, denom0;
1045 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1046 VSE, VT;
1047 char LACE, DBLSCAN, TEXT;
1048 unsigned char seq;
1049 int uplim, lowlim;
1050
1051 /* identity */
1052 gv = &md->gv;
1053 TEXT = (gv->depth == 4);
1054
1055 if (!et_mondefok(gv)) {
1056 printf("mondef not ok\n");
1057 return (0);
1058 }
1059 ba = gp->g_regkva;
1060
1061 /* provide all needed information in grf device-independant locations */
1062 gp->g_data = (caddr_t) gv;
1063 gi = &gp->g_display;
1064 gi->gd_regaddr = (caddr_t) ztwopa(ba);
1065 gi->gd_regsize = 64 * 1024;
1066 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
1067 gi->gd_fbsize = et_fbsize;
1068 gi->gd_colors = 1 << gv->depth;
1069 gi->gd_planes = gv->depth;
1070 gi->gd_fbwidth = gv->disp_width;
1071 gi->gd_fbheight = gv->disp_height;
1072 gi->gd_fbx = 0;
1073 gi->gd_fby = 0;
1074 if (TEXT) {
1075 gi->gd_dwidth = md->fx * md->cols;
1076 gi->gd_dheight = md->fy * md->rows;
1077 } else {
1078 gi->gd_dwidth = gv->disp_width;
1079 gi->gd_dheight = gv->disp_height;
1080 }
1081 gi->gd_dx = 0;
1082 gi->gd_dy = 0;
1083
1084 /* get display mode parameters */
1085
1086 HBS = gv->hblank_start;
1087 HBE = gv->hblank_stop;
1088 HSS = gv->hsync_start;
1089 HSE = gv->hsync_stop;
1090 HT = gv->htotal;
1091 VBS = gv->vblank_start;
1092 VSS = gv->vsync_start;
1093 VSE = gv->vsync_stop;
1094 VBE = gv->vblank_stop;
1095 VT = gv->vtotal;
1096
1097 if (TEXT)
1098 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1099 else
1100 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1101 VDE = gv->disp_height - 1;
1102
1103 /* figure out whether lace or dblscan is needed */
1104
1105 uplim = gv->disp_height + (gv->disp_height / 4);
1106 lowlim = gv->disp_height - (gv->disp_height / 4);
1107 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1108 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1109
1110 /* adjustments */
1111
1112 if (LACE)
1113 VDE /= 2;
1114
1115 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1116
1117 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1118 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1119 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1120
1121 /* Set clock */
1122
1123 et_CompFQ( gv->pixel_clock, &num0, &denom0);
1124
1125 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
1126 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1127 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
1128 switch(denom0) {
1129 case 0:
1130 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1131 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1132 break;
1133 case 1:
1134 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1135 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1136 break;
1137 case 2:
1138 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1139 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1140 break;
1141 case 3:
1142 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1143 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1144 break;
1145 }
1146 /* load display parameters into board */
1147
1148 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1149 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1150 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1151 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1152 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1153 WCrt(ba, CRT_ID_END_HOR_RETR,
1154 (HSE & 0x1f) |
1155 ((HBE & 0x20) ? 0x80 : 0x00));
1156 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1157 WCrt(ba, CRT_ID_OVERFLOW,
1158 0x10 |
1159 ((VT & 0x100) ? 0x01 : 0x00) |
1160 ((VDE & 0x100) ? 0x02 : 0x00) |
1161 ((VSS & 0x100) ? 0x04 : 0x00) |
1162 ((VBS & 0x100) ? 0x08 : 0x00) |
1163 ((VT & 0x200) ? 0x20 : 0x00) |
1164 ((VDE & 0x200) ? 0x40 : 0x00) |
1165 ((VSS & 0x200) ? 0x80 : 0x00));
1166
1167 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1168 0x40 | /* TEXT ? 0x00 ??? */
1169 (DBLSCAN ? 0x80 : 0x00) |
1170 ((VBS & 0x200) ? 0x20 : 0x00) |
1171 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1172
1173 WCrt(ba, CRT_ID_MODE_CONTROL,
1174 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1175
1176 /* text cursor */
1177
1178 if (TEXT) {
1179 #if ET_ULCURSOR
1180 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1181 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1182 #else
1183 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1184 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1185 #endif
1186 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1187 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1188 }
1189
1190 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1191 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1192
1193 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1194 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1195
1196 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1197 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1198 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1199 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1200 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1201
1202 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1203
1204 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1205 ((VBS & 0x400) ? 0x01 : 0x00) |
1206 ((VT & 0x400) ? 0x02 : 0x00) |
1207 ((VDE & 0x400) ? 0x04 : 0x00) |
1208 ((VSS & 0x400) ? 0x08 : 0x00) |
1209 0x10 |
1210 (LACE ? 0x80 : 0x00));
1211
1212 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1213 ((HT & 0x100) ? 0x01 : 0x00) |
1214 ((HBS & 0x100) ? 0x04 : 0x00) |
1215 ((HSS & 0x100) ? 0x10 : 0x00)
1216 );
1217
1218 /* depth dependent stuff */
1219
1220 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1221 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1222 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1223
1224 vgaw(ba, VDAC_MASK, 0xff);
1225 vgar(ba, VDAC_MASK);
1226 vgar(ba, VDAC_MASK);
1227 vgar(ba, VDAC_MASK);
1228 vgar(ba, VDAC_MASK);
1229 switch (gv->depth) {
1230 case 1:
1231 case 4: /* text */
1232 switch(etdtype) {
1233 case SIERRA11483:
1234 case SIERRA15025:
1235 case MUSICDAC:
1236 vgaw(ba, VDAC_MASK, 0);
1237 break;
1238 case MERLINDAC:
1239 setMerlinDACmode(ba, 0);
1240 break;
1241 }
1242 HDE = gv->disp_width / 16;
1243 break;
1244 case 8:
1245 switch(etdtype) {
1246 case SIERRA11483:
1247 case SIERRA15025:
1248 case MUSICDAC:
1249 vgaw(ba, VDAC_MASK, 0);
1250 break;
1251 case MERLINDAC:
1252 setMerlinDACmode(ba, 0);
1253 break;
1254 }
1255 HDE = gv->disp_width / 8;
1256 break;
1257 case 15:
1258 switch(etdtype) {
1259 case SIERRA11483:
1260 case SIERRA15025:
1261 case MUSICDAC:
1262 vgaw(ba, VDAC_MASK, 0xa0);
1263 break;
1264 case MERLINDAC:
1265 setMerlinDACmode(ba, 0xa0);
1266 break;
1267 }
1268 HDE = gv->disp_width / 4;
1269 break;
1270 case 16:
1271 switch(etdtype) {
1272 case SIERRA11483:
1273 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1274 break;
1275 case SIERRA15025:
1276 vgaw(ba, VDAC_MASK, 0xe0);
1277 break;
1278 case MUSICDAC:
1279 vgaw(ba, VDAC_MASK, 0xc0);
1280 break;
1281 case MERLINDAC:
1282 setMerlinDACmode(ba, 0xe0);
1283 break;
1284 }
1285 HDE = gv->disp_width / 4;
1286 break;
1287 case 24:
1288 switch(etdtype) {
1289 case SIERRA11483:
1290 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1291 break;
1292 case SIERRA15025:
1293 vgaw(ba, VDAC_MASK, 0xe1);
1294 break;
1295 case MUSICDAC:
1296 vgaw(ba, VDAC_MASK, 0xe0);
1297 break;
1298 case MERLINDAC:
1299 setMerlinDACmode(ba, 0xf0);
1300 break;
1301 }
1302 HDE = (gv->disp_width / 8) * 3;
1303 break;
1304 case 32:
1305 switch(etdtype) {
1306 case SIERRA11483:
1307 case MUSICDAC:
1308 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1309 break;
1310 case SIERRA15025:
1311 vgaw(ba, VDAC_MASK, 0x61);
1312 break;
1313 case MERLINDAC:
1314 setMerlinDACmode(ba, 0xb0);
1315 break;
1316 }
1317 HDE = gv->disp_width / 2;
1318 break;
1319 }
1320 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1321 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1322 (gv->depth == 1) ? 0x01 : 0x0f);
1323
1324 WCrt(ba, CRT_ID_OFFSET, HDE);
1325
1326 /* text initialization */
1327 if (TEXT) {
1328 et_inittextmode(gp);
1329 }
1330
1331 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1332
1333 /* Pass-through */
1334 RegOffpass(ba);
1335
1336 return (1);
1337 }
1338
1339
1340 void
1341 et_inittextmode(gp)
1342 struct grf_softc *gp;
1343 {
1344 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1345 volatile unsigned char *ba = gp->g_regkva;
1346 unsigned char *fb = gp->g_fbkva;
1347 unsigned char *c, *f, y;
1348 unsigned short z;
1349
1350
1351 /*
1352 * load text font into beginning of display memory. Each character
1353 * cell is 32 bytes long (enough for 4 planes)
1354 */
1355
1356 SetTextPlane(ba, 0x02);
1357 et_memset(fb, 0, 256 * 32);
1358 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1359 f = tm->fdata;
1360 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1361 for (y = 0; y < tm->fy; y++)
1362 *c++ = *f++;
1363
1364 /* clear out text/attr planes (three screens worth) */
1365
1366 SetTextPlane(ba, 0x01);
1367 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1368 SetTextPlane(ba, 0x00);
1369 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1370
1371 /* print out a little init msg */
1372
1373 c = (unsigned char *) (fb) + (tm->cols - 16);
1374 strcpy(c, "TSENG");
1375 c[6] = 0x20;
1376
1377 /* set colors (B&W) */
1378
1379 switch(ettype) {
1380 case MERLIN:
1381 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1382 for (z = 0; z < 256; z++) {
1383 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1384
1385 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1386 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1387 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1388 }
1389 break;
1390 default:
1391 vgaw(ba, VDAC_ADDRESS_W, 0);
1392 for (z = 0; z < 256; z++) {
1393 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1394
1395 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1396 etconscolors[y][0] >> etcmap_shift);
1397 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1398 etconscolors[y][1] >> etcmap_shift);
1399 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1400 etconscolors[y][2] >> etcmap_shift);
1401 }
1402 break;
1403 }
1404 }
1405
1406
1407 void
1408 et_memset(d, c, l)
1409 unsigned char *d;
1410 unsigned char c;
1411 int l;
1412 {
1413 for (; l > 0; l--)
1414 *d++ = c;
1415 }
1416
1417
1418 static int
1419 et_getControllerType(gp)
1420 struct grf_softc * gp;
1421 {
1422 unsigned char *ba = gp->g_regkva; /* register base */
1423 unsigned char *mem = gp->g_fbkva; /* memory base */
1424 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1425
1426 *mem = 0;
1427
1428 /* make ACL visible */
1429 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1430 WIma(ba, IMA_PORTCONTROL, 0x01);
1431
1432 *((unsigned long *)mmu) = 0;
1433 *(mem + 0x13) = 0x38;
1434
1435 *mmu = 0xff;
1436
1437 /* hide ACL */
1438 WIma(ba, IMA_PORTCONTROL, 0x00);
1439 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1440
1441 return((*mem == 0xff) ? ETW32 : ET4000);
1442 }
1443
1444
1445 static int
1446 et_getDACType(gp)
1447 struct grf_softc * gp;
1448 {
1449 unsigned char *ba = gp->g_regkva;
1450 union {
1451 int tt;
1452 char cc[4];
1453 } check;
1454
1455 /* check for Sierra SC 15025 */
1456
1457 /* We MUST do 4 HW reads to switch into command mode */
1458 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1459 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1460
1461 vgaw(ba, VDAC_XINDEX, 9);
1462 check.cc[0] = vgar(ba, VDAC_XDATA);
1463 vgaw(ba, VDAC_XINDEX, 10);
1464 check.cc[1] = vgar(ba, VDAC_XDATA);
1465 vgaw(ba, VDAC_XINDEX, 11);
1466 check.cc[2] = vgar(ba, VDAC_XDATA);
1467 vgaw(ba, VDAC_XINDEX, 12);
1468 check.cc[3] = vgar(ba, VDAC_XDATA);
1469
1470 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1471 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1472
1473 if (check.tt == 0x533ab141) {
1474 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1475 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1476
1477 /* switch to 8 bits per color */
1478 vgaw(ba, VDAC_XINDEX, 8);
1479 vgaw(ba, VDAC_XDATA, 1);
1480 /* do not shift color values */
1481 etcmap_shift = 0;
1482
1483 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1484 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1485
1486 vgaw(ba, VDAC_MASK, 0xff);
1487 return (SIERRA15025);
1488 }
1489
1490 /* check for MUSIC DAC */
1491
1492 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1493 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1494
1495 vgaw(ba, VDAC_XINDEX, 0x01);
1496 if (vgar(ba, VDAC_XDATA) == 0x01) {
1497 /* shift color values by 2 */
1498 etcmap_shift = 2;
1499
1500 vgaw(ba, VDAC_MASK, 0xff);
1501 return (MUSICDAC);
1502 }
1503
1504 /*
1505 * nothing else found, so let us pretend it is a stupid
1506 * Sierra SC 11483
1507 */
1508
1509 /* shift color values by 2 */
1510 etcmap_shift = 2;
1511
1512 vgaw(ba, VDAC_MASK, 0xff);
1513 return (SIERRA11483);
1514 }
1515
1516 #endif /* NGRFET */
1517