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