grf_et.c revision 1.1.4.1 1 /* $NetBSD: grf_et.c,v 1.1.4.1 1996/05/27 01:12:06 is 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 *, void *, void *));
102 void grfetattach __P((struct device *, struct device *, void *));
103 int grfetprint __P((void *, 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, match, auxp)
186 struct device *pdp;
187 void *match, *auxp;
188 {
189 #ifdef TSENGCONSOLE
190 struct cfdata *cfp = match;
191 #endif
192 struct zbus_args *zap;
193 static int regprod, fbprod;
194
195 zap = auxp;
196
197 #ifndef TSENGCONSOLE
198 if (amiga_realconfig == 0)
199 return (0);
200 #endif
201
202 /* Grab the first board we encounter as the preferred one. This will
203 * allow one board to work in a multiple Tseng board system, but not
204 * multiple boards at the same time. */
205 if (ettype == 0) {
206 switch (zap->manid) {
207 case OMNIBUS:
208 if (zap->prodid != 0)
209 return (0);
210 regprod = 0;
211 fbprod = 0;
212 break;
213 case DOMINO:
214 if (zap->prodid != 2 && zap->prodid != 1)
215 return (0);
216 regprod = 2;
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) {
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(pdp, dp, auxp)
271 struct device *pdp, *dp;
272 void *auxp;
273 {
274 static struct grf_softc congrf;
275 struct zbus_args *zap;
276 struct grf_softc *gp;
277 static char attachflag = 0;
278
279 zap = auxp;
280
281 printf("\n");
282
283 /* make sure both halves have matched */
284 if (!et_regaddr || !et_fbaddr)
285 return;
286
287 /* do all that messy console/grf stuff */
288 if (dp == NULL)
289 gp = &congrf;
290 else
291 gp = (struct grf_softc *) dp;
292
293 if (dp != NULL && congrf.g_regkva != 0) {
294 /*
295 * inited earlier, just copy (not device struct)
296 */
297 bcopy(&congrf.g_display, &gp->g_display,
298 (char *) &gp[1] - (char *) &gp->g_display);
299 } else {
300 gp->g_regkva = (volatile caddr_t) et_regaddr;
301 gp->g_fbkva = (volatile caddr_t) et_fbaddr;
302
303 gp->g_unit = GRF_ET4000_UNIT;
304 gp->g_mode = et_mode;
305 gp->g_conpri = grfet_cnprobe();
306 gp->g_flags = GF_ALIVE;
307
308 /* wakeup the board */
309 et_boardinit(gp);
310
311 #ifdef TSENGCONSOLE
312 grfet_iteinit(gp);
313 (void) et_load_mon(gp, &etconsole_mode);
314 #endif
315 }
316
317 /*
318 * attach grf (once)
319 */
320 if (amiga_config_found(cfdata, &gp->g_device, gp, grfetprint)) {
321 attachflag = 1;
322 printf("grfet: %dMB ", et_fbsize / 0x100000);
323 switch (ettype) {
324 case OMNIBUS:
325 printf("oMniBus");
326 break;
327 case DOMINO:
328 printf("Domino");
329 break;
330 case MERLIN:
331 printf("Merlin");
332 break;
333 }
334 printf(" with ");
335 switch (etctype) {
336 case ET4000:
337 printf("Tseng ET4000");
338 break;
339 case ETW32:
340 printf("Tseng ETW32");
341 break;
342 }
343 printf(" and ");
344 switch (etdtype) {
345 case SIERRA11483:
346 printf("Sierra SC11483 DAC");
347 break;
348 case SIERRA15025:
349 printf("Sierra SC15025 DAC");
350 break;
351 case MUSICDAC:
352 printf("MUSIC DAC");
353 break;
354 case MERLINDAC:
355 printf("BrookTree DAC");
356 break;
357 }
358 printf(" being used\n");
359 } else {
360 if (!attachflag)
361 printf("grfet unattached!!\n");
362 }
363 }
364
365
366 int
367 grfetprint(auxp, pnp)
368 void *auxp;
369 char *pnp;
370 {
371 if (pnp)
372 printf("ite at %s: ", pnp);
373 return (UNCONF);
374 }
375
376
377 void
378 et_boardinit(gp)
379 struct grf_softc *gp;
380 {
381 unsigned char *ba = gp->g_regkva;
382 int x;
383
384 /* wakeup board and flip passthru OFF */
385
386 RegWakeup(ba);
387 RegOnpass(ba);
388
389 if (ettype == MERLIN) {
390 /* Merlin needs some special initialisations */
391 vgaw(ba, MERLIN_SWITCH_REG, 0);
392 delay(20000);
393 vgaw(ba, MERLIN_SWITCH_REG, 8);
394 delay(20000);
395 vgaw(ba, MERLIN_SWITCH_REG, 0);
396 delay(20000);
397 vgaw(ba, MERLIN_VDAC_DATA, 1);
398
399 vgaw(ba, MERLIN_VDAC_INDEX, 0x00);
400 vgaw(ba, MERLIN_VDAC_SPRITE, 0xff);
401 vgaw(ba, MERLIN_VDAC_INDEX, 0x01);
402 vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f);
403 vgaw(ba, MERLIN_VDAC_INDEX, 0x02);
404 vgaw(ba, MERLIN_VDAC_SPRITE, 0x42);
405 vgaw(ba, MERLIN_VDAC_INDEX, 0x03);
406 vgaw(ba, MERLIN_VDAC_SPRITE, 0x00);
407
408 vgaw(ba, MERLIN_VDAC_DATA, 0);
409 }
410
411
412 /* setup initial unchanging parameters */
413
414 vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
415 vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
416 vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
417
418 WSeq(ba, SEQ_ID_RESET, 0x03);
419 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
420 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
421 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
422 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
423 /* WSeq(ba, SEQ_ID_TS_STATE_CONTROL, 0x00); */
424 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
425
426 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
427 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
428 WCrt(ba, CRT_ID_CURSOR_END, 0x08);
429 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
430 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
431 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
432 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
433
434 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
435 WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
436 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
437 /* ET4000 special */
438 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
439 WCrt(ba, CTR_ID_EXT_START, 0x00);
440 WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
441 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
442 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); /* assume ZorroII first */
443
444 if (iszthreepa(ba)) {
445 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) |
446 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24 )
447 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* ZorroIII */
448 }
449
450 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
451
452 WGfx(ba, GCT_ID_SET_RESET, 0x00);
453 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
454 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
455 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
456 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
457 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
458 WGfx(ba, GCT_ID_MISC, 0x01);
459 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
460 WGfx(ba, GCT_ID_BITMASK, 0xff);
461
462 vgaw(ba, GREG_SEGMENTSELECT, 0x00);
463
464 for (x = 0; x < 0x10; x++)
465 WAttr(ba, x, x);
466 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
467 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
468 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
469 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
470 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
471 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
472
473 vgaw(ba, VDAC_MASK, 0xff);
474 delay(200000);
475 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
476
477 /* colors initially set to greyscale */
478
479 switch(ettype) {
480 case MERLIN:
481 vgaw(ba, MERLIN_VDAC_INDEX, 0);
482 for (x = 255; x >= 0; x--) {
483 vgaw(ba, MERLIN_VDAC_COLORS, x);
484 vgaw(ba, MERLIN_VDAC_COLORS, x);
485 vgaw(ba, MERLIN_VDAC_COLORS, x);
486 }
487 break;
488 default:
489 vgaw(ba, VDAC_ADDRESS_W, 0);
490 for (x = 255; x >= 0; x--) {
491 vgaw(ba, VDAC_DATA, x);
492 vgaw(ba, VDAC_DATA, x);
493 vgaw(ba, VDAC_DATA, x);
494 }
495 break;
496 }
497 /* set sprite bitmap pointers */
498 /* should work like that */
499 et_cursprite.image = et_imageptr;
500 et_cursprite.mask = et_maskptr;
501 et_cursprite.cmap.red = et_sprred;
502 et_cursprite.cmap.green = et_sprgreen;
503 et_cursprite.cmap.blue = et_sprblue;
504
505 /* card spezific initialisations */
506 switch(ettype) {
507 case OMNIBUS:
508 etctype=et_getControllerType(gp);
509 etdtype=et_getDACType(gp);
510 break;
511 case MERLIN:
512 etctype=ETW32;
513 etdtype=MERLINDAC;
514 break;
515 case DOMINO:
516 etctype=ET4000;
517 etdtype=SIERRA11483;
518 break;
519 }
520 }
521
522
523 int
524 et_getvmode(gp, vm)
525 struct grf_softc *gp;
526 struct grfvideo_mode *vm;
527 {
528 struct grfvideo_mode *gv;
529
530 #ifdef TSENGCONSOLE
531 /* Handle grabbing console mode */
532 if (vm->mode_num == 255) {
533 bcopy(&etconsole_mode, vm, sizeof(struct grfvideo_mode));
534 /* XXX so grfconfig can tell us the correct text dimensions. */
535 vm->depth = etconsole_mode.fy;
536 } else
537 #endif
538 {
539 if (vm->mode_num == 0)
540 vm->mode_num = (monitor_current - monitor_def) + 1;
541 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
542 return (EINVAL);
543 gv = monitor_def + (vm->mode_num - 1);
544 if (gv->mode_num == 0)
545 return (EINVAL);
546
547 bcopy(gv, vm, sizeof(struct grfvideo_mode));
548 }
549
550 /* adjust internal values to pixel values */
551
552 vm->hblank_start *= 8;
553 vm->hblank_stop *= 8;
554 vm->hsync_start *= 8;
555 vm->hsync_stop *= 8;
556 vm->htotal *= 8;
557
558 return (0);
559 }
560
561
562 int
563 et_setvmode(gp, mode)
564 struct grf_softc *gp;
565 unsigned mode;
566 {
567 if (!mode || (mode > monitor_def_max) ||
568 monitor_def[mode - 1].mode_num == 0)
569 return (EINVAL);
570
571 monitor_current = monitor_def + (mode - 1);
572
573 return (0);
574 }
575
576
577 #ifndef TSENGCONSOLE
578 void
579 et_off(gp)
580 struct grf_softc *gp;
581 {
582 char *ba = gp->g_regkva;
583
584 RegOnpass(ba);
585 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
586 }
587 #endif
588
589
590 int
591 et_blank(gp, on)
592 struct grf_softc *gp;
593 int *on;
594 {
595 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? 0x21 : 0x01);
596 return(0);
597 }
598
599
600 /*
601 * Change the mode of the display.
602 * Return a UNIX error number or 0 for success.
603 */
604 int
605 et_mode(gp, cmd, arg, a2, a3)
606 register struct grf_softc *gp;
607 u_long cmd;
608 void *arg;
609 u_long a2;
610 int a3;
611 {
612 int error;
613
614 switch (cmd) {
615 case GM_GRFON:
616 error = et_load_mon(gp,
617 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
618 return (error);
619
620 case GM_GRFOFF:
621 #ifndef TSENGCONSOLE
622 et_off(gp);
623 #else
624 et_load_mon(gp, &etconsole_mode);
625 #endif
626 return (0);
627
628 case GM_GRFCONFIG:
629 return (0);
630
631 case GM_GRFGETVMODE:
632 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
633
634 case GM_GRFSETVMODE:
635 error = et_setvmode(gp, *(unsigned *) arg);
636 if (!error && (gp->g_flags & GF_GRFON))
637 et_load_mon(gp,
638 (struct grfettext_mode *) monitor_current);
639 return (error);
640
641 case GM_GRFGETNUMVM:
642 *(int *) arg = monitor_def_max;
643 return (0);
644
645 case GM_GRFIOCTL:
646 return (et_ioctl(gp, a2, arg));
647
648 default:
649 break;
650 }
651
652 return (EINVAL);
653 }
654
655 int
656 et_ioctl(gp, cmd, data)
657 register struct grf_softc *gp;
658 u_long cmd;
659 void *data;
660 {
661 switch (cmd) {
662 case GRFIOCGSPRITEPOS:
663 return (et_getmousepos(gp, (struct grf_position *) data));
664
665 case GRFIOCSSPRITEPOS:
666 return (et_setmousepos(gp, (struct grf_position *) data));
667
668 case GRFIOCSSPRITEINF:
669 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
670
671 case GRFIOCGSPRITEINF:
672 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
673
674 case GRFIOCGSPRITEMAX:
675 return (et_getspritemax(gp, (struct grf_position *) data));
676
677 case GRFIOCGETCMAP:
678 return (et_getcmap(gp, (struct grf_colormap *) data));
679
680 case GRFIOCPUTCMAP:
681 return (et_putcmap(gp, (struct grf_colormap *) data));
682
683 case GRFIOCBITBLT:
684 break;
685
686 case GRFTOGGLE:
687 return (et_toggle(gp, 0));
688
689 case GRFIOCSETMON:
690 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
691
692 case GRFIOCBLANK:
693 return (et_blank(gp, (int *)data));
694 }
695 return (EINVAL);
696 }
697
698
699 int
700 et_getmousepos(gp, data)
701 struct grf_softc *gp;
702 struct grf_position *data;
703 {
704 data->x = et_cursprite.pos.x;
705 data->y = et_cursprite.pos.y;
706 return (0);
707 }
708
709
710 void
711 et_writesprpos(ba, x, y)
712 volatile char *ba;
713 short x;
714 short y;
715 {
716 }
717
718
719 int
720 et_setmousepos(gp, data)
721 struct grf_softc *gp;
722 struct grf_position *data;
723 {
724 volatile char *ba = gp->g_regkva;
725 short rx, ry, prx, pry;
726
727 /* no movement */
728 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
729 return (0);
730
731 /* current and previous real coordinates */
732 rx = data->x - et_cursprite.hot.x;
733 ry = data->y - et_cursprite.hot.y;
734 prx = et_cursprite.pos.x - et_cursprite.hot.x;
735 pry = et_cursprite.pos.y - et_cursprite.hot.y;
736
737 /* if we are/were on an edge, create (un)shifted bitmap --
738 * ripped out optimization (not extremely worthwhile,
739 * and kind of buggy anyhow).
740 */
741
742 /* do movement, save position */
743 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
744 et_cursprite.pos.x = data->x;
745 et_cursprite.pos.y = data->y;
746
747 return (0);
748 }
749
750
751 int
752 et_getspriteinfo(gp, data)
753 struct grf_softc *gp;
754 struct grf_spriteinfo *data;
755 {
756
757 return(EINVAL);
758 }
759
760
761 static int
762 et_setspriteinfo(gp, data)
763 struct grf_softc *gp;
764 struct grf_spriteinfo *data;
765 {
766
767 return(EINVAL);
768 }
769
770
771 static int
772 et_getspritemax(gp, data)
773 struct grf_softc *gp;
774 struct grf_position *data;
775 {
776
777 return(EINVAL);
778 }
779
780
781 int
782 et_setmonitor(gp, gv)
783 struct grf_softc *gp;
784 struct grfvideo_mode *gv;
785 {
786 struct grfvideo_mode *md;
787
788 if (!et_mondefok(gv))
789 return(EINVAL);
790
791 #ifdef TSENGCONSOLE
792 /* handle interactive setting of console mode */
793 if (gv->mode_num == 255) {
794 bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode));
795 etconsole_mode.gv.hblank_start /= 8;
796 etconsole_mode.gv.hblank_stop /= 8;
797 etconsole_mode.gv.hsync_start /= 8;
798 etconsole_mode.gv.hsync_stop /= 8;
799 etconsole_mode.gv.htotal /= 8;
800 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
801 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
802 if (!(gp->g_flags & GF_GRFON))
803 et_load_mon(gp, &etconsole_mode);
804 ite_reinit(gp->g_itedev);
805 return (0);
806 }
807 #endif
808
809 md = monitor_def + (gv->mode_num - 1);
810 bcopy(gv, md, sizeof(struct grfvideo_mode));
811
812 /* adjust pixel oriented values to internal rep. */
813
814 md->hblank_start /= 8;
815 md->hblank_stop /= 8;
816 md->hsync_start /= 8;
817 md->hsync_stop /= 8;
818 md->htotal /= 8;
819
820 return (0);
821 }
822
823
824 int
825 et_getcmap(gfp, cmap)
826 struct grf_softc *gfp;
827 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->index + cmap->count > 256)
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_W, cmap->index);
859 do {
860 *rp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
861 *gp++ = vgar(ba, VDAC_DATA) << etcmap_shift;
862 *bp++ = vgar(ba, VDAC_DATA) << 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(gfp, cmap)
879 struct grf_softc *gfp;
880 struct grf_colormap *cmap;
881 {
882 volatile unsigned char *ba;
883 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
884 short x;
885 int error;
886
887 if (cmap->count == 0 || cmap->index >= 256)
888 return (0);
889
890 if (cmap->index + cmap->count > 256)
891 cmap->count = 256 - cmap->index;
892
893 /* first copy the colors into kernelspace */
894 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
895 return (error);
896
897 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
898 return (error);
899
900 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
901 return (error);
902
903 ba = gfp->g_regkva;
904 x = cmap->count - 1;
905
906 rp = red + cmap->index;
907 gp = green + cmap->index;
908 bp = blue + cmap->index;
909
910 switch(ettype){
911 case MERLIN:
912 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
913 do {
914 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
915 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
916 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
917 } while (x-- > 0);
918 break;
919 default:
920 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
921 do {
922 vgaw(ba, VDAC_DATA, *rp++ >> etcmap_shift);
923 vgaw(ba, VDAC_DATA, *gp++ >> etcmap_shift);
924 vgaw(ba, VDAC_DATA, *bp++ >> etcmap_shift);
925 } while (x-- > 0);
926 break;
927 }
928
929 return (0);
930 }
931
932
933 int
934 et_toggle(gp, wopp)
935 struct grf_softc *gp;
936 unsigned short 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 #define ET_NUMCLOCKS 32
951
952 static u_char et_clocks[ET_NUMCLOCKS] = {
953 0, 1, 6, 2, 3, 7, 4, 5,
954 0, 1, 6, 2, 3, 7, 4, 5,
955 0, 1, 6, 2, 3, 7, 4, 5,
956 0, 1, 6, 2, 3, 7, 4, 5
957 };
958
959 static u_char et_clockdividers[ET_NUMCLOCKS] = {
960 3, 3, 3, 3, 3, 3, 3, 3,
961 2, 2, 2, 2, 2, 2, 2, 2,
962 1, 1, 1, 1, 1, 1, 1, 1,
963 0, 0, 0, 0, 0, 0, 0, 0
964 };
965
966 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
967 6293750, 7080500, 7875000, 8125000,
968 9000000, 9375000, 10000000, 11225000,
969 12587500, 14161000, 15750000, 16250000,
970 18000000, 18750000, 20000000, 22450000,
971 25175000, 28322000, 31500000, 32500000,
972 36000000, 37500000, 40000000, 44900000,
973 50350000, 56644000, 63000000, 65000000,
974 72000000, 75000000, 80000000, 89800000
975 };
976
977
978 static void
979 et_CompFQ(fq, num, denom)
980 u_int fq;
981 u_char *num;
982 u_char *denom;
983 {
984 int i;
985
986 for (i=0; i < ET_NUMCLOCKS;) {
987 if (fq <= et_clockfreqs[i++]) {
988 break;
989 }
990 }
991
992 *num = et_clocks[--i];
993 *denom = et_clockdividers[i];
994
995 return;
996 }
997
998
999 int
1000 et_mondefok(gv)
1001 struct grfvideo_mode *gv;
1002 {
1003
1004 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1005 if (gv->mode_num != 255 || gv->depth != 4)
1006 return(0);
1007
1008 switch (gv->depth) {
1009 case 4:
1010 if (gv->mode_num != 255)
1011 return(0);
1012 case 1:
1013 case 8:
1014 case 15:
1015 case 16:
1016 case 24:
1017 break;
1018 default:
1019 return (0);
1020 }
1021 return (1);
1022 }
1023
1024
1025 int
1026 et_load_mon(gp, md)
1027 struct grf_softc *gp;
1028 struct grfettext_mode *md;
1029 {
1030 struct grfvideo_mode *gv;
1031 struct grfinfo *gi;
1032 volatile unsigned char *ba;
1033 unsigned char num0, denom0;
1034 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1035 VSE, VT;
1036 char LACE, DBLSCAN, TEXT;
1037 unsigned char seq;
1038 int uplim, lowlim;
1039
1040 /* identity */
1041 gv = &md->gv;
1042 TEXT = (gv->depth == 4);
1043
1044 if (!et_mondefok(gv)) {
1045 printf("mondef not ok\n");
1046 return (0);
1047 }
1048 ba = gp->g_regkva;
1049
1050 /* provide all needed information in grf device-independant locations */
1051 gp->g_data = (caddr_t) gv;
1052 gi = &gp->g_display;
1053 gi->gd_regaddr = (caddr_t) ztwopa(ba);
1054 gi->gd_regsize = 64 * 1024;
1055 gi->gd_fbaddr = (caddr_t) kvtop(gp->g_fbkva);
1056 gi->gd_fbsize = et_fbsize;
1057 gi->gd_colors = 1 << gv->depth;
1058 gi->gd_planes = gv->depth;
1059 gi->gd_fbwidth = gv->disp_width;
1060 gi->gd_fbheight = gv->disp_height;
1061 gi->gd_fbx = 0;
1062 gi->gd_fby = 0;
1063 if (TEXT) {
1064 gi->gd_dwidth = md->fx * md->cols;
1065 gi->gd_dheight = md->fy * md->rows;
1066 } else {
1067 gi->gd_dwidth = gv->disp_width;
1068 gi->gd_dheight = gv->disp_height;
1069 }
1070 gi->gd_dx = 0;
1071 gi->gd_dy = 0;
1072
1073 /* get display mode parameters */
1074
1075 HBS = gv->hblank_start;
1076 HBE = gv->hblank_stop;
1077 HSS = gv->hsync_start;
1078 HSE = gv->hsync_stop;
1079 HT = gv->htotal;
1080 VBS = gv->vblank_start;
1081 VSS = gv->vsync_start;
1082 VSE = gv->vsync_stop;
1083 VBE = gv->vblank_stop;
1084 VT = gv->vtotal;
1085
1086 if (TEXT)
1087 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1088 else
1089 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1090 VDE = gv->disp_height - 1;
1091
1092 /* figure out whether lace or dblscan is needed */
1093
1094 uplim = gv->disp_height + (gv->disp_height / 4);
1095 lowlim = gv->disp_height - (gv->disp_height / 4);
1096 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1097 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1098
1099 /* adjustments */
1100
1101 if (LACE)
1102 VDE /= 2;
1103
1104 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1105
1106 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1107 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1108 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1109
1110 /* Set clock */
1111
1112 et_CompFQ( gv->pixel_clock, &num0, &denom0);
1113
1114 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2));
1115 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1116 seq=RSeq(ba, SEQ_ID_CLOCKING_MODE);
1117 switch(denom0) {
1118 case 0:
1119 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1120 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1121 break;
1122 case 1:
1123 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1124 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1125 break;
1126 case 2:
1127 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1128 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1129 break;
1130 case 3:
1131 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1132 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1133 break;
1134 }
1135 /* load display parameters into board */
1136
1137 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1138 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1139 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1140 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1141 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1142 WCrt(ba, CRT_ID_END_HOR_RETR,
1143 (HSE & 0x1f) |
1144 ((HBE & 0x20) ? 0x80 : 0x00));
1145 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1146 WCrt(ba, CRT_ID_OVERFLOW,
1147 0x10 |
1148 ((VT & 0x100) ? 0x01 : 0x00) |
1149 ((VDE & 0x100) ? 0x02 : 0x00) |
1150 ((VSS & 0x100) ? 0x04 : 0x00) |
1151 ((VBS & 0x100) ? 0x08 : 0x00) |
1152 ((VT & 0x200) ? 0x20 : 0x00) |
1153 ((VDE & 0x200) ? 0x40 : 0x00) |
1154 ((VSS & 0x200) ? 0x80 : 0x00));
1155
1156 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1157 0x40 | /* TEXT ? 0x00 ??? */
1158 (DBLSCAN ? 0x80 : 0x00) |
1159 ((VBS & 0x200) ? 0x20 : 0x00) |
1160 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1161
1162 WCrt(ba, CRT_ID_MODE_CONTROL,
1163 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1164
1165 /* text cursor */
1166
1167 if (TEXT) {
1168 #if ET_ULCURSOR
1169 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1170 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1171 #else
1172 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1173 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1174 #endif
1175 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1176 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1177 }
1178
1179 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1180 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1181
1182 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1183 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1184
1185 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1186 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1187 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1188 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1189 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1190
1191 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1192
1193 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1194 ((VBS & 0x400) ? 0x01 : 0x00) |
1195 ((VT & 0x400) ? 0x02 : 0x00) |
1196 ((VDE & 0x400) ? 0x04 : 0x00) |
1197 ((VSS & 0x400) ? 0x08 : 0x00) |
1198 0x10 |
1199 (LACE ? 0x80 : 0x00));
1200
1201 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1202 ((HT & 0x100) ? 0x01 : 0x00) |
1203 ((HBS & 0x100) ? 0x04 : 0x00) |
1204 ((HSS & 0x100) ? 0x10 : 0x00)
1205 );
1206
1207 /* depth dependent stuff */
1208
1209 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1210 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1211 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1212
1213 vgaw(ba, VDAC_MASK, 0xff);
1214 vgar(ba, VDAC_MASK);
1215 vgar(ba, VDAC_MASK);
1216 vgar(ba, VDAC_MASK);
1217 vgar(ba, VDAC_MASK);
1218 switch (gv->depth) {
1219 case 1:
1220 case 4: /* text */
1221 switch(etdtype) {
1222 case SIERRA11483:
1223 case SIERRA15025:
1224 case MUSICDAC:
1225 vgaw(ba, VDAC_MASK, 0);
1226 break;
1227 case MERLINDAC:
1228 setMerlinDACmode(ba, 0);
1229 break;
1230 }
1231 HDE = gv->disp_width / 16;
1232 break;
1233 case 8:
1234 switch(etdtype) {
1235 case SIERRA11483:
1236 case SIERRA15025:
1237 case MUSICDAC:
1238 vgaw(ba, VDAC_MASK, 0);
1239 break;
1240 case MERLINDAC:
1241 setMerlinDACmode(ba, 0);
1242 break;
1243 }
1244 HDE = gv->disp_width / 8;
1245 break;
1246 case 15:
1247 switch(etdtype) {
1248 case SIERRA11483:
1249 case SIERRA15025:
1250 case MUSICDAC:
1251 vgaw(ba, VDAC_MASK, 0xa0);
1252 break;
1253 case MERLINDAC:
1254 setMerlinDACmode(ba, 0xa0);
1255 break;
1256 }
1257 HDE = gv->disp_width / 4;
1258 break;
1259 case 16:
1260 switch(etdtype) {
1261 case SIERRA11483:
1262 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1263 break;
1264 case SIERRA15025:
1265 vgaw(ba, VDAC_MASK, 0xe0);
1266 break;
1267 case MUSICDAC:
1268 vgaw(ba, VDAC_MASK, 0xc0);
1269 break;
1270 case MERLINDAC:
1271 setMerlinDACmode(ba, 0xe0);
1272 break;
1273 }
1274 HDE = gv->disp_width / 4;
1275 break;
1276 case 24:
1277 switch(etdtype) {
1278 case SIERRA11483:
1279 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1280 break;
1281 case SIERRA15025:
1282 vgaw(ba, VDAC_MASK, 0xe1);
1283 break;
1284 case MUSICDAC:
1285 vgaw(ba, VDAC_MASK, 0xe0);
1286 break;
1287 case MERLINDAC:
1288 setMerlinDACmode(ba, 0xf0);
1289 break;
1290 }
1291 HDE = (gv->disp_width / 8) * 3;
1292 break;
1293 case 32:
1294 switch(etdtype) {
1295 case SIERRA11483:
1296 case MUSICDAC:
1297 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1298 break;
1299 case SIERRA15025:
1300 vgaw(ba, VDAC_MASK, 0x61);
1301 break;
1302 case MERLINDAC:
1303 setMerlinDACmode(ba, 0xb0);
1304 break;
1305 }
1306 HDE = gv->disp_width / 2;
1307 break;
1308 }
1309 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1310 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1311 (gv->depth == 1) ? 0x01 : 0x0f);
1312
1313 WCrt(ba, CRT_ID_OFFSET, HDE);
1314
1315 /* text initialization */
1316 if (TEXT) {
1317 et_inittextmode(gp);
1318 }
1319
1320 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1321
1322 /* Pass-through */
1323 RegOffpass(ba);
1324
1325 return (1);
1326 }
1327
1328
1329 void
1330 et_inittextmode(gp)
1331 struct grf_softc *gp;
1332 {
1333 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1334 volatile unsigned char *ba = gp->g_regkva;
1335 unsigned char *fb = gp->g_fbkva;
1336 unsigned char *c, *f, y;
1337 unsigned short z;
1338
1339
1340 /*
1341 * load text font into beginning of display memory. Each character
1342 * cell is 32 bytes long (enough for 4 planes)
1343 */
1344
1345 SetTextPlane(ba, 0x02);
1346 et_memset(fb, 0, 256 * 32);
1347 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1348 f = tm->fdata;
1349 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1350 for (y = 0; y < tm->fy; y++)
1351 *c++ = *f++;
1352
1353 /* clear out text/attr planes (three screens worth) */
1354
1355 SetTextPlane(ba, 0x01);
1356 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1357 SetTextPlane(ba, 0x00);
1358 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1359
1360 /* print out a little init msg */
1361
1362 c = (unsigned char *) (fb) + (tm->cols - 16);
1363 strcpy(c, "TSENG");
1364 c[6] = 0x20;
1365
1366 /* set colors (B&W) */
1367
1368 switch(ettype) {
1369 case MERLIN:
1370 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1371 for (z = 0; z < 256; z++) {
1372 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1373
1374 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1375 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1376 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1377 }
1378 break;
1379 default:
1380 vgaw(ba, VDAC_ADDRESS_W, 0);
1381 for (z = 0; z < 256; z++) {
1382 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1383
1384 vgaw(ba, VDAC_DATA, etconscolors[y][0] >> etcmap_shift);
1385 vgaw(ba, VDAC_DATA, etconscolors[y][1] >> etcmap_shift);
1386 vgaw(ba, VDAC_DATA, etconscolors[y][2] >> etcmap_shift);
1387 }
1388 break;
1389 }
1390 }
1391
1392
1393 void
1394 et_memset(d, c, l)
1395 unsigned char *d;
1396 unsigned char c;
1397 int l;
1398 {
1399 for (; l > 0; l--)
1400 *d++ = c;
1401 }
1402
1403
1404 static int
1405 et_getControllerType(gp)
1406 struct grf_softc * gp;
1407 {
1408 unsigned char *ba = gp->g_regkva; /* register base */
1409 unsigned char *mem = gp->g_fbkva; /* memory base */
1410 unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1411
1412 *mem = 0;
1413
1414 /* make ACL visible */
1415 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1416 WIma(ba, IMA_PORTCONTROL, 0x01);
1417
1418 *((unsigned long *)mmu) = 0;
1419 *(mem + 0x13) = 0x38;
1420
1421 *mmu = 0xff;
1422
1423 /* hide ACL */
1424 WIma(ba, IMA_PORTCONTROL, 0x00);
1425 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1426
1427 return((*mem == 0xff) ? ETW32 : ET4000);
1428 }
1429
1430
1431 static int
1432 et_getDACType(gp)
1433 struct grf_softc * gp;
1434 {
1435 unsigned char *ba = gp->g_regkva;
1436 union {
1437 int tt;
1438 char cc[4];
1439 } check;
1440
1441 /* check for Sierra SC 15025 */
1442
1443 if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
1444 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1445
1446 vgaw(ba, VDAC_XINDEX, 9);
1447 check.cc[0]=vgar(ba, VDAC_XDATA);
1448 vgaw(ba, VDAC_XINDEX, 10);
1449 check.cc[1]=vgar(ba, VDAC_XDATA);
1450 vgaw(ba, VDAC_XINDEX, 11);
1451 check.cc[2]=vgar(ba, VDAC_XDATA);
1452 vgaw(ba, VDAC_XINDEX, 12);
1453 check.cc[3]=vgar(ba, VDAC_XDATA);
1454
1455 if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
1456 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1457
1458 if(check.tt == 0x533ab141){
1459 if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
1460 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1461
1462 /* switch to 8 bits per color */
1463 vgaw(ba, VDAC_XINDEX, 8);
1464 vgaw(ba, VDAC_XDATA, 1);
1465 /* do not shift color values */
1466 etcmap_shift = 0;
1467
1468 if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR)); if(vgar(ba, HDR));
1469 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1470
1471 vgaw(ba, VDAC_MASK, 0xff);
1472 return(SIERRA15025);
1473 }
1474
1475 /* check for MUSIC DAC */
1476
1477 if(vgar(ba, HDR)); /* We MUST do 4 HW reads to switch into command mode */
1478 if(vgar(ba, HDR));
1479 if(vgar(ba, HDR));
1480 if(vgar(ba, HDR));
1481
1482 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1483
1484 vgaw(ba, VDAC_XINDEX, 0x01);
1485 if(vgar(ba, VDAC_XDATA) == 0x01){
1486 /* shift color values by 2 */
1487 etcmap_shift = 2;
1488
1489 vgaw(ba, VDAC_MASK, 0xff);
1490 return(MUSICDAC);
1491 }
1492
1493 /*
1494 * nothing else found, so let us pretend it is a stupid
1495 * Sierra SC 11483
1496 */
1497
1498 /* shift color values by 2 */
1499 etcmap_shift = 2;
1500
1501 vgaw(ba, VDAC_MASK, 0xff);
1502 return(SIERRA11483);
1503 }
1504
1505 #endif /* NGRFET */
1506