1*64ffcac2Smacallan /* $NetBSD: hyperfb.c,v 1.19 2024/11/13 08:21:16 macallan Exp $ */ 2cf4b16e0Smacallan 3cf4b16e0Smacallan /* 4cf4b16e0Smacallan * Copyright (c) 2024 Michael Lorenz 5cf4b16e0Smacallan * All rights reserved. 6cf4b16e0Smacallan * 7cf4b16e0Smacallan * Redistribution and use in source and binary forms, with or without 8cf4b16e0Smacallan * modification, are permitted provided that the following conditions 9cf4b16e0Smacallan * are met: 10cf4b16e0Smacallan * 1. Redistributions of source code must retain the above copyright 11cf4b16e0Smacallan * notice, this list of conditions and the following disclaimer. 12cf4b16e0Smacallan * 2. Redistributions in binary form must reproduce the above copyright 13cf4b16e0Smacallan * notice, this list of conditions and the following disclaimer in the 14cf4b16e0Smacallan * documentation and/or other materials provided with the distribution. 15cf4b16e0Smacallan * 16cf4b16e0Smacallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17cf4b16e0Smacallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18cf4b16e0Smacallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19cf4b16e0Smacallan * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20cf4b16e0Smacallan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21cf4b16e0Smacallan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22cf4b16e0Smacallan * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23cf4b16e0Smacallan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24cf4b16e0Smacallan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25cf4b16e0Smacallan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26cf4b16e0Smacallan * THE POSSIBILITY OF SUCH DAMAGE. 27cf4b16e0Smacallan */ 28cf4b16e0Smacallan 29cf4b16e0Smacallan /* 30cf4b16e0Smacallan * a native driver for HCRX / hyperdrive cards 315462a444Smacallan * tested on a HCRX24Z in a C360 only so far 32cf4b16e0Smacallan */ 33cf4b16e0Smacallan 34cf4b16e0Smacallan #include <sys/cdefs.h> 35*64ffcac2Smacallan __KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.19 2024/11/13 08:21:16 macallan Exp $"); 36cf4b16e0Smacallan 37cf4b16e0Smacallan #include "opt_cputype.h" 38cf4b16e0Smacallan #include "opt_hyperfb.h" 39cf4b16e0Smacallan 40cf4b16e0Smacallan #include <sys/param.h> 41cf4b16e0Smacallan #include <sys/systm.h> 42cf4b16e0Smacallan #include <sys/device.h> 43cf4b16e0Smacallan 44cf4b16e0Smacallan #include <sys/bus.h> 45cf4b16e0Smacallan #include <machine/cpu.h> 46cf4b16e0Smacallan #include <machine/iomod.h> 47cf4b16e0Smacallan #include <machine/autoconf.h> 48cf4b16e0Smacallan 49cf4b16e0Smacallan #include <dev/wscons/wsdisplayvar.h> 50cf4b16e0Smacallan #include <dev/wscons/wsconsio.h> 51cf4b16e0Smacallan #include <dev/wsfont/wsfont.h> 52cf4b16e0Smacallan #include <dev/rasops/rasops.h> 53cf4b16e0Smacallan #include <dev/wscons/wsdisplay_vconsvar.h> 54cf4b16e0Smacallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 55cf4b16e0Smacallan 56cf4b16e0Smacallan #include <dev/ic/stireg.h> 57cf4b16e0Smacallan #include <dev/ic/stivar.h> 58cf4b16e0Smacallan 59cf4b16e0Smacallan #include <hppa/dev/cpudevs.h> 60cf4b16e0Smacallan #include <hppa/hppa/machdep.h> 61cf4b16e0Smacallan 62cf4b16e0Smacallan #ifdef HYPERFB_DEBUG 63cf4b16e0Smacallan #define DPRINTF printf 64cf4b16e0Smacallan #else 65cf4b16e0Smacallan #define DPRINTF if (0) printf 66cf4b16e0Smacallan #endif 67cf4b16e0Smacallan 68cf4b16e0Smacallan #define STI_ROMSIZE (sizeof(struct sti_dd) * 4) 69cf4b16e0Smacallan 70cf4b16e0Smacallan #define HCRX_FBOFFSET 0x01000000 71cf4b16e0Smacallan #define HCRX_FBLEN 0x01000000 72cf4b16e0Smacallan #define HCRX_REGOFFSET 0x00100000 73cf4b16e0Smacallan #define HCRX_REGLEN 0x00280000 74cf4b16e0Smacallan 75cf4b16e0Smacallan #define HCRX_CONFIG_24BIT 0x100 76cf4b16e0Smacallan 77cf4b16e0Smacallan int hyperfb_match(device_t, cfdata_t, void *); 78cf4b16e0Smacallan void hyperfb_attach(device_t, device_t, void *); 79cf4b16e0Smacallan 80cf4b16e0Smacallan struct hyperfb_softc { 81cf4b16e0Smacallan device_t sc_dev; 82cf4b16e0Smacallan bus_space_tag_t sc_iot; 83cf4b16e0Smacallan bus_addr_t sc_base; 84cf4b16e0Smacallan bus_space_handle_t sc_hfb, sc_hreg; 85cf4b16e0Smacallan void *sc_fb; 86cf4b16e0Smacallan 87cf4b16e0Smacallan int sc_width, sc_height; 88cf4b16e0Smacallan int sc_locked, sc_is_console, sc_24bit; 89cf4b16e0Smacallan struct vcons_screen sc_console_screen; 90cf4b16e0Smacallan struct wsscreen_descr sc_defaultscreen_descr; 91cf4b16e0Smacallan const struct wsscreen_descr *sc_screens[1]; 92cf4b16e0Smacallan struct wsscreen_list sc_screenlist; 93cf4b16e0Smacallan struct vcons_data vd; 94cf4b16e0Smacallan int sc_mode; 95cf4b16e0Smacallan u_char sc_cmap_red[256]; 96cf4b16e0Smacallan u_char sc_cmap_green[256]; 97cf4b16e0Smacallan u_char sc_cmap_blue[256]; 98cf4b16e0Smacallan kmutex_t sc_hwlock; 99cf4b16e0Smacallan uint32_t sc_hwmode; 100cf4b16e0Smacallan #define HW_FB 0 101cf4b16e0Smacallan #define HW_FILL 1 102cf4b16e0Smacallan #define HW_BLIT 2 10343af28fdSmacallan #define HW_SFILL 3 104cf4b16e0Smacallan /* cursor stuff */ 105cf4b16e0Smacallan int sc_cursor_x, sc_cursor_y; 106cf4b16e0Smacallan int sc_hot_x, sc_hot_y, sc_enabled; 107cf4b16e0Smacallan int sc_video_on; 108cf4b16e0Smacallan glyphcache sc_gc; 109cf4b16e0Smacallan }; 110cf4b16e0Smacallan 111cf4b16e0Smacallan extern struct cfdriver hyperfb_cd; 112cf4b16e0Smacallan 113cf4b16e0Smacallan CFATTACH_DECL_NEW(hyperfb, sizeof(struct hyperfb_softc), hyperfb_match, 114cf4b16e0Smacallan hyperfb_attach, NULL, NULL); 115cf4b16e0Smacallan 116aee609b2Smacallan static inline void hyperfb_setup_fb(struct hyperfb_softc *); 117aee609b2Smacallan static inline void hyperfb_setup_fb24(struct hyperfb_softc *); 118cf4b16e0Smacallan static void hyperfb_init_screen(void *, struct vcons_screen *, 119cf4b16e0Smacallan int, long *); 120cf4b16e0Smacallan static int hyperfb_ioctl(void *, void *, u_long, void *, int, 121cf4b16e0Smacallan struct lwp *); 122cf4b16e0Smacallan static paddr_t hyperfb_mmap(void *, void *, off_t, int); 123cf4b16e0Smacallan 124f7add90dSriastradh static int hyperfb_putcmap(struct hyperfb_softc *, 125f7add90dSriastradh struct wsdisplay_cmap *); 126f7add90dSriastradh static int hyperfb_getcmap(struct hyperfb_softc *, 127f7add90dSriastradh struct wsdisplay_cmap *); 128cf4b16e0Smacallan static void hyperfb_restore_palette(struct hyperfb_softc *); 129cf4b16e0Smacallan static int hyperfb_putpalreg(struct hyperfb_softc *, uint8_t, uint8_t, 130cf4b16e0Smacallan uint8_t, uint8_t); 131cf4b16e0Smacallan void hyperfb_setup(struct hyperfb_softc *); 132cf4b16e0Smacallan static void hyperfb_set_video(struct hyperfb_softc *, int); 133cf4b16e0Smacallan 1347d0f5abeSmacallan static void hyperfb_rectfill(struct hyperfb_softc *, int, int, int, int, 1357d0f5abeSmacallan uint32_t); 1367d0f5abeSmacallan static void hyperfb_bitblt(void *, int, int, int, int, int, 1377d0f5abeSmacallan int, int); 1387d0f5abeSmacallan 1397d0f5abeSmacallan static void hyperfb_cursor(void *, int, int, int); 1407d0f5abeSmacallan static void hyperfb_putchar(void *, int, int, u_int, long); 1417d0f5abeSmacallan static void hyperfb_copycols(void *, int, int, int, int); 1427d0f5abeSmacallan static void hyperfb_erasecols(void *, int, int, int, long); 1437d0f5abeSmacallan static void hyperfb_copyrows(void *, int, int, int); 1447d0f5abeSmacallan static void hyperfb_eraserows(void *, int, int, long); 1457d0f5abeSmacallan 1467d0f5abeSmacallan static void hyperfb_move_cursor(struct hyperfb_softc *, int, int); 147f7add90dSriastradh static int hyperfb_do_cursor(struct hyperfb_softc *, 148f7add90dSriastradh struct wsdisplay_cursor *); 1497d0f5abeSmacallan 1507d0f5abeSmacallan static inline void hyperfb_wait_fifo(struct hyperfb_softc *, uint32_t); 1517d0f5abeSmacallan 152cf4b16e0Smacallan #define ngle_bt458_write(sc, r, v) \ 153cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 154cf4b16e0Smacallan 155cf4b16e0Smacallan struct wsdisplay_accessops hyperfb_accessops = { 156cf4b16e0Smacallan hyperfb_ioctl, 157cf4b16e0Smacallan hyperfb_mmap, 158cf4b16e0Smacallan NULL, /* alloc_screen */ 159cf4b16e0Smacallan NULL, /* free_screen */ 160cf4b16e0Smacallan NULL, /* show_screen */ 161cf4b16e0Smacallan NULL, /* load_font */ 162cf4b16e0Smacallan NULL, /* pollc */ 163cf4b16e0Smacallan NULL /* scroll */ 164cf4b16e0Smacallan }; 165cf4b16e0Smacallan 166cf4b16e0Smacallan static inline uint32_t 167cf4b16e0Smacallan hyperfb_read4(struct hyperfb_softc *sc, uint32_t offset) 168cf4b16e0Smacallan { 169cf4b16e0Smacallan return bus_space_read_4(sc->sc_iot, sc->sc_hreg, offset); 170cf4b16e0Smacallan } 171cf4b16e0Smacallan 172cf4b16e0Smacallan static inline uint8_t 173cf4b16e0Smacallan hyperfb_read1(struct hyperfb_softc *sc, uint32_t offset) 174cf4b16e0Smacallan { 175cf4b16e0Smacallan return bus_space_read_1(sc->sc_iot, sc->sc_hreg, offset); 176cf4b16e0Smacallan } 177cf4b16e0Smacallan 178cf4b16e0Smacallan static inline void 179cf4b16e0Smacallan hyperfb_write4(struct hyperfb_softc *sc, uint32_t offset, uint32_t val) 180cf4b16e0Smacallan { 181cf4b16e0Smacallan bus_space_write_4(sc->sc_iot, sc->sc_hreg, offset, val); 182cf4b16e0Smacallan } 183cf4b16e0Smacallan 184cf4b16e0Smacallan static inline void 185cf4b16e0Smacallan hyperfb_write1(struct hyperfb_softc *sc, uint32_t offset, uint8_t val) 186cf4b16e0Smacallan { 187cf4b16e0Smacallan bus_space_write_1(sc->sc_iot, sc->sc_hreg, offset, val); 188cf4b16e0Smacallan } 189cf4b16e0Smacallan 190cf4b16e0Smacallan static inline void 191cf4b16e0Smacallan hyperfb_wait(struct hyperfb_softc *sc) 192cf4b16e0Smacallan { 193cf4b16e0Smacallan uint8_t stat; 194cf4b16e0Smacallan 195cf4b16e0Smacallan do { 196cf4b16e0Smacallan stat = hyperfb_read1(sc, NGLE_REG_15b0); 197cf4b16e0Smacallan if (stat == 0) 198cf4b16e0Smacallan stat = hyperfb_read1(sc, NGLE_REG_15b0); 199cf4b16e0Smacallan } while (stat != 0); 200cf4b16e0Smacallan } 201cf4b16e0Smacallan 2027d0f5abeSmacallan static inline void 2037d0f5abeSmacallan hyperfb_wait_fifo(struct hyperfb_softc *sc, uint32_t slots) 2047d0f5abeSmacallan { 2057d0f5abeSmacallan uint32_t reg; 2067d0f5abeSmacallan 2077d0f5abeSmacallan do { 2087d0f5abeSmacallan reg = hyperfb_read4(sc, NGLE_REG_34); 2097d0f5abeSmacallan } while (reg < slots); 2107d0f5abeSmacallan } 2117d0f5abeSmacallan 212aee609b2Smacallan static inline void 213cf4b16e0Smacallan hyperfb_setup_fb(struct hyperfb_softc *sc) 214cf4b16e0Smacallan { 215cf4b16e0Smacallan 21643af28fdSmacallan /* 21743af28fdSmacallan * turns out the plane mask is applied to everything, including 21843af28fdSmacallan * direct framebuffer writes, so make sure we always set it 21943af28fdSmacallan */ 220cf4b16e0Smacallan hyperfb_wait(sc); 221aee609b2Smacallan if ((sc->sc_mode != WSDISPLAYIO_MODE_EMUL) && sc->sc_24bit) { 22215644928Smacallan hyperfb_write4(sc, NGLE_REG_10, 22315644928Smacallan BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 224aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 22543af28fdSmacallan } else { 22615644928Smacallan hyperfb_write4(sc, NGLE_REG_10, 22715644928Smacallan BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINovly, 0)); 22843af28fdSmacallan hyperfb_write4(sc, NGLE_REG_13, 0xff); 22943af28fdSmacallan } 230cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x83000300); 231cf4b16e0Smacallan hyperfb_wait(sc); 232cf4b16e0Smacallan hyperfb_write1(sc, NGLE_REG_16b1, 1); 233cf4b16e0Smacallan sc->sc_hwmode = HW_FB; 234cf4b16e0Smacallan } 235cf4b16e0Smacallan 236aee609b2Smacallan static inline void 237aee609b2Smacallan hyperfb_setup_fb24(struct hyperfb_softc *sc) 238aee609b2Smacallan { 239aee609b2Smacallan 240aee609b2Smacallan hyperfb_wait(sc); 24115644928Smacallan hyperfb_write4(sc, NGLE_REG_10, 24215644928Smacallan BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 243aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 244aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x83000300); 245aee609b2Smacallan //IBOvals(RopSrc,0,BitmapExtent08,0,DataDynamic,MaskDynamic,0,0) 246aee609b2Smacallan hyperfb_wait(sc); 247aee609b2Smacallan hyperfb_write1(sc, NGLE_REG_16b1, 1); 248aee609b2Smacallan sc->sc_hwmode = HW_FB; 249aee609b2Smacallan } 250aee609b2Smacallan 251cf4b16e0Smacallan int 252cf4b16e0Smacallan hyperfb_match(device_t parent, cfdata_t cf, void *aux) 253cf4b16e0Smacallan { 254cf4b16e0Smacallan struct confargs *ca = aux; 255cf4b16e0Smacallan bus_space_handle_t romh; 256cf4b16e0Smacallan paddr_t rom; 257cf4b16e0Smacallan uint32_t id = 0; 258cf4b16e0Smacallan u_char devtype; 259cf4b16e0Smacallan int rv = 0, romunmapped = 0; 260cf4b16e0Smacallan 261cf4b16e0Smacallan if (ca->ca_type.iodc_type != HPPA_TYPE_FIO) 262cf4b16e0Smacallan return 0; 263cf4b16e0Smacallan 264cf4b16e0Smacallan /* these need further checking for the graphics id */ 265cf4b16e0Smacallan if (ca->ca_type.iodc_sv_model != HPPA_FIO_GSGC && 266cf4b16e0Smacallan ca->ca_type.iodc_sv_model != HPPA_FIO_SGC) 267cf4b16e0Smacallan return 0; 268cf4b16e0Smacallan 269cf4b16e0Smacallan if (ca->ca_naddrs > 0) 270cf4b16e0Smacallan rom = ca->ca_addrs[0].addr; 271cf4b16e0Smacallan else 272cf4b16e0Smacallan rom = ca->ca_hpa; 273cf4b16e0Smacallan 274cf4b16e0Smacallan DPRINTF("%s: hpa=%x, rom=%x\n", __func__, (uint)ca->ca_hpa, 275cf4b16e0Smacallan (uint)rom); 276cf4b16e0Smacallan 277cf4b16e0Smacallan /* if it does not map, probably part of the lasi space */ 278cf4b16e0Smacallan if (bus_space_map(ca->ca_iot, rom, STI_ROMSIZE, 0, &romh)) { 279cf4b16e0Smacallan DPRINTF("%s: can't map rom space (%d)\n", __func__, rv); 280cf4b16e0Smacallan 281cf4b16e0Smacallan if ((rom & HPPA_IOBEGIN) == HPPA_IOBEGIN) { 282cf4b16e0Smacallan romh = rom; 283cf4b16e0Smacallan romunmapped++; 284cf4b16e0Smacallan } else { 285cf4b16e0Smacallan /* in this case nobody has no freaking idea */ 286cf4b16e0Smacallan return 0; 287cf4b16e0Smacallan } 288cf4b16e0Smacallan } 289cf4b16e0Smacallan 290cf4b16e0Smacallan devtype = bus_space_read_1(ca->ca_iot, romh, 3); 291cf4b16e0Smacallan DPRINTF("%s: devtype=%d\n", __func__, devtype); 292cf4b16e0Smacallan rv = 1; 293cf4b16e0Smacallan switch (devtype) { 294cf4b16e0Smacallan case STI_DEVTYPE4: 295cf4b16e0Smacallan id = bus_space_read_4(ca->ca_iot, romh, STI_DEV4_DD_GRID); 296cf4b16e0Smacallan break; 297cf4b16e0Smacallan case STI_DEVTYPE1: 298cf4b16e0Smacallan id = (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID 299cf4b16e0Smacallan + 3) << 24) | 300cf4b16e0Smacallan (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID 301cf4b16e0Smacallan + 7) << 16) | 302cf4b16e0Smacallan (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID 303cf4b16e0Smacallan + 11) << 8) | 304cf4b16e0Smacallan (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID 305cf4b16e0Smacallan + 15)); 306cf4b16e0Smacallan break; 307cf4b16e0Smacallan default: 308cf4b16e0Smacallan DPRINTF("%s: unknown type (%x)\n", __func__, devtype); 309cf4b16e0Smacallan rv = 0; 310cf4b16e0Smacallan } 311cf4b16e0Smacallan 312cf4b16e0Smacallan if (id == STI_DD_HCRX) 313cf4b16e0Smacallan rv = 100; /* beat out sti */ 314cf4b16e0Smacallan 315cf4b16e0Smacallan ca->ca_addrs[ca->ca_naddrs].addr = rom; 316cf4b16e0Smacallan ca->ca_addrs[ca->ca_naddrs].size = sti_rom_size(ca->ca_iot, romh); 317cf4b16e0Smacallan ca->ca_naddrs++; 318cf4b16e0Smacallan 319cf4b16e0Smacallan if (!romunmapped) 320cf4b16e0Smacallan bus_space_unmap(ca->ca_iot, romh, STI_ROMSIZE); 321cf4b16e0Smacallan return rv; 322cf4b16e0Smacallan } 323cf4b16e0Smacallan 324cf4b16e0Smacallan void 325cf4b16e0Smacallan hyperfb_attach(device_t parent, device_t self, void *aux) 326cf4b16e0Smacallan { 327cf4b16e0Smacallan struct hyperfb_softc *sc = device_private(self); 328cf4b16e0Smacallan struct confargs *ca = aux; 329cf4b16e0Smacallan struct rasops_info *ri; 330cf4b16e0Smacallan struct wsemuldisplaydev_attach_args aa; 331cf4b16e0Smacallan bus_space_handle_t hrom; 332cf4b16e0Smacallan hppa_hpa_t consaddr; 333cf4b16e0Smacallan long defattr; 334cf4b16e0Smacallan int pagezero_cookie; 335cf4b16e0Smacallan paddr_t rom; 336cf4b16e0Smacallan uint32_t config; 337cf4b16e0Smacallan 338cf4b16e0Smacallan pagezero_cookie = hppa_pagezero_map(); 339cf4b16e0Smacallan consaddr = (hppa_hpa_t)PAGE0->mem_cons.pz_hpa; 340cf4b16e0Smacallan hppa_pagezero_unmap(pagezero_cookie); 341cf4b16e0Smacallan 342cf4b16e0Smacallan sc->sc_dev = self; 343cf4b16e0Smacallan sc->sc_base = ca->ca_hpa; 344cf4b16e0Smacallan sc->sc_iot = ca->ca_iot; 345cf4b16e0Smacallan sc->sc_is_console =(ca->ca_hpa == consaddr); 346cf4b16e0Smacallan sc->sc_width = 1280; 347cf4b16e0Smacallan sc->sc_height = 1024; 348cf4b16e0Smacallan 349cf4b16e0Smacallan /* we can *not* be interrupted when doing colour map accesses */ 350cf4b16e0Smacallan mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH); 351cf4b16e0Smacallan 352cf4b16e0Smacallan /* we stashed rom addr/len into the last slot during probe */ 353cf4b16e0Smacallan rom = ca->ca_addrs[ca->ca_naddrs - 1].addr; 354cf4b16e0Smacallan 355cf4b16e0Smacallan if (bus_space_map(sc->sc_iot, 356cf4b16e0Smacallan sc->sc_base + HCRX_FBOFFSET, HCRX_FBLEN, 357cf4b16e0Smacallan BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, 358cf4b16e0Smacallan &sc->sc_hfb)) { 359f7add90dSriastradh aprint_error_dev(sc->sc_dev, 360f7add90dSriastradh "failed to map the framebuffer\n"); 361cf4b16e0Smacallan return; 362cf4b16e0Smacallan } 363cf4b16e0Smacallan sc->sc_fb = bus_space_vaddr(sc->sc_iot, sc->sc_hfb); 364cf4b16e0Smacallan 365cf4b16e0Smacallan if (bus_space_map(sc->sc_iot, 366cf4b16e0Smacallan sc->sc_base + HCRX_REGOFFSET, HCRX_REGLEN, 0, &sc->sc_hreg)) { 367cf4b16e0Smacallan aprint_error_dev(sc->sc_dev, "failed to map registers\n"); 368cf4b16e0Smacallan return; 369cf4b16e0Smacallan } 370cf4b16e0Smacallan 371cf4b16e0Smacallan /* 372cf4b16e0Smacallan * we really only need the first word so we can grab the config bits 373cf4b16e0Smacallan * between the bytes 374cf4b16e0Smacallan */ 375f7add90dSriastradh if (bus_space_map(sc->sc_iot, rom, 4, 0, &hrom)) { 376f7add90dSriastradh aprint_error_dev(sc->sc_dev, 377f7add90dSriastradh "failed to map ROM, assuming 8bit\n"); 378cf4b16e0Smacallan config = 0; 379cf4b16e0Smacallan } else { 380cf4b16e0Smacallan /* alright, we got the ROM. now do the idle dance. */ 381cf4b16e0Smacallan volatile uint32_t r = hyperfb_read4(sc, NGLE_REG_15); 382cf4b16e0Smacallan __USE(r); 383cf4b16e0Smacallan hyperfb_wait(sc); 384cf4b16e0Smacallan config = bus_space_read_4(sc->sc_iot, hrom, 0); 385cf4b16e0Smacallan bus_space_unmap(sc->sc_iot, hrom, 4); 386cf4b16e0Smacallan } 387cf4b16e0Smacallan sc->sc_24bit = ((config & HCRX_CONFIG_24BIT) != 0); 388cf4b16e0Smacallan 389cf4b16e0Smacallan printf(" %s\n", sc->sc_24bit ? "HCRX24" : "HCRX"); 390cf4b16e0Smacallan #ifdef HP7300LC_CPU 391cf4b16e0Smacallan /* 392cf4b16e0Smacallan * PCXL2: enable accel I/O for this space, see PCX-L2 ERS "ACCEL_IO". 393cf4b16e0Smacallan * "pcxl2_ers.{ps,pdf}", (section / chapter . rel. page / abs. page) 394cf4b16e0Smacallan * 8.7.4 / 8-12 / 92, 11.3.14 / 11-14 / 122 and 14.8 / 14-5 / 203. 395cf4b16e0Smacallan */ 396cf4b16e0Smacallan if (hppa_cpu_info->hci_cputype == hpcxl2 397cf4b16e0Smacallan && ca->ca_hpa >= PCXL2_ACCEL_IO_START 398cf4b16e0Smacallan && ca->ca_hpa <= PCXL2_ACCEL_IO_END) 399cf4b16e0Smacallan eaio_l2(PCXL2_ACCEL_IO_ADDR2MASK(ca->ca_hpa)); 400cf4b16e0Smacallan #endif /* HP7300LC_CPU */ 401cf4b16e0Smacallan 402aee609b2Smacallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 403aee609b2Smacallan sc->sc_locked = 0; 404aee609b2Smacallan 405cf4b16e0Smacallan hyperfb_setup(sc); 406cf4b16e0Smacallan hyperfb_setup_fb(sc); 407cf4b16e0Smacallan 408cf4b16e0Smacallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 409cf4b16e0Smacallan "default", 410cf4b16e0Smacallan 0, 0, 411cf4b16e0Smacallan NULL, 412cf4b16e0Smacallan 8, 16, 413cf4b16e0Smacallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 414cf4b16e0Smacallan WSSCREEN_RESIZE, 415cf4b16e0Smacallan NULL 416cf4b16e0Smacallan }; 417cf4b16e0Smacallan 418cf4b16e0Smacallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 419cf4b16e0Smacallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 420cf4b16e0Smacallan 421cf4b16e0Smacallan vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 422cf4b16e0Smacallan &hyperfb_accessops); 423cf4b16e0Smacallan sc->vd.init_screen = hyperfb_init_screen; 424cf4b16e0Smacallan sc->vd.show_screen_cookie = &sc->sc_gc; 425cf4b16e0Smacallan sc->vd.show_screen_cb = glyphcache_adapt; 426cf4b16e0Smacallan 427cf4b16e0Smacallan ri = &sc->sc_console_screen.scr_ri; 428cf4b16e0Smacallan 429cf4b16e0Smacallan //sc->sc_gc.gc_bitblt = hyperfb_bitblt; 430cf4b16e0Smacallan //sc->sc_gc.gc_blitcookie = sc; 431cf4b16e0Smacallan //sc->sc_gc.gc_rop = RopSrc; 432cf4b16e0Smacallan 433*64ffcac2Smacallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 434cf4b16e0Smacallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 435cf4b16e0Smacallan 436cf4b16e0Smacallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 437cf4b16e0Smacallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 438cf4b16e0Smacallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 439cf4b16e0Smacallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 440cf4b16e0Smacallan 441cf4b16e0Smacallan #if 0 442cf4b16e0Smacallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 443cf4b16e0Smacallan sc->sc_scr.fbheight - sc->sc_height - 5, 444cf4b16e0Smacallan sc->sc_scr.fbwidth, 445cf4b16e0Smacallan ri->ri_font->fontwidth, 446cf4b16e0Smacallan ri->ri_font->fontheight, 447cf4b16e0Smacallan defattr); 448cf4b16e0Smacallan #endif 4497d0f5abeSmacallan 450cf4b16e0Smacallan hyperfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 451cf4b16e0Smacallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 452cf4b16e0Smacallan hyperfb_restore_palette(sc); 453cf4b16e0Smacallan 454*64ffcac2Smacallan if (sc->sc_is_console) { 455*64ffcac2Smacallan 456*64ffcac2Smacallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 457*64ffcac2Smacallan defattr); 458*64ffcac2Smacallan vcons_replay_msgbuf(&sc->sc_console_screen); 459*64ffcac2Smacallan } 460*64ffcac2Smacallan 461cf4b16e0Smacallan /* no suspend/resume support yet */ 462cf4b16e0Smacallan if (!pmf_device_register(sc->sc_dev, NULL, NULL)) 463cf4b16e0Smacallan aprint_error_dev(sc->sc_dev, 464cf4b16e0Smacallan "couldn't establish power handler\n"); 465cf4b16e0Smacallan 466cf4b16e0Smacallan aa.console = sc->sc_is_console; 467cf4b16e0Smacallan aa.scrdata = &sc->sc_screenlist; 468cf4b16e0Smacallan aa.accessops = &hyperfb_accessops; 469cf4b16e0Smacallan aa.accesscookie = &sc->vd; 470cf4b16e0Smacallan 471cf4b16e0Smacallan config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 472cf4b16e0Smacallan 473aee609b2Smacallan hyperfb_setup_fb(sc); 474bb4ea6beSmacallan 475bb4ea6beSmacallan #ifdef HYPERFB_DEBUG 476bb4ea6beSmacallan int i; 477bb4ea6beSmacallan 478bb4ea6beSmacallan hyperfb_wait_fifo(sc, 4); 479bb4ea6beSmacallan /* transfer data */ 480bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_8, 0xff00ff00); 481bb4ea6beSmacallan /* plane mask */ 482bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_13, 0xff); 483bb4ea6beSmacallan /* bitmap op */ 484bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_14, 485bb4ea6beSmacallan IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0)); 486bb4ea6beSmacallan /* dst bitmap access */ 487bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_11, 488bb4ea6beSmacallan BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly, 0)); 489bb4ea6beSmacallan 490bb4ea6beSmacallan hyperfb_wait_fifo(sc, 3); 491bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_35, 0xe0); 492bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_36, 0x1c); 493bb4ea6beSmacallan /* dst XY */ 494bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_6, (2 << 16) | 902); 495bb4ea6beSmacallan /* len XY start */ 496bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_9, (28 << 16) | 32); 497bb4ea6beSmacallan 498bb4ea6beSmacallan for (i = 0; i < 32; i++) 499bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_8, (i & 4) ? 0xff00ff00 : 0x00ff00ff); 500bb4ea6beSmacallan 501bb4ea6beSmacallan hyperfb_rectfill(sc, 70, 902, 16, 32, 0xe0); 502bb4ea6beSmacallan hyperfb_rectfill(sc, 50, 902, 16, 32, 0x1c); 503bb4ea6beSmacallan #endif 504cf4b16e0Smacallan } 505cf4b16e0Smacallan 506cf4b16e0Smacallan static void 507cf4b16e0Smacallan hyperfb_init_screen(void *cookie, struct vcons_screen *scr, 508cf4b16e0Smacallan int existing, long *defattr) 509cf4b16e0Smacallan { 510cf4b16e0Smacallan struct hyperfb_softc *sc = cookie; 511cf4b16e0Smacallan struct rasops_info *ri = &scr->scr_ri; 512cf4b16e0Smacallan 513cf4b16e0Smacallan ri->ri_depth = 8; 514cf4b16e0Smacallan ri->ri_width = 1280; 515bb4ea6beSmacallan #ifdef HYPERFB_DEBUG 516bb4ea6beSmacallan ri->ri_height = 900; 517bb4ea6beSmacallan #else 518cf4b16e0Smacallan ri->ri_height = 1024; 519bb4ea6beSmacallan #endif 520cf4b16e0Smacallan ri->ri_stride = 2048; 521cf4b16e0Smacallan ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB /*| 522cf4b16e0Smacallan RI_ENABLE_ALPHA | RI_PREFER_ALPHA*/; 523cf4b16e0Smacallan 524cf4b16e0Smacallan ri->ri_bits = (void *)sc->sc_fb; 525cf4b16e0Smacallan rasops_init(ri, 0, 0); 526cf4b16e0Smacallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 527cf4b16e0Smacallan WSSCREEN_RESIZE; 5287d0f5abeSmacallan scr->scr_flags |= VCONS_LOADFONT; 529cf4b16e0Smacallan 530cf4b16e0Smacallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 531cf4b16e0Smacallan sc->sc_width / ri->ri_font->fontwidth); 532cf4b16e0Smacallan 533cf4b16e0Smacallan ri->ri_hw = scr; 5347d0f5abeSmacallan 5357d0f5abeSmacallan ri->ri_ops.copyrows = hyperfb_copyrows; 5367d0f5abeSmacallan ri->ri_ops.copycols = hyperfb_copycols; 5377d0f5abeSmacallan ri->ri_ops.eraserows = hyperfb_eraserows; 5387d0f5abeSmacallan ri->ri_ops.erasecols = hyperfb_erasecols; 5397d0f5abeSmacallan ri->ri_ops.cursor = hyperfb_cursor; 5407d0f5abeSmacallan ri->ri_ops.putchar = hyperfb_putchar; 541cf4b16e0Smacallan } 542cf4b16e0Smacallan 543cf4b16e0Smacallan static int 544cf4b16e0Smacallan hyperfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 545cf4b16e0Smacallan struct lwp *l) 546cf4b16e0Smacallan { 547cf4b16e0Smacallan struct vcons_data *vd = v; 548cf4b16e0Smacallan struct hyperfb_softc *sc = vd->cookie; 549cf4b16e0Smacallan struct wsdisplay_fbinfo *wdf; 550cf4b16e0Smacallan struct vcons_screen *ms = vd->active; 551cf4b16e0Smacallan 552cf4b16e0Smacallan switch (cmd) { 553cf4b16e0Smacallan case WSDISPLAYIO_GTYPE: 554cf4b16e0Smacallan *(u_int *)data = WSDISPLAY_TYPE_STI; 555cf4b16e0Smacallan return 0; 556cf4b16e0Smacallan 5577f6c1850Smacallan case GCID: 5587f6c1850Smacallan *(u_int *)data = STI_DD_HCRX; 5597f6c1850Smacallan return 0; 5607f6c1850Smacallan 561cf4b16e0Smacallan case WSDISPLAYIO_GINFO: 562cf4b16e0Smacallan if (ms == NULL) 563cf4b16e0Smacallan return ENODEV; 564cf4b16e0Smacallan wdf = (void *)data; 565cf4b16e0Smacallan wdf->height = ms->scr_ri.ri_height; 566f7add90dSriastradh wdf->width = sc->sc_24bit ? ms->scr_ri.ri_width << 2 567f7add90dSriastradh : ms->scr_ri.ri_width; 568cf4b16e0Smacallan wdf->depth = ms->scr_ri.ri_depth; 569cf4b16e0Smacallan wdf->cmsize = 256; 570cf4b16e0Smacallan return 0; 571cf4b16e0Smacallan 572cf4b16e0Smacallan case WSDISPLAYIO_GETCMAP: 573cf4b16e0Smacallan return hyperfb_getcmap(sc, 574cf4b16e0Smacallan (struct wsdisplay_cmap *)data); 575cf4b16e0Smacallan 576cf4b16e0Smacallan case WSDISPLAYIO_PUTCMAP: 577cf4b16e0Smacallan return hyperfb_putcmap(sc, 578cf4b16e0Smacallan (struct wsdisplay_cmap *)data); 579cf4b16e0Smacallan case WSDISPLAYIO_LINEBYTES: 580aee609b2Smacallan *(u_int *)data = sc->sc_24bit ? 8192 : 2048; 581cf4b16e0Smacallan return 0; 582cf4b16e0Smacallan 583cf4b16e0Smacallan case WSDISPLAYIO_SMODE: { 584cf4b16e0Smacallan int new_mode = *(int*)data; 585cf4b16e0Smacallan if (new_mode != sc->sc_mode) { 586cf4b16e0Smacallan sc->sc_mode = new_mode; 587cf4b16e0Smacallan if (new_mode == WSDISPLAYIO_MODE_EMUL) { 588cf4b16e0Smacallan hyperfb_setup(sc); 589cf4b16e0Smacallan hyperfb_restore_palette(sc); 590cf4b16e0Smacallan #if 0 591cf4b16e0Smacallan glyphcache_wipe(&sc->sc_gc); 5927d0f5abeSmacallan #endif 593cf4b16e0Smacallan hyperfb_rectfill(sc, 0, 0, sc->sc_width, 594cf4b16e0Smacallan sc->sc_height, ms->scr_ri.ri_devcmap[ 595cf4b16e0Smacallan (ms->scr_defattr >> 16) & 0xff]); 596cf4b16e0Smacallan vcons_redraw_screen(ms); 597cf4b16e0Smacallan hyperfb_set_video(sc, 1); 598aee609b2Smacallan } else { 599aee609b2Smacallan hyperfb_setup(sc); 600aee609b2Smacallan hyperfb_rectfill(sc, 0, 0, sc->sc_width, 601aee609b2Smacallan sc->sc_height, 0xff); 602aee609b2Smacallan hyperfb_setup_fb24(sc); 603cf4b16e0Smacallan } 604cf4b16e0Smacallan } 605cf4b16e0Smacallan } 606cf4b16e0Smacallan return 0; 607cf4b16e0Smacallan 608f7add90dSriastradh case WSDISPLAYIO_GET_FBINFO: { 609cf4b16e0Smacallan struct wsdisplayio_fbinfo *fbi = data; 610cf4b16e0Smacallan int ret; 611cf4b16e0Smacallan 612cf4b16e0Smacallan ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 613cf4b16e0Smacallan fbi->fbi_fbsize = sc->sc_height * 2048; 614aee609b2Smacallan if (sc->sc_24bit) { 615aee609b2Smacallan fbi->fbi_stride = 8192; 616aee609b2Smacallan fbi->fbi_bitsperpixel = 32; 617aee609b2Smacallan fbi->fbi_pixeltype = WSFB_RGB; 618aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16; 619aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 620aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 621aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 622aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0; 623aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 624aee609b2Smacallan fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 625aee609b2Smacallan fbi->fbi_fbsize = sc->sc_height * 8192; 626aee609b2Smacallan } 627cf4b16e0Smacallan return ret; 628cf4b16e0Smacallan } 629cf4b16e0Smacallan 630f7add90dSriastradh case WSDISPLAYIO_GCURPOS: { 631cf4b16e0Smacallan struct wsdisplay_curpos *cp = (void *)data; 632cf4b16e0Smacallan 633cf4b16e0Smacallan cp->x = sc->sc_cursor_x; 634cf4b16e0Smacallan cp->y = sc->sc_cursor_y; 635cf4b16e0Smacallan } 636cf4b16e0Smacallan return 0; 637cf4b16e0Smacallan 638f7add90dSriastradh case WSDISPLAYIO_SCURPOS: { 639cf4b16e0Smacallan struct wsdisplay_curpos *cp = (void *)data; 640cf4b16e0Smacallan 6417d0f5abeSmacallan hyperfb_move_cursor(sc, cp->x, cp->y); 642cf4b16e0Smacallan } 643cf4b16e0Smacallan return 0; 644cf4b16e0Smacallan 645f7add90dSriastradh case WSDISPLAYIO_GCURMAX: { 646cf4b16e0Smacallan struct wsdisplay_curpos *cp = (void *)data; 647cf4b16e0Smacallan 648cf4b16e0Smacallan cp->x = 64; 649cf4b16e0Smacallan cp->y = 64; 650cf4b16e0Smacallan } 651cf4b16e0Smacallan return 0; 652cf4b16e0Smacallan 653f7add90dSriastradh case WSDISPLAYIO_SCURSOR: { 654cf4b16e0Smacallan struct wsdisplay_cursor *cursor = (void *)data; 655cf4b16e0Smacallan 6567d0f5abeSmacallan return hyperfb_do_cursor(sc, cursor); 657cf4b16e0Smacallan } 658cf4b16e0Smacallan 659cf4b16e0Smacallan case WSDISPLAYIO_SVIDEO: 660cf4b16e0Smacallan hyperfb_set_video(sc, *(int *)data); 661cf4b16e0Smacallan return 0; 662cf4b16e0Smacallan case WSDISPLAYIO_GVIDEO: 6631aa0b529Smacallan *(u_int *)data = sc->sc_video_on ? 664cf4b16e0Smacallan WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 6651aa0b529Smacallan return 0; 666cf4b16e0Smacallan } 667cf4b16e0Smacallan return EPASSTHROUGH; 668cf4b16e0Smacallan } 669cf4b16e0Smacallan 670cf4b16e0Smacallan static paddr_t 671cf4b16e0Smacallan hyperfb_mmap(void *v, void *vs, off_t offset, int prot) 672cf4b16e0Smacallan { 673cf4b16e0Smacallan struct vcons_data *vd = v; 674cf4b16e0Smacallan struct hyperfb_softc *sc = vd->cookie; 675cf4b16e0Smacallan paddr_t pa = -1; 676cf4b16e0Smacallan 677cf4b16e0Smacallan 678cf4b16e0Smacallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 679cf4b16e0Smacallan return -1; 680cf4b16e0Smacallan 681e229c7a9Smacallan /* GSC framebuffer space is 16MB */ 682e229c7a9Smacallan if (offset >= 0 && offset < 0x1000000) { 683cf4b16e0Smacallan /* framebuffer */ 684f7add90dSriastradh pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_FBOFFSET, 685f7add90dSriastradh offset, prot, 686f7add90dSriastradh BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE); 687f020d495Smacallan } else if (offset >= 0x80000000 && offset < 0x80400000) { 688cf4b16e0Smacallan /* blitter registers etc. */ 689cf4b16e0Smacallan pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_REGOFFSET, 690cf4b16e0Smacallan offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR); 691cf4b16e0Smacallan } 692cf4b16e0Smacallan 693cf4b16e0Smacallan return pa; 694cf4b16e0Smacallan } 695cf4b16e0Smacallan 696cf4b16e0Smacallan static int 697cf4b16e0Smacallan hyperfb_putcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm) 698cf4b16e0Smacallan { 699cf4b16e0Smacallan u_char *r, *g, *b; 700cf4b16e0Smacallan u_int index = cm->index; 701cf4b16e0Smacallan u_int count = cm->count; 702cf4b16e0Smacallan int i, error; 703cf4b16e0Smacallan u_char rbuf[256], gbuf[256], bbuf[256]; 704cf4b16e0Smacallan 705cf4b16e0Smacallan if (cm->index >= 256 || cm->count > 256 || 706cf4b16e0Smacallan (cm->index + cm->count) > 256) 707cf4b16e0Smacallan return EINVAL; 708cf4b16e0Smacallan error = copyin(cm->red, &rbuf[index], count); 709cf4b16e0Smacallan if (error) 710cf4b16e0Smacallan return error; 711cf4b16e0Smacallan error = copyin(cm->green, &gbuf[index], count); 712cf4b16e0Smacallan if (error) 713cf4b16e0Smacallan return error; 714cf4b16e0Smacallan error = copyin(cm->blue, &bbuf[index], count); 715cf4b16e0Smacallan if (error) 716cf4b16e0Smacallan return error; 717cf4b16e0Smacallan 718cf4b16e0Smacallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 719cf4b16e0Smacallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 720cf4b16e0Smacallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 721cf4b16e0Smacallan 722cf4b16e0Smacallan r = &sc->sc_cmap_red[index]; 723cf4b16e0Smacallan g = &sc->sc_cmap_green[index]; 724cf4b16e0Smacallan b = &sc->sc_cmap_blue[index]; 725cf4b16e0Smacallan 726cf4b16e0Smacallan for (i = 0; i < count; i++) { 727cf4b16e0Smacallan hyperfb_putpalreg(sc, index, *r, *g, *b); 728cf4b16e0Smacallan index++; 729cf4b16e0Smacallan r++, g++, b++; 730cf4b16e0Smacallan } 731cf4b16e0Smacallan return 0; 732cf4b16e0Smacallan } 733cf4b16e0Smacallan 734cf4b16e0Smacallan static int 735cf4b16e0Smacallan hyperfb_getcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm) 736cf4b16e0Smacallan { 737cf4b16e0Smacallan u_int index = cm->index; 738cf4b16e0Smacallan u_int count = cm->count; 739cf4b16e0Smacallan int error; 740cf4b16e0Smacallan 741cf4b16e0Smacallan if (index >= 255 || count > 256 || index + count > 256) 742cf4b16e0Smacallan return EINVAL; 743cf4b16e0Smacallan 744cf4b16e0Smacallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 745cf4b16e0Smacallan if (error) 746cf4b16e0Smacallan return error; 747cf4b16e0Smacallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 748cf4b16e0Smacallan if (error) 749cf4b16e0Smacallan return error; 750cf4b16e0Smacallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 751cf4b16e0Smacallan if (error) 752cf4b16e0Smacallan return error; 753cf4b16e0Smacallan 754cf4b16e0Smacallan return 0; 755cf4b16e0Smacallan } 756cf4b16e0Smacallan 757cf4b16e0Smacallan static void 758cf4b16e0Smacallan hyperfb_restore_palette(struct hyperfb_softc *sc) 759cf4b16e0Smacallan { 760cf4b16e0Smacallan uint8_t cmap[768]; 761cf4b16e0Smacallan int i, j; 762cf4b16e0Smacallan 763cf4b16e0Smacallan j = 0; 764cf4b16e0Smacallan rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap)); 765cf4b16e0Smacallan for (i = 0; i < 256; i++) { 766cf4b16e0Smacallan sc->sc_cmap_red[i] = cmap[j]; 767cf4b16e0Smacallan sc->sc_cmap_green[i] = cmap[j + 1]; 768cf4b16e0Smacallan sc->sc_cmap_blue[i] = cmap[j + 2]; 769cf4b16e0Smacallan hyperfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 770cf4b16e0Smacallan j += 3; 771cf4b16e0Smacallan } 772cf4b16e0Smacallan } 773cf4b16e0Smacallan 774cf4b16e0Smacallan static int 775cf4b16e0Smacallan hyperfb_putpalreg(struct hyperfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 776cf4b16e0Smacallan uint8_t b) 777cf4b16e0Smacallan { 778cf4b16e0Smacallan 779cf4b16e0Smacallan mutex_enter(&sc->sc_hwlock); 780cf4b16e0Smacallan hyperfb_wait(sc); 781cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000); 782cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x03000300); 783cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 784cf4b16e0Smacallan 785cf4b16e0Smacallan hyperfb_wait(sc); 786cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2)); 787cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b); 788cf4b16e0Smacallan 789cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_2, 0x400); 790cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_38, 0x82000100); 791cf4b16e0Smacallan hyperfb_setup_fb(sc); 792cf4b16e0Smacallan mutex_exit(&sc->sc_hwlock); 793cf4b16e0Smacallan return 0; 794cf4b16e0Smacallan } 795cf4b16e0Smacallan 796cf4b16e0Smacallan void 797cf4b16e0Smacallan hyperfb_setup(struct hyperfb_softc *sc) 798cf4b16e0Smacallan { 799cf4b16e0Smacallan int i; 800cf4b16e0Smacallan uint32_t reg; 801cf4b16e0Smacallan 802cf4b16e0Smacallan sc->sc_hwmode = HW_FB; 803cf4b16e0Smacallan sc->sc_hot_x = 0; 804cf4b16e0Smacallan sc->sc_hot_y = 0; 805cf4b16e0Smacallan sc->sc_enabled = 0; 806cf4b16e0Smacallan sc->sc_video_on = 1; 807cf4b16e0Smacallan 808cf4b16e0Smacallan /* set Bt458 read mask register to all planes */ 809cf4b16e0Smacallan /* XXX I'm not sure HCRX even has one of these */ 810cf4b16e0Smacallan hyperfb_wait(sc); 811cf4b16e0Smacallan ngle_bt458_write(sc, 0x08, 0x04); 812cf4b16e0Smacallan ngle_bt458_write(sc, 0x0a, 0xff); 813cf4b16e0Smacallan 814cf4b16e0Smacallan reg = hyperfb_read4(sc, NGLE_REG_32); 815cf4b16e0Smacallan DPRINTF("planereg %08x\n", reg); 816aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_32, 0xffffffff); 817cf4b16e0Smacallan 818cf4b16e0Smacallan /* hyperbowl */ 819cf4b16e0Smacallan hyperfb_wait(sc); 820cf4b16e0Smacallan if (sc->sc_24bit) { 821cf4b16e0Smacallan /* write must happen twice because hw bug */ 822f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_40, 823f7add90dSriastradh HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE); 824f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_40, 825f7add90dSriastradh HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE); 826cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_39, HYPERBOWL_MODE2_8_24); 827f7add90dSriastradh /* Set lut 0 to be the direct color */ 828f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_42, 0x014c0148); 829cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_43, 0x404c4048); 830cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_44, 0x034c0348); 831cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_45, 0x444c4448); 832cf4b16e0Smacallan } else { 833f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_40, 834f7add90dSriastradh HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES); 835f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_40, 836f7add90dSriastradh HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES); 837cf4b16e0Smacallan 838cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_42, 0); 839cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_43, 0); 840cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_44, 0); 841aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_45, 0x444c4048); 842cf4b16e0Smacallan } 843aee609b2Smacallan 844aee609b2Smacallan /* attr. planes */ 845aee609b2Smacallan hyperfb_wait(sc); 846aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_11, 847aee609b2Smacallan BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINattr, 0)); 848aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_14, 849aee609b2Smacallan IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 1, 0)); 850aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_12, 0x04000F00/*NGLE_BUFF0_CMAP0*/); 851aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_8, 0xffffffff); 852aee609b2Smacallan 853aee609b2Smacallan hyperfb_wait(sc); 854aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_6, 0x00000000); 855aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_9, 856aee609b2Smacallan (sc->sc_width << 16) | sc->sc_height); 857aee609b2Smacallan /* 858aee609b2Smacallan * blit into offscreen memory to force flush previous - apparently 859aee609b2Smacallan * some chips have a bug this works around 860aee609b2Smacallan */ 861aee609b2Smacallan hyperfb_wait(sc); 862aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_6, 0x05000000); 863aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_9, 0x00040001); 864aee609b2Smacallan 865aee609b2Smacallan /* 866aee609b2Smacallan * on 24bit-capable hardware we: 867aee609b2Smacallan * - make overlay colour 255 transparent 868aee609b2Smacallan * - blit the 24bit buffer all white 869aee609b2Smacallan * - install a linear ramp in CMAP 0 870aee609b2Smacallan */ 871aee609b2Smacallan if (sc->sc_24bit) { 872aee609b2Smacallan /* overlay transparency */ 873aee609b2Smacallan hyperfb_wait_fifo(sc, 7); 87415644928Smacallan hyperfb_write4(sc, NGLE_REG_11, 87515644928Smacallan BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINovly, 0)); 876aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x03000300); 877aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_3, 0x000017f0); 878aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 879aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_22, 0xffffffff); 880aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_23, 0x0); 881aee609b2Smacallan 882aee609b2Smacallan hyperfb_wait(sc); 883aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_12, 0x00000000); 884aee609b2Smacallan 885aee609b2Smacallan /* clear 24bit buffer */ 886aee609b2Smacallan hyperfb_wait(sc); 887aee609b2Smacallan /* plane mask */ 888aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 889aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_8, 0xffffffff); /* transfer data */ 890aee609b2Smacallan /* bitmap op */ 891aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_14, 892f7add90dSriastradh IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 893f7add90dSriastradh 0, 0)); 894aee609b2Smacallan /* dst bitmap access */ 895aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_11, 896*64ffcac2Smacallan BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 897f7add90dSriastradh 0)); 898aee609b2Smacallan hyperfb_wait_fifo(sc, 3); 899aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_35, 0x00ffffff); /* fg colour */ 900aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_6, 0x00000000); /* dst xy */ 901aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_9, 902aee609b2Smacallan (sc->sc_width << 16) | sc->sc_height); 903aee609b2Smacallan 904aee609b2Smacallan /* write a linear ramp into CMAP0 */ 905aee609b2Smacallan hyperfb_wait(sc); 906aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000); 907aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x03000300); 908aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 909aee609b2Smacallan 910aee609b2Smacallan hyperfb_wait(sc); 911aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_3, 0); 912aee609b2Smacallan for (i = 0; i < 256; i++) { 913aee609b2Smacallan hyperfb_wait(sc); 914f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_4, 915f7add90dSriastradh (i << 16) | (i << 8) | i); 916aee609b2Smacallan } 917aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_2, 0x0); 918f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_38, 919f7add90dSriastradh LBC_ENABLE | LBC_TYPE_CMAP | 0x100); 920aee609b2Smacallan hyperfb_wait(sc); 921aee609b2Smacallan } 922aee609b2Smacallan 923aee609b2Smacallan hyperfb_setup_fb(sc); 924aee609b2Smacallan 925aee609b2Smacallan /* make sure video output is enabled */ 926aee609b2Smacallan hyperfb_wait(sc); 927aee609b2Smacallan hyperfb_write4(sc, NGLE_REG_33, 928aee609b2Smacallan hyperfb_read4(sc, NGLE_REG_33) | 0x0a000000); 929aee609b2Smacallan 930cf4b16e0Smacallan /* cursor mask */ 931cf4b16e0Smacallan hyperfb_wait(sc); 932cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_30, 0); 933cf4b16e0Smacallan for (i = 0; i < 64; i++) { 934cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_31, 0xffffffff); 935cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_31, 0xffffffff); 936cf4b16e0Smacallan } 937cf4b16e0Smacallan 938cf4b16e0Smacallan /* cursor image */ 939cf4b16e0Smacallan hyperfb_wait(sc); 940cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_30, 0x80); 941cf4b16e0Smacallan for (i = 0; i < 64; i++) { 942cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00); 943cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00); 944cf4b16e0Smacallan } 945cf4b16e0Smacallan 946aee609b2Smacallan /* colour map */ 947cf4b16e0Smacallan hyperfb_wait(sc); 948cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000); 949cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x03000300); 950cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 951cf4b16e0Smacallan hyperfb_wait(sc); 952cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_3, 0); 953cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_4, 0x000000ff); /* BG */ 954cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_4, 0x00ff0000); /* FG */ 955cf4b16e0Smacallan hyperfb_wait(sc); 956cf4b16e0Smacallan hyperfb_write4(sc, NGLE_REG_2, 0); 957357dd059Smacallan hyperfb_write4(sc, NGLE_REG_38, LBC_ENABLE | LBC_TYPE_CURSOR | 4); 958cf4b16e0Smacallan hyperfb_setup_fb(sc); 959cf4b16e0Smacallan 960357dd059Smacallan hyperfb_move_cursor(sc, 100, 100); 961cf4b16e0Smacallan } 962cf4b16e0Smacallan 963cf4b16e0Smacallan static void 964cf4b16e0Smacallan hyperfb_set_video(struct hyperfb_softc *sc, int on) 965cf4b16e0Smacallan { 966cf4b16e0Smacallan uint32_t reg; 967cf4b16e0Smacallan 968cf4b16e0Smacallan if (sc->sc_video_on == on) 969cf4b16e0Smacallan return; 970cf4b16e0Smacallan 971cf4b16e0Smacallan sc->sc_video_on = on; 972cf4b16e0Smacallan 973cf4b16e0Smacallan hyperfb_wait(sc); 974cf4b16e0Smacallan reg = hyperfb_read4(sc, NGLE_REG_33); 975cf4b16e0Smacallan 976cf4b16e0Smacallan if (on) { 977357dd059Smacallan hyperfb_write4(sc, NGLE_REG_33, reg | HCRX_VIDEO_ENABLE); 978cf4b16e0Smacallan } else { 979357dd059Smacallan hyperfb_write4(sc, NGLE_REG_33, reg & ~HCRX_VIDEO_ENABLE); 980cf4b16e0Smacallan } 981cf4b16e0Smacallan } 9827d0f5abeSmacallan 9837d0f5abeSmacallan static void 9847d0f5abeSmacallan hyperfb_rectfill(struct hyperfb_softc *sc, int x, int y, int wi, int he, 9857d0f5abeSmacallan uint32_t bg) 9867d0f5abeSmacallan { 987bb4ea6beSmacallan uint32_t mask = 0xffffffff; 988bb4ea6beSmacallan 9897d0f5abeSmacallan /* 9907d0f5abeSmacallan * XXX 991bb4ea6beSmacallan * HCRX and EG both always draw rectangles at least 32 pixels wide 992bb4ea6beSmacallan * for anything narrower we need to set a bit mask and enable 993bb4ea6beSmacallan * transparency 9947d0f5abeSmacallan */ 9957d0f5abeSmacallan 9967d0f5abeSmacallan if (sc->sc_hwmode != HW_FILL) { 997bb4ea6beSmacallan hyperfb_wait_fifo(sc, 3); 9987d0f5abeSmacallan /* plane mask */ 9997d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_13, 0xff); 10007d0f5abeSmacallan /* bitmap op */ 10017d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_14, 1002f7add90dSriastradh IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1003bb4ea6beSmacallan 1 /* bg transparent */, 0)); 10047d0f5abeSmacallan /* dst bitmap access */ 10057d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_11, 1006f7add90dSriastradh BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly, 1007f7add90dSriastradh 0)); 10087d0f5abeSmacallan sc->sc_hwmode = HW_FILL; 10097d0f5abeSmacallan } 1010bb4ea6beSmacallan hyperfb_wait_fifo(sc, 4); 1011bb4ea6beSmacallan if (wi < 32) 1012bb4ea6beSmacallan mask = 0xffffffff << (32 - wi); 1013bb4ea6beSmacallan /* 1014bb4ea6beSmacallan * XXX - the NGLE code calls this 'transfer data' 1015bb4ea6beSmacallan * in reality it's a bit mask applied per pixel, 1016bb4ea6beSmacallan * foreground colour in reg 35, bg in 36 1017bb4ea6beSmacallan */ 1018bb4ea6beSmacallan hyperfb_write4(sc, NGLE_REG_8, mask); 1019bb4ea6beSmacallan 10207d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_35, bg); 10217d0f5abeSmacallan /* dst XY */ 10227d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y); 10237d0f5abeSmacallan /* len XY start */ 10247d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | he); 10257d0f5abeSmacallan } 10267d0f5abeSmacallan 10277d0f5abeSmacallan static void 10287d0f5abeSmacallan hyperfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, 10297d0f5abeSmacallan int he, int rop) 10307d0f5abeSmacallan { 10317d0f5abeSmacallan struct hyperfb_softc *sc = cookie; 10327d0f5abeSmacallan 10337d0f5abeSmacallan if (sc->sc_hwmode != HW_BLIT) { 10347d0f5abeSmacallan hyperfb_wait(sc); 103515644928Smacallan hyperfb_write4(sc, NGLE_REG_10, 103615644928Smacallan BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINovly, 0)); 10377d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_13, 0xff); 10387d0f5abeSmacallan sc->sc_hwmode = HW_BLIT; 10397d0f5abeSmacallan } 10407d0f5abeSmacallan hyperfb_wait_fifo(sc, 4); 10417d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_14, ((rop << 8) & 0xf00) | 0x23000000); 10427d0f5abeSmacallan /* IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0) */ 10437d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_24, (xs << 16) | ys); 10447d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_7, (wi << 16) | he); 10457d0f5abeSmacallan hyperfb_write4(sc, NGLE_REG_25, (xd << 16) | yd); 10467d0f5abeSmacallan } 10477d0f5abeSmacallan 10487d0f5abeSmacallan static void 10497d0f5abeSmacallan hyperfb_nuke_cursor(struct rasops_info *ri) 10507d0f5abeSmacallan { 10517d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 10527d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 10537d0f5abeSmacallan int wi, he, x, y; 10547d0f5abeSmacallan 10557d0f5abeSmacallan if (ri->ri_flg & RI_CURSOR) { 10567d0f5abeSmacallan wi = ri->ri_font->fontwidth; 10577d0f5abeSmacallan he = ri->ri_font->fontheight; 10587d0f5abeSmacallan x = ri->ri_ccol * wi + ri->ri_xorigin; 10597d0f5abeSmacallan y = ri->ri_crow * he + ri->ri_yorigin; 10607d0f5abeSmacallan hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 10617d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 10627d0f5abeSmacallan } 10637d0f5abeSmacallan } 10647d0f5abeSmacallan 10657d0f5abeSmacallan static void 10667d0f5abeSmacallan hyperfb_cursor(void *cookie, int on, int row, int col) 10677d0f5abeSmacallan { 10687d0f5abeSmacallan struct rasops_info *ri = cookie; 10697d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 10707d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 10717d0f5abeSmacallan int x, y, wi, he; 10727d0f5abeSmacallan 10737d0f5abeSmacallan wi = ri->ri_font->fontwidth; 10747d0f5abeSmacallan he = ri->ri_font->fontheight; 10757d0f5abeSmacallan 10767d0f5abeSmacallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 10777d0f5abeSmacallan if (on) { 10787d0f5abeSmacallan if (ri->ri_flg & RI_CURSOR) { 10797d0f5abeSmacallan hyperfb_nuke_cursor(ri); 10807d0f5abeSmacallan } 10817d0f5abeSmacallan x = col * wi + ri->ri_xorigin; 10827d0f5abeSmacallan y = row * he + ri->ri_yorigin; 10837d0f5abeSmacallan hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 10847d0f5abeSmacallan ri->ri_flg |= RI_CURSOR; 10857d0f5abeSmacallan } 10867d0f5abeSmacallan ri->ri_crow = row; 10877d0f5abeSmacallan ri->ri_ccol = col; 1088f7add90dSriastradh } else { 10897d0f5abeSmacallan ri->ri_crow = row; 10907d0f5abeSmacallan ri->ri_ccol = col; 10917d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 10927d0f5abeSmacallan } 10937d0f5abeSmacallan } 10947d0f5abeSmacallan 10957d0f5abeSmacallan static void 10967d0f5abeSmacallan hyperfb_putchar(void *cookie, int row, int col, u_int c, long attr) 10977d0f5abeSmacallan { 10987d0f5abeSmacallan struct rasops_info *ri = cookie; 10997d0f5abeSmacallan struct wsdisplay_font *font = PICK_FONT(ri, c); 11007d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 11017d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 1102a74af143Smacallan void *data; 110302a20feaSmacallan int i, x, y, wi, he/*, rv = GC_NOPE*/; 110402a20feaSmacallan uint32_t bg, fg, mask; 11057d0f5abeSmacallan 11067d0f5abeSmacallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 11077d0f5abeSmacallan return; 11087d0f5abeSmacallan 11097d0f5abeSmacallan if (!CHAR_IN_FONT(c, font)) 11107d0f5abeSmacallan return; 11117d0f5abeSmacallan 11127d0f5abeSmacallan if (row == ri->ri_crow && col == ri->ri_ccol) { 11137d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 11147d0f5abeSmacallan } 11157d0f5abeSmacallan 11167d0f5abeSmacallan wi = font->fontwidth; 11177d0f5abeSmacallan he = font->fontheight; 11187d0f5abeSmacallan 11197d0f5abeSmacallan x = ri->ri_xorigin + col * wi; 11207d0f5abeSmacallan y = ri->ri_yorigin + row * he; 11217d0f5abeSmacallan 11227d0f5abeSmacallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 112302a20feaSmacallan fg = ri->ri_devcmap[(attr >> 24) & 0x0f]; 11247d0f5abeSmacallan 112502a20feaSmacallan /* clear the character cell */ 11267d0f5abeSmacallan hyperfb_rectfill(sc, x, y, wi, he, bg); 112702a20feaSmacallan 112802a20feaSmacallan /* if we're drawing a space we're done here */ 112902a20feaSmacallan if (c == 0x20) 11307d0f5abeSmacallan return; 11317d0f5abeSmacallan 11327d0f5abeSmacallan #if 0 11337d0f5abeSmacallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 11347d0f5abeSmacallan if (rv == GC_OK) 11357d0f5abeSmacallan return; 11367d0f5abeSmacallan #endif 113702a20feaSmacallan 113802a20feaSmacallan data = WSFONT_GLYPH(c, font); 113902a20feaSmacallan 114002a20feaSmacallan hyperfb_wait_fifo(sc, 2); 114102a20feaSmacallan 114202a20feaSmacallan /* character colour */ 114302a20feaSmacallan hyperfb_write4(sc, NGLE_REG_35, fg); 114402a20feaSmacallan /* dst XY */ 114502a20feaSmacallan hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y); 114602a20feaSmacallan 114702a20feaSmacallan /* 114802a20feaSmacallan * drawing a rectangle moves the starting coordinates down the 114902a20feaSmacallan * y-axis so we can just hammer the wi/he register to draw a full 115002a20feaSmacallan * character 115102a20feaSmacallan */ 115202a20feaSmacallan if (ri->ri_font->stride == 1) { 1153a74af143Smacallan uint8_t *data8 = data; 115402a20feaSmacallan for (i = 0; i < he; i++) { 115502a20feaSmacallan hyperfb_wait_fifo(sc, 2); 1156a74af143Smacallan mask = *data8; 1157a74af143Smacallan hyperfb_write4(sc, NGLE_REG_8, mask << 24); 115802a20feaSmacallan hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 1159a74af143Smacallan data8++; 116002a20feaSmacallan } 116102a20feaSmacallan } else { 1162a74af143Smacallan uint16_t *data16 = data; 116302a20feaSmacallan for (i = 0; i < he; i++) { 116402a20feaSmacallan hyperfb_wait_fifo(sc, 2); 1165a74af143Smacallan mask = *data16; 116602a20feaSmacallan hyperfb_write4(sc, NGLE_REG_8, mask << 16); 116702a20feaSmacallan hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 1168a74af143Smacallan data16++; 116902a20feaSmacallan } 117002a20feaSmacallan } 11717d0f5abeSmacallan #if 0 11727d0f5abeSmacallan if (rv == GC_ADD) 11737d0f5abeSmacallan glyphcache_add(&sc->sc_gc, c, x, y); 11747d0f5abeSmacallan #endif 11757d0f5abeSmacallan } 11767d0f5abeSmacallan 11777d0f5abeSmacallan static void 11787d0f5abeSmacallan hyperfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 11797d0f5abeSmacallan { 11807d0f5abeSmacallan struct rasops_info *ri = cookie; 11817d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 11827d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 11837d0f5abeSmacallan int32_t xs, xd, y, width, height; 11847d0f5abeSmacallan 11857d0f5abeSmacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 11867d0f5abeSmacallan if (ri->ri_crow == row && 11877d0f5abeSmacallan (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && 11887d0f5abeSmacallan (ri->ri_flg & RI_CURSOR)) { 11897d0f5abeSmacallan hyperfb_nuke_cursor(ri); 11907d0f5abeSmacallan } 11917d0f5abeSmacallan 11927d0f5abeSmacallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 11937d0f5abeSmacallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 11947d0f5abeSmacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 11957d0f5abeSmacallan width = ri->ri_font->fontwidth * ncols; 11967d0f5abeSmacallan height = ri->ri_font->fontheight; 11977d0f5abeSmacallan hyperfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc); 11987d0f5abeSmacallan if (ri->ri_crow == row && 11997d0f5abeSmacallan (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) 12007d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 12017d0f5abeSmacallan } 12027d0f5abeSmacallan } 12037d0f5abeSmacallan 12047d0f5abeSmacallan static void 1205f7add90dSriastradh hyperfb_erasecols(void *cookie, int row, int startcol, int ncols, 1206f7add90dSriastradh long fillattr) 12077d0f5abeSmacallan { 12087d0f5abeSmacallan struct rasops_info *ri = cookie; 12097d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 12107d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 12117d0f5abeSmacallan int32_t x, y, width, height, fg, bg, ul; 12127d0f5abeSmacallan 12137d0f5abeSmacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 12147d0f5abeSmacallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 12157d0f5abeSmacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 12167d0f5abeSmacallan width = ri->ri_font->fontwidth * ncols; 12177d0f5abeSmacallan height = ri->ri_font->fontheight; 12187d0f5abeSmacallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 12197d0f5abeSmacallan 12207d0f5abeSmacallan hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 12217d0f5abeSmacallan if (ri->ri_crow == row && 1222f7add90dSriastradh (ri->ri_ccol >= startcol && 1223f7add90dSriastradh ri->ri_ccol < (startcol + ncols))) 12247d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 12257d0f5abeSmacallan } 12267d0f5abeSmacallan } 12277d0f5abeSmacallan 12287d0f5abeSmacallan static void 12297d0f5abeSmacallan hyperfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 12307d0f5abeSmacallan { 12317d0f5abeSmacallan struct rasops_info *ri = cookie; 12327d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 12337d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 12347d0f5abeSmacallan int32_t x, ys, yd, width, height; 12357d0f5abeSmacallan 12367d0f5abeSmacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1237f7add90dSriastradh if ((ri->ri_crow >= srcrow && 1238f7add90dSriastradh ri->ri_crow < (srcrow + nrows)) && 12397d0f5abeSmacallan (ri->ri_flg & RI_CURSOR)) { 12407d0f5abeSmacallan hyperfb_nuke_cursor(ri); 12417d0f5abeSmacallan } 12427d0f5abeSmacallan x = ri->ri_xorigin; 12437d0f5abeSmacallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 12447d0f5abeSmacallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 12457d0f5abeSmacallan width = ri->ri_emuwidth; 12467d0f5abeSmacallan height = ri->ri_font->fontheight * nrows; 12477d0f5abeSmacallan hyperfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc); 12487d0f5abeSmacallan if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 12497d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 12507d0f5abeSmacallan } 12517d0f5abeSmacallan } 12527d0f5abeSmacallan 12537d0f5abeSmacallan static void 12547d0f5abeSmacallan hyperfb_eraserows(void *cookie, int row, int nrows, long fillattr) 12557d0f5abeSmacallan { 12567d0f5abeSmacallan struct rasops_info *ri = cookie; 12577d0f5abeSmacallan struct vcons_screen *scr = ri->ri_hw; 12587d0f5abeSmacallan struct hyperfb_softc *sc = scr->scr_cookie; 12597d0f5abeSmacallan int32_t x, y, width, height, fg, bg, ul; 12607d0f5abeSmacallan 12617d0f5abeSmacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 12627d0f5abeSmacallan x = ri->ri_xorigin; 12637d0f5abeSmacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 12647d0f5abeSmacallan width = ri->ri_emuwidth; 12657d0f5abeSmacallan height = ri->ri_font->fontheight * nrows; 12667d0f5abeSmacallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 12677d0f5abeSmacallan 12687d0f5abeSmacallan hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 12697d0f5abeSmacallan 12707d0f5abeSmacallan if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) 12717d0f5abeSmacallan ri->ri_flg &= ~RI_CURSOR; 12727d0f5abeSmacallan } 12737d0f5abeSmacallan } 1274357dd059Smacallan 1275357dd059Smacallan static void 1276357dd059Smacallan hyperfb_move_cursor(struct hyperfb_softc *sc, int x, int y) 1277357dd059Smacallan { 1278357dd059Smacallan uint32_t pos; 1279357dd059Smacallan 1280357dd059Smacallan sc->sc_cursor_x = x; 1281357dd059Smacallan x -= sc->sc_hot_x; 1282357dd059Smacallan sc->sc_cursor_y = y; 1283357dd059Smacallan y -= sc->sc_hot_y; 1284357dd059Smacallan 1285357dd059Smacallan if (x < 0) x = 0x1000 - x; 1286357dd059Smacallan if (y < 0) y = 0x1000 - y; 1287357dd059Smacallan pos = (x << 16) | y; 1288357dd059Smacallan if (sc->sc_enabled) pos |= HCRX_ENABLE_CURSOR; 128996681a35Smacallan hyperfb_wait_fifo(sc, 2); 129096681a35Smacallan hyperfb_write4(sc, NGLE_REG_28, 0); 1291357dd059Smacallan hyperfb_write4(sc, NGLE_REG_29, pos); 1292357dd059Smacallan } 1293357dd059Smacallan 1294357dd059Smacallan static int 1295357dd059Smacallan hyperfb_do_cursor(struct hyperfb_softc *sc, struct wsdisplay_cursor *cur) 1296357dd059Smacallan { 1297357dd059Smacallan 1298357dd059Smacallan if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1299357dd059Smacallan 1300357dd059Smacallan sc->sc_enabled = cur->enable; 1301357dd059Smacallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1302357dd059Smacallan } 1303357dd059Smacallan if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1304357dd059Smacallan 1305357dd059Smacallan sc->sc_hot_x = cur->hot.x; 1306357dd059Smacallan sc->sc_hot_y = cur->hot.y; 1307357dd059Smacallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1308357dd059Smacallan } 1309357dd059Smacallan if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1310357dd059Smacallan 1311357dd059Smacallan hyperfb_move_cursor(sc, cur->pos.x, cur->pos.y); 1312357dd059Smacallan } 1313357dd059Smacallan if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1314357dd059Smacallan uint32_t rgb; 1315357dd059Smacallan uint8_t r[2], g[2], b[2]; 1316357dd059Smacallan 1317357dd059Smacallan copyin(cur->cmap.blue, b, 2); 1318357dd059Smacallan copyin(cur->cmap.green, g, 2); 1319357dd059Smacallan copyin(cur->cmap.red, r, 2); 1320357dd059Smacallan mutex_enter(&sc->sc_hwlock); 1321357dd059Smacallan hyperfb_wait(sc); 1322357dd059Smacallan hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000); 1323357dd059Smacallan hyperfb_write4(sc, NGLE_REG_14, 0x03000300); 1324357dd059Smacallan hyperfb_write4(sc, NGLE_REG_13, 0xffffffff); 1325357dd059Smacallan hyperfb_wait(sc); 1326357dd059Smacallan hyperfb_write4(sc, NGLE_REG_3, 0); 1327357dd059Smacallan rgb = (r[0] << 16) | (g[0] << 8) | b[0]; 1328357dd059Smacallan hyperfb_write4(sc, NGLE_REG_4, rgb); /* BG */ 1329357dd059Smacallan rgb = (r[1] << 16) | (g[1] << 8) | b[1]; 1330357dd059Smacallan hyperfb_write4(sc, NGLE_REG_4, rgb); /* FG */ 1331357dd059Smacallan hyperfb_write4(sc, NGLE_REG_2, 0); 1332f7add90dSriastradh hyperfb_write4(sc, NGLE_REG_38, 1333f7add90dSriastradh LBC_ENABLE | LBC_TYPE_CURSOR | 4); 1334357dd059Smacallan 1335357dd059Smacallan hyperfb_setup_fb(sc); 1336357dd059Smacallan mutex_exit(&sc->sc_hwlock); 1337357dd059Smacallan 1338357dd059Smacallan } 1339357dd059Smacallan if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1340357dd059Smacallan uint32_t buffer[128], latch, tmp; 1341357dd059Smacallan int i; 1342357dd059Smacallan 1343357dd059Smacallan copyin(cur->mask, buffer, 512); 1344357dd059Smacallan hyperfb_wait(sc); 1345357dd059Smacallan hyperfb_write4(sc, NGLE_REG_30, 0); 1346357dd059Smacallan for (i = 0; i < 128; i += 2) { 1347357dd059Smacallan latch = 0; 1348357dd059Smacallan tmp = buffer[i] & 0x80808080; 1349357dd059Smacallan latch |= tmp >> 7; 1350357dd059Smacallan tmp = buffer[i] & 0x40404040; 1351357dd059Smacallan latch |= tmp >> 5; 1352357dd059Smacallan tmp = buffer[i] & 0x20202020; 1353357dd059Smacallan latch |= tmp >> 3; 1354357dd059Smacallan tmp = buffer[i] & 0x10101010; 1355357dd059Smacallan latch |= tmp >> 1; 1356357dd059Smacallan tmp = buffer[i] & 0x08080808; 1357357dd059Smacallan latch |= tmp << 1; 1358357dd059Smacallan tmp = buffer[i] & 0x04040404; 1359357dd059Smacallan latch |= tmp << 3; 1360357dd059Smacallan tmp = buffer[i] & 0x02020202; 1361357dd059Smacallan latch |= tmp << 5; 1362357dd059Smacallan tmp = buffer[i] & 0x01010101; 1363357dd059Smacallan latch |= tmp << 7; 1364357dd059Smacallan hyperfb_write4(sc, NGLE_REG_31, latch); 1365357dd059Smacallan latch = 0; 1366357dd059Smacallan tmp = buffer[i + 1] & 0x80808080; 1367357dd059Smacallan latch |= tmp >> 7; 1368357dd059Smacallan tmp = buffer[i + 1] & 0x40404040; 1369357dd059Smacallan latch |= tmp >> 5; 1370357dd059Smacallan tmp = buffer[i + 1] & 0x20202020; 1371357dd059Smacallan latch |= tmp >> 3; 1372357dd059Smacallan tmp = buffer[i + 1] & 0x10101010; 1373357dd059Smacallan latch |= tmp >> 1; 1374357dd059Smacallan tmp = buffer[i + 1] & 0x08080808; 1375357dd059Smacallan latch |= tmp << 1; 1376357dd059Smacallan tmp = buffer[i + 1] & 0x04040404; 1377357dd059Smacallan latch |= tmp << 3; 1378357dd059Smacallan tmp = buffer[i + 1] & 0x02020202; 1379357dd059Smacallan latch |= tmp << 5; 1380357dd059Smacallan tmp = buffer[i + 1] & 0x01010101; 1381357dd059Smacallan latch |= tmp << 7; 1382357dd059Smacallan hyperfb_write4(sc, NGLE_REG_31, latch); 1383357dd059Smacallan } 1384357dd059Smacallan 1385357dd059Smacallan copyin(cur->image, buffer, 512); 1386357dd059Smacallan hyperfb_wait(sc); 1387357dd059Smacallan hyperfb_write4(sc, NGLE_REG_30, 0x80); 1388357dd059Smacallan for (i = 0; i < 128; i += 2) { 1389357dd059Smacallan latch = 0; 1390357dd059Smacallan tmp = buffer[i] & 0x80808080; 1391357dd059Smacallan latch |= tmp >> 7; 1392357dd059Smacallan tmp = buffer[i] & 0x40404040; 1393357dd059Smacallan latch |= tmp >> 5; 1394357dd059Smacallan tmp = buffer[i] & 0x20202020; 1395357dd059Smacallan latch |= tmp >> 3; 1396357dd059Smacallan tmp = buffer[i] & 0x10101010; 1397357dd059Smacallan latch |= tmp >> 1; 1398357dd059Smacallan tmp = buffer[i] & 0x08080808; 1399357dd059Smacallan latch |= tmp << 1; 1400357dd059Smacallan tmp = buffer[i] & 0x04040404; 1401357dd059Smacallan latch |= tmp << 3; 1402357dd059Smacallan tmp = buffer[i] & 0x02020202; 1403357dd059Smacallan latch |= tmp << 5; 1404357dd059Smacallan tmp = buffer[i] & 0x01010101; 1405357dd059Smacallan latch |= tmp << 7; 1406357dd059Smacallan hyperfb_write4(sc, NGLE_REG_31, latch); 1407357dd059Smacallan latch = 0; 1408357dd059Smacallan tmp = buffer[i + 1] & 0x80808080; 1409357dd059Smacallan latch |= tmp >> 7; 1410357dd059Smacallan tmp = buffer[i + 1] & 0x40404040; 1411357dd059Smacallan latch |= tmp >> 5; 1412357dd059Smacallan tmp = buffer[i + 1] & 0x20202020; 1413357dd059Smacallan latch |= tmp >> 3; 1414357dd059Smacallan tmp = buffer[i + 1] & 0x10101010; 1415357dd059Smacallan latch |= tmp >> 1; 1416357dd059Smacallan tmp = buffer[i + 1] & 0x08080808; 1417357dd059Smacallan latch |= tmp << 1; 1418357dd059Smacallan tmp = buffer[i + 1] & 0x04040404; 1419357dd059Smacallan latch |= tmp << 3; 1420357dd059Smacallan tmp = buffer[i + 1] & 0x02020202; 1421357dd059Smacallan latch |= tmp << 5; 1422357dd059Smacallan tmp = buffer[i + 1] & 0x01010101; 1423357dd059Smacallan latch |= tmp << 7; 1424357dd059Smacallan hyperfb_write4(sc, NGLE_REG_31, latch); 1425357dd059Smacallan } 1426357dd059Smacallan hyperfb_setup_fb(sc); 1427357dd059Smacallan } 1428357dd059Smacallan 1429357dd059Smacallan return 0; 1430357dd059Smacallan } 1431