grfabs_et.c revision 1.12 1 1.12 leo /* $NetBSD: grfabs_et.c,v 1.12 1999/02/19 21:03:00 leo 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.1 leo #include <sys/param.h>
48 1.1 leo #include <sys/queue.h>
49 1.1 leo #include <sys/malloc.h>
50 1.1 leo #include <sys/device.h>
51 1.1 leo #include <sys/systm.h>
52 1.1 leo
53 1.10 leo #include <vm/vm.h>
54 1.10 leo #include <vm/vm_kern.h>
55 1.10 leo
56 1.1 leo /*
57 1.1 leo * For PCI probing...
58 1.1 leo */
59 1.1 leo #include <dev/pci/pcireg.h>
60 1.1 leo #include <dev/pci/pcivar.h>
61 1.10 leo #include <dev/pci/pcidevs.h>
62 1.1 leo
63 1.1 leo #include <machine/iomap.h>
64 1.1 leo #include <machine/video.h>
65 1.1 leo #include <machine/mfp.h>
66 1.6 leo #include <machine/cpu.h>
67 1.1 leo #include <atari/atari/device.h>
68 1.1 leo #include <atari/dev/grfioctl.h>
69 1.1 leo #include <atari/dev/grfabs_reg.h>
70 1.3 leo #include <atari/dev/grfabs_et.h>
71 1.1 leo #include <atari/dev/grf_etreg.h>
72 1.1 leo
73 1.3 leo #define SAVEBUF_SIZE (32*1024 + sizeof(save_area_t))
74 1.1 leo
75 1.1 leo /*
76 1.7 leo * Allow a 16Kb io-region and a 4MB frame buffer to be mapped. This
77 1.7 leo * is more or less required by the XFree server.
78 1.7 leo */
79 1.7 leo #define REG_MAPPABLE (16 * 1024)
80 1.7 leo #define FRAME_MAPPABLE (4 * 1024 * 1024)
81 1.11 thomas #define VGA_MAPPABLE (128 * 1024)
82 1.11 thomas #define VGA_BASE 0xa0000
83 1.7 leo
84 1.7 leo /*
85 1.10 leo * Where we map the PCI registers in the io-space (et6000)
86 1.10 leo * XXX: 0x400 would probably work too...
87 1.10 leo */
88 1.10 leo #define PCI_IOBASE 0x800
89 1.11 thomas /*
90 1.11 thomas * Linear memory base, near the end of the pci area
91 1.11 thomas */
92 1.11 thomas #define PCI_LINMEMBASE 0x0e000000
93 1.10 leo
94 1.10 leo /*
95 1.1 leo * Function decls
96 1.1 leo */
97 1.1 leo static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
98 1.1 leo static colormap_t *alloc_colormap __P((dmode_t *));
99 1.10 leo static void et6000_init __P((void));
100 1.1 leo static void et_display_view __P((view_t *));
101 1.1 leo static view_t *et_alloc_view __P((dmode_t *, dimen_t *, u_char));
102 1.1 leo static void et_boardinit __P((void));
103 1.1 leo static void et_free_view __P((view_t *));
104 1.3 leo static void et_loadmode __P((struct grfvideo_mode *, et_sv_reg_t *));
105 1.1 leo static void et_remove_view __P((view_t *));
106 1.1 leo static void et_save_view __P((view_t *));
107 1.1 leo static int et_use_colormap __P((view_t *, colormap_t *));
108 1.1 leo
109 1.1 leo /*
110 1.1 leo * Our function switch table
111 1.1 leo */
112 1.1 leo struct grfabs_sw et_vid_sw = {
113 1.1 leo et_display_view,
114 1.1 leo et_alloc_view,
115 1.1 leo et_free_view,
116 1.1 leo et_remove_view,
117 1.1 leo et_save_view,
118 1.1 leo et_use_colormap
119 1.1 leo };
120 1.1 leo
121 1.1 leo static struct grfvideo_mode hw_modes[] = {
122 1.1 leo {
123 1.1 leo 0, "", 25175000, /* num, descr, pix-clock */
124 1.3 leo 640, 400, 4, /* width, height, depth */
125 1.5 leo 632/8, 672/8, 688/8, 808/8, 768/8,/* HBS, HBE, HSS, HSE, HT */
126 1.3 leo 399, 450, 408, 413, 449 /* VBS, VBE, VSS, VSE, VT */
127 1.3 leo },
128 1.1 leo {
129 1.1 leo 0, "", 25175000, /* num, descr, pix-clock */
130 1.3 leo 640, 480, 4, /* width, height, depth */
131 1.5 leo 632/8, 672/8, 688/8, 752/8, 752/8,/* HBS, HBE, HSS, HSE, HT */
132 1.3 leo 481, 522, 490, 498, 522 /* VBS, VBE, VSS, VSE, VT */
133 1.1 leo }
134 1.1 leo };
135 1.1 leo
136 1.1 leo static dmode_t vid_modes[] = {
137 1.1 leo { { NULL, NULL },
138 1.3 leo "640x400", { 640, 400 }, 1, (void*)&hw_modes[0], &et_vid_sw },
139 1.3 leo { { NULL, NULL },
140 1.3 leo "640x480", { 640, 480 }, 1, (void*)&hw_modes[1], &et_vid_sw },
141 1.1 leo { { NULL, NULL }, NULL, }
142 1.1 leo };
143 1.1 leo
144 1.1 leo #define ET_NUMCLOCKS 32
145 1.1 leo
146 1.1 leo static u_int et_clockfreqs[ET_NUMCLOCKS] = {
147 1.1 leo 6293750, 7080500, 7875000, 8125000,
148 1.1 leo 9000000, 9375000, 10000000, 11225000,
149 1.1 leo 12587500, 14161000, 15750000, 16250000,
150 1.1 leo 18000000, 18750000, 20000000, 22450000,
151 1.1 leo 25175000, 28322000, 31500000, 32500000,
152 1.1 leo 36000000, 37500000, 40000000, 44900000,
153 1.1 leo 50350000, 56644000, 63000000, 65000000,
154 1.1 leo 72000000, 75000000, 80000000, 89800000
155 1.1 leo };
156 1.1 leo
157 1.1 leo static bmap_t con_bm; /* XXX */
158 1.1 leo
159 1.1 leo struct grfabs_et_priv {
160 1.1 leo pcitag_t pci_tag;
161 1.1 leo volatile caddr_t regkva;
162 1.1 leo volatile caddr_t memkva;
163 1.11 thomas u_int linbase;
164 1.1 leo int regsz;
165 1.1 leo int memsz;
166 1.10 leo int board_type;
167 1.1 leo } et_priv;
168 1.1 leo
169 1.1 leo /*
170 1.10 leo * Board types:
171 1.10 leo */
172 1.10 leo #define BT_ET4000 1
173 1.10 leo #define BT_ET6000 2
174 1.10 leo
175 1.10 leo /*
176 1.1 leo * XXX: called from ite console init routine.
177 1.1 leo * Initialize list of posible video modes.
178 1.1 leo */
179 1.1 leo void
180 1.1 leo et_probe_video(modelp)
181 1.1 leo MODES *modelp;
182 1.1 leo {
183 1.1 leo dmode_t *dm;
184 1.1 leo int i;
185 1.1 leo
186 1.1 leo for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
187 1.1 leo LIST_INSERT_HEAD(modelp, dm, link);
188 1.1 leo }
189 1.1 leo }
190 1.1 leo
191 1.1 leo static void
192 1.1 leo et_display_view(v)
193 1.1 leo view_t *v;
194 1.1 leo {
195 1.1 leo dmode_t *dm = v->mode;
196 1.1 leo bmap_t *bm = v->bitmap;
197 1.1 leo int sv_size;
198 1.1 leo u_short *src, *dst;
199 1.3 leo save_area_t *sa;
200 1.1 leo
201 1.1 leo if (dm->current_view && (dm->current_view != v)) {
202 1.1 leo /*
203 1.1 leo * Mark current view for this mode as no longer displayed
204 1.1 leo */
205 1.1 leo dm->current_view->flags &= ~VF_DISPLAY;
206 1.1 leo }
207 1.1 leo dm->current_view = v;
208 1.1 leo v->flags |= VF_DISPLAY;
209 1.1 leo
210 1.3 leo if ((sa = (save_area_t*)v->save_area) == NULL)
211 1.3 leo return; /* XXX: Can't happen.... */
212 1.3 leo
213 1.3 leo /*
214 1.3 leo * Restore register settings and turn the plane pointer
215 1.3 leo * to the card-memory
216 1.3 leo */
217 1.3 leo et_hwrest(&sa->sv_regs);
218 1.1 leo bm->plane = et_priv.memkva;
219 1.1 leo
220 1.3 leo et_use_colormap(v, v->colormap);
221 1.1 leo
222 1.1 leo /*
223 1.3 leo * Copy the backing store to card-memory
224 1.1 leo */
225 1.3 leo sv_size = sa->fb_size;
226 1.3 leo src = sa->sv_fb;
227 1.3 leo dst = (u_short *)bm->plane;
228 1.1 leo while (sv_size--)
229 1.1 leo *dst++ = *src++;
230 1.1 leo }
231 1.1 leo
232 1.1 leo void
233 1.1 leo et_remove_view(v)
234 1.1 leo view_t *v;
235 1.1 leo {
236 1.1 leo dmode_t *mode = v->mode;
237 1.1 leo
238 1.1 leo if (mode->current_view == v) {
239 1.1 leo #if 0
240 1.1 leo if (v->flags & VF_DISPLAY)
241 1.1 leo panic("Cannot shutdown display\n"); /* XXX */
242 1.1 leo #endif
243 1.1 leo mode->current_view = NULL;
244 1.1 leo }
245 1.1 leo v->flags &= ~VF_DISPLAY;
246 1.1 leo }
247 1.1 leo
248 1.1 leo void
249 1.1 leo et_save_view(v)
250 1.1 leo view_t *v;
251 1.1 leo {
252 1.3 leo bmap_t *bm = v->bitmap;
253 1.3 leo u_char font_height;
254 1.3 leo int sv_size;
255 1.3 leo u_short *src, *dst;
256 1.3 leo save_area_t *sa;
257 1.1 leo
258 1.1 leo if (!atari_realconfig)
259 1.1 leo return;
260 1.3 leo
261 1.1 leo if (RGfx(et_priv.regkva, GCT_ID_MISC) & 1) {
262 1.4 christos #if 0 /* XXX: Can't use printf here.... */
263 1.4 christos printf("et_save_view: Don't know how to save"
264 1.1 leo " a graphics mode\n");
265 1.3 leo #endif
266 1.1 leo return;
267 1.1 leo }
268 1.1 leo if (v->save_area == NULL)
269 1.8 leo v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_NOWAIT);
270 1.1 leo
271 1.1 leo /*
272 1.1 leo * Calculate the size of the copy
273 1.1 leo */
274 1.1 leo font_height = RCrt(et_priv.regkva, CRT_ID_MAX_ROW_ADDRESS) & 0x1f;
275 1.1 leo sv_size = bm->bytes_per_row * (bm->rows / (font_height + 1));
276 1.3 leo sv_size = min(SAVEBUF_SIZE, sv_size);
277 1.1 leo
278 1.3 leo /*
279 1.3 leo * Save all we need to know....
280 1.3 leo */
281 1.3 leo sa = (save_area_t *)v->save_area;
282 1.3 leo et_hwsave(&sa->sv_regs);
283 1.3 leo sa->fb_size = sv_size;
284 1.1 leo src = (u_short *)bm->plane;
285 1.3 leo dst = sa->sv_fb;
286 1.1 leo while (sv_size--)
287 1.1 leo *dst++ = *src++;
288 1.3 leo bm->plane = (u_char *)sa->sv_fb;
289 1.1 leo }
290 1.1 leo
291 1.1 leo void
292 1.1 leo et_free_view(v)
293 1.1 leo view_t *v;
294 1.1 leo {
295 1.1 leo if(v) {
296 1.1 leo et_remove_view(v);
297 1.1 leo if (v->colormap != &gra_con_cmap)
298 1.1 leo free(v->colormap, M_DEVBUF);
299 1.1 leo if (v->save_area != NULL)
300 1.1 leo free(v->save_area, M_DEVBUF);
301 1.1 leo if (v != &gra_con_view) {
302 1.1 leo free(v->bitmap, M_DEVBUF);
303 1.1 leo free(v, M_DEVBUF);
304 1.1 leo }
305 1.1 leo }
306 1.1 leo }
307 1.1 leo
308 1.1 leo static int
309 1.1 leo et_use_colormap(v, cm)
310 1.1 leo view_t *v;
311 1.1 leo colormap_t *cm;
312 1.1 leo {
313 1.1 leo return (0); /* XXX: Nothing here for now... */
314 1.1 leo }
315 1.1 leo
316 1.1 leo static view_t *
317 1.1 leo et_alloc_view(mode, dim, depth)
318 1.1 leo dmode_t *mode;
319 1.1 leo dimen_t *dim;
320 1.1 leo u_char depth;
321 1.1 leo {
322 1.3 leo view_t *v;
323 1.3 leo bmap_t *bm;
324 1.3 leo box_t box;
325 1.3 leo save_area_t *sa;
326 1.1 leo
327 1.1 leo if (!atari_realconfig) {
328 1.1 leo v = &gra_con_view;
329 1.1 leo bm = &con_bm;
330 1.1 leo }
331 1.1 leo else {
332 1.1 leo v = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
333 1.1 leo bm = malloc(sizeof(*bm), M_DEVBUF, M_WAITOK);
334 1.1 leo }
335 1.1 leo v->bitmap = bm;
336 1.1 leo
337 1.1 leo /*
338 1.1 leo * Initialize the bitmap
339 1.1 leo */
340 1.1 leo bm->plane = et_priv.memkva;
341 1.11 thomas bm->vga_address = (caddr_t)kvtop(et_priv.memkva);
342 1.11 thomas bm->vga_base = VGA_BASE;
343 1.11 thomas bm->hw_address = (caddr_t)(PCI_MEM_PHYS | et_priv.linbase);
344 1.11 thomas bm->lin_base = et_priv.linbase;
345 1.1 leo bm->regs = et_priv.regkva;
346 1.6 leo bm->hw_regs = (caddr_t)kvtop(et_priv.regkva);
347 1.7 leo bm->reg_size = REG_MAPPABLE;
348 1.7 leo bm->phys_mappable = FRAME_MAPPABLE;
349 1.11 thomas bm->vga_mappable = VGA_MAPPABLE;
350 1.1 leo
351 1.1 leo bm->bytes_per_row = (mode->size.width * depth) / NBBY;
352 1.1 leo bm->rows = mode->size.height;
353 1.1 leo bm->depth = depth;
354 1.1 leo
355 1.1 leo /*
356 1.1 leo * Allocate a save_area.
357 1.1 leo * Note: If atari_realconfig is false, no save area is (can be)
358 1.1 leo * allocated. This means that the plane is the video memory,
359 1.3 leo * which is what's wanted in this case.
360 1.1 leo */
361 1.1 leo if (atari_realconfig) {
362 1.1 leo v->save_area = malloc(SAVEBUF_SIZE, M_DEVBUF, M_WAITOK);
363 1.3 leo sa = (save_area_t*)v->save_area;
364 1.3 leo sa->fb_size = 0;
365 1.3 leo bm->plane = (u_char *)sa->sv_fb;
366 1.3 leo et_loadmode(mode->data, &sa->sv_regs);
367 1.1 leo }
368 1.1 leo else v->save_area = NULL;
369 1.1 leo
370 1.1 leo v->colormap = alloc_colormap(mode);
371 1.1 leo if (v->colormap) {
372 1.1 leo INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
373 1.1 leo init_view(v, bm, mode, &box);
374 1.1 leo return (v);
375 1.1 leo }
376 1.1 leo if (v != &gra_con_view) {
377 1.1 leo free(v, M_DEVBUF);
378 1.1 leo free(bm, M_DEVBUF);
379 1.1 leo }
380 1.1 leo return (NULL);
381 1.1 leo }
382 1.1 leo
383 1.1 leo static void
384 1.1 leo init_view(v, bm, mode, dbox)
385 1.1 leo view_t *v;
386 1.1 leo bmap_t *bm;
387 1.1 leo dmode_t *mode;
388 1.1 leo box_t *dbox;
389 1.1 leo {
390 1.1 leo v->bitmap = bm;
391 1.1 leo v->mode = mode;
392 1.1 leo v->flags = 0;
393 1.1 leo bcopy(dbox, &v->display, sizeof(box_t));
394 1.1 leo }
395 1.1 leo
396 1.1 leo /* XXX: No more than a stub... */
397 1.1 leo static colormap_t *
398 1.1 leo alloc_colormap(dm)
399 1.1 leo dmode_t *dm;
400 1.1 leo {
401 1.1 leo colormap_t *cm;
402 1.1 leo int i;
403 1.1 leo
404 1.1 leo cm = &gra_con_cmap;
405 1.1 leo cm->entry = gra_con_colors;
406 1.1 leo
407 1.1 leo cm->first = 0;
408 1.1 leo cm->size = 2;
409 1.1 leo
410 1.1 leo for (i = 0; i < 2; i++)
411 1.1 leo cm->entry[i] = gra_def_color16[i % 16];
412 1.1 leo return (cm);
413 1.1 leo }
414 1.1 leo
415 1.1 leo /*
416 1.1 leo * Go look for a VGA card on the PCI-bus. This search is a
417 1.1 leo * stripped down version of the PCI-probe. It only looks on
418 1.10 leo * bus0 for et4000/et6000 cards. The first card found is used.
419 1.1 leo */
420 1.1 leo int
421 1.1 leo et_probe_card()
422 1.1 leo {
423 1.1 leo pci_chipset_tag_t pc = NULL; /* XXX */
424 1.10 leo pcitag_t tag, csr;
425 1.10 leo int device, found, id, maxndevs;
426 1.1 leo
427 1.1 leo found = 0;
428 1.1 leo tag = 0;
429 1.10 leo id = 0;
430 1.1 leo maxndevs = pci_bus_maxdevs(pc, 0);
431 1.1 leo
432 1.10 leo for (device = 0; !found && (device < maxndevs); device++) {
433 1.1 leo
434 1.1 leo tag = pci_make_tag(pc, 0, device, 0);
435 1.1 leo id = pci_conf_read(pc, tag, PCI_ID_REG);
436 1.1 leo if (id == 0 || id == 0xffffffff)
437 1.1 leo continue;
438 1.10 leo switch (PCI_PRODUCT(id)) {
439 1.10 leo case PCI_PRODUCT_TSENG_ET6000:
440 1.10 leo case PCI_PRODUCT_TSENG_ET4000_W32P_A:
441 1.10 leo case PCI_PRODUCT_TSENG_ET4000_W32P_B:
442 1.10 leo case PCI_PRODUCT_TSENG_ET4000_W32P_C:
443 1.10 leo case PCI_PRODUCT_TSENG_ET4000_W32P_D:
444 1.10 leo found = 1;
445 1.10 leo break;
446 1.10 leo default:
447 1.10 leo break;
448 1.1 leo }
449 1.1 leo }
450 1.1 leo if (!found)
451 1.1 leo return (0);
452 1.1 leo
453 1.10 leo if (PCI_PRODUCT(id) == PCI_PRODUCT_TSENG_ET6000)
454 1.10 leo et_priv.board_type = BT_ET6000;
455 1.10 leo else et_priv.board_type = BT_ET4000;
456 1.10 leo
457 1.11 thomas /* Turn on the card */
458 1.11 thomas pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
459 1.11 thomas if (et_priv.board_type == BT_ET6000)
460 1.11 thomas pci_conf_write(pc, tag, PCI_MAPREG_START+4,
461 1.10 leo PCI_IOBASE | PCI_MAPREG_TYPE_IO);
462 1.10 leo csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
463 1.10 leo csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
464 1.10 leo csr |= PCI_COMMAND_MASTER_ENABLE;
465 1.10 leo pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
466 1.10 leo
467 1.1 leo et_priv.pci_tag = tag;
468 1.1 leo
469 1.1 leo /*
470 1.1 leo * The things below are setup in atari_init.c
471 1.1 leo */
472 1.1 leo et_priv.regkva = (volatile caddr_t)pci_io_addr;
473 1.1 leo et_priv.memkva = (volatile caddr_t)pci_mem_addr;
474 1.11 thomas et_priv.linbase = PCI_LINMEMBASE;
475 1.11 thomas et_priv.memsz = PCI_VGA_SIZE;
476 1.7 leo et_priv.regsz = PCI_IO_SIZE;
477 1.1 leo
478 1.1 leo if (found && !atari_realconfig) {
479 1.1 leo et_boardinit();
480 1.3 leo et_loadmode(&hw_modes[0], NULL);
481 1.1 leo return (1);
482 1.1 leo }
483 1.1 leo
484 1.1 leo return (1);
485 1.1 leo }
486 1.1 leo
487 1.1 leo static void
488 1.3 leo et_loadmode(mode, regs)
489 1.3 leo struct grfvideo_mode *mode;
490 1.3 leo et_sv_reg_t *regs;
491 1.1 leo {
492 1.1 leo unsigned short HDE, VDE;
493 1.1 leo int lace, dblscan;
494 1.1 leo int uplim, lowlim;
495 1.3 leo int i;
496 1.1 leo unsigned char clock, tmp;
497 1.1 leo volatile u_char *ba;
498 1.3 leo et_sv_reg_t loc_regs;
499 1.3 leo
500 1.3 leo if (regs == NULL)
501 1.3 leo regs = &loc_regs;
502 1.1 leo
503 1.1 leo ba = et_priv.regkva;
504 1.1 leo HDE = mode->disp_width / 8 - 1;
505 1.1 leo VDE = mode->disp_height - 1;
506 1.1 leo
507 1.1 leo /* figure out whether lace or dblscan is needed */
508 1.1 leo
509 1.1 leo uplim = mode->disp_height + (mode->disp_height / 4);
510 1.1 leo lowlim = mode->disp_height - (mode->disp_height / 4);
511 1.1 leo lace = (((mode->vtotal * 2) > lowlim)
512 1.1 leo && ((mode->vtotal * 2) < uplim)) ? 1 : 0;
513 1.1 leo dblscan = (((mode->vtotal / 2) > lowlim)
514 1.1 leo && ((mode->vtotal / 2) < uplim)) ? 1 : 0;
515 1.1 leo
516 1.1 leo /* adjustments */
517 1.1 leo if (lace)
518 1.1 leo VDE /= 2;
519 1.1 leo
520 1.3 leo regs->misc_output = 0x23; /* Page 0, Color mode */
521 1.3 leo regs->seg_sel = 0x00;
522 1.3 leo regs->state_ctl = 0x00;
523 1.3 leo
524 1.3 leo regs->seq[SEQ_ID_RESET] = 0x03; /* reset off */
525 1.3 leo regs->seq[SEQ_ID_CLOCKING_MODE] = 0x21; /* Turn off screen */
526 1.3 leo regs->seq[SEQ_ID_MAP_MASK] = 0xff; /* Cpu writes all planes*/
527 1.3 leo regs->seq[SEQ_ID_CHAR_MAP_SELECT] = 0x00; /* Char. generator 0 */
528 1.3 leo regs->seq[SEQ_ID_MEMORY_MODE] = 0x0e; /* Seq. Memory mode */
529 1.1 leo
530 1.1 leo /*
531 1.1 leo * Set the clock...
532 1.1 leo */
533 1.1 leo for(clock = ET_NUMCLOCKS-1; clock > 0; clock--) {
534 1.1 leo if (et_clockfreqs[clock] <= mode->pixel_clock)
535 1.1 leo break;
536 1.1 leo }
537 1.3 leo regs->misc_output |= (clock & 3) << 2;
538 1.3 leo regs->aux_mode = 0xb4 | ((clock & 8) << 3);
539 1.3 leo regs->compat_6845 = (clock & 4) ? 0x0a : 0x08;
540 1.3 leo
541 1.3 leo /*
542 1.3 leo * The display parameters...
543 1.3 leo */
544 1.3 leo regs->crt[CRT_ID_HOR_TOTAL] = mode->htotal;
545 1.3 leo regs->crt[CRT_ID_HOR_DISP_ENA_END] = ((HDE >= mode->hblank_start)
546 1.3 leo ? mode->hblank_stop - 1
547 1.3 leo : HDE);
548 1.3 leo regs->crt[CRT_ID_START_HOR_BLANK] = mode->hblank_start;
549 1.3 leo regs->crt[CRT_ID_END_HOR_BLANK] = (mode->hblank_stop & 0x1f) | 0x80;
550 1.3 leo regs->crt[CRT_ID_START_HOR_RETR] = mode->hsync_start;
551 1.3 leo regs->crt[CRT_ID_END_HOR_RETR] = (mode->hsync_stop & 0x1f)
552 1.3 leo | ((mode->hblank_stop & 0x20)
553 1.3 leo ? 0x80 : 0x00);
554 1.3 leo regs->crt[CRT_ID_VER_TOTAL] = mode->vtotal;
555 1.3 leo regs->crt[CRT_ID_START_VER_RETR] = mode->vsync_start;
556 1.3 leo regs->crt[CRT_ID_END_VER_RETR] = (mode->vsync_stop & 0x0f) | 0x30;
557 1.3 leo regs->crt[CRT_ID_VER_DISP_ENA_END] = VDE;
558 1.3 leo regs->crt[CRT_ID_START_VER_BLANK] = mode->vblank_start;
559 1.3 leo regs->crt[CRT_ID_END_VER_BLANK] = mode->vblank_stop;
560 1.3 leo regs->crt[CRT_ID_MODE_CONTROL] = 0xab;
561 1.3 leo regs->crt[CRT_ID_START_ADDR_HIGH] = 0x00;
562 1.3 leo regs->crt[CRT_ID_START_ADDR_LOW] = 0x00;
563 1.3 leo regs->crt[CRT_ID_LINE_COMPARE] = 0xff;
564 1.3 leo regs->crt[CRT_ID_UNDERLINE_LOC] = 0x00;
565 1.3 leo regs->crt[CRT_ID_OFFSET] = mode->disp_width/16;
566 1.3 leo regs->crt[CRT_ID_MAX_ROW_ADDRESS] =
567 1.3 leo 0x40 |
568 1.3 leo (dblscan ? 0x80 : 0x00) |
569 1.3 leo ((mode->vblank_start & 0x200) ? 0x20 : 0x00);
570 1.3 leo regs->crt[CRT_ID_OVERFLOW] =
571 1.1 leo 0x10 |
572 1.1 leo ((mode->vtotal & 0x100) ? 0x01 : 0x00) |
573 1.1 leo ((VDE & 0x100) ? 0x02 : 0x00) |
574 1.1 leo ((mode->vsync_start & 0x100) ? 0x04 : 0x00) |
575 1.1 leo ((mode->vblank_start & 0x100) ? 0x08 : 0x00) |
576 1.1 leo ((mode->vtotal & 0x200) ? 0x20 : 0x00) |
577 1.1 leo ((VDE & 0x200) ? 0x40 : 0x00) |
578 1.3 leo ((mode->vsync_start & 0x200) ? 0x80 : 0x00);
579 1.3 leo regs->overfl_high =
580 1.1 leo 0x10 |
581 1.1 leo ((mode->vblank_start & 0x400) ? 0x01 : 0x00) |
582 1.1 leo ((mode->vtotal & 0x400) ? 0x02 : 0x00) |
583 1.1 leo ((VDE & 0x400) ? 0x04 : 0x00) |
584 1.1 leo ((mode->vsync_start & 0x400) ? 0x08 : 0x00) |
585 1.3 leo (lace ? 0x80 : 0x00);
586 1.3 leo regs->hor_overfl =
587 1.1 leo ((mode->htotal & 0x100) ? 0x01 : 0x00) |
588 1.1 leo ((mode->hblank_start & 0x100) ? 0x04 : 0x00) |
589 1.3 leo ((mode->hsync_start & 0x100) ? 0x10 : 0x00);
590 1.3 leo
591 1.3 leo regs->grf[GCT_ID_SET_RESET] = 0x00;
592 1.3 leo regs->grf[GCT_ID_ENABLE_SET_RESET] = 0x00;
593 1.3 leo regs->grf[GCT_ID_COLOR_COMPARE] = 0x00;
594 1.3 leo regs->grf[GCT_ID_DATA_ROTATE] = 0x00;
595 1.3 leo regs->grf[GCT_ID_READ_MAP_SELECT] = 0x00;
596 1.3 leo regs->grf[GCT_ID_GRAPHICS_MODE] = mode->depth == 1 ? 0x00: 0x40;
597 1.3 leo regs->grf[GCT_ID_MISC] = 0x01;
598 1.3 leo regs->grf[GCT_ID_COLOR_XCARE] = 0x0f;
599 1.3 leo regs->grf[GCT_ID_BITMASK] = 0xff;
600 1.3 leo
601 1.3 leo for (i = 0; i < 0x10; i++)
602 1.3 leo regs->attr[i] = i;
603 1.3 leo regs->attr[ACT_ID_ATTR_MODE_CNTL] = 0x01;
604 1.3 leo regs->attr[ACT_ID_OVERSCAN_COLOR] = 0x00;
605 1.3 leo regs->attr[ACT_ID_COLOR_PLANE_ENA] = 0x0f;
606 1.3 leo regs->attr[ACT_ID_HOR_PEL_PANNING] = 0x00;
607 1.3 leo regs->attr[ACT_ID_COLOR_SELECT] = 0x00;
608 1.3 leo regs->attr[ACT_ID_MISCELLANEOUS] = 0x00;
609 1.1 leo
610 1.1 leo /*
611 1.1 leo * XXX: This works for depth == 4. I need some better docs
612 1.1 leo * to fix the other modes....
613 1.1 leo */
614 1.9 thomas /*
615 1.9 thomas * What we need would be probe functions for RAMDAC/clock chip
616 1.9 thomas */
617 1.9 thomas vgar(ba, VDAC_ADDRESS); /* clear old state */
618 1.1 leo vgar(ba, VDAC_MASK);
619 1.1 leo vgar(ba, VDAC_MASK);
620 1.1 leo vgar(ba, VDAC_MASK);
621 1.1 leo vgar(ba, VDAC_MASK);
622 1.1 leo
623 1.9 thomas vgaw(ba, VDAC_MASK, 0); /* set to palette */
624 1.9 thomas vgar(ba, VDAC_ADDRESS); /* clear state */
625 1.9 thomas
626 1.9 thomas vgaw(ba, VDAC_MASK, 0xff);
627 1.1 leo /*
628 1.1 leo * End of depth stuff
629 1.1 leo */
630 1.1 leo
631 1.1 leo /*
632 1.1 leo * Compute Hsync & Vsync polarity
633 1.1 leo * Note: This seems to be some kind of a black art :-(
634 1.1 leo */
635 1.3 leo tmp = regs->misc_output & 0x3f;
636 1.5 leo #if 1 /* This is according to my BW monitor & Xfree... */
637 1.1 leo if (VDE < 400)
638 1.1 leo tmp |= 0x40; /* -hsync +vsync */
639 1.1 leo else if (VDE < 480)
640 1.1 leo tmp |= 0xc0; /* -hsync -vsync */
641 1.1 leo #else /* This is according to my color monitor.... */
642 1.1 leo if (VDE < 400)
643 1.1 leo tmp |= 0x00; /* +hsync +vsync */
644 1.1 leo else if (VDE < 480)
645 1.1 leo tmp |= 0x80; /* +hsync -vsync */
646 1.1 leo #endif
647 1.1 leo /* I'm unable to try the rest.... */
648 1.3 leo regs->misc_output = tmp;
649 1.1 leo
650 1.3 leo if(regs == &loc_regs)
651 1.3 leo et_hwrest(regs);
652 1.1 leo }
653 1.1 leo
654 1.1 leo static void
655 1.1 leo et_boardinit()
656 1.1 leo {
657 1.1 leo volatile u_char *ba;
658 1.1 leo int i, j;
659 1.1 leo
660 1.1 leo ba = et_priv.regkva;
661 1.1 leo
662 1.1 leo vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
663 1.1 leo vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
664 1.1 leo vgaw(ba, GREG_MISC_OUTPUT_W, 0x23);
665 1.1 leo
666 1.1 leo WSeq(ba, SEQ_ID_RESET, 0x03);
667 1.1 leo WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot, Display off */
668 1.1 leo WSeq(ba, SEQ_ID_MAP_MASK, 0x0f);
669 1.1 leo WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
670 1.1 leo WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e);
671 1.1 leo WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4);
672 1.1 leo
673 1.1 leo WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
674 1.1 leo WCrt(ba, CRT_ID_CURSOR_START, 0x00);
675 1.1 leo WCrt(ba, CRT_ID_CURSOR_END, 0x08);
676 1.1 leo WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
677 1.1 leo WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
678 1.1 leo WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
679 1.1 leo WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
680 1.1 leo
681 1.1 leo WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
682 1.1 leo WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3);
683 1.1 leo WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
684 1.1 leo /*
685 1.1 leo * ET4000 special
686 1.1 leo */
687 1.1 leo WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28);
688 1.1 leo WCrt(ba, CTR_ID_EXT_START, 0x00);
689 1.1 leo WCrt(ba, CRT_ID_6845_COMPAT, 0x08);
690 1.10 leo if (et_priv.board_type == BT_ET6000)
691 1.10 leo et6000_init();
692 1.11 thomas else {
693 1.11 thomas WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x43);
694 1.11 thomas WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x09);
695 1.11 thomas }
696 1.1 leo
697 1.1 leo WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00);
698 1.1 leo
699 1.1 leo WGfx(ba, GCT_ID_SET_RESET, 0x00);
700 1.1 leo WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
701 1.1 leo WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00);
702 1.1 leo WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
703 1.1 leo WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
704 1.10 leo WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40);
705 1.10 leo WGfx(ba, GCT_ID_MISC, 0x05);
706 1.1 leo WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
707 1.1 leo WGfx(ba, GCT_ID_BITMASK, 0xff);
708 1.1 leo
709 1.1 leo vgaw(ba, GREG_SEGMENTSELECT, 0x00);
710 1.1 leo
711 1.1 leo for (i = 0; i < 0x10; i++)
712 1.1 leo WAttr(ba, i, i);
713 1.1 leo WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
714 1.1 leo WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
715 1.1 leo WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
716 1.1 leo WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
717 1.1 leo WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
718 1.1 leo WAttr(ba, ACT_ID_MISCELLANEOUS, 0x00);
719 1.1 leo
720 1.1 leo vgaw(ba, VDAC_MASK, 0xff);
721 1.1 leo
722 1.1 leo #if 0 /* XXX: We like to do this: */
723 1.1 leo delay(200000);
724 1.1 leo #else /* But because we run before the delay is initialized: */
725 1.1 leo for(i = 0; i < 4000; i++)
726 1.1 leo for(j = 0; j < 400; j++);
727 1.1 leo #endif
728 1.1 leo
729 1.1 leo /*
730 1.1 leo * colors initially set to greyscale
731 1.1 leo */
732 1.1 leo vgaw(ba, VDAC_ADDRESS_W, 0);
733 1.1 leo for (i = 255; i >= 0; i--) {
734 1.1 leo vgaw(ba, VDAC_DATA, i);
735 1.1 leo vgaw(ba, VDAC_DATA, i);
736 1.1 leo vgaw(ba, VDAC_DATA, i);
737 1.1 leo }
738 1.10 leo }
739 1.10 leo
740 1.10 leo /*
741 1.10 leo * Initialize the et6000 specific (PCI) registers. Try to do it like the
742 1.10 leo * video-bios would have done it, so things like Xservers get what they
743 1.10 leo * expect. Most info was kindly provided by Koen Gadeyne.
744 1.10 leo *
745 1.10 leo * XXX: not fit for programming beauty contest...
746 1.10 leo */
747 1.10 leo static void
748 1.10 leo et6000_init()
749 1.10 leo {
750 1.10 leo
751 1.10 leo volatile u_char *ba;
752 1.10 leo int i;
753 1.10 leo u_char dac_tab[] = { 0x7d,0x67, 0x5d,0x64, 0x56,0x63,
754 1.10 leo 0x28,0x22, 0x79,0x49, 0x6f,0x47,
755 1.12 leo 0x28,0x41, 0x6b,0x44, 0x00,0x00,
756 1.12 leo 0x00,0x00, 0x5d,0x25, 0x00,0x00,
757 1.12 leo 0x00,0x00, 0x00,0x96 };
758 1.10 leo
759 1.10 leo ba = et_priv.regkva + PCI_IOBASE;
760 1.10 leo
761 1.12 leo
762 1.12 leo ba[0x40] = 0x06; /* Use standard vga addressing */
763 1.10 leo ba[0x41] = 0x2a; /* Performance control */
764 1.10 leo ba[0x43] = 0x02; /* XCLK/SCLK config */
765 1.10 leo ba[0x44] = 0x11; /* RAS/CAS config */
766 1.10 leo ba[0x46] = 0x00; /* CRT display feature */
767 1.12 leo ba[0x47] = 0x10;
768 1.10 leo ba[0x58] = 0x00; /* Video Control 1 */
769 1.10 leo ba[0x59] = 0x04; /* Video Control 2 */
770 1.10 leo
771 1.10 leo /*
772 1.10 leo * Setup a 'standard' CLKDAC
773 1.10 leo */
774 1.10 leo ba[0x42] = 0x00; /* MCLK == CLK0 */
775 1.10 leo ba[0x67] = 0x00; /* Start filling from dac-reg 0 and up... */
776 1.12 leo for (i = 0; i < 0x16; i++)
777 1.10 leo ba[0x69] = dac_tab[i];
778 1.12 leo
779 1.12 leo if (ba[8] == 0x70) { /* et6100, right? */
780 1.12 leo volatile u_char *ma;
781 1.12 leo u_char bv;
782 1.12 leo
783 1.12 leo ma = et_priv.memkva;
784 1.12 leo
785 1.12 leo /*
786 1.12 leo * XXX Black magic to get the bloody MDRAM's to function...
787 1.12 leo * XXX _Only_ tested on my card! [leo]
788 1.12 leo */
789 1.12 leo bv = ba[45];
790 1.12 leo ba[0x45] = bv | 0x40; /* Reset MDRAM's */
791 1.12 leo ba[0x45] = bv | 0x70; /* Program latency value */
792 1.12 leo ma[0x0] = 0; /* Yeah, right :-( */
793 1.12 leo ba[0x45] = bv; /* Back to normal */
794 1.12 leo ba[0x44] = 0x14; /* RAS/CAS config */
795 1.12 leo }
796 1.3 leo }
797 1.3 leo
798 1.3 leo void
799 1.3 leo et_hwsave(et_regs)
800 1.3 leo et_sv_reg_t *et_regs;
801 1.3 leo {
802 1.3 leo volatile u_char *ba;
803 1.3 leo int i, s;
804 1.3 leo
805 1.3 leo ba = et_priv.regkva;
806 1.3 leo
807 1.3 leo s = splhigh();
808 1.3 leo
809 1.3 leo /*
810 1.3 leo * General VGA registers
811 1.3 leo */
812 1.3 leo et_regs->misc_output = vgar(ba, GREG_MISC_OUTPUT_R);
813 1.3 leo for(i = 0; i < 25; i++)
814 1.3 leo et_regs->crt[i] = RCrt(ba, i);
815 1.3 leo for(i = 0; i < 21; i++)
816 1.3 leo et_regs->attr[i] = RAttr(ba, i | 0x20);
817 1.3 leo for(i = 0; i < 9; i++)
818 1.3 leo et_regs->grf[i] = RGfx(ba, i);
819 1.3 leo for(i = 0; i < 5; i++)
820 1.3 leo et_regs->seq[i] = RSeq(ba, i);
821 1.3 leo
822 1.3 leo /*
823 1.3 leo * ET4000 extensions
824 1.3 leo */
825 1.3 leo et_regs->ext_start = RCrt(ba, CTR_ID_EXT_START);
826 1.3 leo et_regs->compat_6845 = RCrt(ba, CRT_ID_6845_COMPAT);
827 1.3 leo et_regs->overfl_high = RCrt(ba, CRT_ID_OVERFLOW_HIGH);
828 1.3 leo et_regs->hor_overfl = RCrt(ba, CRT_ID_HOR_OVERFLOW);
829 1.3 leo et_regs->state_ctl = RSeq(ba, SEQ_ID_STATE_CONTROL);
830 1.3 leo et_regs->aux_mode = RSeq(ba, SEQ_ID_AUXILIARY_MODE);
831 1.3 leo et_regs->seg_sel = vgar(ba, GREG_SEGMENTSELECT);
832 1.3 leo
833 1.3 leo s = splx(s);
834 1.3 leo }
835 1.3 leo
836 1.3 leo void
837 1.3 leo et_hwrest(et_regs)
838 1.3 leo et_sv_reg_t *et_regs;
839 1.3 leo {
840 1.3 leo volatile u_char *ba;
841 1.3 leo int i, s;
842 1.3 leo
843 1.3 leo ba = et_priv.regkva;
844 1.3 leo
845 1.3 leo s = splhigh();
846 1.3 leo
847 1.3 leo vgaw(ba, GREG_SEGMENTSELECT, 0);
848 1.3 leo vgaw(ba, GREG_MISC_OUTPUT_W, et_regs->misc_output);
849 1.3 leo
850 1.3 leo /*
851 1.3 leo * General VGA registers
852 1.3 leo */
853 1.12 leo WSeq(ba, SEQ_ID_RESET, 0x01);
854 1.12 leo for(i = 1; i < 5; i++)
855 1.3 leo WSeq(ba, i, et_regs->seq[i]);
856 1.12 leo WSeq(ba, SEQ_ID_RESET, 0x03);
857 1.3 leo
858 1.3 leo /*
859 1.3 leo * Make sure we're allowed to write all crt-registers
860 1.3 leo */
861 1.3 leo WCrt(ba, CRT_ID_END_VER_RETR,
862 1.3 leo et_regs->crt[CRT_ID_END_VER_RETR] & 0x7f);
863 1.3 leo for(i = 0; i < 25; i++)
864 1.3 leo WCrt(ba, i, et_regs->crt[i]);
865 1.3 leo for(i = 0; i < 9; i++)
866 1.3 leo WGfx(ba, i, et_regs->grf[i]);
867 1.3 leo for(i = 0; i < 21; i++)
868 1.3 leo WAttr(ba, i | 0x20, et_regs->attr[i]);
869 1.3 leo
870 1.3 leo /*
871 1.3 leo * ET4000 extensions
872 1.3 leo */
873 1.3 leo WSeq(ba, SEQ_ID_STATE_CONTROL, et_regs->state_ctl);
874 1.3 leo WSeq(ba, SEQ_ID_AUXILIARY_MODE, et_regs->aux_mode);
875 1.3 leo WCrt(ba, CTR_ID_EXT_START, et_regs->ext_start);
876 1.3 leo WCrt(ba, CRT_ID_6845_COMPAT, et_regs->compat_6845);
877 1.3 leo WCrt(ba, CRT_ID_OVERFLOW_HIGH, et_regs->overfl_high);
878 1.3 leo WCrt(ba, CRT_ID_HOR_OVERFLOW, et_regs->hor_overfl);
879 1.3 leo vgaw(ba, GREG_SEGMENTSELECT, et_regs->seg_sel);
880 1.3 leo
881 1.3 leo i = et_regs->seq[SEQ_ID_CLOCKING_MODE] & ~0x20;
882 1.3 leo WSeq(ba, SEQ_ID_CLOCKING_MODE, i);
883 1.3 leo
884 1.3 leo s = splx(s);
885 1.1 leo }
886