1 | /* |
2 | * Intel AGPGART routines. |
3 | */ |
4 | |
5 | #include <linux/module.h> |
6 | #include <linux/pci.h> |
7 | #include <linux/slab.h> |
8 | #include <linux/init.h> |
9 | #include <linux/kernel.h> |
10 | #include <linux/pagemap.h> |
11 | #include <linux/agp_backend.h> |
12 | #include <asm/smp.h> |
13 | #include "agp.h" |
14 | #include "intel-agp.h" |
15 | #include <drm/intel-gtt.h> |
16 | |
17 | static int intel_fetch_size(void) |
18 | { |
19 | int i; |
20 | u16 temp; |
21 | struct aper_size_info_16 *values; |
22 | |
23 | pci_read_config_word(dev: agp_bridge->dev, INTEL_APSIZE, val: &temp); |
24 | values = A_SIZE_16(agp_bridge->driver->aperture_sizes); |
25 | |
26 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { |
27 | if (temp == values[i].size_value) { |
28 | agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); |
29 | agp_bridge->aperture_size_idx = i; |
30 | return values[i].size; |
31 | } |
32 | } |
33 | |
34 | return 0; |
35 | } |
36 | |
37 | static int __intel_8xx_fetch_size(u8 temp) |
38 | { |
39 | int i; |
40 | struct aper_size_info_8 *values; |
41 | |
42 | values = A_SIZE_8(agp_bridge->driver->aperture_sizes); |
43 | |
44 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { |
45 | if (temp == values[i].size_value) { |
46 | agp_bridge->previous_size = |
47 | agp_bridge->current_size = (void *) (values + i); |
48 | agp_bridge->aperture_size_idx = i; |
49 | return values[i].size; |
50 | } |
51 | } |
52 | return 0; |
53 | } |
54 | |
55 | static int intel_8xx_fetch_size(void) |
56 | { |
57 | u8 temp; |
58 | |
59 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: &temp); |
60 | return __intel_8xx_fetch_size(temp); |
61 | } |
62 | |
63 | static int intel_815_fetch_size(void) |
64 | { |
65 | u8 temp; |
66 | |
67 | /* Intel 815 chipsets have a _weird_ APSIZE register with only |
68 | * one non-reserved bit, so mask the others out ... */ |
69 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: &temp); |
70 | temp &= (1 << 3); |
71 | |
72 | return __intel_8xx_fetch_size(temp); |
73 | } |
74 | |
75 | static void intel_tlbflush(struct agp_memory *mem) |
76 | { |
77 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x2200); |
78 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x2280); |
79 | } |
80 | |
81 | |
82 | static void intel_8xx_tlbflush(struct agp_memory *mem) |
83 | { |
84 | u32 temp; |
85 | pci_read_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: &temp); |
86 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: temp & ~(1 << 7)); |
87 | pci_read_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: &temp); |
88 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: temp | (1 << 7)); |
89 | } |
90 | |
91 | |
92 | static void intel_cleanup(void) |
93 | { |
94 | u16 temp; |
95 | struct aper_size_info_16 *previous_size; |
96 | |
97 | previous_size = A_SIZE_16(agp_bridge->previous_size); |
98 | pci_read_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: &temp); |
99 | pci_write_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: temp & ~(1 << 9)); |
100 | pci_write_config_word(dev: agp_bridge->dev, INTEL_APSIZE, val: previous_size->size_value); |
101 | } |
102 | |
103 | |
104 | static void intel_8xx_cleanup(void) |
105 | { |
106 | u16 temp; |
107 | struct aper_size_info_8 *previous_size; |
108 | |
109 | previous_size = A_SIZE_8(agp_bridge->previous_size); |
110 | pci_read_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: &temp); |
111 | pci_write_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: temp & ~(1 << 9)); |
112 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: previous_size->size_value); |
113 | } |
114 | |
115 | |
116 | static int intel_configure(void) |
117 | { |
118 | u16 temp2; |
119 | struct aper_size_info_16 *current_size; |
120 | |
121 | current_size = A_SIZE_16(agp_bridge->current_size); |
122 | |
123 | /* aperture size */ |
124 | pci_write_config_word(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
125 | |
126 | /* address to map to */ |
127 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
128 | AGP_APERTURE_BAR); |
129 | |
130 | /* attbase - aperture base */ |
131 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
132 | |
133 | /* agpctrl */ |
134 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x2280); |
135 | |
136 | /* paccfg/nbxcfg */ |
137 | pci_read_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: &temp2); |
138 | pci_write_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, |
139 | val: (temp2 & ~(1 << 10)) | (1 << 9)); |
140 | /* clear any possible error conditions */ |
141 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_ERRSTS + 1, val: 7); |
142 | return 0; |
143 | } |
144 | |
145 | static int intel_815_configure(void) |
146 | { |
147 | u32 addr; |
148 | u8 temp2; |
149 | struct aper_size_info_8 *current_size; |
150 | |
151 | /* attbase - aperture base */ |
152 | /* the Intel 815 chipset spec. says that bits 29-31 in the |
153 | * ATTBASE register are reserved -> try not to write them */ |
154 | if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) { |
155 | dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high" ); |
156 | return -EINVAL; |
157 | } |
158 | |
159 | current_size = A_SIZE_8(agp_bridge->current_size); |
160 | |
161 | /* aperture size */ |
162 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, |
163 | val: current_size->size_value); |
164 | |
165 | /* address to map to */ |
166 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
167 | AGP_APERTURE_BAR); |
168 | |
169 | pci_read_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: &addr); |
170 | addr &= INTEL_815_ATTBASE_MASK; |
171 | addr |= agp_bridge->gatt_bus_addr; |
172 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: addr); |
173 | |
174 | /* agpctrl */ |
175 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
176 | |
177 | /* apcont */ |
178 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_815_APCONT, val: &temp2); |
179 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_815_APCONT, val: temp2 | (1 << 1)); |
180 | |
181 | /* clear any possible error conditions */ |
182 | /* Oddness : this chipset seems to have no ERRSTS register ! */ |
183 | return 0; |
184 | } |
185 | |
186 | static void intel_820_tlbflush(struct agp_memory *mem) |
187 | { |
188 | return; |
189 | } |
190 | |
191 | static void intel_820_cleanup(void) |
192 | { |
193 | u8 temp; |
194 | struct aper_size_info_8 *previous_size; |
195 | |
196 | previous_size = A_SIZE_8(agp_bridge->previous_size); |
197 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_I820_RDCR, val: &temp); |
198 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_I820_RDCR, |
199 | val: temp & ~(1 << 1)); |
200 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, |
201 | val: previous_size->size_value); |
202 | } |
203 | |
204 | |
205 | static int intel_820_configure(void) |
206 | { |
207 | u8 temp2; |
208 | struct aper_size_info_8 *current_size; |
209 | |
210 | current_size = A_SIZE_8(agp_bridge->current_size); |
211 | |
212 | /* aperture size */ |
213 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
214 | |
215 | /* address to map to */ |
216 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
217 | AGP_APERTURE_BAR); |
218 | |
219 | /* attbase - aperture base */ |
220 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
221 | |
222 | /* agpctrl */ |
223 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
224 | |
225 | /* global enable aperture access */ |
226 | /* This flag is not accessed through MCHCFG register as in */ |
227 | /* i850 chipset. */ |
228 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_I820_RDCR, val: &temp2); |
229 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_I820_RDCR, val: temp2 | (1 << 1)); |
230 | /* clear any possible AGP-related error conditions */ |
231 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I820_ERRSTS, val: 0x001c); |
232 | return 0; |
233 | } |
234 | |
235 | static int intel_840_configure(void) |
236 | { |
237 | u16 temp2; |
238 | struct aper_size_info_8 *current_size; |
239 | |
240 | current_size = A_SIZE_8(agp_bridge->current_size); |
241 | |
242 | /* aperture size */ |
243 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
244 | |
245 | /* address to map to */ |
246 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
247 | AGP_APERTURE_BAR); |
248 | |
249 | /* attbase - aperture base */ |
250 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
251 | |
252 | /* agpctrl */ |
253 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
254 | |
255 | /* mcgcfg */ |
256 | pci_read_config_word(dev: agp_bridge->dev, INTEL_I840_MCHCFG, val: &temp2); |
257 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I840_MCHCFG, val: temp2 | (1 << 9)); |
258 | /* clear any possible error conditions */ |
259 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I840_ERRSTS, val: 0xc000); |
260 | return 0; |
261 | } |
262 | |
263 | static int intel_845_configure(void) |
264 | { |
265 | u8 temp2; |
266 | struct aper_size_info_8 *current_size; |
267 | |
268 | current_size = A_SIZE_8(agp_bridge->current_size); |
269 | |
270 | /* aperture size */ |
271 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
272 | |
273 | if (agp_bridge->apbase_config != 0) { |
274 | pci_write_config_dword(dev: agp_bridge->dev, AGP_APBASE, |
275 | val: agp_bridge->apbase_config); |
276 | } else { |
277 | /* address to map to */ |
278 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
279 | AGP_APERTURE_BAR); |
280 | agp_bridge->apbase_config = agp_bridge->gart_bus_addr; |
281 | } |
282 | |
283 | /* attbase - aperture base */ |
284 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
285 | |
286 | /* agpctrl */ |
287 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
288 | |
289 | /* agpm */ |
290 | pci_read_config_byte(dev: agp_bridge->dev, INTEL_I845_AGPM, val: &temp2); |
291 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_I845_AGPM, val: temp2 | (1 << 1)); |
292 | /* clear any possible error conditions */ |
293 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I845_ERRSTS, val: 0x001c); |
294 | return 0; |
295 | } |
296 | |
297 | static int intel_850_configure(void) |
298 | { |
299 | u16 temp2; |
300 | struct aper_size_info_8 *current_size; |
301 | |
302 | current_size = A_SIZE_8(agp_bridge->current_size); |
303 | |
304 | /* aperture size */ |
305 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
306 | |
307 | /* address to map to */ |
308 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
309 | AGP_APERTURE_BAR); |
310 | |
311 | /* attbase - aperture base */ |
312 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
313 | |
314 | /* agpctrl */ |
315 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
316 | |
317 | /* mcgcfg */ |
318 | pci_read_config_word(dev: agp_bridge->dev, INTEL_I850_MCHCFG, val: &temp2); |
319 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I850_MCHCFG, val: temp2 | (1 << 9)); |
320 | /* clear any possible AGP-related error conditions */ |
321 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I850_ERRSTS, val: 0x001c); |
322 | return 0; |
323 | } |
324 | |
325 | static int intel_860_configure(void) |
326 | { |
327 | u16 temp2; |
328 | struct aper_size_info_8 *current_size; |
329 | |
330 | current_size = A_SIZE_8(agp_bridge->current_size); |
331 | |
332 | /* aperture size */ |
333 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
334 | |
335 | /* address to map to */ |
336 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
337 | AGP_APERTURE_BAR); |
338 | |
339 | /* attbase - aperture base */ |
340 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
341 | |
342 | /* agpctrl */ |
343 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
344 | |
345 | /* mcgcfg */ |
346 | pci_read_config_word(dev: agp_bridge->dev, INTEL_I860_MCHCFG, val: &temp2); |
347 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I860_MCHCFG, val: temp2 | (1 << 9)); |
348 | /* clear any possible AGP-related error conditions */ |
349 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I860_ERRSTS, val: 0xf700); |
350 | return 0; |
351 | } |
352 | |
353 | static int intel_830mp_configure(void) |
354 | { |
355 | u16 temp2; |
356 | struct aper_size_info_8 *current_size; |
357 | |
358 | current_size = A_SIZE_8(agp_bridge->current_size); |
359 | |
360 | /* aperture size */ |
361 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
362 | |
363 | /* address to map to */ |
364 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
365 | AGP_APERTURE_BAR); |
366 | |
367 | /* attbase - aperture base */ |
368 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
369 | |
370 | /* agpctrl */ |
371 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
372 | |
373 | /* gmch */ |
374 | pci_read_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: &temp2); |
375 | pci_write_config_word(dev: agp_bridge->dev, INTEL_NBXCFG, val: temp2 | (1 << 9)); |
376 | /* clear any possible AGP-related error conditions */ |
377 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I830_ERRSTS, val: 0x1c); |
378 | return 0; |
379 | } |
380 | |
381 | static int intel_7505_configure(void) |
382 | { |
383 | u16 temp2; |
384 | struct aper_size_info_8 *current_size; |
385 | |
386 | current_size = A_SIZE_8(agp_bridge->current_size); |
387 | |
388 | /* aperture size */ |
389 | pci_write_config_byte(dev: agp_bridge->dev, INTEL_APSIZE, val: current_size->size_value); |
390 | |
391 | /* address to map to */ |
392 | agp_bridge->gart_bus_addr = pci_bus_address(pdev: agp_bridge->dev, |
393 | AGP_APERTURE_BAR); |
394 | |
395 | /* attbase - aperture base */ |
396 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_ATTBASE, val: agp_bridge->gatt_bus_addr); |
397 | |
398 | /* agpctrl */ |
399 | pci_write_config_dword(dev: agp_bridge->dev, INTEL_AGPCTRL, val: 0x0000); |
400 | |
401 | /* mchcfg */ |
402 | pci_read_config_word(dev: agp_bridge->dev, INTEL_I7505_MCHCFG, val: &temp2); |
403 | pci_write_config_word(dev: agp_bridge->dev, INTEL_I7505_MCHCFG, val: temp2 | (1 << 9)); |
404 | |
405 | return 0; |
406 | } |
407 | |
408 | /* Setup function */ |
409 | static const struct gatt_mask intel_generic_masks[] = |
410 | { |
411 | {.mask = 0x00000017, .type = 0} |
412 | }; |
413 | |
414 | static const struct aper_size_info_8 intel_815_sizes[2] = |
415 | { |
416 | {64, 16384, 4, 0}, |
417 | {32, 8192, 3, 8}, |
418 | }; |
419 | |
420 | static const struct aper_size_info_8 intel_8xx_sizes[7] = |
421 | { |
422 | {256, 65536, 6, 0}, |
423 | {128, 32768, 5, 32}, |
424 | {64, 16384, 4, 48}, |
425 | {32, 8192, 3, 56}, |
426 | {16, 4096, 2, 60}, |
427 | {8, 2048, 1, 62}, |
428 | {4, 1024, 0, 63} |
429 | }; |
430 | |
431 | static const struct aper_size_info_16 intel_generic_sizes[7] = |
432 | { |
433 | {256, 65536, 6, 0}, |
434 | {128, 32768, 5, 32}, |
435 | {64, 16384, 4, 48}, |
436 | {32, 8192, 3, 56}, |
437 | {16, 4096, 2, 60}, |
438 | {8, 2048, 1, 62}, |
439 | {4, 1024, 0, 63} |
440 | }; |
441 | |
442 | static const struct aper_size_info_8 intel_830mp_sizes[4] = |
443 | { |
444 | {256, 65536, 6, 0}, |
445 | {128, 32768, 5, 32}, |
446 | {64, 16384, 4, 48}, |
447 | {32, 8192, 3, 56} |
448 | }; |
449 | |
450 | static const struct agp_bridge_driver intel_generic_driver = { |
451 | .owner = THIS_MODULE, |
452 | .aperture_sizes = intel_generic_sizes, |
453 | .size_type = U16_APER_SIZE, |
454 | .num_aperture_sizes = 7, |
455 | .needs_scratch_page = true, |
456 | .configure = intel_configure, |
457 | .fetch_size = intel_fetch_size, |
458 | .cleanup = intel_cleanup, |
459 | .tlb_flush = intel_tlbflush, |
460 | .mask_memory = agp_generic_mask_memory, |
461 | .masks = intel_generic_masks, |
462 | .agp_enable = agp_generic_enable, |
463 | .cache_flush = global_cache_flush, |
464 | .create_gatt_table = agp_generic_create_gatt_table, |
465 | .free_gatt_table = agp_generic_free_gatt_table, |
466 | .insert_memory = agp_generic_insert_memory, |
467 | .remove_memory = agp_generic_remove_memory, |
468 | .alloc_by_type = agp_generic_alloc_by_type, |
469 | .free_by_type = agp_generic_free_by_type, |
470 | .agp_alloc_page = agp_generic_alloc_page, |
471 | .agp_alloc_pages = agp_generic_alloc_pages, |
472 | .agp_destroy_page = agp_generic_destroy_page, |
473 | .agp_destroy_pages = agp_generic_destroy_pages, |
474 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
475 | }; |
476 | |
477 | static const struct agp_bridge_driver intel_815_driver = { |
478 | .owner = THIS_MODULE, |
479 | .aperture_sizes = intel_815_sizes, |
480 | .size_type = U8_APER_SIZE, |
481 | .num_aperture_sizes = 2, |
482 | .needs_scratch_page = true, |
483 | .configure = intel_815_configure, |
484 | .fetch_size = intel_815_fetch_size, |
485 | .cleanup = intel_8xx_cleanup, |
486 | .tlb_flush = intel_8xx_tlbflush, |
487 | .mask_memory = agp_generic_mask_memory, |
488 | .masks = intel_generic_masks, |
489 | .agp_enable = agp_generic_enable, |
490 | .cache_flush = global_cache_flush, |
491 | .create_gatt_table = agp_generic_create_gatt_table, |
492 | .free_gatt_table = agp_generic_free_gatt_table, |
493 | .insert_memory = agp_generic_insert_memory, |
494 | .remove_memory = agp_generic_remove_memory, |
495 | .alloc_by_type = agp_generic_alloc_by_type, |
496 | .free_by_type = agp_generic_free_by_type, |
497 | .agp_alloc_page = agp_generic_alloc_page, |
498 | .agp_alloc_pages = agp_generic_alloc_pages, |
499 | .agp_destroy_page = agp_generic_destroy_page, |
500 | .agp_destroy_pages = agp_generic_destroy_pages, |
501 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
502 | }; |
503 | |
504 | static const struct agp_bridge_driver intel_820_driver = { |
505 | .owner = THIS_MODULE, |
506 | .aperture_sizes = intel_8xx_sizes, |
507 | .size_type = U8_APER_SIZE, |
508 | .num_aperture_sizes = 7, |
509 | .needs_scratch_page = true, |
510 | .configure = intel_820_configure, |
511 | .fetch_size = intel_8xx_fetch_size, |
512 | .cleanup = intel_820_cleanup, |
513 | .tlb_flush = intel_820_tlbflush, |
514 | .mask_memory = agp_generic_mask_memory, |
515 | .masks = intel_generic_masks, |
516 | .agp_enable = agp_generic_enable, |
517 | .cache_flush = global_cache_flush, |
518 | .create_gatt_table = agp_generic_create_gatt_table, |
519 | .free_gatt_table = agp_generic_free_gatt_table, |
520 | .insert_memory = agp_generic_insert_memory, |
521 | .remove_memory = agp_generic_remove_memory, |
522 | .alloc_by_type = agp_generic_alloc_by_type, |
523 | .free_by_type = agp_generic_free_by_type, |
524 | .agp_alloc_page = agp_generic_alloc_page, |
525 | .agp_alloc_pages = agp_generic_alloc_pages, |
526 | .agp_destroy_page = agp_generic_destroy_page, |
527 | .agp_destroy_pages = agp_generic_destroy_pages, |
528 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
529 | }; |
530 | |
531 | static const struct agp_bridge_driver intel_830mp_driver = { |
532 | .owner = THIS_MODULE, |
533 | .aperture_sizes = intel_830mp_sizes, |
534 | .size_type = U8_APER_SIZE, |
535 | .num_aperture_sizes = 4, |
536 | .needs_scratch_page = true, |
537 | .configure = intel_830mp_configure, |
538 | .fetch_size = intel_8xx_fetch_size, |
539 | .cleanup = intel_8xx_cleanup, |
540 | .tlb_flush = intel_8xx_tlbflush, |
541 | .mask_memory = agp_generic_mask_memory, |
542 | .masks = intel_generic_masks, |
543 | .agp_enable = agp_generic_enable, |
544 | .cache_flush = global_cache_flush, |
545 | .create_gatt_table = agp_generic_create_gatt_table, |
546 | .free_gatt_table = agp_generic_free_gatt_table, |
547 | .insert_memory = agp_generic_insert_memory, |
548 | .remove_memory = agp_generic_remove_memory, |
549 | .alloc_by_type = agp_generic_alloc_by_type, |
550 | .free_by_type = agp_generic_free_by_type, |
551 | .agp_alloc_page = agp_generic_alloc_page, |
552 | .agp_alloc_pages = agp_generic_alloc_pages, |
553 | .agp_destroy_page = agp_generic_destroy_page, |
554 | .agp_destroy_pages = agp_generic_destroy_pages, |
555 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
556 | }; |
557 | |
558 | static const struct agp_bridge_driver intel_840_driver = { |
559 | .owner = THIS_MODULE, |
560 | .aperture_sizes = intel_8xx_sizes, |
561 | .size_type = U8_APER_SIZE, |
562 | .num_aperture_sizes = 7, |
563 | .needs_scratch_page = true, |
564 | .configure = intel_840_configure, |
565 | .fetch_size = intel_8xx_fetch_size, |
566 | .cleanup = intel_8xx_cleanup, |
567 | .tlb_flush = intel_8xx_tlbflush, |
568 | .mask_memory = agp_generic_mask_memory, |
569 | .masks = intel_generic_masks, |
570 | .agp_enable = agp_generic_enable, |
571 | .cache_flush = global_cache_flush, |
572 | .create_gatt_table = agp_generic_create_gatt_table, |
573 | .free_gatt_table = agp_generic_free_gatt_table, |
574 | .insert_memory = agp_generic_insert_memory, |
575 | .remove_memory = agp_generic_remove_memory, |
576 | .alloc_by_type = agp_generic_alloc_by_type, |
577 | .free_by_type = agp_generic_free_by_type, |
578 | .agp_alloc_page = agp_generic_alloc_page, |
579 | .agp_alloc_pages = agp_generic_alloc_pages, |
580 | .agp_destroy_page = agp_generic_destroy_page, |
581 | .agp_destroy_pages = agp_generic_destroy_pages, |
582 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
583 | }; |
584 | |
585 | static const struct agp_bridge_driver intel_845_driver = { |
586 | .owner = THIS_MODULE, |
587 | .aperture_sizes = intel_8xx_sizes, |
588 | .size_type = U8_APER_SIZE, |
589 | .num_aperture_sizes = 7, |
590 | .needs_scratch_page = true, |
591 | .configure = intel_845_configure, |
592 | .fetch_size = intel_8xx_fetch_size, |
593 | .cleanup = intel_8xx_cleanup, |
594 | .tlb_flush = intel_8xx_tlbflush, |
595 | .mask_memory = agp_generic_mask_memory, |
596 | .masks = intel_generic_masks, |
597 | .agp_enable = agp_generic_enable, |
598 | .cache_flush = global_cache_flush, |
599 | .create_gatt_table = agp_generic_create_gatt_table, |
600 | .free_gatt_table = agp_generic_free_gatt_table, |
601 | .insert_memory = agp_generic_insert_memory, |
602 | .remove_memory = agp_generic_remove_memory, |
603 | .alloc_by_type = agp_generic_alloc_by_type, |
604 | .free_by_type = agp_generic_free_by_type, |
605 | .agp_alloc_page = agp_generic_alloc_page, |
606 | .agp_alloc_pages = agp_generic_alloc_pages, |
607 | .agp_destroy_page = agp_generic_destroy_page, |
608 | .agp_destroy_pages = agp_generic_destroy_pages, |
609 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
610 | }; |
611 | |
612 | static const struct agp_bridge_driver intel_850_driver = { |
613 | .owner = THIS_MODULE, |
614 | .aperture_sizes = intel_8xx_sizes, |
615 | .size_type = U8_APER_SIZE, |
616 | .num_aperture_sizes = 7, |
617 | .needs_scratch_page = true, |
618 | .configure = intel_850_configure, |
619 | .fetch_size = intel_8xx_fetch_size, |
620 | .cleanup = intel_8xx_cleanup, |
621 | .tlb_flush = intel_8xx_tlbflush, |
622 | .mask_memory = agp_generic_mask_memory, |
623 | .masks = intel_generic_masks, |
624 | .agp_enable = agp_generic_enable, |
625 | .cache_flush = global_cache_flush, |
626 | .create_gatt_table = agp_generic_create_gatt_table, |
627 | .free_gatt_table = agp_generic_free_gatt_table, |
628 | .insert_memory = agp_generic_insert_memory, |
629 | .remove_memory = agp_generic_remove_memory, |
630 | .alloc_by_type = agp_generic_alloc_by_type, |
631 | .free_by_type = agp_generic_free_by_type, |
632 | .agp_alloc_page = agp_generic_alloc_page, |
633 | .agp_alloc_pages = agp_generic_alloc_pages, |
634 | .agp_destroy_page = agp_generic_destroy_page, |
635 | .agp_destroy_pages = agp_generic_destroy_pages, |
636 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
637 | }; |
638 | |
639 | static const struct agp_bridge_driver intel_860_driver = { |
640 | .owner = THIS_MODULE, |
641 | .aperture_sizes = intel_8xx_sizes, |
642 | .size_type = U8_APER_SIZE, |
643 | .num_aperture_sizes = 7, |
644 | .needs_scratch_page = true, |
645 | .configure = intel_860_configure, |
646 | .fetch_size = intel_8xx_fetch_size, |
647 | .cleanup = intel_8xx_cleanup, |
648 | .tlb_flush = intel_8xx_tlbflush, |
649 | .mask_memory = agp_generic_mask_memory, |
650 | .masks = intel_generic_masks, |
651 | .agp_enable = agp_generic_enable, |
652 | .cache_flush = global_cache_flush, |
653 | .create_gatt_table = agp_generic_create_gatt_table, |
654 | .free_gatt_table = agp_generic_free_gatt_table, |
655 | .insert_memory = agp_generic_insert_memory, |
656 | .remove_memory = agp_generic_remove_memory, |
657 | .alloc_by_type = agp_generic_alloc_by_type, |
658 | .free_by_type = agp_generic_free_by_type, |
659 | .agp_alloc_page = agp_generic_alloc_page, |
660 | .agp_alloc_pages = agp_generic_alloc_pages, |
661 | .agp_destroy_page = agp_generic_destroy_page, |
662 | .agp_destroy_pages = agp_generic_destroy_pages, |
663 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
664 | }; |
665 | |
666 | static const struct agp_bridge_driver intel_7505_driver = { |
667 | .owner = THIS_MODULE, |
668 | .aperture_sizes = intel_8xx_sizes, |
669 | .size_type = U8_APER_SIZE, |
670 | .num_aperture_sizes = 7, |
671 | .needs_scratch_page = true, |
672 | .configure = intel_7505_configure, |
673 | .fetch_size = intel_8xx_fetch_size, |
674 | .cleanup = intel_8xx_cleanup, |
675 | .tlb_flush = intel_8xx_tlbflush, |
676 | .mask_memory = agp_generic_mask_memory, |
677 | .masks = intel_generic_masks, |
678 | .agp_enable = agp_generic_enable, |
679 | .cache_flush = global_cache_flush, |
680 | .create_gatt_table = agp_generic_create_gatt_table, |
681 | .free_gatt_table = agp_generic_free_gatt_table, |
682 | .insert_memory = agp_generic_insert_memory, |
683 | .remove_memory = agp_generic_remove_memory, |
684 | .alloc_by_type = agp_generic_alloc_by_type, |
685 | .free_by_type = agp_generic_free_by_type, |
686 | .agp_alloc_page = agp_generic_alloc_page, |
687 | .agp_alloc_pages = agp_generic_alloc_pages, |
688 | .agp_destroy_page = agp_generic_destroy_page, |
689 | .agp_destroy_pages = agp_generic_destroy_pages, |
690 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
691 | }; |
692 | |
693 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of |
694 | * driver and gmch_driver must be non-null, and find_gmch will determine |
695 | * which one should be used if a gmch_chip_id is present. |
696 | */ |
697 | static const struct intel_agp_driver_description { |
698 | unsigned int chip_id; |
699 | char *name; |
700 | const struct agp_bridge_driver *driver; |
701 | } intel_agp_chipsets[] = { |
702 | { PCI_DEVICE_ID_INTEL_82443LX_0, "440LX" , &intel_generic_driver }, |
703 | { PCI_DEVICE_ID_INTEL_82443BX_0, "440BX" , &intel_generic_driver }, |
704 | { PCI_DEVICE_ID_INTEL_82443GX_0, "440GX" , &intel_generic_driver }, |
705 | { PCI_DEVICE_ID_INTEL_82815_MC, "i815" , &intel_815_driver }, |
706 | { PCI_DEVICE_ID_INTEL_82820_HB, "i820" , &intel_820_driver }, |
707 | { PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820" , &intel_820_driver }, |
708 | { PCI_DEVICE_ID_INTEL_82830_HB, "830M" , &intel_830mp_driver }, |
709 | { PCI_DEVICE_ID_INTEL_82840_HB, "i840" , &intel_840_driver }, |
710 | { PCI_DEVICE_ID_INTEL_82845_HB, "i845" , &intel_845_driver }, |
711 | { PCI_DEVICE_ID_INTEL_82845G_HB, "845G" , &intel_845_driver }, |
712 | { PCI_DEVICE_ID_INTEL_82850_HB, "i850" , &intel_850_driver }, |
713 | { PCI_DEVICE_ID_INTEL_82854_HB, "854" , &intel_845_driver }, |
714 | { PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM" , &intel_845_driver }, |
715 | { PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM" , &intel_845_driver }, |
716 | { PCI_DEVICE_ID_INTEL_82860_HB, "i860" , &intel_860_driver }, |
717 | { PCI_DEVICE_ID_INTEL_82865_HB, "865" , &intel_845_driver }, |
718 | { PCI_DEVICE_ID_INTEL_82875_HB, "i875" , &intel_845_driver }, |
719 | { PCI_DEVICE_ID_INTEL_7505_0, "E7505" , &intel_7505_driver }, |
720 | { PCI_DEVICE_ID_INTEL_7205_0, "E7205" , &intel_7505_driver }, |
721 | { 0, NULL, NULL } |
722 | }; |
723 | |
724 | static int agp_intel_probe(struct pci_dev *pdev, |
725 | const struct pci_device_id *ent) |
726 | { |
727 | struct agp_bridge_data *bridge; |
728 | u8 cap_ptr = 0; |
729 | struct resource *r; |
730 | int i, err; |
731 | |
732 | cap_ptr = pci_find_capability(dev: pdev, PCI_CAP_ID_AGP); |
733 | |
734 | bridge = agp_alloc_bridge(); |
735 | if (!bridge) |
736 | return -ENOMEM; |
737 | |
738 | bridge->capndx = cap_ptr; |
739 | |
740 | if (intel_gmch_probe(bridge_pdev: pdev, NULL, bridge)) |
741 | goto found_gmch; |
742 | |
743 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
744 | /* In case that multiple models of gfx chip may |
745 | stand on same host bridge type, this can be |
746 | sure we detect the right IGD. */ |
747 | if (pdev->device == intel_agp_chipsets[i].chip_id) { |
748 | bridge->driver = intel_agp_chipsets[i].driver; |
749 | break; |
750 | } |
751 | } |
752 | |
753 | if (!bridge->driver) { |
754 | if (cap_ptr) |
755 | dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n" , |
756 | pdev->vendor, pdev->device); |
757 | agp_put_bridge(bridge); |
758 | return -ENODEV; |
759 | } |
760 | |
761 | bridge->dev = pdev; |
762 | bridge->dev_private_data = NULL; |
763 | |
764 | dev_info(&pdev->dev, "Intel %s Chipset\n" , intel_agp_chipsets[i].name); |
765 | |
766 | /* |
767 | * The following fixes the case where the BIOS has "forgotten" to |
768 | * provide an address range for the GART. |
769 | * 20030610 - hamish@zot.org |
770 | * This happens before pci_enable_device() intentionally; |
771 | * calling pci_enable_device() before assigning the resource |
772 | * will result in the GART being disabled on machines with such |
773 | * BIOSs (the GART ends up with a BAR starting at 0, which |
774 | * conflicts a lot of other devices). |
775 | */ |
776 | r = &pdev->resource[0]; |
777 | if (!r->start && r->end) { |
778 | if (pci_assign_resource(dev: pdev, i: 0)) { |
779 | dev_err(&pdev->dev, "can't assign resource 0\n" ); |
780 | agp_put_bridge(bridge); |
781 | return -ENODEV; |
782 | } |
783 | } |
784 | |
785 | /* |
786 | * If the device has not been properly setup, the following will catch |
787 | * the problem and should stop the system from crashing. |
788 | * 20030610 - hamish@zot.org |
789 | */ |
790 | if (pci_enable_device(dev: pdev)) { |
791 | dev_err(&pdev->dev, "can't enable PCI device\n" ); |
792 | agp_put_bridge(bridge); |
793 | return -ENODEV; |
794 | } |
795 | |
796 | /* Fill in the mode register */ |
797 | if (cap_ptr) { |
798 | pci_read_config_dword(dev: pdev, |
799 | where: bridge->capndx+PCI_AGP_STATUS, |
800 | val: &bridge->mode); |
801 | } |
802 | |
803 | found_gmch: |
804 | pci_set_drvdata(pdev, data: bridge); |
805 | err = agp_add_bridge(bridge); |
806 | return err; |
807 | } |
808 | |
809 | static void agp_intel_remove(struct pci_dev *pdev) |
810 | { |
811 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
812 | |
813 | agp_remove_bridge(bridge); |
814 | |
815 | intel_gmch_remove(); |
816 | |
817 | agp_put_bridge(bridge); |
818 | } |
819 | |
820 | static int agp_intel_resume(struct device *dev) |
821 | { |
822 | struct pci_dev *pdev = to_pci_dev(dev); |
823 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
824 | |
825 | bridge->driver->configure(); |
826 | |
827 | return 0; |
828 | } |
829 | |
830 | static const struct pci_device_id agp_intel_pci_table[] = { |
831 | #define ID(x) \ |
832 | { \ |
833 | .class = (PCI_CLASS_BRIDGE_HOST << 8), \ |
834 | .class_mask = ~0, \ |
835 | .vendor = PCI_VENDOR_ID_INTEL, \ |
836 | .device = x, \ |
837 | .subvendor = PCI_ANY_ID, \ |
838 | .subdevice = PCI_ANY_ID, \ |
839 | } |
840 | ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */ |
841 | ID(PCI_DEVICE_ID_INTEL_82443LX_0), |
842 | ID(PCI_DEVICE_ID_INTEL_82443BX_0), |
843 | ID(PCI_DEVICE_ID_INTEL_82443GX_0), |
844 | ID(PCI_DEVICE_ID_INTEL_82810_MC1), |
845 | ID(PCI_DEVICE_ID_INTEL_82810_MC3), |
846 | ID(PCI_DEVICE_ID_INTEL_82810E_MC), |
847 | ID(PCI_DEVICE_ID_INTEL_82815_MC), |
848 | ID(PCI_DEVICE_ID_INTEL_82820_HB), |
849 | ID(PCI_DEVICE_ID_INTEL_82820_UP_HB), |
850 | ID(PCI_DEVICE_ID_INTEL_82830_HB), |
851 | ID(PCI_DEVICE_ID_INTEL_82840_HB), |
852 | ID(PCI_DEVICE_ID_INTEL_82845_HB), |
853 | ID(PCI_DEVICE_ID_INTEL_82845G_HB), |
854 | ID(PCI_DEVICE_ID_INTEL_82850_HB), |
855 | ID(PCI_DEVICE_ID_INTEL_82854_HB), |
856 | ID(PCI_DEVICE_ID_INTEL_82855PM_HB), |
857 | ID(PCI_DEVICE_ID_INTEL_82855GM_HB), |
858 | ID(PCI_DEVICE_ID_INTEL_82860_HB), |
859 | ID(PCI_DEVICE_ID_INTEL_82865_HB), |
860 | ID(PCI_DEVICE_ID_INTEL_82875_HB), |
861 | ID(PCI_DEVICE_ID_INTEL_7505_0), |
862 | ID(PCI_DEVICE_ID_INTEL_7205_0), |
863 | ID(PCI_DEVICE_ID_INTEL_E7221_HB), |
864 | ID(PCI_DEVICE_ID_INTEL_82915G_HB), |
865 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), |
866 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), |
867 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), |
868 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), |
869 | ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB), |
870 | ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB), |
871 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), |
872 | ID(PCI_DEVICE_ID_INTEL_82G35_HB), |
873 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), |
874 | ID(PCI_DEVICE_ID_INTEL_82965G_HB), |
875 | ID(PCI_DEVICE_ID_INTEL_82965GM_HB), |
876 | ID(PCI_DEVICE_ID_INTEL_82965GME_HB), |
877 | ID(PCI_DEVICE_ID_INTEL_G33_HB), |
878 | ID(PCI_DEVICE_ID_INTEL_Q35_HB), |
879 | ID(PCI_DEVICE_ID_INTEL_Q33_HB), |
880 | ID(PCI_DEVICE_ID_INTEL_GM45_HB), |
881 | ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB), |
882 | ID(PCI_DEVICE_ID_INTEL_Q45_HB), |
883 | ID(PCI_DEVICE_ID_INTEL_G45_HB), |
884 | ID(PCI_DEVICE_ID_INTEL_G41_HB), |
885 | ID(PCI_DEVICE_ID_INTEL_B43_HB), |
886 | ID(PCI_DEVICE_ID_INTEL_B43_1_HB), |
887 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), |
888 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), |
889 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), |
890 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), |
891 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), |
892 | { } |
893 | }; |
894 | |
895 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); |
896 | |
897 | static DEFINE_SIMPLE_DEV_PM_OPS(agp_intel_pm_ops, NULL, agp_intel_resume); |
898 | |
899 | static struct pci_driver agp_intel_pci_driver = { |
900 | .name = "agpgart-intel" , |
901 | .id_table = agp_intel_pci_table, |
902 | .probe = agp_intel_probe, |
903 | .remove = agp_intel_remove, |
904 | .driver.pm = &agp_intel_pm_ops, |
905 | }; |
906 | |
907 | static int __init agp_intel_init(void) |
908 | { |
909 | if (agp_off) |
910 | return -EINVAL; |
911 | return pci_register_driver(&agp_intel_pci_driver); |
912 | } |
913 | |
914 | static void __exit agp_intel_cleanup(void) |
915 | { |
916 | pci_unregister_driver(dev: &agp_intel_pci_driver); |
917 | } |
918 | |
919 | module_init(agp_intel_init); |
920 | module_exit(agp_intel_cleanup); |
921 | |
922 | MODULE_AUTHOR("Dave Jones, Various @Intel" ); |
923 | MODULE_LICENSE("GPL and additional rights" ); |
924 | |