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
has_display_device(pci_info & info,uint32 deviceID)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
gtt_memory_config(intel_info & info)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
determine_gtt_stolen(intel_info & info)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
determine_gtt_size(intel_info & info)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
set_gtt_entry(intel_info & info,uint32 offset,phys_addr_t physicalAddress)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
intel_unmap(intel_info & info)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
intel_map(intel_info & info)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
intel_create_aperture(uint8 bus,uint8 device,uint8 function,size_t size,void ** _aperture)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
intel_delete_aperture(void * aperture)842 intel_delete_aperture(void* aperture)
843 {
844 intel_unmap(sInfo);
845 }
846
847
848 static status_t
intel_get_aperture_info(void * aperture,aperture_info * info)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
intel_set_aperture_size(void * aperture,size_t size)864 intel_set_aperture_size(void* aperture, size_t size)
865 {
866 return B_ERROR;
867 }
868
869
870 static status_t
intel_bind_page(void * aperture,uint32 offset,phys_addr_t physicalAddress)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
intel_unbind_page(void * aperture,uint32 offset)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
intel_flush_tlbs(void * aperture)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
intel_init()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
intel_uninit()936 intel_uninit()
937 {
938 if (sInfo.type)
939 delete sInfo.type;
940 }
941
942
943 static int32
intel_std_ops(int32 op,...)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