Module Name: src Committed By: macallan Date: Tue Nov 19 12:12:18 UTC 2024
Added Files: src/sys/arch/hppa/dev: summitfb.c Log Message: beginnings of a driver for Visualize FX graphics cards So far it does: - work on my FX4 - use the 8bit overlay, in R3G3B2 - all drawing by software, clear screen by hw - X works in 8bit with wsfb To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/arch/hppa/dev/summitfb.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Added files: Index: src/sys/arch/hppa/dev/summitfb.c diff -u /dev/null src/sys/arch/hppa/dev/summitfb.c:1.1 --- /dev/null Tue Nov 19 12:12:18 2024 +++ src/sys/arch/hppa/dev/summitfb.c Tue Nov 19 12:12:18 2024 @@ -0,0 +1,1436 @@ +/* $NetBSD: summitfb.c,v 1.1 2024/11/19 12:12:18 macallan Exp $ */ + +/* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */ + +/* + * Copyright (c) 2006, 2007 Miodrag Vallat. + ^ 2024 Michael Lorenz + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice, this permission notice, and the disclaimer below + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * a native driver for HP Visualize EG PCI graphics cards + * STI portions are from Miodrag Vallat's sti_pci.c + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kmem.h> +#include <sys/device.h> +#include <sys/mutex.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcidevs.h> +#include <dev/pci/pciio.h> + +#include <dev/wscons/wsdisplayvar.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wsfont/wsfont.h> +#include <dev/rasops/rasops.h> +#include <dev/wscons/wsdisplay_vconsvar.h> +#include <dev/pci/wsdisplay_pci.h> +#include <dev/wscons/wsdisplay_glyphcachevar.h> + +#include <dev/ic/stireg.h> +#include <dev/ic/stivar.h> + +#include "opt_summitfb.h" + +#ifdef SUMMITFB_DEBUG +#define DPRINTF(s) printf(s) +#else +#define DPRINTF(s) /* */ +#endif + +int summitfb_match(device_t, cfdata_t, void *); +void summitfb_attach(device_t, device_t, void *); + +struct summitfb_softc { + device_t sc_dev; + pci_chipset_tag_t sc_pc; + pcitag_t sc_tag; + + /* stuff we need in order to use the STI ROM */ + struct sti_softc sc_base; + struct sti_screen sc_scr; + bus_space_handle_t sc_romh; + + int sc_width, sc_height; + int sc_locked; + struct vcons_screen sc_console_screen; + struct wsscreen_descr sc_defaultscreen_descr; + const struct wsscreen_descr *sc_screens[1]; + struct wsscreen_list sc_screenlist; + struct vcons_data vd; + int sc_mode; + void (*sc_putchar)(void *, int, int, u_int, long); + u_char sc_cmap_red[256]; + u_char sc_cmap_green[256]; + u_char sc_cmap_blue[256]; + kmutex_t sc_hwlock; + uint32_t sc_hwmode; +#define HW_FB 0 +#define HW_FILL 1 +#define HW_BLIT 2 + /* cursor stuff */ + int sc_cursor_x, sc_cursor_y; + int sc_hot_x, sc_hot_y, sc_enabled; + int sc_video_on; + glyphcache sc_gc; +}; + +CFATTACH_DECL_NEW(summitfb, sizeof(struct summitfb_softc), + summitfb_match, summitfb_attach, NULL, NULL); + +int summitfb_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int); +int summitfb_check_rom(struct summitfb_softc *, struct pci_attach_args *); +void summitfb_enable_rom(struct sti_softc *); +void summitfb_disable_rom(struct sti_softc *); +void summitfb_enable_rom_internal(struct summitfb_softc *); +void summitfb_disable_rom_internal(struct summitfb_softc *); + +void summitfb_setup(struct summitfb_softc *); + +/* XXX these really need to go into their own header */ +int sti_pci_is_console(struct pci_attach_args *, bus_addr_t *); +int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, + bus_space_handle_t, bus_addr_t *, u_int); +int sti_screen_setup(struct sti_screen *, int); +void sti_describe_screen(struct sti_softc *, struct sti_screen *); + +#define PCI_ROM_SIZE(mr) \ + (PCI_MAPREG_ROM_ADDR(mr) & -PCI_MAPREG_ROM_ADDR(mr)) + +/* wsdisplay stuff */ +static int summitfb_ioctl(void *, void *, u_long, void *, int, + struct lwp *); +static paddr_t summitfb_mmap(void *, void *, off_t, int); +static void summitfb_init_screen(void *, struct vcons_screen *, int, long *); + +static int summitfb_putcmap(struct summitfb_softc *, struct wsdisplay_cmap *); +static int summitfb_getcmap(struct summitfb_softc *, struct wsdisplay_cmap *); +static void summitfb_restore_palette(struct summitfb_softc *); +static int summitfb_putpalreg(struct summitfb_softc *, uint8_t, uint8_t, + uint8_t, uint8_t); + +static inline void summitfb_setup_fb(struct summitfb_softc *); + +static void summitfb_rectfill(struct summitfb_softc *, int, int, int, int, + uint32_t); +static void summitfb_bitblt(void *, int, int, int, int, int, + int, int); + +static void summitfb_cursor(void *, int, int, int); +static void summitfb_putchar(void *, int, int, u_int, long); +static void summitfb_putchar_aa(void *, int, int, u_int, long); +static void summitfb_copycols(void *, int, int, int, int); +static void summitfb_erasecols(void *, int, int, int, long); +static void summitfb_copyrows(void *, int, int, int); +static void summitfb_eraserows(void *, int, int, long); + +static void summitfb_move_cursor(struct summitfb_softc *, int, int); +static int summitfb_do_cursor(struct summitfb_softc *, struct wsdisplay_cursor *); + +static void summitfb_set_video(struct summitfb_softc *, int); + +struct wsdisplay_accessops summitfb_accessops = { + summitfb_ioctl, + summitfb_mmap, + NULL, /* alloc_screen */ + NULL, /* free_screen */ + NULL, /* show_screen */ + NULL, /* load_font */ + NULL, /* pollc */ + NULL /* scroll */ +}; + +static inline void summitfb_wait_fifo(struct summitfb_softc *, uint32_t); + +/* + * register values, found by disassembling the ROM + * some found by Sven Schnelle + * ( see https://patchwork.kernel.org/project/linux-parisc/patch/20211031204952.25678-2-sv...@stackframe.org/ ) + * some by me + */ + +#define VISFX_STATUS 0x641400 // zero when idle +#define VISFX_VRAM_WRITE_MODE 0xa00808 +#define VISFX_PIXEL_MASK 0xa0082c +#define VISFX_FG_COLOUR 0xa0083c +#define VISFX_BG_COLOUR 0xa00844 +#define VISFX_PLANE_MASK 0xa0084c + +#define VISFX_WRITE_MODE_PLAIN 0x02000000 +#define VISFX_WRITE_MODE_EXPAND 0x050004c0 +#define VISFX_WRITE_MODE_FILL 0x050008c0 + +#define VISFX_START 0xb3c000 +#define VISFX_SIZE 0xb3c808 + +#define VISFX_COLOR_MASK 0x800018 +#define VISFX_COLOR_INDEX 0x800020 +#define VISFX_COLOR_VALUE 0x800024 + +int +summitfb_match(device_t parent, cfdata_t cf, void *aux) +{ + struct pci_attach_args *paa = aux; + + if (PCI_VENDOR(paa->pa_id) != PCI_VENDOR_HP) + return 0; + + if (PCI_PRODUCT(paa->pa_id) == PCI_PRODUCT_HP_VISUALIZE_FX4) + return 10; /* beat out sti at pci */ + + return 0; +} + +static inline uint32_t +summitfb_read4(struct summitfb_softc *sc, uint32_t offset) +{ + struct sti_rom *rom = sc->sc_base.sc_rom; + bus_space_tag_t memt = rom->memt; + bus_space_handle_t memh = rom->regh[2]; + return bus_space_read_stream_4(memt, memh, offset - 0x400000); +} + +static inline void +summitfb_write4(struct summitfb_softc *sc, uint32_t offset, uint32_t val) +{ + struct sti_rom *rom = sc->sc_base.sc_rom; + bus_space_tag_t memt = rom->memt; + bus_space_handle_t memh = rom->regh[2]; + bus_space_write_stream_4(memt, memh, offset - 0x400000, val); +} + +static inline uint8_t +summitfb_read1(struct summitfb_softc *sc, uint32_t offset) +{ + struct sti_rom *rom = sc->sc_base.sc_rom; + bus_space_tag_t memt = rom->memt; + bus_space_handle_t memh = rom->regh[2]; + return bus_space_read_1(memt, memh, offset); +} + +static inline void +summitfb_write1(struct summitfb_softc *sc, uint32_t offset, uint8_t val) +{ + struct sti_rom *rom = sc->sc_base.sc_rom; + bus_space_tag_t memt = rom->memt; + bus_space_handle_t memh = rom->regh[2]; + bus_space_write_1(memt, memh, offset, val); +} + +void +summitfb_attach(device_t parent, device_t self, void *aux) +{ + struct summitfb_softc *sc = device_private(self); + struct pci_attach_args *paa = aux; + struct sti_rom *rom; + struct rasops_info *ri; + struct wsemuldisplaydev_attach_args aa; + unsigned long defattr = 0; + int ret, is_console = 0; + + sc->sc_dev = self; + + sc->sc_pc = paa->pa_pc; + sc->sc_tag = paa->pa_tag; + sc->sc_base.sc_dev = self; + sc->sc_base.sc_enable_rom = summitfb_enable_rom; + sc->sc_base.sc_disable_rom = summitfb_disable_rom; + + /* we can *not* be interrupted when doing colour map accesses */ + mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH); + + aprint_normal("\n"); + + if (summitfb_check_rom(sc, paa) != 0) + return; + + ret = sti_pci_is_console(paa, sc->sc_base. bases); + if (ret != 0) { + sc->sc_base.sc_flags |= STI_CONSOLE; + is_console = 1; + } + rom = (struct sti_rom *)kmem_zalloc(sizeof(*rom), KM_SLEEP); + rom->rom_softc = &sc->sc_base; + ret = sti_rom_setup(rom, paa->pa_iot, paa->pa_memt, sc->sc_romh, + sc->sc_base.bases, STI_CODEBASE_MAIN); + if (ret != 0) { + kmem_free(rom, sizeof(*rom)); + return; + } + + sc->sc_base.sc_rom = rom; + + sc->sc_scr.scr_rom = sc->sc_base.sc_rom; + ret = sti_screen_setup(&sc->sc_scr, STI_FBMODE); + + sc->sc_width = sc->sc_scr.scr_cfg.scr_width; + sc->sc_height = sc->sc_scr.scr_cfg.scr_height; + + aprint_normal_dev(sc->sc_dev, "%s at %dx%d\n", sc->sc_scr.name, + sc->sc_width, sc->sc_height); + summitfb_setup(sc); + +#ifdef SUMMITFB_DEBUG + sc->sc_height -= 200; +#endif + + sc->sc_defaultscreen_descr = (struct wsscreen_descr){ + "default", + 0, 0, + NULL, + 8, 16, + WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | + WSSCREEN_RESIZE, + NULL + }; + + sc->sc_screens[0] = &sc->sc_defaultscreen_descr; + sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; + sc->sc_mode = WSDISPLAYIO_MODE_EMUL; + sc->sc_locked = 0; + + vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, + &summitfb_accessops); + sc->vd.init_screen = summitfb_init_screen; + sc->vd.show_screen_cookie = &sc->sc_gc; + sc->vd.show_screen_cb = glyphcache_adapt; + + ri = &sc->sc_console_screen.scr_ri; + + sc->sc_gc.gc_bitblt = summitfb_bitblt; + sc->sc_gc.gc_blitcookie = sc; + sc->sc_gc.gc_rop = RopSrc; + + vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); + sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; + + sc->sc_defaultscreen_descr.textops = &ri->ri_ops; + sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; + sc->sc_defaultscreen_descr.nrows = ri->ri_rows; + sc->sc_defaultscreen_descr.ncols = ri->ri_cols; + + glyphcache_init(&sc->sc_gc, sc->sc_height + 5, + sc->sc_scr.fbheight - sc->sc_height - 5, + sc->sc_scr.fbwidth, + ri->ri_font->fontwidth, + ri->ri_font->fontheight, + defattr); + + summitfb_restore_palette(sc); + summitfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, + ri->ri_devcmap[(defattr >> 16) & 0xff]); + summitfb_setup_fb(sc); + + if (is_console) { + wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, + defattr); + + vcons_replay_msgbuf(&sc->sc_console_screen); + } + + /* no suspend/resume support yet */ + if (!pmf_device_register(sc->sc_dev, NULL, NULL)) + aprint_error_dev(sc->sc_dev, + "couldn't establish power handler\n"); + + aa.console = is_console; + aa.scrdata = &sc->sc_screenlist; + aa.accessops = &summitfb_accessops; + aa.accesscookie = &sc->vd; + + config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); + + printf("pmask %08x\n", summitfb_read4(sc, 0xa0084c)); + printf("vmask %08x\n", summitfb_read4(sc, 0xa0082c)); + printf("status %08x\n", summitfb_read4(sc, 0x249000)); + printf("stat %08x\n", summitfb_read4(sc, 0x641400)); + printf("size %08x\n", summitfb_read4(sc, 0xac1054)); + printf("mode %08x\n", summitfb_read4(sc, VISFX_VRAM_WRITE_MODE)); + printf("colour %08x\n", summitfb_read4(sc, 0xa00844)); + printf("cursor %08x\n", summitfb_read4(sc, 0x400000)); + printf("cindex %08x\n", summitfb_read4(sc, 0x800020)); +} + +/* + * Grovel the STI ROM image. + */ +int +summitfb_check_rom(struct summitfb_softc *spc, struct pci_attach_args *pa) +{ + struct sti_softc *sc = &spc->sc_base; + pcireg_t address, mask; + bus_space_handle_t romh; + bus_size_t romsize, subsize, stiromsize; + bus_addr_t selected, offs, suboffs; + uint32_t tmp; + int i; + int rc; + + /* sort of inline sti_pci_enable_rom(sc) */ + address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); + pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, + ~PCI_MAPREG_ROM_ENABLE); + mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); + address |= PCI_MAPREG_ROM_ENABLE; + pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, address); + sc->sc_flags |= STI_ROM_ENABLED; + /* + * Map the complete ROM for now. + */ + + romsize = PCI_ROM_SIZE(mask); + DPRINTF(("%s: mapping rom @ %lx for %lx\n", __func__, + (long)PCI_MAPREG_ROM_ADDR(address), (long)romsize)); + + rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address), romsize, + 0, &romh); + if (rc != 0) { + aprint_error_dev(sc->sc_dev, "can't map PCI ROM (%d)\n", rc); + goto fail2; + } + + summitfb_disable_rom_internal(spc); + /* + * Iterate over the ROM images, pick the best candidate. + */ + + selected = (bus_addr_t)-1; + for (offs = 0; offs < romsize; offs += subsize) { + summitfb_enable_rom_internal(spc); + /* + * Check for a valid ROM header. + */ + tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0); + tmp = le32toh(tmp); + if (tmp != 0x55aa0000) { + summitfb_disable_rom_internal(spc); + if (offs == 0) { + aprint_error_dev(sc->sc_dev, + "invalid PCI ROM header signature (%08x)\n", + tmp); + rc = EINVAL; + } + break; + } + + /* + * Check ROM type. + */ + tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4); + tmp = le32toh(tmp); + if (tmp != 0x00000001) { /* 1 == STI ROM */ + summitfb_disable_rom_internal(spc); + if (offs == 0) { + aprint_error_dev(sc->sc_dev, + "invalid PCI ROM type (%08x)\n", tmp); + rc = EINVAL; + } + break; + } + + subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, + offs + 0x0c); + subsize <<= 9; + +#ifdef SUMMITFB_DEBUG + summitfb_disable_rom_internal(spc); + DPRINTF(("ROM offset %08x size %08x type %08x", + (u_int)offs, (u_int)subsize, tmp)); + summitfb_enable_rom_internal(spc); +#endif + + /* + * Check for a valid ROM data structure. + * We do not need it except to know what architecture the ROM + * code is for. + */ + + suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh, + offs + 0x18); + tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0); + tmp = le32toh(tmp); + if (tmp != 0x50434952) { /* PCIR */ + summitfb_disable_rom_internal(spc); + if (offs == 0) { + aprint_error_dev(sc->sc_dev, "invalid PCI data" + " signature (%08x)\n", tmp); + rc = EINVAL; + } else { + DPRINTF((" invalid PCI data signature %08x\n", + tmp)); + continue; + } + } + + tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14); + summitfb_disable_rom_internal(spc); + DPRINTF((" code %02x", tmp)); + + switch (tmp) { +#ifdef __hppa__ + case 0x10: + if (selected == (bus_addr_t)-1) + selected = offs; + break; +#endif +#ifdef __i386__ + case 0x00: + if (selected == (bus_addr_t)-1) + selected = offs; + break; +#endif + default: + DPRINTF((" (wrong architecture)")); + break; + } + DPRINTF(("%s\n", selected == offs ? " -> SELECTED" : "")); + } + + if (selected == (bus_addr_t)-1) { + if (rc == 0) { + aprint_error_dev(sc->sc_dev, "found no ROM with " + "correct microcode architecture\n"); + rc = ENOEXEC; + } + goto fail; + } + + /* + * Read the STI region BAR assignments. + */ + + summitfb_enable_rom_internal(spc); + offs = selected + + (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e); + for (i = 0; i < STI_REGION_MAX; i++) { + rc = summitfb_readbar(sc, pa, i, + bus_space_read_1(pa->pa_memt, romh, offs + i)); + if (rc != 0) + goto fail; + } + + /* + * Find out where the STI ROM itself lies, and its size. + */ + + offs = selected + + (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08); + stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, + offs + 0x18); + stiromsize = le32toh(stiromsize); + summitfb_disable_rom_internal(spc); + + /* + * Replace our mapping with a smaller mapping of only the area + * we are interested in. + */ + + DPRINTF(("remapping rom @ %lx for %lx\n", + (long)(PCI_MAPREG_ROM_ADDR(address) + offs), (long)stiromsize)); + bus_space_unmap(pa->pa_memt, romh, romsize); + rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address) + offs, + stiromsize, 0, &spc->sc_romh); + if (rc != 0) { + aprint_error_dev(sc->sc_dev, "can't map STI ROM (%d)\n", + rc); + goto fail2; + } + summitfb_disable_rom_internal(spc); + sc->sc_flags &= ~STI_ROM_ENABLED; + + return 0; + +fail: + bus_space_unmap(pa->pa_memt, romh, romsize); +fail2: + summitfb_disable_rom_internal(spc); + + return rc; +} + +/* + * Decode a BAR register. + */ +int +summitfb_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region, + int bar) +{ + bus_addr_t addr; + bus_size_t size; + uint32_t cf; + int rc; + + if (bar == 0) { + sc->bases[region] = 0; + return (0); + } + +#ifdef DIAGNOSTIC + if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) { + summitfb_disable_rom(sc); + printf("%s: unexpected bar %02x for region %d\n", + device_xname(sc->sc_dev), bar, region); + summitfb_enable_rom(sc); + } +#endif + + cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); + + rc = pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, PCI_MAPREG_TYPE(cf), + &addr, &size, NULL); + + if (rc != 0) { + summitfb_disable_rom(sc); + aprint_error_dev(sc->sc_dev, "invalid bar %02x for region %d\n", + bar, region); + summitfb_enable_rom(sc); + return (rc); + } + + sc->bases[region] = addr; + return (0); +} + +/* + * Enable PCI ROM. + */ +void +summitfb_enable_rom_internal(struct summitfb_softc *spc) +{ + pcireg_t address; + + KASSERT(spc != NULL); + + address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); + address |= PCI_MAPREG_ROM_ENABLE; + pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); +} + +void +summitfb_enable_rom(struct sti_softc *sc) +{ + struct summitfb_softc *spc = device_private(sc->sc_dev); + + if (!ISSET(sc->sc_flags, STI_ROM_ENABLED)) { + summitfb_enable_rom_internal(spc); + } + SET(sc->sc_flags, STI_ROM_ENABLED); +} + +/* + * Disable PCI ROM. + */ +void +summitfb_disable_rom_internal(struct summitfb_softc *spc) +{ + pcireg_t address; + + KASSERT(spc != NULL); + + address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); + address &= ~PCI_MAPREG_ROM_ENABLE; + pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); +} + +void +summitfb_disable_rom(struct sti_softc *sc) +{ + struct summitfb_softc *spc = device_private(sc->sc_dev); + + if (ISSET(sc->sc_flags, STI_ROM_ENABLED)) { + summitfb_disable_rom_internal(spc); + } + CLR(sc->sc_flags, STI_ROM_ENABLED); +} + +static inline void +summitfb_wait(struct summitfb_softc *sc) +{ + + do {} while (summitfb_read4(sc, VISFX_STATUS) != 0); +} + +static inline void +summitfb_setup_fb(struct summitfb_softc *sc) +{ + sc->sc_hwmode = HW_FB; + summitfb_wait(sc); + summitfb_write4(sc, VISFX_VRAM_WRITE_MODE, VISFX_WRITE_MODE_PLAIN); +} + +void +summitfb_setup(struct summitfb_softc *sc) +{ + + sc->sc_hwmode = HW_FB; + sc->sc_hot_x = 0; + sc->sc_hot_y = 0; + sc->sc_enabled = 0; + sc->sc_video_on = 1; + + /* + * STI hands us the frame buffer in 32bit access mode, + * one of these puts us into 8bit FB access mode + */ +#if 1 + summitfb_write4(sc, 0xb08044, 0x1b); + summitfb_write4(sc, 0xb08048, 0x1b); + summitfb_write4(sc, 0x920860, 0xe4); + summitfb_write4(sc, 0xa00818, 0); + summitfb_write4(sc, 0xa00404, 0); + summitfb_write4(sc, 0x921110, 0); + summitfb_write4(sc, 0x9211d8, 0); + summitfb_write4(sc, 0xa0086c, 0); + summitfb_write4(sc, 0x921114, 0); + summitfb_write4(sc, 0xac1050, 0); + summitfb_write4(sc, 0xa00858, 0xb0); +#endif + + summitfb_write4(sc, VISFX_PIXEL_MASK, 0xffffffff); + summitfb_write4(sc, VISFX_PLANE_MASK, 0xffffffff); + + summitfb_setup_fb(sc); +} + +static int +summitfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, + struct lwp *l) +{ + struct vcons_data *vd = v; + struct summitfb_softc *sc = vd->cookie; + struct wsdisplay_fbinfo *wdf; + struct vcons_screen *ms = vd->active; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_STI; + return 0; + + case GCID: + *(u_int *)data = STI_DD_EG; + return 0; + + /* PCI config read/write passthrough. */ + case PCI_IOC_CFGREAD: + case PCI_IOC_CFGWRITE: + return pci_devioctl(sc->sc_pc, sc->sc_tag, + cmd, data, flag, l); + + case WSDISPLAYIO_GET_BUSID: + return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, + sc->sc_tag, data); + + case WSDISPLAYIO_GINFO: + if (ms == NULL) + return ENODEV; + wdf = (void *)data; + wdf->height = ms->scr_ri.ri_height; + wdf->width = ms->scr_ri.ri_width; + wdf->depth = ms->scr_ri.ri_depth; + wdf->cmsize = 256; + return 0; + + case WSDISPLAYIO_GETCMAP: + return summitfb_getcmap(sc, + (struct wsdisplay_cmap *)data); + + case WSDISPLAYIO_PUTCMAP: + return summitfb_putcmap(sc, + (struct wsdisplay_cmap *)data); + + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = 2048; + return 0; + + case WSDISPLAYIO_SMODE: { + int new_mode = *(int*)data; + if (new_mode != sc->sc_mode) { + sc->sc_mode = new_mode; + if(new_mode == WSDISPLAYIO_MODE_EMUL) { + summitfb_setup(sc); + summitfb_restore_palette(sc); + glyphcache_wipe(&sc->sc_gc); + summitfb_rectfill(sc, 0, 0, sc->sc_width, + sc->sc_height, ms->scr_ri.ri_devcmap[ + (ms->scr_defattr >> 16) & 0xff]); + vcons_redraw_screen(ms); + summitfb_set_video(sc, 1); + } + } + } + return 0; + + case WSDISPLAYIO_GET_FBINFO: + { + struct wsdisplayio_fbinfo *fbi = data; + int ret; + + ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); + fbi->fbi_fbsize = sc->sc_scr.fbheight * 2048; + return ret; + } + + case WSDISPLAYIO_GCURPOS: + { + struct wsdisplay_curpos *cp = (void *)data; + + cp->x = sc->sc_cursor_x; + cp->y = sc->sc_cursor_y; + } + return 0; + + case WSDISPLAYIO_SCURPOS: + { + struct wsdisplay_curpos *cp = (void *)data; + + summitfb_move_cursor(sc, cp->x, cp->y); + } + return 0; + + case WSDISPLAYIO_GCURMAX: + { + struct wsdisplay_curpos *cp = (void *)data; + + cp->x = 64; + cp->y = 64; + } + return 0; + + case WSDISPLAYIO_SCURSOR: + { + struct wsdisplay_cursor *cursor = (void *)data; + + return summitfb_do_cursor(sc, cursor); + } + + case WSDISPLAYIO_SVIDEO: + summitfb_set_video(sc, *(int *)data); + return 0; + case WSDISPLAYIO_GVIDEO: + *(u_int *)data = sc->sc_video_on ? + WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; + return 0; + } + return EPASSTHROUGH; +} + +static paddr_t +summitfb_mmap(void *v, void *vs, off_t offset, int prot) +{ + struct vcons_data *vd = v; + struct summitfb_softc *sc = vd->cookie; + struct sti_rom *rom = sc->sc_base.sc_rom; + paddr_t pa = -1; + + if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) + return -1; + + if (offset >= 0 && offset < sc->sc_scr.fblen) { + /* framebuffer */ + pa = bus_space_mmap(rom->memt, sc->sc_scr.fbaddr, offset, + prot, BUS_SPACE_MAP_LINEAR); + } else if (offset >= 0x80000000 && offset < 0x80400000) { + /* blitter registers etc. */ + pa = bus_space_mmap(rom->memt, rom->regh[2], + offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR); + } + + return pa; +} + +static void +summitfb_init_screen(void *cookie, struct vcons_screen *scr, + int existing, long *defattr) +{ + struct summitfb_softc *sc = cookie; + struct rasops_info *ri = &scr->scr_ri; + + ri->ri_depth = 8; + ri->ri_width = sc->sc_width; + ri->ri_height = sc->sc_height; + ri->ri_stride = 2048; + ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB /*| + RI_ENABLE_ALPHA | RI_PREFER_ALPHA*/; + + ri->ri_bits = (void *)sc->sc_scr.fbaddr; + rasops_init(ri, 0, 0); + ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | + WSSCREEN_RESIZE; + scr->scr_flags |= VCONS_LOADFONT | VCONS_DONT_READ; + + rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, + sc->sc_width / ri->ri_font->fontwidth); + + ri->ri_hw = scr; +if (0) { + sc->sc_putchar = ri->ri_ops.putchar; + ri->ri_ops.copyrows = summitfb_copyrows; + ri->ri_ops.copycols = summitfb_copycols; + ri->ri_ops.eraserows = summitfb_eraserows; + ri->ri_ops.erasecols = summitfb_erasecols; + ri->ri_ops.cursor = summitfb_cursor; + if (FONT_IS_ALPHA(ri->ri_font)) { + ri->ri_ops.putchar = summitfb_putchar_aa; + } else + ri->ri_ops.putchar = summitfb_putchar; +} +} + +static int +summitfb_putcmap(struct summitfb_softc *sc, struct wsdisplay_cmap *cm) +{ + u_char *r, *g, *b; + u_int index = cm->index; + u_int count = cm->count; + int i, error; + u_char rbuf[256], gbuf[256], bbuf[256]; + + if (cm->index >= 256 || cm->count > 256 || + (cm->index + cm->count) > 256) + return EINVAL; + error = copyin(cm->red, &rbuf[index], count); + if (error) + return error; + error = copyin(cm->green, &gbuf[index], count); + if (error) + return error; + error = copyin(cm->blue, &bbuf[index], count); + if (error) + return error; + + memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); + memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); + memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); + + r = &sc->sc_cmap_red[index]; + g = &sc->sc_cmap_green[index]; + b = &sc->sc_cmap_blue[index]; + + for (i = 0; i < count; i++) { + summitfb_putpalreg(sc, index, *r, *g, *b); + index++; + r++, g++, b++; + } + return 0; +} + +static int +summitfb_getcmap(struct summitfb_softc *sc, struct wsdisplay_cmap *cm) +{ + u_int index = cm->index; + u_int count = cm->count; + int error; + + if (index >= 255 || count > 256 || index + count > 256) + return EINVAL; + + error = copyout(&sc->sc_cmap_red[index], cm->red, count); + if (error) + return error; + error = copyout(&sc->sc_cmap_green[index], cm->green, count); + if (error) + return error; + error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); + if (error) + return error; + + return 0; +} + +static void +summitfb_restore_palette(struct summitfb_softc *sc) +{ + uint8_t cmap[768]; + int i, j; + + j = 0; + rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap)); + for (i = 0; i < 256; i++) { + sc->sc_cmap_red[i] = cmap[j]; + sc->sc_cmap_green[i] = cmap[j + 1]; + sc->sc_cmap_blue[i] = cmap[j + 2]; + summitfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); + j += 3; + } +} + +static int +summitfb_putpalreg(struct summitfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, + uint8_t b) +{ + mutex_enter(&sc->sc_hwlock); + summitfb_write4(sc, VISFX_COLOR_INDEX, 0xc0005100 + idx); + summitfb_write4(sc, VISFX_COLOR_VALUE, (r << 16) | ( g << 8) | b); + summitfb_write4(sc, VISFX_COLOR_MASK, 0xff); + summitfb_write4(sc, 0x80004c, 0xc); + summitfb_write4(sc, 0x800000, 0); + mutex_exit(&sc->sc_hwlock); + return 0; +} + +static inline void +summitfb_wait_fifo(struct summitfb_softc *sc, uint32_t slots) +{ +#if 0 + uint32_t reg; + do { + reg = summitfb_read4(sc, NGLE_REG_34); + } while (reg < slots); +#endif +} + +static void +summitfb_rectfill(struct summitfb_softc *sc, int x, int y, int wi, int he, + uint32_t bg) +{ + summitfb_wait(sc); + summitfb_write4(sc, VISFX_VRAM_WRITE_MODE, VISFX_WRITE_MODE_FILL); + summitfb_write4(sc, VISFX_FG_COLOUR, bg); + summitfb_write4(sc, VISFX_BG_COLOUR, bg); + summitfb_write4(sc, VISFX_START, (x << 16) | y); + summitfb_write4(sc, VISFX_SIZE, (wi << 16) | he); +} + +static void +summitfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, + int he, int rop) +{ +#if 0 + struct summitfb_softc *sc = cookie; +#endif +} + +static void +summitfb_nuke_cursor(struct rasops_info *ri) +{ + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int wi, he, x, y; + + if (ri->ri_flg & RI_CURSOR) { + wi = ri->ri_font->fontwidth; + he = ri->ri_font->fontheight; + x = ri->ri_ccol * wi + ri->ri_xorigin; + y = ri->ri_crow * he + ri->ri_yorigin; + summitfb_bitblt(sc, x, y, x, y, wi, he, RopInv); + ri->ri_flg &= ~RI_CURSOR; + } +} + +static void +summitfb_cursor(void *cookie, int on, int row, int col) +{ + struct rasops_info *ri = cookie; + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int x, y, wi, he; + + wi = ri->ri_font->fontwidth; + he = ri->ri_font->fontheight; + + if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { + if (on) { + if (ri->ri_flg & RI_CURSOR) { + summitfb_nuke_cursor(ri); + } + x = col * wi + ri->ri_xorigin; + y = row * he + ri->ri_yorigin; + summitfb_bitblt(sc, x, y, x, y, wi, he, RopInv); + ri->ri_flg |= RI_CURSOR; + } + ri->ri_crow = row; + ri->ri_ccol = col; + } else + { + ri->ri_crow = row; + ri->ri_ccol = col; + ri->ri_flg &= ~RI_CURSOR; + } + +} + +static void +summitfb_putchar(void *cookie, int row, int col, u_int c, long attr) +{ +#if 0 + struct rasops_info *ri = cookie; + struct wsdisplay_font *font = PICK_FONT(ri, c); + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + //void *data; + int x, y, wi, he, rv = GC_NOPE; + uint32_t bg, fg, mask; + + if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) + return; + + if (!CHAR_IN_FONT(c, font)) + return; + + if (row == ri->ri_crow && col == ri->ri_ccol) { + ri->ri_flg &= ~RI_CURSOR; + } + + wi = font->fontwidth; + he = font->fontheight; + + x = ri->ri_xorigin + col * wi; + y = ri->ri_yorigin + row * he; + + bg = ri->ri_devcmap[(attr >> 16) & 0xf]; + + /* if we're drawing a space we're done here */ + if (c == 0x20) { + summitfb_rectfill(sc, x, y, wi, he, bg); + return; + } + + fg = ri->ri_devcmap[(attr >> 24) & 0x0f]; + + rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); + if (rv == GC_OK) + return; + + /* clear the character cell */ + summitfb_rectfill(sc, x, y, wi, he, bg); + + //data = WSFONT_GLYPH(c, font); +/* ... */ + if (rv == GC_ADD) + glyphcache_add(&sc->sc_gc, c, x, y); +#endif +} + +static void +summitfb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) +{ + struct rasops_info *ri = cookie; + struct wsdisplay_font *font = PICK_FONT(ri, c); + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int x, y, wi, he, rv = GC_NOPE; + uint32_t bg; + + if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) + return; + + if (!CHAR_IN_FONT(c, font)) + return; + + if (row == ri->ri_crow && col == ri->ri_ccol) { + ri->ri_flg &= ~RI_CURSOR; + } + + wi = font->fontwidth; + he = font->fontheight; + + x = ri->ri_xorigin + col * wi; + y = ri->ri_yorigin + row * he; + + bg = ri->ri_devcmap[(attr >> 16) & 0xf]; + + if (c == 0x20) { + summitfb_rectfill(sc, x, y, wi, he, bg); + return; + } + + rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); + if (rv == GC_OK) + return; + + if (sc->sc_hwmode != HW_FB) summitfb_setup_fb(sc); + sc->sc_putchar(cookie, row, col, c, attr); + + if (rv == GC_ADD) + glyphcache_add(&sc->sc_gc, c, x, y); +} + +static void +summitfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) +{ + struct rasops_info *ri = cookie; + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int32_t xs, xd, y, width, height; + + if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { + if (ri->ri_crow == row && + (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && + (ri->ri_flg & RI_CURSOR)) { + summitfb_nuke_cursor(ri); + } + + xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; + xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; + y = ri->ri_yorigin + ri->ri_font->fontheight * row; + width = ri->ri_font->fontwidth * ncols; + height = ri->ri_font->fontheight; + summitfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc); + if (ri->ri_crow == row && + (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) + ri->ri_flg &= ~RI_CURSOR; + } +} + +static void +summitfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) +{ + struct rasops_info *ri = cookie; + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int32_t x, y, width, height, fg, bg, ul; + + if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { + x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; + y = ri->ri_yorigin + ri->ri_font->fontheight * row; + width = ri->ri_font->fontwidth * ncols; + height = ri->ri_font->fontheight; + rasops_unpack_attr(fillattr, &fg, &bg, &ul); + + summitfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); + if (ri->ri_crow == row && + (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols))) + ri->ri_flg &= ~RI_CURSOR; + } +} + +static void +summitfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) +{ + struct rasops_info *ri = cookie; + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int32_t x, ys, yd, width, height; + + if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { + if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) && + (ri->ri_flg & RI_CURSOR)) { + summitfb_nuke_cursor(ri); + } + x = ri->ri_xorigin; + ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; + yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; + width = ri->ri_emuwidth; + height = ri->ri_font->fontheight * nrows; + summitfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc); + if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) + ri->ri_flg &= ~RI_CURSOR; + } +} + +static void +summitfb_eraserows(void *cookie, int row, int nrows, long fillattr) +{ + struct rasops_info *ri = cookie; + struct vcons_screen *scr = ri->ri_hw; + struct summitfb_softc *sc = scr->scr_cookie; + int32_t x, y, width, height, fg, bg, ul; + + if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { + x = ri->ri_xorigin; + y = ri->ri_yorigin + ri->ri_font->fontheight * row; + width = ri->ri_emuwidth; + height = ri->ri_font->fontheight * nrows; + rasops_unpack_attr(fillattr, &fg, &bg, &ul); + + summitfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); + + if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) + ri->ri_flg &= ~RI_CURSOR; + } +} + +/* + * cursor sprite handling + * like most hw info, xf86 3.3 -> nglehdw.h was used as documentation + * problem is, the PCI EG doesn't quite behave like an S9000_ID_ARTIST + * the cursor position register bahaves like the one on HCRX while using + * the same address as Artist, incuding the enable bit and weird handling + * of negative coordinates. The rest of it, colour map, sprite image etc., + * behave like Artist. + */ + +static void +summitfb_move_cursor(struct summitfb_softc *sc, int x, int y) +{ +#if 0 + uint32_t pos; + + sc->sc_cursor_x = x; + x -= sc->sc_hot_x; + sc->sc_cursor_y = y; + y -= sc->sc_hot_y; + + if (x < 0) x = 0x1000 - x; + if (y < 0) y = 0x1000 - y; + pos = (x << 16) | y; + if (sc->sc_enabled) pos |= 0x80000000; + gftfb_wait(sc); + gftfb_write4(sc, NGLE_REG_17, pos); + gftfb_write4(sc, NGLE_REG_18, 0x80); +#endif +} + +static int +summitfb_do_cursor(struct summitfb_softc *sc, struct wsdisplay_cursor *cur) +{ + if (cur->which & WSDISPLAY_CURSOR_DOCUR) { + + sc->sc_enabled = cur->enable; + cur->which |= WSDISPLAY_CURSOR_DOPOS; + } + if (cur->which & WSDISPLAY_CURSOR_DOHOT) { + + sc->sc_hot_x = cur->hot.x; + sc->sc_hot_y = cur->hot.y; + cur->which |= WSDISPLAY_CURSOR_DOPOS; + } + if (cur->which & WSDISPLAY_CURSOR_DOPOS) { + + summitfb_move_cursor(sc, cur->pos.x, cur->pos.y); + } + if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { + //uint32_t rgb; + uint8_t r[2], g[2], b[2]; + + copyin(cur->cmap.blue, b, 2); + copyin(cur->cmap.green, g, 2); + copyin(cur->cmap.red, r, 2); + mutex_enter(&sc->sc_hwlock); +/* ... */ + mutex_exit(&sc->sc_hwlock); + + } + if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { +#if 0 + uint32_t buffer[128], latch, tmp; + int i; + + copyin(cur->mask, buffer, 512); + gftfb_wait(sc); + gftfb_write4(sc, NGLE_REG_14, 0x300); + gftfb_write4(sc, NGLE_REG_13, 0xffffffff); + gftfb_write4(sc, NGLE_REG_11, + BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcmask, 0)); + gftfb_write4(sc, NGLE_REG_3, 0); + for (i = 0; i < 128; i += 2) { + latch = 0; + tmp = buffer[i] & 0x80808080; + latch |= tmp >> 7; + tmp = buffer[i] & 0x40404040; + latch |= tmp >> 5; + tmp = buffer[i] & 0x20202020; + latch |= tmp >> 3; + tmp = buffer[i] & 0x10101010; + latch |= tmp >> 1; + tmp = buffer[i] & 0x08080808; + latch |= tmp << 1; + tmp = buffer[i] & 0x04040404; + latch |= tmp << 3; + tmp = buffer[i] & 0x02020202; + latch |= tmp << 5; + tmp = buffer[i] & 0x01010101; + latch |= tmp << 7; + gftfb_write4(sc, NGLE_REG_4, latch); + latch = 0; + tmp = buffer[i + 1] & 0x80808080; + latch |= tmp >> 7; + tmp = buffer[i + 1] & 0x40404040; + latch |= tmp >> 5; + tmp = buffer[i + 1] & 0x20202020; + latch |= tmp >> 3; + tmp = buffer[i + 1] & 0x10101010; + latch |= tmp >> 1; + tmp = buffer[i + 1] & 0x08080808; + latch |= tmp << 1; + tmp = buffer[i + 1] & 0x04040404; + latch |= tmp << 3; + tmp = buffer[i + 1] & 0x02020202; + latch |= tmp << 5; + tmp = buffer[i + 1] & 0x01010101; + latch |= tmp << 7; + gftfb_write4(sc, NGLE_REG_5, latch); + } + + copyin(cur->image, buffer, 512); + gftfb_wait(sc); + gftfb_write4(sc, NGLE_REG_14, 0x300); + gftfb_write4(sc, NGLE_REG_13, 0xffffffff); + gftfb_write4(sc, NGLE_REG_11, + BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcursor, 0)); + gftfb_write4(sc, NGLE_REG_3, 0); + for (i = 0; i < 128; i += 2) { + latch = 0; + tmp = buffer[i] & 0x80808080; + latch |= tmp >> 7; + tmp = buffer[i] & 0x40404040; + latch |= tmp >> 5; + tmp = buffer[i] & 0x20202020; + latch |= tmp >> 3; + tmp = buffer[i] & 0x10101010; + latch |= tmp >> 1; + tmp = buffer[i] & 0x08080808; + latch |= tmp << 1; + tmp = buffer[i] & 0x04040404; + latch |= tmp << 3; + tmp = buffer[i] & 0x02020202; + latch |= tmp << 5; + tmp = buffer[i] & 0x01010101; + latch |= tmp << 7; + gftfb_write4(sc, NGLE_REG_4, latch); + latch = 0; + tmp = buffer[i + 1] & 0x80808080; + latch |= tmp >> 7; + tmp = buffer[i + 1] & 0x40404040; + latch |= tmp >> 5; + tmp = buffer[i + 1] & 0x20202020; + latch |= tmp >> 3; + tmp = buffer[i + 1] & 0x10101010; + latch |= tmp >> 1; + tmp = buffer[i + 1] & 0x08080808; + latch |= tmp << 1; + tmp = buffer[i + 1] & 0x04040404; + latch |= tmp << 3; + tmp = buffer[i + 1] & 0x02020202; + latch |= tmp << 5; + tmp = buffer[i + 1] & 0x01010101; + latch |= tmp << 7; + gftfb_write4(sc, NGLE_REG_5, latch); + } + gftfb_setup_fb(sc); +#endif + } + + return 0; +} + +static void +summitfb_set_video(struct summitfb_softc *sc, int on) +{ + if (sc->sc_video_on == on) + return; + + sc->sc_video_on = on; + + summitfb_wait(sc); + if (on) { + } else { + } +}