xref: /openbsd/sys/arch/sparc64/dev/ifb.c (revision 4b6f264a)
1 /*	$OpenBSD: ifb.c,v 1.15 2009/01/19 22:12:11 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 PROM and registers area, in the second BAR, with the registers
77  *   starting 32KB within this area.
78  * - a 8MB memory mapping, which purpose is unknown, in the third BAR.
79  *
80  * In the state the PROM leaves us in, the 8MB frame buffer windows map
81  * the video memory as interleaved stripes, of which the non-visible parts
82  * can still be addressed (probably for fast screen switching).
83  *
84  * Unfortunately, since we do not know how to reconfigure the stripes
85  * to provide at least a linear frame buffer, we have to write to both
86  * windows and have them provide the complete image.
87  *
88  * Moreover, high pixel values in the overlay planes (such as 0xff or 0xfe)
89  * seem to enable other planes with random contents, so we'll limit ourselves
90  * to 7bpp opration.
91  */
92 
93 /*
94  * The Expert3D has an extra BAR that is not present on the -Lite
95  * version.  This register contains bits that tell us how many BARs to
96  * skip before we get to the BARs that interest us.
97  */
98 #define IFB_PCI_CFG			0x5c
99 #define IFB_PCI_CFG_BAR_OFFSET(x)	((x & 0x000000e0) >> 3)
100 
101 #define	IFB_REG_OFFSET			0x8000
102 
103 /*
104  * 0000 magic
105  * This register seems to be used to issue commands to the
106  * acceleration hardware.
107  *
108  */
109 #define IFB_REG_MAGIC			0x0000
110 #define IFB_REG_MAGIC_DIR_BACKWARDS_Y		(0x08 | 0x02)
111 #define IFB_REG_MAGIC_DIR_BACKWARDS_X		(0x04 | 0x01)
112 
113 /*
114  * 0040 component configuration
115  * This register controls which parts of the board will be addressed by
116  * writes to other configuration registers.
117  * Apparently the low two bytes control the frame buffer windows for the
118  * given head (starting at 1).
119  * The high two bytes are texture related.
120  */
121 #define	IFB_REG_COMPONENT_SELECT	0x0040
122 
123 /*
124  * 0044 status
125  * This register has a bit that signals completion of commands issued
126  * to the acceleration hardware.
127  */
128 #define IFB_REG_STATUS			0x0044
129 #define IFB_REG_STATUS_DONE			0x00000004
130 
131 /*
132  * 0058 magnifying configuration
133  * This register apparently controls magnifying.
134  * bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8,
135  *   11: by 16)
136  * bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8)
137  */
138 #define	IFB_REG_MAGNIFY			0x0058
139 #define	IFB_REG_MAGNIFY_DISABLE			0x00000000
140 #define	IFB_REG_MAGNIFY_X2			0x00000040
141 #define	IFB_REG_MAGNIFY_X4			0x00000080
142 #define	IFB_REG_MAGNIFY_X8			0x000000c0
143 #define	IFB_REG_MAGNIFY_WINDIV2			0x00000000
144 #define	IFB_REG_MAGNIFY_WINDIV4			0x00000010
145 #define	IFB_REG_MAGNIFY_WINDIV8			0x00000020
146 #define	IFB_REG_MAGNIFY_WINDIV16		0x00000030
147 
148 /*
149  * 0070 display resolution
150  * Contains the size of the display, as ((height - 1) << 16) | (width - 1)
151  */
152 #define	IFB_REG_RESOLUTION		0x0070
153 /*
154  * 0074 configuration register
155  * Contains 0x1a000088 | ((Log2 stride) << 16)
156  */
157 #define	IFB_REG_CONFIG			0x0074
158 /*
159  * 0078 32bit frame buffer window #0 (8 to 9 MB)
160  * Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
161  */
162 #define	IFB_REG_FB32_0			0x0078
163 /*
164  * 007c 32bit frame buffer window #1 (8 to 9 MB)
165  * Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
166  */
167 #define	IFB_REG_FB32_1			0x007c
168 /*
169  * 0080 8bit frame buffer window #0 (2 to 2.2 MB)
170  * Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
171  */
172 #define	IFB_REG_FB8_0			0x0080
173 /*
174  * 0084 8bit frame buffer window #1 (2 to 2.2 MB)
175  * Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
176  */
177 #define	IFB_REG_FB8_1			0x0084
178 /*
179  * 0088 unknown window (as large as a 32 bit frame buffer)
180  */
181 #define	IFB_REG_FB_UNK0			0x0088
182 /*
183  * 008c unknown window (as large as a 8 bit frame buffer)
184  */
185 #define	IFB_REG_FB_UNK1			0x008c
186 /*
187  * 0090 unknown window (as large as a 8 bit frame buffer)
188  */
189 #define	IFB_REG_FB_UNK2			0x0090
190 
191 /*
192  * 00bc RAMDAC palette index register
193  */
194 #define	IFB_REG_CMAP_INDEX		0x00bc
195 /*
196  * 00c0 RAMDAC palette data register
197  */
198 #define	IFB_REG_CMAP_DATA		0x00c0
199 
200 /*
201  * 00e4 DPMS state register
202  * States ``off'' and ``suspend'' need chip reprogramming before video can
203  * be enabled again.
204  */
205 #define	IFB_REG_DPMS_STATE		0x00e4
206 #define	IFB_REG_DPMS_OFF			0x00000000
207 #define	IFB_REG_DPMS_SUSPEND			0x00000001
208 #define	IFB_REG_DPMS_STANDBY			0x00000002
209 #define	IFB_REG_DPMS_ON				0x00000003
210 
211 /*
212  * (some) ROP codes
213  */
214 
215 #define	IFB_ROP_CLEAR	0x00000000	/* clear bits in rop mask */
216 #define	IFB_ROP_SRC	0x00330000	/* copy src bits matching rop mask */
217 #define	IFB_ROP_XOR	0x00cc0000	/* xor src bits with rop mask */
218 #define	IFB_ROP_SET	0x00ff0000	/* set bits in rop mask */
219 
220 #define IFB_COORDS(x, y)	((x) | (y) << 16)
221 
222 #define	IFB_PIXELMASK	0x7f	/* 7bpp */
223 
224 struct ifb_softc {
225 	struct sunfb sc_sunfb;
226 
227 	bus_space_tag_t sc_mem_t;
228 	pcitag_t sc_pcitag;
229 
230 	bus_space_handle_t sc_mem_h;
231 	bus_addr_t sc_membase, sc_fb8bank0_base, sc_fb8bank1_base;
232 	bus_size_t sc_memlen;
233 	vaddr_t	sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr;
234 
235 	bus_space_handle_t sc_reg_h;
236 	bus_addr_t sc_regbase;
237 	bus_size_t sc_reglen;
238 
239 	u_int	sc_mode;
240 	u_int	sc_accel;
241 
242 	struct wsdisplay_emulops sc_old_ops;
243 	void (*sc_old_cursor)(struct rasops_info *);
244 
245 	int sc_console;
246 	u_int8_t sc_cmap_red[256];
247 	u_int8_t sc_cmap_green[256];
248 	u_int8_t sc_cmap_blue[256];
249 };
250 
251 int	ifb_ioctl(void *, u_long, caddr_t, int, struct proc *);
252 paddr_t	ifb_mmap(void *, off_t, int);
253 void	ifb_burner(void *, u_int, u_int);
254 
255 struct wsdisplay_accessops ifb_accessops = {
256 	ifb_ioctl,
257 	ifb_mmap,
258 	NULL,	/* alloc_screen */
259 	NULL,	/* free_screen */
260 	NULL,	/* show_screen */
261 	NULL,	/* load_font */
262 	NULL,	/* scrollback */
263 	NULL,	/* getchar */
264 	ifb_burner,
265 	NULL	/* pollc */
266 };
267 
268 int	ifbmatch(struct device *, void *, void *);
269 void	ifbattach(struct device *, struct device *, void *);
270 
271 struct cfattach ifb_ca = {
272 	sizeof (struct ifb_softc), ifbmatch, ifbattach
273 };
274 
275 struct cfdriver ifb_cd = {
276 	NULL, "ifb", DV_DULL
277 };
278 
279 int	ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *);
280 int	ifb_is_console(int);
281 int	ifb_mapregs(struct ifb_softc *, struct pci_attach_args *);
282 int	ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *);
283 void	ifb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
284 void	ifb_setcolormap(struct sunfb *,
285 	    void (*)(void *, u_int, u_int8_t, u_int8_t, u_int8_t));
286 
287 void	ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int);
288 void	ifb_fillrect(struct ifb_softc *, int, int, int, int, int);
289 void	ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t,
290 	    int32_t);
291 int	ifb_rop_wait(struct ifb_softc *);
292 
293 void	ifb_putchar_dumb(void *, int, int, u_int, long);
294 void	ifb_copycols_dumb(void *, int, int, int, int);
295 void	ifb_erasecols_dumb(void *, int, int, int, long);
296 void	ifb_copyrows_dumb(void *, int, int, int);
297 void	ifb_eraserows_dumb(void *, int, int, long);
298 void	ifb_do_cursor_dumb(struct rasops_info *);
299 
300 void	ifb_putchar(void *, int, int, u_int, long);
301 void	ifb_copycols(void *, int, int, int, int);
302 void	ifb_erasecols(void *, int, int, int, long);
303 void	ifb_copyrows(void *, int, int, int);
304 void	ifb_eraserows(void *, int, int, long);
305 void	ifb_do_cursor(struct rasops_info *);
306 
307 int
308 ifbmatch(struct device *parent, void *cf, void *aux)
309 {
310 	struct pci_attach_args *paa = aux;
311 	int rc;
312 
313 	if ((rc = ifb_ident(aux)) == 0)
314 		return 0;
315 
316 	/*
317 	 * Multiple heads appear as PCI subfunctions.
318 	 * However, the ofw node for it lacks most properties,
319 	 * and its BAR only give access to registers, not
320 	 * frame buffer memory.
321 	 */
322 	if (node_has_property(PCITAG_NODE(paa->pa_tag), "device_type"))
323 		return rc;
324 
325 	return 0;
326 }
327 
328 void
329 ifbattach(struct device *parent, struct device *self, void *aux)
330 {
331 	struct ifb_softc *sc = (struct ifb_softc *)self;
332 	struct pci_attach_args *paa = aux;
333 	struct rasops_info *ri;
334 	int node;
335 
336 	sc->sc_mem_t = paa->pa_memt;
337 	sc->sc_pcitag = paa->pa_tag;
338 
339 	printf("\n");
340 
341 	if (ifb_mapregs(sc, paa))
342 		return;
343 
344 	sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
345 	      IFB_REG_OFFSET + IFB_REG_FB8_0);
346 	sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
347 	      IFB_REG_OFFSET + IFB_REG_FB8_1);
348 
349 	sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h);
350 	sc->sc_fb8bank0_vaddr = sc->sc_memvaddr +
351 	    sc->sc_fb8bank0_base - sc->sc_membase;
352 	sc->sc_fb8bank1_vaddr = sc->sc_memvaddr +
353 	    sc->sc_fb8bank1_base - sc->sc_membase;
354 
355 	node = PCITAG_NODE(paa->pa_tag);
356 	sc->sc_console = ifb_is_console(node);
357 
358 	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
359 
360 	printf("%s: %dx%d\n",
361 	    self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
362 
363 #if 0
364 	/*
365 	 * Make sure the frame buffer is configured to sane values.
366 	 * So much more is needed there... documentation permitting.
367 	 */
368 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
369 	    IFB_REG_OFFSET + IFB_REG_COMPONENT_SELECT, 0x00000101);
370 	delay(1000);
371 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
372 	    IFB_REG_OFFSET + IFB_REG_MAGNIFY, IFB_REG_MAGNIFY_DISABLE);
373 #endif
374 
375 	ri = &sc->sc_sunfb.sf_ro;
376 	ri->ri_bits = NULL;
377 	ri->ri_hw = sc;
378 
379 	fbwscons_init(&sc->sc_sunfb, RI_BSWAP, sc->sc_console);
380 
381 	/*
382 	 * Clear the unwanted pixel planes: all if non console (thus
383 	 * white background), and all planes above 7bpp otherwise.
384 	 * This also allows to check whether the accelerated code works,
385 	 * or not.
386 	 */
387 	ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
388 	    IFB_ROP_CLEAR, sc->sc_console ? ~IFB_PIXELMASK : ~0);
389 	if (ifb_rop_wait(sc) != 0) {
390 		sc->sc_accel = 1;
391 	} else {
392 		/* due to the way we will handle updates */
393 		ri->ri_flg &= ~RI_FULLCLEAR;
394 
395 		if (!sc->sc_console) {
396 			bzero((void *)sc->sc_fb8bank0_vaddr,
397 			    sc->sc_sunfb.sf_fbsize);
398 			bzero((void *)sc->sc_fb8bank1_vaddr,
399 			    sc->sc_sunfb.sf_fbsize);
400 		}
401 	}
402 
403 	/* pick centering delta */
404 	sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits;
405 	sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits;
406 
407 	sc->sc_old_ops = ri->ri_ops;	/* structure copy */
408 	sc->sc_old_cursor = ri->ri_do_cursor;
409 
410 	if (sc->sc_accel) {
411 		ri->ri_ops.copyrows = ifb_copyrows;
412 		ri->ri_ops.copycols = ifb_copycols;
413 		ri->ri_ops.eraserows = ifb_eraserows;
414 		ri->ri_ops.erasecols = ifb_erasecols;
415 		ri->ri_ops.putchar = ifb_putchar_dumb;
416 		ri->ri_do_cursor = ifb_do_cursor;
417 	} else {
418 		ri->ri_ops.copyrows = ifb_copyrows_dumb;
419 		ri->ri_ops.copycols = ifb_copycols_dumb;
420 		ri->ri_ops.eraserows = ifb_eraserows_dumb;
421 		ri->ri_ops.erasecols = ifb_erasecols_dumb;
422 		ri->ri_ops.putchar = ifb_putchar_dumb;
423 		ri->ri_do_cursor = ifb_do_cursor_dumb;
424 	}
425 
426 	ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
427 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
428 
429 	if (sc->sc_console)
430 		fbwscons_console_init(&sc->sc_sunfb, -1);
431 	fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, sc->sc_console);
432 }
433 
434 int
435 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
436 {
437 	struct ifb_softc *sc = v;
438 	struct wsdisplay_fbinfo *wdf;
439 	struct pcisel *sel;
440 	int mode;
441 
442 	switch (cmd) {
443 	case WSDISPLAYIO_GTYPE:
444 		*(u_int *)data = WSDISPLAY_TYPE_IFB;
445 		break;
446 
447 	case WSDISPLAYIO_SMODE:
448 		mode = *(u_int *)data;
449 		if (mode == WSDISPLAYIO_MODE_EMUL)
450 			ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
451 		sc->sc_mode = mode;
452 		break;
453 	case WSDISPLAYIO_GINFO:
454 		wdf = (void *)data;
455 		wdf->height = sc->sc_sunfb.sf_height;
456 		wdf->width  = sc->sc_sunfb.sf_width;
457 		wdf->depth  = sc->sc_sunfb.sf_depth;
458 		wdf->cmsize = 256;
459 		break;
460 	case WSDISPLAYIO_LINEBYTES:
461 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
462 		break;
463 
464 	case WSDISPLAYIO_GETCMAP:
465 		return ifb_getcmap(sc, (struct wsdisplay_cmap *)data);
466 	case WSDISPLAYIO_PUTCMAP:
467 		return ifb_putcmap(sc, (struct wsdisplay_cmap *)data);
468 
469 	case WSDISPLAYIO_GPCIID:
470 		sel = (struct pcisel *)data;
471 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
472 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
473 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
474 		break;
475 
476 	case WSDISPLAYIO_SVIDEO:
477 	case WSDISPLAYIO_GVIDEO:
478 		break;
479 
480 	case WSDISPLAYIO_GCURPOS:
481 	case WSDISPLAYIO_SCURPOS:
482 	case WSDISPLAYIO_GCURMAX:
483 	case WSDISPLAYIO_GCURSOR:
484 	case WSDISPLAYIO_SCURSOR:
485 	default:
486 		return -1; /* not supported yet */
487         }
488 
489 	return 0;
490 }
491 
492 int
493 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
494 {
495 	u_int index = cm->index;
496 	u_int count = cm->count;
497 	int error;
498 
499 	if (index >= 256 || count > 256 - index)
500 		return EINVAL;
501 
502 	error = copyout(&sc->sc_cmap_red[index], cm->red, count);
503 	if (error)
504 		return error;
505 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
506 	if (error)
507 		return error;
508 	error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
509 	if (error)
510 		return error;
511 	return 0;
512 }
513 
514 int
515 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
516 {
517 	u_int index = cm->index;
518 	u_int count = cm->count;
519 	u_int i;
520 	int error;
521 	u_char *r, *g, *b;
522 
523 	if (index >= 256 || count > 256 - index)
524 		return EINVAL;
525 
526 	if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
527 		return error;
528 	if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
529 		return error;
530 	if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
531 		return error;
532 
533 	r = &sc->sc_cmap_red[index];
534 	g = &sc->sc_cmap_green[index];
535 	b = &sc->sc_cmap_blue[index];
536 
537 	for (i = 0; i < count; i++) {
538 		bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
539 		    IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index);
540 		bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
541 		    IFB_REG_OFFSET + IFB_REG_CMAP_DATA,
542 		    (((u_int)*b) << 22) | (((u_int)*g) << 12) | (((u_int)*r) << 2));
543 		r++, g++, b++, index++;
544 	}
545 	return 0;
546 }
547 
548 void
549 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
550 {
551 	struct ifb_softc *sc = v;
552 
553 	sc->sc_cmap_red[index] = r;
554 	sc->sc_cmap_green[index] = g;
555 	sc->sc_cmap_blue[index] = b;
556 
557 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
558 	    IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index);
559 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
560 	    IFB_REG_OFFSET + IFB_REG_CMAP_DATA,
561 	    (((u_int)b) << 22) | (((u_int)g) << 12) | (((u_int)r) << 2));
562 }
563 
564 /* similar in spirit to fbwscons_setcolormap() */
565 void
566 ifb_setcolormap(struct sunfb *sf,
567     void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
568 {
569 	struct rasops_info *ri = &sf->sf_ro;
570 	int i;
571 	const u_char *color;
572 
573 	/*
574 	 * Compensate for overlay plane limitations. Since we'll operate
575 	 * in 7bpp mode, our basic colors will use positions 00 to 0f,
576 	 * and the inverted colors will use positions 7f to 70.
577 	 */
578 
579 	for (i = 0x00; i < 0x10; i++) {
580 		color = &rasops_cmap[i * 3];
581 		setcolor(sf, i, color[0], color[1], color[2]);
582 	}
583 	for (i = 0x70; i < 0x80; i++) {
584 		color = &rasops_cmap[(0xf0 | i) * 3];
585 		setcolor(sf, i, color[0], color[1], color[2]);
586 	}
587 
588 	/*
589 	 * Proper operation apparently needs black to be 01, always.
590 	 * Replace black, red and white with white, black and red.
591 	 * Kind of ugly, but it works.
592 	 */
593 	ri->ri_devcmap[WSCOL_WHITE] = 0x00000000;
594 	ri->ri_devcmap[WSCOL_BLACK] = 0x01010101;
595 	ri->ri_devcmap[WSCOL_RED] = 0x07070707;
596 
597 	color = &rasops_cmap[(WSCOL_WHITE + 8) * 3];	/* real white */
598 	setcolor(sf, 0, color[0], color[1], color[2]);
599 	setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]);
600 	color = &rasops_cmap[WSCOL_BLACK * 3];
601 	setcolor(sf, 1, color[0], color[1], color[2]);
602 	setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]);
603 	color = &rasops_cmap[WSCOL_RED * 3];
604 	setcolor(sf, 7, color[0], color[1], color[2]);
605 	setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]);
606 }
607 
608 paddr_t
609 ifb_mmap(void *v, off_t off, int prot)
610 {
611 	struct ifb_softc *sc = (struct ifb_softc *)v;
612 
613 	switch (sc->sc_mode) {
614 	case WSDISPLAYIO_MODE_MAPPED:
615 		/*
616 		 * In mapped mode, provide access to the two overlays,
617 		 * followed by the control registers, at the following
618 		 * addresses:
619 		 * 00000000	overlay 0, size up to 2MB (visible fb size)
620 		 * 01000000	overlay 1, size up to 2MB (visible fb size)
621 		 * 02000000	control registers
622 		 */
623 		off -= 0x00000000;
624 		if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
625 			return bus_space_mmap(sc->sc_mem_t,
626 			    sc->sc_fb8bank0_base,
627 			    off, prot, BUS_SPACE_MAP_LINEAR);
628 		}
629 		off -= 0x01000000;
630 		if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
631 			return bus_space_mmap(sc->sc_mem_t,
632 			    sc->sc_fb8bank1_base,
633 			    off, prot, BUS_SPACE_MAP_LINEAR);
634 		}
635 #ifdef APERTURE
636 		off -= 0x01000000;
637 		if (allowaperture != 0 && sc->sc_accel) {
638 			if (off >= 0 && off < round_page(sc->sc_reglen)) {
639 				return bus_space_mmap(sc->sc_mem_t,
640 				    sc->sc_regbase,
641 				    off, prot, BUS_SPACE_MAP_LINEAR);
642 			}
643 		}
644 #endif
645 		break;
646 	}
647 
648 	return -1;
649 }
650 
651 void
652 ifb_burner(void *v, u_int on, u_int flags)
653 {
654 	struct ifb_softc *sc = (struct ifb_softc *)v;
655 	int s;
656 	uint32_t dpms;
657 
658 	s = splhigh();
659 	if (on)
660 		dpms = IFB_REG_DPMS_ON;
661 	else {
662 #ifdef notyet
663 		if (flags & WSDISPLAY_BURN_VBLANK)
664 			dpms = IFB_REG_DPMS_SUSPEND;
665 		else
666 #endif
667 			dpms = IFB_REG_DPMS_STANDBY;
668 	}
669 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
670 	    IFB_REG_OFFSET + IFB_REG_DPMS_STATE, dpms);
671 	splx(s);
672 }
673 
674 int
675 ifb_is_console(int node)
676 {
677 	extern int fbnode;
678 
679 	return fbnode == node;
680 }
681 
682 int
683 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa)
684 {
685 	u_int32_t cf;
686 	int bar, rc;
687 
688 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG);
689 	bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf);
690 
691 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);
692 	if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
693 		rc = EINVAL;
694 	else {
695 		rc = pci_mapreg_map(pa, bar, cf,
696 		    BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h,
697 		    &sc->sc_membase, &sc->sc_memlen, 0);
698 	}
699 	if (rc != 0) {
700 		printf("%s: can't map video memory\n",
701 		    sc->sc_sunfb.sf_dev.dv_xname);
702 		return rc;
703 	}
704 
705 	cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4);
706 	if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
707 		rc = EINVAL;
708 	else {
709 		rc = pci_mapreg_map(pa, bar + 4, cf,
710 		    0, NULL, &sc->sc_reg_h,
711 		     &sc->sc_regbase, &sc->sc_reglen, 0x9000);
712 	}
713 	if (rc != 0) {
714 		printf("%s: can't map register space\n",
715 		    sc->sc_sunfb.sf_dev.dv_xname);
716 		return rc;
717 	}
718 
719 	return 0;
720 }
721 
722 /*
723  * Non accelerated routines.
724  */
725 
726 void
727 ifb_putchar_dumb(void *cookie, int row, int col, u_int uc, long attr)
728 {
729 	struct rasops_info *ri = cookie;
730 	struct ifb_softc *sc = ri->ri_hw;
731 
732 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
733 	sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
734 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
735 	sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
736 }
737 
738 void
739 ifb_copycols_dumb(void *cookie, int row, int src, int dst, int num)
740 {
741 	struct rasops_info *ri = cookie;
742 	struct ifb_softc *sc = ri->ri_hw;
743 
744 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
745 	sc->sc_old_ops.copycols(cookie, row, src, dst, num);
746 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
747 	sc->sc_old_ops.copycols(cookie, row, src, dst, num);
748 }
749 
750 void
751 ifb_erasecols_dumb(void *cookie, int row, int col, int num, long attr)
752 {
753 	struct rasops_info *ri = cookie;
754 	struct ifb_softc *sc = ri->ri_hw;
755 
756 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
757 	sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
758 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
759 	sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
760 }
761 
762 void
763 ifb_copyrows_dumb(void *cookie, int src, int dst, int num)
764 {
765 	struct rasops_info *ri = cookie;
766 	struct ifb_softc *sc = ri->ri_hw;
767 
768 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
769 	sc->sc_old_ops.copyrows(cookie, src, dst, num);
770 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
771 	sc->sc_old_ops.copyrows(cookie, src, dst, num);
772 }
773 
774 void
775 ifb_eraserows_dumb(void *cookie, int row, int num, long attr)
776 {
777 	struct rasops_info *ri = cookie;
778 	struct ifb_softc *sc = ri->ri_hw;
779 
780 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
781 	sc->sc_old_ops.eraserows(cookie, row, num, attr);
782 	ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
783 	sc->sc_old_ops.eraserows(cookie, row, num, attr);
784 }
785 
786 /* Similar to rasops_do_cursor(), but using a 7bit pixel mask. */
787 
788 #define	CURSOR_MASK	0x7f7f7f7f
789 
790 void
791 ifb_do_cursor_dumb(struct rasops_info *ri)
792 {
793 	struct ifb_softc *sc = ri->ri_hw;
794 	int full1, height, cnt, slop1, slop2, row, col;
795 	int ovl_offset = sc->sc_fb8bank1_vaddr - sc->sc_fb8bank0_vaddr;
796 	u_char *dp0, *dp1, *rp;
797 
798 	row = ri->ri_crow;
799 	col = ri->ri_ccol;
800 
801 	ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
802 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
803 	height = ri->ri_font->fontheight;
804 	slop1 = (4 - ((long)rp & 3)) & 3;
805 
806 	if (slop1 > ri->ri_xscale)
807 		slop1 = ri->ri_xscale;
808 
809 	slop2 = (ri->ri_xscale - slop1) & 3;
810 	full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
811 
812 	if ((slop1 | slop2) == 0) {
813 		/* A common case */
814 		while (height--) {
815 			dp0 = rp;
816 			dp1 = dp0 + ovl_offset;
817 			rp += ri->ri_stride;
818 
819 			for (cnt = full1; cnt; cnt--) {
820 				*(int32_t *)dp0 ^= CURSOR_MASK;
821 				*(int32_t *)dp1 ^= CURSOR_MASK;
822 				dp0 += 4;
823 				dp1 += 4;
824 			}
825 		}
826 	} else {
827 		/* XXX this is stupid.. use masks instead */
828 		while (height--) {
829 			dp0 = rp;
830 			dp1 = dp0 + ovl_offset;
831 			rp += ri->ri_stride;
832 
833 			if (slop1 & 1) {
834 				*dp0++ ^= (u_char)CURSOR_MASK;
835 				*dp1++ ^= (u_char)CURSOR_MASK;
836 			}
837 
838 			if (slop1 & 2) {
839 				*(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
840 				*(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
841 				dp0 += 2;
842 				dp1 += 2;
843 			}
844 
845 			for (cnt = full1; cnt; cnt--) {
846 				*(int32_t *)dp0 ^= CURSOR_MASK;
847 				*(int32_t *)dp1 ^= CURSOR_MASK;
848 				dp0 += 4;
849 				dp1 += 4;
850 			}
851 
852 			if (slop2 & 1) {
853 				*dp0++ ^= (u_char)CURSOR_MASK;
854 				*dp1++ ^= (u_char)CURSOR_MASK;
855 			}
856 
857 			if (slop2 & 2) {
858 				*(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
859 				*(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
860 			}
861 		}
862 	}
863 }
864 
865 /*
866  * Accelerated routines.
867  */
868 
869 void
870 ifb_copycols(void *cookie, int row, int src, int dst, int num)
871 {
872 	struct rasops_info *ri = cookie;
873 	struct ifb_softc *sc = ri->ri_hw;
874 
875 	num *= ri->ri_font->fontwidth;
876 	src *= ri->ri_font->fontwidth;
877 	dst *= ri->ri_font->fontwidth;
878 	row *= ri->ri_font->fontheight;
879 
880 	ifb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
881 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
882 	    num, ri->ri_font->fontheight);
883 }
884 
885 void
886 ifb_erasecols(void *cookie, int row, int col, int num, long attr)
887 {
888 	struct rasops_info *ri = cookie;
889 	struct ifb_softc *sc = ri->ri_hw;
890 	int bg, fg;
891 
892 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
893 
894 	row *= ri->ri_font->fontheight;
895 	col *= ri->ri_font->fontwidth;
896 	num *= ri->ri_font->fontwidth;
897 
898 	ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
899 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
900 }
901 
902 void
903 ifb_copyrows(void *cookie, int src, int dst, int num)
904 {
905 	struct rasops_info *ri = cookie;
906 	struct ifb_softc *sc = ri->ri_hw;
907 
908 	num *= ri->ri_font->fontheight;
909 	src *= ri->ri_font->fontheight;
910 	dst *= ri->ri_font->fontheight;
911 
912 	ifb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
913 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
914 }
915 
916 void
917 ifb_eraserows(void *cookie, int row, int num, long attr)
918 {
919 	struct rasops_info *ri = cookie;
920 	struct ifb_softc *sc = ri->ri_hw;
921 	int bg, fg;
922 	int x, y, w;
923 
924 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
925 
926 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
927 		num = ri->ri_height;
928 		x = y = 0;
929 		w = ri->ri_width;
930 	} else {
931 		num *= ri->ri_font->fontheight;
932 		x = ri->ri_xorigin;
933 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
934 		w = ri->ri_emuwidth;
935 	}
936 	ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
937 }
938 
939 void
940 ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h)
941 {
942 	ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK);
943 	ifb_rop_wait(sc);
944 }
945 
946 void
947 ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg)
948 {
949 	int32_t mask;
950 
951 	/* pixels to set... */
952 	mask = IFB_PIXELMASK & bg;
953 	if (mask != 0) {
954 		ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask);
955 		ifb_rop_wait(sc);
956 	}
957 
958 	/* pixels to clear... */
959 	mask = IFB_PIXELMASK & ~bg;
960 	if (mask != 0) {
961 		ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask);
962 		ifb_rop_wait(sc);
963 	}
964 }
965 
966 /*
967  * Perform a raster operation on both overlay planes.
968  * Puzzled by all the magic numbers in there? So are we. Isn't a dire
969  * lack of documentation wonderful?
970  */
971 void
972 ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h,
973     uint32_t rop, int32_t planemask)
974 {
975 	int dir = 0;
976 
977 	/*
978 	 * Compute rop direction. This only really matters for
979 	 * screen-to-screen copies.
980 	 */
981 	if (sy < dy /* && sy + h > dy */) {
982 		sy += h - 1;
983 		dy += h;
984 		dir |= IFB_REG_MAGIC_DIR_BACKWARDS_Y;
985 	}
986 	if (sx < dx /* && sx + w > dx */) {
987 		sx += w - 1;
988 		dx += w;
989 		dir |= IFB_REG_MAGIC_DIR_BACKWARDS_X;
990 	}
991 
992 	/* Which one of those below is your magic number for today? */
993 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
994 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 2);
995 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
996 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 1);
997 	/* the ``0101'' part is probably a component selection */
998 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
999 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x540101ff);
1000 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1001 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x61000001);
1002 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1003 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
1004 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1005 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x6301c080);
1006 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1007 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x80000000);
1008 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1009 	    IFB_REG_OFFSET + IFB_REG_MAGIC, rop);
1010 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1011 	    IFB_REG_OFFSET + IFB_REG_MAGIC, planemask);
1012 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1013 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
1014 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1015 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x64000303);
1016 	/*
1017 	 * This value is a pixel offset within the destination area. It is
1018 	 * probably used to define complex polygon shapes, with the
1019 	 * last pixel in the list being back to (0,0).
1020 	 */
1021 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1022 	    IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(0, 0));
1023 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1024 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
1025 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1026 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x00030000);
1027 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1028 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x2200010d);
1029 
1030 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1031 	    IFB_REG_OFFSET + IFB_REG_MAGIC, 0x33f01000 | dir);
1032 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1033 	    IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(dx, dy));
1034 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1035 	    IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(w, h));
1036 	bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
1037 	    IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(sx, sy));
1038 }
1039 
1040 int
1041 ifb_rop_wait(struct ifb_softc *sc)
1042 {
1043 	int i;
1044 
1045 	for (i = 1000000; i != 0; i--) {
1046 		if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
1047 		    IFB_REG_OFFSET + IFB_REG_STATUS) & IFB_REG_STATUS_DONE)
1048 			break;
1049 		DELAY(1);
1050 	}
1051 
1052 	return i;
1053 }
1054 
1055 void
1056 ifb_do_cursor(struct rasops_info *ri)
1057 {
1058 	struct ifb_softc *sc = ri->ri_hw;
1059 	int y, x;
1060 
1061 	y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight;
1062 	x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth;
1063 
1064 	ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight,
1065 	    IFB_ROP_XOR, IFB_PIXELMASK);
1066 	ifb_rop_wait(sc);
1067 }
1068