xref: /netbsd-src/sys/dev/pci/machfb.c (revision fd5cb0acea84d278e04e640d37ca2398f894991f)
1 /*	$NetBSD: machfb.c,v 1.20 2005/01/17 22:52:46 martin Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 Bang Jun-Young
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. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * Some code is derived from ATI Rage Pro and Derivatives Programmer's Guide.
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: machfb.c,v 1.20 2005/01/17 22:52:46 martin Exp $");
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/callout.h>
43 
44 #ifdef __sparc__
45 #include <machine/promlib.h>
46 #endif
47 
48 #ifdef __powerpc__
49 #include <dev/ofw/openfirm.h>
50 #include <dev/ofw/ofw_pci.h>
51 #endif
52 
53 #include <dev/ic/videomode.h>
54 
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pcireg.h>
57 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/pciio.h>
59 #include <dev/pci/machfbreg.h>
60 
61 #include <dev/wscons/wsdisplayvar.h>
62 #include <dev/wscons/wsconsio.h>
63 #include <dev/wsfont/wsfont.h>
64 #include <dev/rasops/rasops.h>
65 
66 #include "opt_wsemul.h"
67 
68 #define MACH64_REG_SIZE		1024
69 #define MACH64_REG_OFF		0x7ffc00
70 
71 #define	NBARS		3	/* number of Mach64 PCI BARs */
72 
73 struct vga_bar {
74 	bus_addr_t vb_base;
75 	pcireg_t vb_busaddr;
76 	bus_size_t vb_size;
77 	pcireg_t vb_type;
78 	int vb_flags;
79 };
80 
81 struct mach64_softc {
82 	struct device sc_dev;
83 	pci_chipset_tag_t sc_pc;
84 	pcitag_t sc_pcitag;
85 
86 	struct vga_bar sc_bars[NBARS];
87 	struct vga_bar sc_rom;
88 
89 #define sc_aperbase 	sc_bars[0].vb_base
90 #define sc_apersize	sc_bars[0].vb_size
91 #define sc_aperphys 	sc_bars[0].vb_busaddr
92 
93 #define sc_iobase	sc_bars[1].vb_base
94 #define sc_iosize	sc_bars[1].vb_size
95 
96 #define sc_regbase	sc_bars[2].vb_base
97 #define sc_regsize	sc_bars[2].vb_size
98 #define sc_regphys	sc_bars[2].vb_busaddr
99 
100 	bus_space_tag_t sc_regt;
101 	bus_space_tag_t sc_memt;
102 	bus_space_handle_t sc_regh;
103 	bus_space_handle_t sc_memh;
104 
105 	size_t memsize;
106 	int memtype;
107 
108 	int has_dsp;
109 	int bits_per_pixel;
110 	int max_x, max_y;
111 	int virt_x, virt_y;
112 	int color_depth;
113 
114 	int mem_freq;
115 	int ramdac_freq;
116 	int ref_freq;
117 
118 	int ref_div;
119 	int log2_vclk_post_div;
120 	int vclk_post_div;
121 	int vclk_fb_div;
122 	int mclk_post_div;
123 	int mclk_fb_div;
124 
125 	struct mach64screen *wanted;
126 	struct mach64screen *active;
127 	void (*switchcb)(void *, int, int);
128 	void *switchcbarg;
129 	struct callout switch_callout;
130 	LIST_HEAD(, mach64screen) screens;
131 	const struct wsscreen_descr *currenttype;
132 	u_char sc_cmap_red[256];
133 	u_char sc_cmap_green[256];
134 	u_char sc_cmap_blue[256];
135 	int sc_dacw;
136 };
137 
138 struct mach64screen {
139 	struct rasops_info ri;
140 	LIST_ENTRY(mach64screen) next;
141 	struct mach64_softc *sc;
142 	const struct wsscreen_descr *type;
143 	int active;
144 	u_int16_t *mem;
145 	int dispoffset;
146 	int mindispoffset;
147 	int maxdispoffset;
148 
149 	int cursoron;
150 	int cursorcol;
151 	int cursorrow;
152 	u_int16_t cursortmp;
153 };
154 
155 struct mach64_crtcregs {
156 	u_int32_t h_total_disp;
157 	u_int32_t h_sync_strt_wid;
158 	u_int32_t v_total_disp;
159 	u_int32_t v_sync_strt_wid;
160 	u_int32_t gen_cntl;
161 	u_int32_t clock_cntl;
162 	u_int32_t color_depth;
163 	u_int32_t dot_clock;
164 };
165 
166 struct {
167 	u_int16_t chip_id;
168 	u_int32_t ramdac_freq;
169 } mach64_info[] = {
170 	{ PCI_PRODUCT_ATI_MACH64_CT, 135000 },
171 	{ PCI_PRODUCT_ATI_RAGE_PRO_AGP, 230000 },
172 	{ PCI_PRODUCT_ATI_RAGE_PRO_AGP1X, 230000 },
173 	{ PCI_PRODUCT_ATI_RAGE_PRO_PCI_B, 230000 },
174 	{ PCI_PRODUCT_ATI_RAGE_XL_AGP, 230000 },
175 	{ PCI_PRODUCT_ATI_RAGE_PRO_PCI_P, 230000 },
176 	{ PCI_PRODUCT_ATI_RAGE_PRO_PCI_L, 230000 },
177 	{ PCI_PRODUCT_ATI_RAGE_XL_PCI, 230000 },
178 	{ PCI_PRODUCT_ATI_RAGE_II, 135000 },
179 	{ PCI_PRODUCT_ATI_RAGE_IIP, 200000 },
180 	{ PCI_PRODUCT_ATI_RAGE_IIC_PCI, 230000 },
181 	{ PCI_PRODUCT_ATI_RAGE_IIC_AGP_B, 230000 },
182 	{ PCI_PRODUCT_ATI_RAGE_IIC_AGP_P, 230000 },
183 	{ PCI_PRODUCT_ATI_RAGE_LT_PRO_AGP, 230000 },
184 	{ PCI_PRODUCT_ATI_RAGE_MOB_M3_PCI, 230000 },
185 	{ PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP, 230000 },
186 	{ PCI_PRODUCT_ATI_RAGE_LT, 230000 },
187 	{ PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI, 230000 },
188 	{ PCI_PRODUCT_ATI_RAGE_MOBILITY, 230000 },
189 	{ PCI_PRODUCT_ATI_RAGE_LT_PRO, 230000 },
190 	{ PCI_PRODUCT_ATI_MACH64_VT, 170000 },
191 	{ PCI_PRODUCT_ATI_MACH64_VTB, 200000 },
192 	{ PCI_PRODUCT_ATI_MACH64_VT4, 230000 }
193 };
194 
195 static int mach64_chip_id, mach64_chip_rev;
196 static struct videomode default_mode;
197 static struct mach64screen mach64_console_screen;
198 
199 static char *mach64_memtype_names[] = {
200 	"(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM",
201 	"(unknown type)"
202 };
203 
204 struct videomode mach64_modes[] = {
205 	/* 640x400 @ 70 Hz, 31.5 kHz */
206 	{ 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0 },
207 	/* 640x480 @ 72 Hz, 36.5 kHz */
208 	{ 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0 },
209 	/* 800x600 @ 72 Hz, 48.0 kHz */
210 	{ 50000, 800, 856, 976, 1040, 600, 637, 643, 666,
211 	  VID_PHSYNC | VID_PVSYNC },
212 	/* 1024x768 @ 70 Hz, 56.5 kHz */
213 	{ 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806,
214 	  VID_NHSYNC | VID_NVSYNC },
215 	/* 1152x864 @ 70 Hz, 62.4 kHz */
216 	{ 92000, 1152, 1208, 1368, 1474, 864, 865, 875, 895, 0 },
217 	/* 1280x1024 @ 70 Hz, 74.59 kHz */
218 	{ 126500, 1280, 1312, 1472, 1696, 1024, 1032, 1040, 1068,
219 	  VID_NHSYNC | VID_NVSYNC }
220 };
221 
222 /* Macallan: let the terminal emulator program the palette, it should be in the softc anyway */
223 #if 0
224 /* FIXME values are wrong! */
225 const u_char mach64_cmap[16 * 3] = {
226 	0x00, 0x00, 0x00, /* black */
227 	0x7f, 0x00, 0x00, /* red */
228 	0x00, 0x7f, 0x00, /* green */
229 	0x7f, 0x7f, 0x00, /* brown */
230 	0x00, 0x00, 0x7f, /* blue */
231 	0x7f, 0x00, 0x7f, /* magenta */
232 	0x00, 0x7f, 0x7f, /* cyan */
233 	0xc8, 0xc8, 0xc8, /* white */
234 
235 	0x7f, 0x7f, 0x7f, /* black */
236 	0xff, 0x00, 0x00, /* red */
237 	0x00, 0xff, 0x00, /* green */
238 	0xff, 0xff, 0x00, /* brown */
239 	0x00, 0x00, 0xff, /* blue */
240 	0xff, 0x00, 0xff, /* magenta */
241 	0x00, 0xff, 0xff, /* cyan */
242 	0xff, 0xff, 0xff, /* white */
243 };
244 #endif
245 
246 #ifdef WSEMUL_VT100
247 extern const u_char rasops_cmap[768];
248 #endif
249 
250 int	mach64_match(struct device *, struct cfdata *, void *);
251 void	mach64_attach(struct device *, struct device *, void *);
252 
253 CFATTACH_DECL(machfb, sizeof(struct mach64_softc), mach64_match, mach64_attach,
254     NULL, NULL);
255 
256 void	mach64_init(struct mach64_softc *);
257 int	mach64_get_memsize(struct mach64_softc *);
258 int	mach64_get_max_ramdac(struct mach64_softc *);
259 void	mach64_get_mode(struct mach64_softc *, struct videomode *);
260 int	mach64_calc_crtcregs(struct mach64_softc *, struct mach64_crtcregs *,
261 	    struct videomode *);
262 void	mach64_set_crtcregs(struct mach64_softc *, struct mach64_crtcregs *);
263 int	mach64_modeswitch(struct mach64_softc *, struct videomode *);
264 void	mach64_set_dsp(struct mach64_softc *);
265 void	mach64_set_pll(struct mach64_softc *, int);
266 void	mach64_reset_engine(struct mach64_softc *);
267 void	mach64_init_engine(struct mach64_softc *);
268 void	mach64_adjust_frame(struct mach64_softc *, int, int);
269 void	mach64_init_lut(struct mach64_softc *);
270 void	mach64_switch_screen(struct mach64_softc *);
271 void	mach64_init_screen(struct mach64_softc *, struct mach64screen *,
272 	    const struct wsscreen_descr *, int, long *, int);
273 void	mach64_restore_screen(struct mach64screen *,
274 	    const struct wsscreen_descr *, u_int16_t *);
275 int 	mach64_set_screentype(struct mach64_softc *,
276 	    const struct wsscreen_descr *);
277 int	mach64_is_console(struct pci_attach_args *);
278 
279 void	mach64_cursor(void *, int, int, int);
280 int	mach64_mapchar(void *, int, u_int *);
281 void	mach64_putchar(void *, int, int, u_int, long);
282 void	mach64_copycols(void *, int, int, int, int);
283 void	mach64_erasecols(void *, int, int, int, long);
284 void	mach64_copyrows(void *, int, int, int);
285 void	mach64_eraserows(void *, int, int, long);
286 int	mach64_allocattr(void *, int, int, int, long *);
287 
288 void	mach64_scroll(void *, void *, int);
289 
290 int mach64_putcmap(struct mach64_softc *, struct wsdisplay_cmap *);
291 int mach64_getcmap(struct mach64_softc *, struct wsdisplay_cmap *);
292 int mach64_putpalreg(struct mach64_softc *, uint8_t, uint8_t, uint8_t, uint8_t);
293 void mach64_bitblt(struct mach64_softc *, int, int, int, int, int, int, int, int) ;
294 void mach64_rectfill(struct mach64_softc *, int, int, int, int, int);
295 void mach64_showpal(struct mach64_softc *);
296 
297 #if 0
298 const struct wsdisplay_emulops mach64_emulops = {
299 	mach64_cursor,
300 	mach64_mapchar,
301 	mach64_putchar,
302 	mach64_copycols,
303 	mach64_erasecols,
304 	mach64_copyrows,
305 	mach64_eraserows,
306 	mach64_allocattr,
307 };
308 #endif
309 
310 struct wsscreen_descr mach64_defaultscreen = {
311 	"default",
312 	0, 0,
313 	&mach64_console_screen.ri.ri_ops,
314 	8, 16,
315 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
316 	&default_mode
317 }, mach64_80x25_screen = {
318 	"80x25", 80, 25,
319 	&mach64_console_screen.ri.ri_ops,
320 	8, 16,
321 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
322 	&mach64_modes[0]
323 }, mach64_80x30_screen = {
324 	"80x30", 80, 30,
325 	&mach64_console_screen.ri.ri_ops,
326 	8, 16,
327 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
328 	&mach64_modes[1]
329 }, mach64_80x40_screen = {
330 	"80x40", 80, 40,
331 	&mach64_console_screen.ri.ri_ops,
332 	8, 10,
333 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
334 	&mach64_modes[0]
335 }, mach64_80x50_screen = {
336 	"80x50", 80, 50,
337 	&mach64_console_screen.ri.ri_ops,
338 	8, 8,
339 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
340 	&mach64_modes[0]
341 }, mach64_100x37_screen = {
342 	"100x37", 100, 37,
343 	&mach64_console_screen.ri.ri_ops,
344 	8, 16,
345 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
346 	&mach64_modes[2]
347 }, mach64_128x48_screen = {
348 	"128x48", 128, 48,
349 	&mach64_console_screen.ri.ri_ops,
350 	8, 16,
351 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
352 	&mach64_modes[3]
353 }, mach64_144x54_screen = {
354 	"144x54", 144, 54,
355 	&mach64_console_screen.ri.ri_ops,
356 	8, 16,
357 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
358 	&mach64_modes[4]
359 }, mach64_160x64_screen = {
360 	"160x54", 160, 64,
361 	&mach64_console_screen.ri.ri_ops,
362 	8, 16,
363 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
364 	&mach64_modes[5]
365 };
366 
367 const struct wsscreen_descr *_mach64_scrlist[] = {
368 	&mach64_defaultscreen,
369 	&mach64_80x25_screen,
370 	&mach64_80x30_screen,
371 	&mach64_80x40_screen,
372 	&mach64_80x50_screen,
373 	&mach64_100x37_screen,
374 	&mach64_128x48_screen,
375 	&mach64_144x54_screen,
376 	&mach64_160x64_screen
377 };
378 
379 struct wsscreen_list mach64_screenlist = {
380 	sizeof(_mach64_scrlist) / sizeof(struct wsscreen_descr *),
381 	_mach64_scrlist
382 };
383 
384 int	mach64_ioctl(void *, u_long, caddr_t, int, struct proc *);
385 paddr_t	mach64_mmap(void *, off_t, int);
386 int	mach64_alloc_screen(void *, const struct wsscreen_descr *, void **,
387 	    int *, int *, long *);
388 void	mach64_free_screen(void *, void *);
389 int	mach64_show_screen(void *, void *, int, void (*)(void *, int, int),
390 	    void *);
391 int	mach64_load_font(void *, void *, struct wsdisplay_font *);
392 
393 struct wsdisplay_accessops mach64_accessops = {
394 	mach64_ioctl,
395 	mach64_mmap,
396 	mach64_alloc_screen,
397 	mach64_free_screen,
398 	mach64_show_screen,
399 	NULL,	/* load_font */
400 	NULL,	/* polls */
401 	NULL,	/* getwschar */
402 	NULL,	/* putwschar */
403 	NULL,	/* scroll */
404 	NULL,	/* getborder */
405 	NULL	/* setborder */
406 };
407 
408 /*
409  * Inline functions for getting access to register aperture.
410  */
411 static inline u_int32_t regr(struct mach64_softc *, u_int32_t);
412 static inline u_int8_t regrb(struct mach64_softc *, u_int32_t);
413 static inline void regw(struct mach64_softc *, u_int32_t, u_int32_t);
414 static inline void regwb(struct mach64_softc *, u_int32_t, u_int8_t);
415 static inline void regwb_pll(struct mach64_softc *, u_int32_t, u_int8_t);
416 
417 static inline u_int32_t
418 regr(struct mach64_softc *sc, u_int32_t index)
419 {
420 
421 	return bus_space_read_4(sc->sc_regt, sc->sc_regh, index);
422 }
423 
424 static inline u_int8_t
425 regrb(struct mach64_softc *sc, u_int32_t index)
426 {
427 
428 	return bus_space_read_1(sc->sc_regt, sc->sc_regh, index);
429 }
430 
431 static inline void
432 regw(struct mach64_softc *sc, u_int32_t index, u_int32_t data)
433 {
434 
435 	bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data);
436 	bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, BUS_SPACE_BARRIER_WRITE);
437 }
438 
439 static inline void
440 regwb(struct mach64_softc *sc, u_int32_t index, u_int8_t data)
441 {
442 
443 	bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data);
444 	bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1, BUS_SPACE_BARRIER_WRITE);
445 }
446 
447 static inline void
448 regwb_pll(struct mach64_softc *sc, u_int32_t index, u_int8_t data)
449 {
450 
451 	regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN);
452 	regwb(sc, CLOCK_CNTL + 2, data);
453 	regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN);
454 }
455 
456 static inline void
457 wait_for_fifo(struct mach64_softc *sc, u_int8_t v)
458 {
459 
460 	while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v))
461 		;
462 }
463 
464 static inline void
465 wait_for_idle(struct mach64_softc *sc)
466 {
467 
468 	wait_for_fifo(sc, 16);
469 	while ((regr(sc, GUI_STAT) & 1) != 0)
470 		;
471 }
472 
473 int
474 mach64_match(struct device *parent, struct cfdata *match, void *aux)
475 {
476 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
477 	int i;
478 
479 	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
480 	    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
481 		return 0;
482 
483 	for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++)
484 		if (PCI_PRODUCT(pa->pa_id) == mach64_info[i].chip_id) {
485 			mach64_chip_id = PCI_PRODUCT(pa->pa_id);
486 			mach64_chip_rev = PCI_REVISION(pa->pa_class);
487 			return 1;
488 		}
489 
490 	return 0;
491 }
492 
493 void
494 mach64_attach(struct device *parent, struct device *self, void *aux)
495 {
496 	struct mach64_softc *sc = (void *)self;
497 	struct pci_attach_args *pa = aux;
498 	char devinfo[256];
499 	int bar, reg, id;
500 	struct wsemuldisplaydev_attach_args aa;
501 	long defattr;
502 	int setmode, console;
503 
504 	sc->sc_pc = pa->pa_pc;
505 	sc->sc_pcitag = pa->pa_tag;
506 	sc->sc_dacw=-1;
507 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
508 	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
509 
510 	for (bar = 0; bar < NBARS; bar++) {
511 		reg = PCI_MAPREG_START + (bar * 4);
512 		sc->sc_bars[bar].vb_type = pci_mapreg_type(sc->sc_pc,
513 		    sc->sc_pcitag, reg);
514 		(void)pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, reg,
515 		    sc->sc_bars[bar].vb_type, &sc->sc_bars[bar].vb_base,
516 		    &sc->sc_bars[bar].vb_size, &sc->sc_bars[bar].vb_flags);
517 		sc->sc_bars[bar].vb_busaddr=pci_conf_read(sc->sc_pc, sc->sc_pcitag, reg)&0xfffffff0;
518 	}
519 	sc->sc_memt = pa->pa_memt;
520 
521 	mach64_init(sc);
522 
523 	printf("%s: %d MB aperture at 0x%08x, %d KB registers at 0x%08x\n",
524 	    sc->sc_dev.dv_xname, (u_int)(sc->sc_apersize / (1024 * 1024)),
525 	    (u_int)sc->sc_aperphys, (u_int)(sc->sc_regsize / 1024),
526 	    (u_int)sc->sc_regphys);
527 
528 	if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_CT ||
529 	    ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
530 	      mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) &&
531 	      (mach64_chip_rev & 0x07) == 0))
532 		sc->has_dsp = 0;
533 	else
534 		sc->has_dsp = 1;
535 
536 	sc->memsize = mach64_get_memsize(sc);
537 	if (sc->memsize == 8192)
538 		/* The last page is used as register aperture. */
539 		sc->memsize -= 4;
540 	sc->memtype = regr(sc, CONFIG_STAT0) & 0x07;
541 
542 	/* XXX is there any way to calculate reference frequency from
543 	   known values? */
544 	if (mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI)
545 		sc->ref_freq = 29498;
546 	else
547 		sc->ref_freq = 14318;
548 
549 	regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2);
550 	sc->ref_div = regrb(sc, CLOCK_CNTL + 2);
551 	regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2);
552 	sc->mclk_fb_div = regrb(sc, CLOCK_CNTL + 2);
553 	sc->mem_freq = (2 * sc->ref_freq * sc->mclk_fb_div) /
554 	    (sc->ref_div * 2);
555 	sc->mclk_post_div = (sc->mclk_fb_div * 2 * sc->ref_freq) /
556 	    (sc->mem_freq * sc->ref_div);
557 	sc->ramdac_freq = mach64_get_max_ramdac(sc);
558 	printf("%s: %ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz\n",
559 	    sc->sc_dev.dv_xname, (u_long)sc->memsize,
560 	    mach64_memtype_names[sc->memtype],
561 	    sc->mem_freq / 1000, sc->mem_freq % 1000,
562 	    sc->ramdac_freq / 1000);
563 
564 	id = regr(sc, CONFIG_CHIP_ID) & 0xffff;
565 	if (id != mach64_chip_id) {
566 		printf("%s: chip ID mismatch, 0x%x != 0x%x\n",
567 		    sc->sc_dev.dv_xname, id, mach64_chip_id);
568 		return;
569 	}
570 
571 	console = mach64_is_console(pa);
572 
573 #if defined(__sparc__) || defined(__powerpc__)
574 	if (console) {
575 		mach64_get_mode(sc, &default_mode);
576 		setmode = 0;
577 	} else {
578 		memcpy(&default_mode, &mach64_modes[4], sizeof(struct videomode));
579 		setmode = 1;
580 	}
581 #else
582 	memcpy(&default_mode, &mach64_modes[0], sizeof(struct videomode));
583 	setmode = 1;
584 #endif
585 
586 	sc->bits_per_pixel = 8;
587 	sc->virt_x = default_mode.hdisplay;
588 	sc->virt_y = default_mode.vdisplay;
589 	sc->max_x = sc->virt_x - 1;
590 	sc->max_y = (sc->memsize * 1024) /
591 	    (sc->virt_x * (sc->bits_per_pixel / 8)) - 1;
592 
593 	sc->color_depth = CRTC_PIX_WIDTH_8BPP;
594 
595 	mach64_init_engine(sc);
596 #if 0
597 	mach64_adjust_frame(0, 0);
598 	if (sc->bits_per_pixel == 8)
599 		mach64_init_lut(sc);
600 #endif
601 
602 	printf("%s: initial resolution %dx%d at %d bpp\n", sc->sc_dev.dv_xname,
603 	    default_mode.hdisplay, default_mode.vdisplay,
604 	    sc->bits_per_pixel);
605 
606 	mach64_console_screen.ri.ri_hw = sc;
607 	mach64_console_screen.ri.ri_depth = sc->bits_per_pixel;
608 	mach64_console_screen.ri.ri_bits = (void*)(u_long)sc->sc_aperbase;
609 	mach64_console_screen.ri.ri_width = default_mode.hdisplay;
610 	mach64_console_screen.ri.ri_height = default_mode.vdisplay;
611 	mach64_console_screen.ri.ri_stride = mach64_console_screen.ri.ri_width;
612 
613 	mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER;
614 
615 #ifdef WSEMUL_SUN
616 	mach64_console_screen.ri.ri_flg = RI_CLEAR|RI_CENTER|RI_FORCEMONO;
617 #endif
618 
619 	rasops_init(&mach64_console_screen.ri, mach64_console_screen.ri.ri_height / 16,
620 	    mach64_console_screen.ri.ri_width / 8);	/* XXX width/height are nonsense */
621 
622 	/* enable acceleration */
623 	mach64_console_screen.ri.ri_ops.copyrows=mach64_copyrows;
624 	mach64_console_screen.ri.ri_ops.eraserows=mach64_eraserows;
625 	mach64_console_screen.ri.ri_ops.copycols=mach64_copycols;
626 	mach64_console_screen.ri.ri_ops.erasecols=mach64_erasecols;
627 
628 	mach64_defaultscreen.nrows = mach64_console_screen.ri.ri_rows;
629 	mach64_defaultscreen.ncols = mach64_console_screen.ri.ri_cols;
630 
631 	mach64_console_screen.ri.ri_ops.allocattr(&mach64_console_screen.ri, 0, 0, 0,
632 	    &defattr);
633 
634 	/* really necessary? */
635 	mach64_defaultscreen.capabilities=mach64_console_screen.ri.ri_caps;
636 	mach64_defaultscreen.textops=&mach64_console_screen.ri.ri_ops;
637 
638 	/* Initialize fonts */
639 	/* XXX Macallan: shouldn't that happen /before/ we call rasops_init()? */
640 	wsfont_init();
641 
642 	if (console) {
643 		mach64_init_screen(sc, &mach64_console_screen,
644 		    &mach64_defaultscreen, 1, &defattr, setmode);
645 		wsdisplay_cnattach(&mach64_defaultscreen, &mach64_console_screen.ri,
646 		    0, 0, defattr);
647 	}
648 
649 	mach64_init_lut(sc);
650 
651 #ifdef DEBUG
652 	mach64_showpal(sc);
653 	delay(4000000);
654 #endif
655 	aa.console = console;
656 	aa.scrdata = &mach64_screenlist;
657 	aa.accessops = &mach64_accessops;
658 	aa.accesscookie = sc;
659 
660 	config_found(self, &aa, wsemuldisplaydevprint);
661 }
662 
663 void
664 mach64_init_screen(struct mach64_softc *sc, struct mach64screen *scr,
665     const struct wsscreen_descr *type, int existing, long *attrp, int setmode)
666 {
667 
668 	scr->sc = sc;
669 	scr->type = type;
670 	scr->mindispoffset = 0;
671 	scr->maxdispoffset = sc->memsize * 1024;
672 	scr->dispoffset = 0;
673 	scr->cursorcol = 0;
674 	scr->cursorrow = 0;
675 
676 	scr->mem = (u_int16_t *)malloc(type->nrows * type->ncols * 2,
677 	    M_DEVBUF, M_WAITOK);
678 	if (existing) {
679 		scr->active = 1;
680 
681 		if (setmode && mach64_set_screentype(sc, type)) {
682 			panic("%s: failed to switch video mode",
683 			    sc->sc_dev.dv_xname);
684 		}
685 	} else {
686 		scr->active = 0;
687 	}
688 
689 	LIST_INSERT_HEAD(&sc->screens, scr, next);
690 }
691 
692 void
693 mach64_init(struct mach64_softc *sc)
694 {
695 	u_int32_t *p32, saved_value;
696 	u_int8_t *p;
697 	int need_swap;
698 
699 	if (bus_space_map(sc->sc_memt, sc->sc_aperbase, sc->sc_apersize,
700 		BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) {
701 		panic("%s: failed to map aperture", sc->sc_dev.dv_xname);
702 	}
703 	sc->sc_aperbase = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh);
704 
705 	sc->sc_regt = sc->sc_memt;
706 	bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
707 	    sc->sc_regsize, &sc->sc_regh);
708 	sc->sc_regbase = sc->sc_aperbase + 0x7ffc00;
709 
710 	/*
711 	 * Test wether the aperture is byte swapped or not
712 	 */
713 	p32 = (u_int32_t*)(u_long)sc->sc_aperbase;
714 	saved_value = *p32;
715 	p = (u_int8_t*)(u_long)sc->sc_aperbase;
716 	*p32 = 0x12345678;
717 	if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)
718 		need_swap = 0;
719 	else
720 		need_swap = 1;
721 	if (need_swap) {
722 		sc->sc_aperbase += 0x800000;
723 		sc->sc_apersize -= 0x800000;
724 	}
725 	*p32 = saved_value;
726 
727 	LIST_INIT(&sc->screens);
728 	sc->active = NULL;
729 	sc->currenttype = &mach64_defaultscreen;
730 	callout_init(&sc->switch_callout);
731 }
732 
733 int
734 mach64_get_memsize(struct mach64_softc *sc)
735 {
736 	int tmp, memsize;
737 	int mem_tab[] = {
738 		512, 1024, 2048, 4096, 6144, 8192, 12288, 16384
739 	};
740 
741 	tmp = regr(sc, MEM_CNTL);
742 	if (sc->has_dsp) {
743 		tmp &= 0x0000000f;
744 		if (tmp < 8)
745 			memsize = (tmp + 1) * 512;
746 		else if (tmp < 12)
747 			memsize = (tmp - 3) * 1024;
748 		else
749 			memsize = (tmp - 7) * 2048;
750 	} else {
751 		memsize = mem_tab[tmp & 0x07];
752 	}
753 
754 	return memsize;
755 }
756 
757 int
758 mach64_get_max_ramdac(struct mach64_softc *sc)
759 {
760 	int i;
761 
762 	if ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
763 	     mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) &&
764 	     (mach64_chip_rev & 0x07))
765 		return 170000;
766 
767 	for (i = 0; i < sizeof(mach64_info) / sizeof(mach64_info[0]); i++)
768 		if (mach64_chip_id == mach64_info[i].chip_id)
769 			return mach64_info[i].ramdac_freq;
770 
771 	if (sc->bits_per_pixel == 8)
772 		return 135000;
773 	else
774 		return 80000;
775 }
776 
777 void
778 mach64_get_mode(struct mach64_softc *sc, struct videomode *mode)
779 {
780 	struct mach64_crtcregs crtc;
781 
782 	crtc.h_total_disp = regr(sc, CRTC_H_TOTAL_DISP);
783 	crtc.h_sync_strt_wid = regr(sc, CRTC_H_SYNC_STRT_WID);
784 	crtc.v_total_disp = regr(sc, CRTC_V_TOTAL_DISP);
785 	crtc.v_sync_strt_wid = regr(sc, CRTC_V_SYNC_STRT_WID);
786 
787 	mode->htotal = ((crtc.h_total_disp & 0xffff) + 1) << 3;
788 	mode->hdisplay = ((crtc.h_total_disp >> 16) + 1) << 3;
789 	mode->hsync_start = ((crtc.h_sync_strt_wid & 0xffff) + 1) << 3;
790 	mode->hsync_end = ((crtc.h_sync_strt_wid >> 16) << 3) +
791 	    mode->hsync_start;
792 	mode->vtotal = (crtc.v_total_disp & 0xffff) + 1;
793 	mode->vdisplay = (crtc.v_total_disp >> 16) + 1;
794 	mode->vsync_start = (crtc.v_sync_strt_wid & 0xffff) + 1;
795 	mode->vsync_end = (crtc.v_sync_strt_wid >> 16) + mode->vsync_start;
796 
797 #ifdef MACH64_DEBUG
798 	printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n",
799 	    mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal,
800 	    mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal);
801 #endif
802 }
803 
804 int
805 mach64_calc_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc,
806     struct videomode *mode)
807 {
808 
809 	if (mode->dot_clock > sc->ramdac_freq)
810 		/* Clock too high. */
811 		return 1;
812 
813 	crtc->h_total_disp = (((mode->hdisplay >> 3) - 1) << 16) |
814 	    ((mode->htotal >> 3) - 1);
815 	crtc->h_sync_strt_wid =
816 	    (((mode->hsync_end - mode->hsync_start) >> 3) << 16) |
817 	    ((mode->hsync_start >> 3) - 1);
818 
819 	crtc->v_total_disp = ((mode->vdisplay - 1) << 16) |
820 	    (mode->vtotal - 1);
821 	crtc->v_sync_strt_wid =
822 	    ((mode->vsync_end - mode->vsync_start) << 16) |
823 	    (mode->vsync_start - 1);
824 
825 	if (mode->flags & VID_NVSYNC)
826 		crtc->v_sync_strt_wid |= CRTC_VSYNC_NEG;
827 
828 	switch (sc->bits_per_pixel) {
829 	case 8:
830 		crtc->color_depth = CRTC_PIX_WIDTH_8BPP;
831 		break;
832 	case 16:
833 		crtc->color_depth = CRTC_PIX_WIDTH_16BPP;
834 		break;
835 	case 32:
836 		crtc->color_depth = CRTC_PIX_WIDTH_32BPP;
837 		break;
838 	}
839 
840 	crtc->gen_cntl = 0;
841 	if (mode->flags & VID_INTERLACE)
842 		crtc->gen_cntl |= CRTC_INTERLACE_EN;
843 	if (mode->flags & VID_CSYNC)
844 		crtc->gen_cntl |= CRTC_CSYNC_EN;
845 
846 	crtc->dot_clock = mode->dot_clock;
847 
848 	return 0;
849 }
850 
851 void
852 mach64_set_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc)
853 {
854 
855 	mach64_set_pll(sc, crtc->dot_clock);
856 
857 	if (sc->has_dsp)
858 		mach64_set_dsp(sc);
859 
860 	regw(sc, CRTC_H_TOTAL_DISP, crtc->h_total_disp);
861 	regw(sc, CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
862 	regw(sc, CRTC_V_TOTAL_DISP, crtc->v_total_disp);
863 	regw(sc, CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
864 
865 	regw(sc, CRTC_VLINE_CRNT_VLINE, 0);
866 
867 	regw(sc, CRTC_OFF_PITCH, (sc->virt_x >> 3) << 22);
868 
869 	regw(sc, CRTC_GEN_CNTL, crtc->gen_cntl | crtc->color_depth |
870 	    CRTC_EXT_DISP_EN | CRTC_EXT_EN);
871 }
872 
873 int
874 mach64_modeswitch(struct mach64_softc *sc, struct videomode *mode)
875 {
876 	struct mach64_crtcregs crtc;
877 
878 	if (mach64_calc_crtcregs(sc, &crtc, mode))
879 		return 1;
880 
881 	mach64_set_crtcregs(sc, &crtc);
882 	return 0;
883 }
884 
885 void
886 mach64_reset_engine(struct mach64_softc *sc)
887 {
888 
889 	/* Reset engine.*/
890 	regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE);
891 
892 	/* Enable engine. */
893 	regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE);
894 
895 	/* Ensure engine is not locked up by clearing any FIFO or
896 	   host errors. */
897 	regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK |
898 	    BUS_FIFO_ERR_ACK);
899 }
900 
901 void
902 mach64_init_engine(struct mach64_softc *sc)
903 {
904 	u_int32_t pitch_value;
905 
906 	pitch_value = sc->virt_x;
907 
908 	if (sc->bits_per_pixel == 24)
909 		pitch_value *= 3;
910 
911 	mach64_reset_engine(sc);
912 
913 	wait_for_fifo(sc, 14);
914 
915 	regw(sc, CONTEXT_MASK, 0xffffffff);
916 
917 	regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22);
918 
919 	regw(sc, DST_Y_X, 0);
920 	regw(sc, DST_HEIGHT, 0);
921 	regw(sc, DST_BRES_ERR, 0);
922 	regw(sc, DST_BRES_INC, 0);
923 	regw(sc, DST_BRES_DEC, 0);
924 
925 	regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT |
926 	    DST_Y_TOP_TO_BOTTOM);
927 
928 	regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22);
929 
930 	regw(sc, SRC_Y_X, 0);
931 	regw(sc, SRC_HEIGHT1_WIDTH1, 1);
932 	regw(sc, SRC_Y_X_START, 0);
933 	regw(sc, SRC_HEIGHT2_WIDTH2, 1);
934 
935 	regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
936 
937 	wait_for_fifo(sc, 13);
938 	regw(sc, HOST_CNTL, 0);
939 
940 	regw(sc, PAT_REG0, 0);
941 	regw(sc, PAT_REG1, 0);
942 	regw(sc, PAT_CNTL, 0);
943 
944 	regw(sc, SC_LEFT, 0);
945 	regw(sc, SC_TOP, 0);
946 	regw(sc, SC_BOTTOM, default_mode.vdisplay - 1);
947 	regw(sc, SC_RIGHT, pitch_value - 1);
948 
949 	regw(sc, DP_BKGD_CLR, 0);
950 	regw(sc, DP_FRGD_CLR, 0xffffffff);
951 	regw(sc, DP_WRITE_MASK, 0xffffffff);
952 	regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST);
953 
954 	regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR);
955 
956 	wait_for_fifo(sc, 3);
957 	regw(sc, CLR_CMP_CLR, 0);
958 	regw(sc, CLR_CMP_MASK, 0xffffffff);
959 	regw(sc, CLR_CMP_CNTL, 0);
960 
961 	wait_for_fifo(sc, 2);
962 	switch (sc->bits_per_pixel) {
963 	case 8:
964 		regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP);
965 		regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP);
966 		/* XXX Macallan: huh? We /want/ an 8 bit per channel palette! */
967 		/*regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) & ~DAC_8BIT_EN);*/
968 		regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
969 		break;
970 #if 0
971 	case 32:
972 		regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP);
973 		regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP);
974 		regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
975 		break;
976 #endif
977 	}
978 
979 	wait_for_fifo(sc, 5);
980 	regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20);
981 	regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
982 
983 	wait_for_idle(sc);
984 }
985 
986 void
987 mach64_adjust_frame(struct mach64_softc *sc, int x, int y)
988 {
989 	int offset;
990 
991 	offset = ((x + y * sc->virt_x) * (sc->bits_per_pixel >> 3)) >> 3;
992 
993 	regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) |
994 	     offset);
995 }
996 
997 void
998 mach64_set_dsp(struct mach64_softc *sc)
999 {
1000 	u_int32_t fifo_depth, page_size, dsp_precision, dsp_loop_latency;
1001 	u_int32_t dsp_off, dsp_on, dsp_xclks_per_qw;
1002 	u_int32_t xclks_per_qw, y;
1003 	u_int32_t fifo_off, fifo_on;
1004 
1005 	if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT ||
1006 	    mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II ||
1007 	    mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIP ||
1008 	    mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_PCI ||
1009 	    mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_B ||
1010 	    mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_P) {
1011 		dsp_loop_latency = 0;
1012 		fifo_depth = 24;
1013 	} else {
1014 		dsp_loop_latency = 2;
1015 		fifo_depth = 32;
1016 	}
1017 
1018 	dsp_precision = 0;
1019 	xclks_per_qw = (sc->mclk_fb_div * sc->vclk_post_div * 64 << 11) /
1020 	    (sc->vclk_fb_div * sc->mclk_post_div * sc->bits_per_pixel);
1021 	y = (xclks_per_qw * fifo_depth) >> 11;
1022 	while (y) {
1023 		y >>= 1;
1024 		dsp_precision++;
1025 	}
1026 	dsp_precision -= 5;
1027 	fifo_off = ((xclks_per_qw * (fifo_depth - 1)) >> 5) + (3 << 6);
1028 
1029 	switch (sc->memtype) {
1030 	case DRAM:
1031 	case EDO_DRAM:
1032 	case PSEUDO_EDO:
1033 		if (sc->memsize > 1024) {
1034 			page_size = 9;
1035 			dsp_loop_latency += 6;
1036 		} else {
1037 			page_size = 10;
1038 			if (sc->memtype == DRAM)
1039 				dsp_loop_latency += 8;
1040 			else
1041 				dsp_loop_latency += 7;
1042 		}
1043 		break;
1044 	case SDRAM:
1045 	case SGRAM:
1046 		if (sc->memsize > 1024) {
1047 			page_size = 8;
1048 			dsp_loop_latency += 8;
1049 		} else {
1050 			page_size = 10;
1051 			dsp_loop_latency += 9;
1052 		}
1053 		break;
1054 	default:
1055 		page_size = 10;
1056 		dsp_loop_latency += 9;
1057 		break;
1058 	}
1059 
1060 	if (xclks_per_qw >= (page_size << 11))
1061 		fifo_on = ((2 * page_size + 1) << 6) + (xclks_per_qw >> 5);
1062 	else
1063 		fifo_on = (3 * page_size + 2) << 6;
1064 
1065 	dsp_xclks_per_qw = xclks_per_qw >> dsp_precision;
1066 	dsp_on = fifo_on >> dsp_precision;
1067 	dsp_off = fifo_off >> dsp_precision;
1068 
1069 #ifdef MACH64_DEBUG
1070 	printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n"
1071 	    "dsp_precision = %d, dsp_loop_latency = %d,\n"
1072 	    "mclk_fb_div = %d, vclk_fb_div = %d,\n"
1073 	    "mclk_post_div = %d, vclk_post_div = %d\n",
1074 	    dsp_xclks_per_qw, dsp_on, dsp_off, dsp_precision, dsp_loop_latency,
1075 	    sc->mclk_fb_div, sc->vclk_fb_div,
1076 	    sc->mclk_post_div, sc->vclk_post_div);
1077 #endif
1078 
1079 	regw(sc, DSP_ON_OFF, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF));
1080 	regw(sc, DSP_CONFIG, ((dsp_precision << 20) & DSP_PRECISION) |
1081 	    ((dsp_loop_latency << 16) & DSP_LOOP_LATENCY) |
1082 	    (dsp_xclks_per_qw & DSP_XCLKS_PER_QW));
1083 }
1084 
1085 void
1086 mach64_set_pll(struct mach64_softc *sc, int clock)
1087 {
1088 	int q;
1089 
1090 	q = (clock * sc->ref_div * 100) / (2 * sc->ref_freq);
1091 #ifdef MACH64_DEBUG
1092 	printf("q = %d\n", q);
1093 #endif
1094 	if (q > 25500) {
1095 		printf("Warning: q > 25500\n");
1096 		q = 25500;
1097 		sc->vclk_post_div = 1;
1098 		sc->log2_vclk_post_div = 0;
1099 	} else if (q > 12750) {
1100 		sc->vclk_post_div = 1;
1101 		sc->log2_vclk_post_div = 0;
1102 	} else if (q > 6350) {
1103 		sc->vclk_post_div = 2;
1104 		sc->log2_vclk_post_div = 1;
1105 	} else if (q > 3150) {
1106 		sc->vclk_post_div = 4;
1107 		sc->log2_vclk_post_div = 2;
1108 	} else if (q >= 1600) {
1109 		sc->vclk_post_div = 8;
1110 		sc->log2_vclk_post_div = 3;
1111 	} else {
1112 		printf("Warning: q < 1600\n");
1113 		sc->vclk_post_div = 8;
1114 		sc->log2_vclk_post_div = 3;
1115 	}
1116 	sc->vclk_fb_div = q * sc->vclk_post_div / 100;
1117 
1118 	regwb_pll(sc, MCLK_FB_DIV, sc->mclk_fb_div);
1119 	regwb_pll(sc, VCLK_POST_DIV, sc->log2_vclk_post_div);
1120 	regwb_pll(sc, VCLK0_FB_DIV, sc->vclk_fb_div);
1121 }
1122 
1123 void
1124 mach64_init_lut(struct mach64_softc *sc)
1125 {
1126 	/* XXX this is pretty dodgy since it's perfectly possible that
1127 	   both terminal emulations are compiled into the kernel, in this
1128 	   case we'd install the VT100 colour map which may be wrong */
1129 #ifdef WSEMUL_SUN
1130 	mach64_putpalreg(sc,0,255,255,255);
1131 	mach64_putpalreg(sc,1,0,0,0);
1132 	mach64_putpalreg(sc,255,0,0,0);
1133 #endif
1134 #ifdef WSEMUL_VT100
1135 	{
1136 		int i,idx;
1137 		idx=0;
1138 		for(i=0;i<256;i++) {
1139 			mach64_putpalreg(sc,i,rasops_cmap[idx],rasops_cmap[idx+1],rasops_cmap[idx+2]);
1140 			idx+=3;
1141 		}
1142 	}
1143 #endif
1144 }
1145 
1146 int mach64_putpalreg(struct mach64_softc *sc, uint8_t index, uint8_t r, uint8_t g, uint8_t b)
1147 {
1148 	sc->sc_cmap_red[index]=r;
1149 	sc->sc_cmap_green[index]=g;
1150 	sc->sc_cmap_blue[index]=b;
1151 	/* writing the dac index takes a while, in theory we can poll some register
1152 	   to see when it's ready - but we better avoid writing it unnecessarily */
1153 	if(index!=sc->sc_dacw)
1154 	{
1155 		regwb(sc, DAC_MASK, 0xff);
1156 		regwb(sc, DAC_WINDEX, index);
1157 	}
1158 	sc->sc_dacw=index+1;
1159 	regwb(sc, DAC_DATA, r);
1160 	regwb(sc, DAC_DATA, g);
1161 	regwb(sc, DAC_DATA, b);
1162 	return 0;
1163 }
1164 
1165 int mach64_putcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm)
1166 {
1167 	u_int index = cm->index;
1168 	u_int count = cm->count;
1169 	int i, error;
1170 	u_char rbuf[256], gbuf[256], bbuf[256];
1171 	u_char *r, *g, *b;
1172 
1173 	printf("putcmap: %d %d\n",index, count);
1174 	if (cm->index >= 256 || cm->count > 256 ||
1175 	    (cm->index + cm->count) > 256)
1176 		return EINVAL;
1177 	error = copyin(cm->red, &rbuf[index], count);
1178 	if (error)
1179 		return error;
1180 	error = copyin(cm->green, &gbuf[index], count);
1181 	if (error)
1182 		return error;
1183 	error = copyin(cm->blue, &bbuf[index], count);
1184 	if (error)
1185 		return error;
1186 
1187 	memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
1188 	memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
1189 	memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
1190 
1191 	r = &sc->sc_cmap_red[index];
1192 	g = &sc->sc_cmap_green[index];
1193 	b = &sc->sc_cmap_blue[index];
1194 
1195 	for (i = 0; i < count; i++) {
1196 		mach64_putpalreg(sc,index,*r, *g, *b);
1197 		index++;
1198 		r++, g++, b++;
1199 	}
1200 	return 0;
1201 }
1202 
1203 int mach64_getcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm)
1204 {
1205 	u_int index = cm->index;
1206 	u_int count = cm->count;
1207 	int error;
1208 
1209 	if (index >= 255 || count > 256 || index + count > 256)
1210 		return EINVAL;
1211 
1212 	error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
1213 	if (error)
1214 		return error;
1215 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
1216 	if (error)
1217 		return error;
1218 	error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
1219 	if (error)
1220 		return error;
1221 
1222 	return 0;
1223 }
1224 
1225 void
1226 mach64_switch_screen(struct mach64_softc *sc)
1227 {
1228 	struct mach64screen *scr, *oldscr;
1229 	const struct wsscreen_descr *type;
1230 
1231 	scr = sc->wanted;
1232 	if (!scr) {
1233 		printf("mach64_switch_screen: disappeared\n");
1234 		(*sc->switchcb)(sc->switchcbarg, EIO, 0);
1235 		return;
1236 	}
1237 	type = scr->type;
1238 	oldscr = sc->active; /* can be NULL! */
1239 #ifdef DIAGNOSTIC
1240 	if (oldscr) {
1241 		if (!oldscr->active)
1242 			panic("mach64_switch_screen: not active");
1243 		if (oldscr->type != sc->currenttype)
1244 			panic("mach64_switch_screen: bad type");
1245 	}
1246 #endif
1247 	if (scr == oldscr)
1248 		return;
1249 
1250 #ifdef DIAGNOSTIC
1251 /* XXX Macallan: this one bites us at reboot */
1252 /*	if (scr->active)
1253 		panic("mach64_switch_screen: active");*/
1254 #endif
1255 
1256 	if (oldscr)
1257 		oldscr->active = 0;
1258 
1259 	if (sc->currenttype != type) {
1260 		mach64_set_screentype(sc, type);
1261 		sc->currenttype = type;
1262 	}
1263 
1264 	scr->dispoffset = scr->mindispoffset;
1265 
1266 	if (!oldscr || (scr->dispoffset != oldscr->dispoffset)) {
1267 
1268 	}
1269 
1270 	/* Clear the entire screen. */
1271 
1272 	scr->active = 1;
1273 	mach64_restore_screen(scr, type, scr->mem);
1274 
1275 	sc->active = scr;
1276 
1277 	mach64_cursor(scr, scr->cursoron, scr->cursorrow, scr->cursorcol);
1278 
1279 	sc->wanted = 0;
1280 	if (sc->switchcb)
1281 		(*sc->switchcb)(sc->switchcbarg, 0, 0);
1282 }
1283 
1284 void
1285 mach64_restore_screen(struct mach64screen *scr,
1286     const struct wsscreen_descr *type, u_int16_t *mem)
1287 {
1288 
1289 }
1290 
1291 int
1292 mach64_set_screentype(struct mach64_softc *sc, const struct wsscreen_descr *des)
1293 {
1294 	struct mach64_crtcregs regs;
1295 
1296 	if (mach64_calc_crtcregs(sc, &regs,
1297 	    (struct videomode *)des->modecookie))
1298 		return 1;
1299 
1300 	mach64_set_crtcregs(sc, &regs);
1301 	return 0;
1302 }
1303 
1304 int
1305 mach64_is_console(struct pci_attach_args *pa)
1306 {
1307 #ifdef __sparc__
1308 	int node;
1309 
1310 	node = PCITAG_NODE(pa->pa_tag);
1311 	if (node == -1)
1312 		return 0;
1313 
1314 	return (node == prom_instance_to_package(prom_stdout()));
1315 #elif defined(__powerpc__)
1316 	/* check if we're the /chosen console device */
1317 	int chosen, stdout, node, us;
1318 	us=pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
1319 	chosen = OF_finddevice("/chosen");
1320 	OF_getprop(chosen, "stdout", &stdout, 4);
1321 	node = OF_instance_to_package(stdout);
1322 	printf("us  : %08x\n",us);
1323 	printf("inst: %08x\n",stdout);
1324 	printf("node: %08x\n",node);
1325 	return((us==node)||(us==stdout));
1326 #else
1327 	return 1;
1328 #endif
1329 }
1330 
1331 /*
1332  * wsdisplay_emulops
1333  */
1334 
1335 void
1336 mach64_cursor(void *cookie, int on, int row, int col)
1337 {
1338 
1339 }
1340 
1341 #if 0
1342 int
1343 mach64_mapchar(void *cookie, int uni, u_int *index)
1344 {
1345 
1346 	return 0;
1347 }
1348 
1349 void
1350 mach64_putchar(void *cookie, int row, int col, u_int c, long attr)
1351 {
1352 
1353 }
1354 #endif
1355 
1356 void
1357 mach64_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1358 {
1359 	struct rasops_info *ri=cookie;
1360 	struct mach64_softc *sc=ri->ri_hw;
1361 	int32_t xs,xd,y,width,height;
1362 
1363 	xs=ri->ri_xorigin+ri->ri_font->fontwidth*srccol;
1364 	xd=ri->ri_xorigin+ri->ri_font->fontwidth*dstcol;
1365 	y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1366 	width=ri->ri_font->fontwidth*ncols;
1367 	height=ri->ri_font->fontheight;
1368 	mach64_bitblt(sc,xs,y,xd,y,width,height,MIX_SRC,0xff);
1369 }
1370 
1371 void
1372 mach64_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1373 {
1374 	struct rasops_info *ri=cookie;
1375 	struct mach64_softc *sc=ri->ri_hw;
1376 	int32_t x,y,width,height,fg,bg,ul;;
1377 
1378 	x=ri->ri_xorigin+ri->ri_font->fontwidth*startcol;
1379 	y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1380 	width=ri->ri_font->fontwidth*ncols;
1381 	height=ri->ri_font->fontheight;
1382 	rasops_unpack_attr(fillattr,&fg,&bg,&ul);
1383 
1384 	mach64_rectfill(sc,x,y,width,height,bg);
1385 
1386 }
1387 
1388 void
1389 mach64_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1390 {
1391 	struct rasops_info *ri=cookie;
1392 	struct mach64_softc *sc=ri->ri_hw;
1393 	int32_t x,ys,yd,width,height;
1394 
1395 	x=ri->ri_xorigin;
1396 	ys=ri->ri_yorigin+ri->ri_font->fontheight*srcrow;
1397 	yd=ri->ri_yorigin+ri->ri_font->fontheight*dstrow;
1398 	width=ri->ri_emuwidth;
1399 	height=ri->ri_font->fontheight*nrows;
1400 	mach64_bitblt(sc,x,ys,x,yd,width,height,MIX_SRC,0xff);
1401 }
1402 
1403 void mach64_bitblt(struct mach64_softc *sc, int xs, int ys, int xd, int yd, int width, int height, int rop,
1404 int mask)
1405 {
1406 	uint32_t dest_ctl=0;
1407 	wait_for_idle(sc);
1408 	regw(sc,DP_WRITE_MASK,mask);	/* XXX only good for 8 bit */
1409 	regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP);
1410 	regw(sc,DP_SRC,FRGD_SRC_BLIT);
1411 	regw(sc,DP_MIX,(rop&0xffff)<<16);
1412 	regw(sc,CLR_CMP_CNTL,0);	/* no transparency */
1413 	if(yd<ys) {
1414 		dest_ctl=DST_Y_TOP_TO_BOTTOM;
1415 	} else {
1416 		ys+=height-1;
1417 		yd+=height-1;
1418 		dest_ctl=DST_Y_BOTTOM_TO_TOP;
1419 	}
1420 	if(xd<xs) {
1421 		dest_ctl|=DST_X_LEFT_TO_RIGHT;
1422 		regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT);
1423 	} else {
1424 		dest_ctl|=DST_X_RIGHT_TO_LEFT;
1425 		xs+=width-1;
1426 		xd+=width-1;
1427 		regw(sc,SRC_CNTL,SRC_LINE_X_RIGHT_TO_LEFT);
1428 	}
1429 	regw(sc,DST_CNTL,dest_ctl);
1430 
1431 	regw(sc,SRC_Y_X,(xs<<16)|ys);
1432 	regw(sc,SRC_WIDTH1,width);
1433 	regw(sc,DST_Y_X,(xd<<16)|yd);
1434 	regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height);
1435 	/* as long as the other rasops* functions aren't aware of the blitter we must wait here
1436 	   or the blitter might not be done when someone else draws the next line */
1437 	wait_for_idle(sc);
1438 }
1439 
1440 void mach64_rectfill(struct mach64_softc *sc, int x, int y, int width, int height, int colour)
1441 {
1442 	wait_for_idle(sc);
1443 	regw(sc,DP_WRITE_MASK,0xff);
1444 	regw(sc,DP_FRGD_CLR,colour);
1445 	regw(sc,DP_PIX_WIDTH,DST_8BPP|SRC_8BPP|HOST_8BPP);
1446 	regw(sc,DP_SRC,FRGD_SRC_FRGD_CLR);
1447 	regw(sc,DP_MIX,(MIX_SRC)<<16);
1448 	regw(sc,CLR_CMP_CNTL,0);	/* no transparency */
1449 	regw(sc,SRC_CNTL,SRC_LINE_X_LEFT_TO_RIGHT);
1450 	regw(sc,DST_CNTL,DST_X_LEFT_TO_RIGHT|DST_Y_TOP_TO_BOTTOM);
1451 
1452 	regw(sc,SRC_Y_X,(x<<16)|y);
1453 	regw(sc,SRC_WIDTH1,width);
1454 	regw(sc,DST_Y_X,(x<<16)|y);
1455 	regw(sc,DST_HEIGHT_WIDTH,(width<<16)|height);
1456 	wait_for_idle(sc);
1457 }
1458 
1459 void mach64_showpal(struct mach64_softc *sc)
1460 {
1461 	int i,x=0;
1462 	for (i=0;i<16;i++) {
1463 		mach64_rectfill(sc,x,0,64,64,i);
1464 		x+=64;
1465 	}
1466 }
1467 
1468 int
1469 mach64_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
1470 {
1471 
1472 	return 0;
1473 }
1474 
1475 void
1476 mach64_eraserows(void *cookie, int row, int nrows, long fillattr)
1477 {
1478 	struct rasops_info *ri=cookie;
1479 	struct mach64_softc *sc=ri->ri_hw;
1480 	int32_t x,y,width,height,fg,bg,ul;
1481 
1482 	x=ri->ri_xorigin;
1483 	y=ri->ri_yorigin+ri->ri_font->fontheight*row;
1484 	width=ri->ri_emuwidth;
1485 	height=ri->ri_font->fontheight*nrows;
1486 	rasops_unpack_attr(fillattr,&fg,&bg,&ul);
1487 
1488 	mach64_rectfill(sc,x,y,width,height,bg);
1489 }
1490 
1491 /*
1492  * wsdisplay_accessops
1493  */
1494 
1495 int
1496 mach64_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
1497 {
1498 	/* we'll probably need to add more stuff here */
1499 	struct mach64_softc *sc = v;
1500 	struct wsdisplay_fbinfo *wdf;
1501 	struct mach64screen *ms=sc->active;
1502 	switch (cmd) {
1503 		case WSDISPLAYIO_GTYPE:
1504 			*(u_int *)data = WSDISPLAY_TYPE_PCIMISC;	/* XXX ? */
1505 			return 0;
1506 
1507 		case WSDISPLAYIO_GINFO:
1508 			wdf = (void *)data;
1509 			wdf->height = ms->ri.ri_height;
1510 			wdf->width = ms->ri.ri_width;
1511 			wdf->depth = ms->ri.ri_depth;
1512 			wdf->cmsize = 256;
1513 			return 0;
1514 		case WSDISPLAYIO_GETCMAP:
1515 			return mach64_getcmap(sc, (struct wsdisplay_cmap *)data);
1516 
1517 		case WSDISPLAYIO_PUTCMAP:
1518 			return mach64_putcmap(sc, (struct wsdisplay_cmap *)data);
1519 		/* PCI config read/write passthrough. */
1520 		case PCI_IOC_CFGREAD:
1521 		case PCI_IOC_CFGWRITE:
1522 			return (pci_devioctl(sc->sc_pc, sc->sc_pcitag,
1523 			    cmd, data, flag, p));
1524 #ifdef notyet
1525 		case WSDISPLAYIO_SMODE:
1526 			{
1527 				int new_mode=*(int*)data;
1528 				if(new_mode!=sc->sc_mode)
1529 				{
1530 					sc->sc_mode=new_mode;
1531 					if(new_mode==WSDISPLAYIO_MODE_EMUL)
1532 					{
1533 						/* we'll probably want to reset the console into a known state here
1534 						   just in case the Xserver crashed or didn't properly clean up after
1535 						   itself for whetever reason */
1536 					}
1537 				}
1538 			}
1539 #endif
1540 	}
1541 	return EPASSTHROUGH;
1542 }
1543 
1544 paddr_t
1545 mach64_mmap(void *v, off_t offset, int prot)
1546 {
1547 	struct mach64_softc *sc = v;
1548 	paddr_t pa;
1549 	/* 'regular' framebuffer mmap()ing */
1550 	if(offset<sc->sc_apersize) {
1551 		pa = bus_space_mmap(sc->sc_memt,sc->sc_aperbase+offset,0,prot,BUS_SPACE_MAP_LINEAR);
1552 		return pa;
1553 	}
1554 #if 0
1555 	/* allow XFree86 to mmap() PCI space as if the BARs contain physical addresses */
1556 	if((offset>0x80000000) && (offset<=0xffffffff)) {
1557 		pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR);
1558 		return pa;
1559 	}
1560 #endif
1561 
1562 	if((offset>=sc->sc_aperphys) && (offset<(sc->sc_aperphys+sc->sc_apersize))) {
1563 		pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR);
1564 		return pa;
1565 	}
1566 
1567 	if((offset>=sc->sc_regphys) && (offset<(sc->sc_regphys+sc->sc_regsize))) {
1568 		pa = bus_space_mmap(sc->sc_memt,offset,0,prot,BUS_SPACE_MAP_LINEAR);
1569 		return pa;
1570 	}
1571 
1572 	return -1;
1573 }
1574 
1575 int
1576 mach64_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1577     int *curxp, int *curyp, long *defattrp)
1578 {
1579 	struct mach64_softc *sc = v;
1580 	struct mach64screen *scr;
1581 
1582 	scr = malloc(sizeof(struct mach64screen), M_DEVBUF, M_WAITOK|M_ZERO);
1583 	mach64_init_screen(sc, scr, type, 0, defattrp, sc->active == NULL);
1584 	rasops_init(&scr->ri, mach64_console_screen.ri.ri_height / 16,
1585 	    mach64_console_screen.ri.ri_width / 8);
1586 	scr->ri.ri_hw=sc;
1587 	scr->ri.ri_ops.copyrows=mach64_copyrows;
1588 	scr->ri.ri_ops.eraserows=mach64_eraserows;
1589 	scr->ri.ri_ops.copycols=mach64_copycols;
1590 	scr->ri.ri_ops.erasecols=mach64_erasecols;
1591 
1592 	scr->mem = malloc(type->ncols * type->nrows * 2, M_DEVBUF,
1593 	     M_WAITOK);
1594 	mach64_eraserows(&scr->ri, 0, type->nrows, *defattrp);
1595 	if (sc->active == NULL) {
1596 		scr->active = 1;
1597 		sc->active = scr;
1598 		sc->currenttype = type;
1599 	}
1600 
1601 	*cookiep = scr;
1602 	*curxp = scr->cursorcol;
1603 	*curyp = scr->cursorrow;
1604 
1605 	return 0;
1606 }
1607 
1608 void
1609 mach64_free_screen(void *v, void *cookie)
1610 {
1611 	struct mach64_softc *sc = v;
1612 	struct mach64screen *scr = cookie;
1613 
1614 	LIST_REMOVE(scr, next);
1615 	if (scr != &mach64_console_screen)
1616 		free(scr, M_DEVBUF);
1617 	else
1618 		panic("mach64_free_screen: console");
1619 
1620 	if (sc->active == scr)
1621 		sc->active = 0;
1622 }
1623 
1624 int
1625 mach64_show_screen(void *v, void *cookie, int waitok,
1626     void (*cb)(void *, int, int), void *cbarg)
1627 {
1628 	struct mach64_softc *sc = v;
1629 	struct mach64screen *scr, *oldscr;
1630 
1631 	scr = cookie;
1632 	oldscr = sc->active;
1633 	if (scr == oldscr)
1634 		return 0;
1635 
1636 	sc->wanted = scr;
1637 	sc->switchcb = cb;
1638 	sc->switchcbarg = cbarg;
1639 	if (cb) {
1640 		callout_reset(&sc->switch_callout, 0,
1641 		    (void(*)(void *))mach64_switch_screen, sc);
1642 		return EAGAIN;
1643 	}
1644 
1645 	mach64_switch_screen(sc);
1646 
1647 	return 0;
1648 }
1649 
1650 #if 0
1651 int
1652 mach64_load_font(void *v, void *cookie, struct wsdisplay_font *data)
1653 {
1654 
1655 	return 0;
1656 }
1657 #endif
1658