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