1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16 /* 17 * Framebuffer based console support. 18 * 19 * Missing (no particular order): 20 * memory barriers 21 * shadow buffering 22 * copyin for userspace calls and then polled io split. 23 * callbacks for hw blt() and others? 24 */ 25 #include <sys/types.h> 26 #include <sys/visual_io.h> 27 #include <sys/fbio.h> 28 #include <sys/ddi.h> 29 #include <sys/kd.h> 30 #include <sys/sunddi.h> 31 #include <sys/rgb.h> 32 #include <sys/gfx_private.h> 33 #include "gfxp_fb.h" 34 35 #define MYNAME "gfxp_bitmap" 36 37 static ddi_device_acc_attr_t dev_attr = { 38 DDI_DEVICE_ATTR_V0, 39 DDI_NEVERSWAP_ACC, 40 DDI_MERGING_OK_ACC 41 }; 42 43 /* default structure for FBIOGATTR ioctl */ 44 static struct fbgattr bitmap_attr = { 45 /* real_type owner */ 46 FBTYPE_MEMCOLOR, 0, 47 /* fbtype: type h w depth cms size */ 48 { FBTYPE_MEMCOLOR, 0, 0, 0, 0, 0 }, 49 /* fbsattr: flags emu_type dev_specific */ 50 { 0, FBTYPE_MEMCOLOR, { 0 } }, 51 /* emu_types */ 52 { -1 } 53 }; 54 55 static struct vis_identifier gfxp_bitmap_ident = { "illumos_fb" }; 56 57 static void bitmap_copy_fb(struct gfxp_fb_softc *, uint8_t *, uint8_t *); 58 static int bitmap_kdsetmode(struct gfxp_fb_softc *, int); 59 static int bitmap_devinit(struct gfxp_fb_softc *, struct vis_devinit *); 60 static void bitmap_cons_copy(struct gfxp_fb_softc *, struct vis_conscopy *); 61 static void bitmap_cons_display(struct gfxp_fb_softc *, 62 struct vis_consdisplay *); 63 static int bitmap_cons_clear(struct gfxp_fb_softc *, 64 struct vis_consclear *); 65 static void bitmap_cons_cursor(struct gfxp_fb_softc *, 66 struct vis_conscursor *); 67 static uint32_t bitmap_color_map(uint8_t); 68 static void bitmap_polled_copy(struct vis_polledio_arg *, 69 struct vis_conscopy *); 70 static void bitmap_polled_display(struct vis_polledio_arg *, 71 struct vis_consdisplay *); 72 static void bitmap_polled_cursor(struct vis_polledio_arg *, 73 struct vis_conscursor *); 74 static int bitmap_suspend(struct gfxp_fb_softc *softc); 75 static void bitmap_resume(struct gfxp_fb_softc *softc); 76 static int bitmap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, 77 size_t len, size_t *maplen, uint_t model, void *ptr); 78 79 static struct gfxp_ops gfxp_bitmap_ops = { 80 .ident = &gfxp_bitmap_ident, 81 .kdsetmode = bitmap_kdsetmode, 82 .devinit = bitmap_devinit, 83 .cons_copy = bitmap_cons_copy, 84 .cons_display = bitmap_cons_display, 85 .cons_cursor = bitmap_cons_cursor, 86 .cons_clear = bitmap_cons_clear, 87 .suspend = bitmap_suspend, 88 .resume = bitmap_resume, 89 .devmap = bitmap_devmap 90 }; 91 92 void 93 gfxp_bm_register_fbops(gfxp_fb_softc_ptr_t ptr, struct gfxp_blt_ops *ops) 94 { 95 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr; 96 97 if (softc != NULL) { 98 softc->blt_ops.blt = ops->blt; 99 softc->blt_ops.copy = ops->copy; 100 softc->blt_ops.clear = ops->clear; 101 softc->blt_ops.setmode = ops->setmode; 102 } 103 } 104 105 void 106 gfxp_bm_getfb_info(gfxp_fb_softc_ptr_t ptr, struct gfxp_bm_fb_info *fbip) 107 { 108 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr; 109 110 switch (softc->fb_type) { 111 case GFXP_BITMAP: 112 fbip->xres = softc->console->fb.screen.x; 113 fbip->yres = softc->console->fb.screen.y; 114 fbip->bpp = softc->console->fb.bpp; 115 fbip->depth = softc->console->fb.depth; 116 break; 117 case GFXP_VGATEXT: 118 /* 119 * By current knowledge, DRM can not cope with text mode 120 * and the VGA is disabled. The proper approach here 121 * is to set all values to 0. See the drm_getfb_size() and 122 * the i915_gem_init() how the size is used. 123 */ 124 fbip->xres = 0; 125 fbip->yres = 0; 126 fbip->bpp = 0; 127 fbip->depth = 0; 128 break; 129 } 130 } 131 132 int 133 gfxp_bm_attach(dev_info_t *devi __unused, struct gfxp_fb_softc *softc) 134 { 135 softc->polledio.display = bitmap_polled_display; 136 softc->polledio.copy = bitmap_polled_copy; 137 softc->polledio.cursor = bitmap_polled_cursor; 138 softc->gfxp_ops = &gfxp_bitmap_ops; 139 softc->fbgattr = &bitmap_attr; 140 softc->silent = 0; 141 142 return (DDI_SUCCESS); 143 } 144 145 int 146 gfxp_bm_detach(dev_info_t *devi __unused, struct gfxp_fb_softc *softc) 147 { 148 if (softc == NULL || softc->console == NULL) 149 return (DDI_SUCCESS); 150 151 if (softc->console->fb.fb_size != 0) { 152 gfxp_unmap_kernel_space((gfxp_kva_t)softc->console->fb.fb, 153 softc->console->fb.fb_size); 154 fb_info.fb = NULL; 155 kmem_free(softc->console->fb.shadow_fb, 156 softc->console->fb.fb_size); 157 softc->console->fb.shadow_fb = NULL; 158 } 159 return (DDI_SUCCESS); 160 } 161 162 static void 163 bitmap_kdsettext(struct gfxp_fb_softc *softc) 164 { 165 bitmap_copy_fb(softc, softc->console->fb.shadow_fb, 166 softc->console->fb.fb); 167 } 168 169 static void 170 bitmap_kdsetgraphics(struct gfxp_fb_softc *softc __unused) 171 { 172 /* we have the copy of fb content in shadow_fb */ 173 } 174 175 static int 176 bitmap_suspend(struct gfxp_fb_softc *softc __unused) 177 { 178 /* we have the copy of fb content in shadow_fb */ 179 return (DDI_SUCCESS); 180 } 181 182 static void 183 bitmap_resume(struct gfxp_fb_softc *softc) 184 { 185 bitmap_kdsettext(softc); 186 } 187 188 static int 189 bitmap_kdsetmode(struct gfxp_fb_softc *softc, int mode) 190 { 191 switch (mode) { 192 case KD_TEXT: 193 if (softc->blt_ops.setmode != NULL) 194 softc->blt_ops.setmode(KD_TEXT); 195 bitmap_kdsettext(softc); 196 break; 197 case KD_GRAPHICS: 198 bitmap_kdsetgraphics(softc); 199 if (softc->blt_ops.setmode != NULL) 200 softc->blt_ops.setmode(KD_GRAPHICS); 201 break; 202 case KD_RESETTEXT: 203 /* 204 * In order to avoid racing with a starting X server, 205 * this needs to be a test and set that is performed in 206 * a single (softc->lock protected) ioctl into this driver. 207 */ 208 if (softc->mode == KD_TEXT && softc->silent == 1) { 209 bitmap_kdsettext(softc); 210 } 211 mode = KD_TEXT; 212 break; 213 default: 214 return (EINVAL); 215 } 216 217 softc->mode = mode; 218 return (0); 219 } 220 221 /* 222 * Copy fb_info from early boot and set up the FB 223 */ 224 static int 225 bitmap_setup_fb(struct gfxp_fb_softc *softc) 226 { 227 size_t size; 228 struct gfxfb_info *gfxfb_info; 229 230 softc->console = (union gfx_console *)&fb_info; 231 size = ptob(btopr(fb_info.fb_size)); 232 softc->console->fb.fb_size = size; 233 softc->console->fb.fb = (uint8_t *)gfxp_map_kernel_space(fb_info.paddr, 234 size, GFXP_MEMORY_WRITECOMBINED); 235 if (softc->console->fb.fb == NULL) 236 return (DDI_FAILURE); 237 238 softc->console->fb.shadow_fb = kmem_zalloc(size, KM_SLEEP); 239 240 bitmap_attr.fbtype.fb_height = fb_info.screen.y; 241 bitmap_attr.fbtype.fb_width = fb_info.screen.x; 242 bitmap_attr.fbtype.fb_depth = fb_info.depth; 243 bitmap_attr.fbtype.fb_size = size; 244 if (fb_info.depth == 32) 245 bitmap_attr.fbtype.fb_cmsize = 1 << 24; 246 else 247 bitmap_attr.fbtype.fb_cmsize = 1 << fb_info.depth; 248 249 gfxfb_info = (struct gfxfb_info *)bitmap_attr.sattr.dev_specific; 250 gfxfb_info->terminal_origin_x = fb_info.terminal_origin.x; 251 gfxfb_info->terminal_origin_y = fb_info.terminal_origin.y; 252 gfxfb_info->pitch = fb_info.pitch; 253 gfxfb_info->font_width = fb_info.font_width; 254 gfxfb_info->font_height = fb_info.font_height; 255 gfxfb_info->red_mask_size = fb_info.rgb.red.size; 256 gfxfb_info->red_field_position = fb_info.rgb.red.pos; 257 gfxfb_info->green_mask_size = fb_info.rgb.green.size; 258 gfxfb_info->green_field_position = fb_info.rgb.green.pos; 259 gfxfb_info->blue_mask_size = fb_info.rgb.blue.size; 260 gfxfb_info->blue_field_position = fb_info.rgb.blue.pos; 261 262 return (DDI_SUCCESS); 263 } 264 265 static uint32_t 266 bitmap_color_map(uint8_t index) 267 { 268 uint8_t c, mask; 269 uint32_t color = 0; 270 271 c = cmap4_to_24.red[index]; 272 mask = (1 << fb_info.rgb.red.size) - 1; 273 c >>= 8 - fb_info.rgb.red.size; 274 c &= mask; 275 color |= c << fb_info.rgb.red.pos; 276 277 c = cmap4_to_24.green[index]; 278 mask = (1 << fb_info.rgb.green.size) - 1; 279 c >>= 8 - fb_info.rgb.green.size; 280 c &= mask; 281 color |= c << fb_info.rgb.green.pos; 282 283 c = cmap4_to_24.blue[index]; 284 mask = (1 << fb_info.rgb.blue.size) - 1; 285 c >>= 8 - fb_info.rgb.blue.size; 286 c &= mask; 287 color |= c << fb_info.rgb.blue.pos; 288 289 return (color); 290 } 291 292 static int 293 bitmap_devinit(struct gfxp_fb_softc *softc, struct vis_devinit *data) 294 { 295 union gfx_console *console; 296 297 if (bitmap_setup_fb(softc) == DDI_FAILURE) 298 return (1); 299 300 console = softc->console; 301 302 /* make sure we have current state of the screen */ 303 bitmap_copy_fb(softc, console->fb.fb, console->fb.shadow_fb); 304 305 /* initialize console instance */ 306 data->version = VIS_CONS_REV; 307 data->width = console->fb.screen.x; 308 data->height = console->fb.screen.y; 309 data->linebytes = console->fb.pitch; 310 data->color_map = bitmap_color_map; 311 data->depth = console->fb.depth; 312 data->mode = VIS_PIXEL; 313 data->polledio = &softc->polledio; 314 #if 0 315 data->modechg_cb; 316 data->modechg_arg; 317 #endif 318 return (0); 319 } 320 321 /* Buffer to Buffer copy */ 322 static void 323 bitmap_copy_fb(struct gfxp_fb_softc *softc, uint8_t *src, uint8_t *dst) 324 { 325 uint32_t i, pitch, height; 326 327 pitch = softc->console->fb.pitch; 328 height = softc->console->fb.screen.y; 329 330 for (i = 0; i < height; i++) { 331 (void) memmove(dst + i * pitch, src + i * pitch, pitch); 332 } 333 } 334 335 static void 336 bitmap_cons_copy(struct gfxp_fb_softc *softc, struct vis_conscopy *ma) 337 { 338 union gfx_console *console; 339 uint32_t soffset, toffset; 340 uint32_t width, height, pitch; 341 uint8_t *src, *dst, *sdst; 342 int i; 343 344 console = softc->console; 345 soffset = ma->s_col * console->fb.bpp + ma->s_row * console->fb.pitch; 346 toffset = ma->t_col * console->fb.bpp + ma->t_row * console->fb.pitch; 347 src = console->fb.shadow_fb + soffset; 348 dst = console->fb.fb + toffset; 349 sdst = console->fb.shadow_fb + toffset; 350 width = (ma->e_col - ma->s_col + 1) * console->fb.bpp; 351 height = ma->e_row - ma->s_row + 1; 352 pitch = console->fb.pitch; 353 354 if (toffset <= soffset) { 355 for (i = 0; i < height; i++) { 356 uint32_t increment = i * pitch; 357 if (softc->mode == KD_TEXT) { 358 (void) memmove(dst + increment, 359 src + increment, width); 360 } 361 (void) memmove(sdst + increment, src + increment, 362 width); 363 } 364 } else { 365 for (i = height - 1; i >= 0; i--) { 366 uint32_t increment = i * pitch; 367 if (softc->mode == KD_TEXT) { 368 (void) memmove(dst + increment, 369 src + increment, width); 370 } 371 (void) memmove(sdst + increment, src + increment, 372 width); 373 } 374 } 375 } 376 377 /* 378 * Implements alpha blending for RGBA data, could use pixels for arguments, 379 * but byte stream seems more generic. 380 * The generic alpha blending is: 381 * blend = alpha * fg + (1.0 - alpha) * bg. 382 * Since our alpha is not from range [0..1], we scale appropriately. 383 */ 384 static uint8_t 385 alpha_blend(uint8_t fg, uint8_t bg, uint8_t alpha) 386 { 387 uint16_t blend, h, l; 388 389 /* trivial corner cases */ 390 if (alpha == 0) 391 return (bg); 392 if (alpha == 0xFF) 393 return (fg); 394 blend = (alpha * fg + (0xFF - alpha) * bg); 395 /* Division by 0xFF */ 396 h = blend >> 8; 397 l = blend & 0xFF; 398 if (h + l >= 0xFF) 399 h++; 400 return (h); 401 } 402 403 /* Copy memory to framebuffer or to memory. */ 404 static void 405 bitmap_cpy(uint8_t *dst, uint8_t *src, uint32_t len, int bpp) 406 { 407 uint32_t i; 408 uint8_t a; 409 410 switch (bpp) { 411 case 4: 412 for (i = 0; i < len; i += bpp) { 413 a = src[i+3]; 414 dst[i] = alpha_blend(src[i], dst[i], a); 415 dst[i+1] = alpha_blend(src[i+1], dst[i+1], a); 416 dst[i+2] = alpha_blend(src[i+2], dst[i+2], a); 417 dst[i+3] = a; 418 } 419 break; 420 default: 421 (void) memcpy(dst, src, len); 422 break; 423 } 424 } 425 426 static void 427 bitmap_cons_display(struct gfxp_fb_softc *softc, struct vis_consdisplay *da) 428 { 429 union gfx_console *console; 430 uint32_t size; /* write size per scanline */ 431 uint8_t *fbp, *sfbp; /* fb + calculated offset */ 432 int i; 433 434 console = softc->console; 435 /* make sure we will not write past FB */ 436 if (da->col >= console->fb.screen.x || 437 da->row >= console->fb.screen.y || 438 da->col + da->width > console->fb.screen.x || 439 da->row + da->height > console->fb.screen.y) 440 return; 441 442 size = da->width * console->fb.bpp; 443 fbp = console->fb.fb + da->col * console->fb.bpp + 444 da->row * console->fb.pitch; 445 sfbp = console->fb.shadow_fb + da->col * console->fb.bpp + 446 da->row * console->fb.pitch; 447 448 /* write all scanlines in rectangle */ 449 for (i = 0; i < da->height; i++) { 450 uint8_t *dest = fbp + i * console->fb.pitch; 451 uint8_t *src = da->data + i * size; 452 if (softc->mode == KD_TEXT) 453 bitmap_cpy(dest, src, size, console->fb.bpp); 454 dest = sfbp + i * console->fb.pitch; 455 bitmap_cpy(dest, src, size, console->fb.bpp); 456 } 457 } 458 459 static int 460 bitmap_cons_clear(struct gfxp_fb_softc *softc, struct vis_consclear *ca) 461 { 462 union gfx_console *console; 463 uint8_t *fb, *sfb; 464 uint16_t *fb16, *sfb16; 465 uint32_t data, *fb32, *sfb32; 466 int i, j, pitch; 467 468 console = softc->console; 469 pitch = console->fb.pitch; 470 data = bitmap_color_map(ca->bg_color); 471 switch (console->fb.depth) { 472 case 8: 473 for (i = 0; i < console->fb.screen.y; i++) { 474 if (softc->mode == KD_TEXT) { 475 fb = console->fb.fb + i * pitch; 476 (void) memset(fb, ca->bg_color, pitch); 477 } 478 fb = console->fb.shadow_fb + i * pitch; 479 (void) memset(fb, ca->bg_color, pitch); 480 } 481 break; 482 case 15: 483 case 16: 484 for (i = 0; i < console->fb.screen.y; i++) { 485 fb16 = (uint16_t *)(console->fb.fb + i * pitch); 486 sfb16 = (uint16_t *)(console->fb.shadow_fb + i * pitch); 487 for (j = 0; j < console->fb.screen.x; j++) { 488 if (softc->mode == KD_TEXT) 489 fb16[j] = (uint16_t)data & 0xffff; 490 sfb16[j] = (uint16_t)data & 0xffff; 491 } 492 } 493 break; 494 case 24: 495 for (i = 0; i < console->fb.screen.y; i++) { 496 fb = console->fb.fb + i * pitch; 497 sfb = console->fb.shadow_fb + i * pitch; 498 for (j = 0; j < pitch; j += 3) { 499 if (softc->mode == KD_TEXT) { 500 fb[j] = (data >> 16) & 0xff; 501 fb[j+1] = (data >> 8) & 0xff; 502 fb[j+2] = data & 0xff; 503 } 504 505 sfb[j] = (data >> 16) & 0xff; 506 sfb[j+1] = (data >> 8) & 0xff; 507 sfb[j+2] = data & 0xff; 508 } 509 } 510 break; 511 case 32: 512 for (i = 0; i < console->fb.screen.y; i++) { 513 fb32 = (uint32_t *)(console->fb.fb + i * pitch); 514 sfb32 = (uint32_t *)(console->fb.shadow_fb + i * pitch); 515 for (j = 0; j < console->fb.screen.x; j++) { 516 if (softc->mode == KD_TEXT) 517 fb32[j] = data; 518 sfb32[j] = data; 519 } 520 } 521 break; 522 } 523 524 return (0); 525 } 526 527 static void 528 bitmap_display_cursor(struct gfxp_fb_softc *softc, struct vis_conscursor *ca) 529 { 530 union gfx_console *console; 531 uint32_t fg, bg, offset, size; 532 uint32_t *fb32, *sfb32; 533 uint16_t *fb16, *sfb16; 534 uint8_t *fb8, *sfb8; 535 int i, j, bpp, pitch; 536 537 console = softc->console; 538 pitch = console->fb.pitch; 539 bpp = console->fb.bpp; 540 size = ca->width * bpp; 541 542 /* 543 * Build cursor image. We are building mirror image of data on 544 * frame buffer by (D xor FG) xor BG. 545 */ 546 offset = ca->col * bpp + ca->row * pitch; 547 switch (console->fb.depth) { 548 case 8: 549 fg = ca->fg_color.mono; 550 bg = ca->bg_color.mono; 551 for (i = 0; i < ca->height; i++) { 552 fb8 = console->fb.fb + offset + i * pitch; 553 sfb8 = console->fb.shadow_fb + offset + i * pitch; 554 for (j = 0; j < size; j += 1) { 555 if (softc->mode == KD_TEXT) { 556 fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ 557 (bg & 0xff); 558 } 559 sfb8[j] = (sfb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); 560 } 561 } 562 break; 563 case 15: 564 case 16: 565 fg = ca->fg_color.sixteen[0] << 8; 566 fg |= ca->fg_color.sixteen[1]; 567 bg = ca->bg_color.sixteen[0] << 8; 568 bg |= ca->bg_color.sixteen[1]; 569 for (i = 0; i < ca->height; i++) { 570 fb16 = (uint16_t *) 571 (console->fb.fb + offset + i * pitch); 572 sfb16 = (uint16_t *) 573 (console->fb.shadow_fb + offset + i * pitch); 574 for (j = 0; j < ca->width; j++) { 575 if (softc->mode == KD_TEXT) { 576 fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ 577 (bg & 0xffff); 578 } 579 sfb16[j] = (sfb16[j] ^ (fg & 0xffff)) ^ 580 (bg & 0xffff); 581 } 582 } 583 break; 584 case 24: 585 fg = ca->fg_color.twentyfour[0] << console->fb.rgb.red.pos; 586 fg |= ca->fg_color.twentyfour[1] << console->fb.rgb.green.pos; 587 fg |= ca->fg_color.twentyfour[2] << console->fb.rgb.blue.pos; 588 bg = ca->bg_color.twentyfour[0] << console->fb.rgb.red.pos; 589 bg |= ca->bg_color.twentyfour[1] << console->fb.rgb.green.pos; 590 bg |= ca->bg_color.twentyfour[2] << console->fb.rgb.blue.pos; 591 for (i = 0; i < ca->height; i++) { 592 fb8 = console->fb.fb + offset + i * pitch; 593 sfb8 = console->fb.shadow_fb + offset + i * pitch; 594 for (j = 0; j < size; j += 3) { 595 if (softc->mode == KD_TEXT) { 596 fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) 597 ^ ((bg >> 16) & 0xff); 598 fb8[j+1] = 599 (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 600 ((bg >> 8) & 0xff); 601 fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ 602 (bg & 0xff); 603 } 604 605 sfb8[j] = (sfb8[j] ^ ((fg >> 16) & 0xff)) ^ 606 ((bg >> 16) & 0xff); 607 sfb8[j+1] = (sfb8[j+1] ^ ((fg >> 8) & 0xff)) ^ 608 ((bg >> 8) & 0xff); 609 sfb8[j+2] = (sfb8[j+2] ^ (fg & 0xff)) ^ 610 (bg & 0xff); 611 } 612 } 613 break; 614 case 32: 615 fg = ca->fg_color.twentyfour[0] << console->fb.rgb.red.pos; 616 fg |= ca->fg_color.twentyfour[1] << console->fb.rgb.green.pos; 617 fg |= ca->fg_color.twentyfour[2] << console->fb.rgb.blue.pos; 618 bg = ca->bg_color.twentyfour[0] << console->fb.rgb.red.pos; 619 bg |= ca->bg_color.twentyfour[1] << console->fb.rgb.green.pos; 620 bg |= ca->bg_color.twentyfour[2] << console->fb.rgb.blue.pos; 621 for (i = 0; i < ca->height; i++) { 622 fb32 = (uint32_t *) 623 (console->fb.fb + offset + i * pitch); 624 sfb32 = (uint32_t *) 625 (console->fb.shadow_fb + offset + i * pitch); 626 for (j = 0; j < ca->width; j++) { 627 if (softc->mode == KD_TEXT) 628 fb32[j] = (fb32[j] ^ fg) ^ bg; 629 sfb32[j] = (sfb32[j] ^ fg) ^ bg; 630 } 631 } 632 break; 633 } 634 } 635 636 static void 637 bitmap_cons_cursor(struct gfxp_fb_softc *softc, struct vis_conscursor *ca) 638 { 639 union gfx_console *console = softc->console; 640 641 switch (ca->action) { 642 case VIS_HIDE_CURSOR: 643 bitmap_display_cursor(softc, ca); 644 console->fb.cursor.visible = B_FALSE; 645 break; 646 case VIS_DISPLAY_CURSOR: 647 /* keep track of cursor position for polled mode */ 648 console->fb.cursor.pos.x = 649 (ca->col - console->fb.terminal_origin.x) / 650 console->fb.font_width; 651 console->fb.cursor.pos.y = 652 (ca->row - console->fb.terminal_origin.y) / 653 console->fb.font_height; 654 console->fb.cursor.origin.x = ca->col; 655 console->fb.cursor.origin.y = ca->row; 656 657 bitmap_display_cursor(softc, ca); 658 console->fb.cursor.visible = B_TRUE; 659 break; 660 case VIS_GET_CURSOR: 661 ca->row = console->fb.cursor.origin.y; 662 ca->col = console->fb.cursor.origin.x; 663 break; 664 } 665 } 666 667 static void 668 bitmap_polled_copy(struct vis_polledio_arg *arg, struct vis_conscopy *ca) 669 { 670 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg; 671 bitmap_cons_copy(softc, ca); 672 } 673 674 static void 675 bitmap_polled_display(struct vis_polledio_arg *arg, struct vis_consdisplay *da) 676 { 677 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg; 678 bitmap_cons_display(softc, da); 679 } 680 681 static void 682 bitmap_polled_cursor(struct vis_polledio_arg *arg, struct vis_conscursor *ca) 683 { 684 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)arg; 685 bitmap_cons_cursor(softc, ca); 686 } 687 688 /* 689 * Device mapping support. Should be possible to mmmap frame buffer 690 * to user space. Currently not working, mmap will receive -1 as pointer. 691 */ 692 /*ARGSUSED*/ 693 static int 694 bitmap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, 695 size_t len, size_t *maplen, uint_t model, void *ptr) 696 { 697 struct gfxp_fb_softc *softc = (struct gfxp_fb_softc *)ptr; 698 union gfx_console *console = softc->console; 699 size_t length; 700 701 if (softc == NULL) { 702 cmn_err(CE_WARN, "bitmap: Can't find softstate"); 703 return (ENXIO); 704 } 705 706 if (off >= console->fb.fb_size) { 707 cmn_err(CE_WARN, "bitmap: Can't map offset 0x%llx", off); 708 return (ENXIO); 709 } 710 711 if (off + len > console->fb.fb_size) 712 length = console->fb.fb_size - off; 713 else 714 length = len; 715 716 gfxp_map_devmem(dhp, console->fb.paddr, length, &dev_attr); 717 718 *maplen = length; 719 720 return (0); 721 } 722