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