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