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