diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-01-21 17:01:32 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-01-21 17:01:32 +0000 |
commit | bfd46f718e22f99ba43d3ecadfdd66792dad1e82 (patch) | |
tree | 0526b538d3f2e0d0574e6a07cf82c0b0e5ad760f /sys | |
parent | 0feab27359e5707bbfecbdb0c711d0b3cb380011 (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.c | 479 |
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); } |