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