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