1 1.99 macallan /* $NetBSD: cgfourteen.c,v 1.99 2024/09/25 10:06:15 macallan Exp $ */ 2 1.1 abrown 3 1.1 abrown /* 4 1.12 pk * Copyright (c) 1996 5 1.1 abrown * The President and Fellows of Harvard College. All rights reserved. 6 1.1 abrown * Copyright (c) 1992, 1993 7 1.1 abrown * The Regents of the University of California. All rights reserved. 8 1.1 abrown * 9 1.1 abrown * This software was developed by the Computer Systems Engineering group 10 1.1 abrown * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 1.1 abrown * contributed to Berkeley. 12 1.1 abrown * 13 1.1 abrown * All advertising materials mentioning features or use of this software 14 1.1 abrown * must display the following acknowledgement: 15 1.1 abrown * This product includes software developed by Harvard University. 16 1.1 abrown * This product includes software developed by the University of 17 1.1 abrown * California, Lawrence Berkeley Laboratory. 18 1.1 abrown * 19 1.1 abrown * Redistribution and use in source and binary forms, with or without 20 1.1 abrown * modification, are permitted provided that the following conditions 21 1.1 abrown * are met: 22 1.1 abrown * 1. Redistributions of source code must retain the above copyright 23 1.1 abrown * notice, this list of conditions and the following disclaimer. 24 1.1 abrown * 2. Redistributions in binary form must reproduce the above copyright 25 1.1 abrown * notice, this list of conditions and the following disclaimer in the 26 1.1 abrown * documentation and/or other materials provided with the distribution. 27 1.1 abrown * 3. All advertising materials mentioning features or use of this software 28 1.1 abrown * must display the following acknowledgement: 29 1.1 abrown * This product includes software developed by the University of 30 1.1 abrown * California, Berkeley and its contributors. 31 1.1 abrown * This product includes software developed by Harvard University and 32 1.1 abrown * its contributors. 33 1.1 abrown * 4. Neither the name of the University nor the names of its contributors 34 1.1 abrown * may be used to endorse or promote products derived from this software 35 1.1 abrown * without specific prior written permission. 36 1.1 abrown * 37 1.1 abrown * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 38 1.1 abrown * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 1.1 abrown * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 1.1 abrown * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 41 1.1 abrown * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 1.1 abrown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 1.1 abrown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 1.1 abrown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 1.1 abrown * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 1.1 abrown * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 1.1 abrown * SUCH DAMAGE. 48 1.1 abrown * 49 1.1 abrown * Based on: 50 1.1 abrown * NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp 51 1.1 abrown * NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp 52 1.1 abrown */ 53 1.1 abrown 54 1.1 abrown /* 55 1.1 abrown * Driver for Campus-II on-board mbus-based video (cgfourteen). 56 1.1 abrown * 57 1.1 abrown * Does not handle interrupts, even though they can occur. 58 1.1 abrown * 59 1.1 abrown * XXX should defer colormap updates to vertical retrace interrupts 60 1.1 abrown */ 61 1.10 mrg 62 1.70 macallan #include "opt_wsemul.h" 63 1.70 macallan #include "sx.h" 64 1.70 macallan 65 1.1 abrown #include <sys/param.h> 66 1.1 abrown #include <sys/systm.h> 67 1.1 abrown #include <sys/buf.h> 68 1.1 abrown #include <sys/device.h> 69 1.1 abrown #include <sys/ioctl.h> 70 1.55 macallan #include <sys/kmem.h> 71 1.1 abrown #include <sys/mman.h> 72 1.1 abrown #include <sys/tty.h> 73 1.1 abrown #include <sys/conf.h> 74 1.55 macallan #include <dev/pci/pciio.h> 75 1.1 abrown 76 1.18 mrg #include <uvm/uvm_extern.h> 77 1.1 abrown 78 1.42 christos #include <dev/sun/fbio.h> 79 1.19 pk #include <machine/autoconf.h> 80 1.42 christos #include <machine/pmap.h> 81 1.42 christos #include <dev/sun/fbvar.h> 82 1.42 christos #include <machine/cpu.h> 83 1.19 pk #include <dev/sbus/sbusvar.h> 84 1.19 pk 85 1.49 macallan #include "wsdisplay.h" 86 1.49 macallan #include <dev/wscons/wsconsio.h> 87 1.49 macallan #include <dev/wsfont/wsfont.h> 88 1.49 macallan #include <dev/rasops/rasops.h> 89 1.49 macallan 90 1.49 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 91 1.80 macallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 92 1.49 macallan 93 1.70 macallan #include <sparc/sparc/asm.h> 94 1.1 abrown #include <sparc/dev/cgfourteenreg.h> 95 1.1 abrown #include <sparc/dev/cgfourteenvar.h> 96 1.70 macallan #include <sparc/dev/sxreg.h> 97 1.70 macallan #include <sparc/dev/sxvar.h> 98 1.49 macallan 99 1.1 abrown /* autoconfiguration driver */ 100 1.53 macallan static int cgfourteenmatch(device_t, struct cfdata *, void *); 101 1.53 macallan static void cgfourteenattach(device_t, device_t, void *); 102 1.53 macallan static void cgfourteenunblank(device_t); 103 1.1 abrown 104 1.53 macallan CFATTACH_DECL_NEW(cgfourteen, sizeof(struct cgfourteen_softc), 105 1.30 thorpej cgfourteenmatch, cgfourteenattach, NULL, NULL); 106 1.76 macallan 107 1.8 thorpej extern struct cfdriver cgfourteen_cd; 108 1.1 abrown 109 1.26 gehenna dev_type_open(cgfourteenopen); 110 1.26 gehenna dev_type_close(cgfourteenclose); 111 1.26 gehenna dev_type_ioctl(cgfourteenioctl); 112 1.26 gehenna dev_type_mmap(cgfourteenmmap); 113 1.42 christos dev_type_poll(cgfourteenpoll); 114 1.26 gehenna 115 1.26 gehenna const struct cdevsw cgfourteen_cdevsw = { 116 1.77 dholland .d_open = cgfourteenopen, 117 1.77 dholland .d_close = cgfourteenclose, 118 1.77 dholland .d_read = noread, 119 1.77 dholland .d_write = nowrite, 120 1.77 dholland .d_ioctl = cgfourteenioctl, 121 1.77 dholland .d_stop = nostop, 122 1.77 dholland .d_tty = notty, 123 1.77 dholland .d_poll = cgfourteenpoll, 124 1.77 dholland .d_mmap = cgfourteenmmap, 125 1.77 dholland .d_kqfilter = nokqfilter, 126 1.79 dholland .d_discard = nodiscard, 127 1.77 dholland .d_flag = 0 128 1.26 gehenna }; 129 1.26 gehenna 130 1.1 abrown /* frame buffer generic driver */ 131 1.1 abrown static struct fbdriver cgfourteenfbdriver = { 132 1.12 pk cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, 133 1.42 christos cgfourteenpoll, cgfourteenmmap, nokqfilter 134 1.1 abrown }; 135 1.1 abrown 136 1.40 uwe static void cg14_set_video(struct cgfourteen_softc *, int); 137 1.40 uwe static int cg14_get_video(struct cgfourteen_softc *); 138 1.40 uwe static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int); 139 1.40 uwe static int cg14_put_cmap(struct fbcmap *, union cg14cmap *, int); 140 1.40 uwe static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int); 141 1.40 uwe static void cg14_init(struct cgfourteen_softc *); 142 1.40 uwe static void cg14_reset(struct cgfourteen_softc *); 143 1.23 darrenr 144 1.49 macallan #if NWSDISPLAY > 0 145 1.49 macallan static void cg14_setup_wsdisplay(struct cgfourteen_softc *, int); 146 1.49 macallan static void cg14_init_cmap(struct cgfourteen_softc *); 147 1.49 macallan static int cg14_putcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 148 1.49 macallan static int cg14_getcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 149 1.49 macallan static void cg14_set_depth(struct cgfourteen_softc *, int); 150 1.50 macallan static void cg14_move_cursor(struct cgfourteen_softc *, int, int); 151 1.50 macallan static int cg14_do_cursor(struct cgfourteen_softc *, 152 1.50 macallan struct wsdisplay_cursor *); 153 1.70 macallan 154 1.70 macallan #if NSX > 0 155 1.70 macallan static void cg14_wait_idle(struct cgfourteen_softc *); 156 1.72 macallan static void cg14_rectfill(struct cgfourteen_softc *, int, int, int, int, 157 1.72 macallan uint32_t); 158 1.83 macallan static void cg14_rectfill_a(void *, int, int, int, int, long); 159 1.71 macallan static void cg14_invert(struct cgfourteen_softc *, int, int, int, int); 160 1.70 macallan static void cg14_bitblt(void *, int, int, int, int, int, int, int); 161 1.80 macallan static void cg14_bitblt_gc(void *, int, int, int, int, int, int, int); 162 1.70 macallan 163 1.70 macallan static void cg14_putchar_aa(void *, int, int, u_int, long); 164 1.71 macallan static void cg14_cursor(void *, int, int, int); 165 1.70 macallan static void cg14_putchar(void *, int, int, u_int, long); 166 1.70 macallan static void cg14_copycols(void *, int, int, int, int); 167 1.70 macallan static void cg14_erasecols(void *, int, int, int, long); 168 1.70 macallan static void cg14_copyrows(void *, int, int, int); 169 1.70 macallan static void cg14_eraserows(void *, int, int, long); 170 1.94 macallan 171 1.94 macallan /* 172 1.94 macallan * issue ALU instruction: 173 1.94 macallan * sxi(OPCODE, srcA, srcB, dest, count) 174 1.94 macallan */ 175 1.95 macallan #define sxi(inst, a, b, d, cnt) \ 176 1.95 macallan sx_wait(sc->sc_sx); \ 177 1.95 macallan sx_write(sc->sc_sx, SX_INSTRUCTIONS, inst((a), (b), (d), (cnt))) 178 1.94 macallan 179 1.94 macallan /* 180 1.94 macallan * issue memory referencing instruction: 181 1.94 macallan * sxm(OPCODE, address, start register, count) 182 1.94 macallan */ 183 1.94 macallan #define sxm(inst, addr, reg, count) sta((addr) & ~7, ASI_SX, inst((reg), (count), (addr) & 7)) 184 1.94 macallan 185 1.70 macallan #endif /* NSX > 0 */ 186 1.70 macallan 187 1.49 macallan #endif 188 1.49 macallan 189 1.23 darrenr /* 190 1.1 abrown * Match a cgfourteen. 191 1.1 abrown */ 192 1.42 christos int 193 1.53 macallan cgfourteenmatch(device_t parent, struct cfdata *cf, void *aux) 194 1.1 abrown { 195 1.11 pk union obio_attach_args *uoba = aux; 196 1.11 pk struct sbus_attach_args *sa = &uoba->uoba_sbus; 197 1.1 abrown 198 1.1 abrown /* 199 1.1 abrown * The cgfourteen is a local-bus video adaptor, accessed directly 200 1.1 abrown * via the processor, and not through device space or an external 201 1.1 abrown * bus. Thus we look _only_ at the obio bus. 202 1.1 abrown * Additionally, these things exist only on the Sun4m. 203 1.1 abrown */ 204 1.11 pk 205 1.11 pk if (uoba->uoba_isobio4 != 0 || !CPU_ISSUN4M) 206 1.11 pk return (0); 207 1.11 pk 208 1.11 pk /* Check driver name */ 209 1.27 thorpej return (strcmp(cf->cf_name, sa->sa_name) == 0); 210 1.1 abrown } 211 1.1 abrown 212 1.49 macallan #if NWSDISPLAY > 0 213 1.49 macallan static int cg14_ioctl(void *, void *, u_long, void *, int, struct lwp *); 214 1.49 macallan static paddr_t cg14_mmap(void *, void *, off_t, int); 215 1.49 macallan static void cg14_init_screen(void *, struct vcons_screen *, int, long *); 216 1.49 macallan 217 1.49 macallan 218 1.49 macallan struct wsdisplay_accessops cg14_accessops = { 219 1.49 macallan cg14_ioctl, 220 1.49 macallan cg14_mmap, 221 1.49 macallan NULL, /* alloc_screen */ 222 1.49 macallan NULL, /* free_screen */ 223 1.49 macallan NULL, /* show_screen */ 224 1.49 macallan NULL, /* load_font */ 225 1.49 macallan NULL, /* pollc */ 226 1.49 macallan NULL /* scroll */ 227 1.49 macallan }; 228 1.49 macallan #endif 229 1.49 macallan 230 1.42 christos /* 231 1.1 abrown * Attach a display. We need to notice if it is the console, too. 232 1.1 abrown */ 233 1.42 christos void 234 1.53 macallan cgfourteenattach(device_t parent, device_t self, void *aux) 235 1.1 abrown { 236 1.11 pk union obio_attach_args *uoba = aux; 237 1.11 pk struct sbus_attach_args *sa = &uoba->uoba_sbus; 238 1.53 macallan struct cgfourteen_softc *sc = device_private(self); 239 1.11 pk struct fbdevice *fb = &sc->sc_fb; 240 1.11 pk bus_space_handle_t bh; 241 1.75 macallan int node; 242 1.40 uwe volatile uint32_t *lut; 243 1.56 macallan int i, isconsole, items; 244 1.56 macallan uint32_t fbva[2] = {0, 0}; 245 1.56 macallan uint32_t *ptr = fbva; 246 1.99 macallan int ver, impl; 247 1.70 macallan #if NSX > 0 248 1.70 macallan device_t dv; 249 1.70 macallan deviter_t di; 250 1.70 macallan #endif 251 1.11 pk 252 1.53 macallan sc->sc_dev = self; 253 1.55 macallan sc->sc_opens = 0; 254 1.11 pk node = sa->sa_node; 255 1.11 pk 256 1.11 pk /* Remember cookies for cgfourteenmmap() */ 257 1.11 pk sc->sc_bustag = sa->sa_bustag; 258 1.1 abrown 259 1.11 pk fb->fb_driver = &cgfourteenfbdriver; 260 1.53 macallan fb->fb_device = sc->sc_dev; 261 1.11 pk /* Mask out invalid flags from the user. */ 262 1.53 macallan fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; 263 1.1 abrown 264 1.63 macallan fb->fb_type.fb_type = FBTYPE_MDICOLOR; 265 1.11 pk fb->fb_type.fb_depth = 32; 266 1.63 macallan 267 1.11 pk fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node); 268 1.53 macallan 269 1.11 pk fb->fb_type.fb_cmsize = CG14_CLUT_SIZE; 270 1.11 pk 271 1.13 pk if (sa->sa_nreg < 2) { 272 1.13 pk printf("%s: only %d register sets\n", 273 1.68 chs device_xname(self), sa->sa_nreg); 274 1.11 pk return; 275 1.11 pk } 276 1.59 cegger memcpy(sc->sc_physadr, sa->sa_reg, 277 1.42 christos sa->sa_nreg * sizeof(struct sbus_reg)); 278 1.1 abrown 279 1.49 macallan sc->sc_vramsize = sc->sc_physadr[CG14_PXL_IDX].sbr_size; 280 1.75 macallan fb->fb_type.fb_size = sc->sc_vramsize; 281 1.49 macallan 282 1.49 macallan printf(": %d MB VRAM", (uint32_t)(sc->sc_vramsize >> 20)); 283 1.1 abrown /* 284 1.1 abrown * Now map in the 8 useful pages of registers 285 1.1 abrown */ 286 1.11 pk if (sa->sa_size < 0x10000) { 287 1.1 abrown #ifdef DIAGNOSTIC 288 1.5 christos printf("warning: can't find all cgfourteen registers...\n"); 289 1.1 abrown #endif 290 1.11 pk sa->sa_size = 0x10000; 291 1.1 abrown } 292 1.42 christos if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 293 1.42 christos sa->sa_offset, 294 1.42 christos sa->sa_size, 295 1.87 macallan BUS_SPACE_MAP_LINEAR, 296 1.42 christos &bh) != 0) { 297 1.72 macallan printf("%s: cannot map control registers\n", 298 1.72 macallan device_xname(self)); 299 1.11 pk return; 300 1.11 pk } 301 1.49 macallan sc->sc_regh = bh; 302 1.64 macallan sc->sc_regaddr = BUS_ADDR(sa->sa_slot, sa->sa_offset); 303 1.64 macallan sc->sc_fbaddr = BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 304 1.64 macallan sc->sc_physadr[CG14_PXL_IDX].sbr_offset); 305 1.64 macallan 306 1.11 pk sc->sc_ctl = (struct cg14ctl *) (bh); 307 1.11 pk sc->sc_hwc = (struct cg14curs *) (bh + CG14_OFFSET_CURS); 308 1.11 pk sc->sc_dac = (struct cg14dac *) (bh + CG14_OFFSET_DAC); 309 1.11 pk sc->sc_xlut = (struct cg14xlut *) (bh + CG14_OFFSET_XLUT); 310 1.11 pk sc->sc_clut1 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT1); 311 1.11 pk sc->sc_clut2 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT2); 312 1.11 pk sc->sc_clut3 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT3); 313 1.11 pk sc->sc_clutincr = (u_int *) (bh + CG14_OFFSET_CLUTINCR); 314 1.1 abrown 315 1.1 abrown /* 316 1.1 abrown * Let the user know that we're here 317 1.1 abrown */ 318 1.63 macallan printf(": %dx%d", 319 1.11 pk fb->fb_type.fb_width, fb->fb_type.fb_height); 320 1.63 macallan 321 1.1 abrown /* 322 1.42 christos * Enable the video. 323 1.1 abrown */ 324 1.1 abrown cg14_set_video(sc, 1); 325 1.1 abrown 326 1.1 abrown /* 327 1.1 abrown * Grab the initial colormap 328 1.1 abrown */ 329 1.39 tsutsui lut = sc->sc_clut1->clut_lut; 330 1.1 abrown for (i = 0; i < CG14_CLUT_SIZE; i++) 331 1.1 abrown sc->sc_cmap.cm_chip[i] = lut[i]; 332 1.1 abrown 333 1.1 abrown /* See if we're the console */ 334 1.42 christos isconsole = fb_is_console(node); 335 1.1 abrown 336 1.49 macallan #if NWSDISPLAY > 0 337 1.56 macallan prom_getprop(sa->sa_node, "address", 4, &items, &ptr); 338 1.56 macallan if (fbva[1] == 0) { 339 1.60 macallan if (sbus_bus_map( sc->sc_bustag, 340 1.56 macallan sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 341 1.56 macallan sc->sc_physadr[CG14_PXL_IDX].sbr_offset, 342 1.75 macallan sc->sc_vramsize, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 343 1.60 macallan &bh) != 0) { 344 1.58 macallan printf("%s: cannot map pixels\n", 345 1.58 macallan device_xname(sc->sc_dev)); 346 1.56 macallan return; 347 1.56 macallan } 348 1.56 macallan sc->sc_fb.fb_pixels = bus_space_vaddr(sc->sc_bustag, bh); 349 1.56 macallan } else { 350 1.56 macallan sc->sc_fb.fb_pixels = (void *)fbva[1]; 351 1.49 macallan } 352 1.49 macallan 353 1.49 macallan if (isconsole) 354 1.49 macallan printf(" (console)\n"); 355 1.51 jdc else 356 1.51 jdc printf("\n"); 357 1.49 macallan 358 1.99 macallan ver = sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK; 359 1.99 macallan impl = sc->sc_ctl->ctl_rsr & CG14_RSR_IMPLMASK; 360 1.99 macallan aprint_normal_dev(sc->sc_dev, "rev %d, %d CLUTs\n", 361 1.99 macallan ver == 0 ? 1 : 2, 362 1.99 macallan (impl & 1) == 0 ? 2 : 3); 363 1.99 macallan 364 1.49 macallan sc->sc_depth = 8; 365 1.70 macallan 366 1.70 macallan #if NSX > 0 367 1.70 macallan /* see if we've got an SX to help us */ 368 1.70 macallan sc->sc_sx = NULL; 369 1.70 macallan for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 370 1.70 macallan dv != NULL; 371 1.70 macallan dv = deviter_next(&di)) { 372 1.70 macallan if (device_is_a(dv, "sx")) { 373 1.70 macallan sc->sc_sx = device_private(dv); 374 1.70 macallan } 375 1.70 macallan } 376 1.70 macallan deviter_release(&di); 377 1.70 macallan if (sc->sc_sx != NULL) { 378 1.70 macallan sc->sc_fb_paddr = bus_space_mmap(sc->sc_bustag, 379 1.70 macallan sc->sc_fbaddr, 0, 0, 0) & 0xfffff000; 380 1.70 macallan aprint_normal_dev(sc->sc_dev, "using %s\n", 381 1.70 macallan device_xname(sc->sc_sx->sc_dev)); 382 1.94 macallan aprint_normal_dev(sc->sc_dev, "fb paddr: %08x\n", 383 1.70 macallan sc->sc_fb_paddr); 384 1.70 macallan sx_write(sc->sc_sx, SX_PAGE_BOUND_LOWER, sc->sc_fb_paddr); 385 1.70 macallan sx_write(sc->sc_sx, SX_PAGE_BOUND_UPPER, 386 1.70 macallan sc->sc_fb_paddr + 0x03ffffff); 387 1.70 macallan } 388 1.71 macallan cg14_wait_idle(sc); 389 1.70 macallan #endif 390 1.49 macallan cg14_setup_wsdisplay(sc, isconsole); 391 1.49 macallan #endif 392 1.1 abrown 393 1.1 abrown /* Attach to /dev/fb */ 394 1.16 pk fb_attach(&sc->sc_fb, isconsole); 395 1.98 macallan 396 1.1 abrown } 397 1.1 abrown 398 1.1 abrown /* 399 1.12 pk * Keep track of the number of opens made. In the 24-bit driver, we need to 400 1.1 abrown * switch to 24-bit mode on the first open, and switch back to 8-bit on 401 1.1 abrown * the last close. This kind of nonsense is needed to give screenblank 402 1.1 abrown * a fighting chance of working. 403 1.1 abrown */ 404 1.94 macallan 405 1.1 abrown int 406 1.41 christos cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) 407 1.1 abrown { 408 1.42 christos struct cgfourteen_softc *sc; 409 1.55 macallan int oldopens; 410 1.1 abrown 411 1.54 cegger sc = device_lookup_private(&cgfourteen_cd, minor(dev)); 412 1.42 christos if (sc == NULL) 413 1.42 christos return(ENXIO); 414 1.55 macallan oldopens = sc->sc_opens++; 415 1.1 abrown 416 1.1 abrown /* Setup the cg14 as we want it, and save the original PROM state */ 417 1.1 abrown if (oldopens == 0) /* first open only, to make screenblank work */ 418 1.1 abrown cg14_init(sc); 419 1.1 abrown 420 1.1 abrown return (0); 421 1.1 abrown } 422 1.1 abrown 423 1.1 abrown int 424 1.41 christos cgfourteenclose(dev_t dev, int flags, int mode, struct lwp *l) 425 1.1 abrown { 426 1.53 macallan struct cgfourteen_softc *sc = 427 1.54 cegger device_lookup_private(&cgfourteen_cd, minor(dev)); 428 1.55 macallan int opens; 429 1.1 abrown 430 1.55 macallan opens = --sc->sc_opens; 431 1.55 macallan if (sc->sc_opens < 0) 432 1.55 macallan opens = sc->sc_opens = 0; 433 1.1 abrown 434 1.1 abrown /* 435 1.1 abrown * Restore video state to make the PROM happy, on last close. 436 1.1 abrown */ 437 1.82 macallan if (opens == 0) { 438 1.1 abrown cg14_reset(sc); 439 1.82 macallan #if NSX > 0 440 1.82 macallan if (sc->sc_sx) 441 1.82 macallan glyphcache_wipe(&sc->sc_gc); 442 1.82 macallan #endif 443 1.82 macallan } 444 1.1 abrown return (0); 445 1.1 abrown } 446 1.1 abrown 447 1.1 abrown int 448 1.48 christos cgfourteenioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 449 1.1 abrown { 450 1.53 macallan struct cgfourteen_softc *sc = 451 1.54 cegger device_lookup_private(&cgfourteen_cd, minor(dev)); 452 1.11 pk struct fbgattr *fba; 453 1.42 christos int error; 454 1.1 abrown 455 1.1 abrown switch (cmd) { 456 1.1 abrown 457 1.1 abrown case FBIOGTYPE: 458 1.1 abrown *(struct fbtype *)data = sc->sc_fb.fb_type; 459 1.1 abrown break; 460 1.1 abrown 461 1.1 abrown case FBIOGATTR: 462 1.1 abrown fba = (struct fbgattr *)data; 463 1.1 abrown fba->real_type = FBTYPE_MDICOLOR; 464 1.1 abrown fba->owner = 0; /* XXX ??? */ 465 1.1 abrown fba->fbtype = sc->sc_fb.fb_type; 466 1.1 abrown fba->sattr.flags = 0; 467 1.1 abrown fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 468 1.1 abrown fba->sattr.dev_specific[0] = -1; 469 1.1 abrown fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 470 1.1 abrown fba->emu_types[1] = -1; 471 1.1 abrown break; 472 1.1 abrown 473 1.1 abrown case FBIOGETCMAP: 474 1.42 christos return(cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, 475 1.1 abrown CG14_CLUT_SIZE)); 476 1.1 abrown 477 1.1 abrown case FBIOPUTCMAP: 478 1.1 abrown /* copy to software map */ 479 1.1 abrown #define p ((struct fbcmap *)data) 480 1.1 abrown error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE); 481 1.1 abrown if (error) 482 1.1 abrown return (error); 483 1.1 abrown /* now blast them into the chip */ 484 1.1 abrown /* XXX should use retrace interrupt */ 485 1.99 macallan if (sc->sc_depth == 8) 486 1.99 macallan cg14_load_hwcmap(sc, p->index, p->count); 487 1.1 abrown #undef p 488 1.1 abrown break; 489 1.1 abrown 490 1.1 abrown case FBIOGVIDEO: 491 1.1 abrown *(int *)data = cg14_get_video(sc); 492 1.1 abrown break; 493 1.1 abrown 494 1.1 abrown case FBIOSVIDEO: 495 1.1 abrown cg14_set_video(sc, *(int *)data); 496 1.1 abrown break; 497 1.1 abrown 498 1.64 macallan case CG14_SET_PIXELMODE: { 499 1.64 macallan int depth = *(int *)data; 500 1.64 macallan 501 1.66 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 502 1.64 macallan return EINVAL; 503 1.66 macallan 504 1.66 macallan cg14_set_depth(sc, depth); 505 1.98 macallan cg14_init_cmap(sc); 506 1.64 macallan } 507 1.64 macallan break; 508 1.1 abrown default: 509 1.1 abrown return (ENOTTY); 510 1.1 abrown } 511 1.1 abrown return (0); 512 1.1 abrown } 513 1.1 abrown 514 1.1 abrown /* 515 1.1 abrown * Undo the effect of an FBIOSVIDEO that turns the video off. 516 1.1 abrown */ 517 1.1 abrown static void 518 1.53 macallan cgfourteenunblank(device_t dev) 519 1.1 abrown { 520 1.53 macallan struct cgfourteen_softc *sc = device_private(dev); 521 1.1 abrown 522 1.50 macallan cg14_set_video(sc, 1); 523 1.50 macallan #if NWSDISPLAY > 0 524 1.50 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { 525 1.50 macallan cg14_set_depth(sc, 8); 526 1.50 macallan cg14_init_cmap(sc); 527 1.50 macallan vcons_redraw_screen(sc->sc_vd.active); 528 1.50 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 529 1.50 macallan } 530 1.50 macallan #endif 531 1.1 abrown } 532 1.1 abrown 533 1.1 abrown /* 534 1.1 abrown * Return the address that would map the given device at the given 535 1.1 abrown * offset, allowing for the given protection, or return -1 for error. 536 1.64 macallan */ 537 1.17 simonb paddr_t 538 1.40 uwe cgfourteenmmap(dev_t dev, off_t off, int prot) 539 1.1 abrown { 540 1.53 macallan struct cgfourteen_softc *sc = 541 1.54 cegger device_lookup_private(&cgfourteen_cd, minor(dev)); 542 1.64 macallan off_t offset = -1; 543 1.12 pk 544 1.1 abrown if (off & PGOFSET) 545 1.1 abrown panic("cgfourteenmmap"); 546 1.14 mrg 547 1.14 mrg if (off < 0) 548 1.14 mrg return (-1); 549 1.1 abrown 550 1.64 macallan if (off >= 0 && off < 0x10000) { 551 1.64 macallan offset = sc->sc_regaddr; 552 1.64 macallan } else if (off >= CG14_CURSOR_VOFF && 553 1.64 macallan off < (CG14_CURSOR_VOFF + 0x1000)) { 554 1.64 macallan offset = sc->sc_regaddr + CG14_OFFSET_CURS; 555 1.64 macallan off -= CG14_CURSOR_VOFF; 556 1.64 macallan } else if (off >= CG14_DIRECT_VOFF && 557 1.64 macallan off < (CG14_DIRECT_VOFF + sc->sc_vramsize)) { 558 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_VRAM; 559 1.64 macallan off -= CG14_DIRECT_VOFF; 560 1.64 macallan } else if (off >= CG14_BGR_VOFF && 561 1.64 macallan off < (CG14_BGR_VOFF + sc->sc_vramsize)) { 562 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_CBGR; 563 1.64 macallan off -= CG14_BGR_VOFF; 564 1.64 macallan } else if (off >= CG14_X32_VOFF && 565 1.64 macallan off < (CG14_X32_VOFF + (sc->sc_vramsize >> 2))) { 566 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_PX32; 567 1.64 macallan off -= CG14_X32_VOFF; 568 1.64 macallan } else if (off >= CG14_B32_VOFF && 569 1.64 macallan off < (CG14_B32_VOFF + (sc->sc_vramsize >> 2))) { 570 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_PB32; 571 1.64 macallan off -= CG14_B32_VOFF; 572 1.64 macallan } else if (off >= CG14_G32_VOFF && 573 1.64 macallan off < (CG14_G32_VOFF + (sc->sc_vramsize >> 2))) { 574 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_PG32; 575 1.64 macallan off -= CG14_G32_VOFF; 576 1.64 macallan } else if (off >= CG14_R32_VOFF && 577 1.64 macallan off < CG14_R32_VOFF + (sc->sc_vramsize >> 2)) { 578 1.64 macallan offset = sc->sc_fbaddr + CG14_FB_PR32; 579 1.64 macallan off -= CG14_R32_VOFF; 580 1.73 macallan #if NSX > 0 581 1.76 macallan /* 582 1.76 macallan * for convenience we also map the SX ranges here: 583 1.76 macallan * - one page userland registers 584 1.76 macallan * - CG14-sized IO space at 0x800000000 ( not a typo, it's above 4GB ) 585 1.76 macallan */ 586 1.73 macallan } else if (sc->sc_sx == NULL) { 587 1.73 macallan return -1; 588 1.73 macallan } else if (off >= CG14_SXREG_VOFF && 589 1.73 macallan off < (CG14_SXREG_VOFF + 0x400)) { 590 1.73 macallan return (bus_space_mmap(sc->sc_sx->sc_tag, sc->sc_sx->sc_uregs, 591 1.73 macallan 0, prot, BUS_SPACE_MAP_LINEAR)); 592 1.73 macallan } else if (off >= CG14_SXIO_VOFF && 593 1.73 macallan off < (CG14_SXIO_VOFF + 0x03ffffff)) { 594 1.94 macallan off -= CG14_SXIO_VOFF; 595 1.73 macallan return (bus_space_mmap(sc->sc_sx->sc_tag, 0x800000000LL, 596 1.94 macallan sc->sc_fb_paddr + off, 597 1.74 macallan prot, BUS_SPACE_MAP_LINEAR)); 598 1.73 macallan #endif 599 1.64 macallan } else 600 1.64 macallan return -1; 601 1.76 macallan 602 1.64 macallan return (bus_space_mmap(sc->sc_bustag, offset, off, prot, 603 1.64 macallan BUS_SPACE_MAP_LINEAR)); 604 1.12 pk } 605 1.1 abrown 606 1.42 christos int 607 1.42 christos cgfourteenpoll(dev_t dev, int events, struct lwp *l) 608 1.42 christos { 609 1.42 christos 610 1.42 christos return (seltrue(dev, events, l)); 611 1.42 christos } 612 1.42 christos 613 1.1 abrown /* 614 1.12 pk * Miscellaneous helper functions 615 1.1 abrown */ 616 1.1 abrown 617 1.1 abrown /* Initialize the framebuffer, storing away useful state for later reset */ 618 1.12 pk static void 619 1.40 uwe cg14_init(struct cgfourteen_softc *sc) 620 1.1 abrown { 621 1.98 macallan cg14_set_depth(sc, 32); 622 1.98 macallan cg14_init_cmap(sc); 623 1.1 abrown } 624 1.1 abrown 625 1.42 christos static void 626 1.40 uwe /* Restore the state saved on cg14_init */ 627 1.40 uwe cg14_reset(struct cgfourteen_softc *sc) 628 1.1 abrown { 629 1.66 macallan cg14_set_depth(sc, 8); 630 1.98 macallan cg14_init_cmap(sc); 631 1.1 abrown } 632 1.1 abrown 633 1.1 abrown /* Enable/disable video display; power down monitor if DPMS-capable */ 634 1.1 abrown static void 635 1.40 uwe cg14_set_video(struct cgfourteen_softc *sc, int enable) 636 1.1 abrown { 637 1.12 pk /* 638 1.1 abrown * We can only use DPMS to power down the display if the chip revision 639 1.1 abrown * is greater than 0. 640 1.1 abrown */ 641 1.1 abrown if (enable) { 642 1.1 abrown if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 643 1.1 abrown sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID | 644 1.1 abrown CG14_MCTL_POWERCTL); 645 1.1 abrown else 646 1.1 abrown sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID; 647 1.1 abrown } else { 648 1.1 abrown if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 649 1.1 abrown sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID | 650 1.1 abrown CG14_MCTL_POWERCTL); 651 1.1 abrown else 652 1.1 abrown sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID; 653 1.1 abrown } 654 1.1 abrown } 655 1.1 abrown 656 1.1 abrown /* Get status of video display */ 657 1.1 abrown static int 658 1.40 uwe cg14_get_video(struct cgfourteen_softc *sc) 659 1.1 abrown { 660 1.1 abrown return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); 661 1.1 abrown } 662 1.1 abrown 663 1.1 abrown /* Read the software shadow colormap */ 664 1.12 pk static int 665 1.40 uwe cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 666 1.1 abrown { 667 1.42 christos u_int i, start, count; 668 1.42 christos u_char *cp; 669 1.42 christos int error; 670 1.42 christos 671 1.42 christos start = p->index; 672 1.42 christos count = p->count; 673 1.42 christos if (start >= cmsize || count > cmsize - start) 674 1.42 christos return (EINVAL); 675 1.42 christos 676 1.42 christos for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { 677 1.42 christos error = copyout(&cp[3], &p->red[i], 1); 678 1.42 christos if (error) 679 1.42 christos return error; 680 1.42 christos error = copyout(&cp[2], &p->green[i], 1); 681 1.42 christos if (error) 682 1.42 christos return error; 683 1.42 christos error = copyout(&cp[1], &p->blue[i], 1); 684 1.42 christos if (error) 685 1.42 christos return error; 686 1.42 christos } 687 1.42 christos return (0); 688 1.1 abrown } 689 1.1 abrown 690 1.1 abrown /* Write the software shadow colormap */ 691 1.1 abrown static int 692 1.40 uwe cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 693 1.24 itojun { 694 1.42 christos u_int i, start, count; 695 1.42 christos u_char *cp; 696 1.42 christos u_char cmap[256][4]; 697 1.42 christos int error; 698 1.42 christos 699 1.42 christos start = p->index; 700 1.42 christos count = p->count; 701 1.42 christos if (start >= cmsize || count > cmsize - start) 702 1.42 christos return (EINVAL); 703 1.42 christos 704 1.42 christos memcpy(&cmap, &cm->cm_map, sizeof cmap); 705 1.42 christos for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) { 706 1.42 christos error = copyin(&p->red[i], &cp[3], 1); 707 1.42 christos if (error) 708 1.42 christos return error; 709 1.42 christos error = copyin(&p->green[i], &cp[2], 1); 710 1.42 christos if (error) 711 1.42 christos return error; 712 1.42 christos error = copyin(&p->blue[i], &cp[1], 1); 713 1.42 christos if (error) 714 1.42 christos return error; 715 1.42 christos cp[0] = 0; /* no alpha channel */ 716 1.42 christos } 717 1.42 christos memcpy(&cm->cm_map, &cmap, sizeof cmap); 718 1.42 christos return (0); 719 1.1 abrown } 720 1.1 abrown 721 1.1 abrown static void 722 1.40 uwe cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors) 723 1.1 abrown { 724 1.1 abrown /* XXX switch to auto-increment, and on retrace intr */ 725 1.40 uwe 726 1.1 abrown /* Setup pointers to source and dest */ 727 1.40 uwe uint32_t *colp = &sc->sc_cmap.cm_chip[start]; 728 1.40 uwe volatile uint32_t *lutp = &sc->sc_clut1->clut_lut[start]; 729 1.1 abrown 730 1.1 abrown /* Copy by words */ 731 1.1 abrown while (--ncolors >= 0) 732 1.1 abrown *lutp++ = *colp++; 733 1.1 abrown } 734 1.49 macallan 735 1.49 macallan static void 736 1.49 macallan cg14_setup_wsdisplay(struct cgfourteen_softc *sc, int is_cons) 737 1.49 macallan { 738 1.49 macallan struct wsemuldisplaydev_attach_args aa; 739 1.49 macallan struct rasops_info *ri; 740 1.49 macallan long defattr; 741 1.49 macallan 742 1.49 macallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 743 1.49 macallan "default", 744 1.49 macallan 0, 0, 745 1.49 macallan NULL, 746 1.49 macallan 8, 16, 747 1.84 macallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 748 1.84 macallan WSSCREEN_RESIZE, 749 1.49 macallan NULL 750 1.49 macallan }; 751 1.98 macallan 752 1.78 macallan cg14_set_depth(sc, 8); 753 1.98 macallan 754 1.49 macallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 755 1.49 macallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 756 1.49 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 757 1.49 macallan vcons_init(&sc->sc_vd, sc, &sc->sc_defaultscreen_descr, 758 1.49 macallan &cg14_accessops); 759 1.49 macallan sc->sc_vd.init_screen = cg14_init_screen; 760 1.84 macallan sc->sc_vd.show_screen_cookie = &sc->sc_gc; 761 1.84 macallan sc->sc_vd.show_screen_cb = glyphcache_adapt; 762 1.49 macallan 763 1.49 macallan ri = &sc->sc_console_screen.scr_ri; 764 1.49 macallan 765 1.80 macallan sc->sc_gc.gc_bitblt = cg14_bitblt_gc; 766 1.80 macallan sc->sc_gc.gc_blitcookie = sc; 767 1.83 macallan sc->sc_gc.gc_rectfill = cg14_rectfill_a; 768 1.80 macallan sc->sc_gc.gc_rop = 0xc; 769 1.87 macallan 770 1.98 macallan vcons_init_screen(&sc->sc_vd, &sc->sc_console_screen, 1, 771 1.98 macallan &defattr); 772 1.98 macallan 773 1.98 macallan /* clear the screen with the default background colour */ 774 1.98 macallan if (sc->sc_sx != NULL) { 775 1.98 macallan cg14_rectfill(sc, 0, 0, ri->ri_width, ri->ri_height, 776 1.98 macallan ri->ri_devcmap[(defattr >> 16) & 0xf]); 777 1.98 macallan } else { 778 1.98 macallan memset(sc->sc_fb.fb_pixels, 779 1.98 macallan ri->ri_devcmap[(defattr >> 16) & 0xf], 780 1.98 macallan ri->ri_stride * ri->ri_height); 781 1.98 macallan } 782 1.98 macallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 783 1.98 macallan 784 1.98 macallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 785 1.98 macallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 786 1.98 macallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 787 1.98 macallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 788 1.98 macallan glyphcache_init_align(&sc->sc_gc, sc->sc_fb.fb_type.fb_height + 5, 789 1.98 macallan (sc->sc_vramsize / sc->sc_fb.fb_type.fb_width) - 790 1.98 macallan sc->sc_fb.fb_type.fb_height - 5, 791 1.98 macallan sc->sc_fb.fb_type.fb_width, 792 1.98 macallan ri->ri_font->fontwidth, 793 1.98 macallan ri->ri_font->fontheight, 794 1.98 macallan defattr, 4); 795 1.55 macallan 796 1.87 macallan if (is_cons) { 797 1.49 macallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 798 1.49 macallan defattr); 799 1.62 macallan vcons_replay_msgbuf(&sc->sc_console_screen); 800 1.49 macallan } 801 1.49 macallan 802 1.49 macallan aa.console = is_cons; 803 1.49 macallan aa.scrdata = &sc->sc_screenlist; 804 1.49 macallan aa.accessops = &cg14_accessops; 805 1.49 macallan aa.accesscookie = &sc->sc_vd; 806 1.49 macallan 807 1.90 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 808 1.98 macallan 809 1.98 macallan /* 810 1.98 macallan * do this here since any output through firmware calls will mess 811 1.98 macallan * with XLUT settings 812 1.98 macallan */ 813 1.98 macallan cg14_init_cmap(sc); 814 1.49 macallan } 815 1.49 macallan 816 1.49 macallan static void 817 1.49 macallan cg14_init_cmap(struct cgfourteen_softc *sc) 818 1.49 macallan { 819 1.80 macallan struct rasops_info *ri = &sc->sc_console_screen.scr_ri; 820 1.49 macallan int i, j = 0; 821 1.99 macallan uint32_t r, g, b, c, cc; 822 1.80 macallan uint8_t cmap[768]; 823 1.80 macallan 824 1.98 macallan if (sc->sc_depth == 16) { 825 1.98 macallan /* construct an R5G6B5 palette in CLUT1/2 */ 826 1.98 macallan for (i = 0; i < 0x100; i++) { 827 1.98 macallan /* upper byte first */ 828 1.98 macallan r = (i & 0xf8); /* red component */ 829 1.98 macallan r |= r >> 5; /* fill lower bits so 0xf8 */ 830 1.98 macallan c = 0x40000000 | r; /* becomes 0xff */ 831 1.98 macallan g = i & 0x7; /* upper 3 bits of green */ 832 1.99 macallan g |= g << 3; /* 0x003f */ 833 1.98 macallan c |= ((g << 10) & 0xf000); /* make it 4 */ 834 1.98 macallan sc->sc_clut1->clut_lut[i] = c; 835 1.98 macallan /* lower byte */ 836 1.98 macallan g = i & 0xe0; /* lower half of green */ 837 1.98 macallan g |= g >> 3; 838 1.99 macallan cc = 0x40000000 | ((g << 4) & 0x0f00); 839 1.98 macallan b = i & 0x1f; /* and blue */ 840 1.98 macallan b = (b << 3) | (b >> 2); 841 1.99 macallan cc |= (b << 16); 842 1.99 macallan sc->sc_clut2->clut_lut[i] = cc; 843 1.98 macallan } 844 1.98 macallan 845 1.98 macallan /* 846 1.98 macallan * because we alpha blend our components everything is half 847 1.98 macallan * intensity, fix that with the gamma LUT 848 1.98 macallan */ 849 1.98 macallan 850 1.98 macallan sc->sc_dac->dac_mode &= ~6; /* 8bit mode, for simlicity */ 851 1.98 macallan for (i = 0; i < 128; i++) { 852 1.98 macallan sc->sc_dac->dac_addr = i; 853 1.98 macallan sc->sc_dac->dac_gammalut = i << 1; 854 1.98 macallan sc->sc_dac->dac_gammalut = i << 1; 855 1.98 macallan sc->sc_dac->dac_gammalut = i << 1; 856 1.98 macallan } 857 1.98 macallan 858 1.98 macallan /* finally fill the XLUT */ 859 1.98 macallan for (i = 0; i < 256; i++) 860 1.98 macallan sc->sc_xlut->xlut_lut[i] = 861 1.98 macallan CG14_LEFT_CLUT2 | CG14_LEFT_B | 862 1.98 macallan CG14_RIGHT_CLUT1 | CG14_RIGHT_X; 863 1.98 macallan } else { 864 1.98 macallan /* in 8 or 24bit put a linear ramp in the gamma LUT */ 865 1.98 macallan sc->sc_dac->dac_mode &= ~6; /* 8bit mode, for simlicity */ 866 1.98 macallan for (i = 0; i < 256; i++) { 867 1.98 macallan sc->sc_dac->dac_addr = i; 868 1.98 macallan sc->sc_dac->dac_gammalut = i; 869 1.98 macallan sc->sc_dac->dac_gammalut = i; 870 1.98 macallan sc->sc_dac->dac_gammalut = i; 871 1.98 macallan } 872 1.98 macallan 873 1.98 macallan /* and zero the XLUT */ 874 1.98 macallan for (i = 0; i < 256; i++) 875 1.98 macallan sc->sc_xlut->xlut_lut[i] = 0; 876 1.98 macallan 877 1.98 macallan if (sc->sc_depth == 8) { 878 1.98 macallan rasops_get_cmap(ri, cmap, sizeof(cmap)); 879 1.98 macallan 880 1.98 macallan for (i = 0; i < 256; i++) { 881 1.98 macallan sc->sc_cmap.cm_map[i][3] = cmap[j]; 882 1.98 macallan sc->sc_cmap.cm_map[i][2] = cmap[j + 1]; 883 1.98 macallan sc->sc_cmap.cm_map[i][1] = cmap[j + 2]; 884 1.98 macallan j += 3; 885 1.98 macallan } 886 1.98 macallan cg14_load_hwcmap(sc, 0, 256); 887 1.98 macallan } 888 1.49 macallan } 889 1.49 macallan } 890 1.49 macallan 891 1.49 macallan static int 892 1.49 macallan cg14_putcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 893 1.49 macallan { 894 1.49 macallan u_int index = cm->index; 895 1.49 macallan u_int count = cm->count; 896 1.49 macallan int i, error; 897 1.49 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 898 1.49 macallan 899 1.49 macallan if (cm->index >= 256 || cm->count > 256 || 900 1.49 macallan (cm->index + cm->count) > 256) 901 1.49 macallan return EINVAL; 902 1.49 macallan error = copyin(cm->red, &rbuf[index], count); 903 1.49 macallan if (error) 904 1.49 macallan return error; 905 1.49 macallan error = copyin(cm->green, &gbuf[index], count); 906 1.49 macallan if (error) 907 1.49 macallan return error; 908 1.49 macallan error = copyin(cm->blue, &bbuf[index], count); 909 1.49 macallan if (error) 910 1.49 macallan return error; 911 1.49 macallan 912 1.49 macallan for (i = 0; i < count; i++) { 913 1.49 macallan sc->sc_cmap.cm_map[index][3] = rbuf[index]; 914 1.49 macallan sc->sc_cmap.cm_map[index][2] = gbuf[index]; 915 1.49 macallan sc->sc_cmap.cm_map[index][1] = bbuf[index]; 916 1.49 macallan 917 1.49 macallan index++; 918 1.49 macallan } 919 1.99 macallan 920 1.99 macallan if (sc->sc_depth == 8) 921 1.99 macallan cg14_load_hwcmap(sc, 0, 256); 922 1.99 macallan 923 1.49 macallan return 0; 924 1.49 macallan } 925 1.49 macallan 926 1.49 macallan static int 927 1.49 macallan cg14_getcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 928 1.49 macallan { 929 1.49 macallan uint8_t rbuf[256], gbuf[256], bbuf[256]; 930 1.49 macallan u_int index = cm->index; 931 1.49 macallan u_int count = cm->count; 932 1.49 macallan int error, i; 933 1.49 macallan 934 1.49 macallan if (index >= 255 || count > 256 || index + count > 256) 935 1.49 macallan return EINVAL; 936 1.49 macallan 937 1.49 macallan 938 1.49 macallan for (i = 0; i < count; i++) { 939 1.49 macallan rbuf[i] = sc->sc_cmap.cm_map[index][3]; 940 1.49 macallan gbuf[i] = sc->sc_cmap.cm_map[index][2]; 941 1.49 macallan bbuf[i] = sc->sc_cmap.cm_map[index][1]; 942 1.49 macallan 943 1.49 macallan index++; 944 1.49 macallan } 945 1.49 macallan error = copyout(rbuf, cm->red, count); 946 1.49 macallan if (error) 947 1.49 macallan return error; 948 1.49 macallan error = copyout(gbuf, cm->green, count); 949 1.49 macallan if (error) 950 1.49 macallan return error; 951 1.49 macallan error = copyout(bbuf, cm->blue, count); 952 1.49 macallan if (error) 953 1.49 macallan return error; 954 1.49 macallan 955 1.49 macallan return 0; 956 1.49 macallan } 957 1.63 macallan 958 1.49 macallan static int 959 1.49 macallan cg14_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 960 1.49 macallan struct lwp *l) 961 1.49 macallan { 962 1.49 macallan struct vcons_data *vd = v; 963 1.49 macallan struct cgfourteen_softc *sc = vd->cookie; 964 1.49 macallan struct wsdisplay_fbinfo *wdf; 965 1.49 macallan struct vcons_screen *ms = vd->active; 966 1.49 macallan 967 1.49 macallan switch (cmd) { 968 1.49 macallan 969 1.49 macallan case WSDISPLAYIO_GTYPE: 970 1.49 macallan *(uint32_t *)data = WSDISPLAY_TYPE_SUNCG14; 971 1.49 macallan return 0; 972 1.49 macallan 973 1.49 macallan case WSDISPLAYIO_GINFO: 974 1.49 macallan wdf = (void *)data; 975 1.49 macallan wdf->height = ms->scr_ri.ri_height; 976 1.49 macallan wdf->width = ms->scr_ri.ri_width; 977 1.49 macallan wdf->depth = 32; 978 1.49 macallan wdf->cmsize = 256; 979 1.49 macallan return 0; 980 1.49 macallan 981 1.49 macallan case WSDISPLAYIO_GETCMAP: 982 1.49 macallan return cg14_getcmap(sc, 983 1.49 macallan (struct wsdisplay_cmap *)data); 984 1.49 macallan 985 1.49 macallan case WSDISPLAYIO_PUTCMAP: 986 1.49 macallan return cg14_putcmap(sc, 987 1.49 macallan (struct wsdisplay_cmap *)data); 988 1.49 macallan 989 1.49 macallan case WSDISPLAYIO_LINEBYTES: 990 1.55 macallan *(u_int *)data = ms->scr_ri.ri_stride << 2; 991 1.49 macallan return 0; 992 1.49 macallan 993 1.49 macallan case WSDISPLAYIO_SMODE: 994 1.49 macallan { 995 1.49 macallan int new_mode = *(int*)data; 996 1.49 macallan if (new_mode != sc->sc_mode) { 997 1.49 macallan sc->sc_mode = new_mode; 998 1.49 macallan if(new_mode == WSDISPLAYIO_MODE_EMUL) { 999 1.50 macallan bus_space_write_1(sc->sc_bustag, 1000 1.50 macallan sc->sc_regh, 1001 1.50 macallan CG14_CURSOR_CONTROL, 0); 1002 1.66 macallan 1003 1.49 macallan cg14_set_depth(sc, 8); 1004 1.49 macallan cg14_init_cmap(sc); 1005 1.82 macallan #if NSX > 0 1006 1.82 macallan if (sc->sc_sx) 1007 1.82 macallan glyphcache_wipe(&sc->sc_gc); 1008 1.82 macallan #endif 1009 1.49 macallan vcons_redraw_screen(ms); 1010 1.55 macallan } else { 1011 1.66 macallan 1012 1.49 macallan cg14_set_depth(sc, 32); 1013 1.98 macallan cg14_init_cmap(sc); 1014 1.55 macallan } 1015 1.49 macallan } 1016 1.49 macallan } 1017 1.49 macallan return 0; 1018 1.50 macallan case WSDISPLAYIO_SVIDEO: 1019 1.50 macallan cg14_set_video(sc, *(int *)data); 1020 1.50 macallan return 0; 1021 1.50 macallan case WSDISPLAYIO_GVIDEO: 1022 1.99 macallan *(int *)data = cg14_get_video(sc) ? 1023 1.50 macallan WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 1024 1.99 macallan return 0; 1025 1.50 macallan case WSDISPLAYIO_GCURPOS: 1026 1.50 macallan { 1027 1.50 macallan struct wsdisplay_curpos *cp = (void *)data; 1028 1.50 macallan 1029 1.50 macallan cp->x = sc->sc_cursor.cc_pos.x; 1030 1.50 macallan cp->y = sc->sc_cursor.cc_pos.y; 1031 1.50 macallan } 1032 1.50 macallan return 0; 1033 1.50 macallan case WSDISPLAYIO_SCURPOS: 1034 1.50 macallan { 1035 1.50 macallan struct wsdisplay_curpos *cp = (void *)data; 1036 1.50 macallan 1037 1.50 macallan cg14_move_cursor(sc, cp->x, cp->y); 1038 1.50 macallan } 1039 1.50 macallan return 0; 1040 1.50 macallan case WSDISPLAYIO_GCURMAX: 1041 1.50 macallan { 1042 1.50 macallan struct wsdisplay_curpos *cp = (void *)data; 1043 1.50 macallan 1044 1.50 macallan cp->x = 32; 1045 1.50 macallan cp->y = 32; 1046 1.50 macallan } 1047 1.50 macallan return 0; 1048 1.50 macallan case WSDISPLAYIO_SCURSOR: 1049 1.50 macallan { 1050 1.50 macallan struct wsdisplay_cursor *cursor = (void *)data; 1051 1.50 macallan 1052 1.50 macallan return cg14_do_cursor(sc, cursor); 1053 1.50 macallan } 1054 1.55 macallan case PCI_IOC_CFGREAD: 1055 1.55 macallan case PCI_IOC_CFGWRITE: 1056 1.55 macallan return EINVAL; 1057 1.55 macallan 1058 1.49 macallan } 1059 1.49 macallan return EPASSTHROUGH; 1060 1.49 macallan } 1061 1.49 macallan 1062 1.49 macallan static paddr_t 1063 1.49 macallan cg14_mmap(void *v, void *vs, off_t offset, int prot) 1064 1.49 macallan { 1065 1.49 macallan struct vcons_data *vd = v; 1066 1.49 macallan struct cgfourteen_softc *sc = vd->cookie; 1067 1.49 macallan 1068 1.49 macallan /* allow mmap()ing the full framebuffer, not just what we use */ 1069 1.49 macallan if (offset < sc->sc_vramsize) 1070 1.49 macallan return bus_space_mmap(sc->sc_bustag, 1071 1.49 macallan BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 1072 1.49 macallan sc->sc_physadr[CG14_PXL_IDX].sbr_offset), 1073 1.49 macallan offset + CG14_FB_CBGR, prot, BUS_SPACE_MAP_LINEAR); 1074 1.49 macallan 1075 1.49 macallan return -1; 1076 1.49 macallan } 1077 1.49 macallan 1078 1.49 macallan static void 1079 1.49 macallan cg14_init_screen(void *cookie, struct vcons_screen *scr, 1080 1.49 macallan int existing, long *defattr) 1081 1.49 macallan { 1082 1.49 macallan struct cgfourteen_softc *sc = cookie; 1083 1.49 macallan struct rasops_info *ri = &scr->scr_ri; 1084 1.49 macallan 1085 1.98 macallan ri->ri_depth = sc->sc_depth; 1086 1.49 macallan ri->ri_width = sc->sc_fb.fb_type.fb_width; 1087 1.49 macallan ri->ri_height = sc->sc_fb.fb_type.fb_height; 1088 1.98 macallan ri->ri_stride = ri->ri_width * (sc->sc_depth >> 3); 1089 1.49 macallan ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 1090 1.49 macallan 1091 1.65 macallan ri->ri_bits = (char *)sc->sc_fb.fb_pixels; 1092 1.84 macallan 1093 1.84 macallan scr->scr_flags |= VCONS_LOADFONT; 1094 1.70 macallan #if NSX > 0 1095 1.83 macallan ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 1096 1.80 macallan 1097 1.71 macallan /* 1098 1.71 macallan * unaligned copies with horizontal overlap are slow, so don't bother 1099 1.71 macallan * handling them in cg14_bitblt() and use putchar() instead 1100 1.71 macallan */ 1101 1.71 macallan if (sc->sc_sx != NULL) { 1102 1.71 macallan scr->scr_flags |= VCONS_NO_COPYCOLS; 1103 1.71 macallan } else 1104 1.70 macallan #endif 1105 1.84 macallan scr->scr_flags |= VCONS_DONT_READ; 1106 1.49 macallan 1107 1.49 macallan if (existing) { 1108 1.49 macallan ri->ri_flg |= RI_CLEAR; 1109 1.49 macallan } 1110 1.49 macallan 1111 1.67 macallan rasops_init(ri, 0, 0); 1112 1.84 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 1113 1.84 macallan WSSCREEN_RESIZE; 1114 1.49 macallan 1115 1.49 macallan rasops_reconfig(ri, 1116 1.49 macallan sc->sc_fb.fb_type.fb_height / ri->ri_font->fontheight, 1117 1.49 macallan sc->sc_fb.fb_type.fb_width / ri->ri_font->fontwidth); 1118 1.49 macallan 1119 1.49 macallan ri->ri_hw = scr; 1120 1.70 macallan #if NSX > 0 1121 1.98 macallan if ((sc->sc_sx != NULL) && (sc->sc_depth == 8)) { 1122 1.70 macallan ri->ri_ops.copyrows = cg14_copyrows; 1123 1.70 macallan ri->ri_ops.copycols = cg14_copycols; 1124 1.70 macallan ri->ri_ops.eraserows = cg14_eraserows; 1125 1.70 macallan ri->ri_ops.erasecols = cg14_erasecols; 1126 1.71 macallan ri->ri_ops.cursor = cg14_cursor; 1127 1.70 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 1128 1.70 macallan ri->ri_ops.putchar = cg14_putchar_aa; 1129 1.70 macallan } else 1130 1.70 macallan ri->ri_ops.putchar = cg14_putchar; 1131 1.70 macallan } 1132 1.70 macallan #endif /* NSX > 0 */ 1133 1.49 macallan } 1134 1.49 macallan 1135 1.49 macallan static void 1136 1.49 macallan cg14_set_depth(struct cgfourteen_softc *sc, int depth) 1137 1.49 macallan { 1138 1.49 macallan 1139 1.92 macallan /* init mask */ 1140 1.92 macallan if (sc->sc_sx != NULL) { 1141 1.92 macallan sc->sc_mask = 0xffffffff; 1142 1.92 macallan sx_write(sc->sc_sx, SX_QUEUED(R_MASK), sc->sc_mask); 1143 1.92 macallan } 1144 1.92 macallan 1145 1.49 macallan if (sc->sc_depth == depth) 1146 1.49 macallan return; 1147 1.66 macallan 1148 1.49 macallan switch (depth) { 1149 1.49 macallan case 8: 1150 1.49 macallan bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1151 1.49 macallan CG14_MCTL, CG14_MCTL_ENABLEVID | 1152 1.49 macallan CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL); 1153 1.49 macallan sc->sc_depth = 8; 1154 1.97 macallan break; 1155 1.97 macallan case 16: 1156 1.97 macallan bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1157 1.97 macallan CG14_MCTL, CG14_MCTL_ENABLEVID | 1158 1.97 macallan CG14_MCTL_PIXMODE_16 | CG14_MCTL_POWERCTL); 1159 1.97 macallan sc->sc_depth = 16; 1160 1.49 macallan break; 1161 1.49 macallan case 32: 1162 1.49 macallan bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1163 1.49 macallan CG14_MCTL, CG14_MCTL_ENABLEVID | 1164 1.49 macallan CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL); 1165 1.49 macallan sc->sc_depth = 32; 1166 1.49 macallan break; 1167 1.49 macallan default: 1168 1.49 macallan printf("%s: can't change to depth %d\n", 1169 1.53 macallan device_xname(sc->sc_dev), depth); 1170 1.97 macallan return; 1171 1.49 macallan } 1172 1.97 macallan 1173 1.49 macallan } 1174 1.50 macallan 1175 1.50 macallan static void 1176 1.50 macallan cg14_move_cursor(struct cgfourteen_softc *sc, int x, int y) 1177 1.50 macallan { 1178 1.50 macallan uint32_t pos; 1179 1.50 macallan 1180 1.50 macallan sc->sc_cursor.cc_pos.x = x; 1181 1.50 macallan sc->sc_cursor.cc_pos.y = y; 1182 1.50 macallan pos = ((sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x ) << 16) | 1183 1.50 macallan ((sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y ) & 0xffff); 1184 1.50 macallan bus_space_write_4(sc->sc_bustag, sc->sc_regh, CG14_CURSOR_X, pos); 1185 1.50 macallan } 1186 1.50 macallan 1187 1.50 macallan static int 1188 1.50 macallan cg14_do_cursor(struct cgfourteen_softc *sc, struct wsdisplay_cursor *cur) 1189 1.50 macallan { 1190 1.50 macallan if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1191 1.50 macallan 1192 1.50 macallan bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1193 1.50 macallan CG14_CURSOR_CONTROL, cur->enable ? CG14_CRSR_ENABLE : 0); 1194 1.50 macallan } 1195 1.50 macallan if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1196 1.50 macallan 1197 1.50 macallan sc->sc_cursor.cc_hot.x = cur->hot.x; 1198 1.50 macallan sc->sc_cursor.cc_hot.y = cur->hot.y; 1199 1.50 macallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1200 1.50 macallan } 1201 1.50 macallan if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1202 1.50 macallan 1203 1.50 macallan cg14_move_cursor(sc, cur->pos.x, cur->pos.y); 1204 1.50 macallan } 1205 1.50 macallan if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1206 1.50 macallan int i; 1207 1.50 macallan uint32_t val; 1208 1.85 macallan 1209 1.85 macallan if ((cur->cmap.index > 2) || (cur->cmap.count > 3) || 1210 1.85 macallan (cur->cmap.index + cur->cmap.count > 3)) 1211 1.85 macallan return EINVAL; 1212 1.85 macallan 1213 1.86 riastrad for (i = 0; i < uimin(cur->cmap.count, 3); i++) { 1214 1.50 macallan val = (cur->cmap.red[i] ) | 1215 1.50 macallan (cur->cmap.green[i] << 8) | 1216 1.50 macallan (cur->cmap.blue[i] << 16); 1217 1.50 macallan bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1218 1.50 macallan CG14_CURSOR_COLOR1 + ((i + cur->cmap.index) << 2), 1219 1.50 macallan val); 1220 1.50 macallan } 1221 1.50 macallan } 1222 1.50 macallan if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1223 1.50 macallan uint32_t buffer[32], latch, tmp; 1224 1.50 macallan int i; 1225 1.50 macallan 1226 1.55 macallan copyin(cur->mask, buffer, 128); 1227 1.50 macallan for (i = 0; i < 32; i++) { 1228 1.50 macallan latch = 0; 1229 1.50 macallan tmp = buffer[i] & 0x80808080; 1230 1.50 macallan latch |= tmp >> 7; 1231 1.50 macallan tmp = buffer[i] & 0x40404040; 1232 1.50 macallan latch |= tmp >> 5; 1233 1.50 macallan tmp = buffer[i] & 0x20202020; 1234 1.50 macallan latch |= tmp >> 3; 1235 1.50 macallan tmp = buffer[i] & 0x10101010; 1236 1.50 macallan latch |= tmp >> 1; 1237 1.50 macallan tmp = buffer[i] & 0x08080808; 1238 1.50 macallan latch |= tmp << 1; 1239 1.50 macallan tmp = buffer[i] & 0x04040404; 1240 1.50 macallan latch |= tmp << 3; 1241 1.50 macallan tmp = buffer[i] & 0x02020202; 1242 1.50 macallan latch |= tmp << 5; 1243 1.50 macallan tmp = buffer[i] & 0x01010101; 1244 1.50 macallan latch |= tmp << 7; 1245 1.50 macallan bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1246 1.50 macallan CG14_CURSOR_PLANE0 + (i << 2), latch); 1247 1.50 macallan } 1248 1.55 macallan copyin(cur->image, buffer, 128); 1249 1.50 macallan for (i = 0; i < 32; i++) { 1250 1.50 macallan latch = 0; 1251 1.50 macallan tmp = buffer[i] & 0x80808080; 1252 1.50 macallan latch |= tmp >> 7; 1253 1.50 macallan tmp = buffer[i] & 0x40404040; 1254 1.50 macallan latch |= tmp >> 5; 1255 1.50 macallan tmp = buffer[i] & 0x20202020; 1256 1.50 macallan latch |= tmp >> 3; 1257 1.50 macallan tmp = buffer[i] & 0x10101010; 1258 1.50 macallan latch |= tmp >> 1; 1259 1.50 macallan tmp = buffer[i] & 0x08080808; 1260 1.50 macallan latch |= tmp << 1; 1261 1.50 macallan tmp = buffer[i] & 0x04040404; 1262 1.50 macallan latch |= tmp << 3; 1263 1.50 macallan tmp = buffer[i] & 0x02020202; 1264 1.50 macallan latch |= tmp << 5; 1265 1.50 macallan tmp = buffer[i] & 0x01010101; 1266 1.50 macallan latch |= tmp << 7; 1267 1.50 macallan bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1268 1.50 macallan CG14_CURSOR_PLANE1 + (i << 2), latch); 1269 1.50 macallan } 1270 1.50 macallan } 1271 1.50 macallan return 0; 1272 1.50 macallan } 1273 1.70 macallan 1274 1.70 macallan #if NSX > 0 1275 1.70 macallan 1276 1.70 macallan static void 1277 1.70 macallan cg14_wait_idle(struct cgfourteen_softc *sc) 1278 1.70 macallan { 1279 1.70 macallan } 1280 1.70 macallan 1281 1.70 macallan static void 1282 1.70 macallan cg14_rectfill(struct cgfourteen_softc *sc, int x, int y, int wi, int he, 1283 1.70 macallan uint32_t colour) 1284 1.70 macallan { 1285 1.70 macallan uint32_t addr, pptr; 1286 1.71 macallan int line, cnt, pre, words; 1287 1.70 macallan int stride = sc->sc_fb.fb_type.fb_width; 1288 1.70 macallan 1289 1.70 macallan addr = sc->sc_fb_paddr + x + stride * y; 1290 1.70 macallan sx_write(sc->sc_sx, SX_QUEUED(8), colour); 1291 1.70 macallan sx_write(sc->sc_sx, SX_QUEUED(9), colour); 1292 1.71 macallan /* 1293 1.71 macallan * Calculate the number of pixels we need to do one by one 1294 1.71 macallan * until we're 32bit aligned, then do the rest in 32bit 1295 1.71 macallan * mode. Assumes that stride is always a multiple of 4. 1296 1.71 macallan */ 1297 1.73 macallan /* TODO: use 32bit writes with byte mask instead */ 1298 1.71 macallan pre = addr & 3; 1299 1.71 macallan if (pre != 0) pre = 4 - pre; 1300 1.70 macallan for (line = 0; line < he; line++) { 1301 1.70 macallan pptr = addr; 1302 1.70 macallan cnt = wi; 1303 1.71 macallan if (pre) { 1304 1.94 macallan sxm(SX_STBS, pptr, 8, pre - 1); 1305 1.71 macallan pptr += pre; 1306 1.71 macallan cnt -= pre; 1307 1.70 macallan } 1308 1.71 macallan /* now do the aligned pixels in 32bit chunks */ 1309 1.83 macallan while(cnt > 3) { 1310 1.86 riastrad words = uimin(32, cnt >> 2); 1311 1.94 macallan sxm(SX_STS, pptr, 8, words - 1); 1312 1.71 macallan pptr += words << 2; 1313 1.71 macallan cnt -= words << 2; 1314 1.71 macallan } 1315 1.71 macallan /* do any remaining pixels byte-wise again */ 1316 1.70 macallan if (cnt > 0) 1317 1.94 macallan sxm(SX_STBS, pptr, 8, cnt - 1); 1318 1.70 macallan addr += stride; 1319 1.70 macallan } 1320 1.71 macallan } 1321 1.71 macallan 1322 1.71 macallan static void 1323 1.83 macallan cg14_rectfill_a(void *cookie, int dstx, int dsty, 1324 1.83 macallan int width, int height, long attr) 1325 1.83 macallan { 1326 1.83 macallan struct cgfourteen_softc *sc = cookie; 1327 1.83 macallan 1328 1.83 macallan cg14_rectfill(sc, dstx, dsty, width, height, 1329 1.83 macallan sc->sc_vd.active->scr_ri.ri_devcmap[(attr >> 24 & 0xf)]); 1330 1.83 macallan } 1331 1.83 macallan 1332 1.92 macallan static inline void 1333 1.92 macallan cg14_set_mask(struct cgfourteen_softc *sc, uint32_t mask) 1334 1.92 macallan { 1335 1.92 macallan if (mask == sc->sc_mask) return; 1336 1.92 macallan sc->sc_mask = mask; 1337 1.92 macallan sx_write(sc->sc_sx, SX_QUEUED(R_MASK), mask); 1338 1.92 macallan } 1339 1.91 macallan /* 1340 1.91 macallan * invert a rectangle, used only to (un)draw the cursor. 1341 1.91 macallan * - does a scanline at a time 1342 1.91 macallan * - does not handle wi > 64 or wi < 4, not that we need it for our fonts 1343 1.91 macallan * - uses all 32bit accesses 1344 1.91 macallan */ 1345 1.83 macallan static void 1346 1.71 macallan cg14_invert(struct cgfourteen_softc *sc, int x, int y, int wi, int he) 1347 1.71 macallan { 1348 1.91 macallan uint32_t addr, pptr, lmask, rmask; 1349 1.91 macallan int line, cnt, pre, words, pwrds = 0, post, reg; 1350 1.71 macallan int stride = sc->sc_fb.fb_type.fb_width; 1351 1.71 macallan 1352 1.91 macallan addr = (sc->sc_fb_paddr + x + stride * y) & ~3; 1353 1.91 macallan sx_write(sc->sc_sx, SX_ROP_CONTROL, 0x3C); /* ~src a / src a */ 1354 1.71 macallan /* 1355 1.91 macallan * Calculate the number of pixels we need to mask on each end of the 1356 1.91 macallan * scanline and how many we can do without mask, if any 1357 1.91 macallan */ 1358 1.91 macallan pre = x & 3; 1359 1.91 macallan if (pre != 0) { 1360 1.91 macallan lmask = 0xffffffff >> pre; 1361 1.91 macallan pre = 4 - pre; 1362 1.91 macallan pwrds++; 1363 1.91 macallan } 1364 1.91 macallan post = (x + wi) & 3; 1365 1.91 macallan if (post != 0) { 1366 1.91 macallan rmask = ~(0xffffffff >> post); 1367 1.91 macallan pwrds++; 1368 1.91 macallan } 1369 1.91 macallan words = (wi + pre + 3) >> 2; 1370 1.91 macallan cnt = words - pwrds; 1371 1.92 macallan 1372 1.71 macallan for (line = 0; line < he; line++) { 1373 1.71 macallan pptr = addr; 1374 1.91 macallan /* load a whole scanline */ 1375 1.94 macallan sxm(SX_LD, pptr, 8, words - 1); 1376 1.91 macallan reg = 8; 1377 1.71 macallan if (pre) { 1378 1.92 macallan cg14_set_mask(sc, lmask); 1379 1.94 macallan sxi(SX_ROPB, 8, 8, 40, 0); 1380 1.91 macallan reg++; 1381 1.71 macallan } 1382 1.91 macallan if (cnt > 0) { 1383 1.92 macallan cg14_set_mask(sc, 0xffffffff); 1384 1.91 macallan /* XXX handle cnt > 16 */ 1385 1.94 macallan sxi(SX_ROP, reg, reg, reg + 32, cnt - 1); 1386 1.91 macallan reg += cnt; 1387 1.71 macallan } 1388 1.91 macallan if (post) { 1389 1.92 macallan cg14_set_mask(sc, rmask); 1390 1.94 macallan sxi(SX_ROPB, reg, 7, reg + 32, 0); 1391 1.91 macallan reg++; 1392 1.91 macallan } 1393 1.94 macallan sxm(SX_ST, pptr, 40, words - 1); 1394 1.71 macallan addr += stride; 1395 1.71 macallan } 1396 1.71 macallan } 1397 1.71 macallan 1398 1.71 macallan static inline void 1399 1.71 macallan cg14_slurp(int reg, uint32_t addr, int cnt) 1400 1.71 macallan { 1401 1.71 macallan int num; 1402 1.71 macallan while (cnt > 0) { 1403 1.86 riastrad num = uimin(32, cnt); 1404 1.94 macallan sxm(SX_LD, addr, reg, num - 1); 1405 1.71 macallan cnt -= num; 1406 1.71 macallan reg += num; 1407 1.71 macallan addr += (num << 2); 1408 1.71 macallan } 1409 1.71 macallan } 1410 1.71 macallan 1411 1.71 macallan static inline void 1412 1.71 macallan cg14_spit(int reg, uint32_t addr, int cnt) 1413 1.71 macallan { 1414 1.71 macallan int num; 1415 1.71 macallan while (cnt > 0) { 1416 1.86 riastrad num = uimin(32, cnt); 1417 1.94 macallan sxm(SX_ST, addr, reg, num - 1); 1418 1.71 macallan cnt -= num; 1419 1.71 macallan reg += num; 1420 1.71 macallan addr += (num << 2); 1421 1.71 macallan } 1422 1.70 macallan } 1423 1.70 macallan 1424 1.70 macallan static void 1425 1.70 macallan cg14_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1426 1.70 macallan int wi, int he, int rop) 1427 1.70 macallan { 1428 1.70 macallan struct cgfourteen_softc *sc = cookie; 1429 1.70 macallan uint32_t saddr, daddr, sptr, dptr; 1430 1.70 macallan int line, cnt, stride = sc->sc_fb.fb_type.fb_width; 1431 1.71 macallan int num, words, skip; 1432 1.71 macallan 1433 1.71 macallan if (ys < yd) { 1434 1.71 macallan /* need to go bottom-up */ 1435 1.71 macallan saddr = sc->sc_fb_paddr + xs + stride * (ys + he - 1); 1436 1.71 macallan daddr = sc->sc_fb_paddr + xd + stride * (yd + he - 1); 1437 1.71 macallan skip = -stride; 1438 1.71 macallan } else { 1439 1.71 macallan saddr = sc->sc_fb_paddr + xs + stride * ys; 1440 1.71 macallan daddr = sc->sc_fb_paddr + xd + stride * yd; 1441 1.71 macallan skip = stride; 1442 1.71 macallan } 1443 1.70 macallan 1444 1.70 macallan if ((saddr & 3) == (daddr & 3)) { 1445 1.70 macallan int pre = saddr & 3; /* pixels to copy byte-wise */ 1446 1.70 macallan if (pre != 0) pre = 4 - pre; 1447 1.70 macallan for (line = 0; line < he; line++) { 1448 1.70 macallan sptr = saddr; 1449 1.70 macallan dptr = daddr; 1450 1.70 macallan cnt = wi; 1451 1.70 macallan if (pre > 0) { 1452 1.94 macallan sxm(SX_LDB, sptr, 32, pre - 1); 1453 1.94 macallan sxm(SX_STB, dptr, 32, pre - 1); 1454 1.70 macallan cnt -= pre; 1455 1.70 macallan sptr += pre; 1456 1.70 macallan dptr += pre; 1457 1.70 macallan } 1458 1.71 macallan words = cnt >> 2; 1459 1.71 macallan while(cnt > 3) { 1460 1.86 riastrad num = uimin(120, words); 1461 1.71 macallan cg14_slurp(8, sptr, num); 1462 1.71 macallan cg14_spit(8, dptr, num); 1463 1.71 macallan sptr += num << 2; 1464 1.71 macallan dptr += num << 2; 1465 1.71 macallan cnt -= num << 2; 1466 1.70 macallan } 1467 1.70 macallan if (cnt > 0) { 1468 1.94 macallan sxm(SX_LDB, sptr, 32, cnt - 1); 1469 1.94 macallan sxm(SX_STB, dptr, 32, cnt - 1); 1470 1.70 macallan } 1471 1.71 macallan saddr += skip; 1472 1.71 macallan daddr += skip; 1473 1.70 macallan } 1474 1.70 macallan } else { 1475 1.70 macallan /* unaligned, have to use byte mode */ 1476 1.73 macallan /* funnel shifter & byte mask trickery? */ 1477 1.70 macallan for (line = 0; line < he; line++) { 1478 1.70 macallan sptr = saddr; 1479 1.70 macallan dptr = daddr; 1480 1.70 macallan cnt = wi; 1481 1.71 macallan while(cnt > 31) { 1482 1.94 macallan sxm(SX_LDB, sptr, 32, 31); 1483 1.94 macallan sxm(SX_STB, dptr, 32, 31); 1484 1.70 macallan sptr += 32; 1485 1.70 macallan dptr += 32; 1486 1.70 macallan cnt -= 32; 1487 1.70 macallan } 1488 1.70 macallan if (cnt > 0) { 1489 1.94 macallan sxm(SX_LDB, sptr, 32, cnt - 1); 1490 1.94 macallan sxm(SX_STB, dptr, 32, cnt - 1); 1491 1.70 macallan } 1492 1.71 macallan saddr += skip; 1493 1.71 macallan daddr += skip; 1494 1.70 macallan } 1495 1.70 macallan } 1496 1.70 macallan } 1497 1.70 macallan 1498 1.80 macallan /* 1499 1.80 macallan * for copying glyphs around 1500 1.80 macallan * - uses all quads for reads 1501 1.80 macallan * - uses quads for writes as far as possible 1502 1.80 macallan * - limited by number of registers - won't do more than 120 wide 1503 1.80 macallan * - doesn't handle overlaps 1504 1.80 macallan */ 1505 1.80 macallan static void 1506 1.80 macallan cg14_bitblt_gc(void *cookie, int xs, int ys, int xd, int yd, 1507 1.80 macallan int wi, int he, int rop) 1508 1.80 macallan { 1509 1.80 macallan struct cgfourteen_softc *sc = cookie; 1510 1.80 macallan uint32_t saddr, daddr; 1511 1.80 macallan int line, cnt = wi, stride = sc->sc_fb.fb_type.fb_width; 1512 1.80 macallan int dreg = 8, swi = wi, dd; 1513 1.80 macallan int in = 0, q = 0, out = 0, r; 1514 1.80 macallan 1515 1.80 macallan saddr = sc->sc_fb_paddr + xs + stride * ys; 1516 1.80 macallan daddr = sc->sc_fb_paddr + xd + stride * yd; 1517 1.97 macallan 1518 1.80 macallan if (saddr & 3) { 1519 1.80 macallan swi += saddr & 3; 1520 1.80 macallan dreg += saddr & 3; 1521 1.80 macallan saddr &= ~3; 1522 1.80 macallan } 1523 1.80 macallan swi = (swi + 3) >> 2; /* round up, number of quads to read */ 1524 1.80 macallan 1525 1.80 macallan if (daddr & 3) { 1526 1.80 macallan in = 4 - (daddr & 3); /* pixels to write in byte mode */ 1527 1.80 macallan cnt -= in; 1528 1.80 macallan } 1529 1.80 macallan 1530 1.80 macallan q = cnt >> 2; 1531 1.80 macallan out = cnt & 3; 1532 1.80 macallan 1533 1.80 macallan for (line = 0; line < he; line++) { 1534 1.80 macallan /* read source line, in all quads */ 1535 1.94 macallan sxm(SX_LDUQ0, saddr, 8, swi - 1); 1536 1.80 macallan /* now write it out */ 1537 1.80 macallan dd = daddr; 1538 1.80 macallan r = dreg; 1539 1.80 macallan if (in > 0) { 1540 1.94 macallan sxm(SX_STB, dd, r, in - 1); 1541 1.80 macallan dd += in; 1542 1.80 macallan r += in; 1543 1.80 macallan } 1544 1.80 macallan if (q > 0) { 1545 1.94 macallan sxm(SX_STUQ0, dd, r, q - 1); 1546 1.80 macallan r += q << 2; 1547 1.80 macallan dd += q << 2; 1548 1.80 macallan } 1549 1.80 macallan if (out > 0) { 1550 1.94 macallan sxm(SX_STB, dd, r, out - 1); 1551 1.80 macallan } 1552 1.80 macallan saddr += stride; 1553 1.80 macallan daddr += stride; 1554 1.80 macallan } 1555 1.80 macallan } 1556 1.70 macallan 1557 1.70 macallan static void 1558 1.70 macallan cg14_putchar(void *cookie, int row, int col, u_int c, long attr) 1559 1.70 macallan { 1560 1.70 macallan struct rasops_info *ri = cookie; 1561 1.70 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1562 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1563 1.70 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1564 1.70 macallan void *data; 1565 1.70 macallan uint32_t fg, bg; 1566 1.70 macallan int i, x, y, wi, he; 1567 1.70 macallan uint32_t addr; 1568 1.70 macallan int stride = sc->sc_fb.fb_type.fb_width; 1569 1.70 macallan 1570 1.70 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1571 1.70 macallan return; 1572 1.70 macallan 1573 1.70 macallan if (!CHAR_IN_FONT(c, font)) 1574 1.70 macallan return; 1575 1.70 macallan 1576 1.93 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1577 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1578 1.93 macallan } 1579 1.93 macallan 1580 1.70 macallan wi = font->fontwidth; 1581 1.70 macallan he = font->fontheight; 1582 1.70 macallan 1583 1.70 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1584 1.70 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1585 1.70 macallan 1586 1.70 macallan x = ri->ri_xorigin + col * wi; 1587 1.70 macallan y = ri->ri_yorigin + row * he; 1588 1.70 macallan 1589 1.70 macallan if (c == 0x20) { 1590 1.70 macallan cg14_rectfill(sc, x, y, wi, he, bg); 1591 1.83 macallan if (attr & 1) 1592 1.83 macallan cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1593 1.70 macallan return; 1594 1.70 macallan } 1595 1.70 macallan 1596 1.83 macallan sx_write(sc->sc_sx, SX_QUEUED(8), bg); 1597 1.83 macallan sx_write(sc->sc_sx, SX_QUEUED(9), fg); 1598 1.83 macallan 1599 1.70 macallan data = WSFONT_GLYPH(c, font); 1600 1.70 macallan addr = sc->sc_fb_paddr + x + stride * y; 1601 1.70 macallan 1602 1.70 macallan switch (font->stride) { 1603 1.70 macallan case 1: { 1604 1.70 macallan uint8_t *data8 = data; 1605 1.70 macallan uint32_t reg; 1606 1.70 macallan for (i = 0; i < he; i++) { 1607 1.70 macallan reg = *data8; 1608 1.92 macallan cg14_set_mask(sc, reg << 24); 1609 1.94 macallan sxm(SX_STBS, addr, 8, wi - 1); 1610 1.70 macallan data8++; 1611 1.70 macallan addr += stride; 1612 1.70 macallan } 1613 1.70 macallan break; 1614 1.70 macallan } 1615 1.70 macallan case 2: { 1616 1.70 macallan uint16_t *data16 = data; 1617 1.70 macallan uint32_t reg; 1618 1.70 macallan for (i = 0; i < he; i++) { 1619 1.70 macallan reg = *data16; 1620 1.92 macallan cg14_set_mask(sc, reg << 16); 1621 1.94 macallan sxm(SX_STBS, addr, 8, wi - 1); 1622 1.70 macallan data16++; 1623 1.70 macallan addr += stride; 1624 1.70 macallan } 1625 1.70 macallan break; 1626 1.70 macallan } 1627 1.70 macallan } 1628 1.83 macallan if (attr & 1) 1629 1.83 macallan cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1630 1.70 macallan } 1631 1.70 macallan 1632 1.70 macallan static void 1633 1.93 macallan cg14_nuke_cursor(struct rasops_info *ri) 1634 1.93 macallan { 1635 1.93 macallan struct vcons_screen *scr = ri->ri_hw; 1636 1.93 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1637 1.93 macallan int wi, he, x, y; 1638 1.93 macallan 1639 1.93 macallan if (ri->ri_flg & RI_CURSOR) { 1640 1.93 macallan wi = ri->ri_font->fontwidth; 1641 1.93 macallan he = ri->ri_font->fontheight; 1642 1.93 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1643 1.93 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1644 1.93 macallan cg14_invert(sc, x, y, wi, he); 1645 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1646 1.93 macallan } 1647 1.93 macallan } 1648 1.93 macallan 1649 1.93 macallan static void 1650 1.71 macallan cg14_cursor(void *cookie, int on, int row, int col) 1651 1.70 macallan { 1652 1.70 macallan struct rasops_info *ri = cookie; 1653 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1654 1.71 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1655 1.70 macallan int x, y, wi, he; 1656 1.70 macallan 1657 1.70 macallan wi = ri->ri_font->fontwidth; 1658 1.70 macallan he = ri->ri_font->fontheight; 1659 1.70 macallan 1660 1.70 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1661 1.93 macallan if (on) { 1662 1.93 macallan if (ri->ri_flg & RI_CURSOR) { 1663 1.93 macallan cg14_nuke_cursor(ri); 1664 1.93 macallan } 1665 1.93 macallan x = col * wi + ri->ri_xorigin; 1666 1.93 macallan y = row * he + ri->ri_yorigin; 1667 1.71 macallan cg14_invert(sc, x, y, wi, he); 1668 1.93 macallan ri->ri_flg |= RI_CURSOR; 1669 1.70 macallan } 1670 1.70 macallan ri->ri_crow = row; 1671 1.70 macallan ri->ri_ccol = col; 1672 1.70 macallan } else { 1673 1.70 macallan scr->scr_ri.ri_crow = row; 1674 1.70 macallan scr->scr_ri.ri_ccol = col; 1675 1.70 macallan scr->scr_ri.ri_flg &= ~RI_CURSOR; 1676 1.70 macallan } 1677 1.70 macallan 1678 1.70 macallan } 1679 1.70 macallan 1680 1.70 macallan static void 1681 1.80 macallan cg14_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1682 1.70 macallan { 1683 1.70 macallan struct rasops_info *ri = cookie; 1684 1.70 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1685 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1686 1.80 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1687 1.80 macallan int stride = sc->sc_fb.fb_type.fb_width; 1688 1.83 macallan uint32_t bg, fg, addr, bg8, fg8, pixel, in, q, next; 1689 1.80 macallan int i, j, x, y, wi, he, r, g, b, aval, cnt, reg; 1690 1.80 macallan int r1, g1, b1, r0, g0, b0, fgo, bgo, rv; 1691 1.70 macallan uint8_t *data8; 1692 1.70 macallan 1693 1.70 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1694 1.70 macallan return; 1695 1.70 macallan 1696 1.70 macallan if (!CHAR_IN_FONT(c, font)) 1697 1.70 macallan return; 1698 1.70 macallan 1699 1.93 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1700 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1701 1.93 macallan } 1702 1.93 macallan 1703 1.70 macallan wi = font->fontwidth; 1704 1.70 macallan he = font->fontheight; 1705 1.70 macallan 1706 1.70 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1707 1.83 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1708 1.70 macallan x = ri->ri_xorigin + col * wi; 1709 1.70 macallan y = ri->ri_yorigin + row * he; 1710 1.70 macallan if (c == 0x20) { 1711 1.80 macallan cg14_rectfill(sc, x, y, wi, he, bg); 1712 1.83 macallan if (attr & 1) 1713 1.83 macallan cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1714 1.70 macallan return; 1715 1.70 macallan } 1716 1.70 macallan 1717 1.70 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1718 1.70 macallan if (rv == GC_OK) 1719 1.70 macallan return; 1720 1.70 macallan 1721 1.80 macallan addr = sc->sc_fb_paddr + x + stride * y; 1722 1.70 macallan data8 = WSFONT_GLYPH(c, font); 1723 1.70 macallan 1724 1.70 macallan /* 1725 1.70 macallan * we need the RGB colours here, so get offsets into rasops_cmap 1726 1.70 macallan */ 1727 1.70 macallan fgo = ((attr >> 24) & 0xf) * 3; 1728 1.70 macallan bgo = ((attr >> 16) & 0xf) * 3; 1729 1.70 macallan 1730 1.70 macallan r0 = rasops_cmap[bgo]; 1731 1.70 macallan r1 = rasops_cmap[fgo]; 1732 1.70 macallan g0 = rasops_cmap[bgo + 1]; 1733 1.70 macallan g1 = rasops_cmap[fgo + 1]; 1734 1.70 macallan b0 = rasops_cmap[bgo + 2]; 1735 1.70 macallan b1 = rasops_cmap[fgo + 2]; 1736 1.70 macallan #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1737 1.70 macallan bg8 = R3G3B2(r0, g0, b0); 1738 1.70 macallan fg8 = R3G3B2(r1, g1, b1); 1739 1.70 macallan 1740 1.80 macallan for (i = 0; i < he; i++) { 1741 1.80 macallan /* calculate one line of pixels */ 1742 1.80 macallan for (j = 0; j < wi; j++) { 1743 1.80 macallan aval = *data8; 1744 1.80 macallan if (aval == 0) { 1745 1.80 macallan pixel = bg8; 1746 1.80 macallan } else if (aval == 255) { 1747 1.80 macallan pixel = fg8; 1748 1.80 macallan } else { 1749 1.80 macallan r = aval * r1 + (255 - aval) * r0; 1750 1.80 macallan g = aval * g1 + (255 - aval) * g0; 1751 1.80 macallan b = aval * b1 + (255 - aval) * b0; 1752 1.80 macallan pixel = ((r & 0xe000) >> 8) | 1753 1.80 macallan ((g & 0xe000) >> 11) | 1754 1.80 macallan ((b & 0xc000) >> 14); 1755 1.80 macallan } 1756 1.70 macallan /* 1757 1.80 macallan * stick them into SX registers and hope we never have 1758 1.80 macallan * to deal with fonts more than 120 pixels wide 1759 1.70 macallan */ 1760 1.80 macallan sx_write(sc->sc_sx, SX_QUEUED(j + 8), pixel); 1761 1.80 macallan data8++; 1762 1.80 macallan } 1763 1.80 macallan /* now write them into video memory */ 1764 1.80 macallan in = (addr & 3); 1765 1.80 macallan next = addr; 1766 1.80 macallan reg = 8; 1767 1.80 macallan cnt = wi; 1768 1.80 macallan if (in != 0) { 1769 1.80 macallan in = 4 - in; /* pixels to write until aligned */ 1770 1.94 macallan sxm(SX_STB, next, 8, in - 1); 1771 1.80 macallan next += in; 1772 1.80 macallan reg = 8 + in; 1773 1.80 macallan cnt -= in; 1774 1.80 macallan } 1775 1.80 macallan q = cnt >> 2; /* number of writes we can do in quads */ 1776 1.80 macallan if (q > 0) { 1777 1.94 macallan sxm(SX_STUQ0, next, reg, q - 1); 1778 1.80 macallan next += (q << 2); 1779 1.80 macallan cnt -= (q << 2); 1780 1.80 macallan reg += (q << 2); 1781 1.80 macallan } 1782 1.80 macallan if (cnt > 0) { 1783 1.94 macallan sxm(SX_STB, next, reg, cnt - 1); 1784 1.70 macallan } 1785 1.80 macallan 1786 1.80 macallan addr += stride; 1787 1.70 macallan } 1788 1.80 macallan 1789 1.70 macallan if (rv == GC_ADD) { 1790 1.70 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1791 1.83 macallan } else if (attr & 1) 1792 1.83 macallan cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1793 1.83 macallan 1794 1.70 macallan } 1795 1.70 macallan 1796 1.70 macallan static void 1797 1.70 macallan cg14_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1798 1.70 macallan { 1799 1.70 macallan struct rasops_info *ri = cookie; 1800 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1801 1.70 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1802 1.70 macallan int32_t xs, xd, y, width, height; 1803 1.70 macallan 1804 1.70 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1805 1.93 macallan if (ri->ri_crow == row && 1806 1.93 macallan (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && 1807 1.93 macallan (ri->ri_flg & RI_CURSOR)) { 1808 1.93 macallan cg14_nuke_cursor(ri); 1809 1.93 macallan } 1810 1.70 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1811 1.70 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1812 1.70 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1813 1.70 macallan width = ri->ri_font->fontwidth * ncols; 1814 1.70 macallan height = ri->ri_font->fontheight; 1815 1.70 macallan cg14_bitblt(sc, xs, y, xd, y, width, height, 0x0c); 1816 1.93 macallan if (ri->ri_crow == row && 1817 1.93 macallan (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) 1818 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1819 1.70 macallan } 1820 1.70 macallan } 1821 1.70 macallan 1822 1.70 macallan static void 1823 1.70 macallan cg14_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1824 1.70 macallan { 1825 1.70 macallan struct rasops_info *ri = cookie; 1826 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1827 1.70 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1828 1.70 macallan int32_t x, y, width, height, fg, bg, ul; 1829 1.70 macallan 1830 1.70 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1831 1.70 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1832 1.70 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1833 1.70 macallan width = ri->ri_font->fontwidth * ncols; 1834 1.70 macallan height = ri->ri_font->fontheight; 1835 1.70 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1836 1.93 macallan cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1837 1.93 macallan if (ri->ri_crow == row && 1838 1.93 macallan (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols))) 1839 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1840 1.70 macallan 1841 1.70 macallan } 1842 1.70 macallan } 1843 1.70 macallan 1844 1.70 macallan static void 1845 1.70 macallan cg14_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1846 1.70 macallan { 1847 1.70 macallan struct rasops_info *ri = cookie; 1848 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1849 1.70 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1850 1.70 macallan int32_t x, ys, yd, width, height; 1851 1.70 macallan 1852 1.70 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1853 1.93 macallan if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) && 1854 1.93 macallan (ri->ri_flg & RI_CURSOR)) { 1855 1.93 macallan cg14_nuke_cursor(ri); 1856 1.93 macallan } 1857 1.70 macallan x = ri->ri_xorigin; 1858 1.70 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1859 1.70 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1860 1.70 macallan width = ri->ri_emuwidth; 1861 1.70 macallan height = ri->ri_font->fontheight * nrows; 1862 1.70 macallan cg14_bitblt(sc, x, ys, x, yd, width, height, 0x0c); 1863 1.93 macallan if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 1864 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1865 1.70 macallan } 1866 1.70 macallan } 1867 1.70 macallan 1868 1.70 macallan static void 1869 1.70 macallan cg14_eraserows(void *cookie, int row, int nrows, long fillattr) 1870 1.70 macallan { 1871 1.70 macallan struct rasops_info *ri = cookie; 1872 1.70 macallan struct vcons_screen *scr = ri->ri_hw; 1873 1.70 macallan struct cgfourteen_softc *sc = scr->scr_cookie; 1874 1.70 macallan int32_t x, y, width, height, fg, bg, ul; 1875 1.70 macallan 1876 1.70 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1877 1.70 macallan x = ri->ri_xorigin; 1878 1.70 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1879 1.70 macallan width = ri->ri_emuwidth; 1880 1.70 macallan height = ri->ri_font->fontheight * nrows; 1881 1.70 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1882 1.70 macallan cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1883 1.93 macallan if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) 1884 1.93 macallan ri->ri_flg &= ~RI_CURSOR; 1885 1.70 macallan } 1886 1.70 macallan } 1887 1.70 macallan 1888 1.70 macallan #endif /* NSX > 0 */ 1889 1.70 macallan 1890