1 1.60 thorpej /* $NetBSD: igsfb.c,v 1.60 2021/08/07 16:19:12 thorpej Exp $ */ 2 1.1 uwe 3 1.1 uwe /* 4 1.8 uwe * Copyright (c) 2002, 2003 Valeriy E. Ushakov 5 1.1 uwe * All rights reserved. 6 1.1 uwe * 7 1.1 uwe * Redistribution and use in source and binary forms, with or without 8 1.1 uwe * modification, are permitted provided that the following conditions 9 1.1 uwe * are met: 10 1.1 uwe * 1. Redistributions of source code must retain the above copyright 11 1.1 uwe * notice, this list of conditions and the following disclaimer. 12 1.1 uwe * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 uwe * notice, this list of conditions and the following disclaimer in the 14 1.1 uwe * documentation and/or other materials provided with the distribution. 15 1.1 uwe * 3. The name of the author may not be used to endorse or promote products 16 1.1 uwe * derived from this software without specific prior written permission 17 1.1 uwe * 18 1.1 uwe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 uwe * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 uwe * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 uwe * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 uwe * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 uwe * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 uwe * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 uwe * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 uwe * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 uwe * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 uwe */ 29 1.1 uwe 30 1.1 uwe /* 31 1.4 uwe * Integraphics Systems IGA 168x and CyberPro series. 32 1.1 uwe */ 33 1.1 uwe #include <sys/cdefs.h> 34 1.60 thorpej __KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.60 2021/08/07 16:19:12 thorpej Exp $"); 35 1.1 uwe 36 1.1 uwe #include <sys/param.h> 37 1.1 uwe #include <sys/systm.h> 38 1.1 uwe #include <sys/kernel.h> 39 1.1 uwe #include <sys/device.h> 40 1.1 uwe #include <sys/malloc.h> 41 1.2 uwe #include <sys/ioctl.h> 42 1.1 uwe 43 1.43 ad #include <sys/bus.h> 44 1.1 uwe 45 1.1 uwe #include <dev/wscons/wsdisplayvar.h> 46 1.8 uwe #include <dev/wscons/wsconsio.h> 47 1.8 uwe #include <dev/wsfont/wsfont.h> 48 1.1 uwe #include <dev/rasops/rasops.h> 49 1.1 uwe 50 1.27 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 51 1.27 macallan 52 1.1 uwe #include <dev/ic/igsfbreg.h> 53 1.1 uwe #include <dev/ic/igsfbvar.h> 54 1.1 uwe 55 1.1 uwe 56 1.46 macallan struct igsfb_devconfig igsfb_console_dc = { 57 1.46 macallan .dc_mmap = NULL, 58 1.46 macallan .dc_modestring = "", 59 1.46 macallan }; 60 1.8 uwe 61 1.1 uwe /* 62 1.1 uwe * wsscreen 63 1.1 uwe */ 64 1.1 uwe 65 1.33 uwe /* filled from rasops_info in igsfb_init_wsdisplay */ 66 1.1 uwe static struct wsscreen_descr igsfb_stdscreen = { 67 1.33 uwe .name = "std", 68 1.1 uwe }; 69 1.1 uwe 70 1.1 uwe static const struct wsscreen_descr *_igsfb_scrlist[] = { 71 1.1 uwe &igsfb_stdscreen, 72 1.1 uwe }; 73 1.1 uwe 74 1.1 uwe static const struct wsscreen_list igsfb_screenlist = { 75 1.33 uwe .nscreens = sizeof(_igsfb_scrlist) / sizeof(_igsfb_scrlist[0]), 76 1.33 uwe .screens = _igsfb_scrlist, 77 1.1 uwe }; 78 1.1 uwe 79 1.1 uwe 80 1.1 uwe /* 81 1.1 uwe * wsdisplay_accessops 82 1.1 uwe */ 83 1.1 uwe 84 1.42 christos static int igsfb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 85 1.38 jmmv static paddr_t igsfb_mmap(void *, void *, off_t, int); 86 1.1 uwe 87 1.27 macallan static struct wsdisplay_accessops igsfb_accessops = { 88 1.33 uwe .ioctl = igsfb_ioctl, 89 1.33 uwe .mmap = igsfb_mmap, 90 1.1 uwe }; 91 1.1 uwe 92 1.1 uwe 93 1.1 uwe /* 94 1.11 uwe * acceleration 95 1.11 uwe */ 96 1.27 macallan static int igsfb_make_text_cursor(struct igsfb_devconfig *, 97 1.31 uwe struct vcons_screen *); 98 1.11 uwe static void igsfb_accel_cursor(void *, int, int, int); 99 1.11 uwe 100 1.12 uwe static int igsfb_accel_wait(struct igsfb_devconfig *); 101 1.12 uwe static void igsfb_accel_fill(struct igsfb_devconfig *, 102 1.19 uwe uint32_t, uint32_t, uint16_t, uint16_t); 103 1.12 uwe static void igsfb_accel_copy(struct igsfb_devconfig *, 104 1.19 uwe uint32_t, uint32_t, uint16_t, uint16_t); 105 1.12 uwe 106 1.12 uwe static void igsfb_accel_copycols(void *, int, int, int, int); 107 1.12 uwe static void igsfb_accel_erasecols(void *, int, int, int, long); 108 1.12 uwe static void igsfb_accel_copyrows(void *, int, int, int); 109 1.12 uwe static void igsfb_accel_eraserows(void *, int, int, long); 110 1.12 uwe static void igsfb_accel_putchar(void *, int, int, u_int, long); 111 1.12 uwe 112 1.11 uwe 113 1.11 uwe /* 114 1.1 uwe * internal functions 115 1.1 uwe */ 116 1.8 uwe static int igsfb_init_video(struct igsfb_devconfig *); 117 1.8 uwe static void igsfb_init_cmap(struct igsfb_devconfig *); 118 1.19 uwe static uint16_t igsfb_spread_bits_8(uint8_t); 119 1.10 uwe static void igsfb_init_bit_table(struct igsfb_devconfig *); 120 1.27 macallan static void igsfb_init_wsdisplay(void *, struct vcons_screen *, int, 121 1.31 uwe long *); 122 1.27 macallan 123 1.8 uwe 124 1.8 uwe static void igsfb_blank_screen(struct igsfb_devconfig *, int); 125 1.8 uwe static int igsfb_get_cmap(struct igsfb_devconfig *, 126 1.8 uwe struct wsdisplay_cmap *); 127 1.8 uwe static int igsfb_set_cmap(struct igsfb_devconfig *, 128 1.9 uwe const struct wsdisplay_cmap *); 129 1.8 uwe static void igsfb_update_cmap(struct igsfb_devconfig *, u_int, u_int); 130 1.8 uwe static void igsfb_set_curpos(struct igsfb_devconfig *, 131 1.9 uwe const struct wsdisplay_curpos *); 132 1.8 uwe static void igsfb_update_curpos(struct igsfb_devconfig *); 133 1.8 uwe static int igsfb_get_cursor(struct igsfb_devconfig *, 134 1.1 uwe struct wsdisplay_cursor *); 135 1.8 uwe static int igsfb_set_cursor(struct igsfb_devconfig *, 136 1.9 uwe const struct wsdisplay_cursor *); 137 1.8 uwe static void igsfb_update_cursor(struct igsfb_devconfig *, u_int); 138 1.8 uwe static void igsfb_convert_cursor_data(struct igsfb_devconfig *, 139 1.8 uwe u_int, u_int); 140 1.8 uwe 141 1.8 uwe 142 1.8 uwe int 143 1.36 uwe igsfb_cnattach_subr(struct igsfb_devconfig *dc) 144 1.8 uwe { 145 1.8 uwe struct rasops_info *ri; 146 1.8 uwe long defattr; 147 1.1 uwe 148 1.8 uwe KASSERT(dc == &igsfb_console_dc); 149 1.8 uwe 150 1.8 uwe igsfb_init_video(dc); 151 1.27 macallan dc->dc_vd.active = NULL; 152 1.27 macallan igsfb_init_wsdisplay(dc, &dc->dc_console, 1, &defattr); 153 1.1 uwe 154 1.27 macallan ri = &dc->dc_console.scr_ri; 155 1.27 macallan ri->ri_hw = &dc->dc_console; 156 1.27 macallan dc->dc_console.scr_cookie = dc; 157 1.37 uwe 158 1.8 uwe (*ri->ri_ops.allocattr)(ri, 159 1.27 macallan WS_DEFAULT_FG, /* fg */ 160 1.27 macallan WS_DEFAULT_BG, /* bg */ 161 1.8 uwe 0, /* wsattrs */ 162 1.8 uwe &defattr); 163 1.8 uwe 164 1.8 uwe wsdisplay_cnattach(&igsfb_stdscreen, 165 1.8 uwe ri, /* emulcookie */ 166 1.8 uwe 0, 0, /* cursor position */ 167 1.8 uwe defattr); 168 1.37 uwe return 0; 169 1.8 uwe } 170 1.1 uwe 171 1.1 uwe 172 1.1 uwe /* 173 1.1 uwe * Finish off the attach. Bus specific attach method should have 174 1.8 uwe * enabled io and memory accesses and mapped io (and cop?) registers. 175 1.1 uwe */ 176 1.1 uwe void 177 1.36 uwe igsfb_attach_subr(struct igsfb_softc *sc, int isconsole) 178 1.1 uwe { 179 1.8 uwe struct igsfb_devconfig *dc = sc->sc_dc; 180 1.8 uwe struct wsemuldisplaydev_attach_args waa; 181 1.27 macallan struct rasops_info *ri; 182 1.27 macallan long defattr; 183 1.8 uwe 184 1.8 uwe KASSERT(dc != NULL); 185 1.8 uwe 186 1.8 uwe if (!isconsole) { 187 1.8 uwe igsfb_init_video(dc); 188 1.8 uwe } 189 1.8 uwe 190 1.27 macallan vcons_init(&dc->dc_vd, dc, &igsfb_stdscreen, &igsfb_accessops); 191 1.27 macallan dc->dc_vd.init_screen = igsfb_init_wsdisplay; 192 1.37 uwe 193 1.27 macallan vcons_init_screen(&dc->dc_vd, &dc->dc_console, 1, &defattr); 194 1.27 macallan dc->dc_console.scr_flags |= VCONS_SCREEN_IS_STATIC; 195 1.37 uwe 196 1.53 msaitoh aprint_normal("%s: %dMB, %s%dx%d, %dbpp\n", 197 1.50 mrg device_xname(sc->sc_dev), 198 1.19 uwe (uint32_t)(dc->dc_vmemsz >> 20), 199 1.8 uwe (dc->dc_hwflags & IGSFB_HW_BSWAP) 200 1.8 uwe ? (dc->dc_hwflags & IGSFB_HW_BE_SELECT) 201 1.8 uwe ? "hardware bswap, " : "software bswap, " 202 1.8 uwe : "", 203 1.8 uwe dc->dc_width, dc->dc_height, dc->dc_depth); 204 1.53 msaitoh aprint_normal("%s: using %dbpp for X\n", device_xname(sc->sc_dev), 205 1.47 macallan dc->dc_maxdepth); 206 1.27 macallan ri = &dc->dc_console.scr_ri; 207 1.27 macallan ri->ri_ops.eraserows(ri, 0, ri->ri_rows, defattr); 208 1.27 macallan 209 1.46 macallan if (isconsole) 210 1.46 macallan vcons_replay_msgbuf(&dc->dc_console); 211 1.46 macallan 212 1.8 uwe /* attach wsdisplay */ 213 1.8 uwe waa.console = isconsole; 214 1.8 uwe waa.scrdata = &igsfb_screenlist; 215 1.8 uwe waa.accessops = &igsfb_accessops; 216 1.27 macallan waa.accesscookie = &dc->dc_vd; 217 1.8 uwe 218 1.60 thorpej config_found(sc->sc_dev, &waa, wsemuldisplaydevprint, CFARGS_NONE); 219 1.8 uwe } 220 1.8 uwe 221 1.8 uwe 222 1.8 uwe static int 223 1.36 uwe igsfb_init_video(struct igsfb_devconfig *dc) 224 1.8 uwe { 225 1.4 uwe bus_space_handle_t tmph; 226 1.19 uwe uint8_t *p; 227 1.4 uwe int need_bswap; 228 1.8 uwe bus_addr_t fbaddr, craddr; 229 1.1 uwe off_t croffset; 230 1.19 uwe uint8_t busctl, curctl; 231 1.41 cube void *va; 232 1.1 uwe 233 1.8 uwe /* Total amount of video memory. */ 234 1.8 uwe busctl = igs_ext_read(dc->dc_iot, dc->dc_ioh, IGS_EXT_BUS_CTL); 235 1.1 uwe if (busctl & 0x2) 236 1.8 uwe dc->dc_vmemsz = 4; 237 1.1 uwe else if (busctl & 0x1) 238 1.8 uwe dc->dc_vmemsz = 2; 239 1.1 uwe else 240 1.8 uwe dc->dc_vmemsz = 1; 241 1.8 uwe dc->dc_vmemsz <<= 20; /* megabytes -> bytes */ 242 1.4 uwe 243 1.4 uwe /* 244 1.8 uwe * Check for endianness mismatch by writing a word at the end of 245 1.8 uwe * the video memory (off-screen) and reading it back byte-by-byte. 246 1.4 uwe */ 247 1.8 uwe if (bus_space_map(dc->dc_memt, 248 1.19 uwe dc->dc_memaddr + dc->dc_vmemsz - sizeof(uint32_t), 249 1.19 uwe sizeof(uint32_t), 250 1.8 uwe dc->dc_memflags | BUS_SPACE_MAP_LINEAR, 251 1.4 uwe &tmph) != 0) 252 1.4 uwe { 253 1.4 uwe printf("unable to map video memory for endianness test\n"); 254 1.37 uwe return 1; 255 1.4 uwe } 256 1.4 uwe 257 1.8 uwe p = bus_space_vaddr(dc->dc_memt, tmph); 258 1.4 uwe #if BYTE_ORDER == BIG_ENDIAN 259 1.19 uwe *((uint32_t *)p) = 0x12345678; 260 1.4 uwe #else 261 1.19 uwe *((uint32_t *)p) = 0x78563412; 262 1.4 uwe #endif 263 1.4 uwe if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78) 264 1.4 uwe need_bswap = 0; 265 1.4 uwe else 266 1.4 uwe need_bswap = 1; 267 1.4 uwe 268 1.19 uwe bus_space_unmap(dc->dc_memt, tmph, sizeof(uint32_t)); 269 1.4 uwe 270 1.4 uwe /* 271 1.4 uwe * On CyberPro we can use magic bswap bit in linear address. 272 1.4 uwe */ 273 1.8 uwe fbaddr = dc->dc_memaddr; 274 1.8 uwe if (need_bswap) { 275 1.8 uwe dc->dc_hwflags |= IGSFB_HW_BSWAP; 276 1.8 uwe if (dc->dc_id >= 0x2000) { 277 1.8 uwe dc->dc_hwflags |= IGSFB_HW_BE_SELECT; 278 1.4 uwe fbaddr |= IGS_MEM_BE_SELECT; 279 1.4 uwe } 280 1.8 uwe } 281 1.8 uwe 282 1.55 jakllsch /* 283 1.55 jakllsch * Map graphic coprocessor for mode setting and accelerated rasops. 284 1.55 jakllsch */ 285 1.55 jakllsch if (dc->dc_id >= 0x2000) { /* XXX */ 286 1.55 jakllsch if (bus_space_map(dc->dc_iot, 287 1.55 jakllsch dc->dc_iobase + IGS_COP_BASE_B, IGS_COP_SIZE, 288 1.55 jakllsch dc->dc_ioflags, 289 1.55 jakllsch &dc->dc_coph) != 0) 290 1.55 jakllsch { 291 1.55 jakllsch printf("unable to map COP registers\n"); 292 1.55 jakllsch return 1; 293 1.55 jakllsch } 294 1.55 jakllsch } 295 1.55 jakllsch 296 1.8 uwe igsfb_hw_setup(dc); 297 1.8 uwe 298 1.1 uwe /* 299 1.8 uwe * Don't map in all N megs, just the amount we need for the wsscreen. 300 1.1 uwe */ 301 1.46 macallan dc->dc_fbsz = dc->dc_stride * dc->dc_height; 302 1.8 uwe if (bus_space_map(dc->dc_memt, fbaddr, dc->dc_fbsz, 303 1.8 uwe dc->dc_memflags | BUS_SPACE_MAP_LINEAR, 304 1.8 uwe &dc->dc_fbh) != 0) 305 1.1 uwe { 306 1.55 jakllsch if (dc->dc_id >= 0x2000) { /* XXX */ 307 1.55 jakllsch bus_space_unmap(dc->dc_iot, dc->dc_coph, IGS_COP_SIZE); 308 1.55 jakllsch } 309 1.8 uwe bus_space_unmap(dc->dc_iot, dc->dc_ioh, IGS_REG_SIZE); 310 1.1 uwe printf("unable to map framebuffer\n"); 311 1.37 uwe return 1; 312 1.1 uwe } 313 1.1 uwe 314 1.8 uwe igsfb_init_cmap(dc); 315 1.8 uwe 316 1.1 uwe /* 317 1.8 uwe * 1KB for cursor sprite data at the very end of the video memory. 318 1.1 uwe */ 319 1.8 uwe croffset = dc->dc_vmemsz - IGS_CURSOR_DATA_SIZE; 320 1.4 uwe craddr = fbaddr + croffset; 321 1.8 uwe if (bus_space_map(dc->dc_memt, craddr, IGS_CURSOR_DATA_SIZE, 322 1.8 uwe dc->dc_memflags | BUS_SPACE_MAP_LINEAR, 323 1.8 uwe &dc->dc_crh) != 0) 324 1.1 uwe { 325 1.55 jakllsch if (dc->dc_id >= 0x2000) { /* XXX */ 326 1.55 jakllsch bus_space_unmap(dc->dc_iot, dc->dc_coph, IGS_COP_SIZE); 327 1.55 jakllsch } 328 1.8 uwe bus_space_unmap(dc->dc_iot, dc->dc_ioh, IGS_REG_SIZE); 329 1.8 uwe bus_space_unmap(dc->dc_memt, dc->dc_fbh, dc->dc_fbsz); 330 1.1 uwe printf("unable to map cursor sprite region\n"); 331 1.37 uwe return 1; 332 1.1 uwe } 333 1.1 uwe 334 1.1 uwe /* 335 1.8 uwe * Tell the device where cursor sprite data are located in the 336 1.8 uwe * linear space (it takes data offset in 1KB units). 337 1.1 uwe */ 338 1.8 uwe croffset >>= 10; /* bytes -> kilobytes */ 339 1.8 uwe igs_ext_write(dc->dc_iot, dc->dc_ioh, 340 1.1 uwe IGS_EXT_SPRITE_DATA_LO, croffset & 0xff); 341 1.8 uwe igs_ext_write(dc->dc_iot, dc->dc_ioh, 342 1.1 uwe IGS_EXT_SPRITE_DATA_HI, (croffset >> 8) & 0xf); 343 1.1 uwe 344 1.10 uwe /* init the bit expansion table for cursor sprite data conversion */ 345 1.10 uwe igsfb_init_bit_table(dc); 346 1.8 uwe 347 1.8 uwe /* XXX: fill dc_cursor and use igsfb_update_cursor() instead? */ 348 1.8 uwe memset(&dc->dc_cursor, 0, sizeof(struct igs_hwcursor)); 349 1.41 cube va = bus_space_vaddr(dc->dc_memt, dc->dc_crh); 350 1.41 cube memset(va, /* transparent */ 0xaa, IGS_CURSOR_DATA_SIZE); 351 1.1 uwe 352 1.8 uwe curctl = igs_ext_read(dc->dc_iot, dc->dc_ioh, IGS_EXT_SPRITE_CTL); 353 1.1 uwe curctl |= IGS_EXT_SPRITE_64x64; 354 1.1 uwe curctl &= ~IGS_EXT_SPRITE_VISIBLE; 355 1.8 uwe igs_ext_write(dc->dc_iot, dc->dc_ioh, IGS_EXT_SPRITE_CTL, curctl); 356 1.8 uwe dc->dc_curenb = 0; 357 1.1 uwe 358 1.12 uwe /* 359 1.55 jakllsch * Init graphic coprocessor for accelerated rasops. 360 1.12 uwe */ 361 1.12 uwe if (dc->dc_id >= 0x2000) { /* XXX */ 362 1.12 uwe bus_space_write_2(dc->dc_iot, dc->dc_coph, 363 1.12 uwe IGS_COP_SRC_MAP_WIDTH_REG, 364 1.12 uwe dc->dc_width - 1); 365 1.12 uwe bus_space_write_2(dc->dc_iot, dc->dc_coph, 366 1.12 uwe IGS_COP_DST_MAP_WIDTH_REG, 367 1.12 uwe dc->dc_width - 1); 368 1.12 uwe 369 1.12 uwe bus_space_write_1(dc->dc_iot, dc->dc_coph, 370 1.12 uwe IGS_COP_MAP_FMT_REG, 371 1.56 jakllsch howmany(dc->dc_depth, NBBY) - 1); 372 1.12 uwe } 373 1.12 uwe 374 1.8 uwe /* make sure screen is not blanked */ 375 1.8 uwe dc->dc_blanked = 0; 376 1.8 uwe igsfb_blank_screen(dc, dc->dc_blanked); 377 1.1 uwe 378 1.37 uwe return 0; 379 1.1 uwe } 380 1.1 uwe 381 1.1 uwe 382 1.8 uwe static void 383 1.36 uwe igsfb_init_cmap(struct igsfb_devconfig *dc) 384 1.4 uwe { 385 1.8 uwe bus_space_tag_t iot = dc->dc_iot; 386 1.8 uwe bus_space_handle_t ioh = dc->dc_ioh; 387 1.19 uwe const uint8_t *p; 388 1.8 uwe int i; 389 1.4 uwe 390 1.8 uwe p = rasops_cmap; /* "ANSI" color map */ 391 1.4 uwe 392 1.8 uwe /* init software copy */ 393 1.8 uwe for (i = 0; i < IGS_CMAP_SIZE; ++i, p += 3) { 394 1.8 uwe dc->dc_cmap.r[i] = p[0]; 395 1.8 uwe dc->dc_cmap.g[i] = p[1]; 396 1.8 uwe dc->dc_cmap.b[i] = p[2]; 397 1.8 uwe } 398 1.4 uwe 399 1.8 uwe /* propagate to the device */ 400 1.8 uwe igsfb_update_cmap(dc, 0, IGS_CMAP_SIZE); 401 1.1 uwe 402 1.54 jakllsch /* set overscan color */ 403 1.54 jakllsch p = &rasops_cmap[WSDISPLAY_BORDER_COLOR * 3]; 404 1.54 jakllsch igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_RED, p[0]); 405 1.54 jakllsch igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_GREEN, p[1]); 406 1.54 jakllsch igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_BLUE, p[2]); 407 1.1 uwe } 408 1.1 uwe 409 1.8 uwe 410 1.1 uwe static void 411 1.27 macallan igsfb_init_wsdisplay(void *cookie, struct vcons_screen *scr, int existing, 412 1.36 uwe long *defattr) 413 1.1 uwe { 414 1.27 macallan struct igsfb_devconfig *dc = cookie; 415 1.27 macallan struct rasops_info *ri = &scr->scr_ri; 416 1.1 uwe int wsfcookie; 417 1.1 uwe 418 1.49 macallan if (scr == &dc->dc_console) { 419 1.49 macallan if (ri->ri_flg == 0) { 420 1.49 macallan /* first time, need to set RI_NO_AUTO */ 421 1.49 macallan ri->ri_flg |= RI_NO_AUTO; 422 1.49 macallan } else { 423 1.49 macallan /* clear it on 2nd run */ 424 1.49 macallan ri->ri_flg &= ~RI_NO_AUTO; 425 1.49 macallan } 426 1.49 macallan } 427 1.49 macallan ri->ri_flg |= RI_CENTER | RI_FULLCLEAR; 428 1.1 uwe 429 1.8 uwe if (IGSFB_HW_SOFT_BSWAP(dc)) 430 1.31 uwe ri->ri_flg |= RI_BSWAP; 431 1.1 uwe 432 1.8 uwe ri->ri_depth = dc->dc_depth; 433 1.8 uwe ri->ri_width = dc->dc_width; 434 1.8 uwe ri->ri_height = dc->dc_height; 435 1.35 uwe ri->ri_stride = dc->dc_stride; 436 1.34 uwe ri->ri_bits = bus_space_vaddr(dc->dc_memt, dc->dc_fbh); 437 1.1 uwe 438 1.1 uwe /* 439 1.1 uwe * Initialize wsfont related stuff. 440 1.1 uwe */ 441 1.1 uwe wsfont_init(); 442 1.1 uwe 443 1.1 uwe /* prefer gallant that is identical to the one the prom uses */ 444 1.1 uwe wsfcookie = wsfont_find("Gallant", 12, 22, 0, 445 1.1 uwe WSDISPLAY_FONTORDER_L2R, 446 1.52 macallan WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP); 447 1.1 uwe if (wsfcookie <= 0) { 448 1.1 uwe #ifdef DIAGNOSTIC 449 1.8 uwe printf("unable to find font Gallant 12x22\n"); 450 1.1 uwe #endif 451 1.8 uwe wsfcookie = wsfont_find(NULL, 0, 0, 0, /* any font at all? */ 452 1.1 uwe WSDISPLAY_FONTORDER_L2R, 453 1.52 macallan WSDISPLAY_FONTORDER_L2R, 454 1.52 macallan WSFONT_FIND_BITMAP); 455 1.1 uwe } 456 1.1 uwe 457 1.1 uwe if (wsfcookie <= 0) { 458 1.8 uwe printf("unable to find any fonts\n"); 459 1.1 uwe return; 460 1.1 uwe } 461 1.1 uwe 462 1.1 uwe if (wsfont_lock(wsfcookie, &ri->ri_font) != 0) { 463 1.8 uwe printf("unable to lock font\n"); 464 1.1 uwe return; 465 1.1 uwe } 466 1.1 uwe ri->ri_wsfcookie = wsfcookie; 467 1.1 uwe 468 1.1 uwe 469 1.11 uwe /* XXX: TODO: compute term size based on font dimensions? */ 470 1.51 macallan rasops_init(ri, 0, 0); 471 1.22 macallan rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 472 1.22 macallan ri->ri_width / ri->ri_font->fontwidth); 473 1.1 uwe 474 1.12 uwe 475 1.11 uwe /* use the sprite for the text mode cursor */ 476 1.27 macallan igsfb_make_text_cursor(dc, scr); 477 1.11 uwe 478 1.11 uwe /* the cursor is "busy" while we are in the text mode */ 479 1.11 uwe dc->dc_hwflags |= IGSFB_HW_TEXT_CURSOR; 480 1.11 uwe 481 1.11 uwe /* propagate sprite data to the device */ 482 1.11 uwe igsfb_update_cursor(dc, WSDISPLAY_CURSOR_DOSHAPE); 483 1.11 uwe 484 1.12 uwe /* accelerated text cursor */ 485 1.11 uwe ri->ri_ops.cursor = igsfb_accel_cursor; 486 1.11 uwe 487 1.14 uwe if (dc->dc_id >= 0x2000) { /* XXX */ 488 1.31 uwe /* accelerated erase/copy */ 489 1.31 uwe ri->ri_ops.copycols = igsfb_accel_copycols; 490 1.31 uwe ri->ri_ops.erasecols = igsfb_accel_erasecols; 491 1.31 uwe ri->ri_ops.copyrows = igsfb_accel_copyrows; 492 1.31 uwe ri->ri_ops.eraserows = igsfb_accel_eraserows; 493 1.31 uwe 494 1.31 uwe /* putchar hook to sync with the cop */ 495 1.31 uwe dc->dc_ri_putchar = ri->ri_ops.putchar; 496 1.31 uwe ri->ri_ops.putchar = igsfb_accel_putchar; 497 1.14 uwe } 498 1.12 uwe 499 1.1 uwe igsfb_stdscreen.nrows = ri->ri_rows; 500 1.1 uwe igsfb_stdscreen.ncols = ri->ri_cols; 501 1.1 uwe igsfb_stdscreen.textops = &ri->ri_ops; 502 1.1 uwe igsfb_stdscreen.capabilities = ri->ri_caps; 503 1.1 uwe } 504 1.1 uwe 505 1.1 uwe 506 1.1 uwe /* 507 1.11 uwe * Init cursor data in dc_cursor for the accelerated text cursor. 508 1.11 uwe */ 509 1.11 uwe static int 510 1.36 uwe igsfb_make_text_cursor(struct igsfb_devconfig *dc, struct vcons_screen *scr) 511 1.11 uwe { 512 1.27 macallan struct rasops_info *ri = &scr->scr_ri; 513 1.27 macallan struct wsdisplay_font *f = ri->ri_font; 514 1.19 uwe uint16_t cc_scan[8]; /* one sprite scanline */ 515 1.19 uwe uint16_t s; 516 1.11 uwe int w, i; 517 1.11 uwe 518 1.11 uwe KASSERT(f->fontwidth <= IGS_CURSOR_MAX_SIZE); 519 1.11 uwe KASSERT(f->fontheight <= IGS_CURSOR_MAX_SIZE); 520 1.11 uwe 521 1.11 uwe w = f->fontwidth; 522 1.11 uwe for (i = 0; i < f->stride; ++i) { 523 1.11 uwe if (w >= 8) { 524 1.11 uwe s = 0xffff; /* all inverted */ 525 1.11 uwe w -= 8; 526 1.11 uwe } else { 527 1.11 uwe /* first w pixels inverted, the rest is transparent */ 528 1.11 uwe s = ~(0x5555 << (w * 2)); 529 1.29 uwe s = htole16(s); 530 1.11 uwe w = 0; 531 1.11 uwe } 532 1.11 uwe cc_scan[i] = s; 533 1.11 uwe } 534 1.11 uwe 535 1.11 uwe dc->dc_cursor.cc_size.x = f->fontwidth; 536 1.11 uwe dc->dc_cursor.cc_size.y = f->fontheight; 537 1.11 uwe 538 1.11 uwe dc->dc_cursor.cc_hot.x = 0; 539 1.11 uwe dc->dc_cursor.cc_hot.y = 0; 540 1.11 uwe 541 1.11 uwe /* init sprite array to be all transparent */ 542 1.11 uwe memset(dc->dc_cursor.cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE); 543 1.11 uwe 544 1.11 uwe for (i = 0; i < f->fontheight; ++i) 545 1.11 uwe memcpy(&dc->dc_cursor.cc_sprite[i * 8], 546 1.19 uwe cc_scan, f->stride * sizeof(uint16_t)); 547 1.11 uwe 548 1.37 uwe return 0; 549 1.11 uwe } 550 1.11 uwe 551 1.11 uwe 552 1.11 uwe /* 553 1.8 uwe * Spread a byte (abcd.efgh) into two (0a0b.0c0d 0e0f.0g0h). 554 1.10 uwe * Helper function for igsfb_init_bit_table(). 555 1.8 uwe */ 556 1.19 uwe static uint16_t 557 1.36 uwe igsfb_spread_bits_8(uint8_t b) 558 1.8 uwe { 559 1.19 uwe uint16_t s = b; 560 1.8 uwe 561 1.8 uwe s = ((s & 0x00f0) << 4) | (s & 0x000f); 562 1.8 uwe s = ((s & 0x0c0c) << 2) | (s & 0x0303); 563 1.8 uwe s = ((s & 0x2222) << 1) | (s & 0x1111); 564 1.37 uwe return s; 565 1.8 uwe } 566 1.8 uwe 567 1.8 uwe 568 1.8 uwe /* 569 1.8 uwe * Cursor sprite data are in 2bpp. Incoming image/mask are in 1bpp. 570 1.18 uwe * Prebuild the table to expand 1bpp->2bpp, with bswapping if necessary. 571 1.8 uwe */ 572 1.8 uwe static void 573 1.36 uwe igsfb_init_bit_table(struct igsfb_devconfig *dc) 574 1.8 uwe { 575 1.19 uwe uint16_t *expand = dc->dc_bexpand; 576 1.19 uwe uint16_t s; 577 1.8 uwe u_int i; 578 1.8 uwe 579 1.8 uwe for (i = 0; i < 256; ++i) { 580 1.10 uwe s = igsfb_spread_bits_8(i); 581 1.29 uwe expand[i] = htole16(s); 582 1.8 uwe } 583 1.8 uwe } 584 1.8 uwe 585 1.8 uwe 586 1.8 uwe /* 587 1.1 uwe * wsdisplay_accessops: mmap() 588 1.48 elad * XXX: security considerations for allowing mmapping i/o mapped i/o regs? 589 1.1 uwe */ 590 1.1 uwe static paddr_t 591 1.38 jmmv igsfb_mmap(void *v, void *vs, off_t offset, int prot) 592 1.1 uwe { 593 1.27 macallan struct vcons_data *vd = v; 594 1.27 macallan struct igsfb_devconfig *dc = vd->cookie; 595 1.1 uwe 596 1.45 macallan if (offset < dc->dc_memsz && offset >= 0) 597 1.45 macallan return bus_space_mmap(dc->dc_memt, dc->dc_memaddr, offset, 598 1.45 macallan prot, dc->dc_memflags | BUS_SPACE_MAP_LINEAR); 599 1.45 macallan if (dc->dc_mmap) 600 1.45 macallan return dc->dc_mmap(v, vs, offset, prot); 601 1.45 macallan return -1; 602 1.1 uwe } 603 1.1 uwe 604 1.1 uwe 605 1.1 uwe /* 606 1.1 uwe * wsdisplay_accessops: ioctl() 607 1.1 uwe */ 608 1.1 uwe static int 609 1.42 christos igsfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 610 1.38 jmmv struct lwp *l) 611 1.1 uwe { 612 1.27 macallan struct vcons_data *vd = v; 613 1.27 macallan struct igsfb_devconfig *dc = vd->cookie; 614 1.11 uwe int cursor_busy; 615 1.1 uwe int turnoff; 616 1.1 uwe 617 1.11 uwe /* don't permit cursor ioctls if we use sprite for text cursor */ 618 1.11 uwe cursor_busy = !dc->dc_mapped 619 1.11 uwe && (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR); 620 1.11 uwe 621 1.1 uwe switch (cmd) { 622 1.1 uwe 623 1.1 uwe case WSDISPLAYIO_GTYPE: 624 1.1 uwe *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 625 1.37 uwe return 0; 626 1.1 uwe 627 1.1 uwe case WSDISPLAYIO_GINFO: 628 1.1 uwe #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 629 1.35 uwe wsd_fbip->height = dc->dc_height; 630 1.35 uwe wsd_fbip->width = dc->dc_width; 631 1.47 macallan wsd_fbip->depth = dc->dc_maxdepth; 632 1.1 uwe wsd_fbip->cmsize = IGS_CMAP_SIZE; 633 1.1 uwe #undef wsd_fbip 634 1.37 uwe return 0; 635 1.37 uwe 636 1.21 macallan case WSDISPLAYIO_LINEBYTES: 637 1.56 jakllsch *(int *)data = dc->dc_width * howmany(dc->dc_maxdepth, NBBY); 638 1.37 uwe return 0; 639 1.1 uwe 640 1.11 uwe case WSDISPLAYIO_SMODE: 641 1.11 uwe #define d (*(int *)data) 642 1.25 macallan if (d != WSDISPLAYIO_MODE_EMUL) { 643 1.11 uwe dc->dc_mapped = 1; 644 1.23 macallan /* turn off hardware cursor */ 645 1.23 macallan if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) { 646 1.23 macallan dc->dc_curenb = 0; 647 1.23 macallan igsfb_update_cursor(dc, 648 1.23 macallan WSDISPLAY_CURSOR_DOCUR); 649 1.23 macallan } 650 1.47 macallan if ((dc->dc_mode != NULL) && (dc->dc_maxdepth != 8)) 651 1.47 macallan igsfb_set_mode(dc, dc->dc_mode, 652 1.47 macallan dc->dc_maxdepth); 653 1.25 macallan } else { 654 1.11 uwe dc->dc_mapped = 0; 655 1.47 macallan if ((dc->dc_mode != NULL) && (dc->dc_maxdepth != 8)) 656 1.47 macallan igsfb_set_mode(dc, dc->dc_mode, 8); 657 1.47 macallan igsfb_init_cmap(dc); 658 1.11 uwe /* reinit sprite for text cursor */ 659 1.11 uwe if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) { 660 1.27 macallan igsfb_make_text_cursor(dc, dc->dc_vd.active); 661 1.11 uwe dc->dc_curenb = 0; 662 1.11 uwe igsfb_update_cursor(dc, 663 1.11 uwe WSDISPLAY_CURSOR_DOSHAPE 664 1.11 uwe | WSDISPLAY_CURSOR_DOCUR); 665 1.11 uwe } 666 1.27 macallan vcons_redraw_screen(vd->active); 667 1.11 uwe } 668 1.37 uwe return 0; 669 1.11 uwe 670 1.1 uwe case WSDISPLAYIO_GVIDEO: 671 1.8 uwe *(u_int *)data = dc->dc_blanked ? 672 1.1 uwe WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 673 1.37 uwe return 0; 674 1.1 uwe 675 1.1 uwe case WSDISPLAYIO_SVIDEO: 676 1.1 uwe turnoff = (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF); 677 1.8 uwe if (dc->dc_blanked != turnoff) { 678 1.8 uwe dc->dc_blanked = turnoff; 679 1.8 uwe igsfb_blank_screen(dc, dc->dc_blanked); 680 1.1 uwe } 681 1.37 uwe return 0; 682 1.1 uwe 683 1.1 uwe case WSDISPLAYIO_GETCMAP: 684 1.37 uwe return igsfb_get_cmap(dc, (struct wsdisplay_cmap *)data); 685 1.1 uwe 686 1.1 uwe case WSDISPLAYIO_PUTCMAP: 687 1.37 uwe return igsfb_set_cmap(dc, (struct wsdisplay_cmap *)data); 688 1.1 uwe 689 1.1 uwe case WSDISPLAYIO_GCURMAX: 690 1.1 uwe ((struct wsdisplay_curpos *)data)->x = IGS_CURSOR_MAX_SIZE; 691 1.1 uwe ((struct wsdisplay_curpos *)data)->y = IGS_CURSOR_MAX_SIZE; 692 1.37 uwe return 0; 693 1.1 uwe 694 1.1 uwe case WSDISPLAYIO_GCURPOS: 695 1.11 uwe if (cursor_busy) 696 1.37 uwe return EBUSY; 697 1.8 uwe *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos; 698 1.37 uwe return 0; 699 1.1 uwe 700 1.1 uwe case WSDISPLAYIO_SCURPOS: 701 1.11 uwe if (cursor_busy) 702 1.37 uwe return EBUSY; 703 1.8 uwe igsfb_set_curpos(dc, (struct wsdisplay_curpos *)data); 704 1.37 uwe return 0; 705 1.1 uwe 706 1.1 uwe case WSDISPLAYIO_GCURSOR: 707 1.11 uwe if (cursor_busy) 708 1.37 uwe return EBUSY; 709 1.37 uwe return igsfb_get_cursor(dc, (struct wsdisplay_cursor *)data); 710 1.1 uwe 711 1.1 uwe case WSDISPLAYIO_SCURSOR: 712 1.24 uwe if (cursor_busy) 713 1.37 uwe return EBUSY; 714 1.37 uwe return igsfb_set_cursor(dc, (struct wsdisplay_cursor *)data); 715 1.1 uwe } 716 1.1 uwe 717 1.37 uwe return EPASSTHROUGH; 718 1.1 uwe } 719 1.1 uwe 720 1.1 uwe 721 1.1 uwe /* 722 1.1 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_SVIDEO) 723 1.1 uwe */ 724 1.1 uwe static void 725 1.36 uwe igsfb_blank_screen(struct igsfb_devconfig *dc, int blank) 726 1.1 uwe { 727 1.1 uwe 728 1.8 uwe igs_ext_write(dc->dc_iot, dc->dc_ioh, 729 1.1 uwe IGS_EXT_SYNC_CTL, 730 1.1 uwe blank ? IGS_EXT_SYNC_H0 | IGS_EXT_SYNC_V0 731 1.1 uwe : 0); 732 1.1 uwe } 733 1.1 uwe 734 1.1 uwe 735 1.1 uwe /* 736 1.1 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_GETCMAP) 737 1.8 uwe * Served from the software cmap copy. 738 1.1 uwe */ 739 1.1 uwe static int 740 1.36 uwe igsfb_get_cmap(struct igsfb_devconfig *dc, struct wsdisplay_cmap *p) 741 1.1 uwe { 742 1.11 uwe u_int index, count; 743 1.11 uwe int err; 744 1.11 uwe 745 1.11 uwe index = p->index; 746 1.11 uwe count = p->count; 747 1.1 uwe 748 1.5 itojun if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index) 749 1.37 uwe return EINVAL; 750 1.1 uwe 751 1.11 uwe err = copyout(&dc->dc_cmap.r[index], p->red, count); 752 1.11 uwe if (err) 753 1.37 uwe return err; 754 1.11 uwe err = copyout(&dc->dc_cmap.g[index], p->green, count); 755 1.11 uwe if (err) 756 1.37 uwe return err; 757 1.11 uwe err = copyout(&dc->dc_cmap.b[index], p->blue, count); 758 1.11 uwe if (err) 759 1.37 uwe return err; 760 1.1 uwe 761 1.37 uwe return 0; 762 1.1 uwe } 763 1.1 uwe 764 1.1 uwe 765 1.1 uwe /* 766 1.15 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_PUTCMAP) 767 1.8 uwe * Set the software cmap copy and propagate changed range to the device. 768 1.1 uwe */ 769 1.1 uwe static int 770 1.36 uwe igsfb_set_cmap(struct igsfb_devconfig *dc, const struct wsdisplay_cmap *p) 771 1.1 uwe { 772 1.11 uwe u_int index, count; 773 1.17 chs uint8_t r[IGS_CMAP_SIZE]; 774 1.17 chs uint8_t g[IGS_CMAP_SIZE]; 775 1.17 chs uint8_t b[IGS_CMAP_SIZE]; 776 1.17 chs int error; 777 1.11 uwe 778 1.11 uwe index = p->index; 779 1.11 uwe count = p->count; 780 1.5 itojun if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index) 781 1.37 uwe return EINVAL; 782 1.17 chs error = copyin(p->red, &r[index], count); 783 1.17 chs if (error) 784 1.17 chs return error; 785 1.17 chs error = copyin(p->green, &g[index], count); 786 1.17 chs if (error) 787 1.17 chs return error; 788 1.17 chs error = copyin(p->blue, &b[index], count); 789 1.17 chs if (error) 790 1.17 chs return error; 791 1.17 chs 792 1.17 chs memcpy(&dc->dc_cmap.r[index], &r[index], count); 793 1.17 chs memcpy(&dc->dc_cmap.g[index], &g[index], count); 794 1.17 chs memcpy(&dc->dc_cmap.b[index], &b[index], count); 795 1.1 uwe 796 1.11 uwe /* propagate changes to the device */ 797 1.11 uwe igsfb_update_cmap(dc, index, count); 798 1.37 uwe return 0; 799 1.1 uwe } 800 1.1 uwe 801 1.1 uwe 802 1.1 uwe /* 803 1.8 uwe * Propagate specified part of the software cmap copy to the device. 804 1.1 uwe */ 805 1.1 uwe static void 806 1.36 uwe igsfb_update_cmap(struct igsfb_devconfig *dc, u_int index, u_int count) 807 1.1 uwe { 808 1.1 uwe bus_space_tag_t t; 809 1.1 uwe bus_space_handle_t h; 810 1.1 uwe u_int last, i; 811 1.1 uwe 812 1.1 uwe if (index >= IGS_CMAP_SIZE) 813 1.1 uwe return; 814 1.1 uwe 815 1.57 riastrad if (count > IGS_CMAP_SIZE - index) 816 1.1 uwe last = IGS_CMAP_SIZE; 817 1.57 riastrad else 818 1.57 riastrad last = index + count; 819 1.1 uwe 820 1.8 uwe t = dc->dc_iot; 821 1.8 uwe h = dc->dc_ioh; 822 1.1 uwe 823 1.1 uwe /* start palette writing, index is autoincremented by hardware */ 824 1.1 uwe bus_space_write_1(t, h, IGS_DAC_PEL_WRITE_IDX, index); 825 1.1 uwe 826 1.1 uwe for (i = index; i < last; ++i) { 827 1.8 uwe bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.r[i]); 828 1.8 uwe bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.g[i]); 829 1.8 uwe bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.b[i]); 830 1.1 uwe } 831 1.1 uwe } 832 1.1 uwe 833 1.1 uwe 834 1.1 uwe /* 835 1.1 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURPOS) 836 1.1 uwe */ 837 1.1 uwe static void 838 1.36 uwe igsfb_set_curpos(struct igsfb_devconfig *dc, 839 1.36 uwe const struct wsdisplay_curpos *curpos) 840 1.1 uwe { 841 1.27 macallan struct rasops_info *ri = &dc->dc_vd.active->scr_ri; 842 1.9 uwe u_int x = curpos->x, y = curpos->y; 843 1.9 uwe 844 1.9 uwe if (x >= ri->ri_width) 845 1.9 uwe x = ri->ri_width - 1; 846 1.9 uwe if (y >= ri->ri_height) 847 1.9 uwe y = ri->ri_height - 1; 848 1.1 uwe 849 1.8 uwe dc->dc_cursor.cc_pos.x = x; 850 1.8 uwe dc->dc_cursor.cc_pos.y = y; 851 1.1 uwe 852 1.11 uwe /* propagate changes to the device */ 853 1.8 uwe igsfb_update_curpos(dc); 854 1.1 uwe } 855 1.1 uwe 856 1.1 uwe 857 1.1 uwe static void 858 1.36 uwe igsfb_update_curpos(struct igsfb_devconfig *dc) 859 1.1 uwe { 860 1.1 uwe bus_space_tag_t t; 861 1.1 uwe bus_space_handle_t h; 862 1.1 uwe int x, xoff, y, yoff; 863 1.1 uwe 864 1.1 uwe xoff = 0; 865 1.8 uwe x = dc->dc_cursor.cc_pos.x - dc->dc_cursor.cc_hot.x; 866 1.1 uwe if (x < 0) { 867 1.8 uwe xoff = -x; 868 1.1 uwe x = 0; 869 1.1 uwe } 870 1.1 uwe 871 1.1 uwe yoff = 0; 872 1.8 uwe y = dc->dc_cursor.cc_pos.y - dc->dc_cursor.cc_hot.y; 873 1.1 uwe if (y < 0) { 874 1.8 uwe yoff = -y; 875 1.1 uwe y = 0; 876 1.1 uwe } 877 1.1 uwe 878 1.8 uwe t = dc->dc_iot; 879 1.8 uwe h = dc->dc_ioh; 880 1.1 uwe 881 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_LO, x & 0xff); 882 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_HI, (x >> 8) & 0x07); 883 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_HPRESET, xoff & 0x3f); 884 1.1 uwe 885 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_LO, y & 0xff); 886 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_HI, (y >> 8) & 0x07); 887 1.1 uwe igs_ext_write(t, h, IGS_EXT_SPRITE_VPRESET, yoff & 0x3f); 888 1.1 uwe } 889 1.1 uwe 890 1.1 uwe 891 1.1 uwe /* 892 1.1 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_GCURSOR) 893 1.1 uwe */ 894 1.1 uwe static int 895 1.36 uwe igsfb_get_cursor(struct igsfb_devconfig *dc, struct wsdisplay_cursor *p) 896 1.1 uwe { 897 1.1 uwe 898 1.1 uwe /* XXX: TODO */ 899 1.37 uwe return 0; 900 1.1 uwe } 901 1.1 uwe 902 1.1 uwe 903 1.1 uwe /* 904 1.1 uwe * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURSOR) 905 1.1 uwe */ 906 1.1 uwe static int 907 1.36 uwe igsfb_set_cursor(struct igsfb_devconfig *dc, const struct wsdisplay_cursor *p) 908 1.1 uwe { 909 1.1 uwe struct igs_hwcursor *cc; 910 1.9 uwe struct wsdisplay_curpos pos, hot; 911 1.1 uwe u_int v, index, count, icount, iwidth; 912 1.17 chs uint8_t r[2], g[2], b[2], image[512], mask[512]; 913 1.17 chs int error; 914 1.1 uwe 915 1.8 uwe cc = &dc->dc_cursor; 916 1.1 uwe v = p->which; 917 1.17 chs index = count = icount = iwidth = 0; /* XXX: gcc */ 918 1.39 mrg pos.x = pos.y = 0; /* XXX: gcc */ 919 1.24 uwe 920 1.17 chs /* copy in the new cursor colormap */ 921 1.1 uwe if (v & WSDISPLAY_CURSOR_DOCMAP) { 922 1.1 uwe index = p->cmap.index; 923 1.1 uwe count = p->cmap.count; 924 1.1 uwe if (index >= 2 || (index + count) > 2) 925 1.37 uwe return EINVAL; 926 1.17 chs error = copyin(p->cmap.red, &r[index], count); 927 1.17 chs if (error) 928 1.17 chs return error; 929 1.17 chs error = copyin(p->cmap.green, &g[index], count); 930 1.17 chs if (error) 931 1.17 chs return error; 932 1.17 chs error = copyin(p->cmap.blue, &b[index], count); 933 1.17 chs if (error) 934 1.17 chs return error; 935 1.1 uwe } 936 1.1 uwe 937 1.9 uwe /* verify that the new cursor data are valid */ 938 1.1 uwe if (v & WSDISPLAY_CURSOR_DOSHAPE) { 939 1.1 uwe if (p->size.x > IGS_CURSOR_MAX_SIZE 940 1.1 uwe || p->size.y > IGS_CURSOR_MAX_SIZE) 941 1.37 uwe return EINVAL; 942 1.1 uwe 943 1.1 uwe iwidth = (p->size.x + 7) >> 3; /* bytes per scan line */ 944 1.1 uwe icount = iwidth * p->size.y; 945 1.17 chs error = copyin(p->image, image, icount); 946 1.17 chs if (error) 947 1.17 chs return error; 948 1.17 chs error = copyin(p->mask, mask, icount); 949 1.17 chs if (error) 950 1.17 chs return error; 951 1.1 uwe } 952 1.1 uwe 953 1.9 uwe /* enforce that the position is within screen bounds */ 954 1.9 uwe if (v & WSDISPLAY_CURSOR_DOPOS) { 955 1.27 macallan struct rasops_info *ri = &dc->dc_vd.active->scr_ri; 956 1.9 uwe 957 1.9 uwe pos = p->pos; /* local copy we can write to */ 958 1.25 macallan if (pos.x >= ri->ri_width) 959 1.25 macallan pos.x = ri->ri_width - 1; 960 1.25 macallan if (pos.y >= ri->ri_height) 961 1.25 macallan pos.y = ri->ri_height - 1; 962 1.9 uwe } 963 1.9 uwe 964 1.9 uwe /* enforce that the hot spot is within sprite bounds */ 965 1.9 uwe if (v & WSDISPLAY_CURSOR_DOHOT) 966 1.9 uwe hot = p->hot; /* local copy we can write to */ 967 1.9 uwe 968 1.9 uwe if (v & (WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOSHAPE)) { 969 1.9 uwe const struct wsdisplay_curpos *nsize; 970 1.9 uwe struct wsdisplay_curpos *nhot; 971 1.1 uwe 972 1.9 uwe nsize = (v & WSDISPLAY_CURSOR_DOSHAPE) ? 973 1.9 uwe &p->size : &cc->cc_size; 974 1.9 uwe nhot = (v & WSDISPLAY_CURSOR_DOHOT) ? &hot : &cc->cc_hot; 975 1.1 uwe 976 1.9 uwe if (nhot->x >= nsize->x) 977 1.9 uwe nhot->x = nsize->x - 1; 978 1.9 uwe if (nhot->y >= nsize->y) 979 1.9 uwe nhot->y = nsize->y - 1; 980 1.9 uwe } 981 1.9 uwe 982 1.17 chs /* copy data to the driver's cursor info */ 983 1.1 uwe if (v & WSDISPLAY_CURSOR_DOCUR) 984 1.8 uwe dc->dc_curenb = p->enable; 985 1.1 uwe if (v & WSDISPLAY_CURSOR_DOPOS) 986 1.9 uwe cc->cc_pos = pos; /* local copy, possibly corrected */ 987 1.1 uwe if (v & WSDISPLAY_CURSOR_DOHOT) 988 1.9 uwe cc->cc_hot = hot; /* local copy, possibly corrected */ 989 1.1 uwe if (v & WSDISPLAY_CURSOR_DOCMAP) { 990 1.17 chs memcpy(&cc->cc_color[index], &r[index], count); 991 1.17 chs memcpy(&cc->cc_color[index + 2], &g[index], count); 992 1.17 chs memcpy(&cc->cc_color[index + 4], &b[index], count); 993 1.1 uwe } 994 1.1 uwe if (v & WSDISPLAY_CURSOR_DOSHAPE) { 995 1.1 uwe u_int trailing_bits; 996 1.1 uwe 997 1.17 chs memcpy(cc->cc_image, image, icount); 998 1.17 chs memcpy(cc->cc_mask, mask, icount); 999 1.1 uwe cc->cc_size = p->size; 1000 1.1 uwe 1001 1.1 uwe /* clear trailing bits in the "partial" mask bytes */ 1002 1.1 uwe trailing_bits = p->size.x & 0x07; 1003 1.1 uwe if (trailing_bits != 0) { 1004 1.58 maya const u_int cutmask = ~((~0U) << trailing_bits); 1005 1.1 uwe u_char *mp; 1006 1.1 uwe u_int i; 1007 1.1 uwe 1008 1.1 uwe mp = cc->cc_mask + iwidth - 1; 1009 1.1 uwe for (i = 0; i < p->size.y; ++i) { 1010 1.1 uwe *mp &= cutmask; 1011 1.1 uwe mp += iwidth; 1012 1.1 uwe } 1013 1.1 uwe } 1014 1.8 uwe igsfb_convert_cursor_data(dc, iwidth, p->size.y); 1015 1.1 uwe } 1016 1.1 uwe 1017 1.9 uwe /* propagate changes to the device */ 1018 1.8 uwe igsfb_update_cursor(dc, v); 1019 1.9 uwe 1020 1.37 uwe return 0; 1021 1.1 uwe } 1022 1.1 uwe 1023 1.4 uwe 1024 1.1 uwe /* 1025 1.1 uwe * Convert incoming 1bpp cursor image/mask into native 2bpp format. 1026 1.1 uwe */ 1027 1.1 uwe static void 1028 1.36 uwe igsfb_convert_cursor_data(struct igsfb_devconfig *dc, 1029 1.36 uwe u_int width, u_int height) 1030 1.1 uwe { 1031 1.8 uwe struct igs_hwcursor *cc = &dc->dc_cursor; 1032 1.19 uwe uint16_t *expand = dc->dc_bexpand; 1033 1.19 uwe uint8_t *ip, *mp; 1034 1.19 uwe uint16_t is, ms, *dp; 1035 1.1 uwe u_int line, i; 1036 1.1 uwe 1037 1.1 uwe /* init sprite to be all transparent */ 1038 1.1 uwe memset(cc->cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE); 1039 1.1 uwe 1040 1.1 uwe /* first scanline */ 1041 1.1 uwe ip = cc->cc_image; 1042 1.1 uwe mp = cc->cc_mask; 1043 1.1 uwe dp = cc->cc_sprite; 1044 1.1 uwe 1045 1.10 uwe for (line = 0; line < height; ++line) { 1046 1.10 uwe for (i = 0; i < width; ++i) { 1047 1.10 uwe is = expand[ip[i]]; /* image: 0 -> 00, 1 -> 01 */ 1048 1.10 uwe ms = expand[mp[i]]; /* mask: 0 -> 00, 1 -> 11 */ 1049 1.8 uwe ms |= (ms << 1); 1050 1.1 uwe dp[i] = (0xaaaa & ~ms) | (is & ms); 1051 1.1 uwe } 1052 1.1 uwe 1053 1.1 uwe /* next scanline */ 1054 1.10 uwe ip += width; 1055 1.10 uwe mp += width; 1056 1.10 uwe dp += 8; /* 64 pixels, 2bpp, 8 pixels per short = 8 shorts */ 1057 1.1 uwe } 1058 1.1 uwe } 1059 1.1 uwe 1060 1.1 uwe 1061 1.1 uwe /* 1062 1.8 uwe * Propagate cursor changes to the device. 1063 1.8 uwe * "which" is composed of WSDISPLAY_CURSOR_DO* bits. 1064 1.1 uwe */ 1065 1.1 uwe static void 1066 1.36 uwe igsfb_update_cursor(struct igsfb_devconfig *dc, u_int which) 1067 1.1 uwe { 1068 1.8 uwe bus_space_tag_t iot = dc->dc_iot; 1069 1.8 uwe bus_space_handle_t ioh = dc->dc_ioh; 1070 1.19 uwe uint8_t curctl; 1071 1.16 uwe 1072 1.16 uwe curctl = 0; /* XXX: gcc */ 1073 1.1 uwe 1074 1.1 uwe /* 1075 1.1 uwe * We will need to tweak sprite control register for cursor 1076 1.18 uwe * visibility and cursor color map manipulation. 1077 1.1 uwe */ 1078 1.1 uwe if (which & (WSDISPLAY_CURSOR_DOCUR | WSDISPLAY_CURSOR_DOCMAP)) { 1079 1.1 uwe curctl = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL); 1080 1.1 uwe } 1081 1.1 uwe 1082 1.1 uwe if (which & WSDISPLAY_CURSOR_DOSHAPE) { 1083 1.19 uwe uint8_t *dst = bus_space_vaddr(dc->dc_memt, dc->dc_crh); 1084 1.1 uwe 1085 1.1 uwe /* 1086 1.1 uwe * memcpy between spaces of different endianness would 1087 1.8 uwe * be ... special. We cannot be sure if memcpy gonna 1088 1.1 uwe * push data in 4-byte chunks, we can't pre-bswap it, 1089 1.1 uwe * so do it byte-by-byte to preserve byte ordering. 1090 1.1 uwe */ 1091 1.8 uwe if (IGSFB_HW_SOFT_BSWAP(dc)) { 1092 1.19 uwe uint8_t *src = (uint8_t *)dc->dc_cursor.cc_sprite; 1093 1.1 uwe int i; 1094 1.1 uwe 1095 1.8 uwe for (i = 0; i < IGS_CURSOR_DATA_SIZE; ++i) 1096 1.1 uwe *dst++ = *src++; 1097 1.1 uwe } else { 1098 1.8 uwe memcpy(dst, dc->dc_cursor.cc_sprite, 1099 1.8 uwe IGS_CURSOR_DATA_SIZE); 1100 1.1 uwe } 1101 1.1 uwe } 1102 1.1 uwe 1103 1.1 uwe if (which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 1104 1.1 uwe /* code shared with WSDISPLAYIO_SCURPOS */ 1105 1.8 uwe igsfb_update_curpos(dc); 1106 1.1 uwe } 1107 1.1 uwe 1108 1.1 uwe if (which & WSDISPLAY_CURSOR_DOCMAP) { 1109 1.19 uwe uint8_t *p; 1110 1.1 uwe 1111 1.1 uwe /* tell DAC we want access to the cursor palette */ 1112 1.1 uwe igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1113 1.4 uwe curctl | IGS_EXT_SPRITE_DAC_PEL); 1114 1.1 uwe 1115 1.8 uwe p = dc->dc_cursor.cc_color; 1116 1.1 uwe 1117 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 0); 1118 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[0]); 1119 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[2]); 1120 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[4]); 1121 1.1 uwe 1122 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 1); 1123 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[1]); 1124 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[3]); 1125 1.1 uwe bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[5]); 1126 1.1 uwe 1127 1.8 uwe /* restore access to the normal palette */ 1128 1.1 uwe igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, curctl); 1129 1.1 uwe } 1130 1.1 uwe 1131 1.1 uwe if (which & WSDISPLAY_CURSOR_DOCUR) { 1132 1.1 uwe if ((curctl & IGS_EXT_SPRITE_VISIBLE) == 0 1133 1.8 uwe && dc->dc_curenb) 1134 1.1 uwe igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1135 1.1 uwe curctl | IGS_EXT_SPRITE_VISIBLE); 1136 1.1 uwe else if ((curctl & IGS_EXT_SPRITE_VISIBLE) != 0 1137 1.8 uwe && !dc->dc_curenb) 1138 1.1 uwe igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1139 1.1 uwe curctl & ~IGS_EXT_SPRITE_VISIBLE); 1140 1.1 uwe } 1141 1.1 uwe } 1142 1.1 uwe 1143 1.1 uwe 1144 1.1 uwe /* 1145 1.11 uwe * Accelerated text mode cursor that uses hardware sprite. 1146 1.11 uwe */ 1147 1.11 uwe static void 1148 1.36 uwe igsfb_accel_cursor(void *cookie, int on, int row, int col) 1149 1.11 uwe { 1150 1.11 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1151 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1152 1.27 macallan struct igsfb_devconfig *dc = scr->scr_cookie; 1153 1.11 uwe struct igs_hwcursor *cc = &dc->dc_cursor; 1154 1.11 uwe u_int which; 1155 1.11 uwe 1156 1.11 uwe ri->ri_crow = row; 1157 1.11 uwe ri->ri_ccol = col; 1158 1.11 uwe 1159 1.11 uwe which = 0; 1160 1.11 uwe if (on) { 1161 1.11 uwe ri->ri_flg |= RI_CURSOR; 1162 1.11 uwe 1163 1.18 uwe /* only bother to move the cursor if it's visible */ 1164 1.11 uwe cc->cc_pos.x = ri->ri_xorigin 1165 1.11 uwe + ri->ri_ccol * ri->ri_font->fontwidth; 1166 1.11 uwe cc->cc_pos.y = ri->ri_yorigin 1167 1.11 uwe + ri->ri_crow * ri->ri_font->fontheight; 1168 1.11 uwe which |= WSDISPLAY_CURSOR_DOPOS; 1169 1.11 uwe } else 1170 1.11 uwe ri->ri_flg &= ~RI_CURSOR; 1171 1.11 uwe 1172 1.11 uwe if (dc->dc_curenb != on) { 1173 1.11 uwe dc->dc_curenb = on; 1174 1.11 uwe which |= WSDISPLAY_CURSOR_DOCUR; 1175 1.11 uwe } 1176 1.11 uwe 1177 1.11 uwe /* propagate changes to the device */ 1178 1.11 uwe igsfb_update_cursor(dc, which); 1179 1.12 uwe } 1180 1.12 uwe 1181 1.12 uwe 1182 1.12 uwe 1183 1.12 uwe /* 1184 1.12 uwe * Accelerated raster ops that use graphic coprocessor. 1185 1.12 uwe */ 1186 1.12 uwe 1187 1.12 uwe static int 1188 1.36 uwe igsfb_accel_wait(struct igsfb_devconfig *dc) 1189 1.12 uwe { 1190 1.12 uwe bus_space_tag_t t = dc->dc_iot; 1191 1.12 uwe bus_space_handle_t h = dc->dc_coph; 1192 1.12 uwe int timo = 100000; 1193 1.19 uwe uint8_t reg; 1194 1.12 uwe 1195 1.56 jakllsch bus_space_write_1(t, h, IGS_COP_MAP_FMT_REG, 1196 1.56 jakllsch howmany(dc->dc_depth, NBBY) - 1); 1197 1.12 uwe while (timo--) { 1198 1.12 uwe reg = bus_space_read_1(t, h, IGS_COP_CTL_REG); 1199 1.12 uwe if ((reg & IGS_COP_CTL_BUSY) == 0) 1200 1.37 uwe return 0; 1201 1.12 uwe } 1202 1.12 uwe 1203 1.37 uwe return 1; 1204 1.12 uwe } 1205 1.12 uwe 1206 1.12 uwe 1207 1.12 uwe static void 1208 1.36 uwe igsfb_accel_copy(struct igsfb_devconfig *dc, uint32_t src, uint32_t dst, 1209 1.36 uwe uint16_t width, uint16_t height) 1210 1.12 uwe { 1211 1.12 uwe bus_space_tag_t t = dc->dc_iot; 1212 1.12 uwe bus_space_handle_t h = dc->dc_coph; 1213 1.19 uwe uint32_t toend; 1214 1.19 uwe uint8_t drawcmd; 1215 1.12 uwe 1216 1.12 uwe drawcmd = IGS_COP_DRAW_ALL; 1217 1.12 uwe if (dst > src) { 1218 1.27 macallan toend = dc->dc_vd.active->scr_ri.ri_width * (height - 1) + (width - 1); 1219 1.12 uwe src += toend; 1220 1.12 uwe dst += toend; 1221 1.12 uwe drawcmd |= IGS_COP_OCTANT_X_NEG | IGS_COP_OCTANT_Y_NEG; 1222 1.12 uwe } 1223 1.12 uwe 1224 1.12 uwe igsfb_accel_wait(dc); 1225 1.12 uwe bus_space_write_1(t, h, IGS_COP_CTL_REG, 0); 1226 1.12 uwe 1227 1.12 uwe bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S); 1228 1.12 uwe 1229 1.12 uwe bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1); 1230 1.12 uwe bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1); 1231 1.12 uwe 1232 1.12 uwe bus_space_write_4(t, h, IGS_COP_SRC_START_REG, src); 1233 1.12 uwe bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst); 1234 1.12 uwe 1235 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, drawcmd); 1236 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG); 1237 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0); 1238 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG, 1239 1.12 uwe IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC); 1240 1.12 uwe } 1241 1.12 uwe 1242 1.36 uwe 1243 1.12 uwe static void 1244 1.36 uwe igsfb_accel_fill(struct igsfb_devconfig *dc, uint32_t color, uint32_t dst, 1245 1.36 uwe uint16_t width, uint16_t height) 1246 1.12 uwe { 1247 1.12 uwe bus_space_tag_t t = dc->dc_iot; 1248 1.12 uwe bus_space_handle_t h = dc->dc_coph; 1249 1.12 uwe 1250 1.12 uwe igsfb_accel_wait(dc); 1251 1.12 uwe bus_space_write_1(t, h, IGS_COP_CTL_REG, 0); 1252 1.12 uwe 1253 1.12 uwe bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S); 1254 1.12 uwe 1255 1.12 uwe bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1); 1256 1.12 uwe bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1); 1257 1.12 uwe 1258 1.12 uwe bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst); 1259 1.12 uwe bus_space_write_4(t, h, IGS_COP_FG_REG, color); 1260 1.12 uwe 1261 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, IGS_COP_DRAW_ALL); 1262 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG); 1263 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0); 1264 1.12 uwe bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG, IGS_COP_OP_PXBLT); 1265 1.12 uwe } 1266 1.12 uwe 1267 1.12 uwe 1268 1.12 uwe static void 1269 1.36 uwe igsfb_accel_copyrows(void *cookie, int src, int dst, int num) 1270 1.12 uwe { 1271 1.12 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1272 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1273 1.27 macallan struct igsfb_devconfig *dc = (struct igsfb_devconfig *)scr->scr_cookie; 1274 1.19 uwe uint32_t srp, dsp; 1275 1.19 uwe uint16_t width, height; 1276 1.12 uwe 1277 1.12 uwe width = ri->ri_emuwidth; 1278 1.12 uwe height = num * ri->ri_font->fontheight; 1279 1.12 uwe 1280 1.12 uwe srp = ri->ri_xorigin 1281 1.12 uwe + ri->ri_width * (ri->ri_yorigin 1282 1.12 uwe + src * ri->ri_font->fontheight); 1283 1.12 uwe dsp = ri->ri_xorigin 1284 1.12 uwe + ri->ri_width * (ri->ri_yorigin 1285 1.12 uwe + dst * ri->ri_font->fontheight); 1286 1.12 uwe 1287 1.12 uwe igsfb_accel_copy(dc, srp, dsp, width, height); 1288 1.12 uwe } 1289 1.12 uwe 1290 1.12 uwe 1291 1.36 uwe static void 1292 1.36 uwe igsfb_accel_copycols(void *cookie, int row, int src, int dst, int num) 1293 1.12 uwe { 1294 1.12 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1295 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1296 1.27 macallan struct igsfb_devconfig *dc = (struct igsfb_devconfig *)scr->scr_cookie; 1297 1.19 uwe uint32_t rowp, srp, dsp; 1298 1.19 uwe uint16_t width, height; 1299 1.20 perry 1300 1.12 uwe width = num * ri->ri_font->fontwidth; 1301 1.12 uwe height = ri->ri_font->fontheight; 1302 1.12 uwe 1303 1.12 uwe rowp = ri->ri_xorigin 1304 1.12 uwe + ri->ri_width * (ri->ri_yorigin 1305 1.12 uwe + row * ri->ri_font->fontheight); 1306 1.12 uwe 1307 1.12 uwe srp = rowp + src * ri->ri_font->fontwidth; 1308 1.12 uwe dsp = rowp + dst * ri->ri_font->fontwidth; 1309 1.12 uwe 1310 1.20 perry igsfb_accel_copy(dc, srp, dsp, width, height); 1311 1.12 uwe } 1312 1.12 uwe 1313 1.12 uwe 1314 1.12 uwe static void 1315 1.36 uwe igsfb_accel_eraserows(void *cookie, int row, int num, long attr) 1316 1.12 uwe { 1317 1.12 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1318 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1319 1.27 macallan struct igsfb_devconfig *dc = (struct igsfb_devconfig *)scr->scr_cookie; 1320 1.19 uwe uint32_t color; 1321 1.19 uwe uint32_t dsp; 1322 1.19 uwe uint16_t width, height; 1323 1.12 uwe 1324 1.30 uwe if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) { 1325 1.30 uwe width = ri->ri_width; 1326 1.30 uwe height = ri->ri_height; 1327 1.30 uwe dsp = 0; 1328 1.30 uwe } else { 1329 1.30 uwe width = ri->ri_emuwidth; 1330 1.30 uwe height = num * ri->ri_font->fontheight; 1331 1.30 uwe 1332 1.30 uwe dsp = ri->ri_xorigin 1333 1.30 uwe + ri->ri_width * (ri->ri_yorigin 1334 1.30 uwe + row * ri->ri_font->fontheight); 1335 1.30 uwe } 1336 1.12 uwe 1337 1.12 uwe /* XXX: we "know" the encoding that rasops' allocattr uses */ 1338 1.12 uwe color = (attr >> 16) & 0xff; 1339 1.12 uwe 1340 1.12 uwe igsfb_accel_fill(dc, color, dsp, width, height); 1341 1.12 uwe } 1342 1.12 uwe 1343 1.12 uwe 1344 1.36 uwe static void 1345 1.36 uwe igsfb_accel_erasecols(void *cookie, int row, int col, int num, long attr) 1346 1.12 uwe { 1347 1.12 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1348 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1349 1.27 macallan struct igsfb_devconfig *dc = (struct igsfb_devconfig *)scr->scr_cookie; 1350 1.19 uwe uint32_t color; 1351 1.19 uwe uint32_t rowp, dsp; 1352 1.19 uwe uint16_t width, height; 1353 1.12 uwe 1354 1.12 uwe width = num * ri->ri_font->fontwidth; 1355 1.12 uwe height = ri->ri_font->fontheight; 1356 1.12 uwe 1357 1.12 uwe rowp = ri->ri_xorigin 1358 1.12 uwe + ri->ri_width * (ri->ri_yorigin 1359 1.12 uwe + row * ri->ri_font->fontheight); 1360 1.12 uwe 1361 1.12 uwe dsp = rowp + col * ri->ri_font->fontwidth; 1362 1.12 uwe 1363 1.12 uwe /* XXX: we "know" the encoding that rasops' allocattr uses */ 1364 1.12 uwe color = (attr >> 16) & 0xff; 1365 1.12 uwe 1366 1.12 uwe igsfb_accel_fill(dc, color, dsp, width, height); 1367 1.12 uwe } 1368 1.12 uwe 1369 1.12 uwe 1370 1.12 uwe /* 1371 1.12 uwe * Not really implemented here, but we need to hook into the one 1372 1.12 uwe * supplied by rasops so that we can synchronize with the COP. 1373 1.12 uwe */ 1374 1.12 uwe static void 1375 1.36 uwe igsfb_accel_putchar(void *cookie, int row, int col, u_int uc, long attr) 1376 1.12 uwe { 1377 1.12 uwe struct rasops_info *ri = (struct rasops_info *)cookie; 1378 1.27 macallan struct vcons_screen *scr = ri->ri_hw; 1379 1.27 macallan struct igsfb_devconfig *dc = (struct igsfb_devconfig *)scr->scr_cookie; 1380 1.12 uwe 1381 1.12 uwe igsfb_accel_wait(dc); 1382 1.12 uwe (*dc->dc_ri_putchar)(cookie, row, col, uc, attr); 1383 1.1 uwe } 1384