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