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