1 /*        $NetBSD: grfabs_et.c,v 1.37 2023/01/06 10:28:28 tsutsui Exp $         */
2 
3 /*
4  * Copyright (c) 1996 Leo Weppelman.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Most of the lower-level et4000 stuff was derived from:
30  *        .../amiga/dev/grf_et.c
31  *
32  * Which was copyrighted by:
33  *        Copyright (c) 1996 Tobias Abt
34  *        Copyright (c) 1995 Ezra Story
35  *        Copyright (c) 1995 Kari Mettinen
36  *        Copyright (c) 1994 Markus Wild
37  *        Copyright (c) 1994 Lutz Vieweg
38  *
39  * Thanks guys!
40  *
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: grfabs_et.c,v 1.37 2023/01/06 10:28:28 tsutsui Exp $");
45 
46 #include <sys/param.h>
47 #include <sys/queue.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/systm.h>
51 
52 #include <uvm/uvm_extern.h>
53 
54 /*
55  * For PCI probing...
56  */
57 #include <dev/pci/pcireg.h>
58 #include <dev/pci/pcivar.h>
59 #include <dev/pci/pcidevs.h>
60 
61 #include <machine/iomap.h>
62 #include <machine/video.h>
63 #include <machine/mfp.h>
64 #include <machine/cpu.h>
65 #include <atari/atari/device.h>
66 #include <atari/dev/grfioctl.h>
67 #include <atari/dev/grfabs_reg.h>
68 #include <atari/dev/grfabs_et.h>
69 #include <atari/dev/grf_etreg.h>
70 
71 #define   SAVEBUF_SIZE        (32*1024 + sizeof(save_area_t))
72 
73 /*
74  * Allow a 16Kb io-region and a 4MB frame buffer to be mapped. This
75  * is more or less required by the XFree server.
76  */
77 #define   REG_MAPPABLE        (16 * 1024)
78 #define   FRAME_MAPPABLE      (4 * 1024 * 1024)
79 #define VGA_MAPPABLE          (128 * 1024)
80 #define VGA_BASE    0xa0000
81 
82 /*
83  * Linear memory base, near the end of the pci area
84  */
85 #define PCI_LINMEMBASE  0x0e000000
86 
87 /*
88  * Function decls
89  */
90 static void       init_view(view_t *, bmap_t *, dmode_t *, box_t *);
91 static colormap_t *alloc_colormap(dmode_t *);
92 static void           et_display_view(view_t *);
93 static view_t         *et_alloc_view(dmode_t *, dimen_t *, u_char);
94 static void           et_free_view(view_t *);
95 static void           et_loadmode(struct grfvideo_mode *, et_sv_reg_t *);
96 static void           et_remove_view(view_t *);
97 static void           et_save_view(view_t *);
98 static int            et_use_colormap(view_t *, colormap_t *);
99 
100 /*
101  * Our function switch table
102  */
103 struct grfabs_sw et_vid_sw = {
104           et_display_view,
105           et_alloc_view,
106           et_free_view,
107           et_remove_view,
108           et_save_view,
109           et_use_colormap
110 };
111 
112 static struct grfvideo_mode hw_modes[] = {
113     {
114           0, "", 22450000,              /* num, descr, pix-clock      */
115           640, 400, 4,                            /* width, height, depth                 */
116           632/8, 672/8, 688/8, 808/8, 768/8,/* HBS, HBE, HSS, HSE, HT */
117           399, 450, 408, 413, 449                 /* VBS, VBE, VSS, VSE, VT     */
118     },
119     {
120           0, "", 25175000,              /* num, descr, pix-clock      */
121           640, 480, 4,                            /* width, height, depth                 */
122           632/8, 672/8, 688/8, 752/8, 752/8,/* HBS, HBE, HSS, HSE, HT */
123           481, 522, 490, 498, 522                 /* VBS, VBE, VSS, VSE, VT     */
124     }
125 };
126 
127 static dmode_t vid_modes[] = {
128     { { NULL, NULL },
129           "640x400", { 640, 400 }, 1, (void*)&hw_modes[0], &et_vid_sw },
130     { { NULL, NULL },
131           "640x480", { 640, 480 }, 1, (void*)&hw_modes[1], &et_vid_sw },
132     { { NULL, NULL }, NULL,  }
133 };
134 
135 #define   ET_NUMCLOCKS        32
136 
137 static u_int et_clockfreqs[ET_NUMCLOCKS] = {
138            6293750,  7080500,  7875000,  8125000,
139            9000000,  9375000, 10000000, 11225000,
140           12587500, 14161000, 15750000, 16250000,
141           18000000, 18750000, 20000000, 22450000,
142           25175000, 28322000, 31500000, 32500000,
143           36000000, 37500000, 40000000, 44900000,
144           50350000, 56644000, 63000000, 65000000,
145           72000000, 75000000, 80000000, 89800000
146 };
147 
148 static bmap_t       con_bm; /* XXX */
149 
150 struct grfabs_et_priv {
151           pcitag_t            pci_tag;
152           void                          *regkva;
153           void                          *memkva;
154           u_int                         linbase;
155           int                           regsz;
156           int                           memsz;
157           int                           board_type;
158 } et_priv;
159 
160 /*
161  * Board types:
162  */
163 #define   BT_ET4000           1
164 #define   BT_ET6000           2
165 
166 /*
167  * XXX: called from ite console init routine.
168  * Initialize list of possible video modes.
169  */
170 void
et_probe_video(MODES * modelp)171 et_probe_video(MODES *modelp)
172 {
173           dmode_t   *dm;
174           int       i;
175 
176           for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
177                     LIST_INSERT_HEAD(modelp, dm, link);
178           }
179 }
180 
181 static void
et_display_view(view_t * v)182 et_display_view(view_t *v)
183 {
184           dmode_t             *dm = v->mode;
185           bmap_t              *bm = v->bitmap;
186           int                 sv_size;
187           u_short             *src, *dst;
188           save_area_t         *sa;
189 
190           if (dm->current_view && (dm->current_view != v)) {
191                     /*
192                      * Mark current view for this mode as no longer displayed
193                      */
194                     dm->current_view->flags &= ~VF_DISPLAY;
195           }
196           dm->current_view = v;
197           v->flags |= VF_DISPLAY;
198 
199           if ((sa = (save_area_t*)v->save_area) == NULL)
200                     return; /* XXX: Can't happen.... */
201 
202           /*
203            * Restore register settings and turn the plane pointer
204            * to the card-memory
205            */
206           et_hwrest(&sa->sv_regs);
207           bm->plane = et_priv.memkva;
208 
209           et_use_colormap(v, v->colormap);
210 
211           /*
212            * Copy the backing store to card-memory
213            */
214           sv_size = sa->fb_size;
215           src     = sa->sv_fb;
216           dst     = (u_short *)bm->plane;
217           while (sv_size--)
218                     *dst++ = *src++;
219 }
220 
221 void
et_remove_view(view_t * v)222 et_remove_view(view_t *v)
223 {
224           dmode_t *mode = v->mode;
225 
226           if (mode->current_view == v) {
227 #if 0
228                     if (v->flags & VF_DISPLAY)
229                               panic("Cannot shutdown display"); /* XXX */
230 #endif
231                     mode->current_view = NULL;
232           }
233           v->flags &= ~VF_DISPLAY;
234 }
235 
236 void
et_save_view(view_t * v)237 et_save_view(view_t *v)
238 {
239           bmap_t              *bm = v->bitmap;
240           u_char              font_height;
241           int                 sv_size;
242           u_short             *src, *dst;
243           save_area_t         *sa;
244           volatile u_char *ba;
245 
246           if (!atari_realconfig)
247                     return;
248 
249           ba = et_priv.regkva;
250 
251           if (RGfx(ba, GCT_ID_MISC) & 1) {
252 #if 0 /* XXX: Can't use printf here.... */
253                     printf("et_save_view: Don't know how to save"
254                               " a graphics mode\n");
255 #endif
256                     return;
257           }
258           if (v->save_area == NULL)
259                     v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_NOWAIT);
260 
261           /*
262            * Calculate the size of the copy
263            */
264           font_height = RCrt(ba, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
265           sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
266           sv_size = uimin(SAVEBUF_SIZE, sv_size);
267 
268           /*
269            * Save all we need to know....
270            */
271           sa  = (save_area_t *)v->save_area;
272           et_hwsave(&sa->sv_regs);
273           sa->fb_size = sv_size;
274           src = (u_short *)bm->plane;
275           dst = sa->sv_fb;
276           while (sv_size--)
277                     *dst++ = *src++;
278           bm->plane = (u_char *)sa->sv_fb;
279 }
280 
281 void
et_free_view(view_t * v)282 et_free_view(view_t *v)
283 {
284 
285           if (v) {
286                     et_remove_view(v);
287                     if (v->colormap != &gra_con_cmap)
288                               free(v->colormap, M_DEVBUF);
289                     if (v->save_area != NULL)
290                               free(v->save_area, M_DEVBUF);
291                     if (v != &gra_con_view) {
292                               free(v->bitmap, M_DEVBUF);
293                               free(v, M_DEVBUF);
294                     }
295           }
296 }
297 
298 static int
et_use_colormap(view_t * v,colormap_t * cm)299 et_use_colormap(view_t *v, colormap_t *cm)
300 {
301           return (0); /* XXX: Nothing here for now... */
302 }
303 
304 static view_t *
et_alloc_view(dmode_t * mode,dimen_t * dim,u_char depth)305 et_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth)
306 {
307           view_t              *v;
308           bmap_t              *bm;
309           box_t               box;
310           save_area_t         *sa;
311 
312           if (!atari_realconfig) {
313                     v  = &gra_con_view;
314                     bm = &con_bm;
315           } else {
316                     v  = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
317                     bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK);
318           }
319           v->bitmap = bm;
320 
321           /*
322            * Initialize the bitmap
323            */
324           bm->plane         = et_priv.memkva;
325           bm->vga_address   = (void *)kvtop(et_priv.memkva);
326           bm->vga_base      = VGA_BASE;
327           bm->hw_address    = (void *)(PCI_MEM_PHYS | et_priv.linbase);
328           bm->lin_base      = et_priv.linbase;
329           bm->regs          = et_priv.regkva;
330           bm->hw_regs       = (void *)kvtop(et_priv.regkva);
331           bm->reg_size      = REG_MAPPABLE;
332           bm->phys_mappable = FRAME_MAPPABLE;
333           bm->vga_mappable  = VGA_MAPPABLE;
334 
335           bm->bytes_per_row = (mode->size.width * depth) / NBBY;
336           bm->rows          = mode->size.height;
337           bm->depth         = depth;
338 
339           /*
340            * Allocate a save_area.
341            * Note: If atari_realconfig is false, no save area is (can be)
342            * allocated. This means that the plane is the video memory,
343            * which is what's wanted in this case.
344            */
345           if (atari_realconfig) {
346                     v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
347                     sa           = (save_area_t*)v->save_area;
348                     sa->fb_size  = 0;
349                     bm->plane    = (u_char *)sa->sv_fb;
350                     et_loadmode(mode->data, &sa->sv_regs);
351           } else
352                     v->save_area = NULL;
353 
354           v->colormap = alloc_colormap(mode);
355           if (v->colormap) {
356                     INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
357                     init_view(v, bm, mode, &box);
358                     return (v);
359           }
360           if (v != &gra_con_view) {
361                     free(v, M_DEVBUF);
362                     free(bm, M_DEVBUF);
363           }
364           return (NULL);
365 }
366 
367 static void
init_view(view_t * v,bmap_t * bm,dmode_t * mode,box_t * dbox)368 init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox)
369 {
370           v->bitmap    = bm;
371           v->mode      = mode;
372           v->flags     = 0;
373           memcpy(&v->display, dbox, sizeof(box_t));
374 }
375 
376 /* XXX: No more than a stub... */
377 static colormap_t *
alloc_colormap(dmode_t * dm)378 alloc_colormap(dmode_t *dm)
379 {
380           colormap_t          *cm;
381           int                 i;
382 
383           cm = &gra_con_cmap;
384           cm->entry = gra_con_colors;
385 
386           cm->first = 0;
387           cm->size  = 2;
388 
389           for (i = 0; i < 2; i++)
390                     cm->entry[i] = gra_def_color16[i % 16];
391           return (cm);
392 }
393 
394 /*
395  * Go look for a VGA card on the PCI-bus. This search is a
396  * stripped down version of the PCI-probe. It only looks on
397  * bus0 for et4000/et6000 cards. The first card found is used.
398  */
399 int
et_probe_card(void)400 et_probe_card(void)
401 {
402           pci_chipset_tag_t   pc = NULL; /* XXX */
403           pcitag_t            tag;
404           int                           device, found, id, maxndevs;
405 
406           found    = 0;
407           tag      = 0;
408           id       = 0;
409           maxndevs = pci_bus_maxdevs(pc, 0);
410 
411           for (device = 0; !found && (device < maxndevs); device++) {
412 
413                     tag = pci_make_tag(pc, 0, device, 0);
414                     id  = pci_conf_read(pc, tag, PCI_ID_REG);
415                     if (id == 0 || id == 0xffffffff)
416                               continue;
417                     switch (PCI_PRODUCT(id)) {
418                               case PCI_PRODUCT_TSENG_ET6000:
419                               case PCI_PRODUCT_TSENG_ET4000_W32P_A:
420                               case PCI_PRODUCT_TSENG_ET4000_W32P_B:
421                               case PCI_PRODUCT_TSENG_ET4000_W32P_C:
422                               case PCI_PRODUCT_TSENG_ET4000_W32P_D:
423                                         found = 1;
424                                         break;
425                               default:
426                                         break;
427                     }
428           }
429           if (!found)
430                     return (0);
431 
432           if (PCI_PRODUCT(id) ==  PCI_PRODUCT_TSENG_ET6000)
433                     et_priv.board_type = BT_ET6000;
434           else {
435 #ifdef ET4000_HAS_2MB_MEM
436                     volatile u_char *ba;
437 #endif
438 
439                     et_priv.board_type = BT_ET4000;
440 
441 #ifdef ET4000_HAS_2MB_MEM
442                     /* set KEY to access the tseng private registers */
443                     ba = (volatile void *)pci_io_addr;
444                     vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
445                     vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
446 
447                     /* enable memory interleave */
448                     WCrt(ba, CRT_ID_RASCAS_CONFIG, 0xa0);
449                     WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x89);
450 #endif
451           }
452 
453           et_priv.pci_tag = tag;
454 
455           /*
456            * The things below are setup in atari_init.c
457            */
458           et_priv.regkva  = (void *)pci_io_addr;
459           et_priv.memkva  = (void *)pci_mem_addr;
460           et_priv.linbase = PCI_LINMEMBASE; /* XXX pci_conf_read??? */
461           et_priv.memsz   = PCI_VGA_SIZE;
462           et_priv.regsz   = PCI_IO_SIZE;
463 
464           if (!atari_realconfig) {
465                     et_loadmode(&hw_modes[0], NULL);
466                     return (1);
467           }
468 
469           return (1);
470 }
471 
472 static void
et_loadmode(struct grfvideo_mode * mode,et_sv_reg_t * regs)473 et_loadmode(struct grfvideo_mode *mode, et_sv_reg_t *regs)
474 {
475           unsigned short      HDE, VDE;
476           int                 lace, dblscan;
477           int                 uplim, lowlim;
478           int                 i;
479           unsigned char       clock, tmp;
480           volatile u_char     *ba;
481           et_sv_reg_t         loc_regs;
482 
483           if (regs == NULL)
484                     regs = &loc_regs;
485 
486           ba  = et_priv.regkva;
487           HDE = mode->disp_width / 8 - 1;
488           VDE = mode->disp_height - 1;
489 
490           /* figure out whether lace or dblscan is needed */
491 
492           uplim   = mode->disp_height + (mode->disp_height / 4);
493           lowlim  = mode->disp_height - (mode->disp_height / 4);
494           lace    = (((mode->vtotal * 2) > lowlim)
495                        && ((mode->vtotal * 2) < uplim)) ? 1 : 0;
496           dblscan = (((mode->vtotal / 2) > lowlim)
497                        && ((mode->vtotal / 2) < uplim)) ? 1 : 0;
498 
499           /* adjustments */
500           if (lace)
501                     VDE /= 2;
502 
503           regs->misc_output = 0x23; /* Page 0, Color mode */
504           regs->seg_sel     = 0x00;
505           regs->state_ctl   = 0x00;
506 
507           regs->seq[SEQ_ID_RESET]           = 0x03; /* reset off                */
508           regs->seq[SEQ_ID_CLOCKING_MODE]   = 0x21; /* Turn off screen          */
509           regs->seq[SEQ_ID_MAP_MASK]        = 0xff; /* CPU writes all planes*/
510           regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0        */
511           regs->seq[SEQ_ID_MEMORY_MODE]     = 0x0e; /* Seq. Memory mode         */
512 
513           /*
514            * Set the clock...
515            */
516           for (clock = ET_NUMCLOCKS-1; clock > 0; clock--) {
517                     if (et_clockfreqs[clock] <= mode->pixel_clock)
518                               break;
519           }
520           regs->misc_output |= (clock & 3) << 2;
521           regs->aux_mode     = 0xb4 | ((clock & 8) << 3);
522           regs->compat_6845  = (clock & 4) ? 0x0a : 0x08;
523 
524           /*
525            * The display parameters...
526            */
527           regs->crt[CRT_ID_HOR_TOTAL]        =  mode->htotal;
528           regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start)
529                                                             ? mode->hblank_stop - 1
530                                                             : HDE);
531           regs->crt[CRT_ID_START_HOR_BLANK]  = mode->hblank_start;
532           regs->crt[CRT_ID_END_HOR_BLANK]    = (mode->hblank_stop & 0x1f) | 0x80;
533           regs->crt[CRT_ID_START_HOR_RETR]   = mode->hsync_start;
534           regs->crt[CRT_ID_END_HOR_RETR]     = (mode->hsync_stop & 0x1f)
535                                                             | ((mode->hblank_stop & 0x20)
536                                                                       ? 0x80 : 0x00);
537           regs->crt[CRT_ID_VER_TOTAL]        = mode->vtotal;
538           regs->crt[CRT_ID_START_VER_RETR]   = mode->vsync_start;
539           regs->crt[CRT_ID_END_VER_RETR]     = (mode->vsync_stop & 0x0f) | 0x30;
540           regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE;
541           regs->crt[CRT_ID_START_VER_BLANK]  = mode->vblank_start;
542           regs->crt[CRT_ID_END_VER_BLANK]    = mode->vblank_stop;
543           regs->crt[CRT_ID_MODE_CONTROL]     = 0xab;
544           regs->crt[CRT_ID_START_ADDR_HIGH]  = 0x00;
545           regs->crt[CRT_ID_START_ADDR_LOW]   = 0x00;
546           regs->crt[CRT_ID_LINE_COMPARE]     = 0xff;
547           regs->crt[CRT_ID_UNDERLINE_LOC]    = 0x00;
548           regs->crt[CRT_ID_PRESET_ROW_SCAN]  = 0x00;
549           regs->crt[CRT_ID_OFFSET]           = mode->disp_width/16;
550           regs->crt[CRT_ID_MAX_ROW_ADDRESS]  =
551                     0x40 |
552                     (dblscan ? 0x80 : 0x00) |
553                     ((mode->vblank_start & 0x200) ? 0x20 : 0x00);
554           regs->crt[CRT_ID_OVERFLOW] =
555                     0x10 |
556                     ((mode->vtotal       & 0x100) ? 0x01 : 0x00) |
557                     ((VDE                & 0x100) ? 0x02 : 0x00) |
558                     ((mode->vsync_start  & 0x100) ? 0x04 : 0x00) |
559                     ((mode->vblank_start & 0x100) ? 0x08 : 0x00) |
560                     ((mode->vtotal       & 0x200) ? 0x20 : 0x00) |
561                     ((VDE                & 0x200) ? 0x40 : 0x00) |
562                     ((mode->vsync_start  & 0x200) ? 0x80 : 0x00);
563           regs->overfl_high =
564                     0x10 |
565                     ((mode->vblank_start & 0x400) ? 0x01 : 0x00) |
566                     ((mode->vtotal       & 0x400) ? 0x02 : 0x00) |
567                     ((VDE                & 0x400) ? 0x04 : 0x00) |
568                     ((mode->vsync_start  & 0x400) ? 0x08 : 0x00) |
569                     (lace ? 0x80 : 0x00);
570           regs->hor_overfl =
571                     ((mode->htotal       & 0x100) ? 0x01 : 0x00) |
572                     ((mode->hblank_start & 0x100) ? 0x04 : 0x00) |
573                     ((mode->hsync_start  & 0x100) ? 0x10 : 0x00);
574 
575           regs->grf[GCT_ID_SET_RESET]        = 0x00;
576           regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00;
577           regs->grf[GCT_ID_COLOR_COMPARE]    = 0x00;
578           regs->grf[GCT_ID_DATA_ROTATE]      = 0x00;
579           regs->grf[GCT_ID_READ_MAP_SELECT]  = 0x00;
580           regs->grf[GCT_ID_GRAPHICS_MODE]    = mode->depth == 1 ? 0x00: 0x40;
581           regs->grf[GCT_ID_MISC]             = 0x01;
582           regs->grf[GCT_ID_COLOR_XCARE]      = 0x0f;
583           regs->grf[GCT_ID_BITMASK]          = 0xff;
584 
585           for (i = 0; i < 0x10; i++)
586                     regs->attr[i] = i;
587           regs->attr[ACT_ID_ATTR_MODE_CNTL]  = 0x01;
588           regs->attr[ACT_ID_OVERSCAN_COLOR]  = 0x00;
589           regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f;
590           regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00;
591           regs->attr[ACT_ID_COLOR_SELECT]    = 0x00;
592           regs->attr[ACT_ID_MISCELLANEOUS]   = 0x00;
593 
594           /*
595            * XXX: This works for depth == 4. I need some better docs
596            * to fix the other modes....
597            */
598           /*
599            * What we need would be probe functions for RAMDAC/clock chip
600            */
601           vgar(ba, VDAC_ADDRESS);                 /* clear old state */
602           vgar(ba, VDAC_MASK);
603           vgar(ba, VDAC_MASK);
604           vgar(ba, VDAC_MASK);
605           vgar(ba, VDAC_MASK);
606 
607           vgaw(ba, VDAC_MASK, 0);                 /* set to palette */
608           vgar(ba, VDAC_ADDRESS);                 /* clear state */
609 
610           vgaw(ba, VDAC_MASK, 0xff);
611           /*
612            * End of depth stuff
613            */
614 
615           /*
616            * Compute Hsync & Vsync polarity
617            * Note: This seems to be some kind of a black art :-(
618            */
619           tmp = regs->misc_output & 0x3f;
620 #if 1 /* This is according to my BW monitor & Xfree... */
621           if (VDE < 400)
622                     tmp |= 0x40;        /* -hsync +vsync */
623           else if (VDE < 480)
624                     tmp |= 0xc0;        /* -hsync -vsync */
625 #else /* This is according to my color monitor.... */
626           if (VDE < 400)
627                     tmp |= 0x00;        /* +hsync +vsync */
628           else if (VDE < 480)
629                     tmp |= 0x80;        /* +hsync -vsync */
630 #endif
631           /* I'm unable to try the rest.... */
632           regs->misc_output = tmp;
633 
634           if (regs == &loc_regs)
635                     et_hwrest(regs);
636 }
637 
638 void
et_hwsave(et_sv_reg_t * et_regs)639 et_hwsave(et_sv_reg_t *et_regs)
640 {
641           volatile u_char *ba;
642           int                 i, s;
643 
644           ba = et_priv.regkva;
645 
646           s = splhigh();
647 
648           /*
649            * General VGA registers
650            */
651           et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
652           for (i = 0; i < 25; i++)
653                     et_regs->crt[i]  = RCrt(ba, i);
654           for (i = 0; i < 21; i++)
655                     et_regs->attr[i] = RAttr(ba, i | 0x20);
656           for (i = 0; i < 9; i++)
657                     et_regs->grf[i]  = RGfx(ba, i);
658           for (i = 0; i < 5; i++)
659                     et_regs->seq[i]  = RSeq(ba, i);
660 
661           /*
662            * ET4000 extensions
663            */
664           et_regs->ext_start   = RCrt(ba, CTR_ID_EXT_START);
665           et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
666           et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
667           et_regs->hor_overfl  = RCrt(ba, CRT_ID_HOR_OVERFLOW);
668           et_regs->state_ctl   = RSeq(ba, SEQ_ID_STATE_CONTROL);
669           et_regs->aux_mode    = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
670           et_regs->seg_sel     = vgar(ba, GREG_SEGMENTSELECT);
671 
672           splx(s);
673 }
674 
675 void
et_hwrest(et_sv_reg_t * et_regs)676 et_hwrest(et_sv_reg_t *et_regs)
677 {
678           volatile u_char *ba;
679           int                 i, s;
680 
681           ba = et_priv.regkva;
682 
683           s = splhigh();
684 
685           vgaw(ba, GREG_SEGMENTSELECT, 0);
686           vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
687 
688           /*
689            * General VGA registers
690            */
691           WSeq(ba, SEQ_ID_RESET, 0x01);
692           for (i = 1; i < 5; i++)
693                     WSeq(ba, i, et_regs->seq[i]);
694           WSeq(ba, SEQ_ID_RESET, 0x03);
695 
696           /*
697            * Make sure we're allowed to write all crt-registers
698            */
699           WCrt(ba, CRT_ID_END_VER_RETR,
700                     et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
701           for (i = 0; i < 25; i++)
702                     WCrt(ba, i, et_regs->crt[i]);
703           for (i = 0; i < 9; i++)
704                     WGfx(ba, i, et_regs->grf[i]);
705           for (i = 0; i < 21; i++)
706                     WAttr(ba, i | 0x20, et_regs->attr[i]);
707 
708           /*
709            * ET4000 extensions
710            */
711           WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
712           WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
713           WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
714           WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
715           WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
716           WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
717           vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
718 
719           i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
720           WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
721 
722           splx(s);
723 }
724