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