1 | /*
|
---|
2 | * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
|
---|
3 | * Distributed under the terms of the MIT License.
|
---|
4 | */
|
---|
5 |
|
---|
6 |
|
---|
7 | #include <AreaKeeper.h>
|
---|
8 | #include <intel_extreme.h>
|
---|
9 |
|
---|
10 | #include <stdlib.h>
|
---|
11 |
|
---|
12 | #include <AGP.h>
|
---|
13 | #include <KernelExport.h>
|
---|
14 | #include <PCI.h>
|
---|
15 |
|
---|
16 |
|
---|
17 | //#define TRACE_INTEL
|
---|
18 | #ifdef TRACE_INTEL
|
---|
19 | # define TRACE(x...) dprintf("\33[33magp-intel:\33[0m " x)
|
---|
20 | #else
|
---|
21 | # define TRACE(x...) ;
|
---|
22 | #endif
|
---|
23 |
|
---|
24 | #ifndef __HAIKU__
|
---|
25 | # define B_KERNEL_READ_AREA 0
|
---|
26 | # define B_KERNEL_WRITE_AREA 0
|
---|
27 | #endif
|
---|
28 |
|
---|
29 | /* read and write to PCI config space */
|
---|
30 | #define get_pci_config(info, offset, size) \
|
---|
31 | (sPCI->read_pci_config((info).bus, (info).device, (info).function, \
|
---|
32 | (offset), (size)))
|
---|
33 | #define set_pci_config(info, offset, size, value) \
|
---|
34 | (sPCI->write_pci_config((info).bus, (info).device, (info).function, \
|
---|
35 | (offset), (size), (value)))
|
---|
36 | #define write32(address, data) \
|
---|
37 | (*((volatile uint32 *)(address)) = (data))
|
---|
38 | #define read32(address) \
|
---|
39 | (*((volatile uint32 *)(address)))
|
---|
40 |
|
---|
41 |
|
---|
42 | const struct supported_device {
|
---|
43 | uint32 bridge_id;
|
---|
44 | uint32 display_id;
|
---|
45 | uint32 type;
|
---|
46 | const char *name;
|
---|
47 | } kSupportedDevices[] = {
|
---|
48 | {0x3575, 0x3577, INTEL_TYPE_83x, "i830GM"},
|
---|
49 | {0x2560, 0x2562, INTEL_TYPE_83x, "i845G"},
|
---|
50 | {0x3580, 0x3582, INTEL_TYPE_85x, "i855G"},
|
---|
51 | {0x2570, 0x2572, INTEL_TYPE_85x, "i865G"},
|
---|
52 |
|
---|
53 | // {0x2792, INTEL_TYPE_91x, "i910"},
|
---|
54 | // {0x258a, INTEL_TYPE_91x, "i915"},
|
---|
55 | {0x2580, 0x2582, INTEL_TYPE_91x, "i915G"},
|
---|
56 | {0x2590, 0x2592, INTEL_TYPE_91x, "i915GM"},
|
---|
57 | {0x2770, 0x2772, INTEL_TYPE_945, "i945G"},
|
---|
58 | {0x27a0, 0x27a2, INTEL_TYPE_945, "i945GM"},
|
---|
59 | {0x27ac, 0x27ae, INTEL_TYPE_945, "i945GME"},
|
---|
60 |
|
---|
61 | {0x2970, 0x2972, INTEL_TYPE_965, "i946GZ"},
|
---|
62 | {0x2980, 0x2982, INTEL_TYPE_965, "i965G"},
|
---|
63 | {0x2990, 0x2992, INTEL_TYPE_965, "i965Q"},
|
---|
64 | {0x29a0, 0x29a2, INTEL_TYPE_965, "i965G"},
|
---|
65 | {0x2a00, 0x2a02, INTEL_TYPE_965, "i965GM"},
|
---|
66 | {0x2a10, 0x2a12, INTEL_TYPE_965, "i965GME"},
|
---|
67 |
|
---|
68 | {0x29b0, 0x29b2, INTEL_TYPE_G33, "G33"},
|
---|
69 | {0x29c0, 0x29c2, INTEL_TYPE_G33, "Q35"},
|
---|
70 | {0x29d0, 0x29d2, INTEL_TYPE_G33, "Q33"},
|
---|
71 |
|
---|
72 | {0x2e30, 0x2e32, INTEL_TYPE_GM45, "GMA_X4500_VGA"}, // Intel Mystic Lake (dg41mj)
|
---|
73 | {0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"},
|
---|
74 | };
|
---|
75 |
|
---|
76 | struct intel_info {
|
---|
77 | pci_info bridge;
|
---|
78 | pci_info display;
|
---|
79 | uint32 type;
|
---|
80 |
|
---|
81 | uint32 *gtt_base;
|
---|
82 | addr_t gtt_physical_base;
|
---|
83 | area_id gtt_area;
|
---|
84 | size_t gtt_entries;
|
---|
85 | size_t gtt_stolen_entries;
|
---|
86 |
|
---|
87 | vuint32 *registers;
|
---|
88 | area_id registers_area;
|
---|
89 |
|
---|
90 | addr_t aperture_base;
|
---|
91 | addr_t aperture_physical_base;
|
---|
92 | area_id aperture_area;
|
---|
93 | size_t aperture_size;
|
---|
94 | size_t aperture_stolen_size;
|
---|
95 |
|
---|
96 | phys_addr_t scratch_page;
|
---|
97 | area_id scratch_area;
|
---|
98 | };
|
---|
99 |
|
---|
100 | static intel_info sInfo;
|
---|
101 | static pci_module_info *sPCI;
|
---|
102 |
|
---|
103 |
|
---|
104 | static bool
|
---|
105 | has_display_device(pci_info &info, uint32 deviceID)
|
---|
106 | {
|
---|
107 | for (uint32 index = 0; sPCI->get_nth_pci_info(index, &info) == B_OK;
|
---|
108 | index++) {
|
---|
109 | if (info.vendor_id != VENDOR_ID_INTEL
|
---|
110 | || info.device_id != deviceID
|
---|
111 | || info.class_base != PCI_display)
|
---|
112 | continue;
|
---|
113 |
|
---|
114 | return true;
|
---|
115 | }
|
---|
116 |
|
---|
117 | return false;
|
---|
118 | }
|
---|
119 |
|
---|
120 |
|
---|
121 | static void
|
---|
122 | determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
---|
123 | {
|
---|
124 | // read stolen memory from the PCI configuration of the PCI bridge
|
---|
125 | uint16 memoryConfig = get_pci_config(info.bridge,
|
---|
126 | INTEL_GRAPHICS_MEMORY_CONTROL, 2);
|
---|
127 | size_t memorySize = 1 << 20; // 1 MB
|
---|
128 | gttSize = 0;
|
---|
129 | stolenSize = 0;
|
---|
130 |
|
---|
131 | if (info.type == INTEL_TYPE_965) {
|
---|
132 | switch (memoryConfig & i965_GTT_MASK) {
|
---|
133 | case i965_GTT_128K:
|
---|
134 | gttSize = 128 << 10;
|
---|
135 | break;
|
---|
136 | case i965_GTT_256K:
|
---|
137 | gttSize = 256 << 10;
|
---|
138 | break;
|
---|
139 | case i965_GTT_512K:
|
---|
140 | gttSize = 512 << 10;
|
---|
141 | break;
|
---|
142 | }
|
---|
143 | } else if (info.type == INTEL_TYPE_G33) {
|
---|
144 | switch (memoryConfig & G33_GTT_MASK) {
|
---|
145 | case G33_GTT_1M:
|
---|
146 | gttSize = 1 << 20;
|
---|
147 | break;
|
---|
148 | case G33_GTT_2M:
|
---|
149 | gttSize = 2 << 20;
|
---|
150 | break;
|
---|
151 | }
|
---|
152 | } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x) {
|
---|
153 | switch (memoryConfig & G4X_GTT_MASK) {
|
---|
154 | case G4X_GTT_NONE:
|
---|
155 | gttSize = 0;
|
---|
156 | break;
|
---|
157 | case G4X_GTT_1M_NO_IVT:
|
---|
158 | gttSize = 1 << 20;
|
---|
159 | break;
|
---|
160 | case G4X_GTT_2M_NO_IVT:
|
---|
161 | case G4X_GTT_2M_IVT:
|
---|
162 | gttSize = 2 << 20;
|
---|
163 | break;
|
---|
164 | case G4X_GTT_3M_IVT:
|
---|
165 | gttSize = 3 << 20;
|
---|
166 | break;
|
---|
167 | case G4X_GTT_4M_IVT:
|
---|
168 | gttSize = 4 << 20;
|
---|
169 | break;
|
---|
170 | }
|
---|
171 | } else {
|
---|
172 | // older models have the GTT as large as their frame buffer mapping
|
---|
173 | // TODO: check if the i9xx version works with the i8xx chips as well
|
---|
174 | size_t frameBufferSize = 0;
|
---|
175 | if ((info.type & INTEL_TYPE_8xx) != 0) {
|
---|
176 | if (info.type == INTEL_TYPE_83x
|
---|
177 | && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M)
|
---|
178 | frameBufferSize = 64 << 20;
|
---|
179 | else
|
---|
180 | frameBufferSize = 128 << 20;
|
---|
181 | } else if ((info.type & INTEL_TYPE_9xx) != 0)
|
---|
182 | frameBufferSize = info.display.u.h0.base_register_sizes[2];
|
---|
183 |
|
---|
184 | TRACE(("frame buffer size %lu MB\n", frameBufferSize >> 20));
|
---|
185 | gttSize = frameBufferSize / 1024;
|
---|
186 | }
|
---|
187 |
|
---|
188 | // TODO: test with different models!
|
---|
189 |
|
---|
190 | if (info.type == INTEL_TYPE_83x) {
|
---|
191 | // Older chips
|
---|
192 | switch (memoryConfig & STOLEN_MEMORY_MASK) {
|
---|
193 | case i830_LOCAL_MEMORY_ONLY:
|
---|
194 | // TODO: determine its size!
|
---|
195 | dprintf("intel_gart: getting local memory size not implemented.\n");
|
---|
196 | break;
|
---|
197 | case i830_STOLEN_512K:
|
---|
198 | memorySize >>= 1;
|
---|
199 | break;
|
---|
200 | case i830_STOLEN_1M:
|
---|
201 | // default case
|
---|
202 | break;
|
---|
203 | case i830_STOLEN_8M:
|
---|
204 | memorySize *= 8;
|
---|
205 | break;
|
---|
206 | }
|
---|
207 | } else if (info.type == INTEL_TYPE_85x
|
---|
208 | || (info.type & INTEL_TYPE_9xx) == INTEL_TYPE_9xx) {
|
---|
209 | switch (memoryConfig & STOLEN_MEMORY_MASK) {
|
---|
210 | case i855_STOLEN_MEMORY_4M:
|
---|
211 | memorySize *= 4;
|
---|
212 | break;
|
---|
213 | case i855_STOLEN_MEMORY_8M:
|
---|
214 | memorySize *= 8;
|
---|
215 | break;
|
---|
216 | case i855_STOLEN_MEMORY_16M:
|
---|
217 | memorySize *= 16;
|
---|
218 | break;
|
---|
219 | case i855_STOLEN_MEMORY_32M:
|
---|
220 | memorySize *= 32;
|
---|
221 | break;
|
---|
222 | case i855_STOLEN_MEMORY_48M:
|
---|
223 | memorySize *= 48;
|
---|
224 | break;
|
---|
225 | case i855_STOLEN_MEMORY_64M:
|
---|
226 | memorySize *= 64;
|
---|
227 | break;
|
---|
228 | case i855_STOLEN_MEMORY_128M:
|
---|
229 | memorySize *= 128;
|
---|
230 | break;
|
---|
231 | case i855_STOLEN_MEMORY_256M:
|
---|
232 | memorySize *= 256;
|
---|
233 | break;
|
---|
234 | case G4X_STOLEN_MEMORY_96MB:
|
---|
235 | memorySize *= 96;
|
---|
236 | break;
|
---|
237 | case G4X_STOLEN_MEMORY_160MB:
|
---|
238 | memorySize *= 160;
|
---|
239 | break;
|
---|
240 | case G4X_STOLEN_MEMORY_224MB:
|
---|
241 | memorySize *= 224;
|
---|
242 | break;
|
---|
243 | case G4X_STOLEN_MEMORY_352MB:
|
---|
244 | memorySize *= 352;
|
---|
245 | break;
|
---|
246 | }
|
---|
247 | } else {
|
---|
248 | // TODO: error out!
|
---|
249 | memorySize = 4096;
|
---|
250 | }
|
---|
251 |
|
---|
252 | stolenSize = memorySize - 4096;
|
---|
253 | }
|
---|
254 |
|
---|
255 |
|
---|
256 | static void
|
---|
257 | set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress)
|
---|
258 | {
|
---|
259 | // TODO: this is not 64-bit safe!
|
---|
260 | write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT),
|
---|
261 | (uint32)physicalAddress | GTT_ENTRY_VALID);
|
---|
262 | }
|
---|
263 |
|
---|
264 |
|
---|
265 | static void
|
---|
266 | intel_unmap(intel_info &info)
|
---|
267 | {
|
---|
268 | delete_area(info.registers_area);
|
---|
269 | delete_area(info.gtt_area);
|
---|
270 | delete_area(info.scratch_area);
|
---|
271 | delete_area(info.aperture_area);
|
---|
272 | info.aperture_size = 0;
|
---|
273 | }
|
---|
274 |
|
---|
275 |
|
---|
276 | static status_t
|
---|
277 | intel_map(intel_info &info)
|
---|
278 | {
|
---|
279 | int fbIndex = 0;
|
---|
280 | int mmioIndex = 1;
|
---|
281 | if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) {
|
---|
282 | // for some reason Intel saw the need to change the order of the mappings
|
---|
283 | // with the introduction of the i9xx family
|
---|
284 | mmioIndex = 0;
|
---|
285 | fbIndex = 2;
|
---|
286 | }
|
---|
287 |
|
---|
288 | AreaKeeper mmioMapper;
|
---|
289 | info.registers_area = mmioMapper.Map("intel GMCH mmio",
|
---|
290 | (void *)info.display.u.h0.base_registers[mmioIndex],
|
---|
291 | info.display.u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS,
|
---|
292 | B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&info.registers);
|
---|
293 | if (mmioMapper.InitCheck() < B_OK) {
|
---|
294 | dprintf("agp_intel: could not map memory I/O!\n");
|
---|
295 | return info.registers_area;
|
---|
296 | }
|
---|
297 |
|
---|
298 | // make sure bus master, memory-mapped I/O, and frame buffer is enabled
|
---|
299 | set_pci_config(info.display, PCI_command, 2,
|
---|
300 | get_pci_config(info.display, PCI_command, 2)
|
---|
301 | | PCI_command_io | PCI_command_memory | PCI_command_master);
|
---|
302 |
|
---|
303 | void *scratchAddress;
|
---|
304 | AreaKeeper scratchCreator;
|
---|
305 | info.scratch_area = scratchCreator.Create("intel GMCH scratch",
|
---|
306 | &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK,
|
---|
307 | B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
---|
308 | if (scratchCreator.InitCheck() < B_OK) {
|
---|
309 | dprintf("agp_intel: could not create scratch page!\n");
|
---|
310 | return info.scratch_area;
|
---|
311 | }
|
---|
312 |
|
---|
313 | physical_entry entry;
|
---|
314 | if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK)
|
---|
315 | return B_ERROR;
|
---|
316 |
|
---|
317 | if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) {
|
---|
318 | if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x) {
|
---|
319 | info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
---|
320 | + (2UL << 20);
|
---|
321 | } else
|
---|
322 | info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4);
|
---|
323 | } else {
|
---|
324 | info.gtt_physical_base = read32(info.registers
|
---|
325 | + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED;
|
---|
326 | if (info.gtt_physical_base == 0) {
|
---|
327 | // TODO: not sure how this is supposed to work under Linux/FreeBSD,
|
---|
328 | // but on my i865, this code is needed for Haiku.
|
---|
329 | dprintf("intel_gart: Use GTT address fallback.\n");
|
---|
330 | info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
---|
331 | + i830_GTT_BASE;
|
---|
332 | }
|
---|
333 | }
|
---|
334 |
|
---|
335 | size_t gttSize, stolenSize;
|
---|
336 | determine_memory_sizes(info, gttSize, stolenSize);
|
---|
337 |
|
---|
338 | info.gtt_entries = gttSize / 4096;
|
---|
339 | info.gtt_stolen_entries = stolenSize / 4096;
|
---|
340 |
|
---|
341 | TRACE("GTT base %lx, size %lu, entries %lu, stolen %lu\n", info.gtt_physical_base,
|
---|
342 | gttSize, info.gtt_entries, stolenSize);
|
---|
343 |
|
---|
344 | AreaKeeper gttMapper;
|
---|
345 | info.gtt_area = gttMapper.Map("intel GMCH gtt",
|
---|
346 | (void *)info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS,
|
---|
347 | B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&info.gtt_base);
|
---|
348 | if (gttMapper.InitCheck() < B_OK) {
|
---|
349 | dprintf("intel_gart: could not map GTT!\n");
|
---|
350 | return info.gtt_area;
|
---|
351 | }
|
---|
352 |
|
---|
353 | info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex];
|
---|
354 | info.aperture_stolen_size = stolenSize;
|
---|
355 | if (info.aperture_size == 0)
|
---|
356 | info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex];
|
---|
357 |
|
---|
358 | dprintf("intel_gart: detected %ld MB of stolen memory, aperture "
|
---|
359 | "size %ld MB, GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20,
|
---|
360 | info.aperture_size >> 20, gttSize >> 10);
|
---|
361 |
|
---|
362 | dprintf("intel_gart: GTT base = 0x%lx\n", info.gtt_physical_base);
|
---|
363 | dprintf("intel_gart: MMIO base = 0x%lx\n", info.display.u.h0.base_registers[mmioIndex]);
|
---|
364 | dprintf("intel_gart: GMR base = 0x%lx\n", info.aperture_physical_base);
|
---|
365 |
|
---|
366 | AreaKeeper apertureMapper;
|
---|
367 | info.aperture_area = apertureMapper.Map("intel graphics aperture",
|
---|
368 | (void *)info.aperture_physical_base, info.aperture_size,
|
---|
369 | B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
|
---|
370 | B_READ_AREA | B_WRITE_AREA, (void **)&info.aperture_base);
|
---|
371 | if (apertureMapper.InitCheck() < B_OK) {
|
---|
372 | // try again without write combining
|
---|
373 | dprintf(DEVICE_NAME ": enabling write combined mode failed.\n");
|
---|
374 |
|
---|
375 | info.aperture_area = apertureMapper.Map("intel graphics aperture",
|
---|
376 | (void *)info.aperture_physical_base, info.aperture_size,
|
---|
377 | B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
---|
378 | (void **)&info.aperture_base);
|
---|
379 | }
|
---|
380 | if (apertureMapper.InitCheck() < B_OK) {
|
---|
381 | dprintf(DEVICE_NAME ": could not map graphics aperture!\n");
|
---|
382 | return info.aperture_area;
|
---|
383 | }
|
---|
384 |
|
---|
385 | info.scratch_page = entry.address;
|
---|
386 |
|
---|
387 | gttMapper.Detach();
|
---|
388 | mmioMapper.Detach();
|
---|
389 | scratchCreator.Detach();
|
---|
390 | apertureMapper.Detach();
|
---|
391 |
|
---|
392 | return B_OK;
|
---|
393 | }
|
---|
394 |
|
---|
395 |
|
---|
396 | // #pragma mark - module interface
|
---|
397 |
|
---|
398 |
|
---|
399 | status_t
|
---|
400 | intel_create_aperture(uint8 bus, uint8 device, uint8 function, size_t size,
|
---|
401 | void **_aperture)
|
---|
402 | {
|
---|
403 | // TODO: we currently only support a single AGP bridge!
|
---|
404 | if ((bus != sInfo.bridge.bus || device != sInfo.bridge.device
|
---|
405 | || function != sInfo.bridge.function)
|
---|
406 | && (bus != sInfo.display.bus || device != sInfo.display.device
|
---|
407 | || function != sInfo.display.function))
|
---|
408 | return B_BAD_VALUE;
|
---|
409 |
|
---|
410 | sInfo.aperture_size = size;
|
---|
411 |
|
---|
412 | if (intel_map(sInfo) < B_OK)
|
---|
413 | return B_ERROR;
|
---|
414 |
|
---|
415 | uint16 gmchControl = get_pci_config(sInfo.bridge,
|
---|
416 | INTEL_GRAPHICS_MEMORY_CONTROL, 2) | MEMORY_CONTROL_ENABLED;
|
---|
417 | set_pci_config(sInfo.bridge, INTEL_GRAPHICS_MEMORY_CONTROL, 2, gmchControl);
|
---|
418 |
|
---|
419 | write32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL,
|
---|
420 | sInfo.gtt_physical_base | PAGE_TABLE_ENABLED);
|
---|
421 | read32(sInfo.registers + INTEL_PAGE_TABLE_CONTROL);
|
---|
422 |
|
---|
423 | if (sInfo.scratch_page != 0) {
|
---|
424 | for (size_t i = sInfo.gtt_stolen_entries; i < sInfo.gtt_entries; i++) {
|
---|
425 | set_gtt_entry(sInfo, i << GTT_PAGE_SHIFT, sInfo.scratch_page);
|
---|
426 | }
|
---|
427 | read32(sInfo.gtt_base + sInfo.gtt_entries - 1);
|
---|
428 | }
|
---|
429 |
|
---|
430 | asm("wbinvd;");
|
---|
431 |
|
---|
432 | *_aperture = NULL;
|
---|
433 | return B_OK;
|
---|
434 | }
|
---|
435 |
|
---|
436 |
|
---|
437 | void
|
---|
438 | intel_delete_aperture(void *aperture)
|
---|
439 | {
|
---|
440 | intel_unmap(sInfo);
|
---|
441 | }
|
---|
442 |
|
---|
443 |
|
---|
444 | static status_t
|
---|
445 | intel_get_aperture_info(void *aperture, aperture_info *info)
|
---|
446 | {
|
---|
447 | if (info == NULL)
|
---|
448 | return B_BAD_VALUE;
|
---|
449 |
|
---|
450 | info->base = sInfo.aperture_base;
|
---|
451 | info->physical_base = sInfo.aperture_physical_base;
|
---|
452 | info->size = sInfo.aperture_size;
|
---|
453 | info->reserved_size = sInfo.aperture_stolen_size;
|
---|
454 |
|
---|
455 | return B_OK;
|
---|
456 | }
|
---|
457 |
|
---|
458 |
|
---|
459 | status_t
|
---|
460 | intel_set_aperture_size(void *aperture, size_t size)
|
---|
461 | {
|
---|
462 | return B_ERROR;
|
---|
463 | }
|
---|
464 |
|
---|
465 |
|
---|
466 | static status_t
|
---|
467 | intel_bind_page(void *aperture, uint32 offset, phys_addr_t physicalAddress)
|
---|
468 | {
|
---|
469 | //TRACE("bind_page(offset %lx, physical %lx)\n", offset, physicalAddress);
|
---|
470 |
|
---|
471 | set_gtt_entry(sInfo, offset, physicalAddress);
|
---|
472 | return B_OK;
|
---|
473 | }
|
---|
474 |
|
---|
475 |
|
---|
476 | static status_t
|
---|
477 | intel_unbind_page(void *aperture, uint32 offset)
|
---|
478 | {
|
---|
479 | //TRACE("unbind_page(offset %lx)\n", offset);
|
---|
480 |
|
---|
481 | if (sInfo.scratch_page != 0)
|
---|
482 | set_gtt_entry(sInfo, offset, sInfo.scratch_page);
|
---|
483 |
|
---|
484 | return B_OK;
|
---|
485 | }
|
---|
486 |
|
---|
487 |
|
---|
488 | void
|
---|
489 | intel_flush_tlbs(void *aperture)
|
---|
490 | {
|
---|
491 | read32(sInfo.gtt_base + sInfo.gtt_entries - 1);
|
---|
492 | asm("wbinvd;");
|
---|
493 | }
|
---|
494 |
|
---|
495 |
|
---|
496 | // #pragma mark -
|
---|
497 |
|
---|
498 |
|
---|
499 | static status_t
|
---|
500 | intel_init()
|
---|
501 | {
|
---|
502 | TRACE("bus manager init\n");
|
---|
503 |
|
---|
504 | if (get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI) != B_OK)
|
---|
505 | return B_ERROR;
|
---|
506 |
|
---|
507 | bool found = false;
|
---|
508 |
|
---|
509 | for (uint32 index = 0; sPCI->get_nth_pci_info(index, &sInfo.bridge) == B_OK;
|
---|
510 | index++) {
|
---|
511 | if (sInfo.bridge.vendor_id != VENDOR_ID_INTEL
|
---|
512 | || sInfo.bridge.class_base != PCI_bridge)
|
---|
513 | continue;
|
---|
514 |
|
---|
515 | // check device
|
---|
516 | for (uint32 i = 0; i < sizeof(kSupportedDevices)
|
---|
517 | / sizeof(kSupportedDevices[0]); i++) {
|
---|
518 | if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) {
|
---|
519 | sInfo.type = kSupportedDevices[i].type;
|
---|
520 | found = has_display_device(sInfo.display,
|
---|
521 | kSupportedDevices[i].display_id);
|
---|
522 | break;
|
---|
523 | }
|
---|
524 | }
|
---|
525 |
|
---|
526 | if (found)
|
---|
527 | break;
|
---|
528 | }
|
---|
529 |
|
---|
530 | if (!found)
|
---|
531 | return ENODEV;
|
---|
532 |
|
---|
533 | TRACE("found intel bridge\n");
|
---|
534 | return B_OK;
|
---|
535 | }
|
---|
536 |
|
---|
537 |
|
---|
538 | static void
|
---|
539 | intel_uninit()
|
---|
540 | {
|
---|
541 | }
|
---|
542 |
|
---|
543 |
|
---|
544 | static int32
|
---|
545 | intel_std_ops(int32 op, ...)
|
---|
546 | {
|
---|
547 | switch (op) {
|
---|
548 | case B_MODULE_INIT:
|
---|
549 | return intel_init();
|
---|
550 | case B_MODULE_UNINIT:
|
---|
551 | intel_uninit();
|
---|
552 | return B_OK;
|
---|
553 | }
|
---|
554 |
|
---|
555 | return B_BAD_VALUE;
|
---|
556 | }
|
---|
557 |
|
---|
558 |
|
---|
559 | static struct agp_gart_bus_module_info sIntelModuleInfo = {
|
---|
560 | {
|
---|
561 | "busses/agp_gart/intel/v0",
|
---|
562 | 0,
|
---|
563 | intel_std_ops
|
---|
564 | },
|
---|
565 |
|
---|
566 | intel_create_aperture,
|
---|
567 | intel_delete_aperture,
|
---|
568 |
|
---|
569 | intel_get_aperture_info,
|
---|
570 | intel_set_aperture_size,
|
---|
571 | intel_bind_page,
|
---|
572 | intel_unbind_page,
|
---|
573 | intel_flush_tlbs
|
---|
574 | };
|
---|
575 |
|
---|
576 | module_info *modules[] = {
|
---|
577 | (module_info *)&sIntelModuleInfo,
|
---|
578 | NULL
|
---|
579 | };
|
---|