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