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