diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/agp/intel-agp.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/agp/intel-agp.c')
-rw-r--r-- | drivers/char/agp/intel-agp.c | 1833 |
1 files changed, 1833 insertions, 0 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c new file mode 100644 index 000000000000..8c7d727432bb --- /dev/null +++ b/drivers/char/agp/intel-agp.c | |||
@@ -0,0 +1,1833 @@ | |||
1 | /* | ||
2 | * Intel AGPGART routines. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * Intel(R) 855GM/852GM and 865G support added by David Dawes | ||
7 | * <dawes@tungstengraphics.com>. | ||
8 | * | ||
9 | * Intel(R) 915G/915GM support added by Alan Hourihane | ||
10 | * <alanh@tungstengraphics.com>. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/pagemap.h> | ||
17 | #include <linux/agp_backend.h> | ||
18 | #include "agp.h" | ||
19 | |||
20 | /* Intel 815 register */ | ||
21 | #define INTEL_815_APCONT 0x51 | ||
22 | #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF | ||
23 | |||
24 | /* Intel i820 registers */ | ||
25 | #define INTEL_I820_RDCR 0x51 | ||
26 | #define INTEL_I820_ERRSTS 0xc8 | ||
27 | |||
28 | /* Intel i840 registers */ | ||
29 | #define INTEL_I840_MCHCFG 0x50 | ||
30 | #define INTEL_I840_ERRSTS 0xc8 | ||
31 | |||
32 | /* Intel i850 registers */ | ||
33 | #define INTEL_I850_MCHCFG 0x50 | ||
34 | #define INTEL_I850_ERRSTS 0xc8 | ||
35 | |||
36 | /* intel 915G registers */ | ||
37 | #define I915_GMADDR 0x18 | ||
38 | #define I915_MMADDR 0x10 | ||
39 | #define I915_PTEADDR 0x1C | ||
40 | #define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) | ||
41 | #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) | ||
42 | |||
43 | |||
44 | /* Intel 7505 registers */ | ||
45 | #define INTEL_I7505_APSIZE 0x74 | ||
46 | #define INTEL_I7505_NCAPID 0x60 | ||
47 | #define INTEL_I7505_NISTAT 0x6c | ||
48 | #define INTEL_I7505_ATTBASE 0x78 | ||
49 | #define INTEL_I7505_ERRSTS 0x42 | ||
50 | #define INTEL_I7505_AGPCTRL 0x70 | ||
51 | #define INTEL_I7505_MCHCFG 0x50 | ||
52 | |||
53 | static struct aper_size_info_fixed intel_i810_sizes[] = | ||
54 | { | ||
55 | {64, 16384, 4}, | ||
56 | /* The 32M mode still requires a 64k gatt */ | ||
57 | {32, 8192, 4} | ||
58 | }; | ||
59 | |||
60 | #define AGP_DCACHE_MEMORY 1 | ||
61 | #define AGP_PHYS_MEMORY 2 | ||
62 | |||
63 | static struct gatt_mask intel_i810_masks[] = | ||
64 | { | ||
65 | {.mask = I810_PTE_VALID, .type = 0}, | ||
66 | {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, | ||
67 | {.mask = I810_PTE_VALID, .type = 0} | ||
68 | }; | ||
69 | |||
70 | static struct _intel_i810_private { | ||
71 | struct pci_dev *i810_dev; /* device one */ | ||
72 | volatile u8 __iomem *registers; | ||
73 | int num_dcache_entries; | ||
74 | } intel_i810_private; | ||
75 | |||
76 | static int intel_i810_fetch_size(void) | ||
77 | { | ||
78 | u32 smram_miscc; | ||
79 | struct aper_size_info_fixed *values; | ||
80 | |||
81 | pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); | ||
82 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
83 | |||
84 | if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { | ||
85 | printk(KERN_WARNING PFX "i810 is disabled\n"); | ||
86 | return 0; | ||
87 | } | ||
88 | if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { | ||
89 | agp_bridge->previous_size = | ||
90 | agp_bridge->current_size = (void *) (values + 1); | ||
91 | agp_bridge->aperture_size_idx = 1; | ||
92 | return values[1].size; | ||
93 | } else { | ||
94 | agp_bridge->previous_size = | ||
95 | agp_bridge->current_size = (void *) (values); | ||
96 | agp_bridge->aperture_size_idx = 0; | ||
97 | return values[0].size; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int intel_i810_configure(void) | ||
104 | { | ||
105 | struct aper_size_info_fixed *current_size; | ||
106 | u32 temp; | ||
107 | int i; | ||
108 | |||
109 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
110 | |||
111 | pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp); | ||
112 | temp &= 0xfff80000; | ||
113 | |||
114 | intel_i810_private.registers = ioremap(temp, 128 * 4096); | ||
115 | if (!intel_i810_private.registers) { | ||
116 | printk(KERN_ERR PFX "Unable to remap memory.\n"); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | |||
120 | if ((readl(intel_i810_private.registers+I810_DRAM_CTL) | ||
121 | & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { | ||
122 | /* This will need to be dynamically assigned */ | ||
123 | printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); | ||
124 | intel_i810_private.num_dcache_entries = 1024; | ||
125 | } | ||
126 | pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp); | ||
127 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
128 | writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL); | ||
129 | readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
130 | |||
131 | if (agp_bridge->driver->needs_scratch_page) { | ||
132 | for (i = 0; i < current_size->num_entries; i++) { | ||
133 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | ||
134 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */ | ||
135 | } | ||
136 | } | ||
137 | global_cache_flush(); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void intel_i810_cleanup(void) | ||
142 | { | ||
143 | writel(0, intel_i810_private.registers+I810_PGETBL_CTL); | ||
144 | readl(intel_i810_private.registers); /* PCI Posting. */ | ||
145 | iounmap(intel_i810_private.registers); | ||
146 | } | ||
147 | |||
148 | static void intel_i810_tlbflush(struct agp_memory *mem) | ||
149 | { | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode) | ||
154 | { | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | /* Exists to support ARGB cursors */ | ||
159 | static void *i8xx_alloc_pages(void) | ||
160 | { | ||
161 | struct page * page; | ||
162 | |||
163 | page = alloc_pages(GFP_KERNEL, 2); | ||
164 | if (page == NULL) | ||
165 | return NULL; | ||
166 | |||
167 | if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { | ||
168 | global_flush_tlb(); | ||
169 | __free_page(page); | ||
170 | return NULL; | ||
171 | } | ||
172 | global_flush_tlb(); | ||
173 | get_page(page); | ||
174 | SetPageLocked(page); | ||
175 | atomic_inc(&agp_bridge->current_memory_agp); | ||
176 | return page_address(page); | ||
177 | } | ||
178 | |||
179 | static void i8xx_destroy_pages(void *addr) | ||
180 | { | ||
181 | struct page *page; | ||
182 | |||
183 | if (addr == NULL) | ||
184 | return; | ||
185 | |||
186 | page = virt_to_page(addr); | ||
187 | change_page_attr(page, 4, PAGE_KERNEL); | ||
188 | global_flush_tlb(); | ||
189 | put_page(page); | ||
190 | unlock_page(page); | ||
191 | free_pages((unsigned long)addr, 2); | ||
192 | atomic_dec(&agp_bridge->current_memory_agp); | ||
193 | } | ||
194 | |||
195 | static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | ||
196 | int type) | ||
197 | { | ||
198 | int i, j, num_entries; | ||
199 | void *temp; | ||
200 | |||
201 | temp = agp_bridge->current_size; | ||
202 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
203 | |||
204 | if ((pg_start + mem->page_count) > num_entries) { | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | for (j = pg_start; j < (pg_start + mem->page_count); j++) { | ||
208 | if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) | ||
209 | return -EBUSY; | ||
210 | } | ||
211 | |||
212 | if (type != 0 || mem->type != 0) { | ||
213 | if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { | ||
214 | /* special insert */ | ||
215 | global_cache_flush(); | ||
216 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { | ||
217 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | ||
218 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
219 | } | ||
220 | global_cache_flush(); | ||
221 | agp_bridge->driver->tlb_flush(mem); | ||
222 | return 0; | ||
223 | } | ||
224 | if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY)) | ||
225 | goto insert; | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | insert: | ||
230 | global_cache_flush(); | ||
231 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
232 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
233 | mem->memory[i], mem->type), | ||
234 | intel_i810_private.registers+I810_PTE_BASE+(j*4)); | ||
235 | readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
236 | } | ||
237 | global_cache_flush(); | ||
238 | |||
239 | agp_bridge->driver->tlb_flush(mem); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, | ||
244 | int type) | ||
245 | { | ||
246 | int i; | ||
247 | |||
248 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
249 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | ||
250 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
251 | } | ||
252 | |||
253 | global_cache_flush(); | ||
254 | agp_bridge->driver->tlb_flush(mem); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * The i810/i830 requires a physical address to program its mouse | ||
260 | * pointer into hardware. | ||
261 | * However the Xserver still writes to it through the agp aperture. | ||
262 | */ | ||
263 | static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | ||
264 | { | ||
265 | struct agp_memory *new; | ||
266 | void *addr; | ||
267 | |||
268 | if (pg_count != 1 && pg_count != 4) | ||
269 | return NULL; | ||
270 | |||
271 | switch (pg_count) { | ||
272 | case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); | ||
273 | break; | ||
274 | case 4: | ||
275 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
276 | addr = i8xx_alloc_pages(); | ||
277 | break; | ||
278 | default: | ||
279 | return NULL; | ||
280 | } | ||
281 | |||
282 | if (addr == NULL) | ||
283 | return NULL; | ||
284 | |||
285 | new = agp_create_memory(pg_count); | ||
286 | if (new == NULL) | ||
287 | return NULL; | ||
288 | |||
289 | new->memory[0] = virt_to_phys(addr); | ||
290 | if (pg_count == 4) { | ||
291 | /* kludge to get 4 physical pages for ARGB cursor */ | ||
292 | new->memory[1] = new->memory[0] + PAGE_SIZE; | ||
293 | new->memory[2] = new->memory[1] + PAGE_SIZE; | ||
294 | new->memory[3] = new->memory[2] + PAGE_SIZE; | ||
295 | } | ||
296 | new->page_count = pg_count; | ||
297 | new->num_scratch_pages = pg_count; | ||
298 | new->type = AGP_PHYS_MEMORY; | ||
299 | new->physical = new->memory[0]; | ||
300 | return new; | ||
301 | } | ||
302 | |||
303 | static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) | ||
304 | { | ||
305 | struct agp_memory *new; | ||
306 | |||
307 | if (type == AGP_DCACHE_MEMORY) { | ||
308 | if (pg_count != intel_i810_private.num_dcache_entries) | ||
309 | return NULL; | ||
310 | |||
311 | new = agp_create_memory(1); | ||
312 | if (new == NULL) | ||
313 | return NULL; | ||
314 | |||
315 | new->type = AGP_DCACHE_MEMORY; | ||
316 | new->page_count = pg_count; | ||
317 | new->num_scratch_pages = 0; | ||
318 | vfree(new->memory); | ||
319 | return new; | ||
320 | } | ||
321 | if (type == AGP_PHYS_MEMORY) | ||
322 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
323 | |||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | static void intel_i810_free_by_type(struct agp_memory *curr) | ||
328 | { | ||
329 | agp_free_key(curr->key); | ||
330 | if(curr->type == AGP_PHYS_MEMORY) { | ||
331 | if (curr->page_count == 4) | ||
332 | i8xx_destroy_pages(phys_to_virt(curr->memory[0])); | ||
333 | else | ||
334 | agp_bridge->driver->agp_destroy_page( | ||
335 | phys_to_virt(curr->memory[0])); | ||
336 | vfree(curr->memory); | ||
337 | } | ||
338 | kfree(curr); | ||
339 | } | ||
340 | |||
341 | static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, | ||
342 | unsigned long addr, int type) | ||
343 | { | ||
344 | /* Type checking must be done elsewhere */ | ||
345 | return addr | bridge->driver->masks[type].mask; | ||
346 | } | ||
347 | |||
348 | static struct aper_size_info_fixed intel_i830_sizes[] = | ||
349 | { | ||
350 | {128, 32768, 5}, | ||
351 | /* The 64M mode still requires a 128k gatt */ | ||
352 | {64, 16384, 5}, | ||
353 | {256, 65536, 6}, | ||
354 | }; | ||
355 | |||
356 | static struct _intel_i830_private { | ||
357 | struct pci_dev *i830_dev; /* device one */ | ||
358 | volatile u8 __iomem *registers; | ||
359 | volatile u32 __iomem *gtt; /* I915G */ | ||
360 | int gtt_entries; | ||
361 | } intel_i830_private; | ||
362 | |||
363 | static void intel_i830_init_gtt_entries(void) | ||
364 | { | ||
365 | u16 gmch_ctrl; | ||
366 | int gtt_entries; | ||
367 | u8 rdct; | ||
368 | int local = 0; | ||
369 | static const int ddt[4] = { 0, 16, 32, 64 }; | ||
370 | int size; | ||
371 | |||
372 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | ||
373 | |||
374 | /* We obtain the size of the GTT, which is also stored (for some | ||
375 | * reason) at the top of stolen memory. Then we add 4KB to that | ||
376 | * for the video BIOS popup, which is also stored in there. */ | ||
377 | size = agp_bridge->driver->fetch_size() + 4; | ||
378 | |||
379 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || | ||
380 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { | ||
381 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | ||
382 | case I830_GMCH_GMS_STOLEN_512: | ||
383 | gtt_entries = KB(512) - KB(size); | ||
384 | break; | ||
385 | case I830_GMCH_GMS_STOLEN_1024: | ||
386 | gtt_entries = MB(1) - KB(size); | ||
387 | break; | ||
388 | case I830_GMCH_GMS_STOLEN_8192: | ||
389 | gtt_entries = MB(8) - KB(size); | ||
390 | break; | ||
391 | case I830_GMCH_GMS_LOCAL: | ||
392 | rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE); | ||
393 | gtt_entries = (I830_RDRAM_ND(rdct) + 1) * | ||
394 | MB(ddt[I830_RDRAM_DDT(rdct)]); | ||
395 | local = 1; | ||
396 | break; | ||
397 | default: | ||
398 | gtt_entries = 0; | ||
399 | break; | ||
400 | } | ||
401 | } else { | ||
402 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | ||
403 | case I855_GMCH_GMS_STOLEN_1M: | ||
404 | gtt_entries = MB(1) - KB(size); | ||
405 | break; | ||
406 | case I855_GMCH_GMS_STOLEN_4M: | ||
407 | gtt_entries = MB(4) - KB(size); | ||
408 | break; | ||
409 | case I855_GMCH_GMS_STOLEN_8M: | ||
410 | gtt_entries = MB(8) - KB(size); | ||
411 | break; | ||
412 | case I855_GMCH_GMS_STOLEN_16M: | ||
413 | gtt_entries = MB(16) - KB(size); | ||
414 | break; | ||
415 | case I855_GMCH_GMS_STOLEN_32M: | ||
416 | gtt_entries = MB(32) - KB(size); | ||
417 | break; | ||
418 | case I915_GMCH_GMS_STOLEN_48M: | ||
419 | /* Check it's really I915G */ | ||
420 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || | ||
421 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) | ||
422 | gtt_entries = MB(48) - KB(size); | ||
423 | else | ||
424 | gtt_entries = 0; | ||
425 | break; | ||
426 | case I915_GMCH_GMS_STOLEN_64M: | ||
427 | /* Check it's really I915G */ | ||
428 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || | ||
429 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) | ||
430 | gtt_entries = MB(64) - KB(size); | ||
431 | else | ||
432 | gtt_entries = 0; | ||
433 | default: | ||
434 | gtt_entries = 0; | ||
435 | break; | ||
436 | } | ||
437 | } | ||
438 | if (gtt_entries > 0) | ||
439 | printk(KERN_INFO PFX "Detected %dK %s memory.\n", | ||
440 | gtt_entries / KB(1), local ? "local" : "stolen"); | ||
441 | else | ||
442 | printk(KERN_INFO PFX | ||
443 | "No pre-allocated video memory detected.\n"); | ||
444 | gtt_entries /= KB(4); | ||
445 | |||
446 | intel_i830_private.gtt_entries = gtt_entries; | ||
447 | } | ||
448 | |||
449 | /* The intel i830 automatically initializes the agp aperture during POST. | ||
450 | * Use the memory already set aside for in the GTT. | ||
451 | */ | ||
452 | static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) | ||
453 | { | ||
454 | int page_order; | ||
455 | struct aper_size_info_fixed *size; | ||
456 | int num_entries; | ||
457 | u32 temp; | ||
458 | |||
459 | size = agp_bridge->current_size; | ||
460 | page_order = size->page_order; | ||
461 | num_entries = size->num_entries; | ||
462 | agp_bridge->gatt_table_real = NULL; | ||
463 | |||
464 | pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); | ||
465 | temp &= 0xfff80000; | ||
466 | |||
467 | intel_i830_private.registers = ioremap(temp,128 * 4096); | ||
468 | if (!intel_i830_private.registers) | ||
469 | return -ENOMEM; | ||
470 | |||
471 | temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
472 | global_cache_flush(); /* FIXME: ?? */ | ||
473 | |||
474 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
475 | intel_i830_init_gtt_entries(); | ||
476 | |||
477 | agp_bridge->gatt_table = NULL; | ||
478 | |||
479 | agp_bridge->gatt_bus_addr = temp; | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /* Return the gatt table to a sane state. Use the top of stolen | ||
485 | * memory for the GTT. | ||
486 | */ | ||
487 | static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge) | ||
488 | { | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int intel_i830_fetch_size(void) | ||
493 | { | ||
494 | u16 gmch_ctrl; | ||
495 | struct aper_size_info_fixed *values; | ||
496 | |||
497 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
498 | |||
499 | if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && | ||
500 | agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { | ||
501 | /* 855GM/852GM/865G has 128MB aperture size */ | ||
502 | agp_bridge->previous_size = agp_bridge->current_size = (void *) values; | ||
503 | agp_bridge->aperture_size_idx = 0; | ||
504 | return values[0].size; | ||
505 | } | ||
506 | |||
507 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | ||
508 | |||
509 | if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { | ||
510 | agp_bridge->previous_size = agp_bridge->current_size = (void *) values; | ||
511 | agp_bridge->aperture_size_idx = 0; | ||
512 | return values[0].size; | ||
513 | } else { | ||
514 | agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1); | ||
515 | agp_bridge->aperture_size_idx = 1; | ||
516 | return values[1].size; | ||
517 | } | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int intel_i830_configure(void) | ||
523 | { | ||
524 | struct aper_size_info_fixed *current_size; | ||
525 | u32 temp; | ||
526 | u16 gmch_ctrl; | ||
527 | int i; | ||
528 | |||
529 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
530 | |||
531 | pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp); | ||
532 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
533 | |||
534 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | ||
535 | gmch_ctrl |= I830_GMCH_ENABLED; | ||
536 | pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); | ||
537 | |||
538 | writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL); | ||
539 | readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
540 | |||
541 | if (agp_bridge->driver->needs_scratch_page) { | ||
542 | for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) { | ||
543 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); | ||
544 | readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
545 | } | ||
546 | } | ||
547 | |||
548 | global_cache_flush(); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | static void intel_i830_cleanup(void) | ||
553 | { | ||
554 | iounmap(intel_i830_private.registers); | ||
555 | } | ||
556 | |||
557 | static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type) | ||
558 | { | ||
559 | int i,j,num_entries; | ||
560 | void *temp; | ||
561 | |||
562 | temp = agp_bridge->current_size; | ||
563 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
564 | |||
565 | if (pg_start < intel_i830_private.gtt_entries) { | ||
566 | printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", | ||
567 | pg_start,intel_i830_private.gtt_entries); | ||
568 | |||
569 | printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | if ((pg_start + mem->page_count) > num_entries) | ||
574 | return -EINVAL; | ||
575 | |||
576 | /* The i830 can't check the GTT for entries since its read only, | ||
577 | * depend on the caller to make the correct offset decisions. | ||
578 | */ | ||
579 | |||
580 | if ((type != 0 && type != AGP_PHYS_MEMORY) || | ||
581 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | ||
582 | return -EINVAL; | ||
583 | |||
584 | global_cache_flush(); /* FIXME: Necessary ?*/ | ||
585 | |||
586 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
587 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
588 | mem->memory[i], mem->type), | ||
589 | intel_i830_private.registers+I810_PTE_BASE+(j*4)); | ||
590 | readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
591 | } | ||
592 | |||
593 | global_cache_flush(); | ||
594 | agp_bridge->driver->tlb_flush(mem); | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, | ||
599 | int type) | ||
600 | { | ||
601 | int i; | ||
602 | |||
603 | global_cache_flush(); | ||
604 | |||
605 | if (pg_start < intel_i830_private.gtt_entries) { | ||
606 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | |||
610 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
611 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); | ||
612 | readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
613 | } | ||
614 | |||
615 | global_cache_flush(); | ||
616 | agp_bridge->driver->tlb_flush(mem); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) | ||
621 | { | ||
622 | if (type == AGP_PHYS_MEMORY) | ||
623 | return alloc_agpphysmem_i8xx(pg_count, type); | ||
624 | |||
625 | /* always return NULL for other allocation types for now */ | ||
626 | return NULL; | ||
627 | } | ||
628 | |||
629 | static int intel_i915_configure(void) | ||
630 | { | ||
631 | struct aper_size_info_fixed *current_size; | ||
632 | u32 temp; | ||
633 | u16 gmch_ctrl; | ||
634 | int i; | ||
635 | |||
636 | current_size = A_SIZE_FIX(agp_bridge->current_size); | ||
637 | |||
638 | pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp); | ||
639 | |||
640 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
641 | |||
642 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | ||
643 | gmch_ctrl |= I830_GMCH_ENABLED; | ||
644 | pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); | ||
645 | |||
646 | writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL); | ||
647 | readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ | ||
648 | |||
649 | if (agp_bridge->driver->needs_scratch_page) { | ||
650 | for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) { | ||
651 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); | ||
652 | readl(intel_i830_private.gtt+i); /* PCI Posting. */ | ||
653 | } | ||
654 | } | ||
655 | |||
656 | global_cache_flush(); | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static void intel_i915_cleanup(void) | ||
661 | { | ||
662 | iounmap(intel_i830_private.gtt); | ||
663 | iounmap(intel_i830_private.registers); | ||
664 | } | ||
665 | |||
666 | static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | ||
667 | int type) | ||
668 | { | ||
669 | int i,j,num_entries; | ||
670 | void *temp; | ||
671 | |||
672 | temp = agp_bridge->current_size; | ||
673 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
674 | |||
675 | if (pg_start < intel_i830_private.gtt_entries) { | ||
676 | printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n", | ||
677 | pg_start,intel_i830_private.gtt_entries); | ||
678 | |||
679 | printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n"); | ||
680 | return -EINVAL; | ||
681 | } | ||
682 | |||
683 | if ((pg_start + mem->page_count) > num_entries) | ||
684 | return -EINVAL; | ||
685 | |||
686 | /* The i830 can't check the GTT for entries since its read only, | ||
687 | * depend on the caller to make the correct offset decisions. | ||
688 | */ | ||
689 | |||
690 | if ((type != 0 && type != AGP_PHYS_MEMORY) || | ||
691 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | ||
692 | return -EINVAL; | ||
693 | |||
694 | global_cache_flush(); | ||
695 | |||
696 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
697 | writel(agp_bridge->driver->mask_memory(agp_bridge, | ||
698 | mem->memory[i], mem->type), intel_i830_private.gtt+j); | ||
699 | readl(intel_i830_private.gtt+j); /* PCI Posting. */ | ||
700 | } | ||
701 | |||
702 | global_cache_flush(); | ||
703 | agp_bridge->driver->tlb_flush(mem); | ||
704 | return 0; | ||
705 | } | ||
706 | |||
707 | static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, | ||
708 | int type) | ||
709 | { | ||
710 | int i; | ||
711 | |||
712 | global_cache_flush(); | ||
713 | |||
714 | if (pg_start < intel_i830_private.gtt_entries) { | ||
715 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | ||
716 | return -EINVAL; | ||
717 | } | ||
718 | |||
719 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
720 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); | ||
721 | readl(intel_i830_private.gtt+i); | ||
722 | } | ||
723 | |||
724 | global_cache_flush(); | ||
725 | agp_bridge->driver->tlb_flush(mem); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static int intel_i915_fetch_size(void) | ||
730 | { | ||
731 | struct aper_size_info_fixed *values; | ||
732 | u32 temp, offset = 0; | ||
733 | |||
734 | #define I915_256MB_ADDRESS_MASK (1<<27) | ||
735 | |||
736 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
737 | |||
738 | pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp); | ||
739 | if (temp & I915_256MB_ADDRESS_MASK) | ||
740 | offset = 0; /* 128MB aperture */ | ||
741 | else | ||
742 | offset = 2; /* 256MB aperture */ | ||
743 | agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); | ||
744 | return values[offset].size; | ||
745 | } | ||
746 | |||
747 | /* The intel i915 automatically initializes the agp aperture during POST. | ||
748 | * Use the memory already set aside for in the GTT. | ||
749 | */ | ||
750 | static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) | ||
751 | { | ||
752 | int page_order; | ||
753 | struct aper_size_info_fixed *size; | ||
754 | int num_entries; | ||
755 | u32 temp, temp2; | ||
756 | |||
757 | size = agp_bridge->current_size; | ||
758 | page_order = size->page_order; | ||
759 | num_entries = size->num_entries; | ||
760 | agp_bridge->gatt_table_real = NULL; | ||
761 | |||
762 | pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp); | ||
763 | pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2); | ||
764 | |||
765 | intel_i830_private.gtt = ioremap(temp2, 256 * 1024); | ||
766 | if (!intel_i830_private.gtt) | ||
767 | return -ENOMEM; | ||
768 | |||
769 | temp &= 0xfff80000; | ||
770 | |||
771 | intel_i830_private.registers = ioremap(temp,128 * 4096); | ||
772 | if (!intel_i830_private.registers) | ||
773 | return -ENOMEM; | ||
774 | |||
775 | temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; | ||
776 | global_cache_flush(); /* FIXME: ? */ | ||
777 | |||
778 | /* we have to call this as early as possible after the MMIO base address is known */ | ||
779 | intel_i830_init_gtt_entries(); | ||
780 | |||
781 | agp_bridge->gatt_table = NULL; | ||
782 | |||
783 | agp_bridge->gatt_bus_addr = temp; | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | static int intel_fetch_size(void) | ||
789 | { | ||
790 | int i; | ||
791 | u16 temp; | ||
792 | struct aper_size_info_16 *values; | ||
793 | |||
794 | pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp); | ||
795 | values = A_SIZE_16(agp_bridge->driver->aperture_sizes); | ||
796 | |||
797 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { | ||
798 | if (temp == values[i].size_value) { | ||
799 | agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); | ||
800 | agp_bridge->aperture_size_idx = i; | ||
801 | return values[i].size; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | static int __intel_8xx_fetch_size(u8 temp) | ||
809 | { | ||
810 | int i; | ||
811 | struct aper_size_info_8 *values; | ||
812 | |||
813 | values = A_SIZE_8(agp_bridge->driver->aperture_sizes); | ||
814 | |||
815 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { | ||
816 | if (temp == values[i].size_value) { | ||
817 | agp_bridge->previous_size = | ||
818 | agp_bridge->current_size = (void *) (values + i); | ||
819 | agp_bridge->aperture_size_idx = i; | ||
820 | return values[i].size; | ||
821 | } | ||
822 | } | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int intel_8xx_fetch_size(void) | ||
827 | { | ||
828 | u8 temp; | ||
829 | |||
830 | pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); | ||
831 | return __intel_8xx_fetch_size(temp); | ||
832 | } | ||
833 | |||
834 | static int intel_815_fetch_size(void) | ||
835 | { | ||
836 | u8 temp; | ||
837 | |||
838 | /* Intel 815 chipsets have a _weird_ APSIZE register with only | ||
839 | * one non-reserved bit, so mask the others out ... */ | ||
840 | pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); | ||
841 | temp &= (1 << 3); | ||
842 | |||
843 | return __intel_8xx_fetch_size(temp); | ||
844 | } | ||
845 | |||
846 | static void intel_tlbflush(struct agp_memory *mem) | ||
847 | { | ||
848 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200); | ||
849 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); | ||
850 | } | ||
851 | |||
852 | |||
853 | static void intel_8xx_tlbflush(struct agp_memory *mem) | ||
854 | { | ||
855 | u32 temp; | ||
856 | pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp); | ||
857 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7)); | ||
858 | pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp); | ||
859 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7)); | ||
860 | } | ||
861 | |||
862 | |||
863 | static void intel_cleanup(void) | ||
864 | { | ||
865 | u16 temp; | ||
866 | struct aper_size_info_16 *previous_size; | ||
867 | |||
868 | previous_size = A_SIZE_16(agp_bridge->previous_size); | ||
869 | pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp); | ||
870 | pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9)); | ||
871 | pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value); | ||
872 | } | ||
873 | |||
874 | |||
875 | static void intel_8xx_cleanup(void) | ||
876 | { | ||
877 | u16 temp; | ||
878 | struct aper_size_info_8 *previous_size; | ||
879 | |||
880 | previous_size = A_SIZE_8(agp_bridge->previous_size); | ||
881 | pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp); | ||
882 | pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9)); | ||
883 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value); | ||
884 | } | ||
885 | |||
886 | |||
887 | static int intel_configure(void) | ||
888 | { | ||
889 | u32 temp; | ||
890 | u16 temp2; | ||
891 | struct aper_size_info_16 *current_size; | ||
892 | |||
893 | current_size = A_SIZE_16(agp_bridge->current_size); | ||
894 | |||
895 | /* aperture size */ | ||
896 | pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
897 | |||
898 | /* address to map to */ | ||
899 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
900 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
901 | |||
902 | /* attbase - aperture base */ | ||
903 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
904 | |||
905 | /* agpctrl */ | ||
906 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); | ||
907 | |||
908 | /* paccfg/nbxcfg */ | ||
909 | pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2); | ||
910 | pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, | ||
911 | (temp2 & ~(1 << 10)) | (1 << 9)); | ||
912 | /* clear any possible error conditions */ | ||
913 | pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7); | ||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | static int intel_815_configure(void) | ||
918 | { | ||
919 | u32 temp, addr; | ||
920 | u8 temp2; | ||
921 | struct aper_size_info_8 *current_size; | ||
922 | |||
923 | /* attbase - aperture base */ | ||
924 | /* the Intel 815 chipset spec. says that bits 29-31 in the | ||
925 | * ATTBASE register are reserved -> try not to write them */ | ||
926 | if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) { | ||
927 | printk (KERN_EMERG PFX "gatt bus addr too high"); | ||
928 | return -EINVAL; | ||
929 | } | ||
930 | |||
931 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
932 | |||
933 | /* aperture size */ | ||
934 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, | ||
935 | current_size->size_value); | ||
936 | |||
937 | /* address to map to */ | ||
938 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
939 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
940 | |||
941 | pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr); | ||
942 | addr &= INTEL_815_ATTBASE_MASK; | ||
943 | addr |= agp_bridge->gatt_bus_addr; | ||
944 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr); | ||
945 | |||
946 | /* agpctrl */ | ||
947 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
948 | |||
949 | /* apcont */ | ||
950 | pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2); | ||
951 | pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1)); | ||
952 | |||
953 | /* clear any possible error conditions */ | ||
954 | /* Oddness : this chipset seems to have no ERRSTS register ! */ | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static void intel_820_tlbflush(struct agp_memory *mem) | ||
959 | { | ||
960 | return; | ||
961 | } | ||
962 | |||
963 | static void intel_820_cleanup(void) | ||
964 | { | ||
965 | u8 temp; | ||
966 | struct aper_size_info_8 *previous_size; | ||
967 | |||
968 | previous_size = A_SIZE_8(agp_bridge->previous_size); | ||
969 | pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp); | ||
970 | pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, | ||
971 | temp & ~(1 << 1)); | ||
972 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, | ||
973 | previous_size->size_value); | ||
974 | } | ||
975 | |||
976 | |||
977 | static int intel_820_configure(void) | ||
978 | { | ||
979 | u32 temp; | ||
980 | u8 temp2; | ||
981 | struct aper_size_info_8 *current_size; | ||
982 | |||
983 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
984 | |||
985 | /* aperture size */ | ||
986 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
987 | |||
988 | /* address to map to */ | ||
989 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
990 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
991 | |||
992 | /* attbase - aperture base */ | ||
993 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
994 | |||
995 | /* agpctrl */ | ||
996 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
997 | |||
998 | /* global enable aperture access */ | ||
999 | /* This flag is not accessed through MCHCFG register as in */ | ||
1000 | /* i850 chipset. */ | ||
1001 | pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2); | ||
1002 | pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1)); | ||
1003 | /* clear any possible AGP-related error conditions */ | ||
1004 | pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c); | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | static int intel_840_configure(void) | ||
1009 | { | ||
1010 | u32 temp; | ||
1011 | u16 temp2; | ||
1012 | struct aper_size_info_8 *current_size; | ||
1013 | |||
1014 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1015 | |||
1016 | /* aperture size */ | ||
1017 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1018 | |||
1019 | /* address to map to */ | ||
1020 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1021 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1022 | |||
1023 | /* attbase - aperture base */ | ||
1024 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1025 | |||
1026 | /* agpctrl */ | ||
1027 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1028 | |||
1029 | /* mcgcfg */ | ||
1030 | pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2); | ||
1031 | pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9)); | ||
1032 | /* clear any possible error conditions */ | ||
1033 | pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000); | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static int intel_845_configure(void) | ||
1038 | { | ||
1039 | u32 temp; | ||
1040 | u8 temp2; | ||
1041 | struct aper_size_info_8 *current_size; | ||
1042 | |||
1043 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1044 | |||
1045 | /* aperture size */ | ||
1046 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1047 | |||
1048 | /* address to map to */ | ||
1049 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1050 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1051 | |||
1052 | /* attbase - aperture base */ | ||
1053 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1054 | |||
1055 | /* agpctrl */ | ||
1056 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1057 | |||
1058 | /* agpm */ | ||
1059 | pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2); | ||
1060 | pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1)); | ||
1061 | /* clear any possible error conditions */ | ||
1062 | pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); | ||
1063 | return 0; | ||
1064 | } | ||
1065 | |||
1066 | static int intel_850_configure(void) | ||
1067 | { | ||
1068 | u32 temp; | ||
1069 | u16 temp2; | ||
1070 | struct aper_size_info_8 *current_size; | ||
1071 | |||
1072 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1073 | |||
1074 | /* aperture size */ | ||
1075 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1076 | |||
1077 | /* address to map to */ | ||
1078 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1079 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1080 | |||
1081 | /* attbase - aperture base */ | ||
1082 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1083 | |||
1084 | /* agpctrl */ | ||
1085 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1086 | |||
1087 | /* mcgcfg */ | ||
1088 | pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2); | ||
1089 | pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9)); | ||
1090 | /* clear any possible AGP-related error conditions */ | ||
1091 | pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static int intel_860_configure(void) | ||
1096 | { | ||
1097 | u32 temp; | ||
1098 | u16 temp2; | ||
1099 | struct aper_size_info_8 *current_size; | ||
1100 | |||
1101 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1102 | |||
1103 | /* aperture size */ | ||
1104 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1105 | |||
1106 | /* address to map to */ | ||
1107 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1108 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1109 | |||
1110 | /* attbase - aperture base */ | ||
1111 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1112 | |||
1113 | /* agpctrl */ | ||
1114 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1115 | |||
1116 | /* mcgcfg */ | ||
1117 | pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2); | ||
1118 | pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9)); | ||
1119 | /* clear any possible AGP-related error conditions */ | ||
1120 | pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700); | ||
1121 | return 0; | ||
1122 | } | ||
1123 | |||
1124 | static int intel_830mp_configure(void) | ||
1125 | { | ||
1126 | u32 temp; | ||
1127 | u16 temp2; | ||
1128 | struct aper_size_info_8 *current_size; | ||
1129 | |||
1130 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1131 | |||
1132 | /* aperture size */ | ||
1133 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1134 | |||
1135 | /* address to map to */ | ||
1136 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1137 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1138 | |||
1139 | /* attbase - aperture base */ | ||
1140 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1141 | |||
1142 | /* agpctrl */ | ||
1143 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1144 | |||
1145 | /* gmch */ | ||
1146 | pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2); | ||
1147 | pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9)); | ||
1148 | /* clear any possible AGP-related error conditions */ | ||
1149 | pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c); | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | static int intel_7505_configure(void) | ||
1154 | { | ||
1155 | u32 temp; | ||
1156 | u16 temp2; | ||
1157 | struct aper_size_info_8 *current_size; | ||
1158 | |||
1159 | current_size = A_SIZE_8(agp_bridge->current_size); | ||
1160 | |||
1161 | /* aperture size */ | ||
1162 | pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); | ||
1163 | |||
1164 | /* address to map to */ | ||
1165 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1166 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1167 | |||
1168 | /* attbase - aperture base */ | ||
1169 | pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); | ||
1170 | |||
1171 | /* agpctrl */ | ||
1172 | pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); | ||
1173 | |||
1174 | /* mchcfg */ | ||
1175 | pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2); | ||
1176 | pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9)); | ||
1177 | |||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | /* Setup function */ | ||
1182 | static struct gatt_mask intel_generic_masks[] = | ||
1183 | { | ||
1184 | {.mask = 0x00000017, .type = 0} | ||
1185 | }; | ||
1186 | |||
1187 | static struct aper_size_info_8 intel_815_sizes[2] = | ||
1188 | { | ||
1189 | {64, 16384, 4, 0}, | ||
1190 | {32, 8192, 3, 8}, | ||
1191 | }; | ||
1192 | |||
1193 | static struct aper_size_info_8 intel_8xx_sizes[7] = | ||
1194 | { | ||
1195 | {256, 65536, 6, 0}, | ||
1196 | {128, 32768, 5, 32}, | ||
1197 | {64, 16384, 4, 48}, | ||
1198 | {32, 8192, 3, 56}, | ||
1199 | {16, 4096, 2, 60}, | ||
1200 | {8, 2048, 1, 62}, | ||
1201 | {4, 1024, 0, 63} | ||
1202 | }; | ||
1203 | |||
1204 | static struct aper_size_info_16 intel_generic_sizes[7] = | ||
1205 | { | ||
1206 | {256, 65536, 6, 0}, | ||
1207 | {128, 32768, 5, 32}, | ||
1208 | {64, 16384, 4, 48}, | ||
1209 | {32, 8192, 3, 56}, | ||
1210 | {16, 4096, 2, 60}, | ||
1211 | {8, 2048, 1, 62}, | ||
1212 | {4, 1024, 0, 63} | ||
1213 | }; | ||
1214 | |||
1215 | static struct aper_size_info_8 intel_830mp_sizes[4] = | ||
1216 | { | ||
1217 | {256, 65536, 6, 0}, | ||
1218 | {128, 32768, 5, 32}, | ||
1219 | {64, 16384, 4, 48}, | ||
1220 | {32, 8192, 3, 56} | ||
1221 | }; | ||
1222 | |||
1223 | static struct agp_bridge_driver intel_generic_driver = { | ||
1224 | .owner = THIS_MODULE, | ||
1225 | .aperture_sizes = intel_generic_sizes, | ||
1226 | .size_type = U16_APER_SIZE, | ||
1227 | .num_aperture_sizes = 7, | ||
1228 | .configure = intel_configure, | ||
1229 | .fetch_size = intel_fetch_size, | ||
1230 | .cleanup = intel_cleanup, | ||
1231 | .tlb_flush = intel_tlbflush, | ||
1232 | .mask_memory = agp_generic_mask_memory, | ||
1233 | .masks = intel_generic_masks, | ||
1234 | .agp_enable = agp_generic_enable, | ||
1235 | .cache_flush = global_cache_flush, | ||
1236 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1237 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1238 | .insert_memory = agp_generic_insert_memory, | ||
1239 | .remove_memory = agp_generic_remove_memory, | ||
1240 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1241 | .free_by_type = agp_generic_free_by_type, | ||
1242 | .agp_alloc_page = agp_generic_alloc_page, | ||
1243 | .agp_destroy_page = agp_generic_destroy_page, | ||
1244 | }; | ||
1245 | |||
1246 | static struct agp_bridge_driver intel_810_driver = { | ||
1247 | .owner = THIS_MODULE, | ||
1248 | .aperture_sizes = intel_i810_sizes, | ||
1249 | .size_type = FIXED_APER_SIZE, | ||
1250 | .num_aperture_sizes = 2, | ||
1251 | .needs_scratch_page = TRUE, | ||
1252 | .configure = intel_i810_configure, | ||
1253 | .fetch_size = intel_i810_fetch_size, | ||
1254 | .cleanup = intel_i810_cleanup, | ||
1255 | .tlb_flush = intel_i810_tlbflush, | ||
1256 | .mask_memory = intel_i810_mask_memory, | ||
1257 | .masks = intel_i810_masks, | ||
1258 | .agp_enable = intel_i810_agp_enable, | ||
1259 | .cache_flush = global_cache_flush, | ||
1260 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1261 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1262 | .insert_memory = intel_i810_insert_entries, | ||
1263 | .remove_memory = intel_i810_remove_entries, | ||
1264 | .alloc_by_type = intel_i810_alloc_by_type, | ||
1265 | .free_by_type = intel_i810_free_by_type, | ||
1266 | .agp_alloc_page = agp_generic_alloc_page, | ||
1267 | .agp_destroy_page = agp_generic_destroy_page, | ||
1268 | }; | ||
1269 | |||
1270 | static struct agp_bridge_driver intel_815_driver = { | ||
1271 | .owner = THIS_MODULE, | ||
1272 | .aperture_sizes = intel_815_sizes, | ||
1273 | .size_type = U8_APER_SIZE, | ||
1274 | .num_aperture_sizes = 2, | ||
1275 | .configure = intel_815_configure, | ||
1276 | .fetch_size = intel_815_fetch_size, | ||
1277 | .cleanup = intel_8xx_cleanup, | ||
1278 | .tlb_flush = intel_8xx_tlbflush, | ||
1279 | .mask_memory = agp_generic_mask_memory, | ||
1280 | .masks = intel_generic_masks, | ||
1281 | .agp_enable = agp_generic_enable, | ||
1282 | .cache_flush = global_cache_flush, | ||
1283 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1284 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1285 | .insert_memory = agp_generic_insert_memory, | ||
1286 | .remove_memory = agp_generic_remove_memory, | ||
1287 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1288 | .free_by_type = agp_generic_free_by_type, | ||
1289 | .agp_alloc_page = agp_generic_alloc_page, | ||
1290 | .agp_destroy_page = agp_generic_destroy_page, | ||
1291 | }; | ||
1292 | |||
1293 | static struct agp_bridge_driver intel_830_driver = { | ||
1294 | .owner = THIS_MODULE, | ||
1295 | .aperture_sizes = intel_i830_sizes, | ||
1296 | .size_type = FIXED_APER_SIZE, | ||
1297 | .num_aperture_sizes = 3, | ||
1298 | .needs_scratch_page = TRUE, | ||
1299 | .configure = intel_i830_configure, | ||
1300 | .fetch_size = intel_i830_fetch_size, | ||
1301 | .cleanup = intel_i830_cleanup, | ||
1302 | .tlb_flush = intel_i810_tlbflush, | ||
1303 | .mask_memory = intel_i810_mask_memory, | ||
1304 | .masks = intel_i810_masks, | ||
1305 | .agp_enable = intel_i810_agp_enable, | ||
1306 | .cache_flush = global_cache_flush, | ||
1307 | .create_gatt_table = intel_i830_create_gatt_table, | ||
1308 | .free_gatt_table = intel_i830_free_gatt_table, | ||
1309 | .insert_memory = intel_i830_insert_entries, | ||
1310 | .remove_memory = intel_i830_remove_entries, | ||
1311 | .alloc_by_type = intel_i830_alloc_by_type, | ||
1312 | .free_by_type = intel_i810_free_by_type, | ||
1313 | .agp_alloc_page = agp_generic_alloc_page, | ||
1314 | .agp_destroy_page = agp_generic_destroy_page, | ||
1315 | }; | ||
1316 | |||
1317 | static struct agp_bridge_driver intel_820_driver = { | ||
1318 | .owner = THIS_MODULE, | ||
1319 | .aperture_sizes = intel_8xx_sizes, | ||
1320 | .size_type = U8_APER_SIZE, | ||
1321 | .num_aperture_sizes = 7, | ||
1322 | .configure = intel_820_configure, | ||
1323 | .fetch_size = intel_8xx_fetch_size, | ||
1324 | .cleanup = intel_820_cleanup, | ||
1325 | .tlb_flush = intel_820_tlbflush, | ||
1326 | .mask_memory = agp_generic_mask_memory, | ||
1327 | .masks = intel_generic_masks, | ||
1328 | .agp_enable = agp_generic_enable, | ||
1329 | .cache_flush = global_cache_flush, | ||
1330 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1331 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1332 | .insert_memory = agp_generic_insert_memory, | ||
1333 | .remove_memory = agp_generic_remove_memory, | ||
1334 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1335 | .free_by_type = agp_generic_free_by_type, | ||
1336 | .agp_alloc_page = agp_generic_alloc_page, | ||
1337 | .agp_destroy_page = agp_generic_destroy_page, | ||
1338 | }; | ||
1339 | |||
1340 | static struct agp_bridge_driver intel_830mp_driver = { | ||
1341 | .owner = THIS_MODULE, | ||
1342 | .aperture_sizes = intel_830mp_sizes, | ||
1343 | .size_type = U8_APER_SIZE, | ||
1344 | .num_aperture_sizes = 4, | ||
1345 | .configure = intel_830mp_configure, | ||
1346 | .fetch_size = intel_8xx_fetch_size, | ||
1347 | .cleanup = intel_8xx_cleanup, | ||
1348 | .tlb_flush = intel_8xx_tlbflush, | ||
1349 | .mask_memory = agp_generic_mask_memory, | ||
1350 | .masks = intel_generic_masks, | ||
1351 | .agp_enable = agp_generic_enable, | ||
1352 | .cache_flush = global_cache_flush, | ||
1353 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1354 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1355 | .insert_memory = agp_generic_insert_memory, | ||
1356 | .remove_memory = agp_generic_remove_memory, | ||
1357 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1358 | .free_by_type = agp_generic_free_by_type, | ||
1359 | .agp_alloc_page = agp_generic_alloc_page, | ||
1360 | .agp_destroy_page = agp_generic_destroy_page, | ||
1361 | }; | ||
1362 | |||
1363 | static struct agp_bridge_driver intel_840_driver = { | ||
1364 | .owner = THIS_MODULE, | ||
1365 | .aperture_sizes = intel_8xx_sizes, | ||
1366 | .size_type = U8_APER_SIZE, | ||
1367 | .num_aperture_sizes = 7, | ||
1368 | .configure = intel_840_configure, | ||
1369 | .fetch_size = intel_8xx_fetch_size, | ||
1370 | .cleanup = intel_8xx_cleanup, | ||
1371 | .tlb_flush = intel_8xx_tlbflush, | ||
1372 | .mask_memory = agp_generic_mask_memory, | ||
1373 | .masks = intel_generic_masks, | ||
1374 | .agp_enable = agp_generic_enable, | ||
1375 | .cache_flush = global_cache_flush, | ||
1376 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1377 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1378 | .insert_memory = agp_generic_insert_memory, | ||
1379 | .remove_memory = agp_generic_remove_memory, | ||
1380 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1381 | .free_by_type = agp_generic_free_by_type, | ||
1382 | .agp_alloc_page = agp_generic_alloc_page, | ||
1383 | .agp_destroy_page = agp_generic_destroy_page, | ||
1384 | }; | ||
1385 | |||
1386 | static struct agp_bridge_driver intel_845_driver = { | ||
1387 | .owner = THIS_MODULE, | ||
1388 | .aperture_sizes = intel_8xx_sizes, | ||
1389 | .size_type = U8_APER_SIZE, | ||
1390 | .num_aperture_sizes = 7, | ||
1391 | .configure = intel_845_configure, | ||
1392 | .fetch_size = intel_8xx_fetch_size, | ||
1393 | .cleanup = intel_8xx_cleanup, | ||
1394 | .tlb_flush = intel_8xx_tlbflush, | ||
1395 | .mask_memory = agp_generic_mask_memory, | ||
1396 | .masks = intel_generic_masks, | ||
1397 | .agp_enable = agp_generic_enable, | ||
1398 | .cache_flush = global_cache_flush, | ||
1399 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1400 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1401 | .insert_memory = agp_generic_insert_memory, | ||
1402 | .remove_memory = agp_generic_remove_memory, | ||
1403 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1404 | .free_by_type = agp_generic_free_by_type, | ||
1405 | .agp_alloc_page = agp_generic_alloc_page, | ||
1406 | .agp_destroy_page = agp_generic_destroy_page, | ||
1407 | }; | ||
1408 | |||
1409 | static struct agp_bridge_driver intel_850_driver = { | ||
1410 | .owner = THIS_MODULE, | ||
1411 | .aperture_sizes = intel_8xx_sizes, | ||
1412 | .size_type = U8_APER_SIZE, | ||
1413 | .num_aperture_sizes = 7, | ||
1414 | .configure = intel_850_configure, | ||
1415 | .fetch_size = intel_8xx_fetch_size, | ||
1416 | .cleanup = intel_8xx_cleanup, | ||
1417 | .tlb_flush = intel_8xx_tlbflush, | ||
1418 | .mask_memory = agp_generic_mask_memory, | ||
1419 | .masks = intel_generic_masks, | ||
1420 | .agp_enable = agp_generic_enable, | ||
1421 | .cache_flush = global_cache_flush, | ||
1422 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1423 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1424 | .insert_memory = agp_generic_insert_memory, | ||
1425 | .remove_memory = agp_generic_remove_memory, | ||
1426 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1427 | .free_by_type = agp_generic_free_by_type, | ||
1428 | .agp_alloc_page = agp_generic_alloc_page, | ||
1429 | .agp_destroy_page = agp_generic_destroy_page, | ||
1430 | }; | ||
1431 | |||
1432 | static struct agp_bridge_driver intel_860_driver = { | ||
1433 | .owner = THIS_MODULE, | ||
1434 | .aperture_sizes = intel_8xx_sizes, | ||
1435 | .size_type = U8_APER_SIZE, | ||
1436 | .num_aperture_sizes = 7, | ||
1437 | .configure = intel_860_configure, | ||
1438 | .fetch_size = intel_8xx_fetch_size, | ||
1439 | .cleanup = intel_8xx_cleanup, | ||
1440 | .tlb_flush = intel_8xx_tlbflush, | ||
1441 | .mask_memory = agp_generic_mask_memory, | ||
1442 | .masks = intel_generic_masks, | ||
1443 | .agp_enable = agp_generic_enable, | ||
1444 | .cache_flush = global_cache_flush, | ||
1445 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1446 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1447 | .insert_memory = agp_generic_insert_memory, | ||
1448 | .remove_memory = agp_generic_remove_memory, | ||
1449 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1450 | .free_by_type = agp_generic_free_by_type, | ||
1451 | .agp_alloc_page = agp_generic_alloc_page, | ||
1452 | .agp_destroy_page = agp_generic_destroy_page, | ||
1453 | }; | ||
1454 | |||
1455 | static struct agp_bridge_driver intel_915_driver = { | ||
1456 | .owner = THIS_MODULE, | ||
1457 | .aperture_sizes = intel_i830_sizes, | ||
1458 | .size_type = FIXED_APER_SIZE, | ||
1459 | .num_aperture_sizes = 3, | ||
1460 | .needs_scratch_page = TRUE, | ||
1461 | .configure = intel_i915_configure, | ||
1462 | .fetch_size = intel_i915_fetch_size, | ||
1463 | .cleanup = intel_i915_cleanup, | ||
1464 | .tlb_flush = intel_i810_tlbflush, | ||
1465 | .mask_memory = intel_i810_mask_memory, | ||
1466 | .masks = intel_i810_masks, | ||
1467 | .agp_enable = intel_i810_agp_enable, | ||
1468 | .cache_flush = global_cache_flush, | ||
1469 | .create_gatt_table = intel_i915_create_gatt_table, | ||
1470 | .free_gatt_table = intel_i830_free_gatt_table, | ||
1471 | .insert_memory = intel_i915_insert_entries, | ||
1472 | .remove_memory = intel_i915_remove_entries, | ||
1473 | .alloc_by_type = intel_i830_alloc_by_type, | ||
1474 | .free_by_type = intel_i810_free_by_type, | ||
1475 | .agp_alloc_page = agp_generic_alloc_page, | ||
1476 | .agp_destroy_page = agp_generic_destroy_page, | ||
1477 | }; | ||
1478 | |||
1479 | |||
1480 | static struct agp_bridge_driver intel_7505_driver = { | ||
1481 | .owner = THIS_MODULE, | ||
1482 | .aperture_sizes = intel_8xx_sizes, | ||
1483 | .size_type = U8_APER_SIZE, | ||
1484 | .num_aperture_sizes = 7, | ||
1485 | .configure = intel_7505_configure, | ||
1486 | .fetch_size = intel_8xx_fetch_size, | ||
1487 | .cleanup = intel_8xx_cleanup, | ||
1488 | .tlb_flush = intel_8xx_tlbflush, | ||
1489 | .mask_memory = agp_generic_mask_memory, | ||
1490 | .masks = intel_generic_masks, | ||
1491 | .agp_enable = agp_generic_enable, | ||
1492 | .cache_flush = global_cache_flush, | ||
1493 | .create_gatt_table = agp_generic_create_gatt_table, | ||
1494 | .free_gatt_table = agp_generic_free_gatt_table, | ||
1495 | .insert_memory = agp_generic_insert_memory, | ||
1496 | .remove_memory = agp_generic_remove_memory, | ||
1497 | .alloc_by_type = agp_generic_alloc_by_type, | ||
1498 | .free_by_type = agp_generic_free_by_type, | ||
1499 | .agp_alloc_page = agp_generic_alloc_page, | ||
1500 | .agp_destroy_page = agp_generic_destroy_page, | ||
1501 | }; | ||
1502 | |||
1503 | static int find_i810(u16 device) | ||
1504 | { | ||
1505 | struct pci_dev *i810_dev; | ||
1506 | |||
1507 | i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); | ||
1508 | if (!i810_dev) | ||
1509 | return 0; | ||
1510 | intel_i810_private.i810_dev = i810_dev; | ||
1511 | return 1; | ||
1512 | } | ||
1513 | |||
1514 | static int find_i830(u16 device) | ||
1515 | { | ||
1516 | struct pci_dev *i830_dev; | ||
1517 | |||
1518 | i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); | ||
1519 | if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) { | ||
1520 | i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1521 | device, i830_dev); | ||
1522 | } | ||
1523 | |||
1524 | if (!i830_dev) | ||
1525 | return 0; | ||
1526 | |||
1527 | intel_i830_private.i830_dev = i830_dev; | ||
1528 | return 1; | ||
1529 | } | ||
1530 | |||
1531 | static int __devinit agp_intel_probe(struct pci_dev *pdev, | ||
1532 | const struct pci_device_id *ent) | ||
1533 | { | ||
1534 | struct agp_bridge_data *bridge; | ||
1535 | char *name = "(unknown)"; | ||
1536 | u8 cap_ptr = 0; | ||
1537 | struct resource *r; | ||
1538 | |||
1539 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | ||
1540 | |||
1541 | bridge = agp_alloc_bridge(); | ||
1542 | if (!bridge) | ||
1543 | return -ENOMEM; | ||
1544 | |||
1545 | switch (pdev->device) { | ||
1546 | case PCI_DEVICE_ID_INTEL_82443LX_0: | ||
1547 | bridge->driver = &intel_generic_driver; | ||
1548 | name = "440LX"; | ||
1549 | break; | ||
1550 | case PCI_DEVICE_ID_INTEL_82443BX_0: | ||
1551 | bridge->driver = &intel_generic_driver; | ||
1552 | name = "440BX"; | ||
1553 | break; | ||
1554 | case PCI_DEVICE_ID_INTEL_82443GX_0: | ||
1555 | bridge->driver = &intel_generic_driver; | ||
1556 | name = "440GX"; | ||
1557 | break; | ||
1558 | case PCI_DEVICE_ID_INTEL_82810_MC1: | ||
1559 | name = "i810"; | ||
1560 | if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1)) | ||
1561 | goto fail; | ||
1562 | bridge->driver = &intel_810_driver; | ||
1563 | break; | ||
1564 | case PCI_DEVICE_ID_INTEL_82810_MC3: | ||
1565 | name = "i810 DC100"; | ||
1566 | if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3)) | ||
1567 | goto fail; | ||
1568 | bridge->driver = &intel_810_driver; | ||
1569 | break; | ||
1570 | case PCI_DEVICE_ID_INTEL_82810E_MC: | ||
1571 | name = "i810 E"; | ||
1572 | if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG)) | ||
1573 | goto fail; | ||
1574 | bridge->driver = &intel_810_driver; | ||
1575 | break; | ||
1576 | case PCI_DEVICE_ID_INTEL_82815_MC: | ||
1577 | /* | ||
1578 | * The i815 can operate either as an i810 style | ||
1579 | * integrated device, or as an AGP4X motherboard. | ||
1580 | */ | ||
1581 | if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC)) | ||
1582 | bridge->driver = &intel_810_driver; | ||
1583 | else | ||
1584 | bridge->driver = &intel_815_driver; | ||
1585 | name = "i815"; | ||
1586 | break; | ||
1587 | case PCI_DEVICE_ID_INTEL_82820_HB: | ||
1588 | case PCI_DEVICE_ID_INTEL_82820_UP_HB: | ||
1589 | bridge->driver = &intel_820_driver; | ||
1590 | name = "i820"; | ||
1591 | break; | ||
1592 | case PCI_DEVICE_ID_INTEL_82830_HB: | ||
1593 | if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) { | ||
1594 | bridge->driver = &intel_830_driver; | ||
1595 | } else { | ||
1596 | bridge->driver = &intel_830mp_driver; | ||
1597 | } | ||
1598 | name = "830M"; | ||
1599 | break; | ||
1600 | case PCI_DEVICE_ID_INTEL_82840_HB: | ||
1601 | bridge->driver = &intel_840_driver; | ||
1602 | name = "i840"; | ||
1603 | break; | ||
1604 | case PCI_DEVICE_ID_INTEL_82845_HB: | ||
1605 | bridge->driver = &intel_845_driver; | ||
1606 | name = "i845"; | ||
1607 | break; | ||
1608 | case PCI_DEVICE_ID_INTEL_82845G_HB: | ||
1609 | if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) { | ||
1610 | bridge->driver = &intel_830_driver; | ||
1611 | } else { | ||
1612 | bridge->driver = &intel_845_driver; | ||
1613 | } | ||
1614 | name = "845G"; | ||
1615 | break; | ||
1616 | case PCI_DEVICE_ID_INTEL_82850_HB: | ||
1617 | bridge->driver = &intel_850_driver; | ||
1618 | name = "i850"; | ||
1619 | break; | ||
1620 | case PCI_DEVICE_ID_INTEL_82855PM_HB: | ||
1621 | bridge->driver = &intel_845_driver; | ||
1622 | name = "855PM"; | ||
1623 | break; | ||
1624 | case PCI_DEVICE_ID_INTEL_82855GM_HB: | ||
1625 | if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) { | ||
1626 | bridge->driver = &intel_830_driver; | ||
1627 | name = "855"; | ||
1628 | } else { | ||
1629 | bridge->driver = &intel_845_driver; | ||
1630 | name = "855GM"; | ||
1631 | } | ||
1632 | break; | ||
1633 | case PCI_DEVICE_ID_INTEL_82860_HB: | ||
1634 | bridge->driver = &intel_860_driver; | ||
1635 | name = "i860"; | ||
1636 | break; | ||
1637 | case PCI_DEVICE_ID_INTEL_82865_HB: | ||
1638 | if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) { | ||
1639 | bridge->driver = &intel_830_driver; | ||
1640 | } else { | ||
1641 | bridge->driver = &intel_845_driver; | ||
1642 | } | ||
1643 | name = "865"; | ||
1644 | break; | ||
1645 | case PCI_DEVICE_ID_INTEL_82875_HB: | ||
1646 | bridge->driver = &intel_845_driver; | ||
1647 | name = "i875"; | ||
1648 | break; | ||
1649 | case PCI_DEVICE_ID_INTEL_82915G_HB: | ||
1650 | if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) { | ||
1651 | bridge->driver = &intel_915_driver; | ||
1652 | } else { | ||
1653 | bridge->driver = &intel_845_driver; | ||
1654 | } | ||
1655 | name = "915G"; | ||
1656 | break; | ||
1657 | case PCI_DEVICE_ID_INTEL_82915GM_HB: | ||
1658 | if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) { | ||
1659 | bridge->driver = &intel_915_driver; | ||
1660 | } else { | ||
1661 | bridge->driver = &intel_845_driver; | ||
1662 | } | ||
1663 | name = "915GM"; | ||
1664 | break; | ||
1665 | case PCI_DEVICE_ID_INTEL_7505_0: | ||
1666 | bridge->driver = &intel_7505_driver; | ||
1667 | name = "E7505"; | ||
1668 | break; | ||
1669 | case PCI_DEVICE_ID_INTEL_7205_0: | ||
1670 | bridge->driver = &intel_7505_driver; | ||
1671 | name = "E7205"; | ||
1672 | break; | ||
1673 | default: | ||
1674 | if (cap_ptr) | ||
1675 | printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n", | ||
1676 | pdev->device); | ||
1677 | agp_put_bridge(bridge); | ||
1678 | return -ENODEV; | ||
1679 | }; | ||
1680 | |||
1681 | bridge->dev = pdev; | ||
1682 | bridge->capndx = cap_ptr; | ||
1683 | |||
1684 | if (bridge->driver == &intel_810_driver) | ||
1685 | bridge->dev_private_data = &intel_i810_private; | ||
1686 | else if (bridge->driver == &intel_830_driver) | ||
1687 | bridge->dev_private_data = &intel_i830_private; | ||
1688 | |||
1689 | printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); | ||
1690 | |||
1691 | /* | ||
1692 | * The following fixes the case where the BIOS has "forgotten" to | ||
1693 | * provide an address range for the GART. | ||
1694 | * 20030610 - hamish@zot.org | ||
1695 | */ | ||
1696 | r = &pdev->resource[0]; | ||
1697 | if (!r->start && r->end) { | ||
1698 | if(pci_assign_resource(pdev, 0)) { | ||
1699 | printk(KERN_ERR PFX "could not assign resource 0\n"); | ||
1700 | agp_put_bridge(bridge); | ||
1701 | return -ENODEV; | ||
1702 | } | ||
1703 | } | ||
1704 | |||
1705 | /* | ||
1706 | * If the device has not been properly setup, the following will catch | ||
1707 | * the problem and should stop the system from crashing. | ||
1708 | * 20030610 - hamish@zot.org | ||
1709 | */ | ||
1710 | if (pci_enable_device(pdev)) { | ||
1711 | printk(KERN_ERR PFX "Unable to Enable PCI device\n"); | ||
1712 | agp_put_bridge(bridge); | ||
1713 | return -ENODEV; | ||
1714 | } | ||
1715 | |||
1716 | /* Fill in the mode register */ | ||
1717 | if (cap_ptr) { | ||
1718 | pci_read_config_dword(pdev, | ||
1719 | bridge->capndx+PCI_AGP_STATUS, | ||
1720 | &bridge->mode); | ||
1721 | } | ||
1722 | |||
1723 | pci_set_drvdata(pdev, bridge); | ||
1724 | return agp_add_bridge(bridge); | ||
1725 | |||
1726 | fail: | ||
1727 | printk(KERN_ERR PFX "Detected an Intel %s chipset, " | ||
1728 | "but could not find the secondary device.\n", name); | ||
1729 | agp_put_bridge(bridge); | ||
1730 | return -ENODEV; | ||
1731 | } | ||
1732 | |||
1733 | static void __devexit agp_intel_remove(struct pci_dev *pdev) | ||
1734 | { | ||
1735 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | ||
1736 | |||
1737 | agp_remove_bridge(bridge); | ||
1738 | |||
1739 | if (intel_i810_private.i810_dev) | ||
1740 | pci_dev_put(intel_i810_private.i810_dev); | ||
1741 | if (intel_i830_private.i830_dev) | ||
1742 | pci_dev_put(intel_i830_private.i830_dev); | ||
1743 | |||
1744 | agp_put_bridge(bridge); | ||
1745 | } | ||
1746 | |||
1747 | static int agp_intel_resume(struct pci_dev *pdev) | ||
1748 | { | ||
1749 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | ||
1750 | |||
1751 | pci_restore_state(pdev); | ||
1752 | |||
1753 | if (bridge->driver == &intel_generic_driver) | ||
1754 | intel_configure(); | ||
1755 | else if (bridge->driver == &intel_850_driver) | ||
1756 | intel_850_configure(); | ||
1757 | else if (bridge->driver == &intel_845_driver) | ||
1758 | intel_845_configure(); | ||
1759 | else if (bridge->driver == &intel_830mp_driver) | ||
1760 | intel_830mp_configure(); | ||
1761 | else if (bridge->driver == &intel_915_driver) | ||
1762 | intel_i915_configure(); | ||
1763 | else if (bridge->driver == &intel_830_driver) | ||
1764 | intel_i830_configure(); | ||
1765 | else if (bridge->driver == &intel_810_driver) | ||
1766 | intel_i810_configure(); | ||
1767 | |||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | static struct pci_device_id agp_intel_pci_table[] = { | ||
1772 | #define ID(x) \ | ||
1773 | { \ | ||
1774 | .class = (PCI_CLASS_BRIDGE_HOST << 8), \ | ||
1775 | .class_mask = ~0, \ | ||
1776 | .vendor = PCI_VENDOR_ID_INTEL, \ | ||
1777 | .device = x, \ | ||
1778 | .subvendor = PCI_ANY_ID, \ | ||
1779 | .subdevice = PCI_ANY_ID, \ | ||
1780 | } | ||
1781 | ID(PCI_DEVICE_ID_INTEL_82443LX_0), | ||
1782 | ID(PCI_DEVICE_ID_INTEL_82443BX_0), | ||
1783 | ID(PCI_DEVICE_ID_INTEL_82443GX_0), | ||
1784 | ID(PCI_DEVICE_ID_INTEL_82810_MC1), | ||
1785 | ID(PCI_DEVICE_ID_INTEL_82810_MC3), | ||
1786 | ID(PCI_DEVICE_ID_INTEL_82810E_MC), | ||
1787 | ID(PCI_DEVICE_ID_INTEL_82815_MC), | ||
1788 | ID(PCI_DEVICE_ID_INTEL_82820_HB), | ||
1789 | ID(PCI_DEVICE_ID_INTEL_82820_UP_HB), | ||
1790 | ID(PCI_DEVICE_ID_INTEL_82830_HB), | ||
1791 | ID(PCI_DEVICE_ID_INTEL_82840_HB), | ||
1792 | ID(PCI_DEVICE_ID_INTEL_82845_HB), | ||
1793 | ID(PCI_DEVICE_ID_INTEL_82845G_HB), | ||
1794 | ID(PCI_DEVICE_ID_INTEL_82850_HB), | ||
1795 | ID(PCI_DEVICE_ID_INTEL_82855PM_HB), | ||
1796 | ID(PCI_DEVICE_ID_INTEL_82855GM_HB), | ||
1797 | ID(PCI_DEVICE_ID_INTEL_82860_HB), | ||
1798 | ID(PCI_DEVICE_ID_INTEL_82865_HB), | ||
1799 | ID(PCI_DEVICE_ID_INTEL_82875_HB), | ||
1800 | ID(PCI_DEVICE_ID_INTEL_7505_0), | ||
1801 | ID(PCI_DEVICE_ID_INTEL_7205_0), | ||
1802 | ID(PCI_DEVICE_ID_INTEL_82915G_HB), | ||
1803 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), | ||
1804 | { } | ||
1805 | }; | ||
1806 | |||
1807 | MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); | ||
1808 | |||
1809 | static struct pci_driver agp_intel_pci_driver = { | ||
1810 | .name = "agpgart-intel", | ||
1811 | .id_table = agp_intel_pci_table, | ||
1812 | .probe = agp_intel_probe, | ||
1813 | .remove = __devexit_p(agp_intel_remove), | ||
1814 | .resume = agp_intel_resume, | ||
1815 | }; | ||
1816 | |||
1817 | static int __init agp_intel_init(void) | ||
1818 | { | ||
1819 | if (agp_off) | ||
1820 | return -EINVAL; | ||
1821 | return pci_register_driver(&agp_intel_pci_driver); | ||
1822 | } | ||
1823 | |||
1824 | static void __exit agp_intel_cleanup(void) | ||
1825 | { | ||
1826 | pci_unregister_driver(&agp_intel_pci_driver); | ||
1827 | } | ||
1828 | |||
1829 | module_init(agp_intel_init); | ||
1830 | module_exit(agp_intel_cleanup); | ||
1831 | |||
1832 | MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); | ||
1833 | MODULE_LICENSE("GPL and additional rights"); | ||