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 case INTEL_BR_965GME: 364 memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC); 365 switch (memval & I8XX_GC_MODE_MASK) { 366 case I8XX_GC_MODE1: 367 kbytes = 1024; /* 1M preallocated memory */ 368 break; 369 case I8XX_GC_MODE3: 370 kbytes = 8 * 1024; /* 8M preallocated memory */ 371 break; 372 default: 373 kbytes = 0; /* an unexpected case */ 374 } 375 break; 376 default: 377 kbytes = 0; 378 } 379 380 TARGETDB_PRINT2((CE_NOTE, 381 "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected", 382 kbytes)); 383 return (kbytes); 384 } 385 386 /*ARGSUSED*/ 387 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, 388 void *arg, void **resultp) 389 { 390 agp_target_softstate_t *st; 391 int instance, rval = DDI_FAILURE; 392 dev_t dev; 393 394 switch (cmd) { 395 case DDI_INFO_DEVT2DEVINFO: 396 dev = (dev_t)arg; 397 instance = DEV2INST(dev); 398 st = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 399 if (st != NULL) { 400 mutex_enter(&st->tsoft_lock); 401 *resultp = st->tsoft_dip; 402 mutex_exit(&st->tsoft_lock); 403 rval = DDI_SUCCESS; 404 } else 405 *resultp = NULL; 406 407 break; 408 case DDI_INFO_DEVT2INSTANCE: 409 dev = (dev_t)arg; 410 instance = DEV2INST(dev); 411 *resultp = (void *)(uintptr_t)instance; 412 rval = DDI_SUCCESS; 413 default: 414 break; 415 } 416 417 return (rval); 418 } 419 420 static int 421 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 422 { 423 agp_target_softstate_t *softstate; 424 int instance; 425 int status; 426 427 if (cmd != DDI_ATTACH) 428 return (DDI_FAILURE); 429 430 instance = ddi_get_instance(dip); 431 432 if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) != 433 DDI_SUCCESS) 434 return (DDI_FAILURE); 435 436 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 437 mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL); 438 softstate->tsoft_dip = dip; 439 status = pci_config_setup(dip, &softstate->tsoft_pcihdl); 440 if (status != DDI_SUCCESS) { 441 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 442 return (DDI_FAILURE); 443 } 444 445 softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl, 446 PCI_CONF_VENID); 447 softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl); 448 if (softstate->tsoft_acaptr == 0) { 449 /* Make a correction for some Intel chipsets */ 450 if ((softstate->tsoft_devid & VENDOR_ID_MASK) == 451 INTEL_VENDOR_ID) 452 softstate->tsoft_acaptr = AGP_CAP_OFF_DEF; 453 else 454 return (DDI_FAILURE); 455 } 456 457 status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR, 458 INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0); 459 460 if (status != DDI_SUCCESS) { 461 pci_config_teardown(&softstate->tsoft_pcihdl); 462 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 463 return (DDI_FAILURE); 464 } 465 466 return (DDI_SUCCESS); 467 } 468 469 /*ARGSUSED*/ 470 static int 471 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 472 { 473 int instance; 474 agp_target_softstate_t *softstate; 475 476 if (cmd != DDI_DETACH) 477 return (DDI_FAILURE); 478 479 instance = ddi_get_instance(dip); 480 481 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance); 482 483 ddi_remove_minor_node(dip, AGPTARGET_NAME); 484 pci_config_teardown(&softstate->tsoft_pcihdl); 485 mutex_destroy(&softstate->tsoft_lock); 486 ddi_soft_state_free(agptarget_glob_soft_handle, instance); 487 return (DDI_SUCCESS); 488 } 489 490 /*ARGSUSED*/ 491 static int 492 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 493 cred_t *cred, int *rval) 494 { 495 int instance = DEV2INST(dev); 496 agp_target_softstate_t *st; 497 static char kernel_only[] = 498 "amd64_gart_ioctl: is a kernel only ioctl"; 499 500 if (!(mode & FKIOCTL)) { 501 TARGETDB_PRINT2((CE_CONT, kernel_only)); 502 return (ENXIO); 503 } 504 st = GETSOFTC(instance); 505 506 if (st == NULL) 507 return (ENXIO); 508 509 mutex_enter(&st->tsoft_lock); 510 511 switch (cmd) { 512 case CHIP_DETECT: 513 { 514 int type; 515 switch (st->tsoft_devid & VENDOR_ID_MASK) { 516 case INTEL_VENDOR_ID: 517 type = CHIP_IS_INTEL; 518 break; 519 case AMD_VENDOR_ID: 520 type = CHIP_IS_AMD; 521 break; 522 default: 523 type = 0; 524 } 525 if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) { 526 mutex_exit(&st->tsoft_lock); 527 return (EFAULT); 528 } 529 530 break; 531 } 532 case I8XX_GET_PREALLOC_SIZE: 533 { 534 size_t prealloc_size; 535 536 if ((st->tsoft_devid & VENDOR_ID_MASK) != 537 INTEL_VENDOR_ID) { 538 mutex_exit(&st->tsoft_lock); 539 return (EINVAL); 540 } 541 542 prealloc_size = i8xx_biosmem_detect(st); 543 if (ddi_copyout(&prealloc_size, (void *)data, 544 sizeof (size_t), mode)) { 545 mutex_exit(&st->tsoft_lock); 546 return (EFAULT); 547 } 548 549 break; 550 } 551 case AGP_TARGET_GETINFO: 552 { 553 i_agp_info_t info; 554 uint32_t value; 555 off_t cap; 556 557 ASSERT(st->tsoft_acaptr); 558 559 cap = st->tsoft_acaptr; 560 value = pci_config_get32(st->tsoft_pcihdl, cap); 561 info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf); 562 info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf); 563 info.iagp_devid = st->tsoft_devid; 564 info.iagp_mode = pci_config_get32(st->tsoft_pcihdl, 565 cap + AGP_CONF_STATUS); 566 info.iagp_aperbase = agp_target_get_apbase(st); 567 info.iagp_apersize = agp_target_get_apsize(st); 568 569 if (ddi_copyout(&info, (void *)data, 570 sizeof (i_agp_info_t), mode)) { 571 mutex_exit(&st->tsoft_lock); 572 return (EFAULT); 573 } 574 break; 575 576 } 577 /* 578 * This ioctl is only for Intel AGP chipsets. 579 * It is not necessary for the AMD8151 AGP bridge, because 580 * this register in the AMD8151 does not control any hardware. 581 * It is only provided for compatibility with an Intel AGP bridge. 582 * Please refer to the <<AMD8151 data sheet>> page 24, 583 * AGP device GART pointer. 584 */ 585 case AGP_TARGET_SET_GATTADDR: 586 { 587 uint32_t gartaddr; 588 589 if (ddi_copyin((void *)data, &gartaddr, 590 sizeof (uint32_t), mode)) { 591 mutex_exit(&st->tsoft_lock); 592 return (EFAULT); 593 } 594 595 agp_target_set_gartaddr(st, gartaddr); 596 break; 597 } 598 case AGP_TARGET_SETCMD: 599 { 600 uint32_t command; 601 602 if (ddi_copyin((void *)data, &command, 603 sizeof (uint32_t), mode)) { 604 mutex_exit(&st->tsoft_lock); 605 return (EFAULT); 606 } 607 608 ASSERT(st->tsoft_acaptr); 609 610 pci_config_put32(st->tsoft_pcihdl, 611 st->tsoft_acaptr + AGP_CONF_COMMAND, 612 command); 613 break; 614 615 } 616 case AGP_TARGET_FLUSH_GTLB: 617 { 618 uint16_t value; 619 620 ASSERT(st->tsoft_acaptr); 621 622 value = pci_config_get16(st->tsoft_pcihdl, 623 st->tsoft_acaptr + AGP_CONF_CONTROL); 624 value &= ~AGPCTRL_GTLBEN; 625 pci_config_put16(st->tsoft_pcihdl, 626 st->tsoft_acaptr + AGP_CONF_CONTROL, value); 627 value |= AGPCTRL_GTLBEN; 628 pci_config_put16(st->tsoft_pcihdl, 629 st->tsoft_acaptr + AGP_CONF_CONTROL, value); 630 631 break; 632 } 633 case AGP_TARGET_CONFIGURE: 634 { 635 uint8_t value; 636 637 ASSERT(st->tsoft_acaptr); 638 639 value = pci_config_get8(st->tsoft_pcihdl, 640 st->tsoft_acaptr + AGP_CONF_MISC); 641 value |= AGP_MISC_APEN; 642 pci_config_put8(st->tsoft_pcihdl, 643 st->tsoft_acaptr + AGP_CONF_MISC, value); 644 break; 645 646 } 647 case AGP_TARGET_UNCONFIG: 648 { 649 uint32_t value1; 650 uint8_t value2; 651 652 ASSERT(st->tsoft_acaptr); 653 654 pci_config_put16(st->tsoft_pcihdl, 655 st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0); 656 657 value2 = pci_config_get8(st->tsoft_pcihdl, 658 st->tsoft_acaptr + AGP_CONF_MISC); 659 value2 &= ~AGP_MISC_APEN; 660 pci_config_put8(st->tsoft_pcihdl, 661 st->tsoft_acaptr + AGP_CONF_MISC, value2); 662 663 value1 = pci_config_get32(st->tsoft_pcihdl, 664 st->tsoft_acaptr + AGP_CONF_COMMAND); 665 value1 &= ~AGPCMD_AGPEN; 666 pci_config_put32(st->tsoft_pcihdl, 667 st->tsoft_acaptr + AGP_CONF_COMMAND, 668 value1); 669 670 pci_config_put32(st->tsoft_pcihdl, 671 st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0); 672 673 break; 674 } 675 676 default: 677 mutex_exit(&st->tsoft_lock); 678 return (ENXIO); 679 } /* end switch */ 680 681 mutex_exit(&st->tsoft_lock); 682 683 return (0); 684 } 685 686 /*ARGSUSED*/ 687 static int 688 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred) 689 { 690 int instance = DEV2INST(*devp); 691 agp_target_softstate_t *st; 692 693 if (!(flag & FKLYR)) 694 return (ENXIO); 695 696 st = GETSOFTC(instance); 697 698 if (st == NULL) 699 return (ENXIO); 700 701 return (0); 702 } 703 704 /*ARGSUSED*/ 705 static int 706 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred) 707 { 708 int instance = DEV2INST(dev); 709 agp_target_softstate_t *st; 710 711 st = GETSOFTC(instance); 712 713 if (st == NULL) 714 return (ENXIO); 715 716 return (0); 717 } 718 719 static struct cb_ops agp_target_cb_ops = { 720 agp_target_open, /* cb_open */ 721 agp_target_close, /* cb_close */ 722 nodev, /* cb_strategy */ 723 nodev, /* cb_print */ 724 nodev, /* cb_dump */ 725 nodev, /* cb_read() */ 726 nodev, /* cb_write() */ 727 agp_target_ioctl, /* cb_ioctl */ 728 nodev, /* cb_devmap */ 729 nodev, /* cb_mmap */ 730 nodev, /* cb_segmap */ 731 nochpoll, /* cb_chpoll */ 732 ddi_prop_op, /* cb_prop_op */ 733 0, /* cb_stream */ 734 D_NEW | D_MP, /* cb_flag */ 735 CB_REV, /* cb_ops version? */ 736 nodev, /* cb_aread() */ 737 nodev, /* cb_awrite() */ 738 }; 739 740 /* device operations */ 741 static struct dev_ops agp_target_ops = { 742 DEVO_REV, /* devo_rev */ 743 0, /* devo_refcnt */ 744 agptarget_getinfo, /* devo_getinfo */ 745 nulldev, /* devo_identify */ 746 nulldev, /* devo_probe */ 747 agp_target_attach, /* devo_attach */ 748 agp_target_detach, /* devo_detach */ 749 nodev, /* devo_reset */ 750 &agp_target_cb_ops, /* devo_cb_ops */ 751 0, /* devo_bus_ops */ 752 0, /* devo_power */ 753 }; 754 755 static struct modldrv modldrv = { 756 &mod_driverops, 757 "AGP target driver v%I%", 758 &agp_target_ops, 759 }; 760 761 static struct modlinkage modlinkage = { 762 MODREV_1, /* MODREV_1 is indicated by manual */ 763 {&modldrv, NULL, NULL, NULL} 764 }; 765 766 int 767 _init(void) 768 { 769 int ret; 770 771 ret = ddi_soft_state_init(&agptarget_glob_soft_handle, 772 sizeof (agp_target_softstate_t), 1); 773 774 if (ret) 775 goto err1; 776 777 if ((ret = mod_install(&modlinkage)) != 0) { 778 goto err2; 779 } 780 781 return (DDI_SUCCESS); 782 err2: 783 ddi_soft_state_fini(&agptarget_glob_soft_handle); 784 err1: 785 return (ret); 786 } 787 788 int 789 _info(struct modinfo *modinfop) 790 { 791 return (mod_info(&modlinkage, modinfop)); 792 } 793 794 int 795 _fini(void) 796 { 797 int ret; 798 799 if ((ret = mod_remove(&modlinkage)) == 0) { 800 ddi_soft_state_fini(&agptarget_glob_soft_handle); 801 } 802 return (ret); 803 } 804