1 /* 2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Axel Dörfler, axeld@pinc-software.de 8 * Jerome Duval, jerome.duval@gmail.com 9 * Adrien Destugues, pulkomandy@gmail.com 10 * Michael Lotz, mmlr@mlotz.ch 11 * Alexander von Gluck IV, kallisti5@unixzen.com 12 */ 13 14 15 #include <AreaKeeper.h> 16 #include <intel_extreme.h> 17 18 #include <stdlib.h> 19 20 #include <AGP.h> 21 #include <KernelExport.h> 22 #include <PCI.h> 23 24 #include <new> 25 26 27 #define TRACE_INTEL 28 #ifdef TRACE_INTEL 29 # define TRACE(x...) dprintf("intel_gart: " x) 30 #else 31 # define TRACE(x...) ; 32 #endif 33 #define ERROR(x...) dprintf("intel_gart: " x) 34 35 36 /* read and write to PCI config space */ 37 #define get_pci_config(info, offset, size) \ 38 (sPCI->read_pci_config((info).bus, (info).device, (info).function, \ 39 (offset), (size))) 40 #define set_pci_config(info, offset, size, value) \ 41 (sPCI->write_pci_config((info).bus, (info).device, (info).function, \ 42 (offset), (size), (value))) 43 #define write32(address, data) \ 44 (*((volatile uint32*)(address)) = (data)) 45 #define read32(address) \ 46 (*((volatile uint32*)(address))) 47 48 49 // PCI "Host bridge" is most cases :-) 50 const struct supported_device { 51 uint32 bridge_id; 52 uint32 display_id; 53 int32 type; 54 const char *name; 55 } kSupportedDevices[] = { 56 {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"}, 57 {0x2560, 0x2562, INTEL_GROUP_83x, "i845G"}, 58 {0x3580, 0x3582, INTEL_GROUP_85x, "i855G"}, 59 {0x358c, 0x358e, INTEL_GROUP_85x, "i855G"}, 60 {0x2570, 0x2572, INTEL_GROUP_85x, "i865G"}, 61 62 // {0x2792, INTEL_GROUP_91x, "i910"}, 63 // {0x258a, INTEL_GROUP_91x, "i915"}, 64 {0x2580, 0x2582, INTEL_MODEL_915, "i915G"}, 65 {0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"}, 66 {0x2770, 0x2772, INTEL_MODEL_945, "i945G"}, 67 {0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"}, 68 {0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"}, 69 70 {0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"}, 71 {0x2980, 0x2982, INTEL_MODEL_965, "G35"}, 72 {0x2990, 0x2992, INTEL_MODEL_965, "i965Q"}, 73 {0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"}, 74 {0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"}, 75 {0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"}, 76 77 {0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"}, 78 {0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"}, 79 {0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"}, 80 81 {0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"}, 82 {0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"}, 83 {0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"}, 84 {0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"}, 85 {0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"}, 86 {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"}, 87 {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"}, 88 89 {0xa000, 0xa001, INTEL_MODEL_PINE, "Atom D4xx"}, 90 {0xa000, 0xa002, INTEL_MODEL_PINE, "Atom D5xx"}, 91 {0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom N4xx"}, 92 {0xa010, 0xa012, INTEL_MODEL_PINEM, "Atom N5xx"}, 93 94 {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, 95 {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 96 {0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 97 {0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, 98 99 {0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, 100 {0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, 101 {0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, 102 {0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, 103 {0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, 104 {0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, 105 {0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, 106 107 {0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, 108 {0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, 109 {0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, 110 {0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, 111 {0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, 112 {0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, 113 114 {0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, 115 {0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, 116 {0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, 117 {0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, 118 119 #if 0 120 // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31 121 {0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 122 {0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 123 {0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 124 {0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, 125 #endif 126 127 // XXX: 0x1604 only confirmed on 0x1616 128 {0x1604, 0x1606, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"}, 129 {0x1604, 0x160b, INTEL_MODEL_BDWM, "Broadwell GT1 Iris"}, 130 {0x1604, 0x160e, INTEL_MODEL_BDWM, "Broadwell GT1 ULX"}, 131 {0x1604, 0x1602, INTEL_MODEL_BDWM, "Broadwell GT1 ULT"}, 132 {0x1604, 0x160a, INTEL_MODEL_BDWS, "Broadwell GT1 Server"}, 133 {0x1604, 0x160d, INTEL_MODEL_BDW, "Broadwell GT1 Workstation"}, 134 {0x1604, 0x1616, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"}, 135 {0x1604, 0x161b, INTEL_MODEL_BDWM, "Broadwell GT2 ULT"}, 136 {0x1604, 0x161e, INTEL_MODEL_BDWM, "Broadwell GT2 ULX"}, 137 {0x1604, 0x1612, INTEL_MODEL_BDWM, "Broadwell GT2 Halo"}, 138 {0x1604, 0x161a, INTEL_MODEL_BDWS, "Broadwell GT2 Server"}, 139 {0x1604, 0x161d, INTEL_MODEL_BDW, "Broadwell GT2 Workstation"}, 140 {0x1604, 0x1626, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"}, 141 {0x1604, 0x162b, INTEL_MODEL_BDWM, "Broadwell GT3 Iris"}, 142 {0x1604, 0x162e, INTEL_MODEL_BDWM, "Broadwell GT3 ULX"}, 143 {0x1604, 0x1622, INTEL_MODEL_BDWM, "Broadwell GT3 ULT"}, 144 {0x1604, 0x162a, INTEL_MODEL_BDWS, "Broadwell GT3 Server"}, 145 {0x1604, 0x162d, INTEL_MODEL_BDW, "Broadwell GT3 Workstation"}, 146 147 // XXX: 0x1904 only confirmed on 0x1916 148 {0x1904, 0x1902, INTEL_MODEL_SKY, "Skylake GT1"}, 149 {0x1904, 0x1906, INTEL_MODEL_SKYM, "Skylake GT1"}, 150 {0x1904, 0x190a, INTEL_MODEL_SKYS, "Skylake GT1"}, 151 {0x1904, 0x190b, INTEL_MODEL_SKY, "Skylake GT1"}, 152 {0x1904, 0x190e, INTEL_MODEL_SKYM, "Skylake GT1"}, 153 {0x191f, 0x1912, INTEL_MODEL_SKY, "Skylake GT2"}, // confirmed 154 {0x1904, 0x1916, INTEL_MODEL_SKYM, "Skylake GT2"}, 155 {0x1904, 0x191a, INTEL_MODEL_SKYS, "Skylake GT2"}, 156 {0x1904, 0x191b, INTEL_MODEL_SKY, "Skylake GT2"}, 157 {0x1904, 0x191d, INTEL_MODEL_SKY, "Skylake GT2"}, 158 {0x1904, 0x191e, INTEL_MODEL_SKYM, "Skylake GT2"}, 159 {0x1904, 0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"}, 160 {0x1904, 0x1926, INTEL_MODEL_SKYM, "Skylake GT3"}, 161 {0x1904, 0x192a, INTEL_MODEL_SKYS, "Skylake GT3"}, 162 {0x1904, 0x192b, INTEL_MODEL_SKY, "Skylake GT3"}, 163 164 {0x5904, 0x5906, INTEL_MODEL_KBY, "Kabylake ULT GT1"}, 165 {0x590f, 0x5902, INTEL_MODEL_KBY, "Kabylake DT GT1"}, 166 {0x5904, 0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"}, 167 {0x590c, 0x5916, INTEL_MODEL_KBYM, "Kabylake ULT GT2"}, 168 {0x5904, 0x5921, INTEL_MODEL_KBYM, "Kabylake ULT GT2F"}, 169 {0x590c, 0x591c, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 170 {0x590c, 0x591e, INTEL_MODEL_KBY, "Kabylake ULX GT2"}, 171 {0x591f, 0x5912, INTEL_MODEL_KBY, "Kabylake DT GT2"}, 172 {0x5914, 0x5917, INTEL_MODEL_KBYM, "Kabylake Mobile GT2"}, 173 {0x5910, 0x591b, INTEL_MODEL_KBYM, "Kabylake Halo GT2"}, 174 {0x5918, 0x591d, INTEL_MODEL_KBY, "Kabylake WKS GT2"}, 175 {0x5904, 0x5926, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 176 {0x5904, 0x5927, INTEL_MODEL_KBY, "Kabylake ULT GT3"}, 177 178 {0x3e0f, 0x3e90, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 179 {0x3e0f, 0x3e93, INTEL_MODEL_CFL, "CoffeeLake GT1"}, 180 {0x3e1f, 0x3e91, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 181 {0x3ec2, 0x3e92, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 182 {0x3e18, 0x3e96, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 183 {0x3e30, 0x3e98, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 184 {0x3e31, 0x3e9a, INTEL_MODEL_CFL, "CoffeeLake GT2"}, 185 {0x3ec4, 0x3e9b, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 186 {0x3e10, 0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 187 {0x3ec4, 0x3eab, INTEL_MODEL_CFLM, "CoffeeLake Halo GT2"}, 188 {0x3ed0, 0x3ea5, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 189 {0x3ed0, 0x3ea6, INTEL_MODEL_CFL, "CoffeeLake GT3"}, 190 191 {0x9b64, 0x9ba4, INTEL_MODEL_CML, "CometLake GT1"}, 192 {0x9b73, 0x9ba8, INTEL_MODEL_CML, "CometLake GT1"}, 193 {0x9b71, 0x9b21, INTEL_MODEL_CMLM, "CometLake U GT1"}, 194 {0x9b71, 0x9baa, INTEL_MODEL_CMLM, "CometLake U GT1"}, 195 {0x9b54, 0x9bc4, INTEL_MODEL_CML, "CometLake GT2"}, 196 {0x9b43, 0x9bc5, INTEL_MODEL_CML, "CometLake GT2"}, 197 {0x9b53, 0x9bc5, INTEL_MODEL_CML, "CometLake GT2"}, 198 {0x9b33, 0x9bc6, INTEL_MODEL_CML, "CometLake GT2"}, 199 {0x9b53, 0x9bc8, INTEL_MODEL_CML, "CometLake GT2"}, 200 {0x9b63, 0x9bc8, INTEL_MODEL_CML, "CometLake GT2"}, 201 {0x9b53, 0x9be6, INTEL_MODEL_CML, "CometLake GT2"}, 202 {0x9b44, 0x9bf6, INTEL_MODEL_CML, "CometLake GT2"}, 203 {0x9b54, 0x9bf6, INTEL_MODEL_CML, "CometLake GT2"}, 204 {0x9b61, 0x9b41, INTEL_MODEL_CMLM, "CometLake U GT2"}, 205 {0x9b51, 0x9bca, INTEL_MODEL_CMLM, "CometLake U GT2"}, 206 {0x9b61, 0x9bca, INTEL_MODEL_CMLM, "CometLake U GT2"}, 207 {0x9b51, 0x9bcc, INTEL_MODEL_CMLM, "CometLake U GT2"}, 208 209 {0x4e22, 0x4e55, INTEL_MODEL_JSL, "JasperLake"}, 210 {0x4e24, 0x4e55, INTEL_MODEL_JSL, "JasperLake"}, 211 {0x4e12, 0x4e61, INTEL_MODEL_JSL, "JasperLake"}, 212 {0x4e26, 0x4e71, INTEL_MODEL_JSLM, "JasperLake"}, 213 {0x4e28, 0x4e71, INTEL_MODEL_JSLM, "JasperLake"}, 214 215 {0x9a14, 0x9a49, INTEL_MODEL_TGLM, "TigerLake-LP GT2"}, 216 }; 217 218 struct intel_info { 219 pci_info bridge; 220 pci_info display; 221 DeviceType* type; 222 223 uint32* gtt_base; 224 phys_addr_t gtt_physical_base; 225 area_id gtt_area; 226 size_t gtt_entries; 227 size_t gtt_stolen_entries; 228 229 vuint32* registers; 230 area_id registers_area; 231 232 addr_t aperture_base; 233 phys_addr_t aperture_physical_base; 234 area_id aperture_area; 235 size_t aperture_size; 236 size_t aperture_stolen_size; 237 238 phys_addr_t scratch_page; 239 area_id scratch_area; 240 }; 241 242 static intel_info sInfo; 243 static pci_module_info* sPCI; 244 245 246 static bool 247 has_display_device(pci_info &info, uint32 deviceID) 248 { 249 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK; 250 index++) { 251 if (info.vendor_id != VENDOR_ID_INTEL 252 || info.device_id != deviceID 253 || info.class_base != PCI_display) 254 continue; 255 256 return true; 257 } 258 259 return false; 260 } 261 262 263 static uint16 264 gtt_memory_config(intel_info &info) 265 { 266 uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; 267 if (info.type->Generation() >= 6) 268 controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; 269 270 return get_pci_config(info.bridge, controlRegister, 2); 271 } 272 273 274 static size_t 275 determine_gtt_stolen(intel_info &info) 276 { 277 uint16 memoryConfig = gtt_memory_config(info); 278 size_t memorySize = 1 << 20; // 1 MB 279 280 if (info.type->InGroup(INTEL_GROUP_83x)) { 281 // Older chips 282 switch (memoryConfig & STOLEN_MEMORY_MASK) { 283 case i830_LOCAL_MEMORY_ONLY: 284 // TODO: determine its size! 285 ERROR("getting local memory size not implemented.\n"); 286 break; 287 case i830_STOLEN_512K: 288 memorySize >>= 1; 289 break; 290 case i830_STOLEN_1M: 291 // default case 292 break; 293 case i830_STOLEN_8M: 294 memorySize *= 8; 295 break; 296 } 297 } else if (info.type->InGroup(INTEL_GROUP_SNB) 298 || info.type->InGroup(INTEL_GROUP_IVB) 299 || info.type->InGroup(INTEL_GROUP_HAS)) { 300 switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { 301 case SNB_STOLEN_MEMORY_32MB: 302 memorySize *= 32; 303 break; 304 case SNB_STOLEN_MEMORY_64MB: 305 memorySize *= 64; 306 break; 307 case SNB_STOLEN_MEMORY_96MB: 308 memorySize *= 96; 309 break; 310 case SNB_STOLEN_MEMORY_128MB: 311 memorySize *= 128; 312 break; 313 case SNB_STOLEN_MEMORY_160MB: 314 memorySize *= 160; 315 break; 316 case SNB_STOLEN_MEMORY_192MB: 317 memorySize *= 192; 318 break; 319 case SNB_STOLEN_MEMORY_224MB: 320 memorySize *= 224; 321 break; 322 case SNB_STOLEN_MEMORY_256MB: 323 memorySize *= 256; 324 break; 325 case SNB_STOLEN_MEMORY_288MB: 326 memorySize *= 288; 327 break; 328 case SNB_STOLEN_MEMORY_320MB: 329 memorySize *= 320; 330 break; 331 case SNB_STOLEN_MEMORY_352MB: 332 memorySize *= 352; 333 break; 334 case SNB_STOLEN_MEMORY_384MB: 335 memorySize *= 384; 336 break; 337 case SNB_STOLEN_MEMORY_416MB: 338 memorySize *= 416; 339 break; 340 case SNB_STOLEN_MEMORY_448MB: 341 memorySize *= 448; 342 break; 343 case SNB_STOLEN_MEMORY_480MB: 344 memorySize *= 480; 345 break; 346 case SNB_STOLEN_MEMORY_512MB: 347 memorySize *= 512; 348 break; 349 } 350 } else if (info.type->InGroup(INTEL_GROUP_BDW) 351 || info.type->InFamily(INTEL_FAMILY_LAKE)) { 352 switch (memoryConfig & BDW_STOLEN_MEMORY_MASK) { 353 case BDW_STOLEN_MEMORY_32MB: 354 memorySize *= 32; 355 break; 356 case BDW_STOLEN_MEMORY_64MB: 357 memorySize *= 64; 358 break; 359 case BDW_STOLEN_MEMORY_96MB: 360 memorySize *= 96; 361 break; 362 case BDW_STOLEN_MEMORY_128MB: 363 memorySize *= 128; 364 break; 365 case BDW_STOLEN_MEMORY_160MB: 366 memorySize *= 160; 367 break; 368 case BDW_STOLEN_MEMORY_192MB: 369 memorySize *= 192; 370 break; 371 case BDW_STOLEN_MEMORY_224MB: 372 memorySize *= 224; 373 break; 374 case BDW_STOLEN_MEMORY_256MB: 375 memorySize *= 256; 376 break; 377 case BDW_STOLEN_MEMORY_288MB: 378 memorySize *= 288; 379 break; 380 case BDW_STOLEN_MEMORY_320MB: 381 memorySize *= 320; 382 break; 383 case BDW_STOLEN_MEMORY_352MB: 384 memorySize *= 352; 385 break; 386 case BDW_STOLEN_MEMORY_384MB: 387 memorySize *= 384; 388 break; 389 case BDW_STOLEN_MEMORY_416MB: 390 memorySize *= 416; 391 break; 392 case BDW_STOLEN_MEMORY_448MB: 393 memorySize *= 448; 394 break; 395 case BDW_STOLEN_MEMORY_480MB: 396 memorySize *= 480; 397 break; 398 case BDW_STOLEN_MEMORY_512MB: 399 memorySize *= 512; 400 break; 401 case BDW_STOLEN_MEMORY_1024MB: 402 memorySize *= 1024; 403 break; 404 case BDW_STOLEN_MEMORY_1536MB: 405 memorySize *= 1536; 406 break; 407 } 408 if(info.type->InGroup(INTEL_GROUP_BDW)) { 409 if((memoryConfig & BDW_STOLEN_MEMORY_MASK) == BDW_STOLEN_MEMORY_2016MB) { 410 memorySize *= 2016; 411 } 412 } else if(info.type->InFamily(INTEL_FAMILY_LAKE)) { 413 switch(memoryConfig & BDW_STOLEN_MEMORY_MASK) { 414 case SKL_STOLEN_MEMORY_4MB: 415 memorySize *= 4; 416 break; 417 case SKL_STOLEN_MEMORY_8MB: 418 memorySize *= 8; 419 break; 420 case SKL_STOLEN_MEMORY_12MB: 421 memorySize *= 12; 422 break; 423 case SKL_STOLEN_MEMORY_16MB: 424 memorySize *= 16; 425 break; 426 case SKL_STOLEN_MEMORY_20MB: 427 memorySize *= 20; 428 break; 429 case SKL_STOLEN_MEMORY_24MB: 430 memorySize *= 24; 431 break; 432 case SKL_STOLEN_MEMORY_28MB: 433 memorySize *= 28; 434 break; 435 case SKL_STOLEN_MEMORY_32MB: 436 memorySize *= 32; 437 break; 438 case SKL_STOLEN_MEMORY_36MB: 439 memorySize *= 36; 440 break; 441 case SKL_STOLEN_MEMORY_40MB: 442 memorySize *= 40; 443 break; 444 case SKL_STOLEN_MEMORY_44MB: 445 memorySize *= 44; 446 break; 447 case SKL_STOLEN_MEMORY_48MB: 448 memorySize *= 48; 449 break; 450 case SKL_STOLEN_MEMORY_52MB: 451 memorySize *= 52; 452 break; 453 case SKL_STOLEN_MEMORY_56MB: 454 memorySize *= 56; 455 break; 456 case SKL_STOLEN_MEMORY_60MB: 457 memorySize *= 60; 458 break; 459 } 460 } 461 } else if (info.type->InGroup(INTEL_GROUP_85x) 462 || info.type->InFamily(INTEL_FAMILY_9xx) 463 || info.type->InGroup(INTEL_GROUP_ILK)) { 464 switch (memoryConfig & STOLEN_MEMORY_MASK) { 465 case i855_STOLEN_MEMORY_4M: 466 memorySize *= 4; 467 break; 468 case i855_STOLEN_MEMORY_8M: 469 memorySize *= 8; 470 break; 471 case i855_STOLEN_MEMORY_16M: 472 memorySize *= 16; 473 break; 474 case i855_STOLEN_MEMORY_32M: 475 memorySize *= 32; 476 break; 477 case i855_STOLEN_MEMORY_48M: 478 memorySize *= 48; 479 break; 480 case i855_STOLEN_MEMORY_64M: 481 memorySize *= 64; 482 break; 483 case i855_STOLEN_MEMORY_128M: 484 memorySize *= 128; 485 break; 486 case i855_STOLEN_MEMORY_256M: 487 memorySize *= 256; 488 break; 489 case G4X_STOLEN_MEMORY_96MB: 490 memorySize *= 96; 491 break; 492 case G4X_STOLEN_MEMORY_160MB: 493 memorySize *= 160; 494 break; 495 case G4X_STOLEN_MEMORY_224MB: 496 memorySize *= 224; 497 break; 498 case G4X_STOLEN_MEMORY_352MB: 499 memorySize *= 352; 500 break; 501 } 502 } else { 503 // TODO: error out! 504 memorySize = 4096; 505 } 506 return memorySize - 4096; 507 } 508 509 510 static size_t 511 determine_gtt_size(intel_info &info) 512 { 513 uint16 memoryConfig = gtt_memory_config(info); 514 size_t gttSize = 0; 515 516 if (info.type->IsModel(INTEL_MODEL_965)) { 517 switch (memoryConfig & i965_GTT_MASK) { 518 case i965_GTT_128K: 519 gttSize = 128 << 10; 520 break; 521 case i965_GTT_256K: 522 gttSize = 256 << 10; 523 break; 524 case i965_GTT_512K: 525 gttSize = 512 << 10; 526 break; 527 } 528 } else if (info.type->IsModel(INTEL_MODEL_G33) 529 || info.type->InGroup(INTEL_GROUP_PIN)) { 530 switch (memoryConfig & G33_GTT_MASK) { 531 case G33_GTT_1M: 532 gttSize = 1 << 20; 533 break; 534 case G33_GTT_2M: 535 gttSize = 2 << 20; 536 break; 537 } 538 } else if (info.type->InGroup(INTEL_GROUP_G4x) 539 || info.type->InGroup(INTEL_GROUP_ILK)) { 540 switch (memoryConfig & G4X_GTT_MASK) { 541 case G4X_GTT_NONE: 542 gttSize = 0; 543 break; 544 case G4X_GTT_1M_NO_IVT: 545 gttSize = 1 << 20; 546 break; 547 case G4X_GTT_2M_NO_IVT: 548 case G4X_GTT_2M_IVT: 549 gttSize = 2 << 20; 550 break; 551 case G4X_GTT_3M_IVT: 552 gttSize = 3 << 20; 553 break; 554 case G4X_GTT_4M_IVT: 555 gttSize = 4 << 20; 556 break; 557 } 558 } else if (info.type->InGroup(INTEL_GROUP_SNB) 559 || info.type->InGroup(INTEL_GROUP_IVB) 560 || info.type->InGroup(INTEL_GROUP_HAS)) { 561 switch (memoryConfig & SNB_GTT_SIZE_MASK) { 562 case SNB_GTT_SIZE_NONE: 563 gttSize = 0; 564 break; 565 case SNB_GTT_SIZE_1MB: 566 gttSize = 1 << 20; 567 break; 568 case SNB_GTT_SIZE_2MB: 569 gttSize = 2 << 20; 570 break; 571 } 572 } else if (info.type->InGroup(INTEL_GROUP_BDW) 573 || info.type->InFamily(INTEL_FAMILY_LAKE)) { 574 switch (memoryConfig & BDW_GTT_SIZE_MASK) { 575 case BDW_GTT_SIZE_NONE: 576 gttSize = 0; 577 break; 578 case BDW_GTT_SIZE_2MB: 579 gttSize = 2 << 20; 580 break; 581 case BDW_GTT_SIZE_4MB: 582 gttSize = 4 << 20; 583 break; 584 case BDW_GTT_SIZE_8MB: 585 gttSize = 8 << 20; 586 break; 587 } 588 } else { 589 // older models have the GTT as large as their frame buffer mapping 590 // TODO: check if the i9xx version works with the i8xx chips as well 591 size_t frameBufferSize = 0; 592 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 593 if (info.type->InGroup(INTEL_GROUP_83x) 594 && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) 595 frameBufferSize = 64 << 20; 596 else 597 frameBufferSize = 128 << 20; 598 } else if (info.type->Generation() >= 3) { 599 frameBufferSize = info.display.u.h0.base_register_sizes[2]; 600 } 601 602 TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); 603 gttSize = frameBufferSize / 1024; 604 } 605 return gttSize; 606 } 607 608 609 static void 610 set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) 611 { 612 if (info.type->Generation() >= 8) { 613 // CHV + BXT 614 physicalAddress |= (physicalAddress >> 28) & 0x07f0; 615 // TODO: cache control? 616 } else if (info.type->Generation() >= 6) { 617 // SandyBridge, IronLake, IvyBridge, Haswell 618 physicalAddress |= (physicalAddress >> 28) & 0x0ff0; 619 physicalAddress |= 0x02; // cache control, l3 cacheable 620 } else if (info.type->Generation() >= 4) { 621 // Intel 9xx minus 91x, 94x, G33 622 // possible high bits are stored in the lower end 623 physicalAddress |= (physicalAddress >> 28) & 0x00f0; 624 // TODO: cache control? 625 } 626 627 // TODO: this is not 64-bit safe! 628 write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), 629 (uint32)physicalAddress | GTT_ENTRY_VALID); 630 } 631 632 633 static void 634 intel_unmap(intel_info &info) 635 { 636 delete_area(info.registers_area); 637 delete_area(info.gtt_area); 638 delete_area(info.scratch_area); 639 delete_area(info.aperture_area); 640 info.aperture_size = 0; 641 } 642 643 644 static status_t 645 intel_map(intel_info &info) 646 { 647 int fbIndex = 0; 648 int mmioIndex = 1; 649 if (info.type->Generation() >= 3) { 650 // for some reason Intel saw the need to change the order of the 651 // mappings with the introduction of the i9xx family 652 mmioIndex = 0; 653 fbIndex = 2; 654 } 655 656 phys_addr_t addr = info.display.u.h0.base_registers[mmioIndex]; 657 uint64 barSize = info.display.u.h0.base_register_sizes[mmioIndex]; 658 if ((info.display.u.h0.base_register_flags[mmioIndex] & PCI_address_type) == PCI_address_type_64) { 659 addr |= (uint64)info.display.u.h0.base_registers[mmioIndex + 1] << 32; 660 barSize |= (uint64)info.display.u.h0.base_register_sizes[mmioIndex + 1] << 32; 661 } 662 663 AreaKeeper mmioMapper; 664 info.registers_area = mmioMapper.Map("intel GMCH mmio", addr, barSize, 665 B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); 666 667 if (mmioMapper.InitCheck() < B_OK) { 668 ERROR("could not map memory I/O!\n"); 669 return info.registers_area; 670 } 671 672 // make sure bus master, memory-mapped I/O, and frame buffer is enabled 673 set_pci_config(info.display, PCI_command, 2, 674 get_pci_config(info.display, PCI_command, 2) 675 | PCI_command_io | PCI_command_memory | PCI_command_master); 676 677 void* scratchAddress; 678 AreaKeeper scratchCreator; 679 info.scratch_area = scratchCreator.Create("intel GMCH scratch", 680 &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, 681 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 682 if (scratchCreator.InitCheck() < B_OK) { 683 ERROR("could not create scratch page!\n"); 684 return info.scratch_area; 685 } 686 687 physical_entry entry; 688 if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) 689 return B_ERROR; 690 691 // TODO: Review these 692 if (info.type->InFamily(INTEL_FAMILY_8xx)) { 693 info.gtt_physical_base = read32(info.registers 694 + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED; 695 if (info.gtt_physical_base == 0) { 696 // TODO: not sure how this is supposed to work under Linux/FreeBSD, 697 // but on my i865, this code is needed for Haiku. 698 ERROR("Use GTT address fallback.\n"); 699 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] 700 + i830_GTT_BASE; 701 } 702 } else if (info.type->InGroup(INTEL_GROUP_91x)) { 703 info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); 704 } else { 705 // 945+? 706 info.gtt_physical_base = addr + (2UL << 20); 707 } 708 709 size_t gttSize = determine_gtt_size(info); 710 size_t stolenSize = determine_gtt_stolen(info); 711 712 info.gtt_entries = gttSize / 4096; 713 info.gtt_stolen_entries = stolenSize / 4096; 714 715 TRACE("GTT base %" B_PRIxPHYSADDR ", size %lu, entries %lu, stolen %lu\n", 716 info.gtt_physical_base, gttSize, info.gtt_entries, stolenSize); 717 718 AreaKeeper gttMapper; 719 info.gtt_area = gttMapper.Map("intel GMCH gtt", 720 info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS, 721 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base); 722 if (gttMapper.InitCheck() < B_OK) { 723 ERROR("could not map GTT!\n"); 724 return info.gtt_area; 725 } 726 727 info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex]; 728 info.aperture_stolen_size = stolenSize; 729 if ((info.display.u.h0.base_register_flags[fbIndex] & PCI_address_type) == PCI_address_type_64) { 730 info.aperture_physical_base |= (uint64)info.display.u.h0.base_registers[fbIndex + 1] << 32; 731 if (info.aperture_size == 0) { 732 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex] 733 |= (uint64)info.display.u.h0.base_register_sizes[fbIndex + 1] << 32; 734 } 735 } else if (info.aperture_size == 0) 736 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; 737 738 ERROR("detected %ld MB of stolen memory, aperture size %ld MB, " 739 "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, 740 info.aperture_size >> 20, gttSize >> 10); 741 742 ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base); 743 ERROR("MMIO base = 0x%" B_PRIx32 "\n", 744 info.display.u.h0.base_registers[mmioIndex]); 745 ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base); 746 747 AreaKeeper apertureMapper; 748 info.aperture_area = apertureMapper.Map("intel graphics aperture", 749 info.aperture_physical_base, info.aperture_size, 750 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 751 B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base); 752 if (apertureMapper.InitCheck() < B_OK) { 753 // try again without write combining 754 ERROR("enabling write combined mode failed.\n"); 755 756 info.aperture_area = apertureMapper.Map("intel graphics aperture", 757 info.aperture_physical_base, info.aperture_size, 758 B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, 759 (void**)&info.aperture_base); 760 } 761 if (apertureMapper.InitCheck() < B_OK) { 762 ERROR("could not map graphics aperture!\n"); 763 return info.aperture_area; 764 } 765 766 info.scratch_page = entry.address; 767 768 gttMapper.Detach(); 769 mmioMapper.Detach(); 770 scratchCreator.Detach(); 771 apertureMapper.Detach(); 772 773 return B_OK; 774 } 775 776 777 // #pragma mark - module interface 778 779 780 status_t 781 intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size, 782 void** _aperture) 783 { 784 // TODO: we currently only support a single AGP bridge! 785 if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device 786 || function != sInfo.bridge.function) 787 && (bus != sInfo.display.bus || device != sInfo.display.device 788 || function != sInfo.display.function)) 789 return B_BAD_VALUE; 790 791 sInfo.aperture_size = size; 792 793 if (intel_map(sInfo) < B_OK) 794 return B_ERROR; 795 796 uint16 gmchControl = get_pci_config(sInfo.bridge, 797 INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED; 798 set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl); 799 800 write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL, 801 sInfo.gtt_physical_base | PAGE_TABLE_ENABLED); 802 read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL); 803 804 if (sInfo.scratch_page != 0) { 805 for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) { 806 set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page); 807 } 808 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 809 } 810 811 asm("wbinvd;"); 812 813 *_aperture = NULL; 814 return B_OK; 815 } 816 817 818 void 819 intel_delete_aperture(void* aperture) 820 { 821 intel_unmap(sInfo); 822 } 823 824 825 static status_t 826 intel_get_aperture_info(void* aperture, aperture_info* info) 827 { 828 if (info == NULL) 829 return B_BAD_VALUE; 830 831 info->base = sInfo.aperture_base; 832 info->physical_base = sInfo.aperture_physical_base; 833 info->size = sInfo.aperture_size; 834 info->reserved_size = sInfo.aperture_stolen_size; 835 836 return B_OK; 837 } 838 839 840 status_t 841 intel_set_aperture_size(void* aperture, size_t size) 842 { 843 return B_ERROR; 844 } 845 846 847 static status_t 848 intel_bind_page(void* aperture, uint32 offset, phys_addr_t physicalAddress) 849 { 850 //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress); 851 852 set_gtt_entry(sInfo, offset, physicalAddress); 853 return B_OK; 854 } 855 856 857 static status_t 858 intel_unbind_page(void* aperture, uint32 offset) 859 { 860 //TRACE("unbind_page(offset %lx)\n", offset); 861 862 if (sInfo.scratch_page != 0) 863 set_gtt_entry(sInfo, offset, sInfo.scratch_page); 864 865 return B_OK; 866 } 867 868 869 void 870 intel_flush_tlbs(void* aperture) 871 { 872 read32(sInfo.gtt_base + sInfo.gtt_entries - 1); 873 asm("wbinvd;"); 874 } 875 876 877 // #pragma mark - 878 879 880 static status_t 881 intel_init() 882 { 883 TRACE("bus manager init\n"); 884 885 if (get_module(B_PCI_MODULE_NAME, (module_info**)&sPCI) != B_OK) 886 return B_ERROR; 887 888 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK; 889 index++) { 890 if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL 891 || sInfo.bridge.class_base != PCI_bridge) 892 continue; 893 894 // check device 895 for (uint32 i = 0; i < sizeof(kSupportedDevices) 896 / sizeof(kSupportedDevices[0]); i++) { 897 if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) { 898 sInfo.type = new DeviceType(kSupportedDevices[i].type); 899 if (has_display_device(sInfo.display, 900 kSupportedDevices[i].display_id)) { 901 TRACE("found intel bridge\n"); 902 return B_OK; 903 } 904 } 905 } 906 } 907 908 return ENODEV; 909 } 910 911 912 static void 913 intel_uninit() 914 { 915 if (sInfo.type) 916 delete sInfo.type; 917 } 918 919 920 static int32 921 intel_std_ops(int32 op, ...) 922 { 923 switch (op) { 924 case B_MODULE_INIT: 925 return intel_init(); 926 case B_MODULE_UNINIT: 927 intel_uninit(); 928 return B_OK; 929 } 930 931 return B_BAD_VALUE; 932 } 933 934 935 static struct agp_gart_bus_module_info sIntelModuleInfo = { 936 { 937 "busses/agp_gart/intel/v0", 938 0, 939 intel_std_ops 940 }, 941 942 intel_create_aperture, 943 intel_delete_aperture, 944 945 intel_get_aperture_info, 946 intel_set_aperture_size, 947 intel_bind_page, 948 intel_unbind_page, 949 intel_flush_tlbs 950 }; 951 952 module_info* modules[] = { 953 (module_info*)&sIntelModuleInfo, 954 NULL 955 }; 956