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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/systm.h> 30 #include <sys/conf.h> 31 #include <sys/modctl.h> 32 #include <sys/file.h> 33 #include <sys/stat.h> 34 #include <sys/ddi.h> 35 #include <sys/sunddi.h> 36 #include <sys/modctl.h> 37 #include <sys/sunldi.h> 38 #include <sys/pci.h> 39 #include <sys/agpgart.h> 40 #include <sys/agp/agpdefs.h> 41 #include <sys/agp/agptarget_io.h> 42 43 int agptarget_debug_var = 0; 44 #define TARGETDB_PRINT2(fmt) if (agptarget_debug_var >= 1) cmn_err fmt 45 #define INST2NODENUM(inst) (inst) 46 #define DEV2INST(dev) (getminor(dev)) 47 48 typedef struct agp_target_softstate { 49 dev_info_t *tsoft_dip; 50 ddi_acc_handle_t tsoft_pcihdl; 51 uint32_t tsoft_devid; 52 /* The offset of the ACAPID register */ 53 off_t tsoft_acaptr; 54 kmutex_t tsoft_lock; 55 }agp_target_softstate_t; 56 57 /* 58 * To get the pre-allocated graphics mem size using Graphics Mode Select 59 * (GMS) value. 60 */ 61 typedef struct gms_mode { 62 uint32_t gm_devid; /* bridge vendor + device id */ 63 off_t gm_regoff; /* mode selection register offset */ 64 uint32_t gm_mask; /* GMS mask */ 65 uint32_t gm_num; /* number of modes in gm_vec */ 66 int *gm_vec; /* modes array */ 67 } gms_mode_t; 68 69 static void *agptarget_glob_soft_handle; 70 71 #define GETSOFTC(instance) ((agp_target_softstate_t *) \ 72 ddi_get_soft_state(agptarget_glob_soft_handle, instance)); 73 74 /* 75 * The AMD8151 bridge is the only supported 64 bit hardware 76 */ 77 static int 78 is_64bit_aper(agp_target_softstate_t *softstate) 79 { 80 return (softstate->tsoft_devid == AMD_BR_8151); 81 } 82 83 /* 84 * agp_target_cap_find() 85 * 86 * Description: 87 * This function searches the linked capability list to find the offset 88 * of the AGP capability register. When it was not found, return 0. 89 * This works for standard AGP chipsets, but not for some Intel chipsets, 90 * like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for 91 * these chipsets even if AGP is supported. So the offset of acapid 92 * should be set manually in thoses cases. 93 * 94 * Arguments: 95 * pci_handle ddi acc handle of pci config 96 * 97 * Returns: 98 * 0 No capability pointer register found 99 * nexcap The AGP capability pointer register offset 100 */ 101 static off_t 102 agp_target_cap_find(ddi_acc_handle_t pci_handle) 103 { 104 off_t nextcap = 0; 105 uint32_t ncapid = 0; 106 uint8_t value = 0; 107 108 /* Check if this device supports the capability pointer */ 109 value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT) 110 & PCI_CONF_CAP_MASK); 111 112 if (!value) 113 return (0); 114 /* Get the offset of the first capability pointer from CAPPTR */ 115 nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR)); 116 117 /* Check the AGP capability from the first capability pointer */ 118 while (nextcap) { 119 ncapid = pci_config_get32(pci_handle, nextcap); 120 /* 121 * AGP3.0 rev1.0 127 the capid was assigned by the PCI SIG, 122 * 845 data sheet page 69 123 */ 124 if ((ncapid & PCI_CONF_CAPID_MASK) == 125 AGP_CAP_ID) /* The AGP cap was found */ 126 break; 127 128 nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8); 129 } 130 131 return (nextcap); 132 133 } 134 135 /* 136 * agp_target_get_aperbase() 137 * 138 * Description: 139 * This function gets the AGP aperture base address from the AGP target 140 * register, the AGP aperture base register was programmed by the BIOS. 141 * 142 * Arguments: 143 * softstate driver soft state pointer 144 * 145 * Returns: 146 * aper_base AGP aperture base address 147 * 148 * Notes: 149 * If a 64bit bridge device is available, the AGP aperture base address 150 * can be 64 bit. 151 */ 152 static uint64_t 153 agp_target_get_apbase(agp_target_softstate_t *softstate) 154 { 155 uint64_t aper_base; 156 157 if (!is_64bit_aper(softstate)) { 158 aper_base = pci_config_get32(softstate->tsoft_pcihdl, 159 AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK; 160 } else { 161 aper_base = pci_config_get64(softstate->tsoft_pcihdl, 162 AGP_CONF_APERBASE); 163 /* 32-bit or 64-bit aperbase base pointer */ 164 if ((aper_base & AGP_APER_TYPE_MASK) == 0) 165 aper_base &= AGP_32_APERBASE_MASK; 166 else 167 aper_base &= AGP_64_APERBASE_MASK; 168 } 169 return (aper_base); 170 } 171 172 /* 173 * agp_target_get_apsize() 174 * 175 * Description: 176 * This function gets the AGP aperture size by reading the AGP aperture 177 * size register. 178 * Arguments: 179 * softstate driver soft state pointer 180 * 181 * Return: 182 * size The AGP aperture size in megabytes 183 * 0 an unexpected error 184 */ 185 static size_t 186 agp_target_get_apsize(agp_target_softstate_t *softstate) 187 { 188 off_t cap; 189 uint16_t value; 190 size_t size, regsize; 191 192 ASSERT(softstate->tsoft_acaptr); 193 cap = softstate->tsoft_acaptr; 194 195 if ((softstate->tsoft_devid & VENDOR_ID_MASK) == INTEL_VENDOR_ID) { 196 /* extend this value to 16 bit for later tests */ 197 value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl, 198 cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK; 199 } else { 200 value = pci_config_get16(softstate->tsoft_pcihdl, 201 cap + AGP_CONF_APERSIZE); 202 } 203 204 if (value & AGP_APER_128M_MASK) { 205 switch (value & AGP_APER_128M_MASK) { 206 case AGP_APER_4M: 207 size = 4; /* 4M */ 208 break; 209 case AGP_APER_8M: 210 size = 8; /* 8M */ 211 break; 212 case AGP_APER_16M: 213 size = 16; /* 16M */ 214 break; 215 case AGP_APER_32M: 216 size = 32; /* 32M */ 217 break; 218 case AGP_APER_64M: 219 size = 64; /* 64M */ 220 break; 221 case AGP_APER_128M: 222 size = 128; /* 128M */ 223 break; 224 default: 225 size = 0; /* not true */ 226 } 227 } else { 228 switch (value & AGP_APER_4G_MASK) { 229 case AGP_APER_256M: 230 size = 256; /* 256 M */ 231 break; 232 case AGP_APER_512M: 233 size = 512; /* 512 M */ 234 break; 235 case AGP_APER_1024M: 236 size = 1024; /* 1024 M */ 237 break; 238 case AGP_APER_2048M: 239 size = 2048; /* 2048 M */ 240 break; 241 case AGP_APER_4G: 242 size = 4096; /* 4096 M */ 243 break; 244 default: 245 size = 0; /* not true */ 246 } 247 } 248 /* 249 * In some cases, there is no APSIZE register, so the size value 250 * of 256M could be wrong. Check the value by reading the size of 251 * the first register which was set in the PCI configuration space. 252 */ 253 if (size == 256) { 254 if (ddi_dev_regsize(softstate->tsoft_dip, 255 AGP_TARGET_BAR1, (off_t *)®size) == DDI_FAILURE) 256 return (0); 257 258 if (MB2BYTES(size) != regsize) { 259 TARGETDB_PRINT2((CE_WARN, 260 "APSIZE 256M doesn't match regsize %lx", 261 regsize)); 262 TARGETDB_PRINT2((CE_WARN, "Use regsize instead")); 263 size = BYTES2MB(regsize); 264 } 265 } 266 267 return (size); 268 } 269 270 static void 271 agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr) 272 { 273 ASSERT(softstate->tsoft_acaptr); 274 275 /* Disable the GTLB for Intel chipsets */ 276 pci_config_put16(softstate->tsoft_pcihdl, 277 softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000); 278 279 pci_config_put32(softstate->tsoft_pcihdl, 280 softstate->tsoft_acaptr + AGP_CONF_ATTBASE, 281 gartaddr & AGP_ATTBASE_MASK); 282 } 283 284 /* 285 * Pre-allocated graphics memory for every type of Intel north bridge, mem size 286 * are specified in kbytes. 287 */ 288 #define GMS_MB(n) ((n) * 1024) 289 #define GMS_SHIFT 4 290 #define GMS_SIZE(a) (sizeof (a) / sizeof (int)) 291 292 /* 293 * Since value zero always means "No memory pre-allocated", value of (GMS - 1) 294 * is used to index these arrays, i.e. gms_xxx[1] contains the mem size (in kb) 295 * that GMS value 0x1 corresponding to. 296 * 297 * Assuming all "reserved" GMS value as zero bytes of pre-allocated graphics 298 * memory, unless some special BIOS settings exist. 299 */ 300 static int gms_810[12] = {0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, GMS_MB(1)}; 301 static int gms_830_845[4] = {0, 512, GMS_MB(1), GMS_MB(8)}; 302 static int gms_855GM[5] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16), 303 GMS_MB(32)}; 304 /* There is no modes for 16M in datasheet, but some BIOS add it. */ 305 static int gms_865_915GM[4] = {GMS_MB(1), 0, GMS_MB(8), GMS_MB(16)}; 306 static int gms_915_945_965[3] = {GMS_MB(1), 0, GMS_MB(8)}; 307 static int gms_965GM[7] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16), 308 GMS_MB(32), GMS_MB(48), GMS_MB(64)}; 309 static int gms_X33[9] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16), 310 GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256)}; 311 312 static gms_mode_t gms_modes[] = { 313 {INTEL_BR_810, I810_CONF_SMRAM, I810_GMS_MASK, 314 GMS_SIZE(gms_810), gms_810}, 315 {INTEL_BR_810DC, I810_CONF_SMRAM, I810_GMS_MASK, 316 GMS_SIZE(gms_810), gms_810}, 317 {INTEL_BR_810E, I810_CONF_SMRAM, I810_GMS_MASK, 318 GMS_SIZE(gms_810), gms_810}, 319 {INTEL_BR_830M, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 320 GMS_SIZE(gms_830_845), gms_830_845}, 321 {INTEL_BR_845, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 322 GMS_SIZE(gms_830_845), gms_830_845}, 323 {INTEL_BR_855GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 324 GMS_SIZE(gms_855GM), gms_855GM}, 325 {INTEL_BR_865, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 326 GMS_SIZE(gms_865_915GM), gms_865_915GM}, 327 {INTEL_BR_915GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 328 GMS_SIZE(gms_865_915GM), gms_865_915GM}, 329 {INTEL_BR_915, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 330 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 331 {INTEL_BR_945, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 332 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 333 {INTEL_BR_945GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 334 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 335 {INTEL_BR_946GZ, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 336 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 337 {INTEL_BR_965G1, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 338 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 339 {INTEL_BR_965G2, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 340 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 341 {INTEL_BR_965Q, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 342 GMS_SIZE(gms_915_945_965), gms_915_945_965}, 343 {INTEL_BR_965GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 344 GMS_SIZE(gms_965GM), gms_965GM}, 345 {INTEL_BR_965GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK, 346 GMS_SIZE(gms_965GM), gms_965GM}, 347 {INTEL_BR_Q35, I8XX_CONF_GC, IX33_GC_MODE_MASK, 348 GMS_SIZE(gms_X33), gms_X33}, 349 {INTEL_BR_G33, I8XX_CONF_GC, IX33_GC_MODE_MASK, 350 GMS_SIZE(gms_X33), gms_X33}, 351 {INTEL_BR_Q33, I8XX_CONF_GC, IX33_GC_MODE_MASK, 352 GMS_SIZE(gms_X33), gms_X33} 353 }; 354 355 /* Returns the size (kbytes) of pre-allocated graphics memory */ 356 static size_t 357 i8xx_biosmem_detect(agp_target_softstate_t *softstate) 358 { 359 uint8_t memval; 360 size_t kbytes; 361 int i; 362 int num_modes; 363 364 kbytes = 0; 365 /* get GMS modes list entry */ 366 num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t)); 367 for (i = 0; i < num_modes; i++) { 368 if (gms_modes[i].gm_devid == softstate->tsoft_devid) 369 break; 370 } 371 if (i == num_modes) 372 goto done; 373 /* fetch the GMS value from DRAM controller */ 374 memval = pci_config_get8(softstate->tsoft_pcihdl, 375 gms_modes[i].gm_regoff); 376 TARGETDB_PRINT2((CE_NOTE, "i8xx_biosmem_detect: memval = %x", memval)); 377 memval = (memval & gms_modes[i].gm_mask) >> GMS_SHIFT; 378 /* assuming zero byte for 0 or "reserved" GMS values */ 379 if (memval == 0 || memval > gms_modes[i].gm_num) { 380 TARGETDB_PRINT2((CE_WARN, "i8xx_biosmem_detect: " 381 "devid = %x, GMS = %x. assuming zero byte of " 382 "pre-allocated memory", gms_modes[i].gm_devid, memval)); 383 goto done; 384 } 385 memval--; /* use (GMS_value - 1) as index */ 386 kbytes = (gms_modes[i].gm_vec)[memval]; 387 388 done: 389 TARGETDB_PRINT2((CE_NOTE, 390 "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected", 391 kbytes)); 392 return (kbytes); 393 } 394 395 /*ARGSUSED*/ 396 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 397 void *arg, void **resultp) 398 { 399 agp_target_softstate_t *st; 400 int instance, rval = DDI_FAILURE; 401 dev_t dev; 402 403 switch (cmd) { 404 case DDI_INFO_DEVT2DEVINFO: 405 dev = (dev_t)arg; 406 instance = DEV2INST(dev); 407 st = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 408 if (st != NULL) { 409 mutex_enter(&st->tsoft_lock); 410 *resultp = st->tsoft_dip; 411 mutex_exit(&st->tsoft_lock); 412 rval = DDI_SUCCESS; 413 } else 414 *resultp = NULL; 415 416 break; 417 case DDI_INFO_DEVT2INSTANCE: 418 dev = (dev_t)arg; 419 instance = DEV2INST(dev); 420 *resultp = (void *)(uintptr_t)instance; 421 rval = DDI_SUCCESS; 422 default: 423 break; 424 } 425 426 return (rval); 427 } 428 429 static int 430 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 431 { 432 agp_target_softstate_t *softstate; 433 int instance; 434 int status; 435 436 if (cmd != DDI_ATTACH) 437 return (DDI_FAILURE); 438 439 instance = ddi_get_instance(dip); 440 441 if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) != 442 DDI_SUCCESS) 443 return (DDI_FAILURE); 444 445 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 446 mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL); 447 softstate->tsoft_dip = dip; 448 status = pci_config_setup(dip, &softstate->tsoft_pcihdl); 449 if (status != DDI_SUCCESS) { 450 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 451 return (DDI_FAILURE); 452 } 453 454 softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl, 455 PCI_CONF_VENID); 456 softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl); 457 if (softstate->tsoft_acaptr == 0) { 458 /* Make a correction for some Intel chipsets */ 459 if ((softstate->tsoft_devid & VENDOR_ID_MASK) == 460 INTEL_VENDOR_ID) 461 softstate->tsoft_acaptr = AGP_CAP_OFF_DEF; 462 else 463 return (DDI_FAILURE); 464 } 465 466 status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR, 467 INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0); 468 469 if (status != DDI_SUCCESS) { 470 pci_config_teardown(&softstate->tsoft_pcihdl); 471 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 472 return (DDI_FAILURE); 473 } 474 475 return (DDI_SUCCESS); 476 } 477 478 /*ARGSUSED*/ 479 static int 480 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 481 { 482 int instance; 483 agp_target_softstate_t *softstate; 484 485 if (cmd != DDI_DETACH) 486 return (DDI_FAILURE); 487 488 instance = ddi_get_instance(dip); 489 490 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 491 492 ddi_remove_minor_node(dip, AGPTARGET_NAME); 493 pci_config_teardown(&softstate->tsoft_pcihdl); 494 mutex_destroy(&softstate->tsoft_lock); 495 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 496 return (DDI_SUCCESS); 497 } 498 499 /*ARGSUSED*/ 500 static int 501 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 502 cred_t *cred, int *rval) 503 { 504 int instance = DEV2INST(dev); 505 agp_target_softstate_t *st; 506 static char kernel_only[] = 507 "amd64_gart_ioctl: is a kernel only ioctl"; 508 509 if (!(mode & FKIOCTL)) { 510 TARGETDB_PRINT2((CE_CONT, kernel_only)); 511 return (ENXIO); 512 } 513 st = GETSOFTC(instance); 514 515 if (st == NULL) 516 return (ENXIO); 517 518 mutex_enter(&st->tsoft_lock); 519 520 switch (cmd) { 521 case CHIP_DETECT: 522 { 523 int type; 524 switch (st->tsoft_devid & VENDOR_ID_MASK) { 525 case INTEL_VENDOR_ID: 526 type = CHIP_IS_INTEL; 527 break; 528 case AMD_VENDOR_ID: 529 type = CHIP_IS_AMD; 530 break; 531 default: 532 type = 0; 533 } 534 if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) { 535 mutex_exit(&st->tsoft_lock); 536 return (EFAULT); 537 } 538 539 break; 540 } 541 case I8XX_GET_PREALLOC_SIZE: 542 { 543 size_t prealloc_size; 544 545 if ((st->tsoft_devid & VENDOR_ID_MASK) != 546 INTEL_VENDOR_ID) { 547 mutex_exit(&st->tsoft_lock); 548 return (EINVAL); 549 } 550 551 prealloc_size = i8xx_biosmem_detect(st); 552 if (ddi_copyout(&prealloc_size, (void *)data, 553 sizeof (size_t), mode)) { 554 mutex_exit(&st->tsoft_lock); 555 return (EFAULT); 556 } 557 558 break; 559 } 560 case AGP_TARGET_GETINFO: 561 { 562 i_agp_info_t info; 563 uint32_t value; 564 off_t cap; 565 566 ASSERT(st->tsoft_acaptr); 567 568 cap = st->tsoft_acaptr; 569 value = pci_config_get32(st->tsoft_pcihdl, cap); 570 info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf); 571 info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf); 572 info.iagp_devid = st->tsoft_devid; 573 info.iagp_mode = pci_config_get32(st->tsoft_pcihdl, 574 cap + AGP_CONF_STATUS); 575 info.iagp_aperbase = agp_target_get_apbase(st); 576 info.iagp_apersize = agp_target_get_apsize(st); 577 578 if (ddi_copyout(&info, (void *)data, 579 sizeof (i_agp_info_t), mode)) { 580 mutex_exit(&st->tsoft_lock); 581 return (EFAULT); 582 } 583 break; 584 585 } 586 /* 587 * This ioctl is only for Intel AGP chipsets. 588 * It is not necessary for the AMD8151 AGP bridge, because 589 * this register in the AMD8151 does not control any hardware. 590 * It is only provided for compatibility with an Intel AGP bridge. 591 * Please refer to the <<AMD8151 data sheet>> page 24, 592 * AGP device GART pointer. 593 */ 594 case AGP_TARGET_SET_GATTADDR: 595 { 596 uint32_t gartaddr; 597 598 if (ddi_copyin((void *)data, &gartaddr, 599 sizeof (uint32_t), mode)) { 600 mutex_exit(&st->tsoft_lock); 601 return (EFAULT); 602 } 603 604 agp_target_set_gartaddr(st, gartaddr); 605 break; 606 } 607 case AGP_TARGET_SETCMD: 608 { 609 uint32_t command; 610 611 if (ddi_copyin((void *)data, &command, 612 sizeof (uint32_t), mode)) { 613 mutex_exit(&st->tsoft_lock); 614 return (EFAULT); 615 } 616 617 ASSERT(st->tsoft_acaptr); 618 619 pci_config_put32(st->tsoft_pcihdl, 620 st->tsoft_acaptr + AGP_CONF_COMMAND, 621 command); 622 break; 623 624 } 625 case AGP_TARGET_FLUSH_GTLB: 626 { 627 uint16_t value; 628 629 ASSERT(st->tsoft_acaptr); 630 631 value = pci_config_get16(st->tsoft_pcihdl, 632 st->tsoft_acaptr + AGP_CONF_CONTROL); 633 value &= ~AGPCTRL_GTLBEN; 634 pci_config_put16(st->tsoft_pcihdl, 635 st->tsoft_acaptr + AGP_CONF_CONTROL, value); 636 value |= AGPCTRL_GTLBEN; 637 pci_config_put16(st->tsoft_pcihdl, 638 st->tsoft_acaptr + AGP_CONF_CONTROL, value); 639 640 break; 641 } 642 case AGP_TARGET_CONFIGURE: 643 { 644 uint8_t value; 645 646 ASSERT(st->tsoft_acaptr); 647 648 value = pci_config_get8(st->tsoft_pcihdl, 649 st->tsoft_acaptr + AGP_CONF_MISC); 650 value |= AGP_MISC_APEN; 651 pci_config_put8(st->tsoft_pcihdl, 652 st->tsoft_acaptr + AGP_CONF_MISC, value); 653 break; 654 655 } 656 case AGP_TARGET_UNCONFIG: 657 { 658 uint32_t value1; 659 uint8_t value2; 660 661 ASSERT(st->tsoft_acaptr); 662 663 pci_config_put16(st->tsoft_pcihdl, 664 st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0); 665 666 value2 = pci_config_get8(st->tsoft_pcihdl, 667 st->tsoft_acaptr + AGP_CONF_MISC); 668 value2 &= ~AGP_MISC_APEN; 669 pci_config_put8(st->tsoft_pcihdl, 670 st->tsoft_acaptr + AGP_CONF_MISC, value2); 671 672 value1 = pci_config_get32(st->tsoft_pcihdl, 673 st->tsoft_acaptr + AGP_CONF_COMMAND); 674 value1 &= ~AGPCMD_AGPEN; 675 pci_config_put32(st->tsoft_pcihdl, 676 st->tsoft_acaptr + AGP_CONF_COMMAND, 677 value1); 678 679 pci_config_put32(st->tsoft_pcihdl, 680 st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0); 681 682 break; 683 } 684 685 default: 686 mutex_exit(&st->tsoft_lock); 687 return (ENXIO); 688 } /* end switch */ 689 690 mutex_exit(&st->tsoft_lock); 691 692 return (0); 693 } 694 695 /*ARGSUSED*/ 696 static int 697 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred) 698 { 699 int instance = DEV2INST(*devp); 700 agp_target_softstate_t *st; 701 702 if (!(flag & FKLYR)) 703 return (ENXIO); 704 705 st = GETSOFTC(instance); 706 707 if (st == NULL) 708 return (ENXIO); 709 710 return (0); 711 } 712 713 /*ARGSUSED*/ 714 static int 715 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred) 716 { 717 int instance = DEV2INST(dev); 718 agp_target_softstate_t *st; 719 720 st = GETSOFTC(instance); 721 722 if (st == NULL) 723 return (ENXIO); 724 725 return (0); 726 } 727 728 static struct cb_ops agp_target_cb_ops = { 729 agp_target_open, /* cb_open */ 730 agp_target_close, /* cb_close */ 731 nodev, /* cb_strategy */ 732 nodev, /* cb_print */ 733 nodev, /* cb_dump */ 734 nodev, /* cb_read() */ 735 nodev, /* cb_write() */ 736 agp_target_ioctl, /* cb_ioctl */ 737 nodev, /* cb_devmap */ 738 nodev, /* cb_mmap */ 739 nodev, /* cb_segmap */ 740 nochpoll, /* cb_chpoll */ 741 ddi_prop_op, /* cb_prop_op */ 742 0, /* cb_stream */ 743 D_NEW | D_MP, /* cb_flag */ 744 CB_REV, /* cb_ops version? */ 745 nodev, /* cb_aread() */ 746 nodev, /* cb_awrite() */ 747 }; 748 749 /* device operations */ 750 static struct dev_ops agp_target_ops = { 751 DEVO_REV, /* devo_rev */ 752 0, /* devo_refcnt */ 753 agptarget_getinfo, /* devo_getinfo */ 754 nulldev, /* devo_identify */ 755 nulldev, /* devo_probe */ 756 agp_target_attach, /* devo_attach */ 757 agp_target_detach, /* devo_detach */ 758 nodev, /* devo_reset */ 759 &agp_target_cb_ops, /* devo_cb_ops */ 760 0, /* devo_bus_ops */ 761 0, /* devo_power */ 762 }; 763 764 static struct modldrv modldrv = { 765 &mod_driverops, 766 "AGP target driver v%I%", 767 &agp_target_ops, 768 }; 769 770 static struct modlinkage modlinkage = { 771 MODREV_1, /* MODREV_1 is indicated by manual */ 772 {&modldrv, NULL, NULL, NULL} 773 }; 774 775 int 776 _init(void) 777 { 778 int ret; 779 780 ret = ddi_soft_state_init(&agptarget_glob_soft_handle, 781 sizeof (agp_target_softstate_t), 1); 782 783 if (ret) 784 goto err1; 785 786 if ((ret = mod_install(&modlinkage)) != 0) { 787 goto err2; 788 } 789 790 return (DDI_SUCCESS); 791 err2: 792 ddi_soft_state_fini(&agptarget_glob_soft_handle); 793 err1: 794 return (ret); 795 } 796 797 int 798 _info(struct modinfo *modinfop) 799 { 800 return (mod_info(&modlinkage, modinfop)); 801 } 802 803 int 804 _fini(void) 805 { 806 int ret; 807 808 if ((ret = mod_remove(&modlinkage)) == 0) { 809 ddi_soft_state_fini(&agptarget_glob_soft_handle); 810 } 811 return (ret); 812 } 813