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