1 /* $NetBSD: igsfb.c,v 1.17 2003/11/13 03:09:29 chs 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.17 2003/11/13 03:09:29 chs 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 proc *); 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 u_int32_t, u_int32_t, u_int16_t, u_int16_t); 116 static void igsfb_accel_copy(struct igsfb_devconfig *, 117 u_int32_t, u_int32_t, u_int16_t, u_int16_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 u_int16_t igsfb_spread_bits_8(u_int8_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 (u_int32_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 u_int8_t *p; 226 int need_bswap; 227 bus_addr_t fbaddr, craddr; 228 off_t croffset; 229 u_int8_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(u_int32_t), 247 sizeof(u_int32_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 *((u_int32_t *)p) = 0x12345678; 258 #else 259 *((u_int32_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(u_int32_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 abd 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 u_int8_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 461 462 /* use the sprite for the text mode cursor */ 463 igsfb_make_text_cursor(dc); 464 465 /* the cursor is "busy" while we are in the text mode */ 466 dc->dc_hwflags |= IGSFB_HW_TEXT_CURSOR; 467 468 /* propagate sprite data to the device */ 469 igsfb_update_cursor(dc, WSDISPLAY_CURSOR_DOSHAPE); 470 471 /* accelerated text cursor */ 472 ri->ri_ops.cursor = igsfb_accel_cursor; 473 474 if (dc->dc_id >= 0x2000) { /* XXX */ 475 /* accelerated erase/copy */ 476 ri->ri_ops.copycols = igsfb_accel_copycols; 477 ri->ri_ops.erasecols = igsfb_accel_erasecols; 478 ri->ri_ops.copyrows = igsfb_accel_copyrows; 479 ri->ri_ops.eraserows = igsfb_accel_eraserows; 480 481 /* putchar hook to sync with the cop */ 482 dc->dc_ri_putchar = ri->ri_ops.putchar; 483 ri->ri_ops.putchar = igsfb_accel_putchar; 484 } 485 486 igsfb_stdscreen.nrows = ri->ri_rows; 487 igsfb_stdscreen.ncols = ri->ri_cols; 488 igsfb_stdscreen.textops = &ri->ri_ops; 489 igsfb_stdscreen.capabilities = ri->ri_caps; 490 } 491 492 493 /* 494 * Init cursor data in dc_cursor for the accelerated text cursor. 495 */ 496 static int 497 igsfb_make_text_cursor(dc) 498 struct igsfb_devconfig *dc; 499 { 500 struct wsdisplay_font *f = dc->dc_ri.ri_font; 501 u_int16_t cc_scan[8]; /* one sprite scanline */ 502 u_int16_t s; 503 int w, i; 504 505 KASSERT(f->fontwidth <= IGS_CURSOR_MAX_SIZE); 506 KASSERT(f->fontheight <= IGS_CURSOR_MAX_SIZE); 507 508 w = f->fontwidth; 509 for (i = 0; i < f->stride; ++i) { 510 if (w >= 8) { 511 s = 0xffff; /* all inverted */ 512 w -= 8; 513 } else { 514 /* first w pixels inverted, the rest is transparent */ 515 s = ~(0x5555 << (w * 2)); 516 if (IGSFB_HW_SOFT_BSWAP(dc)) 517 s = bswap16(s); 518 w = 0; 519 } 520 cc_scan[i] = s; 521 } 522 523 dc->dc_cursor.cc_size.x = f->fontwidth; 524 dc->dc_cursor.cc_size.y = f->fontheight; 525 526 dc->dc_cursor.cc_hot.x = 0; 527 dc->dc_cursor.cc_hot.y = 0; 528 529 /* init sprite array to be all transparent */ 530 memset(dc->dc_cursor.cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE); 531 532 for (i = 0; i < f->fontheight; ++i) 533 memcpy(&dc->dc_cursor.cc_sprite[i * 8], 534 cc_scan, f->stride * sizeof(u_int16_t)); 535 536 return (0); 537 } 538 539 540 /* 541 * Spread a byte (abcd.efgh) into two (0a0b.0c0d 0e0f.0g0h). 542 * Helper function for igsfb_init_bit_table(). 543 */ 544 static u_int16_t 545 igsfb_spread_bits_8(b) 546 u_int8_t b; 547 { 548 u_int16_t s = b; 549 550 s = ((s & 0x00f0) << 4) | (s & 0x000f); 551 s = ((s & 0x0c0c) << 2) | (s & 0x0303); 552 s = ((s & 0x2222) << 1) | (s & 0x1111); 553 return (s); 554 } 555 556 557 /* 558 * Cursor sprite data are in 2bpp. Incoming image/mask are in 1bpp. 559 * Prebuild the table to expand 1bpp->2bpp, with bswapping if neccessary. 560 */ 561 static void 562 igsfb_init_bit_table(dc) 563 struct igsfb_devconfig *dc; 564 { 565 u_int16_t *expand = dc->dc_bexpand; 566 int need_bswap = IGSFB_HW_SOFT_BSWAP(dc); 567 u_int16_t s; 568 u_int i; 569 570 for (i = 0; i < 256; ++i) { 571 s = igsfb_spread_bits_8(i); 572 expand[i] = need_bswap ? bswap16(s) : s; 573 } 574 } 575 576 577 /* 578 * wsdisplay_accessops: mmap() 579 * XXX: allow mmapping i/o mapped i/o regs if INSECURE??? 580 */ 581 static paddr_t 582 igsfb_mmap(v, offset, prot) 583 void *v; 584 off_t offset; 585 int prot; 586 { 587 struct igsfb_devconfig *dc = v; 588 589 if (offset >= dc->dc_memsz || offset < 0) 590 return (-1); 591 592 return (bus_space_mmap(dc->dc_memt, dc->dc_memaddr, offset, prot, 593 dc->dc_memflags | BUS_SPACE_MAP_LINEAR)); 594 } 595 596 597 /* 598 * wsdisplay_accessops: ioctl() 599 */ 600 static int 601 igsfb_ioctl(v, cmd, data, flag, p) 602 void *v; 603 u_long cmd; 604 caddr_t data; 605 int flag; 606 struct proc *p; 607 { 608 struct igsfb_devconfig *dc = v; 609 struct rasops_info *ri; 610 int cursor_busy; 611 int turnoff; 612 613 /* don't permit cursor ioctls if we use sprite for text cursor */ 614 cursor_busy = !dc->dc_mapped 615 && (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR); 616 617 switch (cmd) { 618 619 case WSDISPLAYIO_GTYPE: 620 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 621 return (0); 622 623 case WSDISPLAYIO_GINFO: 624 ri = &dc->dc_ri; 625 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 626 wsd_fbip->height = ri->ri_height; 627 wsd_fbip->width = ri->ri_width; 628 wsd_fbip->depth = ri->ri_depth; 629 wsd_fbip->cmsize = IGS_CMAP_SIZE; 630 #undef wsd_fbip 631 return (0); 632 633 case WSDISPLAYIO_SMODE: 634 #define d (*(int *)data) 635 if (d == WSDISPLAYIO_MODE_MAPPED) 636 dc->dc_mapped = 1; 637 else { 638 dc->dc_mapped = 0; 639 /* reinit sprite for text cursor */ 640 if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) { 641 igsfb_make_text_cursor(dc); 642 dc->dc_curenb = 0; 643 igsfb_update_cursor(dc, 644 WSDISPLAY_CURSOR_DOSHAPE 645 | WSDISPLAY_CURSOR_DOCUR); 646 } 647 } 648 return (0); 649 650 case WSDISPLAYIO_GVIDEO: 651 *(u_int *)data = dc->dc_blanked ? 652 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 653 return (0); 654 655 case WSDISPLAYIO_SVIDEO: 656 turnoff = (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF); 657 if (dc->dc_blanked != turnoff) { 658 dc->dc_blanked = turnoff; 659 igsfb_blank_screen(dc, dc->dc_blanked); 660 } 661 return (0); 662 663 case WSDISPLAYIO_GETCMAP: 664 return (igsfb_get_cmap(dc, (struct wsdisplay_cmap *)data)); 665 666 case WSDISPLAYIO_PUTCMAP: 667 return (igsfb_set_cmap(dc, (struct wsdisplay_cmap *)data)); 668 669 case WSDISPLAYIO_GCURMAX: 670 ((struct wsdisplay_curpos *)data)->x = IGS_CURSOR_MAX_SIZE; 671 ((struct wsdisplay_curpos *)data)->y = IGS_CURSOR_MAX_SIZE; 672 return (0); 673 674 case WSDISPLAYIO_GCURPOS: 675 if (cursor_busy) 676 return (EBUSY); 677 *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos; 678 return (0); 679 680 case WSDISPLAYIO_SCURPOS: 681 if (cursor_busy) 682 return (EBUSY); 683 igsfb_set_curpos(dc, (struct wsdisplay_curpos *)data); 684 return (0); 685 686 case WSDISPLAYIO_GCURSOR: 687 if (cursor_busy) 688 return (EBUSY); 689 return (igsfb_get_cursor(dc, (struct wsdisplay_cursor *)data)); 690 691 case WSDISPLAYIO_SCURSOR: 692 if (cursor_busy) 693 return (EBUSY); 694 return (igsfb_set_cursor(dc, (struct wsdisplay_cursor *)data)); 695 } 696 697 return (EPASSTHROUGH); 698 } 699 700 701 /* 702 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SVIDEO) 703 */ 704 static void 705 igsfb_blank_screen(dc, blank) 706 struct igsfb_devconfig *dc; 707 int blank; 708 { 709 710 igs_ext_write(dc->dc_iot, dc->dc_ioh, 711 IGS_EXT_SYNC_CTL, 712 blank ? IGS_EXT_SYNC_H0 | IGS_EXT_SYNC_V0 713 : 0); 714 } 715 716 717 /* 718 * wsdisplay_accessops: ioctl(WSDISPLAYIO_GETCMAP) 719 * Served from the software cmap copy. 720 */ 721 static int 722 igsfb_get_cmap(dc, p) 723 struct igsfb_devconfig *dc; 724 struct wsdisplay_cmap *p; 725 { 726 u_int index, count; 727 int err; 728 729 index = p->index; 730 count = p->count; 731 732 if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index) 733 return (EINVAL); 734 735 err = copyout(&dc->dc_cmap.r[index], p->red, count); 736 if (err) 737 return (err); 738 err = copyout(&dc->dc_cmap.g[index], p->green, count); 739 if (err) 740 return (err); 741 err = copyout(&dc->dc_cmap.b[index], p->blue, count); 742 if (err) 743 return (err); 744 745 return (0); 746 } 747 748 749 /* 750 * wsdisplay_accessops: ioctl(WSDISPLAYIO_PUTCMAP) 751 * Set the software cmap copy and propagate changed range to the device. 752 */ 753 static int 754 igsfb_set_cmap(dc, p) 755 struct igsfb_devconfig *dc; 756 const struct wsdisplay_cmap *p; 757 { 758 u_int index, count; 759 uint8_t r[IGS_CMAP_SIZE]; 760 uint8_t g[IGS_CMAP_SIZE]; 761 uint8_t b[IGS_CMAP_SIZE]; 762 int error; 763 764 index = p->index; 765 count = p->count; 766 if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index) 767 return (EINVAL); 768 error = copyin(p->red, &r[index], count); 769 if (error) 770 return error; 771 error = copyin(p->green, &g[index], count); 772 if (error) 773 return error; 774 error = copyin(p->blue, &b[index], count); 775 if (error) 776 return error; 777 778 memcpy(&dc->dc_cmap.r[index], &r[index], count); 779 memcpy(&dc->dc_cmap.g[index], &g[index], count); 780 memcpy(&dc->dc_cmap.b[index], &b[index], count); 781 782 /* propagate changes to the device */ 783 igsfb_update_cmap(dc, index, count); 784 return (0); 785 } 786 787 788 /* 789 * Propagate specified part of the software cmap copy to the device. 790 */ 791 static void 792 igsfb_update_cmap(dc, index, count) 793 struct igsfb_devconfig *dc; 794 u_int index, count; 795 { 796 bus_space_tag_t t; 797 bus_space_handle_t h; 798 u_int last, i; 799 800 if (index >= IGS_CMAP_SIZE) 801 return; 802 803 last = index + count; 804 if (last > IGS_CMAP_SIZE) 805 last = IGS_CMAP_SIZE; 806 807 t = dc->dc_iot; 808 h = dc->dc_ioh; 809 810 /* start palette writing, index is autoincremented by hardware */ 811 bus_space_write_1(t, h, IGS_DAC_PEL_WRITE_IDX, index); 812 813 for (i = index; i < last; ++i) { 814 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.r[i]); 815 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.g[i]); 816 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.b[i]); 817 } 818 } 819 820 821 /* 822 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURPOS) 823 */ 824 static void 825 igsfb_set_curpos(dc, curpos) 826 struct igsfb_devconfig *dc; 827 const struct wsdisplay_curpos *curpos; 828 { 829 struct rasops_info *ri = &dc->dc_ri; 830 u_int x = curpos->x, y = curpos->y; 831 832 if (x >= ri->ri_width) 833 x = ri->ri_width - 1; 834 if (y >= ri->ri_height) 835 y = ri->ri_height - 1; 836 837 dc->dc_cursor.cc_pos.x = x; 838 dc->dc_cursor.cc_pos.y = y; 839 840 /* propagate changes to the device */ 841 igsfb_update_curpos(dc); 842 } 843 844 845 static void 846 igsfb_update_curpos(dc) 847 struct igsfb_devconfig *dc; 848 { 849 bus_space_tag_t t; 850 bus_space_handle_t h; 851 int x, xoff, y, yoff; 852 853 xoff = 0; 854 x = dc->dc_cursor.cc_pos.x - dc->dc_cursor.cc_hot.x; 855 if (x < 0) { 856 xoff = -x; 857 x = 0; 858 } 859 860 yoff = 0; 861 y = dc->dc_cursor.cc_pos.y - dc->dc_cursor.cc_hot.y; 862 if (y < 0) { 863 yoff = -y; 864 y = 0; 865 } 866 867 t = dc->dc_iot; 868 h = dc->dc_ioh; 869 870 igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_LO, x & 0xff); 871 igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_HI, (x >> 8) & 0x07); 872 igs_ext_write(t, h, IGS_EXT_SPRITE_HPRESET, xoff & 0x3f); 873 874 igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_LO, y & 0xff); 875 igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_HI, (y >> 8) & 0x07); 876 igs_ext_write(t, h, IGS_EXT_SPRITE_VPRESET, yoff & 0x3f); 877 } 878 879 880 /* 881 * wsdisplay_accessops: ioctl(WSDISPLAYIO_GCURSOR) 882 */ 883 static int 884 igsfb_get_cursor(dc, p) 885 struct igsfb_devconfig *dc; 886 struct wsdisplay_cursor *p; 887 { 888 889 /* XXX: TODO */ 890 return (0); 891 } 892 893 894 /* 895 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURSOR) 896 */ 897 static int 898 igsfb_set_cursor(dc, p) 899 struct igsfb_devconfig *dc; 900 const struct wsdisplay_cursor *p; 901 { 902 struct igs_hwcursor *cc; 903 struct wsdisplay_curpos pos, hot; 904 u_int v, index, count, icount, iwidth; 905 uint8_t r[2], g[2], b[2], image[512], mask[512]; 906 int error; 907 908 cc = &dc->dc_cursor; 909 v = p->which; 910 index = count = icount = iwidth = 0; /* XXX: gcc */ 911 912 /* copy in the new cursor colormap */ 913 if (v & WSDISPLAY_CURSOR_DOCMAP) { 914 index = p->cmap.index; 915 count = p->cmap.count; 916 if (index >= 2 || (index + count) > 2) 917 return (EINVAL); 918 error = copyin(p->cmap.red, &r[index], count); 919 if (error) 920 return error; 921 error = copyin(p->cmap.green, &g[index], count); 922 if (error) 923 return error; 924 error = copyin(p->cmap.blue, &b[index], count); 925 if (error) 926 return error; 927 } 928 929 /* verify that the new cursor data are valid */ 930 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 931 if (p->size.x > IGS_CURSOR_MAX_SIZE 932 || p->size.y > IGS_CURSOR_MAX_SIZE) 933 return (EINVAL); 934 935 iwidth = (p->size.x + 7) >> 3; /* bytes per scan line */ 936 icount = iwidth * p->size.y; 937 error = copyin(p->image, image, icount); 938 if (error) 939 return error; 940 error = copyin(p->mask, mask, icount); 941 if (error) 942 return error; 943 } 944 945 /* enforce that the position is within screen bounds */ 946 if (v & WSDISPLAY_CURSOR_DOPOS) { 947 struct rasops_info *ri = &dc->dc_ri; 948 949 pos = p->pos; /* local copy we can write to */ 950 if (pos.x >= ri->ri_width) 951 pos.x = ri->ri_width - 1; 952 if (pos.y >= ri->ri_height) 953 pos.y = ri->ri_height - 1; 954 } 955 956 /* enforce that the hot spot is within sprite bounds */ 957 if (v & WSDISPLAY_CURSOR_DOHOT) 958 hot = p->hot; /* local copy we can write to */ 959 960 if (v & (WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOSHAPE)) { 961 const struct wsdisplay_curpos *nsize; 962 struct wsdisplay_curpos *nhot; 963 964 nsize = (v & WSDISPLAY_CURSOR_DOSHAPE) ? 965 &p->size : &cc->cc_size; 966 nhot = (v & WSDISPLAY_CURSOR_DOHOT) ? &hot : &cc->cc_hot; 967 968 if (nhot->x >= nsize->x) 969 nhot->x = nsize->x - 1; 970 if (nhot->y >= nsize->y) 971 nhot->y = nsize->y - 1; 972 } 973 974 /* copy data to the driver's cursor info */ 975 if (v & WSDISPLAY_CURSOR_DOCUR) 976 dc->dc_curenb = p->enable; 977 if (v & WSDISPLAY_CURSOR_DOPOS) 978 cc->cc_pos = pos; /* local copy, possibly corrected */ 979 if (v & WSDISPLAY_CURSOR_DOHOT) 980 cc->cc_hot = hot; /* local copy, possibly corrected */ 981 if (v & WSDISPLAY_CURSOR_DOCMAP) { 982 memcpy(&cc->cc_color[index], &r[index], count); 983 memcpy(&cc->cc_color[index + 2], &g[index], count); 984 memcpy(&cc->cc_color[index + 4], &b[index], count); 985 } 986 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 987 u_int trailing_bits; 988 989 memcpy(cc->cc_image, image, icount); 990 memcpy(cc->cc_mask, mask, icount); 991 cc->cc_size = p->size; 992 993 /* clear trailing bits in the "partial" mask bytes */ 994 trailing_bits = p->size.x & 0x07; 995 if (trailing_bits != 0) { 996 const u_int cutmask = ~((~0) << trailing_bits); 997 u_char *mp; 998 u_int i; 999 1000 mp = cc->cc_mask + iwidth - 1; 1001 for (i = 0; i < p->size.y; ++i) { 1002 *mp &= cutmask; 1003 mp += iwidth; 1004 } 1005 } 1006 igsfb_convert_cursor_data(dc, iwidth, p->size.y); 1007 } 1008 1009 /* propagate changes to the device */ 1010 igsfb_update_cursor(dc, v); 1011 1012 return (0); 1013 } 1014 1015 1016 /* 1017 * Convert incoming 1bpp cursor image/mask into native 2bpp format. 1018 */ 1019 static void 1020 igsfb_convert_cursor_data(dc, width, height) 1021 struct igsfb_devconfig *dc; 1022 u_int width, height; 1023 { 1024 struct igs_hwcursor *cc = &dc->dc_cursor; 1025 u_int16_t *expand = dc->dc_bexpand; 1026 u_int8_t *ip, *mp; 1027 u_int16_t is, ms, *dp; 1028 u_int line, i; 1029 1030 /* init sprite to be all transparent */ 1031 memset(cc->cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE); 1032 1033 /* first scanline */ 1034 ip = cc->cc_image; 1035 mp = cc->cc_mask; 1036 dp = cc->cc_sprite; 1037 1038 for (line = 0; line < height; ++line) { 1039 for (i = 0; i < width; ++i) { 1040 is = expand[ip[i]]; /* image: 0 -> 00, 1 -> 01 */ 1041 ms = expand[mp[i]]; /* mask: 0 -> 00, 1 -> 11 */ 1042 ms |= (ms << 1); 1043 dp[i] = (0xaaaa & ~ms) | (is & ms); 1044 } 1045 1046 /* next scanline */ 1047 ip += width; 1048 mp += width; 1049 dp += 8; /* 64 pixels, 2bpp, 8 pixels per short = 8 shorts */ 1050 } 1051 } 1052 1053 1054 /* 1055 * Propagate cursor changes to the device. 1056 * "which" is composed of WSDISPLAY_CURSOR_DO* bits. 1057 */ 1058 static void 1059 igsfb_update_cursor(dc, which) 1060 struct igsfb_devconfig *dc; 1061 u_int which; 1062 { 1063 bus_space_tag_t iot = dc->dc_iot; 1064 bus_space_handle_t ioh = dc->dc_ioh; 1065 u_int8_t curctl; 1066 1067 curctl = 0; /* XXX: gcc */ 1068 1069 /* 1070 * We will need to tweak sprite control register for cursor 1071 * visibility and cursor color map manipualtion. 1072 */ 1073 if (which & (WSDISPLAY_CURSOR_DOCUR | WSDISPLAY_CURSOR_DOCMAP)) { 1074 curctl = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL); 1075 } 1076 1077 if (which & WSDISPLAY_CURSOR_DOSHAPE) { 1078 u_int8_t *dst = bus_space_vaddr(dc->dc_memt, dc->dc_crh); 1079 1080 /* 1081 * memcpy between spaces of different endianness would 1082 * be ... special. We cannot be sure if memcpy gonna 1083 * push data in 4-byte chunks, we can't pre-bswap it, 1084 * so do it byte-by-byte to preserve byte ordering. 1085 */ 1086 if (IGSFB_HW_SOFT_BSWAP(dc)) { 1087 u_int8_t *src = (u_int8_t *)dc->dc_cursor.cc_sprite; 1088 int i; 1089 1090 for (i = 0; i < IGS_CURSOR_DATA_SIZE; ++i) 1091 *dst++ = *src++; 1092 } else { 1093 memcpy(dst, dc->dc_cursor.cc_sprite, 1094 IGS_CURSOR_DATA_SIZE); 1095 } 1096 } 1097 1098 if (which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 1099 /* code shared with WSDISPLAYIO_SCURPOS */ 1100 igsfb_update_curpos(dc); 1101 } 1102 1103 if (which & WSDISPLAY_CURSOR_DOCMAP) { 1104 u_int8_t *p; 1105 1106 /* tell DAC we want access to the cursor palette */ 1107 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1108 curctl | IGS_EXT_SPRITE_DAC_PEL); 1109 1110 p = dc->dc_cursor.cc_color; 1111 1112 bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 0); 1113 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[0]); 1114 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[2]); 1115 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[4]); 1116 1117 bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 1); 1118 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[1]); 1119 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[3]); 1120 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[5]); 1121 1122 /* restore access to the normal palette */ 1123 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, curctl); 1124 } 1125 1126 if (which & WSDISPLAY_CURSOR_DOCUR) { 1127 if ((curctl & IGS_EXT_SPRITE_VISIBLE) == 0 1128 && dc->dc_curenb) 1129 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1130 curctl | IGS_EXT_SPRITE_VISIBLE); 1131 else if ((curctl & IGS_EXT_SPRITE_VISIBLE) != 0 1132 && !dc->dc_curenb) 1133 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 1134 curctl & ~IGS_EXT_SPRITE_VISIBLE); 1135 } 1136 } 1137 1138 1139 /* 1140 * wsdisplay_accessops: alloc_screen() 1141 */ 1142 static int 1143 igsfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 1144 void *v; 1145 const struct wsscreen_descr *type; 1146 void **cookiep; 1147 int *curxp, *curyp; 1148 long *attrp; 1149 { 1150 struct igsfb_devconfig *dc = v; 1151 struct rasops_info *ri = &dc->dc_ri; 1152 1153 if (dc->dc_nscreens > 0) /* only do single screen for now */ 1154 return (ENOMEM); 1155 1156 dc->dc_nscreens = 1; 1157 1158 *cookiep = ri; /* emulcookie for igsgfb_stdscreen.textops */ 1159 *curxp = *curyp = 0; /* cursor position */ 1160 (*ri->ri_ops.allocattr)(ri, 1161 WSCOL_BLACK, /* fg */ 1162 WSCOL_BLACK, /* bg */ 1163 0, /* wsattr */ 1164 attrp); 1165 return (0); 1166 } 1167 1168 1169 /* 1170 * wsdisplay_accessops: free_screen() 1171 */ 1172 static void 1173 igsfb_free_screen(v, cookie) 1174 void *v; 1175 void *cookie; 1176 { 1177 1178 /* XXX */ 1179 return; 1180 } 1181 1182 1183 /* 1184 * wsdisplay_accessops: show_screen() 1185 */ 1186 static int 1187 igsfb_show_screen(v, cookie, waitok, cb, cbarg) 1188 void *v; 1189 void *cookie; 1190 int waitok; 1191 void (*cb)(void *, int, int); 1192 void *cbarg; 1193 { 1194 1195 /* XXX */ 1196 return (0); 1197 } 1198 1199 1200 1201 /* 1202 * Accelerated text mode cursor that uses hardware sprite. 1203 */ 1204 static void 1205 igsfb_accel_cursor(cookie, on, row, col) 1206 void *cookie; 1207 int on, row, col; 1208 { 1209 struct rasops_info *ri = (struct rasops_info *)cookie; 1210 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1211 struct igs_hwcursor *cc = &dc->dc_cursor; 1212 u_int which; 1213 1214 ri->ri_crow = row; 1215 ri->ri_ccol = col; 1216 1217 which = 0; 1218 if (on) { 1219 ri->ri_flg |= RI_CURSOR; 1220 1221 /* only bother to move the cursor if it's visibile */ 1222 cc->cc_pos.x = ri->ri_xorigin 1223 + ri->ri_ccol * ri->ri_font->fontwidth; 1224 cc->cc_pos.y = ri->ri_yorigin 1225 + ri->ri_crow * ri->ri_font->fontheight; 1226 which |= WSDISPLAY_CURSOR_DOPOS; 1227 } else 1228 ri->ri_flg &= ~RI_CURSOR; 1229 1230 if (dc->dc_curenb != on) { 1231 dc->dc_curenb = on; 1232 which |= WSDISPLAY_CURSOR_DOCUR; 1233 } 1234 1235 /* propagate changes to the device */ 1236 igsfb_update_cursor(dc, which); 1237 } 1238 1239 1240 1241 /* 1242 * Accelerated raster ops that use graphic coprocessor. 1243 */ 1244 1245 static int 1246 igsfb_accel_wait(dc) 1247 struct igsfb_devconfig *dc; 1248 { 1249 bus_space_tag_t t = dc->dc_iot; 1250 bus_space_handle_t h = dc->dc_coph; 1251 int timo = 100000; 1252 u_int8_t reg; 1253 1254 while (timo--) { 1255 reg = bus_space_read_1(t, h, IGS_COP_CTL_REG); 1256 if ((reg & IGS_COP_CTL_BUSY) == 0) 1257 return (0); 1258 } 1259 1260 return (1); 1261 } 1262 1263 1264 static void 1265 igsfb_accel_copy(dc, src, dst, width, height) 1266 struct igsfb_devconfig *dc; 1267 u_int32_t src, dst; 1268 u_int16_t width, height; 1269 { 1270 bus_space_tag_t t = dc->dc_iot; 1271 bus_space_handle_t h = dc->dc_coph; 1272 u_int32_t toend; 1273 u_int8_t drawcmd; 1274 1275 drawcmd = IGS_COP_DRAW_ALL; 1276 if (dst > src) { 1277 toend = dc->dc_ri.ri_width * (height - 1) + (width - 1); 1278 src += toend; 1279 dst += toend; 1280 drawcmd |= IGS_COP_OCTANT_X_NEG | IGS_COP_OCTANT_Y_NEG; 1281 } 1282 1283 igsfb_accel_wait(dc); 1284 bus_space_write_1(t, h, IGS_COP_CTL_REG, 0); 1285 1286 bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S); 1287 1288 bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1); 1289 bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1); 1290 1291 bus_space_write_4(t, h, IGS_COP_SRC_START_REG, src); 1292 bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst); 1293 1294 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, drawcmd); 1295 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG); 1296 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0); 1297 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG, 1298 IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC); 1299 } 1300 1301 static void 1302 igsfb_accel_fill(dc, color, dst, width, height) 1303 struct igsfb_devconfig *dc; 1304 u_int32_t color; 1305 u_int32_t dst; 1306 u_int16_t width, height; 1307 { 1308 bus_space_tag_t t = dc->dc_iot; 1309 bus_space_handle_t h = dc->dc_coph; 1310 1311 igsfb_accel_wait(dc); 1312 bus_space_write_1(t, h, IGS_COP_CTL_REG, 0); 1313 1314 bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S); 1315 1316 bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1); 1317 bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1); 1318 1319 bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst); 1320 bus_space_write_4(t, h, IGS_COP_FG_REG, color); 1321 1322 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, IGS_COP_DRAW_ALL); 1323 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG); 1324 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0); 1325 bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG, IGS_COP_OP_PXBLT); 1326 } 1327 1328 1329 static void 1330 igsfb_accel_copyrows(cookie, src, dst, num) 1331 void *cookie; 1332 int src, dst, num; 1333 { 1334 struct rasops_info *ri = (struct rasops_info *)cookie; 1335 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1336 u_int32_t srp, dsp; 1337 u_int16_t width, height; 1338 1339 width = ri->ri_emuwidth; 1340 height = num * ri->ri_font->fontheight; 1341 1342 srp = ri->ri_xorigin 1343 + ri->ri_width * (ri->ri_yorigin 1344 + src * ri->ri_font->fontheight); 1345 dsp = ri->ri_xorigin 1346 + ri->ri_width * (ri->ri_yorigin 1347 + dst * ri->ri_font->fontheight); 1348 1349 igsfb_accel_copy(dc, srp, dsp, width, height); 1350 } 1351 1352 1353 void 1354 igsfb_accel_copycols(cookie, row, src, dst, num) 1355 void *cookie; 1356 int row, src, dst, num; 1357 { 1358 struct rasops_info *ri = (struct rasops_info *)cookie; 1359 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1360 u_int32_t rowp, srp, dsp; 1361 u_int16_t width, height; 1362 1363 width = num * ri->ri_font->fontwidth; 1364 height = ri->ri_font->fontheight; 1365 1366 rowp = ri->ri_xorigin 1367 + ri->ri_width * (ri->ri_yorigin 1368 + row * ri->ri_font->fontheight); 1369 1370 srp = rowp + src * ri->ri_font->fontwidth; 1371 dsp = rowp + dst * ri->ri_font->fontwidth; 1372 1373 igsfb_accel_copy(dc, srp, dsp, width, height); 1374 } 1375 1376 1377 static void 1378 igsfb_accel_eraserows(cookie, row, num, attr) 1379 void *cookie; 1380 int row, num; 1381 long attr; 1382 { 1383 struct rasops_info *ri = (struct rasops_info *)cookie; 1384 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1385 u_int32_t color; 1386 u_int32_t dsp; 1387 u_int16_t width, height; 1388 1389 width = ri->ri_emuwidth; 1390 height = num * ri->ri_font->fontheight; 1391 1392 dsp = ri->ri_xorigin 1393 + ri->ri_width * (ri->ri_yorigin 1394 + row * ri->ri_font->fontheight); 1395 1396 /* XXX: we "know" the encoding that rasops' allocattr uses */ 1397 color = (attr >> 16) & 0xff; 1398 1399 igsfb_accel_fill(dc, color, dsp, width, height); 1400 } 1401 1402 1403 void 1404 igsfb_accel_erasecols(cookie, row, col, num, attr) 1405 void *cookie; 1406 int row, col, num; 1407 long attr; 1408 { 1409 struct rasops_info *ri = (struct rasops_info *)cookie; 1410 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1411 u_int32_t color; 1412 u_int32_t rowp, dsp; 1413 u_int16_t width, height; 1414 1415 width = num * ri->ri_font->fontwidth; 1416 height = ri->ri_font->fontheight; 1417 1418 rowp = ri->ri_xorigin 1419 + ri->ri_width * (ri->ri_yorigin 1420 + row * ri->ri_font->fontheight); 1421 1422 dsp = rowp + col * ri->ri_font->fontwidth; 1423 1424 /* XXX: we "know" the encoding that rasops' allocattr uses */ 1425 color = (attr >> 16) & 0xff; 1426 1427 igsfb_accel_fill(dc, color, dsp, width, height); 1428 } 1429 1430 1431 /* 1432 * Not really implemented here, but we need to hook into the one 1433 * supplied by rasops so that we can synchronize with the COP. 1434 */ 1435 static void 1436 igsfb_accel_putchar(cookie, row, col, uc, attr) 1437 void *cookie; 1438 int row, col; 1439 u_int uc; 1440 long attr; 1441 { 1442 struct rasops_info *ri = (struct rasops_info *)cookie; 1443 struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw; 1444 1445 igsfb_accel_wait(dc); 1446 (*dc->dc_ri_putchar)(cookie, row, col, uc, attr); 1447 } 1448