1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 29 /* All Rights Reserved */ 30 31 #include <sys/errno.h> 32 #include <sys/types.h> 33 #include <sys/conf.h> 34 #include <sys/kmem.h> 35 #include <sys/visual_io.h> 36 #include <sys/font.h> 37 #include <sys/fbio.h> 38 #include <sys/ddi.h> 39 #include <sys/stat.h> 40 #include <sys/sunddi.h> 41 #include <sys/file.h> 42 #include <sys/open.h> 43 #include <sys/modctl.h> 44 #include <sys/vgareg.h> 45 #include <sys/vgasubr.h> 46 #include <sys/pci.h> 47 #include <sys/kd.h> 48 #include <sys/ddi_impldefs.h> 49 #include <sys/gfx_private.h> 50 51 #define MYNAME "gfxp_vgatext" 52 53 #define TEXT_ROWS 25 54 #define TEXT_COLS 80 55 56 #define VGA_BRIGHT_WHITE 0x0f 57 #define VGA_BLACK 0x00 58 59 #define VGA_REG_ADDR 0x3c0 60 #define VGA_REG_SIZE 0x20 61 62 #define VGA_MEM_ADDR 0xa0000 63 #define VGA_MEM_SIZE 0x20000 64 65 #define VGA_MMAP_FB_BASE VGA_MEM_ADDR 66 67 struct vgatext_softc { 68 struct vgaregmap regs; 69 struct vgaregmap fb; 70 off_t fb_size; 71 int fb_regno; 72 dev_info_t *devi; 73 int mode; /* KD_TEXT or KD_GRAPHICS */ 74 caddr_t text_base; /* hardware text base */ 75 char shadow[TEXT_ROWS*TEXT_COLS*2]; 76 caddr_t current_base; /* hardware or shadow */ 77 struct { 78 boolean_t visible; 79 int row; 80 int col; 81 } cursor; 82 struct vis_polledio polledio; 83 struct { 84 unsigned char red; 85 unsigned char green; 86 unsigned char blue; 87 } colormap[VGA8_CMAP_ENTRIES]; 88 unsigned char attrib_palette[VGA_ATR_NUM_PLT]; 89 unsigned int flags; 90 kmutex_t lock; 91 }; 92 93 typedef enum pc_colors { 94 pc_black = 0, 95 pc_blue = 1, 96 pc_green = 2, 97 pc_cyan = 3, 98 pc_red = 4, 99 pc_magenta = 5, 100 pc_brown = 6, 101 pc_white = 7, 102 pc_grey = 8, 103 pc_brt_blue = 9, 104 pc_brt_green = 10, 105 pc_brt_cyan = 11, 106 pc_brt_red = 12, 107 pc_brt_magenta = 13, 108 pc_yellow = 14, 109 pc_brt_white = 15 110 } pc_colors_t; 111 112 static const unsigned char solaris_color_to_pc_color[16] = { 113 pc_brt_white, /* 0 - brt_white */ 114 pc_black, /* 1 - black */ 115 pc_blue, /* 2 - blue */ 116 pc_green, /* 3 - green */ 117 pc_cyan, /* 4 - cyan */ 118 pc_red, /* 5 - red */ 119 pc_magenta, /* 6 - magenta */ 120 pc_brown, /* 7 - brown */ 121 pc_white, /* 8 - white */ 122 pc_grey, /* 9 - gery */ 123 pc_brt_blue, /* 10 - brt_blue */ 124 pc_brt_green, /* 11 - brt_green */ 125 pc_brt_cyan, /* 12 - brt_cyan */ 126 pc_brt_red, /* 13 - brt_red */ 127 pc_brt_magenta, /* 14 - brt_magenta */ 128 pc_yellow /* 15 - yellow */ 129 }; 130 131 static ddi_device_acc_attr_t dev_attr = { 132 DDI_DEVICE_ATTR_V0, 133 DDI_NEVERSWAP_ACC, 134 DDI_STRICTORDER_ACC, 135 }; 136 137 /* default structure for FBIOGATTR ioctl */ 138 static struct fbgattr vgatext_attr = { 139 /* real_type owner */ 140 FBTYPE_SUNFAST_COLOR, 0, 141 /* fbtype: type h w depth cms size */ 142 { FBTYPE_SUNFAST_COLOR, TEXT_ROWS, TEXT_COLS, 1, 256, 0 }, 143 /* fbsattr: flags emu_type dev_specific */ 144 { 0, FBTYPE_SUN4COLOR, { 0 } }, 145 /* emu_types */ 146 { -1 } 147 }; 148 149 #define GFXP_FLAG_CONSOLE 0x00000001 150 #define GFXP_IS_CONSOLE(softc) ((softc)->flags & GFXP_FLAG_CONSOLE) 151 152 /* 153 * Global name used to write the softc pointer in, for the 154 * data wrapper vgatext_return_pointers() 155 */ 156 157 158 int gfxp_vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd, 159 gfxp_vgatext_softc_ptr_t ptr); 160 static int vgatext_devinit(struct vgatext_softc *, struct vis_devinit *data); 161 static void vgatext_cons_copy(struct vgatext_softc *, 162 struct vis_conscopy *); 163 static void vgatext_cons_display(struct vgatext_softc *, 164 struct vis_consdisplay *); 165 static void vgatext_cons_cursor(struct vgatext_softc *, 166 struct vis_conscursor *); 167 static void vgatext_polled_copy(struct vis_polledio_arg *, 168 struct vis_conscopy *); 169 static void vgatext_polled_display(struct vis_polledio_arg *, 170 struct vis_consdisplay *); 171 static void vgatext_polled_cursor(struct vis_polledio_arg *, 172 struct vis_conscursor *); 173 static void vgatext_init(struct vgatext_softc *); 174 static void vgatext_set_text(struct vgatext_softc *); 175 176 static void vgatext_save_text(struct vgatext_softc *softc); 177 static void vgatext_restore_textmode(struct vgatext_softc *softc); 178 static int vgatext_suspend(struct vgatext_softc *softc); 179 static void vgatext_resume(struct vgatext_softc *softc); 180 181 #if defined(USE_BORDERS) 182 static void vgatext_init_graphics(struct vgatext_softc *); 183 #endif 184 185 static int vgatext_kdsetmode(struct vgatext_softc *softc, int mode); 186 static void vgatext_setfont(struct vgatext_softc *softc); 187 static void vgatext_get_cursor(struct vgatext_softc *softc, 188 screen_pos_t *row, screen_pos_t *col); 189 static void vgatext_set_cursor(struct vgatext_softc *softc, int row, int col); 190 static void vgatext_hide_cursor(struct vgatext_softc *softc); 191 static void vgatext_save_colormap(struct vgatext_softc *softc); 192 static void vgatext_restore_colormap(struct vgatext_softc *softc); 193 static int vgatext_get_pci_reg_index(dev_info_t *const devi, 194 unsigned long himask, unsigned long hival, unsigned long addr, 195 off_t *offset); 196 static int vgatext_get_isa_reg_index(dev_info_t *const devi, 197 unsigned long hival, unsigned long addr, off_t *offset); 198 199 static char vgatext_silent; 200 static char happyface_boot; 201 202 gfxp_vgatext_softc_ptr_t 203 gfxp_vgatext_softc_alloc(void) 204 { 205 return (kmem_zalloc(sizeof (struct vgatext_softc), KM_SLEEP)); 206 } 207 208 void 209 gfxp_vgatext_softc_free(gfxp_vgatext_softc_ptr_t ptr) 210 { 211 kmem_free(ptr, sizeof (struct vgatext_softc)); 212 } 213 214 /* 215 * NOTE: this function is duplicated here and in consplat/vgatext while 216 * we work on a set of commitable interfaces to sunpci.c. 217 * 218 * Use the class code to determine if the device is a PCI-to-PCI bridge. 219 * Returns: B_TRUE if the device is a bridge. 220 * B_FALSE if the device is not a bridge or the property cannot be 221 * retrieved. 222 */ 223 static boolean_t 224 is_pci_bridge(dev_info_t *dip) 225 { 226 uint32_t class_code; 227 228 class_code = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, 229 DDI_PROP_DONTPASS, "class-code", 0xffffffff); 230 231 if (class_code == 0xffffffff || class_code == DDI_PROP_NOT_FOUND) 232 return (B_FALSE); 233 234 class_code &= 0x00ffff00; 235 if (class_code == ((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8))) 236 return (B_TRUE); 237 238 return (B_FALSE); 239 } 240 241 #define STREQ(a, b) (strcmp((a), (b)) == 0) 242 243 static void 244 gfxp_check_for_console(dev_info_t *devi, struct vgatext_softc *softc, 245 int pci_pcie_bus) 246 { 247 ddi_acc_handle_t pci_conf; 248 dev_info_t *pdevi; 249 uint16_t data16; 250 251 /* 252 * Based on Section 11.3, "PCI Display Subsystem Initialization", 253 * of the 1.1 PCI-to-PCI Bridge Architecture Specification 254 * determine if this is the boot console device. First, see 255 * if the SBIOS has turned on PCI I/O for this device. Then if 256 * this is PCI/PCI-E, verify the parent bridge has VGAEnable set. 257 */ 258 259 if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) { 260 cmn_err(CE_WARN, 261 MYNAME 262 ": can't get PCI conf handle"); 263 return; 264 } 265 266 data16 = pci_config_get16(pci_conf, PCI_CONF_COMM); 267 if (data16 & PCI_COMM_IO) 268 softc->flags |= GFXP_FLAG_CONSOLE; 269 270 pci_config_teardown(&pci_conf); 271 272 /* If IO not enabled or ISA/EISA, just return */ 273 if (!(softc->flags & GFXP_FLAG_CONSOLE) || !pci_pcie_bus) 274 return; 275 276 /* 277 * Check for VGA Enable in the Bridge Control register for all 278 * PCI/PCIEX parents. If not set all the way up the chain, 279 * this cannot be the boot console. 280 */ 281 282 pdevi = devi; 283 while (pdevi = ddi_get_parent(pdevi)) { 284 int error; 285 ddi_acc_handle_t ppci_conf; 286 char *parent_type = NULL; 287 288 error = ddi_prop_lookup_string(DDI_DEV_T_ANY, pdevi, 289 DDI_PROP_DONTPASS, "device_type", &parent_type); 290 if (error != DDI_SUCCESS) { 291 return; 292 } 293 294 /* Verify still on the PCI/PCIEX parent tree */ 295 if (!STREQ(parent_type, "pci") && 296 !STREQ(parent_type, "pciex")) { 297 ddi_prop_free(parent_type); 298 return; 299 } 300 301 ddi_prop_free(parent_type); 302 parent_type = NULL; 303 304 /* VGAEnable is set only for PCI-to-PCI bridges. */ 305 if (is_pci_bridge(pdevi) == B_FALSE) 306 continue; 307 308 if (pci_config_setup(pdevi, &ppci_conf) != DDI_SUCCESS) 309 continue; 310 311 data16 = pci_config_get16(ppci_conf, PCI_BCNF_BCNTRL); 312 pci_config_teardown(&ppci_conf); 313 314 if (!(data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)) { 315 softc->flags &= ~GFXP_FLAG_CONSOLE; 316 return; 317 } 318 } 319 } 320 321 int 322 gfxp_vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd, 323 gfxp_vgatext_softc_ptr_t ptr) 324 { 325 struct vgatext_softc *softc = (struct vgatext_softc *)ptr; 326 int unit = ddi_get_instance(devi); 327 int error; 328 char *parent_type = NULL; 329 int reg_rnumber; 330 off_t reg_offset; 331 off_t mem_offset; 332 char *cons; 333 int pci_pcie_bus = 0; 334 int value; 335 336 switch (cmd) { 337 case DDI_ATTACH: 338 break; 339 340 case DDI_RESUME: 341 vgatext_resume(softc); 342 return (DDI_SUCCESS); 343 344 default: 345 return (DDI_FAILURE); 346 } 347 348 /* DDI_ATTACH */ 349 350 softc->devi = devi; /* Copy and init DEVI */ 351 352 softc->polledio.arg = (struct vis_polledio_arg *)softc; 353 softc->polledio.display = vgatext_polled_display; 354 softc->polledio.copy = vgatext_polled_copy; 355 softc->polledio.cursor = vgatext_polled_cursor; 356 357 mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL); 358 359 error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi), 360 DDI_PROP_DONTPASS, "device_type", &parent_type); 361 if (error != DDI_SUCCESS) { 362 cmn_err(CE_WARN, MYNAME ": can't determine parent type."); 363 goto fail; 364 } 365 366 /* Not enable AGP and DRM by default */ 367 if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) { 368 reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR, 369 ®_offset); 370 if (reg_rnumber < 0) { 371 cmn_err(CE_WARN, 372 MYNAME 373 ": can't find reg entry for registers"); 374 error = DDI_FAILURE; 375 goto fail; 376 } 377 softc->fb_regno = vgatext_get_isa_reg_index(devi, 0, 378 VGA_MEM_ADDR, &mem_offset); 379 if (softc->fb_regno < 0) { 380 cmn_err(CE_WARN, 381 MYNAME 382 ": can't find reg entry for memory"); 383 error = DDI_FAILURE; 384 goto fail; 385 } 386 } else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) { 387 pci_pcie_bus = 1; 388 reg_rnumber = vgatext_get_pci_reg_index(devi, 389 PCI_REG_ADDR_M|PCI_REG_REL_M, 390 PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR, 391 ®_offset); 392 if (reg_rnumber < 0) { 393 cmn_err(CE_WARN, 394 MYNAME 395 ": can't find reg entry for registers"); 396 error = DDI_FAILURE; 397 goto fail; 398 } 399 softc->fb_regno = vgatext_get_pci_reg_index(devi, 400 PCI_REG_ADDR_M|PCI_REG_REL_M, 401 PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR, 402 &mem_offset); 403 if (softc->fb_regno < 0) { 404 cmn_err(CE_WARN, 405 MYNAME 406 ": can't find reg entry for memory"); 407 error = DDI_FAILURE; 408 goto fail; 409 } 410 } else { 411 cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".", 412 parent_type); 413 error = DDI_FAILURE; 414 goto fail; 415 } 416 ddi_prop_free(parent_type); 417 parent_type = NULL; 418 419 error = ddi_regs_map_setup(devi, reg_rnumber, 420 (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE, 421 &dev_attr, &softc->regs.handle); 422 if (error != DDI_SUCCESS) 423 goto fail; 424 softc->regs.mapped = B_TRUE; 425 426 softc->fb_size = VGA_MEM_SIZE; 427 428 error = ddi_regs_map_setup(devi, softc->fb_regno, 429 (caddr_t *)&softc->fb.addr, 430 mem_offset, softc->fb_size, 431 &dev_attr, &softc->fb.handle); 432 if (error != DDI_SUCCESS) 433 goto fail; 434 softc->fb.mapped = B_TRUE; 435 436 if (ddi_get8(softc->regs.handle, 437 softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL) 438 softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE; 439 else 440 softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE; 441 442 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 443 DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) { 444 if (strcmp(cons, "graphics") == 0) { 445 happyface_boot = 1; 446 vgatext_silent = 1; 447 softc->current_base = softc->shadow; 448 } else { 449 softc->current_base = softc->text_base; 450 } 451 ddi_prop_free(cons); 452 } else { 453 softc->current_base = softc->text_base; 454 } 455 456 error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit), 457 devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); 458 if (error != DDI_SUCCESS) 459 goto fail; 460 461 gfxp_check_for_console(devi, softc, pci_pcie_bus); 462 463 value = GFXP_IS_CONSOLE(softc) ? 1 : 0; 464 if (ddi_prop_update_int(DDI_DEV_T_NONE, devi, 465 "primary-controller", value) != DDI_SUCCESS) { 466 cmn_err(CE_WARN, 467 "Can not %s primary-controller " 468 "property for driver", value ? "set" : "clear"); 469 } 470 471 /* only do this if not in graphics mode */ 472 if ((vgatext_silent == 0) && (GFXP_IS_CONSOLE(softc))) { 473 vgatext_init(softc); 474 vgatext_save_colormap(softc); 475 } 476 477 return (DDI_SUCCESS); 478 479 fail: 480 if (parent_type != NULL) 481 ddi_prop_free(parent_type); 482 (void) gfxp_vgatext_detach(devi, DDI_DETACH, (void *)softc); 483 return (error); 484 } 485 486 /*ARGSUSED*/ 487 int 488 gfxp_vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd, 489 gfxp_vgatext_softc_ptr_t ptr) 490 { 491 struct vgatext_softc *softc = (struct vgatext_softc *)ptr; 492 493 (void) ddi_prop_remove(DDI_DEV_T_ANY, devi, "primary-controller"); 494 495 switch (cmd) { 496 497 case DDI_SUSPEND: 498 return (vgatext_suspend(softc)); 499 /* break; */ 500 case DDI_DETACH: 501 if (softc->fb.mapped) 502 ddi_regs_map_free(&softc->fb.handle); 503 if (softc->regs.mapped) 504 ddi_regs_map_free(&softc->regs.handle); 505 mutex_destroy(&(softc->lock)); 506 return (DDI_SUCCESS); 507 508 default: 509 cmn_err(CE_WARN, "gfxp_vgatext_detach: unknown cmd 0x%x\n", 510 cmd); 511 return (DDI_FAILURE); 512 } 513 } 514 515 /*ARGSUSED*/ 516 int 517 gfxp_vgatext_open(dev_t *devp, int flag, int otyp, cred_t *cred, 518 gfxp_vgatext_softc_ptr_t ptr) 519 { 520 struct vgatext_softc *softc = (struct vgatext_softc *)ptr; 521 522 if (softc == NULL || otyp == OTYP_BLK) 523 return (ENXIO); 524 525 return (0); 526 } 527 528 /*ARGSUSED*/ 529 int 530 gfxp_vgatext_close(dev_t devp, int flag, int otyp, cred_t *cred, 531 gfxp_vgatext_softc_ptr_t ptr) 532 { 533 return (0); 534 } 535 536 static int 537 do_gfx_ioctl(int cmd, intptr_t data, int mode, struct vgatext_softc *softc) 538 { 539 static char kernel_only[] = 540 "gfxp_vgatext_ioctl: %s is a kernel only ioctl"; 541 int err; 542 int kd_mode; 543 544 switch (cmd) { 545 case KDSETMODE: 546 return (vgatext_kdsetmode(softc, (int)data)); 547 548 case KDGETMODE: 549 kd_mode = softc->mode; 550 if (ddi_copyout(&kd_mode, (void *)data, sizeof (int), mode)) 551 return (EFAULT); 552 break; 553 554 case VIS_DEVINIT: 555 556 if (!(mode & FKIOCTL)) { 557 cmn_err(CE_CONT, kernel_only, "VIS_DEVINIT"); 558 return (ENXIO); 559 } 560 561 err = vgatext_devinit(softc, (struct vis_devinit *)data); 562 if (err != 0) { 563 cmn_err(CE_WARN, 564 "gfxp_vgatext_ioctl: could not" 565 " initialize console"); 566 return (err); 567 } 568 break; 569 570 case VIS_CONSCOPY: /* move */ 571 { 572 struct vis_conscopy pma; 573 574 if (ddi_copyin((void *)data, &pma, 575 sizeof (struct vis_conscopy), mode)) 576 return (EFAULT); 577 578 vgatext_cons_copy(softc, &pma); 579 break; 580 } 581 582 case VIS_CONSDISPLAY: /* display */ 583 { 584 struct vis_consdisplay display_request; 585 586 if (ddi_copyin((void *)data, &display_request, 587 sizeof (display_request), mode)) 588 return (EFAULT); 589 590 vgatext_cons_display(softc, &display_request); 591 break; 592 } 593 594 case VIS_CONSCURSOR: 595 { 596 struct vis_conscursor cursor_request; 597 598 if (ddi_copyin((void *)data, &cursor_request, 599 sizeof (cursor_request), mode)) 600 return (EFAULT); 601 602 vgatext_cons_cursor(softc, &cursor_request); 603 604 if (cursor_request.action == VIS_GET_CURSOR && 605 ddi_copyout(&cursor_request, (void *)data, 606 sizeof (cursor_request), mode)) 607 return (EFAULT); 608 break; 609 } 610 611 case VIS_GETCMAP: 612 case VIS_PUTCMAP: 613 case FBIOPUTCMAP: 614 case FBIOGETCMAP: 615 /* 616 * At the moment, text mode is not considered to have 617 * a color map. 618 */ 619 return (EINVAL); 620 621 case FBIOGATTR: 622 if (copyout(&vgatext_attr, (void *)data, 623 sizeof (struct fbgattr))) 624 return (EFAULT); 625 break; 626 627 case FBIOGTYPE: 628 if (copyout(&vgatext_attr.fbtype, (void *)data, 629 sizeof (struct fbtype))) 630 return (EFAULT); 631 break; 632 633 default: 634 return (ENXIO); 635 } 636 return (0); 637 } 638 639 /*ARGSUSED*/ 640 int 641 gfxp_vgatext_ioctl( 642 dev_t dev, 643 int cmd, 644 intptr_t data, 645 int mode, 646 cred_t *cred, 647 int *rval, 648 gfxp_vgatext_softc_ptr_t ptr) 649 { 650 int err; 651 652 struct vgatext_softc *softc = (struct vgatext_softc *)ptr; 653 654 mutex_enter(&(softc->lock)); 655 err = do_gfx_ioctl(cmd, data, mode, softc); 656 mutex_exit(&(softc->lock)); 657 658 return (err); 659 } 660 661 /* 662 * vgatext_save_text 663 * vgatext_restore_textmode 664 * vgatext_suspend 665 * vgatext_resume 666 * 667 * Routines to save and restore contents of the VGA text area 668 * Mostly, this is to support Suspend/Resume operation for graphics 669 * device drivers. Here in the VGAtext common code, we simply squirrel 670 * away the contents of the hardware's text area during Suspend and then 671 * put it back during Resume 672 */ 673 static void 674 vgatext_save_text(struct vgatext_softc *softc) 675 { 676 unsigned i; 677 678 for (i = 0; i < sizeof (softc->shadow); i++) 679 softc->shadow[i] = softc->current_base[i]; 680 } 681 682 static void 683 vgatext_restore_textmode(struct vgatext_softc *softc) 684 { 685 unsigned i; 686 687 vgatext_init(softc); 688 for (i = 0; i < sizeof (softc->shadow); i++) { 689 softc->text_base[i] = softc->shadow[i]; 690 } 691 if (softc->cursor.visible) { 692 vgatext_set_cursor(softc, 693 softc->cursor.row, softc->cursor.col); 694 } 695 vgatext_restore_colormap(softc); 696 } 697 698 static int 699 vgatext_suspend(struct vgatext_softc *softc) 700 { 701 switch (softc->mode) { 702 case KD_TEXT: 703 vgatext_save_text(softc); 704 break; 705 706 case KD_GRAPHICS: 707 break; 708 709 default: 710 cmn_err(CE_WARN, MYNAME ": unknown mode in vgatext_suspend."); 711 return (DDI_FAILURE); 712 } 713 return (DDI_SUCCESS); 714 } 715 716 static void 717 vgatext_resume(struct vgatext_softc *softc) 718 { 719 720 switch (softc->mode) { 721 case KD_TEXT: 722 vgatext_restore_textmode(softc); 723 break; 724 725 case KD_GRAPHICS: 726 727 /* 728 * Upon RESUME, the graphics device will always actually 729 * be in TEXT mode even though the Xorg server did not 730 * make that mode change itself (the suspend code did). 731 * We want first, therefore, to restore textmode 732 * operation fully, and then the Xorg server will 733 * do the rest to restore the device to its 734 * (hi resolution) graphics mode 735 */ 736 vgatext_restore_textmode(softc); 737 #if defined(USE_BORDERS) 738 vgatext_init_graphics(softc); 739 #endif 740 break; 741 default: 742 cmn_err(CE_WARN, MYNAME ": unknown mode in vgatext_resume."); 743 break; 744 } 745 } 746 747 static void 748 vgatext_progressbar_stop() 749 { 750 extern void progressbar_stop(void); 751 752 if (vgatext_silent == 1) { 753 vgatext_silent = 0; 754 progressbar_stop(); 755 } 756 } 757 758 static void 759 vgatext_kdsettext(struct vgatext_softc *softc) 760 { 761 int i; 762 763 vgatext_init(softc); 764 for (i = 0; i < sizeof (softc->shadow); i++) { 765 softc->text_base[i] = softc->shadow[i]; 766 } 767 softc->current_base = softc->text_base; 768 if (softc->cursor.visible) { 769 vgatext_set_cursor(softc, 770 softc->cursor.row, softc->cursor.col); 771 } 772 vgatext_restore_colormap(softc); 773 } 774 775 static void 776 vgatext_kdsetgraphics(struct vgatext_softc *softc) 777 { 778 vgatext_progressbar_stop(); 779 vgatext_save_text(softc); 780 softc->current_base = softc->shadow; 781 #if defined(USE_BORDERS) 782 vgatext_init_graphics(softc); 783 #endif 784 } 785 786 static int 787 vgatext_kdsetmode(struct vgatext_softc *softc, int mode) 788 { 789 if ((mode == softc->mode) || (!GFXP_IS_CONSOLE(softc))) 790 return (0); 791 792 switch (mode) { 793 case KD_TEXT: 794 vgatext_kdsettext(softc); 795 break; 796 797 case KD_GRAPHICS: 798 vgatext_kdsetgraphics(softc); 799 break; 800 801 case KD_RESETTEXT: 802 /* 803 * In order to avoid racing with a starting X server, 804 * this needs to be a test and set that is performed in 805 * a single (softc->lock protected) ioctl into this driver. 806 */ 807 if (softc->mode == KD_TEXT && vgatext_silent == 1) { 808 vgatext_progressbar_stop(); 809 vgatext_kdsettext(softc); 810 } 811 break; 812 813 default: 814 return (EINVAL); 815 } 816 817 softc->mode = mode; 818 return (0); 819 } 820 821 /*ARGSUSED*/ 822 int 823 gfxp_vgatext_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, 824 size_t *maplen, uint_t model, void *ptr) 825 { 826 struct vgatext_softc *softc = (struct vgatext_softc *)ptr; 827 int err; 828 size_t length; 829 830 831 if (softc == NULL) { 832 cmn_err(CE_WARN, "vgatext: Can't find softstate"); 833 return (-1); 834 } 835 836 if (!(off >= VGA_MMAP_FB_BASE && 837 off < VGA_MMAP_FB_BASE + softc->fb_size)) { 838 cmn_err(CE_WARN, "vgatext: Can't map offset 0x%llx", off); 839 return (-1); 840 } 841 842 if (off + len > VGA_MMAP_FB_BASE + softc->fb_size) 843 length = VGA_MMAP_FB_BASE + softc->fb_size - off; 844 else 845 length = len; 846 847 if ((err = devmap_devmem_setup(dhp, softc->devi, 848 NULL, softc->fb_regno, off - VGA_MMAP_FB_BASE, 849 length, PROT_ALL, 0, &dev_attr)) < 0) { 850 return (err); 851 } 852 853 854 *maplen = length; 855 return (0); 856 } 857 858 859 static int 860 vgatext_devinit(struct vgatext_softc *softc, struct vis_devinit *data) 861 { 862 /* initialize console instance */ 863 data->version = VIS_CONS_REV; 864 data->width = TEXT_COLS; 865 data->height = TEXT_ROWS; 866 data->linebytes = TEXT_COLS; 867 data->depth = 4; 868 data->mode = VIS_TEXT; 869 data->polledio = &softc->polledio; 870 871 return (0); 872 } 873 874 /* 875 * display a string on the screen at (row, col) 876 * assume it has been cropped to fit. 877 */ 878 879 static void 880 vgatext_cons_display(struct vgatext_softc *softc, struct vis_consdisplay *da) 881 { 882 unsigned char *string; 883 int i; 884 unsigned char attr; 885 struct cgatext { 886 unsigned char ch; 887 unsigned char attr; 888 }; 889 struct cgatext *addr; 890 891 /* 892 * Sanity checks. This is a last-ditch effort to avoid damage 893 * from brokenness or maliciousness above. 894 */ 895 if (da->row < 0 || da->row >= TEXT_ROWS || 896 da->col < 0 || da->col >= TEXT_COLS || 897 da->col + da->width > TEXT_COLS) 898 return; 899 900 /* 901 * To be fully general, we should copyin the data. This is not 902 * really relevant for this text-only driver, but a graphical driver 903 * should support these ioctls from userland to enable simple 904 * system startup graphics. 905 */ 906 attr = (solaris_color_to_pc_color[da->bg_color & 0xf] << 4) 907 | solaris_color_to_pc_color[da->fg_color & 0xf]; 908 string = da->data; 909 addr = (struct cgatext *)softc->current_base 910 + (da->row * TEXT_COLS + da->col); 911 for (i = 0; i < da->width; i++) { 912 addr->ch = string[i]; 913 addr->attr = attr; 914 addr++; 915 } 916 } 917 918 static void 919 vgatext_polled_display( 920 struct vis_polledio_arg *arg, 921 struct vis_consdisplay *da) 922 { 923 vgatext_cons_display((struct vgatext_softc *)arg, da); 924 } 925 926 /* 927 * screen-to-screen copy 928 */ 929 930 static void 931 vgatext_cons_copy(struct vgatext_softc *softc, struct vis_conscopy *ma) 932 { 933 unsigned short *from; 934 unsigned short *to; 935 int cnt; 936 screen_size_t chars_per_row; 937 unsigned short *to_row_start; 938 unsigned short *from_row_start; 939 screen_size_t rows_to_move; 940 unsigned short *base; 941 942 /* 943 * Sanity checks. Note that this is a last-ditch effort to avoid 944 * damage caused by broken-ness or maliciousness above. 945 */ 946 if (ma->s_col < 0 || ma->s_col >= TEXT_COLS || 947 ma->s_row < 0 || ma->s_row >= TEXT_ROWS || 948 ma->e_col < 0 || ma->e_col >= TEXT_COLS || 949 ma->e_row < 0 || ma->e_row >= TEXT_ROWS || 950 ma->t_col < 0 || ma->t_col >= TEXT_COLS || 951 ma->t_row < 0 || ma->t_row >= TEXT_ROWS || 952 ma->s_col > ma->e_col || 953 ma->s_row > ma->e_row) 954 return; 955 956 /* 957 * Remember we're going to copy shorts because each 958 * character/attribute pair is 16 bits. 959 */ 960 chars_per_row = ma->e_col - ma->s_col + 1; 961 rows_to_move = ma->e_row - ma->s_row + 1; 962 963 /* More sanity checks. */ 964 if (ma->t_row + rows_to_move > TEXT_ROWS || 965 ma->t_col + chars_per_row > TEXT_COLS) 966 return; 967 968 base = (unsigned short *)softc->current_base; 969 970 to_row_start = base + ((ma->t_row * TEXT_COLS) + ma->t_col); 971 from_row_start = base + ((ma->s_row * TEXT_COLS) + ma->s_col); 972 973 if (to_row_start < from_row_start) { 974 while (rows_to_move-- > 0) { 975 to = to_row_start; 976 from = from_row_start; 977 to_row_start += TEXT_COLS; 978 from_row_start += TEXT_COLS; 979 for (cnt = chars_per_row; cnt-- > 0; ) 980 *to++ = *from++; 981 } 982 } else { 983 /* 984 * Offset to the end of the region and copy backwards. 985 */ 986 cnt = rows_to_move * TEXT_COLS + chars_per_row; 987 to_row_start += cnt; 988 from_row_start += cnt; 989 990 while (rows_to_move-- > 0) { 991 to_row_start -= TEXT_COLS; 992 from_row_start -= TEXT_COLS; 993 to = to_row_start; 994 from = from_row_start; 995 for (cnt = chars_per_row; cnt-- > 0; ) 996 *--to = *--from; 997 } 998 } 999 } 1000 1001 static void 1002 vgatext_polled_copy( 1003 struct vis_polledio_arg *arg, 1004 struct vis_conscopy *ca) 1005 { 1006 vgatext_cons_copy((struct vgatext_softc *)arg, ca); 1007 } 1008 1009 1010 static void 1011 vgatext_cons_cursor(struct vgatext_softc *softc, struct vis_conscursor *ca) 1012 { 1013 if (vgatext_silent) 1014 return; 1015 1016 switch (ca->action) { 1017 case VIS_HIDE_CURSOR: 1018 softc->cursor.visible = B_FALSE; 1019 if (softc->current_base == softc->text_base) 1020 vgatext_hide_cursor(softc); 1021 break; 1022 case VIS_DISPLAY_CURSOR: 1023 /* 1024 * Sanity check. This is a last-ditch effort to avoid 1025 * damage from brokenness or maliciousness above. 1026 */ 1027 if (ca->col < 0 || ca->col >= TEXT_COLS || 1028 ca->row < 0 || ca->row >= TEXT_ROWS) 1029 return; 1030 1031 softc->cursor.visible = B_TRUE; 1032 softc->cursor.col = ca->col; 1033 softc->cursor.row = ca->row; 1034 if (softc->current_base == softc->text_base) 1035 vgatext_set_cursor(softc, ca->row, ca->col); 1036 break; 1037 case VIS_GET_CURSOR: 1038 if (softc->current_base == softc->text_base) { 1039 vgatext_get_cursor(softc, &ca->row, &ca->col); 1040 } 1041 break; 1042 } 1043 } 1044 1045 static void 1046 vgatext_polled_cursor( 1047 struct vis_polledio_arg *arg, 1048 struct vis_conscursor *ca) 1049 { 1050 vgatext_cons_cursor((struct vgatext_softc *)arg, ca); 1051 } 1052 1053 1054 1055 /*ARGSUSED*/ 1056 static void 1057 vgatext_hide_cursor(struct vgatext_softc *softc) 1058 { 1059 /* Nothing at present */ 1060 } 1061 1062 static void 1063 vgatext_set_cursor(struct vgatext_softc *softc, int row, int col) 1064 { 1065 short addr; 1066 1067 if (vgatext_silent) 1068 return; 1069 1070 addr = row * TEXT_COLS + col; 1071 1072 vga_set_crtc(&softc->regs, VGA_CRTC_CLAH, addr >> 8); 1073 vga_set_crtc(&softc->regs, VGA_CRTC_CLAL, addr & 0xff); 1074 } 1075 1076 static int vga_row, vga_col; 1077 1078 static void 1079 vgatext_get_cursor(struct vgatext_softc *softc, 1080 screen_pos_t *row, screen_pos_t *col) 1081 { 1082 short addr; 1083 1084 addr = (vga_get_crtc(&softc->regs, VGA_CRTC_CLAH) << 8) + 1085 vga_get_crtc(&softc->regs, VGA_CRTC_CLAL); 1086 1087 vga_row = *row = addr / TEXT_COLS; 1088 vga_col = *col = addr % TEXT_COLS; 1089 } 1090 1091 /* 1092 * This code is experimental. It's only enabled if console is 1093 * set to graphics, a preliminary implementation of happyface boot. 1094 */ 1095 static void 1096 vgatext_set_text(struct vgatext_softc *softc) 1097 { 1098 int i; 1099 1100 if (happyface_boot == 0) 1101 return; 1102 1103 /* we are in graphics mode, set to text 80X25 mode */ 1104 1105 /* set misc registers */ 1106 vga_set_reg(&softc->regs, VGA_MISC_W, VGA_MISC_TEXT); 1107 1108 /* set sequencer registers */ 1109 vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN, 1110 (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) & 1111 ~VGA_SEQ_RST_SYN_NO_SYNC_RESET)); 1112 for (i = 1; i < NUM_SEQ_REG; i++) { 1113 vga_set_seq(&softc->regs, i, VGA_SEQ_TEXT[i]); 1114 } 1115 vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN, 1116 (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) | 1117 VGA_SEQ_RST_SYN_NO_ASYNC_RESET | 1118 VGA_SEQ_RST_SYN_NO_SYNC_RESET)); 1119 1120 /* set crt controller registers */ 1121 vga_set_crtc(&softc->regs, VGA_CRTC_VRE, 1122 (vga_get_crtc(&softc->regs, VGA_CRTC_VRE) & 1123 ~VGA_CRTC_VRE_LOCK)); 1124 for (i = 0; i < NUM_CRTC_REG; i++) { 1125 vga_set_crtc(&softc->regs, i, VGA_CRTC_TEXT[i]); 1126 } 1127 1128 /* set graphics controller registers */ 1129 for (i = 0; i < NUM_GRC_REG; i++) { 1130 vga_set_grc(&softc->regs, i, VGA_GRC_TEXT[i]); 1131 } 1132 1133 /* set attribute registers */ 1134 for (i = 0; i < NUM_ATR_REG; i++) { 1135 vga_set_atr(&softc->regs, i, VGA_ATR_TEXT[i]); 1136 } 1137 1138 /* set palette */ 1139 for (i = 0; i < VGA_TEXT_CMAP_ENTRIES; i++) { 1140 vga_put_cmap(&softc->regs, i, VGA_TEXT_PALETTES[i][0] << 2, 1141 VGA_TEXT_PALETTES[i][1] << 2, 1142 VGA_TEXT_PALETTES[i][2] << 2); 1143 } 1144 for (i = VGA_TEXT_CMAP_ENTRIES; i < VGA8_CMAP_ENTRIES; i++) { 1145 vga_put_cmap(&softc->regs, i, 0, 0, 0); 1146 } 1147 1148 vgatext_save_colormap(softc); 1149 } 1150 1151 static void 1152 vgatext_init(struct vgatext_softc *softc) 1153 { 1154 unsigned char atr_mode; 1155 1156 atr_mode = vga_get_atr(&softc->regs, VGA_ATR_MODE); 1157 if (atr_mode & VGA_ATR_MODE_GRAPH) 1158 vgatext_set_text(softc); 1159 atr_mode = vga_get_atr(&softc->regs, VGA_ATR_MODE); 1160 atr_mode &= ~VGA_ATR_MODE_BLINK; 1161 atr_mode &= ~VGA_ATR_MODE_9WIDE; 1162 vga_set_atr(&softc->regs, VGA_ATR_MODE, atr_mode); 1163 #if defined(USE_BORDERS) 1164 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, 1165 vga_get_atr(&softc->regs, VGA_BRIGHT_WHITE)); 1166 #else 1167 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, 1168 vga_get_atr(&softc->regs, VGA_BLACK)); 1169 #endif 1170 vgatext_setfont(softc); /* need selectable font? */ 1171 } 1172 1173 #if defined(USE_BORDERS) 1174 static void 1175 vgatext_init_graphics(struct vgatext_softc *softc) 1176 { 1177 vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, 1178 vga_get_atr(&softc->regs, VGA_BLACK)); 1179 } 1180 #endif 1181 1182 static void 1183 vgatext_setfont(struct vgatext_softc *softc) 1184 { 1185 extern unsigned char *ENCODINGS[]; 1186 unsigned char *from; 1187 unsigned char *to; 1188 int i; 1189 int j; 1190 int bpc; 1191 1192 /* 1193 * The newboot code to use font plane 2 breaks NVIDIA 1194 * (and some ATI) behavior. Revert back to the S10 1195 * code. 1196 */ 1197 1198 /* 1199 * I'm embarassed to say that I don't know what these magic 1200 * sequences do, other than at the high level of "set the 1201 * memory window to allow font setup". I stole them straight 1202 * from "kd"... 1203 */ 1204 vga_set_seq(&softc->regs, 0x02, 0x04); 1205 vga_set_seq(&softc->regs, 0x04, 0x06); 1206 vga_set_grc(&softc->regs, 0x05, 0x00); 1207 vga_set_grc(&softc->regs, 0x06, 0x04); 1208 1209 /* 1210 * This assumes 8x16 characters, which yield the traditional 80x25 1211 * screen. It really should support other character heights. 1212 */ 1213 bpc = 16; 1214 for (i = 0; i < 256; i++) { 1215 from = ENCODINGS[i]; 1216 to = (unsigned char *)softc->fb.addr + i * 0x20; 1217 for (j = 0; j < bpc; j++) 1218 *to++ = *from++; 1219 } 1220 1221 vga_set_seq(&softc->regs, 0x02, 0x03); 1222 vga_set_seq(&softc->regs, 0x04, 0x02); 1223 vga_set_grc(&softc->regs, 0x04, 0x00); 1224 vga_set_grc(&softc->regs, 0x05, 0x10); 1225 vga_set_grc(&softc->regs, 0x06, 0x0e); 1226 1227 } 1228 1229 static void 1230 vgatext_save_colormap(struct vgatext_softc *softc) 1231 { 1232 int i; 1233 1234 for (i = 0; i < VGA_ATR_NUM_PLT; i++) { 1235 softc->attrib_palette[i] = vga_get_atr(&softc->regs, i); 1236 } 1237 for (i = 0; i < VGA8_CMAP_ENTRIES; i++) { 1238 vga_get_cmap(&softc->regs, i, 1239 &softc->colormap[i].red, 1240 &softc->colormap[i].green, 1241 &softc->colormap[i].blue); 1242 } 1243 } 1244 1245 static void 1246 vgatext_restore_colormap(struct vgatext_softc *softc) 1247 { 1248 int i; 1249 1250 for (i = 0; i < VGA_ATR_NUM_PLT; i++) { 1251 vga_set_atr(&softc->regs, i, softc->attrib_palette[i]); 1252 } 1253 for (i = 0; i < VGA8_CMAP_ENTRIES; i++) { 1254 vga_put_cmap(&softc->regs, i, 1255 softc->colormap[i].red, 1256 softc->colormap[i].green, 1257 softc->colormap[i].blue); 1258 } 1259 } 1260 1261 /* 1262 * search the entries of the "reg" property for one which has the desired 1263 * combination of phys_hi bits and contains the desired address. 1264 * 1265 * This version searches a PCI-style "reg" property. It was prompted by 1266 * issues surrounding the presence or absence of an entry for the ROM: 1267 * (a) a transition problem with PowerPC Virtual Open Firmware 1268 * (b) uncertainty as to whether an entry will be included on a device 1269 * with ROM support (and so an "active" ROM base address register), 1270 * but no ROM actually installed. 1271 * 1272 * See the note below on vgatext_get_isa_reg_index for the reasons for 1273 * returning the offset. 1274 * 1275 * Note that this routine may not be fully general; it is intended for the 1276 * specific purpose of finding a couple of particular VGA reg entries and 1277 * may not be suitable for all reg-searching purposes. 1278 */ 1279 static int 1280 vgatext_get_pci_reg_index( 1281 dev_info_t *const devi, 1282 unsigned long himask, 1283 unsigned long hival, 1284 unsigned long addr, 1285 off_t *offset) 1286 { 1287 1288 int length, index; 1289 pci_regspec_t *reg; 1290 1291 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 1292 "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { 1293 return (-1); 1294 } 1295 1296 for (index = 0; index < length / sizeof (pci_regspec_t); index++) { 1297 if ((reg[index].pci_phys_hi & himask) != hival) 1298 continue; 1299 if (reg[index].pci_size_hi != 0) 1300 continue; 1301 if (reg[index].pci_phys_mid != 0) 1302 continue; 1303 if (reg[index].pci_phys_low > addr) 1304 continue; 1305 if (reg[index].pci_phys_low + reg[index].pci_size_low <= addr) 1306 continue; 1307 1308 *offset = addr - reg[index].pci_phys_low; 1309 kmem_free(reg, (size_t)length); 1310 return (index); 1311 } 1312 kmem_free(reg, (size_t)length); 1313 1314 return (-1); 1315 } 1316 1317 /* 1318 * search the entries of the "reg" property for one which has the desired 1319 * combination of phys_hi bits and contains the desired address. 1320 * 1321 * This version searches a ISA-style "reg" property. It was prompted by 1322 * issues surrounding 8514/A support. By IEEE 1275 compatibility conventions, 1323 * 8514/A registers should have been added after all standard VGA registers. 1324 * Unfortunately, the Solaris/Intel device configuration framework 1325 * (a) lists the 8514/A registers before the video memory, and then 1326 * (b) also sorts the entries so that I/O entries come before memory 1327 * entries. 1328 * 1329 * It returns the "reg" index and offset into that register set. 1330 * The offset is needed because there exist (broken?) BIOSes that 1331 * report larger ranges enclosing the standard ranges. One reports 1332 * 0x3bf for 0x21 instead of 0x3c0 for 0x20, for instance. Using the 1333 * offset adjusts for this difference in the base of the register set. 1334 * 1335 * Note that this routine may not be fully general; it is intended for the 1336 * specific purpose of finding a couple of particular VGA reg entries and 1337 * may not be suitable for all reg-searching purposes. 1338 */ 1339 static int 1340 vgatext_get_isa_reg_index( 1341 dev_info_t *const devi, 1342 unsigned long hival, 1343 unsigned long addr, 1344 off_t *offset) 1345 { 1346 1347 int length, index; 1348 struct regspec *reg; 1349 1350 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 1351 "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { 1352 return (-1); 1353 } 1354 1355 for (index = 0; index < length / sizeof (struct regspec); index++) { 1356 if (reg[index].regspec_bustype != hival) 1357 continue; 1358 if (reg[index].regspec_addr > addr) 1359 continue; 1360 if (reg[index].regspec_addr + reg[index].regspec_size <= addr) 1361 continue; 1362 1363 *offset = addr - reg[index].regspec_addr; 1364 kmem_free(reg, (size_t)length); 1365 return (index); 1366 } 1367 kmem_free(reg, (size_t)length); 1368 1369 return (-1); 1370 } 1371 1372 /* 1373 * This vgatext function is used to return the fb, and reg pointers 1374 * and handles for peer graphics drivers. 1375 */ 1376 1377 void 1378 vgatext_return_pointers(struct vgatext_softc *softc, 1379 struct vgaregmap *fbs, 1380 struct vgaregmap *regss) 1381 { 1382 1383 fbs->addr = softc->fb.addr; 1384 fbs->handle = softc->fb.handle; 1385 fbs->mapped = softc->fb.mapped; 1386 regss->addr = softc->regs.addr; 1387 regss->handle = softc->regs.handle; 1388 regss->mapped = softc->regs.mapped; 1389 } 1390 1391 1392 /* 1393 * **************************************************************** 1394 * If we had a "bitmap" console implementation, it could 1395 * use the functions below to cooperate with DRM. 1396 */ 1397 1398 1399 /* 1400 * If we had "bitmap" console support, this would 1401 * register call-back functions: drm_gfxp_setmode, 1402 * (and maybe others for blt, copy, clear) for the 1403 * "bitmap" console to use. 1404 * 1405 * The current (text) console doesn't need it. 1406 */ 1407 /* ARGSUSED */ 1408 void 1409 gfxp_bm_register_fbops(gfxp_fb_softc_ptr_t softc, 1410 struct gfxp_blt_ops *ops) 1411 { 1412 } 1413 1414 /* 1415 * This is patchable with mdb, i.e.: 1416 * $ mdb -w /platform/i86pc/kernel/misc/amd64/gfx_private 1417 * > gfxp_fb_info?ddVV 1418 * 1024 768 32 24 1419 */ 1420 struct gfxp_bm_fb_info gfxp_fb_info = { 1421 .xres = 1024, 1422 .yres = 768, 1423 .bpp = 32, 1424 .depth = 24, 1425 }; 1426 1427 /* 1428 * If we had "bitmap" console support, this would 1429 * ask the size of it. (how is TBD) 1430 * 1431 * Just guess (for now) 1432 */ 1433 void 1434 gfxp_bm_getfb_info(gfxp_fb_softc_ptr_t softc, 1435 struct gfxp_bm_fb_info *fbip) 1436 { 1437 _NOTE(ARGUNUSED(softc)) 1438 1439 *fbip = gfxp_fb_info; 1440 } 1441