xref: /openbsd/sys/arch/sparc64/dev/ifb.c (revision 36fd90dc)
1 /*	$OpenBSD: ifb.c,v 1.24 2021/03/11 11:17:00 jsg Exp $	*/
2 
3 /*
4  * Copyright (c) 2007, 2008, 2009 Miodrag Vallat.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Least-effort driver for the Sun Expert3D cards (based on the
21  * ``Wildcat'' chips).
22  *
23  * There is no public documentation for these chips available.
24  * Since they are no longer supported by 3DLabs (which got bought by
25  * Creative), and Sun does not want to publish even minimal information
26  * or source code, the best we can do is experiment.
27  *
28  * Quoting Alan Coopersmith in
29  * http://mail.opensolaris.org/pipermail/opensolaris-discuss/2005-December/011885.html
30  * ``Unfortunately, the lawyers have asked we not give details about why
31  *   specific components are not being released.''
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/malloc.h>
40 #include <sys/pciio.h>
41 
42 #include <uvm/uvm_extern.h>
43 
44 #include <machine/autoconf.h>
45 #include <machine/bus.h>
46 #include <machine/intr.h>
47 #include <machine/openfirm.h>
48 
49 #include <dev/pci/pcireg.h>
50 #include <dev/pci/pcivar.h>
51 
52 #include <dev/wscons/wsconsio.h>
53 #include <dev/wscons/wsdisplayvar.h>
54 
55 #include <dev/rasops/rasops.h>
56 
57 #include <machine/fbvar.h>
58 
59 #ifdef APERTURE
60 extern int allowaperture;
61 #endif
62 
63 /*
64  * Parts of the following hardware knowledge come from David S. Miller's
65  * XVR-500 Linux driver (drivers/video/sunxvr500.c).
66  */
67 
68 /*
69  * The Expert3D and Expert3d-Lite cards are built around the Wildcat
70  * 5110, 6210 and 7210 chips.
71  *
72  * The card exposes the following resources:
73  * - a 32MB (ifb), 64MB (xvr600) or 128MB (jfb) aperture window in which
74  *   views to the different frame buffer areas can be mapped, in the first BAR.
75  * - a 64KB or 128KB PROM and registers area, in the second BAR.
76  * - a 8MB ``direct burst'' memory mapping, in the third BAR.
77  *
78  * The location of this BAR range is pointed to by a board-specific PCI
79  * configuration register.
80  *
81  * In the state the PROM leaves us in, the 8MB frame buffer windows map
82  * the video memory as interleaved stripes, of which the non-visible parts
83  * can still be addressed (probably for fast screen switching).
84  *
85  * Unfortunately, since we do not know how to reconfigure the stripes
86  * to provide at least a linear frame buffer, we have to write to both
87  * windows and have them provide the complete image.
88  *
89  * Moreover, high pixel values in the overlay planes (such as 0xff or 0xfe)
90  * seem to enable other planes with random contents, so we'll limit ourselves
91  * to 7bpp operation.
92  */
93 
94 /*
95  * The Fcode driver sets up a communication structure, allowing third-party
96  * code to reprogram the video mode while still allowing the Fcode routines
97  * to access the overlay planes.
98  *
99  * We'll use this information as well, although so far it's unlikely
100  * any code will do so, as long as the only documentation for this
101  * hardware amounts to zilch.
102  */
103 
104 /* probably some form of signature */
105 #define	IFB_SHARED_SIGNATURE		0x00
106 #define	SIG_IFB					0x09209911
107 #define	SIG_JFB					0x05140213
108 #define	IFB_SHARED_MONITOR_MODE		0x10
109 #define	IFB_SHARED_WIDTH		0x14
110 #define	IFB_SHARED_HEIGHT		0x18
111 #define	IFB_SHARED_V_FREQ		0x1c
112 #define	IFB_SHARED_TIMING_H_FP		0x20
113 #define	IFB_SHARED_TIMING_H_SYNC	0x24
114 #define	IFB_SHARED_TIMING_H_BP		0x28
115 #define	IFB_SHARED_TIMING_V_FP		0x2c
116 #define	IFB_SHARED_TIMING_V_SYNC	0x30
117 #define	IFB_SHARED_TIMING_V_BP		0x34
118 #define	IFB_SHARED_TIMING_FLAGS		0x38
119 #define	IFB_SHARED_CMAP_DIRTY		0x3c
120 #define	IFB_SHARED_TERM8_GSR		0x4c
121 #define	IFB_SHARED_TERM8_SPR		0x50
122 #define	IFB_SHARED_TERM8_SPLR		0x54
123 
124 /*
125  * The Expert3D has an extra BAR that is not present on the -Lite
126  * version.  This register contains bits that tell us how many BARs to
127  * skip before we get to the BARs that interest us.
128  */
129 #define IFB_PCI_CFG			0x5c
130 #define IFB_PCI_CFG_BAR_OFFSET(x)	((x & 0x000000e0) >> 3)
131 
132 /*
133  * 6000 (jfb) / 8000 (ifb) engine command
134  * This register is used to issue (some) commands sequences to the
135  * acceleration hardware.
136  */
137 #define JFB_REG_ENGINE			0x6000
138 #define IFB_REG_ENGINE			0x8000
139 
140 /*
141  * 8040 component configuration
142  * This register controls which parts of the board will be addressed by
143  * writes to other configuration registers.
144  * Apparently the low two bytes control the frame buffer windows for the
145  * given head (starting at 1).
146  * The high two bytes are texture related.
147  */
148 #define	IFB_REG_COMPONENT_SELECT	0x8040
149 
150 /*
151  * 8044 status
152  * This register has a bit that signals completion of commands issued
153  * to the acceleration hardware.
154  */
155 #define IFB_REG_STATUS			0x8044
156 #define IFB_REG_STATUS_DONE			0x00000004
157 
158 /*
159  * 8058 magnifying configuration
160  * This register apparently controls magnifying.
161  * bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8,
162  *   11: by 16)
163  * bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8)
164  */
165 #define	IFB_REG_MAGNIFY			0x8058
166 #define	IFB_REG_MAGNIFY_DISABLE			0x00000000
167 #define	IFB_REG_MAGNIFY_X2			0x00000040
168 #define	IFB_REG_MAGNIFY_X4			0x00000080
169 #define	IFB_REG_MAGNIFY_X8			0x000000c0
170 #define	IFB_REG_MAGNIFY_WINDIV2			0x00000000
171 #define	IFB_REG_MAGNIFY_WINDIV4			0x00000010
172 #define	IFB_REG_MAGNIFY_WINDIV8			0x00000020
173 #define	IFB_REG_MAGNIFY_WINDIV16		0x00000030
174 
175 /*
176  * 8070 display resolution
177  * Contains the size of the display, as ((height - 1) << 16) | (width - 1)
178  */
179 #define	IFB_REG_RESOLUTION		0x8070
180 /*
181  * 8074 configuration register
182  * Contains 0x1a000088 | ((Log2 stride) << 16)
183  */
184 #define	IFB_REG_CONFIG			0x8074
185 /*
186  * 8078 32bit frame buffer window #0 (8 to 9 MB)
187  * Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
188  */
189 #define	IFB_REG_FB32_0			0x8078
190 /*
191  * 807c 32bit frame buffer window #1 (8 to 9 MB)
192  * Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
193  */
194 #define	IFB_REG_FB32_1			0x807c
195 /*
196  * 8080 8bit frame buffer window #0 (2 to 2.2 MB)
197  * Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
198  */
199 #define	IFB_REG_FB8_0			0x8080
200 /*
201  * 8084 8bit frame buffer window #1 (2 to 2.2 MB)
202  * Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
203  */
204 #define	IFB_REG_FB8_1			0x8084
205 /*
206  * 8088 unknown window (as large as a 32 bit frame buffer)
207  */
208 #define	IFB_REG_FB_UNK0			0x8088
209 /*
210  * 808c unknown window (as large as a 8 bit frame buffer)
211  */
212 #define	IFB_REG_FB_UNK1			0x808c
213 /*
214  * 8090 unknown window (as large as a 8 bit frame buffer)
215  */
216 #define	IFB_REG_FB_UNK2			0x8090
217 
218 /*
219  * 80bc RAMDAC palette index register
220  */
221 #define	IFB_REG_CMAP_INDEX		0x80bc
222 /*
223  * 80c0 RAMDAC palette data register
224  */
225 #define	IFB_REG_CMAP_DATA		0x80c0
226 
227 /*
228  * 80e4 DPMS state register
229  * States ``off'' and ``suspend'' need chip reprogramming before video can
230  * be enabled again.
231  */
232 #define	IFB_REG_DPMS_STATE		0x80e4
233 #define	IFB_REG_DPMS_OFF			0x00000000
234 #define	IFB_REG_DPMS_SUSPEND			0x00000001
235 #define	IFB_REG_DPMS_STANDBY			0x00000002
236 #define	IFB_REG_DPMS_ON				0x00000003
237 
238 /*
239  * (some) ROP codes
240  */
241 
242 #define	IFB_ROP_CLEAR	0x00000000	/* clear bits in rop mask */
243 #define	IFB_ROP_SRC	0x00330000	/* copy src bits matching rop mask */
244 #define	IFB_ROP_XOR	0x00cc0000	/* xor src bits with rop mask */
245 #define	IFB_ROP_SET	0x00ff0000	/* set bits in rop mask */
246 
247 #define IFB_COORDS(x, y)	((x) | (y) << 16)
248 
249 /* blitter directions */
250 #define IFB_BLT_DIR_BACKWARDS_Y		(0x08 | 0x02)
251 #define IFB_BLT_DIR_BACKWARDS_X		(0x04 | 0x01)
252 
253 #define	IFB_PIXELMASK	0x7f	/* 7bpp */
254 
255 struct ifb_softc {
256 	struct sunfb sc_sunfb;
257 
258 	bus_space_tag_t sc_mem_t;
259 	pcitag_t sc_pcitag;
260 
261 	/* overlays mappings */
262 	bus_space_handle_t sc_mem_h;
263 	bus_addr_t sc_membase, sc_fb8bank0_base, sc_fb8bank1_base;
264 	bus_size_t sc_memlen;
265 	vaddr_t	sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr;
266 
267 	/* registers mapping */
268 	bus_space_handle_t sc_reg_h;
269 	bus_addr_t sc_regbase;
270 	bus_size_t sc_reglen;
271 
272 	/* communication area */
273 	volatile uint32_t *sc_comm;
274 
275 	/* acceleration information */
276 	u_int	sc_acceltype;
277 #define	IFB_ACCEL_NONE			0
278 #define	IFB_ACCEL_IFB			1	/* Expert3D style */
279 #define	IFB_ACCEL_JFB			2	/* XVR-500 style */
280 	void (*sc_rop)(void *, int, int, int, int, int, int, uint32_t, int32_t);
281 
282 	/* wsdisplay related goo */
283 	u_int	sc_mode;
284 	struct wsdisplay_emulops sc_old_ops;
285 	u_int8_t sc_cmap_red[256];
286 	u_int8_t sc_cmap_green[256];
287 	u_int8_t sc_cmap_blue[256];
288 };
289 
290 int	ifb_ioctl(void *, u_long, caddr_t, int, struct proc *);
291 paddr_t	ifb_mmap(void *, off_t, int);
292 void	ifb_burner(void *, u_int, u_int);
293 
294 struct wsdisplay_accessops ifb_accessops = {
295 	.ioctl = ifb_ioctl,
296 	.mmap = ifb_mmap,
297 	.burn_screen = ifb_burner
298 };
299 
300 int	ifbmatch(struct device *, void *, void *);
301 void	ifbattach(struct device *, struct device *, void *);
302 
303 struct cfattach ifb_ca = {
304 	sizeof (struct ifb_softc), ifbmatch, ifbattach
305 };
306 
307 struct cfdriver ifb_cd = {
308 	NULL, "ifb", DV_DULL
309 };
310 
311 int	ifb_accel_identify(const char *);
312 static inline
313 u_int	ifb_dac_value(u_int, u_int, u_int);
314 int	ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *);
315 static inline
316 int	ifb_is_console(int);
317 int	ifb_mapregs(struct ifb_softc *, struct pci_attach_args *);
318 int	ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *);
319 void	ifb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
320 void	ifb_setcolormap(struct sunfb *,
321 	    void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t));
322 
323 void	ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int);
324 void	ifb_fillrect(struct ifb_softc *, int, int, int, int, int);
325 static inline
326 void	ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t,
327 	    int32_t);
328 void	ifb_rop_common(struct ifb_softc *, bus_addr_t, int, int, int, int,
329 	    int, int, uint32_t, int32_t);
330 void	ifb_rop_ifb(void *, int, int, int, int, int, int, uint32_t, int32_t);
331 void	ifb_rop_jfb(void *, int, int, int, int, int, int, uint32_t, int32_t);
332 int	ifb_rop_wait(struct ifb_softc *);
333 
334 int	ifb_putchar_dumb(void *, int, int, u_int, uint32_t);
335 int	ifb_copycols_dumb(void *, int, int, int, int);
336 int	ifb_erasecols_dumb(void *, int, int, int, uint32_t);
337 int	ifb_copyrows_dumb(void *, int, int, int);
338 int	ifb_eraserows_dumb(void *, int, int, uint32_t);
339 int	ifb_do_cursor_dumb(struct rasops_info *);
340 
341 int	ifb_putchar(void *, int, int, u_int, uint32_t);
342 int	ifb_copycols(void *, int, int, int, int);
343 int	ifb_erasecols(void *, int, int, int, uint32_t);
344 int	ifb_copyrows(void *, int, int, int);
345 int	ifb_eraserows(void *, int, int, uint32_t);
346 int	ifb_do_cursor(struct rasops_info *);
347 
348 int
349 ifbmatch(struct device *parent, void *cf, void *aux)
350 {
351 	return ifb_ident(aux);
352 }
353 
354 void
355 ifbattach(struct device *parent, struct device *self, void *aux)
356 {
357 	struct ifb_softc *sc = (struct ifb_softc *)self;
358 	struct pci_attach_args *paa = aux;
359 	struct rasops_info *ri;
360 	uint32_t dev_comm;
361 	int node, console;
362 	char *name, *text;
363 	char namebuf[32];
364 
365 	sc->sc_mem_t = paa->pa_memt;
366 	sc->sc_pcitag = paa->pa_tag;
367 
368 	node = PCITAG_NODE(paa->pa_tag);
369 	console = ifb_is_console(node);
370 
371 	printf("\n");
372 
373 	/*
374 	 * Multiple heads appear as PCI subfunctions.
375 	 * However, the ofw node for it lacks most properties,
376 	 * and its BAR only give access to registers, not
377 	 * frame buffer memory.
378 	 */
379 	if (!node_has_property(node, "device_type")) {
380 		printf("%s: secondary output not supported yet\n",
381 		    self->dv_xname);
382 		return;
383 	}
384 
385 	/*
386 	 * Describe the beast.
387 	 */
388 
389 	name = text = getpropstringA(node, "name", namebuf);
390 	if (strncmp(text, "SUNW,", 5) == 0)
391 		text += 5;
392 	printf("%s: %s", self->dv_xname, text);
393 	text = getpropstring(node, "model");
394 	if (*text != '\0')
395 		printf(" (%s)", text);
396 
397 	if (ifb_mapregs(sc, paa))
398 		return;
399 
400 	sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
401 	      IFB_REG_FB8_0);
402 	sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
403 	      IFB_REG_FB8_1);
404 
405 	sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h);
406 	sc->sc_fb8bank0_vaddr = sc->sc_memvaddr +
407 	    sc->sc_fb8bank0_base - sc->sc_membase;
408 	sc->sc_fb8bank1_vaddr = sc->sc_memvaddr +
409 	    sc->sc_fb8bank1_base - sc->sc_membase;
410 
411 	/*
412 	 * The values stored into the node properties might have been
413 	 * modified since the Fcode was last run. Pick the geometry
414 	 * information from the configuration registers instead.
415 	 * This replaces
416 	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
417 	 */
418 
419 	sc->sc_sunfb.sf_width = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
420 	    IFB_REG_RESOLUTION) & 0xffff) + 1;
421 	sc->sc_sunfb.sf_height = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
422 	    IFB_REG_RESOLUTION) >> 16) + 1;
423 	sc->sc_sunfb.sf_depth = 8;
424 	sc->sc_sunfb.sf_linebytes = 1 << (bus_space_read_4(sc->sc_mem_t,
425 	    sc->sc_reg_h, IFB_REG_CONFIG) >> 16);
426 	sc->sc_sunfb.sf_fbsize =
427 	    sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
428 
429 	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
430 
431 	ri = &sc->sc_sunfb.sf_ro;
432 	ri->ri_bits = NULL;
433 	ri->ri_hw = sc;
434 
435 	fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
436 
437 	/*
438 	 * Find out what flavour of ifb we are...
439 	 */
440 
441 	sc->sc_acceltype = ifb_accel_identify(name);
442 
443 	switch (sc->sc_acceltype) {
444 	case IFB_ACCEL_IFB:
445 		sc->sc_rop = ifb_rop_ifb;
446 		break;
447 	case IFB_ACCEL_JFB:
448 		/*
449 		 * Remember the address of the communication area
450 		 */
451 		if (OF_getprop(node, "dev-comm", &dev_comm,
452 		    sizeof dev_comm) != -1) {
453 			sc->sc_comm = (volatile uint32_t *)(vaddr_t)dev_comm;
454 		}
455 		sc->sc_rop = ifb_rop_jfb;
456 		break;
457 	}
458 
459 	/*
460 	 * Clear the unwanted pixel planes: all if non console (thus
461 	 * white background), and all planes above 7bpp otherwise.
462 	 * This also allows to check whether the accelerated code works,
463 	 * or not.
464 	 */
465 
466 	if (sc->sc_acceltype != IFB_ACCEL_NONE) {
467 		ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width,
468 		    sc->sc_sunfb.sf_height, IFB_ROP_CLEAR,
469 		    console ? ~IFB_PIXELMASK : ~0);
470 		if (ifb_rop_wait(sc) == 0) {
471 			/* fall back to dumb software operation */
472 			sc->sc_acceltype = IFB_ACCEL_NONE;
473 		}
474 	}
475 
476 	if (sc->sc_acceltype == IFB_ACCEL_NONE) {
477 		/* due to the way we will handle updates */
478 		ri->ri_flg &= ~RI_FULLCLEAR;
479 
480 		if (!console) {
481 			bzero((void *)sc->sc_fb8bank0_vaddr,
482 			    sc->sc_sunfb.sf_fbsize);
483 			bzero((void *)sc->sc_fb8bank1_vaddr,
484 			    sc->sc_sunfb.sf_fbsize);
485 		}
486 	}
487 
488 	/* pick centering delta */
489 	sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits;
490 	sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits;
491 
492 	sc->sc_old_ops = ri->ri_ops;	/* structure copy */
493 
494 	if (sc->sc_acceltype != IFB_ACCEL_NONE) {
495 		ri->ri_ops.copyrows = ifb_copyrows;
496 		ri->ri_ops.copycols = ifb_copycols;
497 		ri->ri_ops.eraserows = ifb_eraserows;
498 		ri->ri_ops.erasecols = ifb_erasecols;
499 		ri->ri_ops.putchar = ifb_putchar_dumb;
500 		ri->ri_do_cursor = ifb_do_cursor;
501 	} else {
502 		ri->ri_ops.copyrows = ifb_copyrows_dumb;
503 		ri->ri_ops.copycols = ifb_copycols_dumb;
504 		ri->ri_ops.eraserows = ifb_eraserows_dumb;
505 		ri->ri_ops.erasecols = ifb_erasecols_dumb;
506 		ri->ri_ops.putchar = ifb_putchar_dumb;
507 		ri->ri_do_cursor = ifb_do_cursor_dumb;
508 	}
509 
510 	ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
511 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
512 
513 	if (console)
514 		fbwscons_console_init(&sc->sc_sunfb, -1);
515 	fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, console);
516 }
517 
518 /*
519  * Attempt to identify what kind of ifb we are talking to, so as to setup
520  * proper acceleration information.
521  */
522 int
523 ifb_accel_identify(const char *name)
524 {
525 	if (strcmp(name, "SUNW,Expert3D") == 0 ||
526 	    strcmp(name, "SUNW,Expert3D-Lite") == 0)
527 		return IFB_ACCEL_IFB;	/* ifblite */
528 
529 	if (strcmp(name, "SUNW,XVR-1200") == 0)
530 		return IFB_ACCEL_JFB;	/* jfb */
531 
532 	if (strcmp(name, "SUNW,XVR-600") == 0)
533 		return IFB_ACCEL_JFB;	/* xvr600 */
534 
535 	/* XVR-500 is bobcat */
536 
537 	return IFB_ACCEL_NONE;
538 }
539 
540 int
541 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
542 {
543 	struct ifb_softc *sc = v;
544 	struct wsdisplay_fbinfo *wdf;
545 	struct pcisel *sel;
546 	int mode;
547 
548 	switch (cmd) {
549 	case WSDISPLAYIO_GTYPE:
550 		*(u_int *)data = WSDISPLAY_TYPE_IFB;
551 		break;
552 
553 	case WSDISPLAYIO_SMODE:
554 		mode = *(u_int *)data;
555 		if (mode == WSDISPLAYIO_MODE_EMUL)
556 			ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
557 		sc->sc_mode = mode;
558 		break;
559 	case WSDISPLAYIO_GINFO:
560 		wdf = (void *)data;
561 		wdf->height = sc->sc_sunfb.sf_height;
562 		wdf->width  = sc->sc_sunfb.sf_width;
563 		wdf->depth  = sc->sc_sunfb.sf_depth;
564 		wdf->cmsize = 256;
565 		break;
566 	case WSDISPLAYIO_LINEBYTES:
567 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
568 		break;
569 
570 	case WSDISPLAYIO_GETCMAP:
571 		return ifb_getcmap(sc, (struct wsdisplay_cmap *)data);
572 	case WSDISPLAYIO_PUTCMAP:
573 		return ifb_putcmap(sc, (struct wsdisplay_cmap *)data);
574 
575 	case WSDISPLAYIO_GPCIID:
576 		sel = (struct pcisel *)data;
577 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
578 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
579 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
580 		break;
581 
582 	case WSDISPLAYIO_SVIDEO:
583 	case WSDISPLAYIO_GVIDEO:
584 		break;
585 
586 	case WSDISPLAYIO_GCURPOS:
587 	case WSDISPLAYIO_SCURPOS:
588 	case WSDISPLAYIO_GCURMAX:
589 	case WSDISPLAYIO_GCURSOR:
590 	case WSDISPLAYIO_SCURSOR:
591 	default:
592 		return -1; /* not supported yet */
593         }
594 
595 	return 0;
596 }
597 
598 static inline
599 u_int
600 ifb_dac_value(u_int r, u_int g, u_int b)
601 {
602 	/*
603 	 * Convert 8 bit values to 10 bit scale, by shifting and inserting
604 	 * the former high bits in the low two bits.
605 	 * Simply shifting is slightly too dull.
606 	 */
607 	r = (r << 2) | (r >> 6);
608 	g = (g << 2) | (g >> 6);
609 	b = (b << 2) | (b >> 6);
610 
611 	return (b << 20) | (g << 10) | r;
612 }
613 
614 int
615 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
616 {
617 	u_int index = cm->index;
618 	u_int count = cm->count;
619 	int error;
620 
621 	if (index >= 256 || count > 256 - index)
622 		return EINVAL;
623 
624 	error = copyout(&sc->sc_cmap_red[index], cm->red, count);
625 	if (error)
626 		return error;
627 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
628 	if (error)
629 		return error;
630 	error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
631 	if (error)
632 		return error;
633 	return 0;
634 }
635 
636 int
637 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
638 {
639 	u_int index = cm->index;
640 	u_int count = cm->count;
641 	u_int i;
642 	int error;
643 	u_char *r, *g, *b;
644 
645 	if (index >= 256 || count > 256 - index)
646 		return EINVAL;
647 
648 	if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
649 		return error;
650 	if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
651 		return error;
652 	if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
653 		return error;
654 
655 	r = &sc->sc_cmap_red[index];
656 	g = &sc->sc_cmap_green[index];
657 	b = &sc->sc_cmap_blue[index];
658 
659 	for (i = 0; i < count; i++) {
660 		bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
661 		    IFB_REG_CMAP_INDEX, index);
662 		bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
663 		    ifb_dac_value(*r, *g, *b));
664 		r++, g++, b++, index++;
665 	}
666 	return 0;
667 }
668 
669 void
670 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
671 {
672 	struct ifb_softc *sc = v;
673 
674 	sc->sc_cmap_red[index] = r;
675 	sc->sc_cmap_green[index] = g;
676 	sc->sc_cmap_blue[index] = b;
677 
678 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_INDEX,
679 	    index);
680 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
681 	    ifb_dac_value(r, g, b));
682 }
683 
684 /* similar in spirit to fbwscons_setcolormap() */
685 void
686 ifb_setcolormap(struct sunfb *sf,
687     void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
688 {
689 	struct rasops_info *ri = &sf->sf_ro;
690 	int i;
691 	const u_char *color;
692 
693 	/*
694 	 * Compensate for overlay plane limitations. Since we'll operate
695 	 * in 7bpp mode, our basic colors will use positions 00 to 0f,
696 	 * and the inverted colors will use positions 7f to 70.
697 	 */
698 
699 	for (i = 0x00; i < 0x10; i++) {
700 		color = &rasops_cmap[i * 3];
701 		setcolor(sf, i, color[0], color[1], color[2]);
702 	}
703 	for (i = 0x70; i < 0x80; i++) {
704 		color = &rasops_cmap[(0xf0 | i) * 3];
705 		setcolor(sf, i, color[0], color[1], color[2]);
706 	}
707 
708 	/*
709 	 * Proper operation apparently needs black to be 01, always.
710 	 * Replace black, red and white with white, black and red.
711 	 * Kind of ugly, but it works.
712 	 */
713 	ri->ri_devcmap[WSCOL_WHITE] = 0x00000000;
714 	ri->ri_devcmap[WSCOL_BLACK] = 0x01010101;
715 	ri->ri_devcmap[WSCOL_RED] = 0x07070707;
716 
717 	color = &rasops_cmap[(WSCOL_WHITE + 8) * 3];	/* real white */
718 	setcolor(sf, 0, color[0], color[1], color[2]);
719 	setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]);
720 	color = &rasops_cmap[WSCOL_BLACK * 3];
721 	setcolor(sf, 1, color[0], color[1], color[2]);
722 	setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]);
723 	color = &rasops_cmap[WSCOL_RED * 3];
724 	setcolor(sf, 7, color[0], color[1], color[2]);
725 	setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]);
726 }
727 
728 paddr_t
729 ifb_mmap(void *v, off_t off, int prot)
730 {
731 	struct ifb_softc *sc = (struct ifb_softc *)v;
732 
733 	switch (sc->sc_mode) {
734 	case WSDISPLAYIO_MODE_MAPPED:
735 		/*
736 		 * In mapped mode, provide access to the two overlays,
737 		 * followed by the control registers, at the following
738 		 * addresses:
739 		 * 00000000	overlay 0, size up to 2MB (visible fb size)
740 		 * 01000000	overlay 1, size up to 2MB (visible fb size)
741 		 * 02000000	control registers
742 		 */
743 		off -= 0x00000000;
744 		if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
745 			return bus_space_mmap(sc->sc_mem_t,
746 			    sc->sc_fb8bank0_base,
747 			    off, prot, BUS_SPACE_MAP_LINEAR);
748 		}
749 		off -= 0x01000000;
750 		if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
751 			return bus_space_mmap(sc->sc_mem_t,
752 			    sc->sc_fb8bank1_base,
753 			    off, prot, BUS_SPACE_MAP_LINEAR);
754 		}
755 #ifdef APERTURE
756 		off -= 0x01000000;
757 		if (allowaperture != 0 && sc->sc_acceltype != IFB_ACCEL_NONE) {
758 			if (off >= 0 && off < round_page(sc->sc_reglen)) {
759 				return bus_space_mmap(sc->sc_mem_t,
760 				    sc->sc_regbase,
761 				    off, prot, BUS_SPACE_MAP_LINEAR);
762 			}
763 		}
764 #endif
765 		break;
766 	}
767 
768 	return -1;
769 }
770 
771 void
772 ifb_burner(void *v, u_int on, u_int flags)
773 {
774 	struct ifb_softc *sc = (struct ifb_softc *)v;
775 	int s;
776 	uint32_t dpms;
777 
778 	s = splhigh();
779 	if (on)
780 		dpms = IFB_REG_DPMS_ON;
781 	else {
782 #ifdef notyet
783 		if (flags & WSDISPLAY_BURN_VBLANK)
784 			dpms = IFB_REG_DPMS_SUSPEND;
785 		else
786 #endif
787 			dpms = IFB_REG_DPMS_STANDBY;
788 	}
789 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_DPMS_STATE, dpms);
790 	splx(s);
791 }
792 
793 static inline int
794 ifb_is_console(int node)
795 {
796 	extern int fbnode;
797 
798 	return fbnode == node;
799 }
800 
801 int
802 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa)
803 {
804 	u_int32_t cf;
805 	int bar, rc;
806 
807 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG);
808 	bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf);
809 
810 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);
811 	if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
812 		rc = EINVAL;
813 	else {
814 		rc = pci_mapreg_map(pa, bar, cf,
815 		    BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h,
816 		    &sc->sc_membase, &sc->sc_memlen, 0);
817 	}
818 	if (rc != 0) {
819 		printf("\n%s: can't map video memory\n",
820 		    sc->sc_sunfb.sf_dev.dv_xname);
821 		return rc;
822 	}
823 
824 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4);
825 	if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
826 		rc = EINVAL;
827 	else {
828 		rc = pci_mapreg_map(pa, bar + 4, cf,
829 		    0, NULL, &sc->sc_reg_h,
830 		     &sc->sc_regbase, &sc->sc_reglen, 0x9000);
831 	}
832 	if (rc != 0) {
833 		printf("\n%s: can't map register space\n",
834 		    sc->sc_sunfb.sf_dev.dv_xname);
835 		return rc;
836 	}
837 
838 	return 0;
839 }
840 
841 /*
842  * Non accelerated routines.
843  */
844 
845 int
846 ifb_putchar_dumb(void *cookie, int row, int col, u_int uc, uint32_t attr)
847 {
848 	struct rasops_info *ri = cookie;
849 	struct ifb_softc *sc = ri->ri_hw;
850 
851 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
852 	sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
853 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
854 	sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
855 
856 	return 0;
857 }
858 
859 int
860 ifb_copycols_dumb(void *cookie, int row, int src, int dst, int num)
861 {
862 	struct rasops_info *ri = cookie;
863 	struct ifb_softc *sc = ri->ri_hw;
864 
865 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
866 	sc->sc_old_ops.copycols(cookie, row, src, dst, num);
867 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
868 	sc->sc_old_ops.copycols(cookie, row, src, dst, num);
869 
870 	return 0;
871 }
872 
873 int
874 ifb_erasecols_dumb(void *cookie, int row, int col, int num, uint32_t attr)
875 {
876 	struct rasops_info *ri = cookie;
877 	struct ifb_softc *sc = ri->ri_hw;
878 
879 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
880 	sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
881 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
882 	sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
883 
884 	return 0;
885 }
886 
887 int
888 ifb_copyrows_dumb(void *cookie, int src, int dst, int num)
889 {
890 	struct rasops_info *ri = cookie;
891 	struct ifb_softc *sc = ri->ri_hw;
892 
893 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
894 	sc->sc_old_ops.copyrows(cookie, src, dst, num);
895 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
896 	sc->sc_old_ops.copyrows(cookie, src, dst, num);
897 
898 	return 0;
899 }
900 
901 int
902 ifb_eraserows_dumb(void *cookie, int row, int num, uint32_t attr)
903 {
904 	struct rasops_info *ri = cookie;
905 	struct ifb_softc *sc = ri->ri_hw;
906 
907 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
908 	sc->sc_old_ops.eraserows(cookie, row, num, attr);
909 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
910 	sc->sc_old_ops.eraserows(cookie, row, num, attr);
911 
912 	return 0;
913 }
914 
915 /* Similar to rasops_do_cursor(), but using a 7bit pixel mask. */
916 
917 #define	CURSOR_MASK	0x7f7f7f7f
918 
919 int
920 ifb_do_cursor_dumb(struct rasops_info *ri)
921 {
922 	struct ifb_softc *sc = ri->ri_hw;
923 	int full1, height, cnt, slop1, slop2, row, col;
924 	int ovl_offset = sc->sc_fb8bank1_vaddr - sc->sc_fb8bank0_vaddr;
925 	u_char *dp0, *dp1, *rp;
926 
927 	row = ri->ri_crow;
928 	col = ri->ri_ccol;
929 
930 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
931 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
932 	height = ri->ri_font->fontheight;
933 	slop1 = (4 - ((long)rp & 3)) & 3;
934 
935 	if (slop1 > ri->ri_xscale)
936 		slop1 = ri->ri_xscale;
937 
938 	slop2 = (ri->ri_xscale - slop1) & 3;
939 	full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
940 
941 	if ((slop1 | slop2) == 0) {
942 		/* A common case */
943 		while (height--) {
944 			dp0 = rp;
945 			dp1 = dp0 + ovl_offset;
946 			rp += ri->ri_stride;
947 
948 			for (cnt = full1; cnt; cnt--) {
949 				*(int32_t *)dp0 ^= CURSOR_MASK;
950 				*(int32_t *)dp1 ^= CURSOR_MASK;
951 				dp0 += 4;
952 				dp1 += 4;
953 			}
954 		}
955 	} else {
956 		/* XXX this is stupid.. use masks instead */
957 		while (height--) {
958 			dp0 = rp;
959 			dp1 = dp0 + ovl_offset;
960 			rp += ri->ri_stride;
961 
962 			if (slop1 & 1) {
963 				*dp0++ ^= (u_char)CURSOR_MASK;
964 				*dp1++ ^= (u_char)CURSOR_MASK;
965 			}
966 
967 			if (slop1 & 2) {
968 				*(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
969 				*(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
970 				dp0 += 2;
971 				dp1 += 2;
972 			}
973 
974 			for (cnt = full1; cnt; cnt--) {
975 				*(int32_t *)dp0 ^= CURSOR_MASK;
976 				*(int32_t *)dp1 ^= CURSOR_MASK;
977 				dp0 += 4;
978 				dp1 += 4;
979 			}
980 
981 			if (slop2 & 1) {
982 				*dp0++ ^= (u_char)CURSOR_MASK;
983 				*dp1++ ^= (u_char)CURSOR_MASK;
984 			}
985 
986 			if (slop2 & 2) {
987 				*(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
988 				*(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
989 			}
990 		}
991 	}
992 
993 	return 0;
994 }
995 
996 /*
997  * Accelerated routines.
998  */
999 
1000 int
1001 ifb_copycols(void *cookie, int row, int src, int dst, int num)
1002 {
1003 	struct rasops_info *ri = cookie;
1004 	struct ifb_softc *sc = ri->ri_hw;
1005 
1006 	num *= ri->ri_font->fontwidth;
1007 	src *= ri->ri_font->fontwidth;
1008 	dst *= ri->ri_font->fontwidth;
1009 	row *= ri->ri_font->fontheight;
1010 
1011 	ifb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
1012 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
1013 	    num, ri->ri_font->fontheight);
1014 
1015 	return 0;
1016 }
1017 
1018 int
1019 ifb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
1020 {
1021 	struct rasops_info *ri = cookie;
1022 	struct ifb_softc *sc = ri->ri_hw;
1023 	int bg, fg;
1024 
1025 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
1026 
1027 	row *= ri->ri_font->fontheight;
1028 	col *= ri->ri_font->fontwidth;
1029 	num *= ri->ri_font->fontwidth;
1030 
1031 	ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
1032 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
1033 
1034 	return 0;
1035 }
1036 
1037 int
1038 ifb_copyrows(void *cookie, int src, int dst, int num)
1039 {
1040 	struct rasops_info *ri = cookie;
1041 	struct ifb_softc *sc = ri->ri_hw;
1042 
1043 	num *= ri->ri_font->fontheight;
1044 	src *= ri->ri_font->fontheight;
1045 	dst *= ri->ri_font->fontheight;
1046 
1047 	ifb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
1048 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
1049 
1050 	return 0;
1051 }
1052 
1053 int
1054 ifb_eraserows(void *cookie, int row, int num, uint32_t attr)
1055 {
1056 	struct rasops_info *ri = cookie;
1057 	struct ifb_softc *sc = ri->ri_hw;
1058 	int bg, fg;
1059 	int x, y, w;
1060 
1061 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
1062 
1063 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
1064 		num = ri->ri_height;
1065 		x = y = 0;
1066 		w = ri->ri_width;
1067 	} else {
1068 		num *= ri->ri_font->fontheight;
1069 		x = ri->ri_xorigin;
1070 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
1071 		w = ri->ri_emuwidth;
1072 	}
1073 	ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
1074 
1075 	return 0;
1076 }
1077 
1078 void
1079 ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h)
1080 {
1081 	ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK);
1082 	ifb_rop_wait(sc);
1083 }
1084 
1085 void
1086 ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg)
1087 {
1088 	int32_t mask;
1089 
1090 	/* pixels to set... */
1091 	mask = IFB_PIXELMASK & bg;
1092 	if (mask != 0) {
1093 		ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask);
1094 		ifb_rop_wait(sc);
1095 	}
1096 
1097 	/* pixels to clear... */
1098 	mask = IFB_PIXELMASK & ~bg;
1099 	if (mask != 0) {
1100 		ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask);
1101 		ifb_rop_wait(sc);
1102 	}
1103 }
1104 
1105 /*
1106  * Perform a raster operation on both overlay planes.
1107  * Puzzled by all the magic numbers in there? So are we. Isn't a dire
1108  * lack of documentation wonderful?
1109  */
1110 
1111 static inline void
1112 ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h,
1113     uint32_t rop, int32_t planemask)
1114 {
1115 	(*sc->sc_rop)(sc, sx, sy, dx, dy, w, h, rop, planemask);
1116 }
1117 
1118 void
1119 ifb_rop_common(struct ifb_softc *sc, bus_addr_t reg, int sx, int sy,
1120     int dx, int dy, int w, int h, uint32_t rop, int32_t planemask)
1121 {
1122 	int dir = 0;
1123 
1124 	/*
1125 	 * Compute rop direction. This only really matters for
1126 	 * screen-to-screen copies.
1127 	 */
1128 	if (sy < dy /* && sy + h > dy */) {
1129 		sy += h - 1;
1130 		dy += h;
1131 		dir |= IFB_BLT_DIR_BACKWARDS_Y;
1132 	}
1133 	if (sx < dx /* && sx + w > dx */) {
1134 		sx += w - 1;
1135 		dx += w;
1136 		dir |= IFB_BLT_DIR_BACKWARDS_X;
1137 	}
1138 
1139 	/* Which one of those below is your magic number for today? */
1140 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x61000001);
1141 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1142 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x6301c080);
1143 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x80000000);
1144 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, rop);
1145 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, planemask);
1146 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1147 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x64000303);
1148 	/*
1149 	 * This value is a pixel offset within the destination area. It is
1150 	 * probably used to define complex polygon shapes, with the
1151 	 * last pixel in the list being back to (0,0).
1152 	 */
1153 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(0, 0));
1154 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1155 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00030000);
1156 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x2200010d);
1157 
1158 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x33f01000 | dir);
1159 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(dx, dy));
1160 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(w, h));
1161 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(sx, sy));
1162 }
1163 
1164 void
1165 ifb_rop_ifb(void *v, int sx, int sy, int dx, int dy, int w, int h,
1166     uint32_t rop, int32_t planemask)
1167 {
1168 	struct ifb_softc *sc = (struct ifb_softc *)v;
1169 	bus_addr_t reg = IFB_REG_ENGINE;
1170 
1171 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 2);
1172 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 1);
1173 	/* the ``0101'' part is probably a component selection */
1174 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x540101ff);
1175 
1176 	ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
1177 }
1178 
1179 void
1180 ifb_rop_jfb(void *v, int sx, int sy, int dx, int dy, int w, int h,
1181     uint32_t rop, int32_t planemask)
1182 {
1183 	struct ifb_softc *sc = (struct ifb_softc *)v;
1184 	bus_addr_t reg = JFB_REG_ENGINE;
1185 	uint32_t spr, splr;
1186 
1187 	/*
1188 	 * Pick the current spr and splr values from the communication
1189 	 * area if possible.
1190 	 */
1191 	if (sc->sc_comm != NULL) {
1192 		spr = sc->sc_comm[IFB_SHARED_TERM8_SPR >> 2];
1193 		splr = sc->sc_comm[IFB_SHARED_TERM8_SPLR >> 2];
1194 	} else {
1195 		/* supposedly sane defaults */
1196 		spr = 0x54ff0303;
1197 		splr = 0x5c0000ff;
1198 	}
1199 
1200 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00400016);
1201 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000002);
1202 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000000);
1203 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, spr);
1204 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, splr);
1205 
1206 	ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
1207 
1208 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000001);
1209 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000001);
1210 }
1211 
1212 int
1213 ifb_rop_wait(struct ifb_softc *sc)
1214 {
1215 	int i;
1216 
1217 	for (i = 1000000; i != 0; i--) {
1218 		if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
1219 		    IFB_REG_STATUS) & IFB_REG_STATUS_DONE)
1220 			break;
1221 		DELAY(1);
1222 	}
1223 
1224 	return i;
1225 }
1226 
1227 int
1228 ifb_do_cursor(struct rasops_info *ri)
1229 {
1230 	struct ifb_softc *sc = ri->ri_hw;
1231 	int y, x;
1232 
1233 	y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight;
1234 	x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth;
1235 
1236 	ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight,
1237 	    IFB_ROP_XOR, IFB_PIXELMASK);
1238 	ifb_rop_wait(sc);
1239 
1240 	return 0;
1241 }
1242