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