summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-01-21 17:01:32 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-01-21 17:01:32 +0000
commitbfd46f718e22f99ba43d3ecadfdd66792dad1e82 (patch)
tree0526b538d3f2e0d0574e6a07cf82c0b0e5ad760f /sys
parent0feab27359e5707bbfecbdb0c711d0b3cb380011 (diff)
Extend the acceleration code to handle jfb (XVR-600, XVR-1200) models, the
software only code is kept in case we can't reliably figure out what kind of device we are facing. Tested on XVR-1200 by Mattieu Baptiste, and on Expert3D-Lite by me.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/dev/ifb.c479
1 files changed, 327 insertions, 152 deletions
diff --git a/sys/arch/sparc64/dev/ifb.c b/sys/arch/sparc64/dev/ifb.c
index cd5ab3779d8..554b70fbeaf 100644
--- a/sys/arch/sparc64/dev/ifb.c
+++ b/sys/arch/sparc64/dev/ifb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifb.c,v 1.15 2009/01/19 22:12:11 miod Exp $ */
+/* $OpenBSD: ifb.c,v 1.16 2009/01/21 17:01:31 miod Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Miodrag Vallat.
@@ -73,9 +73,11 @@ extern int allowaperture;
* The card exposes the following resources:
* - a 32MB aperture window in which views to the different frame buffer
* areas can be mapped, in the first BAR.
- * - a 64KB PROM and registers area, in the second BAR, with the registers
- * starting 32KB within this area.
- * - a 8MB memory mapping, which purpose is unknown, in the third BAR.
+ * - a 64KB or 128KB PROM and registers area, in the second BAR.
+ * - a 8MB ``direct burst'' memory mapping, in the third BAR.
+ *
+ * The location of this BAR range is pointed to by a board-specific PCI
+ * configuration register.
*
* In the state the PROM leaves us in, the 8MB frame buffer windows map
* the video memory as interleaved stripes, of which the non-visible parts
@@ -91,6 +93,36 @@ extern int allowaperture;
*/
/*
+ * The Fcode driver sets up a communication structure, allowing third-party
+ * code to reprogram the video mode while still allowing the Fcode routines
+ * to access the overlay planes.
+ *
+ * We'll use this information as well, although so far it's unlikely
+ * any code will do so, as long as the only documentation for this
+ * hardware amounts to zilch.
+ */
+
+/* probably some form of signature */
+#define IFB_SHARED_SIGNATURE 0x00
+#define SIG_IFB 0x09209911
+#define SIG_JFB 0x05140213
+#define IFB_SHARED_MONITOR_MODE 0x10
+#define IFB_SHARED_WIDTH 0x14
+#define IFB_SHARED_HEIGHT 0x18
+#define IFB_SHARED_V_FREQ 0x1c
+#define IFB_SHARED_TIMING_H_FP 0x20
+#define IFB_SHARED_TIMING_H_SYNC 0x24
+#define IFB_SHARED_TIMING_H_BP 0x28
+#define IFB_SHARED_TIMING_V_FP 0x2c
+#define IFB_SHARED_TIMING_V_SYNC 0x30
+#define IFB_SHARED_TIMING_V_BP 0x34
+#define IFB_SHARED_TIMING_FLAGS 0x38
+#define IFB_SHARED_CMAP_DIRTY 0x3c
+#define IFB_SHARED_TERM8_GSR 0x4c
+#define IFB_SHARED_TERM8_SPR 0x50
+#define IFB_SHARED_TERM8_SPLR 0x54
+
+/*
* The Expert3D has an extra BAR that is not present on the -Lite
* version. This register contains bits that tell us how many BARs to
* skip before we get to the BARs that interest us.
@@ -98,44 +130,40 @@ extern int allowaperture;
#define IFB_PCI_CFG 0x5c
#define IFB_PCI_CFG_BAR_OFFSET(x) ((x & 0x000000e0) >> 3)
-#define IFB_REG_OFFSET 0x8000
-
/*
- * 0000 magic
- * This register seems to be used to issue commands to the
+ * 6000 (jfb) / 8000 (ifb) engine command
+ * This register is used to issue (some) commands sequences to the
* acceleration hardware.
- *
*/
-#define IFB_REG_MAGIC 0x0000
-#define IFB_REG_MAGIC_DIR_BACKWARDS_Y (0x08 | 0x02)
-#define IFB_REG_MAGIC_DIR_BACKWARDS_X (0x04 | 0x01)
+#define JFB_REG_ENGINE 0x6000
+#define IFB_REG_ENGINE 0x8000
/*
- * 0040 component configuration
+ * 8040 component configuration
* This register controls which parts of the board will be addressed by
* writes to other configuration registers.
* Apparently the low two bytes control the frame buffer windows for the
* given head (starting at 1).
* The high two bytes are texture related.
*/
-#define IFB_REG_COMPONENT_SELECT 0x0040
+#define IFB_REG_COMPONENT_SELECT 0x8040
/*
- * 0044 status
+ * 8044 status
* This register has a bit that signals completion of commands issued
* to the acceleration hardware.
*/
-#define IFB_REG_STATUS 0x0044
+#define IFB_REG_STATUS 0x8044
#define IFB_REG_STATUS_DONE 0x00000004
/*
- * 0058 magnifying configuration
+ * 8058 magnifying configuration
* This register apparently controls magnifying.
* bits 5-6 select the window width divider (00: by 2, 01: by 4, 10: by 8,
* 11: by 16)
* bits 7-8 select the zoom factor (00: disabled, 01: x2, 10: x4, 11: x8)
*/
-#define IFB_REG_MAGNIFY 0x0058
+#define IFB_REG_MAGNIFY 0x8058
#define IFB_REG_MAGNIFY_DISABLE 0x00000000
#define IFB_REG_MAGNIFY_X2 0x00000040
#define IFB_REG_MAGNIFY_X4 0x00000080
@@ -146,63 +174,63 @@ extern int allowaperture;
#define IFB_REG_MAGNIFY_WINDIV16 0x00000030
/*
- * 0070 display resolution
+ * 8070 display resolution
* Contains the size of the display, as ((height - 1) << 16) | (width - 1)
*/
-#define IFB_REG_RESOLUTION 0x0070
+#define IFB_REG_RESOLUTION 0x8070
/*
- * 0074 configuration register
+ * 8074 configuration register
* Contains 0x1a000088 | ((Log2 stride) << 16)
*/
-#define IFB_REG_CONFIG 0x0074
+#define IFB_REG_CONFIG 0x8074
/*
- * 0078 32bit frame buffer window #0 (8 to 9 MB)
+ * 8078 32bit frame buffer window #0 (8 to 9 MB)
* Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
*/
-#define IFB_REG_FB32_0 0x0078
+#define IFB_REG_FB32_0 0x8078
/*
- * 007c 32bit frame buffer window #1 (8 to 9 MB)
+ * 807c 32bit frame buffer window #1 (8 to 9 MB)
* Contains the offset (relative to BAR0) of the 32 bit frame buffer window.
*/
-#define IFB_REG_FB32_1 0x007c
+#define IFB_REG_FB32_1 0x807c
/*
- * 0080 8bit frame buffer window #0 (2 to 2.2 MB)
+ * 8080 8bit frame buffer window #0 (2 to 2.2 MB)
* Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
*/
-#define IFB_REG_FB8_0 0x0080
+#define IFB_REG_FB8_0 0x8080
/*
- * 0084 8bit frame buffer window #1 (2 to 2.2 MB)
+ * 8084 8bit frame buffer window #1 (2 to 2.2 MB)
* Contains the offset (relative to BAR0) of the 8 bit frame buffer window.
*/
-#define IFB_REG_FB8_1 0x0084
+#define IFB_REG_FB8_1 0x8084
/*
- * 0088 unknown window (as large as a 32 bit frame buffer)
+ * 8088 unknown window (as large as a 32 bit frame buffer)
*/
-#define IFB_REG_FB_UNK0 0x0088
+#define IFB_REG_FB_UNK0 0x8088
/*
- * 008c unknown window (as large as a 8 bit frame buffer)
+ * 808c unknown window (as large as a 8 bit frame buffer)
*/
-#define IFB_REG_FB_UNK1 0x008c
+#define IFB_REG_FB_UNK1 0x808c
/*
- * 0090 unknown window (as large as a 8 bit frame buffer)
+ * 8090 unknown window (as large as a 8 bit frame buffer)
*/
-#define IFB_REG_FB_UNK2 0x0090
+#define IFB_REG_FB_UNK2 0x8090
/*
- * 00bc RAMDAC palette index register
+ * 80bc RAMDAC palette index register
*/
-#define IFB_REG_CMAP_INDEX 0x00bc
+#define IFB_REG_CMAP_INDEX 0x80bc
/*
- * 00c0 RAMDAC palette data register
+ * 80c0 RAMDAC palette data register
*/
-#define IFB_REG_CMAP_DATA 0x00c0
+#define IFB_REG_CMAP_DATA 0x80c0
/*
- * 00e4 DPMS state register
+ * 80e4 DPMS state register
* States ``off'' and ``suspend'' need chip reprogramming before video can
* be enabled again.
*/
-#define IFB_REG_DPMS_STATE 0x00e4
+#define IFB_REG_DPMS_STATE 0x80e4
#define IFB_REG_DPMS_OFF 0x00000000
#define IFB_REG_DPMS_SUSPEND 0x00000001
#define IFB_REG_DPMS_STANDBY 0x00000002
@@ -219,6 +247,10 @@ extern int allowaperture;
#define IFB_COORDS(x, y) ((x) | (y) << 16)
+/* blitter directions */
+#define IFB_BLT_DIR_BACKWARDS_Y (0x08 | 0x02)
+#define IFB_BLT_DIR_BACKWARDS_X (0x04 | 0x01)
+
#define IFB_PIXELMASK 0x7f /* 7bpp */
struct ifb_softc {
@@ -227,22 +259,30 @@ struct ifb_softc {
bus_space_tag_t sc_mem_t;
pcitag_t sc_pcitag;
+ /* overlays mappings */
bus_space_handle_t sc_mem_h;
bus_addr_t sc_membase, sc_fb8bank0_base, sc_fb8bank1_base;
bus_size_t sc_memlen;
vaddr_t sc_memvaddr, sc_fb8bank0_vaddr, sc_fb8bank1_vaddr;
+ /* registers mapping */
bus_space_handle_t sc_reg_h;
bus_addr_t sc_regbase;
bus_size_t sc_reglen;
- u_int sc_mode;
- u_int sc_accel;
+ /* communication area */
+ volatile uint32_t *sc_comm;
- struct wsdisplay_emulops sc_old_ops;
- void (*sc_old_cursor)(struct rasops_info *);
+ /* acceleration information */
+ u_int sc_acceltype;
+#define IFB_ACCEL_NONE 0
+#define IFB_ACCEL_IFB 1 /* Expert3D style */
+#define IFB_ACCEL_JFB 2 /* XVR-500 style */
+ void (*sc_rop)(void *, int, int, int, int, int, int, uint32_t, int32_t);
- int sc_console;
+ /* wsdisplay related goo */
+ u_int sc_mode;
+ struct wsdisplay_emulops sc_old_ops;
u_int8_t sc_cmap_red[256];
u_int8_t sc_cmap_green[256];
u_int8_t sc_cmap_blue[256];
@@ -276,7 +316,11 @@ struct cfdriver ifb_cd = {
NULL, "ifb", DV_DULL
};
+int ifb_accel_identify(struct pci_attach_args *);
+static inline
+u_int ifb_dac_value(u_int, u_int, u_int);
int ifb_getcmap(struct ifb_softc *, struct wsdisplay_cmap *);
+static inline
int ifb_is_console(int);
int ifb_mapregs(struct ifb_softc *, struct pci_attach_args *);
int ifb_putcmap(struct ifb_softc *, struct wsdisplay_cmap *);
@@ -286,8 +330,13 @@ void ifb_setcolormap(struct sunfb *,
void ifb_copyrect(struct ifb_softc *, int, int, int, int, int, int);
void ifb_fillrect(struct ifb_softc *, int, int, int, int, int);
+static inline
void ifb_rop(struct ifb_softc *, int, int, int, int, int, int, uint32_t,
int32_t);
+void ifb_rop_common(struct ifb_softc *, bus_addr_t, int, int, int, int,
+ int, int, uint32_t, int32_t);
+void ifb_rop_ifb(void *, int, int, int, int, int, int, uint32_t, int32_t);
+void ifb_rop_jfb(void *, int, int, int, int, int, int, uint32_t, int32_t);
int ifb_rop_wait(struct ifb_softc *);
void ifb_putchar_dumb(void *, int, int, u_int, long);
@@ -307,22 +356,7 @@ void ifb_do_cursor(struct rasops_info *);
int
ifbmatch(struct device *parent, void *cf, void *aux)
{
- struct pci_attach_args *paa = aux;
- int rc;
-
- if ((rc = ifb_ident(aux)) == 0)
- return 0;
-
- /*
- * Multiple heads appear as PCI subfunctions.
- * However, the ofw node for it lacks most properties,
- * and its BAR only give access to registers, not
- * frame buffer memory.
- */
- if (node_has_property(PCITAG_NODE(paa->pa_tag), "device_type"))
- return rc;
-
- return 0;
+ return ifb_ident(aux);
}
void
@@ -331,20 +365,49 @@ ifbattach(struct device *parent, struct device *self, void *aux)
struct ifb_softc *sc = (struct ifb_softc *)self;
struct pci_attach_args *paa = aux;
struct rasops_info *ri;
- int node;
+ uint32_t dev_comm;
+ int node, console;
+ char *text;
sc->sc_mem_t = paa->pa_memt;
sc->sc_pcitag = paa->pa_tag;
+ node = PCITAG_NODE(paa->pa_tag);
+ console = ifb_is_console(node);
+
printf("\n");
+ /*
+ * Multiple heads appear as PCI subfunctions.
+ * However, the ofw node for it lacks most properties,
+ * and its BAR only give access to registers, not
+ * frame buffer memory.
+ */
+ if (!node_has_property(node, "device_type")) {
+ printf("%s: secondary output not supported yet\n",
+ self->dv_xname);
+ return;
+ }
+
+ /*
+ * Describe the beast.
+ */
+
+ text = getpropstring(node, "name");
+ if (strncmp(text, "SUNW,", 5) == 0)
+ text += 5;
+ printf("%s: %s", self->dv_xname, text);
+ text = getpropstring(node, "model");
+ if (*text != '\0')
+ printf(" (%s)", text);
+
if (ifb_mapregs(sc, paa))
return;
sc->sc_fb8bank0_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_FB8_0);
+ IFB_REG_FB8_0);
sc->sc_fb8bank1_base = bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_FB8_1);
+ IFB_REG_FB8_1);
sc->sc_memvaddr = (vaddr_t)bus_space_vaddr(sc->sc_mem_t, sc->sc_mem_h);
sc->sc_fb8bank0_vaddr = sc->sc_memvaddr +
@@ -352,31 +415,53 @@ ifbattach(struct device *parent, struct device *self, void *aux)
sc->sc_fb8bank1_vaddr = sc->sc_memvaddr +
sc->sc_fb8bank1_base - sc->sc_membase;
- node = PCITAG_NODE(paa->pa_tag);
- sc->sc_console = ifb_is_console(node);
-
+ /*
+ * The values stored into the node properties might have been
+ * modified since the Fcode was last run. Pick the geometry
+ * information from the configuration registers instead.
+ * This replaces
fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
+ */
- printf("%s: %dx%d\n",
- self->dv_xname, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
+ sc->sc_sunfb.sf_width = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
+ IFB_REG_RESOLUTION) & 0xffff) + 1;
+ sc->sc_sunfb.sf_height = (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
+ IFB_REG_RESOLUTION) >> 16) + 1;
+ sc->sc_sunfb.sf_depth = 8;
+ sc->sc_sunfb.sf_linebytes = 1 << (bus_space_read_4(sc->sc_mem_t,
+ sc->sc_reg_h, IFB_REG_CONFIG) >> 16);
+ sc->sc_sunfb.sf_fbsize =
+ sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
-#if 0
- /*
- * Make sure the frame buffer is configured to sane values.
- * So much more is needed there... documentation permitting.
- */
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_COMPONENT_SELECT, 0x00000101);
- delay(1000);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGNIFY, IFB_REG_MAGNIFY_DISABLE);
-#endif
+ printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
ri = &sc->sc_sunfb.sf_ro;
ri->ri_bits = NULL;
ri->ri_hw = sc;
- fbwscons_init(&sc->sc_sunfb, RI_BSWAP, sc->sc_console);
+ fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
+
+ /*
+ * Find out what flavour of ifb we are...
+ */
+
+ sc->sc_acceltype = ifb_accel_identify(paa);
+
+ switch (sc->sc_acceltype) {
+ case IFB_ACCEL_IFB:
+ sc->sc_rop = ifb_rop_ifb;
+ break;
+ case IFB_ACCEL_JFB:
+ /*
+ * Remember the address of the communication area
+ */
+ if (OF_getprop(node, "dev-comm", &dev_comm,
+ sizeof dev_comm) != -1) {
+ sc->sc_comm = (volatile uint32_t *)(vaddr_t)dev_comm;
+ }
+ sc->sc_rop = ifb_rop_jfb;
+ break;
+ }
/*
* Clear the unwanted pixel planes: all if non console (thus
@@ -384,15 +469,22 @@ ifbattach(struct device *parent, struct device *self, void *aux)
* This also allows to check whether the accelerated code works,
* or not.
*/
- ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
- IFB_ROP_CLEAR, sc->sc_console ? ~IFB_PIXELMASK : ~0);
- if (ifb_rop_wait(sc) != 0) {
- sc->sc_accel = 1;
- } else {
+
+ if (sc->sc_acceltype != IFB_ACCEL_NONE) {
+ ifb_rop(sc, 0, 0, 0, 0, sc->sc_sunfb.sf_width,
+ sc->sc_sunfb.sf_height, IFB_ROP_CLEAR,
+ console ? ~IFB_PIXELMASK : ~0);
+ if (ifb_rop_wait(sc) == 0) {
+ /* fall back to dumb software operation */
+ sc->sc_acceltype = IFB_ACCEL_NONE;
+ }
+ }
+
+ if (sc->sc_acceltype == IFB_ACCEL_NONE) {
/* due to the way we will handle updates */
ri->ri_flg &= ~RI_FULLCLEAR;
- if (!sc->sc_console) {
+ if (!console) {
bzero((void *)sc->sc_fb8bank0_vaddr,
sc->sc_sunfb.sf_fbsize);
bzero((void *)sc->sc_fb8bank1_vaddr,
@@ -405,9 +497,8 @@ ifbattach(struct device *parent, struct device *self, void *aux)
sc->sc_fb8bank1_vaddr += ri->ri_bits - ri->ri_origbits;
sc->sc_old_ops = ri->ri_ops; /* structure copy */
- sc->sc_old_cursor = ri->ri_do_cursor;
- if (sc->sc_accel) {
+ if (sc->sc_acceltype != IFB_ACCEL_NONE) {
ri->ri_ops.copyrows = ifb_copyrows;
ri->ri_ops.copycols = ifb_copycols;
ri->ri_ops.eraserows = ifb_eraserows;
@@ -426,9 +517,47 @@ ifbattach(struct device *parent, struct device *self, void *aux)
ifb_setcolormap(&sc->sc_sunfb, ifb_setcolor);
sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
- if (sc->sc_console)
+ if (console)
fbwscons_console_init(&sc->sc_sunfb, -1);
- fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, sc->sc_console);
+ fbwscons_attach(&sc->sc_sunfb, &ifb_accessops, console);
+}
+
+/*
+ * Attempt to identify what kind of ifb we are talking to, so as to setup
+ * proper acceleration information.
+ */
+int
+ifb_accel_identify(struct pci_attach_args *pa)
+{
+ uint32_t subid;
+
+ subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
+
+ /*
+ * If we have an exact Expert3D match, or the subsystem id
+ * matches Expert3D or Expert3D-Lite, we have an IFB.
+ */
+
+ if (pa->pa_id ==
+ PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, PCI_PRODUCT_INTERGRAPH_EXPERT3D))
+ return IFB_ACCEL_IFB;
+ if (subid == PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, 0x108) ||
+ subid == PCI_ID_CODE(PCI_VENDOR_INTERGRAPH, 0x140))
+ return IFB_ACCEL_IFB;
+
+ /*
+ * If we have an exact 5110 match, or the subsystem id matches
+ * another set of magic values, we have a JFB.
+ */
+
+ if (pa->pa_id ==
+ PCI_ID_CODE(PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_WILDCAT_5110))
+ return IFB_ACCEL_JFB;
+ if (subid == PCI_ID_CODE(PCI_VENDOR_3DLABS, 0x1044) ||
+ subid == PCI_ID_CODE(PCI_VENDOR_3DLABS, 0x1047))
+ return IFB_ACCEL_JFB;
+
+ return IFB_ACCEL_NONE;
}
int
@@ -489,6 +618,22 @@ ifb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
return 0;
}
+static inline
+u_int
+ifb_dac_value(u_int r, u_int g, u_int b)
+{
+ /*
+ * Convert 8 bit values to 10 bit scale, by shifting and inserting
+ * the former high bits in the low two bits.
+ * Simply shifting is sligthly too dull.
+ */
+ r = (r << 2) | (r >> 6);
+ g = (g << 2) | (g >> 6);
+ b = (b << 2) | (b >> 6);
+
+ return (b << 20) | (g << 10) | r;
+}
+
int
ifb_getcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
{
@@ -536,10 +681,9 @@ ifb_putcmap(struct ifb_softc *sc, struct wsdisplay_cmap *cm)
for (i = 0; i < count; i++) {
bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_CMAP_DATA,
- (((u_int)*b) << 22) | (((u_int)*g) << 12) | (((u_int)*r) << 2));
+ IFB_REG_CMAP_INDEX, index);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
+ ifb_dac_value(*r, *g, *b));
r++, g++, b++, index++;
}
return 0;
@@ -554,11 +698,10 @@ ifb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
sc->sc_cmap_green[index] = g;
sc->sc_cmap_blue[index] = b;
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_CMAP_INDEX, index);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_CMAP_DATA,
- (((u_int)b) << 22) | (((u_int)g) << 12) | (((u_int)r) << 2));
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_INDEX,
+ index);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_CMAP_DATA,
+ ifb_dac_value(r, g, b));
}
/* similar in spirit to fbwscons_setcolormap() */
@@ -634,7 +777,7 @@ ifb_mmap(void *v, off_t off, int prot)
}
#ifdef APERTURE
off -= 0x01000000;
- if (allowaperture != 0 && sc->sc_accel) {
+ if (allowaperture != 0 && sc->sc_acceltype != IFB_ACCEL_NONE) {
if (off >= 0 && off < round_page(sc->sc_reglen)) {
return bus_space_mmap(sc->sc_mem_t,
sc->sc_regbase,
@@ -666,12 +809,11 @@ ifb_burner(void *v, u_int on, u_int flags)
#endif
dpms = IFB_REG_DPMS_STANDBY;
}
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_DPMS_STATE, dpms);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, IFB_REG_DPMS_STATE, dpms);
splx(s);
}
-int
+static inline int
ifb_is_console(int node)
{
extern int fbnode;
@@ -697,7 +839,7 @@ ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa)
&sc->sc_membase, &sc->sc_memlen, 0);
}
if (rc != 0) {
- printf("%s: can't map video memory\n",
+ printf("\n%s: can't map video memory\n",
sc->sc_sunfb.sf_dev.dv_xname);
return rc;
}
@@ -711,7 +853,7 @@ ifb_mapregs(struct ifb_softc *sc, struct pci_attach_args *pa)
&sc->sc_regbase, &sc->sc_reglen, 0x9000);
}
if (rc != 0) {
- printf("%s: can't map register space\n",
+ printf("\n%s: can't map register space\n",
sc->sc_sunfb.sf_dev.dv_xname);
return rc;
}
@@ -968,10 +1110,18 @@ ifb_fillrect(struct ifb_softc *sc, int x, int y, int w, int h, int bg)
* Puzzled by all the magic numbers in there? So are we. Isn't a dire
* lack of documentation wonderful?
*/
-void
+
+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)
{
+ (*sc->sc_rop)(sc, sx, sy, dx, dy, w, h, rop, planemask);
+}
+
+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)
+{
int dir = 0;
/*
@@ -981,60 +1131,85 @@ ifb_rop(struct ifb_softc *sc, int sx, int sy, int dx, int dy, int w, int h,
if (sy < dy /* && sy + h > dy */) {
sy += h - 1;
dy += h;
- dir |= IFB_REG_MAGIC_DIR_BACKWARDS_Y;
+ dir |= IFB_BLT_DIR_BACKWARDS_Y;
}
if (sx < dx /* && sx + w > dx */) {
sx += w - 1;
dx += w;
- dir |= IFB_REG_MAGIC_DIR_BACKWARDS_X;
+ dir |= IFB_BLT_DIR_BACKWARDS_X;
}
/* Which one of those below is your magic number for today? */
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 2);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 1);
- /* the ``0101'' part is probably a component selection */
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x540101ff);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x61000001);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x6301c080);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x80000000);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, rop);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, planemask);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x64000303);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x61000001);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x6301c080);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x80000000);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, rop);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, planemask);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x64000303);
/*
* This value is a pixel offset within the destination area. It is
* probably used to define complex polygon shapes, with the
* last pixel in the list being back to (0,0).
*/
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(0, 0));
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x00030000);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x2200010d);
-
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, 0x33f01000 | dir);
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(dx, dy));
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(w, h));
- bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_MAGIC, IFB_COORDS(sx, sy));
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(0, 0));
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00030000);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x2200010d);
+
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x33f01000 | dir);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(dx, dy));
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(w, h));
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, IFB_COORDS(sx, sy));
+}
+
+void
+ifb_rop_ifb(void *v, int sx, int sy, int dx, int dy, int w, int h,
+ uint32_t rop, int32_t planemask)
+{
+ struct ifb_softc *sc = (struct ifb_softc *)v;
+ bus_addr_t reg = IFB_REG_ENGINE;
+
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 2);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 1);
+ /* the ``0101'' part is probably a component selection */
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x540101ff);
+
+ ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
+}
+
+void
+ifb_rop_jfb(void *v, int sx, int sy, int dx, int dy, int w, int h,
+ uint32_t rop, int32_t planemask)
+{
+ struct ifb_softc *sc = (struct ifb_softc *)v;
+ bus_addr_t reg = JFB_REG_ENGINE;
+ uint32_t spr, splr;
+
+ /*
+ * Pick the current spr and splr values from the communication
+ * area if possible.
+ */
+ if (sc->sc_comm != NULL) {
+ spr = sc->sc_comm[IFB_SHARED_TERM8_SPR >> 2];
+ splr = sc->sc_comm[IFB_SHARED_TERM8_SPLR >> 2];
+ } else {
+ /* supposedly sane defaults */
+ spr = 0x54ff0303;
+ splr = 0x5c0000ff;
+ }
+
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x00400016);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000002);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000000);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, spr);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, splr);
+
+ ifb_rop_common(sc, reg, sx, sy, dx, dy, w, h, rop, planemask);
+
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5a000001);
+ bus_space_write_4(sc->sc_mem_t, sc->sc_reg_h, reg, 0x5b000001);
}
int
@@ -1044,7 +1219,7 @@ ifb_rop_wait(struct ifb_softc *sc)
for (i = 1000000; i != 0; i--) {
if (bus_space_read_4(sc->sc_mem_t, sc->sc_reg_h,
- IFB_REG_OFFSET + IFB_REG_STATUS) & IFB_REG_STATUS_DONE)
+ IFB_REG_STATUS) & IFB_REG_STATUS_DONE)
break;
DELAY(1);
}