grf_et.c revision 1.33 1 /* $NetBSD: grf_et.c,v 1.33 2016/11/04 18:06:08 phx 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.33 2016/11/04 18:06:08 phx Exp $");
41
42 #include "grfet.h"
43 #include "ite.h"
44 #include "wsdisplay.h"
45 #if NGRFET > 0
46
47 /*
48 * Graphics routines for Tseng ET4000 (&W32) boards,
49 *
50 * This code offers low-level routines to access Tseng ET4000
51 * graphics-boards from within NetBSD for the Amiga.
52 * No warranties for any kind of function at all - this
53 * code may crash your hardware and scratch your harddisk. Use at your
54 * own risk. Freely distributable.
55 *
56 * Modified for Tseng ET4000 from
57 * Kari Mettinen's Cirrus driver by Tobias Abt
58 *
59 * Fixed Merlin in Z-III, fixed LACE and DBLSCAN, added Domino16M proto
60 * and AT&T ATT20c491 DAC, added memory-size detection by Klaus Burkert.
61 *
62 *
63 * TODO:
64 *
65 */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/errno.h>
70 #include <sys/ioctl.h>
71 #include <sys/device.h>
72 #include <sys/malloc.h>
73
74 #include <machine/cpu.h>
75 #include <dev/cons.h>
76 #if NWSDISPLAY > 0
77 #include <dev/wscons/wsconsio.h>
78 #include <dev/wscons/wsdisplayvar.h>
79 #include <dev/rasops/rasops.h>
80 #include <dev/wscons/wsdisplay_vconsvar.h>
81 #endif
82 #ifdef TSENGCONSOLE
83 #include <amiga/dev/itevar.h>
84 #endif
85 #include <amiga/amiga/device.h>
86 #include <amiga/dev/grfioctl.h>
87 #include <amiga/dev/grfvar.h>
88 #include <amiga/dev/grf_etreg.h>
89 #include <amiga/dev/zbusvar.h>
90
91 int et_mondefok(struct grfvideo_mode *);
92 void et_boardinit(struct grf_softc *);
93 static void et_CompFQ(u_int fq, u_char *, u_char *);
94 int et_getvmode(struct grf_softc *, struct grfvideo_mode *);
95 int et_setvmode(struct grf_softc *, unsigned int);
96 int et_toggle(struct grf_softc *, unsigned short);
97 int et_getcmap(struct grf_softc *, struct grf_colormap *);
98 int et_putcmap(struct grf_softc *, struct grf_colormap *);
99 #ifndef TSENGCONSOLE
100 void et_off(struct grf_softc *);
101 #endif
102 void et_inittextmode(struct grf_softc *);
103 int et_ioctl(register struct grf_softc *, u_long cmd, void *);
104 int et_getmousepos(struct grf_softc *, struct grf_position *);
105 void et_writesprpos(volatile char *ba, short, short);
106 int et_setmousepos(struct grf_softc *, struct grf_position *);
107 static int et_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
108 int et_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
109 static int et_getspritemax(struct grf_softc *, struct grf_position *);
110 int et_setmonitor(struct grf_softc *, struct grfvideo_mode *);
111 int et_blank(struct grf_softc *, int);
112 int et_isblank(struct grf_softc *);
113 static int et_getControllerType(struct grf_softc *);
114 static int et_getDACType(struct grf_softc *);
115
116 int grfetmatch(device_t, cfdata_t, void *);
117 void grfetattach(device_t, device_t, void *);
118 int grfetprint(void *, const char *);
119 void et_memset(volatile unsigned char *, unsigned char, int);
120
121 #if NWSDISPLAY > 0
122 /* wsdisplay acessops, emulops */
123 static int et_wsioctl(void *, void *, u_long, void *, int, struct lwp *);
124 static int et_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *);
125
126 static void et_wscursor(void *, int, int, int);
127 static void et_wsputchar(void *, int, int, u_int, long);
128 static void et_wscopycols(void *, int, int, int, int);
129 static void et_wserasecols(void *, int, int, int, long);
130 static void et_wscopyrows(void *, int, int, int);
131 static void et_wseraserows(void *, int, int, long);
132 static int et_wsallocattr(void *, int, int, int, long *);
133 static int et_wsmapchar(void *, int, unsigned int *);
134 #endif /* NWSDISPLAY > 0 */
135
136 /*
137 * Graphics display definitions.
138 * These are filled by 'grfconfig' using GRFIOCSETMON.
139 */
140 #define monitor_def_max 24
141 static struct grfvideo_mode monitor_def[24] = {
142 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
143 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
144 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
145 };
146 static struct grfvideo_mode *monitor_current = &monitor_def[0];
147
148 /* Console display definition.
149 * Default hardcoded text mode. This grf_et is set up to
150 * use one text mode only, and this is it. You may use
151 * grfconfig to change the mode after boot.
152 */
153 /* Console font */
154 #ifdef KFONT_8X11
155 #define TSENGFONT kernel_font_8x11
156 #define TSENGFONTY 11
157 #else
158 #define TSENGFONT kernel_font_8x8
159 #define TSENGFONTY 8
160 #endif
161 extern unsigned char TSENGFONT[];
162
163 struct grfettext_mode etconsole_mode = {
164 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8,
165 481, 491, 493, 525, 0},
166 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255
167 };
168
169 /* Console colors */
170 unsigned char etconscolors[3][3] = { /* background, foreground, hilite */
171 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
172 };
173
174 int ettype = 0; /* oMniBus, Domino or Merlin */
175 int etctype = 0; /* ET4000 or ETW32 */
176 int etdtype = 0; /* Type of DAC (see grf_etregs.h) */
177
178 char etcmap_shift = 0; /* 6 or 8 bit cmap entries */
179 unsigned char pass_toggle; /* passthru status tracker */
180
181 unsigned char Merlin_switch = 0;
182
183 /*
184 * Because all Tseng-boards have 2 configdev entries, one for
185 * framebuffer mem and the other for regs, we have to hold onto
186 * the pointers globally until we match on both. This and 'ettype'
187 * are the primary obsticles to multiple board support, but if you
188 * have multiple boards you have bigger problems than grf_et.
189 */
190 static void *et_fbaddr = 0; /* framebuffer */
191 static void *et_regaddr = 0; /* registers */
192 static int et_fbsize; /* framebuffer size */
193
194 /* current sprite info, if you add support for multiple boards
195 * make this an array or something
196 */
197 struct grf_spriteinfo et_cursprite;
198
199 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
200 * you add multiple board support
201 */
202 static unsigned char et_imageptr[8 * 64], et_maskptr[8 * 64];
203 static unsigned char et_sprred[2], et_sprgreen[2], et_sprblue[2];
204
205 #if NWSDISPLAY > 0
206 static struct wsdisplay_accessops et_accessops = {
207 .ioctl = et_wsioctl,
208 .mmap = grf_wsmmap
209 };
210
211 static struct wsdisplay_emulops et_textops = {
212 .cursor = et_wscursor,
213 .mapchar = et_wsmapchar,
214 .putchar = et_wsputchar,
215 .copycols = et_wscopycols,
216 .erasecols = et_wserasecols,
217 .copyrows = et_wscopyrows,
218 .eraserows = et_wseraserows,
219 .allocattr = et_wsallocattr
220 };
221
222 static struct wsscreen_descr et_defaultscreen = {
223 .name = "default",
224 .textops = &et_textops,
225 .fontwidth = 8,
226 .fontheight = TSENGFONTY,
227 .capabilities = WSSCREEN_HILIT | WSSCREEN_BLINK |
228 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
229 };
230
231 static const struct wsscreen_descr *et_screens[] = {
232 &et_defaultscreen,
233 };
234
235 static struct wsscreen_list et_screenlist = {
236 sizeof(et_screens) / sizeof(struct wsscreen_descr *), et_screens
237 };
238 #endif /* NWSDISPLAY > 0 */
239
240 /* standard driver stuff */
241 CFATTACH_DECL_NEW(grfet, sizeof(struct grf_softc),
242 grfetmatch, grfetattach, NULL, NULL);
243
244 static struct cfdata *cfdata;
245
246 int
247 grfetmatch(device_t parent, cfdata_t cf, void *aux)
248 {
249 struct zbus_args *zap;
250 static int regprod, regprod2 = 0, fbprod;
251
252 zap = aux;
253
254 #ifndef TSENGCONSOLE
255 if (amiga_realconfig == 0)
256 return (0);
257 #endif
258
259 /* Grab the first board we encounter as the preferred one. This will
260 * allow one board to work in a multiple Tseng board system, but not
261 * multiple boards at the same time. */
262 if (ettype == 0) {
263 switch (zap->manid) {
264 case OMNIBUS:
265 if (zap->prodid != 0)
266 return (0);
267 regprod = 0;
268 fbprod = 0;
269 break;
270 case DOMINO:
271 /* 2167/3 is Domino16M proto (crest) */
272 if (zap->prodid != 3 && zap->prodid != 2 && zap->prodid != 1)
273 return (0);
274 regprod = 2;
275 regprod2 = 3;
276 fbprod = 1;
277 break;
278 case MERLIN:
279 if (zap->prodid != 3 && zap->prodid != 4)
280 return (0);
281 regprod = 4;
282 fbprod = 3;
283 break;
284 default:
285 return (0);
286 }
287 ettype = zap->manid;
288 } else {
289 if (ettype != zap->manid) {
290 return (0);
291 }
292 }
293
294 /* Configure either registers or framebuffer in any order */
295 /* as said before, oMniBus does not support ProdID */
296 if (ettype == OMNIBUS) {
297 if (zap->size == 64 * 1024) {
298 /* register area */
299 et_regaddr = zap->va;
300 } else {
301 /* memory area */
302 et_fbaddr = zap->va;
303 et_fbsize = zap->size;
304 }
305 } else {
306 if (zap->prodid == regprod || zap->prodid == regprod2) {
307 et_regaddr = zap->va;
308 } else {
309 if (zap->prodid == fbprod) {
310 et_fbaddr = zap->va;
311 et_fbsize = zap->size;
312 } else {
313 return (0);
314 }
315 }
316 }
317
318 #ifdef TSENGCONSOLE
319 if (amiga_realconfig == 0) {
320 cfdata = cf;
321 }
322 #endif
323
324 return (1);
325 }
326
327
328 void
329 grfetattach(device_t parent, device_t self, void *aux)
330 {
331 static struct grf_softc congrf;
332 static char attachflag = 0;
333 struct device temp;
334 struct grf_softc *gp;
335
336 printf("\n");
337
338 /* make sure both halves have matched */
339 if (!et_regaddr || !et_fbaddr)
340 return;
341
342 /* do all that messy console/grf stuff */
343 if (self == NULL) {
344 gp = &congrf;
345 gp->g_device = &temp;
346 temp.dv_private = gp;
347 } else {
348 gp = device_private(self);
349 gp->g_device = self;
350 }
351
352 if (self != NULL && congrf.g_regkva != 0) {
353 /*
354 * inited earlier, just copy (not device struct)
355 */
356 memcpy(&gp->g_display, &congrf.g_display,
357 (char *) &gp[1] - (char *) &gp->g_display);
358 } else {
359 gp->g_regkva = (volatile void *) et_regaddr;
360 gp->g_fbkva = (volatile void *) et_fbaddr;
361
362 gp->g_unit = GRF_ET4000_UNIT;
363 gp->g_mode = et_mode;
364 #if NITE > 0
365 gp->g_conpri = grfet_cnprobe();
366 #endif
367 gp->g_flags = GF_ALIVE;
368
369 /* wakeup the board */
370 et_boardinit(gp);
371
372 #ifdef TSENGCONSOLE
373 #if NWSDISPLAY > 0
374 gp->g_accessops = &et_accessops;
375 gp->g_emulops = &et_textops;
376 gp->g_defaultscr = &et_defaultscreen;
377 gp->g_scrlist = &et_screenlist;
378 #else
379 #if NITE > 0
380 grfet_iteinit(gp);
381 #endif
382 #endif /* NWSDISPLAY > 0 */
383 (void) et_load_mon(gp, &etconsole_mode);
384 #endif
385 }
386
387 /*
388 * attach grf (once)
389 */
390 if (amiga_config_found(cfdata, gp->g_device, gp, grfetprint)) {
391 attachflag = 1;
392 printf("grfet: %dMB ", et_fbsize / 0x100000);
393 switch (ettype) {
394 case OMNIBUS:
395 printf("oMniBus");
396 break;
397 case DOMINO:
398 printf("Domino");
399 break;
400 case MERLIN:
401 printf("Merlin");
402 break;
403 }
404 printf(" with ");
405 switch (etctype) {
406 case ET4000:
407 printf("Tseng ET4000");
408 break;
409 case ETW32:
410 printf("Tseng ETW32");
411 break;
412 }
413 printf(" and ");
414 switch (etdtype) {
415 case SIERRA11483:
416 printf("Sierra SC11483 DAC");
417 break;
418 case SIERRA15025:
419 printf("Sierra SC15025 DAC");
420 break;
421 case MUSICDAC:
422 printf("MUSIC DAC");
423 break;
424 case MERLINDAC:
425 printf("BrookTree Bt482 DAC");
426 break;
427 case ATT20C491:
428 printf("AT&T ATT20c491 DAC");
429 break;
430 }
431 printf(" being used\n");
432 } else {
433 if (!attachflag)
434 printf("grfet unattached!!\n");
435 }
436 }
437
438
439 int
440 grfetprint(void *aux, const char *pnp)
441 {
442 if (pnp)
443 aprint_normal("ite at %s: ", pnp);
444 return (UNCONF);
445 }
446
447
448 void
449 et_boardinit(struct grf_softc *gp)
450 {
451 volatile unsigned char *ba = gp->g_regkva;
452 int x;
453
454 /* wakeup board and flip passthru OFF */
455
456 RegWakeup(ba);
457 RegOnpass(ba);
458
459 if (ettype == MERLIN) {
460 /* Merlin needs some special initialisations */
461 vgaw(ba, MERLIN_SWITCH_REG, 0);
462 delay(20000);
463 vgaw(ba, MERLIN_SWITCH_REG, 8);
464 delay(20000);
465 vgaw(ba, MERLIN_SWITCH_REG, 0);
466 delay(20000);
467 vgaw(ba, MERLIN_VDAC_DATA, 1);
468
469 vgaw(ba, MERLIN_VDAC_INDEX, 0x00);
470 vgaw(ba, MERLIN_VDAC_SPRITE, 0xff);
471 vgaw(ba, MERLIN_VDAC_INDEX, 0x01);
472 vgaw(ba, MERLIN_VDAC_SPRITE, 0x0f);
473 vgaw(ba, MERLIN_VDAC_INDEX, 0x02);
474 vgaw(ba, MERLIN_VDAC_SPRITE, 0x42);
475 vgaw(ba, MERLIN_VDAC_INDEX, 0x03);
476 vgaw(ba, MERLIN_VDAC_SPRITE, 0x00);
477
478 vgaw(ba, MERLIN_VDAC_DATA, 0);
479 }
480
481
482 /* setup initial unchanging parameters */
483
484 vgaw(ba, GREG_HERCULESCOMPAT + ((ettype == DOMINO) ? 0x0fff : 0), 0x03);
485 vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
486 vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
487
488 if (ettype == DOMINO)
489 {
490 vgaw(ba, CRT_ADDRESS, CRT_ID_VIDEO_CONFIG1);
491 vgaw(ba, CRT_ADDRESS_W + 0x0fff,
492 0xc0 | vgar(ba, CRT_ADDRESS_R + 0x0fff));
493 }
494
495 WSeq(ba, SEQ_ID_RESET, 0x03);
496 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
497 WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
498 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
499 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
500 WSeq(ba, SEQ_ID_STATE_CONTROL, 0x00);
501 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
502
503 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
504 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
505 WCrt(ba, CRT_ID_CURSOR_END, 0x08);
506 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
507 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
508 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
509 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
510
511 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x67);
512 WCrt(ba, CRT_ID_MODE_CONTROL, 0xc3);
513 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
514
515 /* ET4000 special */
516 WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
517 WCrt(ba, CRT_ID_EXT_START, 0x00);
518 WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
519
520 /* ET4000/W32 special (currently only for Merlin (crest) */
521 if (ettype == MERLIN) {
522 WCrt(ba, CRT_ID_SEGMENT_COMP, 0x1c);
523 WCrt(ba, CRT_ID_GENERAL_PURPOSE, 0x00);
524 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93);
525 }
526 else {
527 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
528 }
529
530 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f);
531 WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
532
533 vgaw(ba, GREG_SEGMENTSELECT, 0x00);
534
535 WGfx(ba, GCT_ID_SET_RESET, 0x00);
536 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
537 WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
538 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
539 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
540 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
541 WGfx(ba, GCT_ID_MISC, 0x01);
542 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
543 WGfx(ba, GCT_ID_BITMASK, 0xff);
544
545 for (x = 0; x < 0x10; x++)
546 WAttr(ba, x, x);
547 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
548 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
549 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
550 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
551 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
552 WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
553
554 vgaw(ba, VDAC_MASK, 0xff);
555 delay(200000);
556 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3);
557
558 /* colors initially set to greyscale */
559 switch(ettype) {
560 case MERLIN:
561 vgaw(ba, MERLIN_VDAC_INDEX, 0);
562 for (x = 255; x >= 0; x--) {
563 vgaw(ba, MERLIN_VDAC_COLORS, x);
564 vgaw(ba, MERLIN_VDAC_COLORS, x);
565 vgaw(ba, MERLIN_VDAC_COLORS, x);
566 }
567 break;
568 default:
569 vgaw(ba, VDAC_ADDRESS_W, 0);
570 for (x = 255; x >= 0; x--) {
571 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
572 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
573 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), x);
574 }
575 break;
576 }
577 /* set sprite bitmap pointers */
578 /* should work like that */
579 et_cursprite.image = et_imageptr;
580 et_cursprite.mask = et_maskptr;
581 et_cursprite.cmap.red = et_sprred;
582 et_cursprite.cmap.green = et_sprgreen;
583 et_cursprite.cmap.blue = et_sprblue;
584
585 /* card specific initialisations */
586 switch(ettype) {
587 case OMNIBUS:
588 etctype = et_getControllerType(gp);
589 etdtype = et_getDACType(gp);
590 break;
591 case MERLIN:
592 vgaw(ba, GREG_SEGMENTSELECT2, 0x00);
593 if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) |
594 (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24) {
595 WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* 1Mx4 RAM */
596 et_fbsize = 0x400000; /* 4 MB */
597 }
598 else {
599 /* check for 1MB or 2MB board (crest) */
600 /* has there a 1MB Merlin ever been sold ??? */
601 volatile unsigned long *et_fbtestaddr;
602 et_fbtestaddr = (volatile unsigned long *)gp->g_fbkva;
603 *et_fbtestaddr = 0x0;
604 vgaw(ba, GREG_SEGMENTSELECT2, 0x11); /* 1MB offset */
605 *et_fbtestaddr = 0x12345678;
606 vgaw(ba, GREG_SEGMENTSELECT2, 0x00);
607 if (*et_fbtestaddr == 0x0)
608 et_fbsize = 0x200000; /* 2 MB */
609 else
610 et_fbsize = 0x100000; /* 1 MB */
611 }
612 /* ZorroII can map 2 MB max ... */
613 if (!iszthreepa(kvtop(__UNVOLATILE(gp->g_fbkva))) &&
614 et_fbsize == 0x400000)
615 et_fbsize = 0x200000;
616 etctype = ETW32;
617 etdtype = MERLINDAC;
618 break;
619 case DOMINO:
620 etctype = ET4000;
621 etdtype = et_getDACType(gp);
622 break;
623 }
624 }
625
626
627 int
628 et_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
629 {
630 struct grfvideo_mode *gv;
631
632 #ifdef TSENGCONSOLE
633 /* Handle grabbing console mode */
634 if (vm->mode_num == 255) {
635 memcpy(vm, &etconsole_mode, sizeof(struct grfvideo_mode));
636 /* XXX so grfconfig can tell us the correct text dimensions. */
637 vm->depth = etconsole_mode.fy;
638 } else
639 #endif
640 {
641 if (vm->mode_num == 0)
642 vm->mode_num = (monitor_current - monitor_def) + 1;
643 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
644 return (EINVAL);
645 gv = monitor_def + (vm->mode_num - 1);
646 if (gv->mode_num == 0)
647 return (EINVAL);
648
649 memcpy(vm, gv, sizeof(struct grfvideo_mode));
650 }
651
652 /* adjust internal values to pixel values */
653
654 vm->hblank_start *= 8;
655 vm->hsync_start *= 8;
656 vm->hsync_stop *= 8;
657 vm->htotal *= 8;
658
659 return (0);
660 }
661
662
663 int
664 et_setvmode(struct grf_softc *gp, unsigned mode)
665 {
666 if (!mode || (mode > monitor_def_max) ||
667 monitor_def[mode - 1].mode_num == 0)
668 return (EINVAL);
669
670 monitor_current = monitor_def + (mode - 1);
671
672 return (0);
673 }
674
675
676 #ifndef TSENGCONSOLE
677 void
678 et_off(struct grf_softc *gp)
679 {
680 char *ba = gp->g_regkva;
681
682 RegOnpass(ba);
683 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
684 }
685 #endif
686
687
688 int
689 et_blank(struct grf_softc *gp, int on)
690 {
691
692 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, on > 0 ? 0x01 : 0x21);
693 return 0;
694 }
695
696
697 int
698 et_isblank(struct grf_softc *gp)
699 {
700 int r;
701
702 r = RSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE);
703 return (r & 0x20) != 0;
704 }
705
706
707 /*
708 * Change the mode of the display.
709 * Return a UNIX error number or 0 for success.
710 */
711 int
712 et_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2,
713 int a3)
714 {
715 int error;
716
717 switch (cmd) {
718 case GM_GRFON:
719 error = et_load_mon(gp,
720 (struct grfettext_mode *) monitor_current) ? 0 : EINVAL;
721 return (error);
722
723 case GM_GRFOFF:
724 #ifndef TSENGCONSOLE
725 et_off(gp);
726 #else
727 et_load_mon(gp, &etconsole_mode);
728 #endif
729 return (0);
730
731 case GM_GRFCONFIG:
732 return (0);
733
734 case GM_GRFGETVMODE:
735 return (et_getvmode(gp, (struct grfvideo_mode *) arg));
736
737 case GM_GRFSETVMODE:
738 error = et_setvmode(gp, *(unsigned *) arg);
739 if (!error && (gp->g_flags & GF_GRFON))
740 et_load_mon(gp,
741 (struct grfettext_mode *) monitor_current);
742 return (error);
743
744 case GM_GRFGETNUMVM:
745 *(int *) arg = monitor_def_max;
746 return (0);
747
748 case GM_GRFIOCTL:
749 return (et_ioctl(gp, a2, arg));
750
751 default:
752 break;
753 }
754
755 return (EPASSTHROUGH);
756 }
757
758
759 int
760 et_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
761 {
762 switch (cmd) {
763 case GRFIOCGSPRITEPOS:
764 return (et_getmousepos(gp, (struct grf_position *) data));
765
766 case GRFIOCSSPRITEPOS:
767 return (et_setmousepos(gp, (struct grf_position *) data));
768
769 case GRFIOCSSPRITEINF:
770 return (et_setspriteinfo(gp, (struct grf_spriteinfo *) data));
771
772 case GRFIOCGSPRITEINF:
773 return (et_getspriteinfo(gp, (struct grf_spriteinfo *) data));
774
775 case GRFIOCGSPRITEMAX:
776 return (et_getspritemax(gp, (struct grf_position *) data));
777
778 case GRFIOCGETCMAP:
779 return (et_getcmap(gp, (struct grf_colormap *) data));
780
781 case GRFIOCPUTCMAP:
782 return (et_putcmap(gp, (struct grf_colormap *) data));
783
784 case GRFIOCBITBLT:
785 break;
786
787 case GRFTOGGLE:
788 return (et_toggle(gp, 0));
789
790 case GRFIOCSETMON:
791 return (et_setmonitor(gp, (struct grfvideo_mode *) data));
792
793 case GRFIOCBLANK:
794 return (et_blank(gp, *(int *)data));
795 }
796 return (EPASSTHROUGH);
797 }
798
799
800 int
801 et_getmousepos(struct grf_softc *gp, struct grf_position *data)
802 {
803 data->x = et_cursprite.pos.x;
804 data->y = et_cursprite.pos.y;
805
806 return (0);
807 }
808
809
810 void
811 et_writesprpos(volatile char *ba, short x, short y)
812 {
813 }
814
815
816 int
817 et_setmousepos(struct grf_softc *gp, struct grf_position *data)
818 {
819 volatile char *ba = gp->g_regkva;
820 short rx, ry;
821
822 /* no movement */
823 if (et_cursprite.pos.x == data->x && et_cursprite.pos.y == data->y)
824 return (0);
825
826 /* current and previous real coordinates */
827 rx = data->x - et_cursprite.hot.x;
828 ry = data->y - et_cursprite.hot.y;
829
830 /* if we are/were on an edge, create (un)shifted bitmap --
831 * ripped out optimization (not extremely worthwhile,
832 * and kind of buggy anyhow).
833 */
834
835 /* do movement, save position */
836 et_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
837 et_cursprite.pos.x = data->x;
838 et_cursprite.pos.y = data->y;
839
840 return (0);
841 }
842
843
844 int
845 et_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
846 {
847
848 return(EINVAL);
849 }
850
851
852 static int
853 et_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
854 {
855
856 return(EINVAL);
857 }
858
859
860 static int
861 et_getspritemax(struct grf_softc *gp, struct grf_position *data)
862 {
863
864 return(EINVAL);
865 }
866
867
868 int
869 et_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
870 {
871 struct grfvideo_mode *md;
872
873 if (!et_mondefok(gv))
874 return(EINVAL);
875
876 #ifdef TSENGCONSOLE
877 /* handle interactive setting of console mode */
878 if (gv->mode_num == 255) {
879 memcpy(&etconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
880 etconsole_mode.gv.hblank_start /= 8;
881 etconsole_mode.gv.hsync_start /= 8;
882 etconsole_mode.gv.hsync_stop /= 8;
883 etconsole_mode.gv.htotal /= 8;
884 etconsole_mode.rows = gv->disp_height / etconsole_mode.fy;
885 etconsole_mode.cols = gv->disp_width / etconsole_mode.fx;
886 if (!(gp->g_flags & GF_GRFON))
887 et_load_mon(gp, &etconsole_mode);
888 #if NITE > 0
889 ite_reinit(gp->g_itedev);
890 #endif
891 return (0);
892 }
893 #endif
894
895 md = monitor_def + (gv->mode_num - 1);
896 memcpy(md, gv, sizeof(struct grfvideo_mode));
897
898 /* adjust pixel oriented values to internal rep. */
899
900 md->hblank_start /= 8;
901 md->hsync_start /= 8;
902 md->hsync_stop /= 8;
903 md->htotal /= 8;
904
905 return (0);
906 }
907
908
909 int
910 et_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
911 {
912 volatile unsigned char *ba;
913 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
914 short x;
915 int error;
916
917 if (cmap->count == 0 || cmap->index >= 256)
918 return 0;
919
920 if (cmap->count > 256 - cmap->index)
921 cmap->count = 256 - cmap->index;
922
923 ba = gfp->g_regkva;
924 /* first read colors out of the chip, then copyout to userspace */
925 x = cmap->count - 1;
926
927 rp = red + cmap->index;
928 gp = green + cmap->index;
929 bp = blue + cmap->index;
930
931 switch(ettype) {
932 case MERLIN:
933 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
934 do {
935 *rp++ = vgar(ba, MERLIN_VDAC_COLORS);
936 *gp++ = vgar(ba, MERLIN_VDAC_COLORS);
937 *bp++ = vgar(ba, MERLIN_VDAC_COLORS);
938 } while (x-- > 0);
939 break;
940 default:
941 vgaw(ba, VDAC_ADDRESS_R+((ettype==DOMINO)?0x0fff:0), cmap->index);
942 do {
943 *rp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
944 *gp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
945 *bp++ = vgar(ba, VDAC_DATA+((ettype==DOMINO)?0x0fff:0)) << etcmap_shift;
946 } while (x-- > 0);
947 break;
948 }
949
950 error = copyout(red + cmap->index, cmap->red, cmap->count);
951 if (!error)
952 error = copyout(green + cmap->index, cmap->green, cmap->count);
953 if (!error)
954 error = copyout(blue + cmap->index, cmap->blue, cmap->count);
955
956 return (error);
957 }
958
959
960 int
961 et_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
962 {
963 volatile unsigned char *ba;
964 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
965 short x;
966 int error;
967
968 if (cmap->count == 0 || cmap->index >= 256)
969 return (0);
970
971 if (cmap->count > 256 - cmap->index)
972 cmap->count = 256 - cmap->index;
973
974 /* first copy the colors into kernelspace */
975 if ((error = copyin(cmap->red, red + cmap->index, cmap->count)))
976 return (error);
977
978 if ((error = copyin(cmap->green, green + cmap->index, cmap->count)))
979 return (error);
980
981 if ((error = copyin(cmap->blue, blue + cmap->index, cmap->count)))
982 return (error);
983
984 ba = gfp->g_regkva;
985 x = cmap->count - 1;
986
987 rp = red + cmap->index;
988 gp = green + cmap->index;
989 bp = blue + cmap->index;
990
991 switch(ettype){
992 case MERLIN:
993 vgaw(ba, MERLIN_VDAC_INDEX, cmap->index);
994 do {
995 vgaw(ba, MERLIN_VDAC_COLORS, *rp++);
996 vgaw(ba, MERLIN_VDAC_COLORS, *gp++);
997 vgaw(ba, MERLIN_VDAC_COLORS, *bp++);
998 } while (x-- > 0);
999 break;
1000 default:
1001 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
1002 do {
1003 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1004 *rp++ >> etcmap_shift);
1005 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1006 *gp++ >> etcmap_shift);
1007 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1008 *bp++ >> etcmap_shift);
1009 } while (x-- > 0);
1010 break;
1011 }
1012
1013 return (0);
1014 }
1015
1016
1017 int
1018 et_toggle(struct grf_softc *gp, unsigned short wopp)
1019 /* (variable wopp) don't need that one yet, ill */
1020 {
1021 volatile unsigned char *ba;
1022
1023 ba = gp->g_regkva;
1024
1025 if (pass_toggle) {
1026 RegOffpass(ba);
1027 } else {
1028 RegOnpass(ba);
1029 }
1030 return (0);
1031 }
1032
1033
1034 #define ET_NUMCLOCKS 32
1035
1036 static u_char et_clocks[ET_NUMCLOCKS] = {
1037 0, 1, 6, 2, 3, 7, 4, 5,
1038 0, 1, 6, 2, 3, 7, 4, 5,
1039 0, 1, 6, 2, 3, 7, 4, 5,
1040 0, 1, 6, 2, 3, 7, 4, 5
1041 };
1042
1043 static u_char et_clockdividers[ET_NUMCLOCKS] = {
1044 3, 3, 3, 3, 3, 3, 3, 3,
1045 2, 2, 2, 2, 2, 2, 2, 2,
1046 1, 1, 1, 1, 1, 1, 1, 1,
1047 0, 0, 0, 0, 0, 0, 0, 0
1048 };
1049
1050 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
1051 6293750, 7080500, 7875000, 8125000,
1052 9000000, 9375000, 10000000, 11225000,
1053 12587500, 14161000, 15750000, 16250000,
1054 18000000, 18750000, 20000000, 22450000,
1055 25175000, 28322000, 31500000, 32500000,
1056 36000000, 37500000, 40000000, 44900000,
1057 50350000, 56644000, 63000000, 65000000,
1058 72000000, 75000000, 80000000, 89800000
1059 };
1060
1061
1062 static void
1063 et_CompFQ(u_int fq, u_char *num, u_char *denom)
1064 {
1065 int i;
1066
1067 for (i=0; i < ET_NUMCLOCKS;) {
1068 if (fq <= et_clockfreqs[i++]) {
1069 break;
1070 }
1071 }
1072
1073 *num = et_clocks[--i];
1074 *denom = et_clockdividers[i];
1075
1076 return;
1077 }
1078
1079
1080 int
1081 et_mondefok(struct grfvideo_mode *gv)
1082 {
1083 unsigned long maxpix;
1084
1085 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1086 if (gv->mode_num != 255 || gv->depth != 4)
1087 return(0);
1088
1089 switch (gv->depth) {
1090 case 4:
1091 if (gv->mode_num != 255)
1092 return(0);
1093 case 1:
1094 case 8:
1095 maxpix = 85000000;
1096 break;
1097 case 15:
1098 case 16:
1099 maxpix = 45000000;
1100 break;
1101 case 24:
1102 maxpix = 28000000;
1103 break;
1104 case 32:
1105 maxpix = 21000000;
1106 break;
1107 default:
1108 printf("grfet: Illegal depth in mode %d\n",
1109 (int) gv->mode_num);
1110 return (0);
1111 }
1112
1113 if (gv->pixel_clock > maxpix) {
1114 printf("grfet: Pixelclock too high in mode %d\n",
1115 (int) gv->mode_num);
1116 return (0);
1117 }
1118
1119 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1120 printf("grfet: sync-on-green is not supported\n");
1121 return (0);
1122 }
1123
1124 return (1);
1125 }
1126
1127
1128 int
1129 et_load_mon(struct grf_softc *gp, struct grfettext_mode *md)
1130 {
1131 struct grfvideo_mode *gv;
1132 struct grfinfo *gi;
1133 volatile unsigned char *ba;
1134 unsigned char num0, denom0;
1135 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1136 VSE, VT;
1137 unsigned char hvsync_pulse, seq;
1138 char TEXT;
1139 int hmul;
1140
1141 /* identity */
1142 gv = &md->gv;
1143 TEXT = (gv->depth == 4);
1144
1145 if (!et_mondefok(gv)) {
1146 printf("grfet: Monitor definition not ok\n");
1147 return (0);
1148 }
1149
1150 ba = gp->g_regkva;
1151
1152 /* provide all needed information in grf device-independent locations */
1153 gp->g_data = (void *) gv;
1154 gi = &gp->g_display;
1155 gi->gd_regaddr = ztwopa(__UNVOLATILE(ba));
1156 gi->gd_regsize = 64 * 1024;
1157 gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(gp->g_fbkva));
1158 gi->gd_fbsize = et_fbsize;
1159 gi->gd_colors = 1 << gv->depth;
1160 gi->gd_planes = gv->depth;
1161 gi->gd_fbwidth = gv->disp_width;
1162 gi->gd_fbheight = gv->disp_height;
1163 gi->gd_fbx = 0;
1164 gi->gd_fby = 0;
1165 if (TEXT) {
1166 gi->gd_dwidth = md->fx * md->cols;
1167 gi->gd_dheight = md->fy * md->rows;
1168 } else {
1169 gi->gd_dwidth = gv->disp_width;
1170 gi->gd_dheight = gv->disp_height;
1171 }
1172 gi->gd_dx = 0;
1173 gi->gd_dy = 0;
1174
1175 /* get display mode parameters */
1176
1177 HBS = gv->hblank_start;
1178 HSS = gv->hsync_start;
1179 HSE = gv->hsync_stop;
1180 HBE = gv->htotal - 1;
1181 HT = gv->htotal;
1182 VBS = gv->vblank_start;
1183 VSS = gv->vsync_start;
1184 VSE = gv->vsync_stop;
1185 VBE = gv->vtotal - 1;
1186 VT = gv->vtotal;
1187
1188 if (TEXT)
1189 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1190 else
1191 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1192 VDE = gv->disp_height - 1;
1193
1194 /* adjustments (crest) */
1195 switch (gv->depth) {
1196 case 15:
1197 case 16:
1198 hmul = 2;
1199 break;
1200 case 24:
1201 hmul = 3;
1202 break;
1203 case 32:
1204 hmul = 4;
1205 break;
1206 default:
1207 hmul = 1;
1208 break;
1209 }
1210
1211 HDE *= hmul;
1212 HBS *= hmul;
1213 HSS *= hmul;
1214 HSE *= hmul;
1215 HBE *= hmul;
1216 HT *= hmul;
1217
1218 if (gv->disp_flags & GRF_FLAGS_LACE) {
1219 VDE /= 2;
1220 VT = VT + 1;
1221 }
1222
1223 if (gv->disp_flags & GRF_FLAGS_DBLSCAN) {
1224 VDE *= 2;
1225 VBS *= 2;
1226 VSS *= 2;
1227 VSE *= 2;
1228 VBE *= 2;
1229 VT *= 2;
1230 }
1231
1232 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1233
1234 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1235 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1236 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1237
1238 /* Set clock */
1239 et_CompFQ( gv->pixel_clock * hmul, &num0, &denom0);
1240
1241 /* Horizontal/Vertical Sync Pulse */
1242 hvsync_pulse = 0xe3;
1243 if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1244 hvsync_pulse &= ~0x40;
1245 else
1246 hvsync_pulse |= 0x40;
1247 if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1248 hvsync_pulse &= ~0x80;
1249 else
1250 hvsync_pulse |= 0x80;
1251
1252 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse | ((num0 & 3) << 2));
1253 WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08);
1254 seq = RSeq(ba, SEQ_ID_CLOCKING_MODE);
1255 switch(denom0) {
1256 case 0:
1257 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4);
1258 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1259 break;
1260 case 1:
1261 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
1262 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1263 break;
1264 case 2:
1265 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1266 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7);
1267 break;
1268 case 3:
1269 WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5);
1270 WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08);
1271 break;
1272 }
1273
1274 /* load display parameters into board */
1275 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1276 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1277 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1278 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80);
1279 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1280 WCrt(ba, CRT_ID_END_HOR_RETR,
1281 (HSE & 0x1f) |
1282 ((HBE & 0x20) ? 0x80 : 0x00));
1283 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1284 WCrt(ba, CRT_ID_OVERFLOW,
1285 0x10 |
1286 ((VT & 0x100) ? 0x01 : 0x00) |
1287 ((VDE & 0x100) ? 0x02 : 0x00) |
1288 ((VSS & 0x100) ? 0x04 : 0x00) |
1289 ((VBS & 0x100) ? 0x08 : 0x00) |
1290 ((VT & 0x200) ? 0x20 : 0x00) |
1291 ((VDE & 0x200) ? 0x40 : 0x00) |
1292 ((VSS & 0x200) ? 0x80 : 0x00));
1293
1294 WCrt(ba, CRT_ID_MAX_ROW_ADDRESS,
1295 0x40 | /* splitscreen not visible */
1296 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1297 ((VBS & 0x200) ? 0x20 : 0x00) |
1298 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1299
1300 WCrt(ba, CRT_ID_MODE_CONTROL,
1301 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab));
1302
1303 /* text cursor */
1304 if (TEXT) {
1305 #if ET_ULCURSOR
1306 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1307 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1308 #else
1309 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1310 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1311 #endif
1312 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1313 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1314 }
1315
1316 WCrt(ba, CRT_ID_UNDERLINE_LOC, ((md->fy - 1) & 0x1f)
1317 | ((TEXT || (gv->depth == 1)) ? 0x00 : 0x60));
1318
1319 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1320 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1321
1322 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1323 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1324 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1325 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1326 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1327
1328 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1329
1330 WCrt(ba, CRT_ID_OVERFLOW_HIGH,
1331 ((VBS & 0x400) ? 0x01 : 0x00) |
1332 ((VT & 0x400) ? 0x02 : 0x00) |
1333 ((VDE & 0x400) ? 0x04 : 0x00) |
1334 ((VSS & 0x400) ? 0x08 : 0x00) |
1335 0x10 |
1336 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x80 : 0x00));
1337
1338 WCrt(ba, CRT_ID_HOR_OVERFLOW,
1339 ((HT & 0x100) ? 0x01 : 0x00) |
1340 ((HBS & 0x100) ? 0x04 : 0x00) |
1341 ((HSS & 0x100) ? 0x10 : 0x00)
1342 );
1343
1344 /* depth dependent stuff */
1345
1346 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1347 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1348 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1349
1350 vgaw(ba, VDAC_MASK, 0xff);
1351 vgar(ba, VDAC_MASK);
1352 vgar(ba, VDAC_MASK);
1353 vgar(ba, VDAC_MASK);
1354 vgar(ba, VDAC_MASK);
1355 switch (gv->depth) {
1356 case 1:
1357 case 4: /* text */
1358 switch(etdtype) {
1359 case SIERRA11483:
1360 case SIERRA15025:
1361 case MUSICDAC:
1362 vgaw(ba, VDAC_MASK, 0);
1363 break;
1364 case ATT20C491:
1365 vgaw(ba, VDAC_MASK, 0x02);
1366 break;
1367 case MERLINDAC:
1368 setMerlinDACmode(ba, 0);
1369 break;
1370 }
1371 HDE = gv->disp_width / 16;
1372 break;
1373 case 8:
1374 switch(etdtype) {
1375 case SIERRA11483:
1376 case SIERRA15025:
1377 case MUSICDAC:
1378 vgaw(ba, VDAC_MASK, 0);
1379 break;
1380 case ATT20C491:
1381 vgaw(ba, VDAC_MASK, 0x02);
1382 break;
1383 case MERLINDAC:
1384 setMerlinDACmode(ba, 0);
1385 break;
1386 }
1387 HDE = gv->disp_width / 8;
1388 break;
1389 case 15:
1390 switch(etdtype) {
1391 case SIERRA11483:
1392 case SIERRA15025:
1393 case MUSICDAC:
1394 case ATT20C491:
1395 vgaw(ba, VDAC_MASK, 0xa0);
1396 break;
1397 case MERLINDAC:
1398 setMerlinDACmode(ba, 0xa0);
1399 break;
1400 }
1401 HDE = gv->disp_width / 4;
1402 break;
1403 case 16:
1404 switch(etdtype) {
1405 case SIERRA11483:
1406 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1407 break;
1408 case SIERRA15025:
1409 vgaw(ba, VDAC_MASK, 0xe0);
1410 break;
1411 case MUSICDAC:
1412 case ATT20C491:
1413 vgaw(ba, VDAC_MASK, 0xc0);
1414 break;
1415 case MERLINDAC:
1416 setMerlinDACmode(ba, 0xe0);
1417 break;
1418 }
1419 HDE = gv->disp_width / 4;
1420 break;
1421 case 24:
1422 switch(etdtype) {
1423 case SIERRA11483:
1424 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1425 break;
1426 case SIERRA15025:
1427 vgaw(ba, VDAC_MASK, 0xe1);
1428 break;
1429 case MUSICDAC:
1430 case ATT20C491:
1431 vgaw(ba, VDAC_MASK, 0xe0);
1432 break;
1433 case MERLINDAC:
1434 setMerlinDACmode(ba, 0xf0);
1435 break;
1436 }
1437 HDE = (gv->disp_width / 8) * 3;
1438 break;
1439 case 32:
1440 switch(etdtype) {
1441 case SIERRA11483:
1442 case MUSICDAC:
1443 case ATT20C491:
1444 vgaw(ba, VDAC_MASK, 0); /* illegal mode! */
1445 break;
1446 case SIERRA15025:
1447 vgaw(ba, VDAC_MASK, 0x61);
1448 break;
1449 case MERLINDAC:
1450 setMerlinDACmode(ba, 0xb0);
1451 break;
1452 }
1453 HDE = gv->disp_width / 2;
1454 break;
1455 }
1456 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1457 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1458 (gv->depth == 1) ? 0x01 : 0x0f);
1459
1460 WCrt(ba, CRT_ID_OFFSET, HDE);
1461 vgaw(ba, CRT_ADDRESS, CRT_ID_HOR_OVERFLOW);
1462 vgaw(ba, CRT_ADDRESS_W,
1463 (vgar(ba, CRT_ADDRESS_R) & 0x7f)
1464 | ((HDE & 0x100) ? 0x80: 0x00));
1465
1466 /* text initialization */
1467 if (TEXT) {
1468 et_inittextmode(gp);
1469 }
1470
1471 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1472
1473 /* Pass-through */
1474 RegOffpass(ba);
1475
1476 return (1);
1477 }
1478
1479
1480 void
1481 et_inittextmode(struct grf_softc *gp)
1482 {
1483 struct grfettext_mode *tm = (struct grfettext_mode *) gp->g_data;
1484 volatile unsigned char *ba = gp->g_regkva;
1485 volatile unsigned char *fb = gp->g_fbkva;
1486 volatile unsigned char *c;
1487 unsigned char *f, y;
1488 unsigned short z;
1489
1490
1491 /*
1492 * load text font into beginning of display memory. Each character
1493 * cell is 32 bytes long (enough for 4 planes)
1494 */
1495
1496 SetTextPlane(ba, 0x02);
1497 et_memset(fb, 0, 256 * 32);
1498 c = fb + (32 * tm->fdstart);
1499 f = tm->fdata;
1500 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1501 for (y = 0; y < tm->fy; y++)
1502 *c++ = *f++;
1503
1504 /* clear out text/attr planes (three screens worth) */
1505
1506 SetTextPlane(ba, 0x01);
1507 et_memset(fb, 0x07, tm->cols * tm->rows * 3);
1508 SetTextPlane(ba, 0x00);
1509 et_memset(fb, 0x20, tm->cols * tm->rows * 3);
1510
1511 /* print out a little init msg */
1512
1513 c = fb + (tm->cols - 16);
1514 strcpy(__UNVOLATILE(c), "TSENG");
1515 c[5] = 0x20;
1516
1517 /* set colors (B&W) */
1518
1519 switch(ettype) {
1520 case MERLIN:
1521 vgaw(ba, MERLIN_VDAC_INDEX, 0);
1522 for (z = 0; z < 256; z++) {
1523 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1524
1525 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]);
1526 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]);
1527 vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]);
1528 }
1529 break;
1530 default:
1531 vgaw(ba, VDAC_ADDRESS_W, 0);
1532 for (z = 0; z < 256; z++) {
1533 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1534
1535 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1536 etconscolors[y][0] >> etcmap_shift);
1537 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1538 etconscolors[y][1] >> etcmap_shift);
1539 vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0),
1540 etconscolors[y][2] >> etcmap_shift);
1541 }
1542 break;
1543 }
1544 }
1545
1546
1547 void
1548 et_memset(volatile unsigned char *d, unsigned char c, int l)
1549 {
1550 for (; l > 0; l--)
1551 *d++ = c;
1552 }
1553
1554
1555 static int
1556 et_getControllerType(struct grf_softc *gp)
1557 {
1558 volatile unsigned char *ba = gp->g_regkva; /* register base */
1559 volatile unsigned char *mem = gp->g_fbkva; /* memory base */
1560 volatile unsigned char *mmu = mem + MMU_APERTURE0; /* MMU aperture 0 base */
1561
1562 *mem = 0;
1563
1564 /* make ACL visible */
1565 if (ettype == MERLIN) {
1566 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xbb);
1567 } else {
1568 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb);
1569 }
1570
1571 WIma(ba, IMA_PORTCONTROL, 0x01);
1572
1573 *((volatile unsigned long *)mmu) = 0;
1574 *(mem + 0x13) = 0x38;
1575
1576 *mmu = 0xff;
1577
1578 /* hide ACL */
1579 WIma(ba, IMA_PORTCONTROL, 0x00);
1580
1581 if (ettype == MERLIN) {
1582 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93);
1583 } else {
1584 WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3);
1585 }
1586 return ((*mem == 0xff) ? ETW32 : ET4000);
1587 }
1588
1589
1590 static int
1591 et_getDACType(struct grf_softc *gp)
1592 {
1593 volatile unsigned char *ba = gp->g_regkva;
1594 union {
1595 int tt;
1596 char cc[4];
1597 } check;
1598
1599 /* check for Sierra SC 15025 */
1600
1601 /* We MUST do 4 HW reads to switch into command mode */
1602 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1603 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1604
1605 vgaw(ba, VDAC_XINDEX, 9);
1606 check.cc[0] = vgar(ba, VDAC_XDATA);
1607 vgaw(ba, VDAC_XINDEX, 10);
1608 check.cc[1] = vgar(ba, VDAC_XDATA);
1609 vgaw(ba, VDAC_XINDEX, 11);
1610 check.cc[2] = vgar(ba, VDAC_XDATA);
1611 vgaw(ba, VDAC_XINDEX, 12);
1612 check.cc[3] = vgar(ba, VDAC_XDATA);
1613
1614 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1615 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1616
1617 if (check.tt == 0x533ab141) {
1618 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1619 vgaw(ba, VDAC_COMMAND, 0x10); /* set ERPF */
1620
1621 /* switch to 8 bits per color */
1622 vgaw(ba, VDAC_XINDEX, 8);
1623 vgaw(ba, VDAC_XDATA, 1);
1624 /* do not shift color values */
1625 etcmap_shift = 0;
1626
1627 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1628 vgaw(ba, VDAC_COMMAND, 0x00); /* clear ERPF */
1629
1630 vgaw(ba, VDAC_MASK, 0xff);
1631 return (SIERRA15025);
1632 }
1633
1634 /* check for MUSIC DAC */
1635
1636 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1637 vgaw(ba, VDAC_COMMAND, 0x02); /* set some strange MUSIC mode (???) */
1638
1639 vgaw(ba, VDAC_XINDEX, 0x01);
1640 if (vgar(ba, VDAC_XDATA) == 0x01) {
1641 /* shift color values by 2 */
1642 etcmap_shift = 2;
1643
1644 vgaw(ba, VDAC_MASK, 0xff);
1645 return (MUSICDAC);
1646 }
1647
1648 /* check for AT&T ATT20c491 DAC (crest) */
1649 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1650 vgaw(ba, HDR, 0xff);
1651 vgaw(ba, VDAC_MASK, 0x01);
1652 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1653 if (vgar(ba, HDR) == 0xff) {
1654 /* do not shift color values */
1655 etcmap_shift = 0;
1656
1657 vgaw(ba, VDAC_MASK, 0xff);
1658 return (ATT20C491);
1659 }
1660
1661 /* restore PowerUp settings (crest) */
1662 if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR)); if (vgar(ba, HDR));
1663 vgaw(ba, HDR, 0x00);
1664
1665 /*
1666 * nothing else found, so let us pretend it is a stupid
1667 * Sierra SC 11483
1668 */
1669
1670 /* shift color values by 2 */
1671 etcmap_shift = 2;
1672
1673 vgaw(ba, VDAC_MASK, 0xff);
1674 return (SIERRA11483);
1675 }
1676
1677
1678 #if NWSDISPLAY > 0
1679 static void
1680 et_wscursor(void *c, int on, int row, int col)
1681 {
1682 struct rasops_info *ri;
1683 struct vcons_screen *scr;
1684 struct grf_softc *gp;
1685 volatile void *ba;
1686 int offs;
1687
1688 ri = c;
1689 scr = ri->ri_hw;
1690 gp = scr->scr_cookie;
1691 ba = gp->g_regkva;
1692
1693 if ((ri->ri_flg & RI_CURSOR) && !on) {
1694 /* cursor was visible, but we want to remove it */
1695 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1696 ri->ri_flg &= ~RI_CURSOR;
1697 }
1698
1699 ri->ri_crow = row;
1700 ri->ri_ccol = col;
1701
1702 if (on) {
1703 /* move cursor to new location */
1704 if (!(ri->ri_flg & RI_CURSOR)) {
1705 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1706 ri->ri_flg |= RI_CURSOR;
1707 }
1708 offs = gp->g_rowoffset[row] + col;
1709 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
1710 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (offs >> 8) & 0xff);
1711 WCrt(ba, CRT_ID_EXT_START, (offs >> (16-2)) & 0x0c);
1712 }
1713 }
1714
1715 static void
1716 et_wsputchar(void *c, int row, int col, u_int ch, long attr)
1717 {
1718 struct rasops_info *ri;
1719 struct vcons_screen *scr;
1720 struct grf_softc *gp;
1721 volatile unsigned char *ba, *cp;
1722
1723 ri = c;
1724 scr = ri->ri_hw;
1725 gp = scr->scr_cookie;
1726 ba = gp->g_regkva;
1727 cp = gp->g_fbkva;
1728
1729 cp += gp->g_rowoffset[row] + col;
1730 SetTextPlane(ba, 0x00);
1731 *cp = ch;
1732 SetTextPlane(ba, 0x01);
1733 *cp = attr;
1734 }
1735
1736 static void
1737 et_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
1738 {
1739 volatile unsigned char *ba, *dst, *src;
1740 struct rasops_info *ri;
1741 struct vcons_screen *scr;
1742 struct grf_softc *gp;
1743 int i;
1744
1745 KASSERT(ncols > 0);
1746 ri = c;
1747 scr = ri->ri_hw;
1748 gp = scr->scr_cookie;
1749 ba = gp->g_regkva;
1750 src = gp->g_fbkva;
1751
1752 src += gp->g_rowoffset[row];
1753 dst = src;
1754 src += srccol;
1755 dst += dstcol;
1756 if (srccol < dstcol) {
1757 /* need to copy backwards */
1758 src += ncols;
1759 dst += ncols;
1760 SetTextPlane(ba, 0x00);
1761 for (i = 0; i < ncols; i++)
1762 *(--dst) = *(--src);
1763 src += ncols;
1764 dst += ncols;
1765 SetTextPlane(ba, 0x01);
1766 for (i = 0; i < ncols; i++)
1767 *(--dst) = *(--src);
1768 } else {
1769 SetTextPlane(ba, 0x00);
1770 for (i = 0; i < ncols; i++)
1771 *dst++ = *src++;
1772 src -= ncols;
1773 dst -= ncols;
1774 SetTextPlane(ba, 0x01);
1775 for (i = 0; i < ncols; i++)
1776 *dst++ = *src++;
1777 }
1778 }
1779
1780 static void
1781 et_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
1782 {
1783 volatile unsigned char *ba, *cp;
1784 struct rasops_info *ri;
1785 struct vcons_screen *scr;
1786 struct grf_softc *gp;
1787 int i;
1788
1789 ri = c;
1790 scr = ri->ri_hw;
1791 gp = scr->scr_cookie;
1792 ba = gp->g_regkva;
1793 cp = gp->g_fbkva;
1794
1795 cp += gp->g_rowoffset[row] + startcol;
1796 SetTextPlane(ba, 0x00);
1797 for (i = 0; i < ncols; i++)
1798 *cp++ = 0x20;
1799 cp -= ncols;
1800 SetTextPlane(ba, 0x01);
1801 for (i = 0; i < ncols; i++)
1802 *cp++ = 0x07;
1803 }
1804
1805 static void
1806 et_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
1807 {
1808 volatile unsigned char *ba, *dst, *src;
1809 struct rasops_info *ri;
1810 struct vcons_screen *scr;
1811 struct grf_softc *gp;
1812 int i, n;
1813
1814 KASSERT(nrows > 0);
1815 ri = c;
1816 scr = ri->ri_hw;
1817 gp = scr->scr_cookie;
1818 ba = gp->g_regkva;
1819 src = dst = gp->g_fbkva;
1820 n = ri->ri_cols * nrows;
1821
1822 if (srcrow < dstrow) {
1823 /* need to copy backwards */
1824 src += gp->g_rowoffset[srcrow + nrows];
1825 dst += gp->g_rowoffset[dstrow + nrows];
1826 SetTextPlane(ba, 0x00);
1827 for (i = 0; i < n; i++)
1828 *(--dst) = *(--src);
1829 src += n;
1830 dst += n;
1831 SetTextPlane(ba, 0x01);
1832 for (i = 0; i < n; i++)
1833 *(--dst) = *(--src);
1834 } else {
1835 src += gp->g_rowoffset[srcrow];
1836 dst += gp->g_rowoffset[dstrow];
1837 SetTextPlane(ba, 0x00);
1838 for (i = 0; i < n; i++)
1839 *dst++ = *src++;
1840 src -= n;
1841 dst -= n;
1842 SetTextPlane(ba, 0x01);
1843 for (i = 0; i < n; i++)
1844 *dst++ = *src++;
1845 }
1846 }
1847
1848 static void
1849 et_wseraserows(void *c, int row, int nrows, long fillattr)
1850 {
1851 volatile unsigned char *ba, *cp;
1852 struct rasops_info *ri;
1853 struct vcons_screen *scr;
1854 struct grf_softc *gp;
1855 int i, n;
1856
1857 ri = c;
1858 scr = ri->ri_hw;
1859 gp = scr->scr_cookie;
1860 ba = gp->g_regkva;
1861 cp = gp->g_fbkva;
1862
1863 cp += gp->g_rowoffset[row];
1864 n = ri->ri_cols * nrows;
1865 SetTextPlane(ba, 0x00);
1866 for (i = 0; i < n; i++)
1867 *cp++ = 0x20;
1868 cp -= n;
1869 SetTextPlane(ba, 0x01);
1870 for (i = 0; i < n; i++)
1871 *cp++ = 0x07;
1872 }
1873
1874 static int
1875 et_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
1876 {
1877
1878 /* XXX color support? */
1879 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
1880 if (flg & WSATTR_UNDERLINE) *attr = 0x01;
1881 if (flg & WSATTR_HILIT) *attr |= 0x08;
1882 if (flg & WSATTR_BLINK) *attr |= 0x80;
1883 return 0;
1884 }
1885
1886 /* our font does not support unicode extensions */
1887 static int
1888 et_wsmapchar(void *c, int ch, unsigned int *cp)
1889 {
1890
1891 if (ch > 0 && ch < 256) {
1892 *cp = ch;
1893 return 5;
1894 }
1895 *cp = ' ';
1896 return 0;
1897 }
1898
1899 static int
1900 et_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
1901 {
1902 struct vcons_data *vd;
1903 struct grf_softc *gp;
1904
1905 vd = v;
1906 gp = vd->cookie;
1907
1908 switch (cmd) {
1909 case WSDISPLAYIO_GETCMAP:
1910 /* Note: wsdisplay_cmap and grf_colormap have same format */
1911 if (gp->g_display.gd_planes == 8)
1912 return et_getcmap(gp, (struct grf_colormap *)data);
1913 return EINVAL;
1914
1915 case WSDISPLAYIO_PUTCMAP:
1916 /* Note: wsdisplay_cmap and grf_colormap have same format */
1917 if (gp->g_display.gd_planes == 8)
1918 return et_putcmap(gp, (struct grf_colormap *)data);
1919 return EINVAL;
1920
1921 case WSDISPLAYIO_GVIDEO:
1922 if (et_isblank(gp))
1923 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
1924 else
1925 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
1926 return 0;
1927
1928 case WSDISPLAYIO_SVIDEO:
1929 return et_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON);
1930
1931 case WSDISPLAYIO_SMODE:
1932 if ((*(int *)data) != gp->g_wsmode) {
1933 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
1934 /* load console text mode, redraw screen */
1935 (void)et_load_mon(gp, &etconsole_mode);
1936 if (vd->active != NULL)
1937 vcons_redraw_screen(vd->active);
1938 } else {
1939 /* switch to current graphics mode */
1940 if (!et_load_mon(gp,
1941 (struct grfettext_mode *)monitor_current))
1942 return EINVAL;
1943 }
1944 gp->g_wsmode = *(int *)data;
1945 }
1946 return 0;
1947
1948 case WSDISPLAYIO_GET_FBINFO:
1949 return et_get_fbinfo(gp, data);
1950 }
1951
1952 /* handle this command hw-independant in grf(4) */
1953 return grf_wsioctl(v, vs, cmd, data, flag, l);
1954 }
1955
1956 /*
1957 * Fill the wsdisplayio_fbinfo structure with information from the current
1958 * graphics mode. Even when text mode is active.
1959 */
1960 static int
1961 et_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
1962 {
1963 struct grfvideo_mode *md;
1964 uint32_t rbits, gbits, bbits;
1965
1966 md = monitor_current;
1967
1968 switch (md->depth) {
1969 case 8:
1970 fbi->fbi_bitsperpixel = 8;
1971 rbits = gbits = bbits = 6; /* keep gcc happy */
1972 break;
1973 case 15:
1974 fbi->fbi_bitsperpixel = 16;
1975 rbits = gbits = bbits = 5;
1976 break;
1977 case 16:
1978 fbi->fbi_bitsperpixel = 16;
1979 rbits = bbits = 5;
1980 gbits = 6;
1981 break;
1982 case 24:
1983 fbi->fbi_bitsperpixel = 24;
1984 rbits = gbits = bbits = 8;
1985 break;
1986 default:
1987 return EINVAL;
1988 }
1989
1990 fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width;
1991 fbi->fbi_width = md->disp_width;
1992 fbi->fbi_height = md->disp_height;
1993
1994 if (md->depth > 8) {
1995 fbi->fbi_pixeltype = WSFB_RGB;
1996 fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
1997 fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
1998 fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
1999 fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
2000 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
2001 fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
2002 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
2003 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
2004 } else {
2005 fbi->fbi_pixeltype = WSFB_CI;
2006 fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
2007 }
2008
2009 fbi->fbi_flags = 0;
2010 fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
2011 fbi->fbi_fboffset = 0;
2012 return 0;
2013 }
2014 #endif /* NWSDISPLAY > 0 */
2015
2016 #endif /* NGRFET */
2017