btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / add-ons / kernel / busses / agp_gart / intel_gart.cpp
blob4e0557dd2ebbd6a0725242229837c2dd0b8f38cb
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.
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
15 #include <AreaKeeper.h>
16 #include <intel_extreme.h>
18 #include <stdlib.h>
20 #include <AGP.h>
21 #include <KernelExport.h>
22 #include <PCI.h>
24 #include <new>
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)
35 #ifndef __HAIKU__
36 # define B_KERNEL_READ_AREA 0
37 # define B_KERNEL_WRITE_AREA 0
38 #endif
40 /* read and write to PCI config space */
41 #define get_pci_config(info, offset, size) \
42 (sPCI->read_pci_config((info).bus, (info).device, (info).function, \
43 (offset), (size)))
44 #define set_pci_config(info, offset, size, value) \
45 (sPCI->write_pci_config((info).bus, (info).device, (info).function, \
46 (offset), (size), (value)))
47 #define write32(address, data) \
48 (*((volatile uint32*)(address)) = (data))
49 #define read32(address) \
50 (*((volatile uint32*)(address)))
53 // PCI "Host bridge" is most cases :-)
54 const struct supported_device {
55 uint32 bridge_id;
56 uint32 display_id;
57 int32 type;
58 const char *name;
59 } kSupportedDevices[] = {
60 {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"},
61 {0x2560, 0x2562, INTEL_GROUP_83x, "i845G"},
62 {0x3580, 0x3582, INTEL_GROUP_85x, "i855G"},
63 {0x358c, 0x358e, INTEL_GROUP_85x, "i855G"},
64 {0x2570, 0x2572, INTEL_GROUP_85x, "i865G"},
66 // {0x2792, INTEL_GROUP_91x, "i910"},
67 // {0x258a, INTEL_GROUP_91x, "i915"},
68 {0x2580, 0x2582, INTEL_MODEL_915, "i915G"},
69 {0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"},
70 {0x2770, 0x2772, INTEL_MODEL_945, "i945G"},
71 {0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"},
72 {0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"},
74 {0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"},
75 {0x2980, 0x2982, INTEL_MODEL_965, "G35"},
76 {0x2990, 0x2992, INTEL_MODEL_965, "i965Q"},
77 {0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"},
78 {0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"},
79 {0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"},
81 {0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"},
82 {0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"},
83 {0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"},
85 {0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"},
86 {0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"},
87 {0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"},
88 {0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"},
89 {0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"},
90 {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"},
91 {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"},
93 {0xa000, 0xa001, INTEL_MODEL_PINE, "Atom D4xx"},
94 {0xa000, 0xa002, INTEL_MODEL_PINE, "Atom D5xx"},
95 {0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom N4xx"},
96 {0xa010, 0xa012, INTEL_MODEL_PINEM, "Atom N5xx"},
98 {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"},
99 {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
100 {0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
101 {0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"},
103 {0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"},
104 {0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"},
105 {0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"},
106 {0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"},
107 {0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"},
108 {0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"},
109 {0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"},
111 {0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"},
112 {0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"},
113 {0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"},
114 {0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"},
115 {0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"},
116 {0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"},
118 {0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"},
119 {0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"},
120 {0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"},
121 {0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"},
123 // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31
124 {0x0f00, 0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"},
125 {0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"},
126 {0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"},
127 {0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"},
128 {0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"},
129 {0x0f00, 0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"},
131 {0x1604, 0x1616, INTEL_MODEL_BDWM, "HD Graphics 5500 (Broadwell GT2)"},
133 // XXX: 0x1904 only confirmed on 0x1916
134 {0x1904, 0x1902, INTEL_MODEL_SKY, "Skylake GT1"},
135 {0x1904, 0x1906, INTEL_MODEL_SKYM, "Skylake GT1"},
136 {0x1904, 0x190a, INTEL_MODEL_SKYS, "Skylake GT1"},
137 {0x1904, 0x190b, INTEL_MODEL_SKY, "Skylake GT1"},
138 {0x1904, 0x190e, INTEL_MODEL_SKYM, "Skylake GT1"},
139 {0x1904, 0x1912, INTEL_MODEL_SKY, "Skylake GT2"},
140 {0x1904, 0x1916, INTEL_MODEL_SKYM, "Skylake GT2"},
141 {0x1904, 0x191a, INTEL_MODEL_SKYS, "Skylake GT2"},
142 {0x1904, 0x191b, INTEL_MODEL_SKY, "Skylake GT2"},
143 {0x1904, 0x191d, INTEL_MODEL_SKY, "Skylake GT2"},
144 {0x1904, 0x191e, INTEL_MODEL_SKYM, "Skylake GT2"},
145 {0x1904, 0x1921, INTEL_MODEL_SKYM, "Skylake GT2F"},
146 {0x1904, 0x1926, INTEL_MODEL_SKYM, "Skylake GT3"},
147 {0x1904, 0x192a, INTEL_MODEL_SKYS, "Skylake GT3"},
148 {0x1904, 0x192b, INTEL_MODEL_SKY, "Skylake GT3"},
151 struct intel_info {
152 pci_info bridge;
153 pci_info display;
154 DeviceType* type;
156 uint32* gtt_base;
157 phys_addr_t gtt_physical_base;
158 area_id gtt_area;
159 size_t gtt_entries;
160 size_t gtt_stolen_entries;
162 vuint32* registers;
163 area_id registers_area;
165 addr_t aperture_base;
166 phys_addr_t aperture_physical_base;
167 area_id aperture_area;
168 size_t aperture_size;
169 size_t aperture_stolen_size;
171 phys_addr_t scratch_page;
172 area_id scratch_area;
175 static intel_info sInfo;
176 static pci_module_info* sPCI;
179 static bool
180 has_display_device(pci_info &info, uint32 deviceID)
182 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK;
183 index++) {
184 if (info.vendor_id != VENDOR_ID_INTEL
185 || info.device_id != deviceID
186 || info.class_base != PCI_display)
187 continue;
189 return true;
192 return false;
196 static uint16
197 gtt_memory_config(intel_info &info)
199 uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL;
200 if (info.type->InGroup(INTEL_GROUP_SNB))
201 controlRegister = SNB_GRAPHICS_MEMORY_CONTROL;
203 return get_pci_config(info.bridge, controlRegister, 2);
207 static size_t
208 determine_gtt_stolen(intel_info &info)
210 uint16 memoryConfig = gtt_memory_config(info);
211 size_t memorySize = 1 << 20; // 1 MB
213 if (info.type->InGroup(INTEL_GROUP_83x)) {
214 // Older chips
215 switch (memoryConfig & STOLEN_MEMORY_MASK) {
216 case i830_LOCAL_MEMORY_ONLY:
217 // TODO: determine its size!
218 ERROR("getting local memory size not implemented.\n");
219 break;
220 case i830_STOLEN_512K:
221 memorySize >>= 1;
222 break;
223 case i830_STOLEN_1M:
224 // default case
225 break;
226 case i830_STOLEN_8M:
227 memorySize *= 8;
228 break;
230 } else if (info.type->InGroup(INTEL_GROUP_SNB)) {
231 switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) {
232 case SNB_STOLEN_MEMORY_32MB:
233 memorySize *= 32;
234 break;
235 case SNB_STOLEN_MEMORY_64MB:
236 memorySize *= 64;
237 break;
238 case SNB_STOLEN_MEMORY_96MB:
239 memorySize *= 96;
240 break;
241 case SNB_STOLEN_MEMORY_128MB:
242 memorySize *= 128;
243 break;
244 case SNB_STOLEN_MEMORY_160MB:
245 memorySize *= 160;
246 break;
247 case SNB_STOLEN_MEMORY_192MB:
248 memorySize *= 192;
249 break;
250 case SNB_STOLEN_MEMORY_224MB:
251 memorySize *= 224;
252 break;
253 case SNB_STOLEN_MEMORY_256MB:
254 memorySize *= 256;
255 break;
256 case SNB_STOLEN_MEMORY_288MB:
257 memorySize *= 288;
258 break;
259 case SNB_STOLEN_MEMORY_320MB:
260 memorySize *= 320;
261 break;
262 case SNB_STOLEN_MEMORY_352MB:
263 memorySize *= 352;
264 break;
265 case SNB_STOLEN_MEMORY_384MB:
266 memorySize *= 384;
267 break;
268 case SNB_STOLEN_MEMORY_416MB:
269 memorySize *= 416;
270 break;
271 case SNB_STOLEN_MEMORY_448MB:
272 memorySize *= 448;
273 break;
274 case SNB_STOLEN_MEMORY_480MB:
275 memorySize *= 480;
276 break;
277 case SNB_STOLEN_MEMORY_512MB:
278 memorySize *= 512;
279 break;
281 } else if (info.type->InGroup(INTEL_GROUP_85x)
282 || info.type->InFamily(INTEL_FAMILY_9xx)
283 || info.type->InFamily(INTEL_FAMILY_SER5)
284 || info.type->InFamily(INTEL_FAMILY_SOC0)
285 || info.type->InFamily(INTEL_FAMILY_POVR)) {
286 switch (memoryConfig & STOLEN_MEMORY_MASK) {
287 case i855_STOLEN_MEMORY_4M:
288 memorySize *= 4;
289 break;
290 case i855_STOLEN_MEMORY_8M:
291 memorySize *= 8;
292 break;
293 case i855_STOLEN_MEMORY_16M:
294 memorySize *= 16;
295 break;
296 case i855_STOLEN_MEMORY_32M:
297 memorySize *= 32;
298 break;
299 case i855_STOLEN_MEMORY_48M:
300 memorySize *= 48;
301 break;
302 case i855_STOLEN_MEMORY_64M:
303 memorySize *= 64;
304 break;
305 case i855_STOLEN_MEMORY_128M:
306 memorySize *= 128;
307 break;
308 case i855_STOLEN_MEMORY_256M:
309 memorySize *= 256;
310 break;
311 case G4X_STOLEN_MEMORY_96MB:
312 memorySize *= 96;
313 break;
314 case G4X_STOLEN_MEMORY_160MB:
315 memorySize *= 160;
316 break;
317 case G4X_STOLEN_MEMORY_224MB:
318 memorySize *= 224;
319 break;
320 case G4X_STOLEN_MEMORY_352MB:
321 memorySize *= 352;
322 break;
324 } else {
325 // TODO: error out!
326 memorySize = 4096;
328 return memorySize - 4096;
332 static size_t
333 determine_gtt_size(intel_info &info)
335 uint16 memoryConfig = gtt_memory_config(info);
336 size_t gttSize = 0;
338 if (info.type->IsModel(INTEL_MODEL_965)) {
339 switch (memoryConfig & i965_GTT_MASK) {
340 case i965_GTT_128K:
341 gttSize = 128 << 10;
342 break;
343 case i965_GTT_256K:
344 gttSize = 256 << 10;
345 break;
346 case i965_GTT_512K:
347 gttSize = 512 << 10;
348 break;
350 } else if (info.type->IsModel(INTEL_MODEL_G33)
351 || info.type->InGroup(INTEL_GROUP_PIN)) {
352 switch (memoryConfig & G33_GTT_MASK) {
353 case G33_GTT_1M:
354 gttSize = 1 << 20;
355 break;
356 case G33_GTT_2M:
357 gttSize = 2 << 20;
358 break;
360 } else if (info.type->InGroup(INTEL_GROUP_G4x)
361 || info.type->InGroup(INTEL_GROUP_ILK)) {
362 switch (memoryConfig & G4X_GTT_MASK) {
363 case G4X_GTT_NONE:
364 gttSize = 0;
365 break;
366 case G4X_GTT_1M_NO_IVT:
367 gttSize = 1 << 20;
368 break;
369 case G4X_GTT_2M_NO_IVT:
370 case G4X_GTT_2M_IVT:
371 gttSize = 2 << 20;
372 break;
373 case G4X_GTT_3M_IVT:
374 gttSize = 3 << 20;
375 break;
376 case G4X_GTT_4M_IVT:
377 gttSize = 4 << 20;
378 break;
380 } else if (info.type->InGroup(INTEL_GROUP_SNB)) {
381 switch (memoryConfig & SNB_GTT_SIZE_MASK) {
382 case SNB_GTT_SIZE_NONE:
383 gttSize = 0;
384 break;
385 case SNB_GTT_SIZE_1MB:
386 gttSize = 1 << 20;
387 break;
388 case SNB_GTT_SIZE_2MB:
389 gttSize = 2 << 20;
390 break;
392 } else {
393 // older models have the GTT as large as their frame buffer mapping
394 // TODO: check if the i9xx version works with the i8xx chips as well
395 size_t frameBufferSize = 0;
396 if (info.type->InFamily(INTEL_FAMILY_8xx)) {
397 if (info.type->InGroup(INTEL_GROUP_83x)
398 && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M)
399 frameBufferSize = 64 << 20;
400 else
401 frameBufferSize = 128 << 20;
402 } else if (info.type->Generation() >= 3) {
403 frameBufferSize = info.display.u.h0.base_register_sizes[2];
406 TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20);
407 gttSize = frameBufferSize / 1024;
409 return gttSize;
413 static void
414 set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress)
416 if (info.type->Generation() >= 8) {
417 // CHV + BXT
418 physicalAddress |= (physicalAddress >> 28) & 0x07f0;
419 // TODO: cache control?
420 } else if (info.type->Generation() >= 6) {
421 // SandyBridge, IronLake, IvyBridge, Haswell
422 physicalAddress |= (physicalAddress >> 28) & 0x0ff0;
423 physicalAddress |= 0x02; // cache control, l3 cacheable
424 } else if (info.type->Generation() >= 4) {
425 // Intel 9xx minus 91x, 94x, G33
426 // possible high bits are stored in the lower end
427 physicalAddress |= (physicalAddress >> 28) & 0x00f0;
428 // TODO: cache control?
431 // TODO: this is not 64-bit safe!
432 write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT),
433 (uint32)physicalAddress | GTT_ENTRY_VALID);
437 static void
438 intel_unmap(intel_info &info)
440 delete_area(info.registers_area);
441 delete_area(info.gtt_area);
442 delete_area(info.scratch_area);
443 delete_area(info.aperture_area);
444 info.aperture_size = 0;
448 static status_t
449 intel_map(intel_info &info)
451 int fbIndex = 0;
452 int mmioIndex = 1;
453 if (info.type->Generation() >= 3) {
454 // for some reason Intel saw the need to change the order of the
455 // mappings with the introduction of the i9xx family
456 mmioIndex = 0;
457 fbIndex = 2;
460 AreaKeeper mmioMapper;
461 info.registers_area = mmioMapper.Map("intel GMCH mmio",
462 info.display.u.h0.base_registers[mmioIndex],
463 info.display.u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS,
464 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers);
466 if (mmioMapper.InitCheck() < B_OK) {
467 ERROR("could not map memory I/O!\n");
468 return info.registers_area;
471 // make sure bus master, memory-mapped I/O, and frame buffer is enabled
472 set_pci_config(info.display, PCI_command, 2,
473 get_pci_config(info.display, PCI_command, 2)
474 | PCI_command_io | PCI_command_memory | PCI_command_master);
476 void* scratchAddress;
477 AreaKeeper scratchCreator;
478 info.scratch_area = scratchCreator.Create("intel GMCH scratch",
479 &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK,
480 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
481 if (scratchCreator.InitCheck() < B_OK) {
482 ERROR("could not create scratch page!\n");
483 return info.scratch_area;
486 physical_entry entry;
487 if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK)
488 return B_ERROR;
490 // TODO: Review these
491 if (info.type->InFamily(INTEL_FAMILY_8xx)) {
492 info.gtt_physical_base = read32(info.registers
493 + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED;
494 if (info.gtt_physical_base == 0) {
495 // TODO: not sure how this is supposed to work under Linux/FreeBSD,
496 // but on my i865, this code is needed for Haiku.
497 ERROR("Use GTT address fallback.\n");
498 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
499 + i830_GTT_BASE;
501 } else if (info.type->InGroup(INTEL_GROUP_91x)) {
502 info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4);
503 } else {
504 // 945+?
505 info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
506 + (2UL << 20);
509 size_t gttSize = determine_gtt_size(info);
510 size_t stolenSize = determine_gtt_stolen(info);
512 info.gtt_entries = gttSize / 4096;
513 info.gtt_stolen_entries = stolenSize / 4096;
515 TRACE("GTT base %" B_PRIxPHYSADDR ", size %lu, entries %lu, stolen %lu\n",
516 info.gtt_physical_base, gttSize, info.gtt_entries, stolenSize);
518 AreaKeeper gttMapper;
519 info.gtt_area = gttMapper.Map("intel GMCH gtt",
520 info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS,
521 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base);
522 if (gttMapper.InitCheck() < B_OK) {
523 ERROR("could not map GTT!\n");
524 return info.gtt_area;
527 info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex];
528 info.aperture_stolen_size = stolenSize;
529 if (info.aperture_size == 0)
530 info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex];
532 ERROR("detected %ld MB of stolen memory, aperture size %ld MB, "
533 "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20,
534 info.aperture_size >> 20, gttSize >> 10);
536 ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base);
537 ERROR("MMIO base = 0x%" B_PRIx32 "\n",
538 info.display.u.h0.base_registers[mmioIndex]);
539 ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base);
541 AreaKeeper apertureMapper;
542 info.aperture_area = apertureMapper.Map("intel graphics aperture",
543 info.aperture_physical_base, info.aperture_size,
544 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
545 B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base);
546 if (apertureMapper.InitCheck() < B_OK) {
547 // try again without write combining
548 ERROR("enabling write combined mode failed.\n");
550 info.aperture_area = apertureMapper.Map("intel graphics aperture",
551 info.aperture_physical_base, info.aperture_size,
552 B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA,
553 (void**)&info.aperture_base);
555 if (apertureMapper.InitCheck() < B_OK) {
556 ERROR("could not map graphics aperture!\n");
557 return info.aperture_area;
560 info.scratch_page = entry.address;
562 gttMapper.Detach();
563 mmioMapper.Detach();
564 scratchCreator.Detach();
565 apertureMapper.Detach();
567 return B_OK;
571 // #pragma mark - module interface
574 status_t
575 intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size,
576 void** _aperture)
578 // TODO: we currently only support a single AGP bridge!
579 if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device
580 || function != sInfo.bridge.function)
581 && (bus != sInfo.display.bus || device != sInfo.display.device
582 || function != sInfo.display.function))
583 return B_BAD_VALUE;
585 sInfo.aperture_size = size;
587 if (intel_map(sInfo) < B_OK)
588 return B_ERROR;
590 uint16 gmchControl = get_pci_config(sInfo.bridge,
591 INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED;
592 set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl);
594 write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL,
595 sInfo.gtt_physical_base | PAGE_TABLE_ENABLED);
596 read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL);
598 if (sInfo.scratch_page != 0) {
599 for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) {
600 set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page);
602 read32(sInfo.gtt_base + sInfo.gtt_entries - 1);
605 asm("wbinvd;");
607 *_aperture = NULL;
608 return B_OK;
612 void
613 intel_delete_aperture(void* aperture)
615 intel_unmap(sInfo);
619 static status_t
620 intel_get_aperture_info(void* aperture, aperture_info* info)
622 if (info == NULL)
623 return B_BAD_VALUE;
625 info->base = sInfo.aperture_base;
626 info->physical_base = sInfo.aperture_physical_base;
627 info->size = sInfo.aperture_size;
628 info->reserved_size = sInfo.aperture_stolen_size;
630 return B_OK;
634 status_t
635 intel_set_aperture_size(void* aperture, size_t size)
637 return B_ERROR;
641 static status_t
642 intel_bind_page(void* aperture, uint32 offset, phys_addr_t physicalAddress)
644 //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress);
646 set_gtt_entry(sInfo, offset, physicalAddress);
647 return B_OK;
651 static status_t
652 intel_unbind_page(void* aperture, uint32 offset)
654 //TRACE("unbind_page(offset %lx)\n", offset);
656 if (sInfo.scratch_page != 0)
657 set_gtt_entry(sInfo, offset, sInfo.scratch_page);
659 return B_OK;
663 void
664 intel_flush_tlbs(void* aperture)
666 read32(sInfo.gtt_base + sInfo.gtt_entries - 1);
667 asm("wbinvd;");
671 // #pragma mark -
674 static status_t
675 intel_init()
677 TRACE("bus manager init\n");
679 if (get_module(B_PCI_MODULE_NAME, (module_info**)&sPCI) != B_OK)
680 return B_ERROR;
682 for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK;
683 index++) {
684 if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL
685 || sInfo.bridge.class_base != PCI_bridge)
686 continue;
688 // check device
689 for (uint32 i = 0; i < sizeof(kSupportedDevices)
690 / sizeof(kSupportedDevices[0]); i++) {
691 if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) {
692 sInfo.type = new DeviceType(kSupportedDevices[i].type);
693 if (has_display_device(sInfo.display,
694 kSupportedDevices[i].display_id)) {
695 TRACE("found intel bridge\n");
696 return B_OK;
702 return ENODEV;
706 static void
707 intel_uninit()
709 if (sInfo.type)
710 delete sInfo.type;
714 static int32
715 intel_std_ops(int32 op, ...)
717 switch (op) {
718 case B_MODULE_INIT:
719 return intel_init();
720 case B_MODULE_UNINIT:
721 intel_uninit();
722 return B_OK;
725 return B_BAD_VALUE;
729 static struct agp_gart_bus_module_info sIntelModuleInfo = {
731 "busses/agp_gart/intel/v0",
733 intel_std_ops
736 intel_create_aperture,
737 intel_delete_aperture,
739 intel_get_aperture_info,
740 intel_set_aperture_size,
741 intel_bind_page,
742 intel_unbind_page,
743 intel_flush_tlbs
746 module_info* modules[] = {
747 (module_info*)&sIntelModuleInfo,
748 NULL