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