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