1 /* $OpenBSD: ifb.c,v 1.27 2024/05/14 08:26:13 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 const 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_copycols(void *, int, int, int, int);
342 int ifb_erasecols(void *, int, int, int, uint32_t);
343 int ifb_copyrows(void *, int, int, int);
344 int ifb_eraserows(void *, int, int, uint32_t);
345 int ifb_do_cursor(struct rasops_info *);
346
347 int
ifbmatch(struct device * parent,void * cf,void * aux)348 ifbmatch(struct device *parent, void *cf, void *aux)
349 {
350 return ifb_ident(aux);
351 }
352
353 void
ifbattach(struct device * parent,struct device * self,void * aux)354 ifbattach(struct device *parent, struct device *self, void *aux)
355 {
356 struct ifb_softc *sc = (struct ifb_softc *)self;
357 struct pci_attach_args *paa = aux;
358 struct rasops_info *ri;
359 uint32_t dev_comm;
360 int node, console;
361 char *name, *text;
362 char namebuf[32];
363
364 sc->sc_mem_t = paa->pa_memt;
365 sc->sc_pcitag = paa->pa_tag;
366
367 node = PCITAG_NODE(paa->pa_tag);
368 console = ifb_is_console(node);
369
370 printf("\n");
371
372 /*
373 * Multiple heads appear as PCI subfunctions.
374 * However, the ofw node for it lacks most properties,
375 * and its BAR only give access to registers, not
376 * frame buffer memory.
377 */
378 if (!node_has_property(node, "device_type")) {
379 printf("%s: secondary output not supported yet\n",
380 self->dv_xname);
381 return;
382 }
383
384 /*
385 * Describe the beast.
386 */
387
388 name = text = getpropstringA(node, "name", namebuf);
389 if (strncmp(text, "SUNW,", 5) == 0)
390 text += 5;
391 printf("%s: %s", self->dv_xname, text);
392 text = getpropstring(node, "model");
393 if (*text != '\0')
394 printf(" (%s)", text);
395
396 if (ifb_mapregs(sc, paa))
397 return;
398
399 sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
400 IFB_REG_FB8_0);
401 sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
402 IFB_REG_FB8_1);
403
404 sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h);
405 sc->sc_fb8bank0_vaddr = sc->sc_memvaddr +
406 sc->sc_fb8bank0_base - sc->sc_membase;
407 sc->sc_fb8bank1_vaddr = sc->sc_memvaddr +
408 sc->sc_fb8bank1_base - sc->sc_membase;
409
410 /*
411 * The values stored into the node properties might have been
412 * modified since the Fcode was last run. Pick the geometry
413 * information from the configuration registers instead.
414 * This replaces
415 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
416 */
417
418 sc->sc_sunfb.sf_width = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
419 IFB_REG_RESOLUTION) & 0xffff) + 1;
420 sc->sc_sunfb.sf_height = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
421 IFB_REG_RESOLUTION) >> 16) + 1;
422 sc->sc_sunfb.sf_depth = 8;
423 sc->sc_sunfb.sf_linebytes = 1 << (bus_space_read_4(sc->sc_mem_t,
424 sc->sc_reg_h, IFB_REG_CONFIG) >> 16);
425 sc->sc_sunfb.sf_fbsize =
426 sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
427
428 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
429
430 ri = &sc->sc_sunfb.sf_ro;
431 ri->ri_bits = NULL;
432 ri->ri_hw = sc;
433
434 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
435
436 /*
437 * Find out what flavour of ifb we are...
438 */
439
440 sc->sc_acceltype = ifb_accel_identify(name);
441
442 switch (sc->sc_acceltype) {
443 case IFB_ACCEL_IFB:
444 sc->sc_rop = ifb_rop_ifb;
445 break;
446 case IFB_ACCEL_JFB:
447 /*
448 * Remember the address of the communication area
449 */
450 if (OF_getprop(node, "dev-comm", &dev_comm,
451 sizeof dev_comm) != -1) {
452 sc->sc_comm = (volatile uint32_t *)(vaddr_t)dev_comm;
453 }
454 sc->sc_rop = ifb_rop_jfb;
455 break;
456 }
457
458 /*
459 * Clear the unwanted pixel planes: all if non console (thus
460 * white background), and all planes above 7bpp otherwise.
461 * This also allows to check whether the accelerated code works,
462 * or not.
463 */
464
465 if (sc->sc_acceltype != IFB_ACCEL_NONE) {
466 ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width,
467 sc->sc_sunfb.sf_height, IFB_ROP_CLEAR,
468 console ? ~IFB_PIXELMASK : ~0);
469 if (ifb_rop_wait(sc) == 0) {
470 /* fall back to dumb software operation */
471 sc->sc_acceltype = IFB_ACCEL_NONE;
472 }
473 }
474
475 if (sc->sc_acceltype == IFB_ACCEL_NONE) {
476 /* due to the way we will handle updates */
477 ri->ri_flg &= ~RI_FULLCLEAR;
478
479 if (!console) {
480 bzero((void *)sc->sc_fb8bank0_vaddr,
481 sc->sc_sunfb.sf_fbsize);
482 bzero((void *)sc->sc_fb8bank1_vaddr,
483 sc->sc_sunfb.sf_fbsize);
484 }
485 }
486
487 /* pick centering delta */
488 sc->sc_fb8bank0_vaddr += ri->ri_bits - ri->ri_origbits;
489 sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits;
490
491 sc->sc_old_ops = ri->ri_ops; /* structure copy */
492
493 if (sc->sc_acceltype != IFB_ACCEL_NONE) {
494 ri->ri_ops.copyrows = ifb_copyrows;
495 ri->ri_ops.copycols = ifb_copycols;
496 ri->ri_ops.eraserows = ifb_eraserows;
497 ri->ri_ops.erasecols = ifb_erasecols;
498 ri->ri_ops.putchar = ifb_putchar_dumb;
499 ri->ri_do_cursor = ifb_do_cursor;
500 } else {
501 ri->ri_ops.copyrows = ifb_copyrows_dumb;
502 ri->ri_ops.copycols = ifb_copycols_dumb;
503 ri->ri_ops.eraserows = ifb_eraserows_dumb;
504 ri->ri_ops.erasecols = ifb_erasecols_dumb;
505 ri->ri_ops.putchar = ifb_putchar_dumb;
506 ri->ri_do_cursor = ifb_do_cursor_dumb;
507 }
508
509 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
510 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
511
512 if (console)
513 fbwscons_console_init(&sc->sc_sunfb, -1);
514 fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, console);
515 }
516
517 /*
518 * Attempt to identify what kind of ifb we are talking to, so as to setup
519 * proper acceleration information.
520 */
521 int
ifb_accel_identify(const char * name)522 ifb_accel_identify(const char *name)
523 {
524 if (strcmp(name, "SUNW,Expert3D") == 0 ||
525 strcmp(name, "SUNW,Expert3D-Lite") == 0)
526 return IFB_ACCEL_IFB; /* ifblite */
527
528 if (strcmp(name, "SUNW,XVR-1200") == 0)
529 return IFB_ACCEL_JFB; /* jfb */
530
531 if (strcmp(name, "SUNW,XVR-600") == 0)
532 return IFB_ACCEL_JFB; /* xvr600 */
533
534 /* XVR-500 is bobcat */
535
536 return IFB_ACCEL_NONE;
537 }
538
539 int
ifb_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)540 ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
541 {
542 struct ifb_softc *sc = v;
543 struct wsdisplay_fbinfo *wdf;
544 struct pcisel *sel;
545 int mode;
546
547 switch (cmd) {
548 case WSDISPLAYIO_GTYPE:
549 *(u_int *)data = WSDISPLAY_TYPE_IFB;
550 break;
551
552 case WSDISPLAYIO_SMODE:
553 mode = *(u_int *)data;
554 if (mode == WSDISPLAYIO_MODE_EMUL)
555 ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
556 sc->sc_mode = mode;
557 break;
558 case WSDISPLAYIO_GINFO:
559 wdf = (void *)data;
560 wdf->height = sc->sc_sunfb.sf_height;
561 wdf->width = sc->sc_sunfb.sf_width;
562 wdf->depth = sc->sc_sunfb.sf_depth;
563 wdf->stride = sc->sc_sunfb.sf_linebytes;
564 wdf->offset = 0;
565 wdf->cmsize = 256;
566 break;
567 case WSDISPLAYIO_LINEBYTES:
568 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
569 break;
570
571 case WSDISPLAYIO_GETCMAP:
572 return ifb_getcmap(sc, (struct wsdisplay_cmap *)data);
573 case WSDISPLAYIO_PUTCMAP:
574 return ifb_putcmap(sc, (struct wsdisplay_cmap *)data);
575
576 case WSDISPLAYIO_GPCIID:
577 sel = (struct pcisel *)data;
578 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
579 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
580 sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
581 break;
582
583 case WSDISPLAYIO_SVIDEO:
584 case WSDISPLAYIO_GVIDEO:
585 break;
586
587 case WSDISPLAYIO_GCURPOS:
588 case WSDISPLAYIO_SCURPOS:
589 case WSDISPLAYIO_GCURMAX:
590 case WSDISPLAYIO_GCURSOR:
591 case WSDISPLAYIO_SCURSOR:
592 default:
593 return -1; /* not supported yet */
594 }
595
596 return 0;
597 }
598
599 static inline
600 u_int
ifb_dac_value(u_int r,u_int g,u_int b)601 ifb_dac_value(u_int r, u_int g, u_int b)
602 {
603 /*
604 * Convert 8 bit values to 10 bit scale, by shifting and inserting
605 * the former high bits in the low two bits.
606 * Simply shifting is slightly too dull.
607 */
608 r = (r << 2) | (r >> 6);
609 g = (g << 2) | (g >> 6);
610 b = (b << 2) | (b >> 6);
611
612 return (b << 20) | (g << 10) | r;
613 }
614
615 int
ifb_getcmap(struct ifb_softc * sc,struct wsdisplay_cmap * cm)616 ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
617 {
618 u_int index = cm->index;
619 u_int count = cm->count;
620 int error;
621
622 if (index >= 256 || count > 256 - index)
623 return EINVAL;
624
625 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
626 if (error)
627 return error;
628 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
629 if (error)
630 return error;
631 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
632 if (error)
633 return error;
634 return 0;
635 }
636
637 int
ifb_putcmap(struct ifb_softc * sc,struct wsdisplay_cmap * cm)638 ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
639 {
640 u_int index = cm->index;
641 u_int count = cm->count;
642 u_int i;
643 int error;
644 u_char *r, *g, *b;
645
646 if (index >= 256 || count > 256 - index)
647 return EINVAL;
648
649 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
650 return error;
651 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
652 return error;
653 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
654 return error;
655
656 r = &sc->sc_cmap_red[index];
657 g = &sc->sc_cmap_green[index];
658 b = &sc->sc_cmap_blue[index];
659
660 for (i = 0; i < count; i++) {
661 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
662 IFB_REG_CMAP_INDEX, index);
663 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
664 ifb_dac_value(*r, *g, *b));
665 r++, g++, b++, index++;
666 }
667 return 0;
668 }
669
670 void
ifb_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)671 ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
672 {
673 struct ifb_softc *sc = v;
674
675 sc->sc_cmap_red[index] = r;
676 sc->sc_cmap_green[index] = g;
677 sc->sc_cmap_blue[index] = b;
678
679 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_INDEX,
680 index);
681 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
682 ifb_dac_value(r, g, b));
683 }
684
685 /* similar in spirit to fbwscons_setcolormap() */
686 void
ifb_setcolormap(struct sunfb * sf,void (* setcolor)(void *,u_int,u_int8_t,u_int8_t,u_int8_t))687 ifb_setcolormap(struct sunfb *sf,
688 void (*setcolor)(void *, u_int, u_int8_t, u_int8_t, u_int8_t))
689 {
690 struct rasops_info *ri = &sf->sf_ro;
691 int i;
692 const u_char *color;
693
694 /*
695 * Compensate for overlay plane limitations. Since we'll operate
696 * in 7bpp mode, our basic colors will use positions 00 to 0f,
697 * and the inverted colors will use positions 7f to 70.
698 */
699
700 for (i = 0x00; i < 0x10; i++) {
701 color = &rasops_cmap[i * 3];
702 setcolor(sf, i, color[0], color[1], color[2]);
703 }
704 for (i = 0x70; i < 0x80; i++) {
705 color = &rasops_cmap[(0xf0 | i) * 3];
706 setcolor(sf, i, color[0], color[1], color[2]);
707 }
708
709 /*
710 * Proper operation apparently needs black to be 01, always.
711 * Replace black, red and white with white, black and red.
712 * Kind of ugly, but it works.
713 */
714 ri->ri_devcmap[WSCOL_WHITE] = 0x00000000;
715 ri->ri_devcmap[WSCOL_BLACK] = 0x01010101;
716 ri->ri_devcmap[WSCOL_RED] = 0x07070707;
717
718 color = &rasops_cmap[(WSCOL_WHITE + 8) * 3]; /* real white */
719 setcolor(sf, 0, color[0], color[1], color[2]);
720 setcolor(sf, IFB_PIXELMASK ^ 0, ~color[0], ~color[1], ~color[2]);
721 color = &rasops_cmap[WSCOL_BLACK * 3];
722 setcolor(sf, 1, color[0], color[1], color[2]);
723 setcolor(sf, IFB_PIXELMASK ^ 1, ~color[0], ~color[1], ~color[2]);
724 color = &rasops_cmap[WSCOL_RED * 3];
725 setcolor(sf, 7, color[0], color[1], color[2]);
726 setcolor(sf, IFB_PIXELMASK ^ 7, ~color[0], ~color[1], ~color[2]);
727 }
728
729 paddr_t
ifb_mmap(void * v,off_t off,int prot)730 ifb_mmap(void *v, off_t off, int prot)
731 {
732 struct ifb_softc *sc = (struct ifb_softc *)v;
733
734 switch (sc->sc_mode) {
735 case WSDISPLAYIO_MODE_MAPPED:
736 /*
737 * In mapped mode, provide access to the two overlays,
738 * followed by the control registers, at the following
739 * addresses:
740 * 00000000 overlay 0, size up to 2MB (visible fb size)
741 * 01000000 overlay 1, size up to 2MB (visible fb size)
742 * 02000000 control registers
743 */
744 off -= 0x00000000;
745 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
746 return bus_space_mmap(sc->sc_mem_t,
747 sc->sc_fb8bank0_base,
748 off, prot, BUS_SPACE_MAP_LINEAR);
749 }
750 off -= 0x01000000;
751 if (off >= 0 && off < round_page(sc->sc_sunfb.sf_fbsize)) {
752 return bus_space_mmap(sc->sc_mem_t,
753 sc->sc_fb8bank1_base,
754 off, prot, BUS_SPACE_MAP_LINEAR);
755 }
756 #ifdef APERTURE
757 off -= 0x01000000;
758 if (allowaperture != 0 && sc->sc_acceltype != IFB_ACCEL_NONE) {
759 if (off >= 0 && off < round_page(sc->sc_reglen)) {
760 return bus_space_mmap(sc->sc_mem_t,
761 sc->sc_regbase,
762 off, prot, BUS_SPACE_MAP_LINEAR);
763 }
764 }
765 #endif
766 break;
767 }
768
769 return -1;
770 }
771
772 void
ifb_burner(void * v,u_int on,u_int flags)773 ifb_burner(void *v, u_int on, u_int flags)
774 {
775 struct ifb_softc *sc = (struct ifb_softc *)v;
776 int s;
777 uint32_t dpms;
778
779 s = splhigh();
780 if (on)
781 dpms = IFB_REG_DPMS_ON;
782 else {
783 #ifdef notyet
784 if (flags & WSDISPLAY_BURN_VBLANK)
785 dpms = IFB_REG_DPMS_SUSPEND;
786 else
787 #endif
788 dpms = IFB_REG_DPMS_STANDBY;
789 }
790 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_DPMS_STATE, dpms);
791 splx(s);
792 }
793
794 static inline int
ifb_is_console(int node)795 ifb_is_console(int node)
796 {
797 extern int fbnode;
798
799 return fbnode == node;
800 }
801
802 int
ifb_mapregs(struct ifb_softc * sc,struct pci_attach_args * pa)803 ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa)
804 {
805 u_int32_t cf;
806 int bar, rc;
807
808 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, IFB_PCI_CFG);
809 bar = PCI_MAPREG_START + IFB_PCI_CFG_BAR_OFFSET(cf);
810
811 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);
812 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
813 rc = EINVAL;
814 else {
815 rc = pci_mapreg_map(pa, bar, cf,
816 BUS_SPACE_MAP_LINEAR, NULL, &sc->sc_mem_h,
817 &sc->sc_membase, &sc->sc_memlen, 0);
818 }
819 if (rc != 0) {
820 printf("\n%s: can't map video memory\n",
821 sc->sc_sunfb.sf_dev.dv_xname);
822 return rc;
823 }
824
825 cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar + 4);
826 if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
827 rc = EINVAL;
828 else {
829 rc = pci_mapreg_map(pa, bar + 4, cf,
830 0, NULL, &sc->sc_reg_h,
831 &sc->sc_regbase, &sc->sc_reglen, 0x9000);
832 }
833 if (rc != 0) {
834 printf("\n%s: can't map register space\n",
835 sc->sc_sunfb.sf_dev.dv_xname);
836 return rc;
837 }
838
839 return 0;
840 }
841
842 /*
843 * Non accelerated routines.
844 */
845
846 int
ifb_putchar_dumb(void * cookie,int row,int col,u_int uc,uint32_t attr)847 ifb_putchar_dumb(void *cookie, int row, int col, u_int uc, uint32_t attr)
848 {
849 struct rasops_info *ri = cookie;
850 struct ifb_softc *sc = ri->ri_hw;
851
852 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
853 sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
854 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
855 sc->sc_old_ops.putchar(cookie, row, col, uc, attr);
856
857 return 0;
858 }
859
860 int
ifb_copycols_dumb(void * cookie,int row,int src,int dst,int num)861 ifb_copycols_dumb(void *cookie, int row, int src, int dst, int num)
862 {
863 struct rasops_info *ri = cookie;
864 struct ifb_softc *sc = ri->ri_hw;
865
866 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
867 sc->sc_old_ops.copycols(cookie, row, src, dst, num);
868 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
869 sc->sc_old_ops.copycols(cookie, row, src, dst, num);
870
871 return 0;
872 }
873
874 int
ifb_erasecols_dumb(void * cookie,int row,int col,int num,uint32_t attr)875 ifb_erasecols_dumb(void *cookie, int row, int col, int num, uint32_t attr)
876 {
877 struct rasops_info *ri = cookie;
878 struct ifb_softc *sc = ri->ri_hw;
879
880 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
881 sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
882 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
883 sc->sc_old_ops.erasecols(cookie, row, col, num, attr);
884
885 return 0;
886 }
887
888 int
ifb_copyrows_dumb(void * cookie,int src,int dst,int num)889 ifb_copyrows_dumb(void *cookie, int src, int dst, int num)
890 {
891 struct rasops_info *ri = cookie;
892 struct ifb_softc *sc = ri->ri_hw;
893
894 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
895 sc->sc_old_ops.copyrows(cookie, src, dst, num);
896 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
897 sc->sc_old_ops.copyrows(cookie, src, dst, num);
898
899 return 0;
900 }
901
902 int
ifb_eraserows_dumb(void * cookie,int row,int num,uint32_t attr)903 ifb_eraserows_dumb(void *cookie, int row, int num, uint32_t attr)
904 {
905 struct rasops_info *ri = cookie;
906 struct ifb_softc *sc = ri->ri_hw;
907
908 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
909 sc->sc_old_ops.eraserows(cookie, row, num, attr);
910 ri->ri_bits = (void *)sc->sc_fb8bank1_vaddr;
911 sc->sc_old_ops.eraserows(cookie, row, num, attr);
912
913 return 0;
914 }
915
916 /* Similar to rasops_do_cursor(), but using a 7bit pixel mask. */
917
918 #define CURSOR_MASK 0x7f7f7f7f
919
920 int
ifb_do_cursor_dumb(struct rasops_info * ri)921 ifb_do_cursor_dumb(struct rasops_info *ri)
922 {
923 struct ifb_softc *sc = ri->ri_hw;
924 int full1, height, cnt, slop1, slop2, row, col;
925 int ovl_offset = sc->sc_fb8bank1_vaddr - sc->sc_fb8bank0_vaddr;
926 u_char *dp0, *dp1, *rp;
927
928 row = ri->ri_crow;
929 col = ri->ri_ccol;
930
931 ri->ri_bits = (void *)sc->sc_fb8bank0_vaddr;
932 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
933 height = ri->ri_font->fontheight;
934 slop1 = (4 - ((long)rp & 3)) & 3;
935
936 if (slop1 > ri->ri_xscale)
937 slop1 = ri->ri_xscale;
938
939 slop2 = (ri->ri_xscale - slop1) & 3;
940 full1 = (ri->ri_xscale - slop1 - slop2) >> 2;
941
942 if ((slop1 | slop2) == 0) {
943 /* A common case */
944 while (height--) {
945 dp0 = rp;
946 dp1 = dp0 + ovl_offset;
947 rp += ri->ri_stride;
948
949 for (cnt = full1; cnt; cnt--) {
950 *(int32_t *)dp0 ^= CURSOR_MASK;
951 *(int32_t *)dp1 ^= CURSOR_MASK;
952 dp0 += 4;
953 dp1 += 4;
954 }
955 }
956 } else {
957 /* XXX this is stupid.. use masks instead */
958 while (height--) {
959 dp0 = rp;
960 dp1 = dp0 + ovl_offset;
961 rp += ri->ri_stride;
962
963 if (slop1 & 1) {
964 *dp0++ ^= (u_char)CURSOR_MASK;
965 *dp1++ ^= (u_char)CURSOR_MASK;
966 }
967
968 if (slop1 & 2) {
969 *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
970 *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
971 dp0 += 2;
972 dp1 += 2;
973 }
974
975 for (cnt = full1; cnt; cnt--) {
976 *(int32_t *)dp0 ^= CURSOR_MASK;
977 *(int32_t *)dp1 ^= CURSOR_MASK;
978 dp0 += 4;
979 dp1 += 4;
980 }
981
982 if (slop2 & 1) {
983 *dp0++ ^= (u_char)CURSOR_MASK;
984 *dp1++ ^= (u_char)CURSOR_MASK;
985 }
986
987 if (slop2 & 2) {
988 *(int16_t *)dp0 ^= (int16_t)CURSOR_MASK;
989 *(int16_t *)dp1 ^= (int16_t)CURSOR_MASK;
990 }
991 }
992 }
993
994 return 0;
995 }
996
997 /*
998 * Accelerated routines.
999 */
1000
1001 int
ifb_copycols(void * cookie,int row,int src,int dst,int num)1002 ifb_copycols(void *cookie, int row, int src, int dst, int num)
1003 {
1004 struct rasops_info *ri = cookie;
1005 struct ifb_softc *sc = ri->ri_hw;
1006
1007 num *= ri->ri_font->fontwidth;
1008 src *= ri->ri_font->fontwidth;
1009 dst *= ri->ri_font->fontwidth;
1010 row *= ri->ri_font->fontheight;
1011
1012 ifb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
1013 ri->ri_xorigin + dst, ri->ri_yorigin + row,
1014 num, ri->ri_font->fontheight);
1015
1016 return 0;
1017 }
1018
1019 int
ifb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)1020 ifb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
1021 {
1022 struct rasops_info *ri = cookie;
1023 struct ifb_softc *sc = ri->ri_hw;
1024 int bg, fg;
1025
1026 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
1027
1028 row *= ri->ri_font->fontheight;
1029 col *= ri->ri_font->fontwidth;
1030 num *= ri->ri_font->fontwidth;
1031
1032 ifb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
1033 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
1034
1035 return 0;
1036 }
1037
1038 int
ifb_copyrows(void * cookie,int src,int dst,int num)1039 ifb_copyrows(void *cookie, int src, int dst, int num)
1040 {
1041 struct rasops_info *ri = cookie;
1042 struct ifb_softc *sc = ri->ri_hw;
1043
1044 num *= ri->ri_font->fontheight;
1045 src *= ri->ri_font->fontheight;
1046 dst *= ri->ri_font->fontheight;
1047
1048 ifb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
1049 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
1050
1051 return 0;
1052 }
1053
1054 int
ifb_eraserows(void * cookie,int row,int num,uint32_t attr)1055 ifb_eraserows(void *cookie, int row, int num, uint32_t attr)
1056 {
1057 struct rasops_info *ri = cookie;
1058 struct ifb_softc *sc = ri->ri_hw;
1059 int bg, fg;
1060 int x, y, w;
1061
1062 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
1063
1064 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
1065 num = ri->ri_height;
1066 x = y = 0;
1067 w = ri->ri_width;
1068 } else {
1069 num *= ri->ri_font->fontheight;
1070 x = ri->ri_xorigin;
1071 y = ri->ri_yorigin + row * ri->ri_font->fontheight;
1072 w = ri->ri_emuwidth;
1073 }
1074 ifb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
1075
1076 return 0;
1077 }
1078
1079 void
ifb_copyrect(struct ifb_softc * sc,int sx,int sy,int dx,int dy,int w,int h)1080 ifb_copyrect(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h)
1081 {
1082 ifb_rop(sc, sx, sy, dx, dy, w, h, IFB_ROP_SRC, IFB_PIXELMASK);
1083 ifb_rop_wait(sc);
1084 }
1085
1086 void
ifb_fillrect(struct ifb_softc * sc,int x,int y,int w,int h,int bg)1087 ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg)
1088 {
1089 int32_t mask;
1090
1091 /* pixels to set... */
1092 mask = IFB_PIXELMASK & bg;
1093 if (mask != 0) {
1094 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_SET, mask);
1095 ifb_rop_wait(sc);
1096 }
1097
1098 /* pixels to clear... */
1099 mask = IFB_PIXELMASK & ~bg;
1100 if (mask != 0) {
1101 ifb_rop(sc, x, y, x, y, w, h, IFB_ROP_CLEAR, mask);
1102 ifb_rop_wait(sc);
1103 }
1104 }
1105
1106 /*
1107 * Perform a raster operation on both overlay planes.
1108 * Puzzled by all the magic numbers in there? So are we. Isn't a dire
1109 * lack of documentation wonderful?
1110 */
1111
1112 static inline void
ifb_rop(struct ifb_softc * sc,int sx,int sy,int dx,int dy,int w,int h,uint32_t rop,int32_t planemask)1113 ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h,
1114 uint32_t rop, int32_t planemask)
1115 {
1116 (*sc->sc_rop)(sc, sx, sy, dx, dy, w, h, rop, planemask);
1117 }
1118
1119 void
ifb_rop_common(struct ifb_softc * sc,bus_addr_t reg,int sx,int sy,int dx,int dy,int w,int h,uint32_t rop,int32_t planemask)1120 ifb_rop_common(struct ifb_softc *sc, bus_addr_t reg, int sx, int sy,
1121 int dx, int dy, int w, int h, uint32_t rop, int32_t planemask)
1122 {
1123 int dir = 0;
1124
1125 /*
1126 * Compute rop direction. This only really matters for
1127 * screen-to-screen copies.
1128 */
1129 if (sy < dy /* && sy + h > dy */) {
1130 sy += h - 1;
1131 dy += h;
1132 dir |= IFB_BLT_DIR_BACKWARDS_Y;
1133 }
1134 if (sx < dx /* && sx + w > dx */) {
1135 sx += w - 1;
1136 dx += w;
1137 dir |= IFB_BLT_DIR_BACKWARDS_X;
1138 }
1139
1140 /* Which one of those below is your magic number for today? */
1141 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x61000001);
1142 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1143 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x6301c080);
1144 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x80000000);
1145 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, rop);
1146 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, planemask);
1147 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1148 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x64000303);
1149 /*
1150 * This value is a pixel offset within the destination area. It is
1151 * probably used to define complex polygon shapes, with the
1152 * last pixel in the list being back to (0,0).
1153 */
1154 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(0, 0));
1155 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
1156 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00030000);
1157 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x2200010d);
1158
1159 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x33f01000 | dir);
1160 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(dx, dy));
1161 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(w, h));
1162 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(sx, sy));
1163 }
1164
1165 void
ifb_rop_ifb(void * v,int sx,int sy,int dx,int dy,int w,int h,uint32_t rop,int32_t planemask)1166 ifb_rop_ifb(void *v, int sx, int sy, int dx, int dy, int w, int h,
1167 uint32_t rop, int32_t planemask)
1168 {
1169 struct ifb_softc *sc = (struct ifb_softc *)v;
1170 bus_addr_t reg = IFB_REG_ENGINE;
1171
1172 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 2);
1173 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 1);
1174 /* the ``0101'' part is probably a component selection */
1175 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x540101ff);
1176
1177 ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
1178 }
1179
1180 void
ifb_rop_jfb(void * v,int sx,int sy,int dx,int dy,int w,int h,uint32_t rop,int32_t planemask)1181 ifb_rop_jfb(void *v, int sx, int sy, int dx, int dy, int w, int h,
1182 uint32_t rop, int32_t planemask)
1183 {
1184 struct ifb_softc *sc = (struct ifb_softc *)v;
1185 bus_addr_t reg = JFB_REG_ENGINE;
1186 uint32_t spr, splr;
1187
1188 /*
1189 * Pick the current spr and splr values from the communication
1190 * area if possible.
1191 */
1192 if (sc->sc_comm != NULL) {
1193 spr = sc->sc_comm[IFB_SHARED_TERM8_SPR >> 2];
1194 splr = sc->sc_comm[IFB_SHARED_TERM8_SPLR >> 2];
1195 } else {
1196 /* supposedly sane defaults */
1197 spr = 0x54ff0303;
1198 splr = 0x5c0000ff;
1199 }
1200
1201 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00400016);
1202 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000002);
1203 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000000);
1204 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, spr);
1205 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, splr);
1206
1207 ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
1208
1209 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000001);
1210 bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000001);
1211 }
1212
1213 int
ifb_rop_wait(struct ifb_softc * sc)1214 ifb_rop_wait(struct ifb_softc *sc)
1215 {
1216 int i;
1217
1218 for (i = 1000000; i != 0; i--) {
1219 if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
1220 IFB_REG_STATUS) & IFB_REG_STATUS_DONE)
1221 break;
1222 DELAY(1);
1223 }
1224
1225 return i;
1226 }
1227
1228 int
ifb_do_cursor(struct rasops_info * ri)1229 ifb_do_cursor(struct rasops_info *ri)
1230 {
1231 struct ifb_softc *sc = ri->ri_hw;
1232 int y, x;
1233
1234 y = ri->ri_yorigin + ri->ri_crow * ri->ri_font->fontheight;
1235 x = ri->ri_xorigin + ri->ri_ccol * ri->ri_font->fontwidth;
1236
1237 ifb_rop(sc, x, y, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight,
1238 IFB_ROP_XOR, IFB_PIXELMASK);
1239 ifb_rop_wait(sc);
1240
1241 return 0;
1242 }
1243