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