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