blob: a9fdbf9126caf58b919912529f5cea509cb09f43 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Intel AGPGART routines.
3 */
4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/module.h>
6#include <linux/pci.h>
7#include <linux/init.h>
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02008#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/pagemap.h>
10#include <linux/agp_backend.h>
11#include "agp.h"
12
Eric Anholt65c25aa2006-09-06 11:57:18 -040013#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
14#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
15#define PCI_DEVICE_ID_INTEL_82965G_1_HB 0x2980
16#define PCI_DEVICE_ID_INTEL_82965G_1_IG 0x2982
17#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
18#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
19#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
20#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
Wang Zhenyu4598af32007-04-09 08:51:36 +080021#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
22#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
Eric Anholt65c25aa2006-09-06 11:57:18 -040023
24#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
25 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
26 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
Wang Zhenyu4598af32007-04-09 08:51:36 +080027 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
28 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040029
30
Thomas Hellstroma030ce42007-01-23 10:33:43 +010031extern int agp_memory_reserved;
32
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034/* Intel 815 register */
35#define INTEL_815_APCONT 0x51
36#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
37
38/* Intel i820 registers */
39#define INTEL_I820_RDCR 0x51
40#define INTEL_I820_ERRSTS 0xc8
41
42/* Intel i840 registers */
43#define INTEL_I840_MCHCFG 0x50
44#define INTEL_I840_ERRSTS 0xc8
45
46/* Intel i850 registers */
47#define INTEL_I850_MCHCFG 0x50
48#define INTEL_I850_ERRSTS 0xc8
49
50/* intel 915G registers */
51#define I915_GMADDR 0x18
52#define I915_MMADDR 0x10
53#define I915_PTEADDR 0x1C
54#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
55#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
56
Eric Anholt65c25aa2006-09-06 11:57:18 -040057/* Intel 965G registers */
58#define I965_MSAC 0x62
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60/* Intel 7505 registers */
61#define INTEL_I7505_APSIZE 0x74
62#define INTEL_I7505_NCAPID 0x60
63#define INTEL_I7505_NISTAT 0x6c
64#define INTEL_I7505_ATTBASE 0x78
65#define INTEL_I7505_ERRSTS 0x42
66#define INTEL_I7505_AGPCTRL 0x70
67#define INTEL_I7505_MCHCFG 0x50
68
Dave Jonese5524f32007-02-22 18:41:28 -050069static const struct aper_size_info_fixed intel_i810_sizes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -070070{
71 {64, 16384, 4},
72 /* The 32M mode still requires a 64k gatt */
73 {32, 8192, 4}
74};
75
76#define AGP_DCACHE_MEMORY 1
77#define AGP_PHYS_MEMORY 2
Thomas Hellstroma030ce42007-01-23 10:33:43 +010078#define INTEL_AGP_CACHED_MEMORY 3
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80static struct gatt_mask intel_i810_masks[] =
81{
82 {.mask = I810_PTE_VALID, .type = 0},
83 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
Thomas Hellstroma030ce42007-01-23 10:33:43 +010084 {.mask = I810_PTE_VALID, .type = 0},
85 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
86 .type = INTEL_AGP_CACHED_MEMORY}
Linus Torvalds1da177e2005-04-16 15:20:36 -070087};
88
89static struct _intel_i810_private {
90 struct pci_dev *i810_dev; /* device one */
91 volatile u8 __iomem *registers;
92 int num_dcache_entries;
93} intel_i810_private;
94
95static int intel_i810_fetch_size(void)
96{
97 u32 smram_miscc;
98 struct aper_size_info_fixed *values;
99
100 pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
101 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
102
103 if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
104 printk(KERN_WARNING PFX "i810 is disabled\n");
105 return 0;
106 }
107 if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
108 agp_bridge->previous_size =
109 agp_bridge->current_size = (void *) (values + 1);
110 agp_bridge->aperture_size_idx = 1;
111 return values[1].size;
112 } else {
113 agp_bridge->previous_size =
114 agp_bridge->current_size = (void *) (values);
115 agp_bridge->aperture_size_idx = 0;
116 return values[0].size;
117 }
118
119 return 0;
120}
121
122static int intel_i810_configure(void)
123{
124 struct aper_size_info_fixed *current_size;
125 u32 temp;
126 int i;
127
128 current_size = A_SIZE_FIX(agp_bridge->current_size);
129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 if (!intel_i810_private.registers) {
Dave Jonese4ac5e42007-02-04 17:37:42 -0500131 pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
132 temp &= 0xfff80000;
133
134 intel_i810_private.registers = ioremap(temp, 128 * 4096);
135 if (!intel_i810_private.registers) {
136 printk(KERN_ERR PFX "Unable to remap memory.\n");
137 return -ENOMEM;
138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 }
140
141 if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
142 & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
143 /* This will need to be dynamically assigned */
144 printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
145 intel_i810_private.num_dcache_entries = 1024;
146 }
147 pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
148 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
149 writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
150 readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
151
152 if (agp_bridge->driver->needs_scratch_page) {
153 for (i = 0; i < current_size->num_entries; i++) {
154 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
155 readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
156 }
157 }
158 global_cache_flush();
159 return 0;
160}
161
162static void intel_i810_cleanup(void)
163{
164 writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
165 readl(intel_i810_private.registers); /* PCI Posting. */
166 iounmap(intel_i810_private.registers);
167}
168
169static void intel_i810_tlbflush(struct agp_memory *mem)
170{
171 return;
172}
173
174static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
175{
176 return;
177}
178
179/* Exists to support ARGB cursors */
180static void *i8xx_alloc_pages(void)
181{
182 struct page * page;
183
Linus Torvalds66c669b2006-11-22 14:55:29 -0800184 page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 if (page == NULL)
186 return NULL;
187
188 if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
189 global_flush_tlb();
190 __free_page(page);
191 return NULL;
192 }
193 global_flush_tlb();
194 get_page(page);
195 SetPageLocked(page);
196 atomic_inc(&agp_bridge->current_memory_agp);
197 return page_address(page);
198}
199
200static void i8xx_destroy_pages(void *addr)
201{
202 struct page *page;
203
204 if (addr == NULL)
205 return;
206
207 page = virt_to_page(addr);
208 change_page_attr(page, 4, PAGE_KERNEL);
209 global_flush_tlb();
210 put_page(page);
211 unlock_page(page);
212 free_pages((unsigned long)addr, 2);
213 atomic_dec(&agp_bridge->current_memory_agp);
214}
215
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100216static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
217 int type)
218{
219 if (type < AGP_USER_TYPES)
220 return type;
221 else if (type == AGP_USER_CACHED_MEMORY)
222 return INTEL_AGP_CACHED_MEMORY;
223 else
224 return 0;
225}
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
228 int type)
229{
230 int i, j, num_entries;
231 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100232 int ret = -EINVAL;
233 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100235 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100236 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100237
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 temp = agp_bridge->current_size;
239 num_entries = A_SIZE_FIX(temp)->num_entries;
240
Dave Jones6a92a4e2006-02-28 00:54:25 -0500241 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100242 goto out_err;
243
Dave Jones6a92a4e2006-02-28 00:54:25 -0500244
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100246 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
247 ret = -EBUSY;
248 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 }
251
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100252 if (type != mem->type)
253 goto out_err;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100254
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100255 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
256
257 switch (mask_type) {
258 case AGP_DCACHE_MEMORY:
259 if (!mem->is_flushed)
260 global_cache_flush();
261 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
262 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
263 intel_i810_private.registers+I810_PTE_BASE+(i*4));
264 }
265 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
266 break;
267 case AGP_PHYS_MEMORY:
268 case AGP_NORMAL_MEMORY:
269 if (!mem->is_flushed)
270 global_cache_flush();
271 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
272 writel(agp_bridge->driver->mask_memory(agp_bridge,
273 mem->memory[i],
274 mask_type),
275 intel_i810_private.registers+I810_PTE_BASE+(j*4));
276 }
277 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
278 break;
279 default:
280 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
283 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100284out:
285 ret = 0;
286out_err:
287 mem->is_flushed = 1;
288 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
290
291static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
292 int type)
293{
294 int i;
295
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100296 if (mem->page_count == 0)
297 return 0;
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
300 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100302 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 agp_bridge->driver->tlb_flush(mem);
305 return 0;
306}
307
308/*
309 * The i810/i830 requires a physical address to program its mouse
310 * pointer into hardware.
311 * However the Xserver still writes to it through the agp aperture.
312 */
313static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
314{
315 struct agp_memory *new;
316 void *addr;
317
318 if (pg_count != 1 && pg_count != 4)
319 return NULL;
320
321 switch (pg_count) {
322 case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
Alan Hourihane88d51962005-11-06 23:35:34 -0800323 global_flush_tlb();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 break;
325 case 4:
326 /* kludge to get 4 physical pages for ARGB cursor */
327 addr = i8xx_alloc_pages();
328 break;
329 default:
330 return NULL;
331 }
332
333 if (addr == NULL)
334 return NULL;
335
336 new = agp_create_memory(pg_count);
337 if (new == NULL)
338 return NULL;
339
Keir Fraser07eee782005-03-30 13:17:04 -0800340 new->memory[0] = virt_to_gart(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 if (pg_count == 4) {
342 /* kludge to get 4 physical pages for ARGB cursor */
343 new->memory[1] = new->memory[0] + PAGE_SIZE;
344 new->memory[2] = new->memory[1] + PAGE_SIZE;
345 new->memory[3] = new->memory[2] + PAGE_SIZE;
346 }
347 new->page_count = pg_count;
348 new->num_scratch_pages = pg_count;
349 new->type = AGP_PHYS_MEMORY;
350 new->physical = new->memory[0];
351 return new;
352}
353
354static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
355{
356 struct agp_memory *new;
357
358 if (type == AGP_DCACHE_MEMORY) {
359 if (pg_count != intel_i810_private.num_dcache_entries)
360 return NULL;
361
362 new = agp_create_memory(1);
363 if (new == NULL)
364 return NULL;
365
366 new->type = AGP_DCACHE_MEMORY;
367 new->page_count = pg_count;
368 new->num_scratch_pages = 0;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100369 agp_free_page_array(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return new;
371 }
372 if (type == AGP_PHYS_MEMORY)
373 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 return NULL;
375}
376
377static void intel_i810_free_by_type(struct agp_memory *curr)
378{
379 agp_free_key(curr->key);
Dave Jones6a92a4e2006-02-28 00:54:25 -0500380 if (curr->type == AGP_PHYS_MEMORY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 if (curr->page_count == 4)
Keir Fraser07eee782005-03-30 13:17:04 -0800382 i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
Alan Hourihane88d51962005-11-06 23:35:34 -0800383 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 agp_bridge->driver->agp_destroy_page(
Keir Fraser07eee782005-03-30 13:17:04 -0800385 gart_to_virt(curr->memory[0]));
Alan Hourihane88d51962005-11-06 23:35:34 -0800386 global_flush_tlb();
387 }
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100388 agp_free_page_array(curr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 }
390 kfree(curr);
391}
392
393static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
394 unsigned long addr, int type)
395{
396 /* Type checking must be done elsewhere */
397 return addr | bridge->driver->masks[type].mask;
398}
399
400static struct aper_size_info_fixed intel_i830_sizes[] =
401{
402 {128, 32768, 5},
403 /* The 64M mode still requires a 128k gatt */
404 {64, 16384, 5},
405 {256, 65536, 6},
Eric Anholt65c25aa2006-09-06 11:57:18 -0400406 {512, 131072, 7},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407};
408
409static struct _intel_i830_private {
410 struct pci_dev *i830_dev; /* device one */
411 volatile u8 __iomem *registers;
412 volatile u32 __iomem *gtt; /* I915G */
Eric Anholtc41e0de2006-12-19 12:57:24 -0800413 /* gtt_entries is the number of gtt entries that are already mapped
414 * to stolen memory. Stolen memory is larger than the memory mapped
415 * through gtt_entries, as it includes some reserved space for the BIOS
416 * popup and for the GTT.
417 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 int gtt_entries;
419} intel_i830_private;
420
421static void intel_i830_init_gtt_entries(void)
422{
423 u16 gmch_ctrl;
424 int gtt_entries;
425 u8 rdct;
426 int local = 0;
427 static const int ddt[4] = { 0, 16, 32, 64 };
Eric Anholtc41e0de2006-12-19 12:57:24 -0800428 int size; /* reserved space (in kb) at the top of stolen memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
431
Eric Anholtc41e0de2006-12-19 12:57:24 -0800432 if (IS_I965) {
433 u32 pgetbl_ctl;
434
435 pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
436 &pgetbl_ctl);
437 /* The 965 has a field telling us the size of the GTT,
438 * which may be larger than what is necessary to map the
439 * aperture.
440 */
441 switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
442 case I965_PGETBL_SIZE_128KB:
443 size = 128;
444 break;
445 case I965_PGETBL_SIZE_256KB:
446 size = 256;
447 break;
448 case I965_PGETBL_SIZE_512KB:
449 size = 512;
450 break;
451 default:
452 printk(KERN_INFO PFX "Unknown page table size, "
453 "assuming 512KB\n");
454 size = 512;
455 }
456 size += 4; /* add in BIOS popup space */
457 } else {
458 /* On previous hardware, the GTT size was just what was
459 * required to map the aperture.
460 */
461 size = agp_bridge->driver->fetch_size() + 4;
462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
465 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
466 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
467 case I830_GMCH_GMS_STOLEN_512:
468 gtt_entries = KB(512) - KB(size);
469 break;
470 case I830_GMCH_GMS_STOLEN_1024:
471 gtt_entries = MB(1) - KB(size);
472 break;
473 case I830_GMCH_GMS_STOLEN_8192:
474 gtt_entries = MB(8) - KB(size);
475 break;
476 case I830_GMCH_GMS_LOCAL:
477 rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
478 gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
479 MB(ddt[I830_RDRAM_DDT(rdct)]);
480 local = 1;
481 break;
482 default:
483 gtt_entries = 0;
484 break;
485 }
486 } else {
487 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
488 case I855_GMCH_GMS_STOLEN_1M:
489 gtt_entries = MB(1) - KB(size);
490 break;
491 case I855_GMCH_GMS_STOLEN_4M:
492 gtt_entries = MB(4) - KB(size);
493 break;
494 case I855_GMCH_GMS_STOLEN_8M:
495 gtt_entries = MB(8) - KB(size);
496 break;
497 case I855_GMCH_GMS_STOLEN_16M:
498 gtt_entries = MB(16) - KB(size);
499 break;
500 case I855_GMCH_GMS_STOLEN_32M:
501 gtt_entries = MB(32) - KB(size);
502 break;
503 case I915_GMCH_GMS_STOLEN_48M:
504 /* Check it's really I915G */
505 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
Alan Hourihaned0de98f2005-05-31 19:50:49 +0100506 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +0000507 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
Eric Anholt65c25aa2006-09-06 11:57:18 -0400508 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 gtt_entries = MB(48) - KB(size);
510 else
511 gtt_entries = 0;
512 break;
513 case I915_GMCH_GMS_STOLEN_64M:
514 /* Check it's really I915G */
515 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
Alan Hourihaned0de98f2005-05-31 19:50:49 +0100516 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +0000517 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
Eric Anholt65c25aa2006-09-06 11:57:18 -0400518 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 gtt_entries = MB(64) - KB(size);
520 else
521 gtt_entries = 0;
522 default:
523 gtt_entries = 0;
524 break;
525 }
526 }
527 if (gtt_entries > 0)
528 printk(KERN_INFO PFX "Detected %dK %s memory.\n",
529 gtt_entries / KB(1), local ? "local" : "stolen");
530 else
531 printk(KERN_INFO PFX
532 "No pre-allocated video memory detected.\n");
533 gtt_entries /= KB(4);
534
535 intel_i830_private.gtt_entries = gtt_entries;
536}
537
538/* The intel i830 automatically initializes the agp aperture during POST.
539 * Use the memory already set aside for in the GTT.
540 */
541static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
542{
543 int page_order;
544 struct aper_size_info_fixed *size;
545 int num_entries;
546 u32 temp;
547
548 size = agp_bridge->current_size;
549 page_order = size->page_order;
550 num_entries = size->num_entries;
551 agp_bridge->gatt_table_real = NULL;
552
553 pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
554 temp &= 0xfff80000;
555
556 intel_i830_private.registers = ioremap(temp,128 * 4096);
557 if (!intel_i830_private.registers)
558 return -ENOMEM;
559
560 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
561 global_cache_flush(); /* FIXME: ?? */
562
563 /* we have to call this as early as possible after the MMIO base address is known */
564 intel_i830_init_gtt_entries();
565
566 agp_bridge->gatt_table = NULL;
567
568 agp_bridge->gatt_bus_addr = temp;
569
570 return 0;
571}
572
573/* Return the gatt table to a sane state. Use the top of stolen
574 * memory for the GTT.
575 */
576static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
577{
578 return 0;
579}
580
581static int intel_i830_fetch_size(void)
582{
583 u16 gmch_ctrl;
584 struct aper_size_info_fixed *values;
585
586 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
587
588 if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
589 agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
590 /* 855GM/852GM/865G has 128MB aperture size */
591 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
592 agp_bridge->aperture_size_idx = 0;
593 return values[0].size;
594 }
595
596 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
597
598 if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
599 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
600 agp_bridge->aperture_size_idx = 0;
601 return values[0].size;
602 } else {
603 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
604 agp_bridge->aperture_size_idx = 1;
605 return values[1].size;
606 }
607
608 return 0;
609}
610
611static int intel_i830_configure(void)
612{
613 struct aper_size_info_fixed *current_size;
614 u32 temp;
615 u16 gmch_ctrl;
616 int i;
617
618 current_size = A_SIZE_FIX(agp_bridge->current_size);
619
620 pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
621 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
622
623 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
624 gmch_ctrl |= I830_GMCH_ENABLED;
625 pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
626
627 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
628 readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
629
630 if (agp_bridge->driver->needs_scratch_page) {
631 for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
632 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
633 readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
634 }
635 }
636
637 global_cache_flush();
638 return 0;
639}
640
641static void intel_i830_cleanup(void)
642{
643 iounmap(intel_i830_private.registers);
644}
645
646static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
647{
648 int i,j,num_entries;
649 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100650 int ret = -EINVAL;
651 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100653 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100654 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 temp = agp_bridge->current_size;
657 num_entries = A_SIZE_FIX(temp)->num_entries;
658
659 if (pg_start < intel_i830_private.gtt_entries) {
660 printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
661 pg_start,intel_i830_private.gtt_entries);
662
663 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100664 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 }
666
667 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100668 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
670 /* The i830 can't check the GTT for entries since its read only,
671 * depend on the caller to make the correct offset decisions.
672 */
673
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100674 if (type != mem->type)
675 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100677 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
678
679 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
680 mask_type != INTEL_AGP_CACHED_MEMORY)
681 goto out_err;
682
683 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100684 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
686 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
687 writel(agp_bridge->driver->mask_memory(agp_bridge,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100688 mem->memory[i], mask_type),
689 intel_i830_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100691 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100693
694out:
695 ret = 0;
696out_err:
697 mem->is_flushed = 1;
698 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699}
700
701static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
702 int type)
703{
704 int i;
705
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100706 if (mem->page_count == 0)
707 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 if (pg_start < intel_i830_private.gtt_entries) {
710 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
711 return -EINVAL;
712 }
713
714 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
715 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100717 readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 agp_bridge->driver->tlb_flush(mem);
720 return 0;
721}
722
723static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
724{
725 if (type == AGP_PHYS_MEMORY)
726 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 /* always return NULL for other allocation types for now */
728 return NULL;
729}
730
731static int intel_i915_configure(void)
732{
733 struct aper_size_info_fixed *current_size;
734 u32 temp;
735 u16 gmch_ctrl;
736 int i;
737
738 current_size = A_SIZE_FIX(agp_bridge->current_size);
739
740 pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
741
742 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
743
744 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
745 gmch_ctrl |= I830_GMCH_ENABLED;
746 pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
747
748 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
749 readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
750
751 if (agp_bridge->driver->needs_scratch_page) {
752 for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
753 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
754 readl(intel_i830_private.gtt+i); /* PCI Posting. */
755 }
756 }
757
758 global_cache_flush();
759 return 0;
760}
761
762static void intel_i915_cleanup(void)
763{
764 iounmap(intel_i830_private.gtt);
765 iounmap(intel_i830_private.registers);
766}
767
768static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
769 int type)
770{
771 int i,j,num_entries;
772 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100773 int ret = -EINVAL;
774 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100776 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100777 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 temp = agp_bridge->current_size;
780 num_entries = A_SIZE_FIX(temp)->num_entries;
781
782 if (pg_start < intel_i830_private.gtt_entries) {
783 printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
784 pg_start,intel_i830_private.gtt_entries);
785
786 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100787 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 }
789
790 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100791 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100793 /* The i915 can't check the GTT for entries since its read only,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 * depend on the caller to make the correct offset decisions.
795 */
796
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100797 if (type != mem->type)
798 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100800 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
801
802 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
803 mask_type != INTEL_AGP_CACHED_MEMORY)
804 goto out_err;
805
806 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100807 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
809 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
810 writel(agp_bridge->driver->mask_memory(agp_bridge,
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100811 mem->memory[i], mask_type), intel_i830_private.gtt+j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
813
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100814 readl(intel_i830_private.gtt+j-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100816
817 out:
818 ret = 0;
819 out_err:
820 mem->is_flushed = 1;
821 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822}
823
824static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
825 int type)
826{
827 int i;
828
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100829 if (mem->page_count == 0)
830 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 if (pg_start < intel_i830_private.gtt_entries) {
833 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
834 return -EINVAL;
835 }
836
837 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
838 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100840 readl(intel_i830_private.gtt+i-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 agp_bridge->driver->tlb_flush(mem);
843 return 0;
844}
845
Eric Anholtc41e0de2006-12-19 12:57:24 -0800846/* Return the aperture size by just checking the resource length. The effect
847 * described in the spec of the MSAC registers is just changing of the
848 * resource size.
849 */
850static int intel_i9xx_fetch_size(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +0200852 int num_sizes = ARRAY_SIZE(intel_i830_sizes);
Eric Anholtc41e0de2006-12-19 12:57:24 -0800853 int aper_size; /* size in megabytes */
854 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Eric Anholtc41e0de2006-12-19 12:57:24 -0800856 aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Eric Anholtc41e0de2006-12-19 12:57:24 -0800858 for (i = 0; i < num_sizes; i++) {
859 if (aper_size == intel_i830_sizes[i].size) {
860 agp_bridge->current_size = intel_i830_sizes + i;
861 agp_bridge->previous_size = agp_bridge->current_size;
862 return aper_size;
863 }
864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Eric Anholtc41e0de2006-12-19 12:57:24 -0800866 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867}
868
869/* The intel i915 automatically initializes the agp aperture during POST.
870 * Use the memory already set aside for in the GTT.
871 */
872static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
873{
874 int page_order;
875 struct aper_size_info_fixed *size;
876 int num_entries;
877 u32 temp, temp2;
878
879 size = agp_bridge->current_size;
880 page_order = size->page_order;
881 num_entries = size->num_entries;
882 agp_bridge->gatt_table_real = NULL;
883
884 pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
885 pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
886
887 intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
888 if (!intel_i830_private.gtt)
889 return -ENOMEM;
890
891 temp &= 0xfff80000;
892
893 intel_i830_private.registers = ioremap(temp,128 * 4096);
894 if (!intel_i830_private.registers)
895 return -ENOMEM;
896
897 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
898 global_cache_flush(); /* FIXME: ? */
899
900 /* we have to call this as early as possible after the MMIO base address is known */
901 intel_i830_init_gtt_entries();
902
903 agp_bridge->gatt_table = NULL;
904
905 agp_bridge->gatt_bus_addr = temp;
906
907 return 0;
908}
Linus Torvalds7d915a32006-11-22 09:37:54 -0800909
910/*
911 * The i965 supports 36-bit physical addresses, but to keep
912 * the format of the GTT the same, the bits that don't fit
913 * in a 32-bit word are shifted down to bits 4..7.
914 *
915 * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
916 * is always zero on 32-bit architectures, so no need to make
917 * this conditional.
918 */
919static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
920 unsigned long addr, int type)
921{
922 /* Shift high bits down */
923 addr |= (addr >> 28) & 0xf0;
924
925 /* Type checking must be done elsewhere */
926 return addr | bridge->driver->masks[type].mask;
927}
928
Eric Anholt65c25aa2006-09-06 11:57:18 -0400929/* The intel i965 automatically initializes the agp aperture during POST.
Eric Anholtc41e0de2006-12-19 12:57:24 -0800930 * Use the memory already set aside for in the GTT.
931 */
Eric Anholt65c25aa2006-09-06 11:57:18 -0400932static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
933{
934 int page_order;
935 struct aper_size_info_fixed *size;
936 int num_entries;
937 u32 temp;
938
939 size = agp_bridge->current_size;
940 page_order = size->page_order;
941 num_entries = size->num_entries;
942 agp_bridge->gatt_table_real = NULL;
943
944 pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
945
946 temp &= 0xfff00000;
947 intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
948
949 if (!intel_i830_private.gtt)
950 return -ENOMEM;
951
952
953 intel_i830_private.registers = ioremap(temp,128 * 4096);
954 if (!intel_i830_private.registers)
955 return -ENOMEM;
956
957 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
958 global_cache_flush(); /* FIXME: ? */
959
960 /* we have to call this as early as possible after the MMIO base address is known */
961 intel_i830_init_gtt_entries();
962
963 agp_bridge->gatt_table = NULL;
964
965 agp_bridge->gatt_bus_addr = temp;
966
967 return 0;
968}
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
971static int intel_fetch_size(void)
972{
973 int i;
974 u16 temp;
975 struct aper_size_info_16 *values;
976
977 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
978 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
979
980 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
981 if (temp == values[i].size_value) {
982 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
983 agp_bridge->aperture_size_idx = i;
984 return values[i].size;
985 }
986 }
987
988 return 0;
989}
990
991static int __intel_8xx_fetch_size(u8 temp)
992{
993 int i;
994 struct aper_size_info_8 *values;
995
996 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
997
998 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
999 if (temp == values[i].size_value) {
1000 agp_bridge->previous_size =
1001 agp_bridge->current_size = (void *) (values + i);
1002 agp_bridge->aperture_size_idx = i;
1003 return values[i].size;
1004 }
1005 }
1006 return 0;
1007}
1008
1009static int intel_8xx_fetch_size(void)
1010{
1011 u8 temp;
1012
1013 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1014 return __intel_8xx_fetch_size(temp);
1015}
1016
1017static int intel_815_fetch_size(void)
1018{
1019 u8 temp;
1020
1021 /* Intel 815 chipsets have a _weird_ APSIZE register with only
1022 * one non-reserved bit, so mask the others out ... */
1023 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1024 temp &= (1 << 3);
1025
1026 return __intel_8xx_fetch_size(temp);
1027}
1028
1029static void intel_tlbflush(struct agp_memory *mem)
1030{
1031 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
1032 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1033}
1034
1035
1036static void intel_8xx_tlbflush(struct agp_memory *mem)
1037{
1038 u32 temp;
1039 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1040 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
1041 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1042 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
1043}
1044
1045
1046static void intel_cleanup(void)
1047{
1048 u16 temp;
1049 struct aper_size_info_16 *previous_size;
1050
1051 previous_size = A_SIZE_16(agp_bridge->previous_size);
1052 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1053 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1054 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1055}
1056
1057
1058static void intel_8xx_cleanup(void)
1059{
1060 u16 temp;
1061 struct aper_size_info_8 *previous_size;
1062
1063 previous_size = A_SIZE_8(agp_bridge->previous_size);
1064 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1065 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1066 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1067}
1068
1069
1070static int intel_configure(void)
1071{
1072 u32 temp;
1073 u16 temp2;
1074 struct aper_size_info_16 *current_size;
1075
1076 current_size = A_SIZE_16(agp_bridge->current_size);
1077
1078 /* aperture size */
1079 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1080
1081 /* address to map to */
1082 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1083 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1084
1085 /* attbase - aperture base */
1086 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1087
1088 /* agpctrl */
1089 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1090
1091 /* paccfg/nbxcfg */
1092 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1093 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
1094 (temp2 & ~(1 << 10)) | (1 << 9));
1095 /* clear any possible error conditions */
1096 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
1097 return 0;
1098}
1099
1100static int intel_815_configure(void)
1101{
1102 u32 temp, addr;
1103 u8 temp2;
1104 struct aper_size_info_8 *current_size;
1105
1106 /* attbase - aperture base */
1107 /* the Intel 815 chipset spec. says that bits 29-31 in the
1108 * ATTBASE register are reserved -> try not to write them */
1109 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
1110 printk (KERN_EMERG PFX "gatt bus addr too high");
1111 return -EINVAL;
1112 }
1113
1114 current_size = A_SIZE_8(agp_bridge->current_size);
1115
1116 /* aperture size */
1117 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1118 current_size->size_value);
1119
1120 /* address to map to */
1121 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1122 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1123
1124 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
1125 addr &= INTEL_815_ATTBASE_MASK;
1126 addr |= agp_bridge->gatt_bus_addr;
1127 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
1128
1129 /* agpctrl */
1130 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1131
1132 /* apcont */
1133 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
1134 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
1135
1136 /* clear any possible error conditions */
1137 /* Oddness : this chipset seems to have no ERRSTS register ! */
1138 return 0;
1139}
1140
1141static void intel_820_tlbflush(struct agp_memory *mem)
1142{
1143 return;
1144}
1145
1146static void intel_820_cleanup(void)
1147{
1148 u8 temp;
1149 struct aper_size_info_8 *previous_size;
1150
1151 previous_size = A_SIZE_8(agp_bridge->previous_size);
1152 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
1153 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
1154 temp & ~(1 << 1));
1155 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1156 previous_size->size_value);
1157}
1158
1159
1160static int intel_820_configure(void)
1161{
1162 u32 temp;
1163 u8 temp2;
1164 struct aper_size_info_8 *current_size;
1165
1166 current_size = A_SIZE_8(agp_bridge->current_size);
1167
1168 /* aperture size */
1169 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1170
1171 /* address to map to */
1172 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1173 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1174
1175 /* attbase - aperture base */
1176 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1177
1178 /* agpctrl */
1179 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1180
1181 /* global enable aperture access */
1182 /* This flag is not accessed through MCHCFG register as in */
1183 /* i850 chipset. */
1184 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
1185 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
1186 /* clear any possible AGP-related error conditions */
1187 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
1188 return 0;
1189}
1190
1191static int intel_840_configure(void)
1192{
1193 u32 temp;
1194 u16 temp2;
1195 struct aper_size_info_8 *current_size;
1196
1197 current_size = A_SIZE_8(agp_bridge->current_size);
1198
1199 /* aperture size */
1200 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1201
1202 /* address to map to */
1203 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1204 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1205
1206 /* attbase - aperture base */
1207 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1208
1209 /* agpctrl */
1210 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1211
1212 /* mcgcfg */
1213 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
1214 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
1215 /* clear any possible error conditions */
1216 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
1217 return 0;
1218}
1219
1220static int intel_845_configure(void)
1221{
1222 u32 temp;
1223 u8 temp2;
1224 struct aper_size_info_8 *current_size;
1225
1226 current_size = A_SIZE_8(agp_bridge->current_size);
1227
1228 /* aperture size */
1229 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1230
Matthew Garrettb0825482005-07-29 14:03:39 -07001231 if (agp_bridge->apbase_config != 0) {
1232 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1233 agp_bridge->apbase_config);
1234 } else {
1235 /* address to map to */
1236 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1237 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1238 agp_bridge->apbase_config = temp;
1239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 /* attbase - aperture base */
1242 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1243
1244 /* agpctrl */
1245 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1246
1247 /* agpm */
1248 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
1249 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1250 /* clear any possible error conditions */
1251 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
1252 return 0;
1253}
1254
1255static int intel_850_configure(void)
1256{
1257 u32 temp;
1258 u16 temp2;
1259 struct aper_size_info_8 *current_size;
1260
1261 current_size = A_SIZE_8(agp_bridge->current_size);
1262
1263 /* aperture size */
1264 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1265
1266 /* address to map to */
1267 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1268 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1269
1270 /* attbase - aperture base */
1271 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1272
1273 /* agpctrl */
1274 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1275
1276 /* mcgcfg */
1277 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
1278 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
1279 /* clear any possible AGP-related error conditions */
1280 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
1281 return 0;
1282}
1283
1284static int intel_860_configure(void)
1285{
1286 u32 temp;
1287 u16 temp2;
1288 struct aper_size_info_8 *current_size;
1289
1290 current_size = A_SIZE_8(agp_bridge->current_size);
1291
1292 /* aperture size */
1293 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1294
1295 /* address to map to */
1296 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1297 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1298
1299 /* attbase - aperture base */
1300 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1301
1302 /* agpctrl */
1303 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1304
1305 /* mcgcfg */
1306 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
1307 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
1308 /* clear any possible AGP-related error conditions */
1309 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
1310 return 0;
1311}
1312
1313static int intel_830mp_configure(void)
1314{
1315 u32 temp;
1316 u16 temp2;
1317 struct aper_size_info_8 *current_size;
1318
1319 current_size = A_SIZE_8(agp_bridge->current_size);
1320
1321 /* aperture size */
1322 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1323
1324 /* address to map to */
1325 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1326 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1327
1328 /* attbase - aperture base */
1329 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1330
1331 /* agpctrl */
1332 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1333
1334 /* gmch */
1335 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1336 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
1337 /* clear any possible AGP-related error conditions */
1338 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
1339 return 0;
1340}
1341
1342static int intel_7505_configure(void)
1343{
1344 u32 temp;
1345 u16 temp2;
1346 struct aper_size_info_8 *current_size;
1347
1348 current_size = A_SIZE_8(agp_bridge->current_size);
1349
1350 /* aperture size */
1351 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1352
1353 /* address to map to */
1354 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1355 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1356
1357 /* attbase - aperture base */
1358 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1359
1360 /* agpctrl */
1361 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1362
1363 /* mchcfg */
1364 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
1365 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
1366
1367 return 0;
1368}
1369
1370/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -05001371static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
1373 {.mask = 0x00000017, .type = 0}
1374};
1375
Dave Jonese5524f32007-02-22 18:41:28 -05001376static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
1378 {64, 16384, 4, 0},
1379 {32, 8192, 3, 8},
1380};
1381
Dave Jonese5524f32007-02-22 18:41:28 -05001382static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383{
1384 {256, 65536, 6, 0},
1385 {128, 32768, 5, 32},
1386 {64, 16384, 4, 48},
1387 {32, 8192, 3, 56},
1388 {16, 4096, 2, 60},
1389 {8, 2048, 1, 62},
1390 {4, 1024, 0, 63}
1391};
1392
Dave Jonese5524f32007-02-22 18:41:28 -05001393static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
1395 {256, 65536, 6, 0},
1396 {128, 32768, 5, 32},
1397 {64, 16384, 4, 48},
1398 {32, 8192, 3, 56},
1399 {16, 4096, 2, 60},
1400 {8, 2048, 1, 62},
1401 {4, 1024, 0, 63}
1402};
1403
Dave Jonese5524f32007-02-22 18:41:28 -05001404static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405{
1406 {256, 65536, 6, 0},
1407 {128, 32768, 5, 32},
1408 {64, 16384, 4, 48},
1409 {32, 8192, 3, 56}
1410};
1411
Dave Jonese5524f32007-02-22 18:41:28 -05001412static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 .owner = THIS_MODULE,
1414 .aperture_sizes = intel_generic_sizes,
1415 .size_type = U16_APER_SIZE,
1416 .num_aperture_sizes = 7,
1417 .configure = intel_configure,
1418 .fetch_size = intel_fetch_size,
1419 .cleanup = intel_cleanup,
1420 .tlb_flush = intel_tlbflush,
1421 .mask_memory = agp_generic_mask_memory,
1422 .masks = intel_generic_masks,
1423 .agp_enable = agp_generic_enable,
1424 .cache_flush = global_cache_flush,
1425 .create_gatt_table = agp_generic_create_gatt_table,
1426 .free_gatt_table = agp_generic_free_gatt_table,
1427 .insert_memory = agp_generic_insert_memory,
1428 .remove_memory = agp_generic_remove_memory,
1429 .alloc_by_type = agp_generic_alloc_by_type,
1430 .free_by_type = agp_generic_free_by_type,
1431 .agp_alloc_page = agp_generic_alloc_page,
1432 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001433 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434};
1435
Dave Jonese5524f32007-02-22 18:41:28 -05001436static const struct agp_bridge_driver intel_810_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 .owner = THIS_MODULE,
1438 .aperture_sizes = intel_i810_sizes,
1439 .size_type = FIXED_APER_SIZE,
1440 .num_aperture_sizes = 2,
1441 .needs_scratch_page = TRUE,
1442 .configure = intel_i810_configure,
1443 .fetch_size = intel_i810_fetch_size,
1444 .cleanup = intel_i810_cleanup,
1445 .tlb_flush = intel_i810_tlbflush,
1446 .mask_memory = intel_i810_mask_memory,
1447 .masks = intel_i810_masks,
1448 .agp_enable = intel_i810_agp_enable,
1449 .cache_flush = global_cache_flush,
1450 .create_gatt_table = agp_generic_create_gatt_table,
1451 .free_gatt_table = agp_generic_free_gatt_table,
1452 .insert_memory = intel_i810_insert_entries,
1453 .remove_memory = intel_i810_remove_entries,
1454 .alloc_by_type = intel_i810_alloc_by_type,
1455 .free_by_type = intel_i810_free_by_type,
1456 .agp_alloc_page = agp_generic_alloc_page,
1457 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001458 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459};
1460
Dave Jonese5524f32007-02-22 18:41:28 -05001461static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 .owner = THIS_MODULE,
1463 .aperture_sizes = intel_815_sizes,
1464 .size_type = U8_APER_SIZE,
1465 .num_aperture_sizes = 2,
1466 .configure = intel_815_configure,
1467 .fetch_size = intel_815_fetch_size,
1468 .cleanup = intel_8xx_cleanup,
1469 .tlb_flush = intel_8xx_tlbflush,
1470 .mask_memory = agp_generic_mask_memory,
1471 .masks = intel_generic_masks,
1472 .agp_enable = agp_generic_enable,
1473 .cache_flush = global_cache_flush,
1474 .create_gatt_table = agp_generic_create_gatt_table,
1475 .free_gatt_table = agp_generic_free_gatt_table,
1476 .insert_memory = agp_generic_insert_memory,
1477 .remove_memory = agp_generic_remove_memory,
1478 .alloc_by_type = agp_generic_alloc_by_type,
1479 .free_by_type = agp_generic_free_by_type,
1480 .agp_alloc_page = agp_generic_alloc_page,
1481 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001482 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483};
1484
Dave Jonese5524f32007-02-22 18:41:28 -05001485static const struct agp_bridge_driver intel_830_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 .owner = THIS_MODULE,
1487 .aperture_sizes = intel_i830_sizes,
1488 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04001489 .num_aperture_sizes = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 .needs_scratch_page = TRUE,
1491 .configure = intel_i830_configure,
1492 .fetch_size = intel_i830_fetch_size,
1493 .cleanup = intel_i830_cleanup,
1494 .tlb_flush = intel_i810_tlbflush,
1495 .mask_memory = intel_i810_mask_memory,
1496 .masks = intel_i810_masks,
1497 .agp_enable = intel_i810_agp_enable,
1498 .cache_flush = global_cache_flush,
1499 .create_gatt_table = intel_i830_create_gatt_table,
1500 .free_gatt_table = intel_i830_free_gatt_table,
1501 .insert_memory = intel_i830_insert_entries,
1502 .remove_memory = intel_i830_remove_entries,
1503 .alloc_by_type = intel_i830_alloc_by_type,
1504 .free_by_type = intel_i810_free_by_type,
1505 .agp_alloc_page = agp_generic_alloc_page,
1506 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001507 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508};
1509
Dave Jonese5524f32007-02-22 18:41:28 -05001510static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 .owner = THIS_MODULE,
1512 .aperture_sizes = intel_8xx_sizes,
1513 .size_type = U8_APER_SIZE,
1514 .num_aperture_sizes = 7,
1515 .configure = intel_820_configure,
1516 .fetch_size = intel_8xx_fetch_size,
1517 .cleanup = intel_820_cleanup,
1518 .tlb_flush = intel_820_tlbflush,
1519 .mask_memory = agp_generic_mask_memory,
1520 .masks = intel_generic_masks,
1521 .agp_enable = agp_generic_enable,
1522 .cache_flush = global_cache_flush,
1523 .create_gatt_table = agp_generic_create_gatt_table,
1524 .free_gatt_table = agp_generic_free_gatt_table,
1525 .insert_memory = agp_generic_insert_memory,
1526 .remove_memory = agp_generic_remove_memory,
1527 .alloc_by_type = agp_generic_alloc_by_type,
1528 .free_by_type = agp_generic_free_by_type,
1529 .agp_alloc_page = agp_generic_alloc_page,
1530 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001531 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532};
1533
Dave Jonese5524f32007-02-22 18:41:28 -05001534static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 .owner = THIS_MODULE,
1536 .aperture_sizes = intel_830mp_sizes,
1537 .size_type = U8_APER_SIZE,
1538 .num_aperture_sizes = 4,
1539 .configure = intel_830mp_configure,
1540 .fetch_size = intel_8xx_fetch_size,
1541 .cleanup = intel_8xx_cleanup,
1542 .tlb_flush = intel_8xx_tlbflush,
1543 .mask_memory = agp_generic_mask_memory,
1544 .masks = intel_generic_masks,
1545 .agp_enable = agp_generic_enable,
1546 .cache_flush = global_cache_flush,
1547 .create_gatt_table = agp_generic_create_gatt_table,
1548 .free_gatt_table = agp_generic_free_gatt_table,
1549 .insert_memory = agp_generic_insert_memory,
1550 .remove_memory = agp_generic_remove_memory,
1551 .alloc_by_type = agp_generic_alloc_by_type,
1552 .free_by_type = agp_generic_free_by_type,
1553 .agp_alloc_page = agp_generic_alloc_page,
1554 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001555 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556};
1557
Dave Jonese5524f32007-02-22 18:41:28 -05001558static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 .owner = THIS_MODULE,
1560 .aperture_sizes = intel_8xx_sizes,
1561 .size_type = U8_APER_SIZE,
1562 .num_aperture_sizes = 7,
1563 .configure = intel_840_configure,
1564 .fetch_size = intel_8xx_fetch_size,
1565 .cleanup = intel_8xx_cleanup,
1566 .tlb_flush = intel_8xx_tlbflush,
1567 .mask_memory = agp_generic_mask_memory,
1568 .masks = intel_generic_masks,
1569 .agp_enable = agp_generic_enable,
1570 .cache_flush = global_cache_flush,
1571 .create_gatt_table = agp_generic_create_gatt_table,
1572 .free_gatt_table = agp_generic_free_gatt_table,
1573 .insert_memory = agp_generic_insert_memory,
1574 .remove_memory = agp_generic_remove_memory,
1575 .alloc_by_type = agp_generic_alloc_by_type,
1576 .free_by_type = agp_generic_free_by_type,
1577 .agp_alloc_page = agp_generic_alloc_page,
1578 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001579 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580};
1581
Dave Jonese5524f32007-02-22 18:41:28 -05001582static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 .owner = THIS_MODULE,
1584 .aperture_sizes = intel_8xx_sizes,
1585 .size_type = U8_APER_SIZE,
1586 .num_aperture_sizes = 7,
1587 .configure = intel_845_configure,
1588 .fetch_size = intel_8xx_fetch_size,
1589 .cleanup = intel_8xx_cleanup,
1590 .tlb_flush = intel_8xx_tlbflush,
1591 .mask_memory = agp_generic_mask_memory,
1592 .masks = intel_generic_masks,
1593 .agp_enable = agp_generic_enable,
1594 .cache_flush = global_cache_flush,
1595 .create_gatt_table = agp_generic_create_gatt_table,
1596 .free_gatt_table = agp_generic_free_gatt_table,
1597 .insert_memory = agp_generic_insert_memory,
1598 .remove_memory = agp_generic_remove_memory,
1599 .alloc_by_type = agp_generic_alloc_by_type,
1600 .free_by_type = agp_generic_free_by_type,
1601 .agp_alloc_page = agp_generic_alloc_page,
1602 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001603 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604};
1605
Dave Jonese5524f32007-02-22 18:41:28 -05001606static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 .owner = THIS_MODULE,
1608 .aperture_sizes = intel_8xx_sizes,
1609 .size_type = U8_APER_SIZE,
1610 .num_aperture_sizes = 7,
1611 .configure = intel_850_configure,
1612 .fetch_size = intel_8xx_fetch_size,
1613 .cleanup = intel_8xx_cleanup,
1614 .tlb_flush = intel_8xx_tlbflush,
1615 .mask_memory = agp_generic_mask_memory,
1616 .masks = intel_generic_masks,
1617 .agp_enable = agp_generic_enable,
1618 .cache_flush = global_cache_flush,
1619 .create_gatt_table = agp_generic_create_gatt_table,
1620 .free_gatt_table = agp_generic_free_gatt_table,
1621 .insert_memory = agp_generic_insert_memory,
1622 .remove_memory = agp_generic_remove_memory,
1623 .alloc_by_type = agp_generic_alloc_by_type,
1624 .free_by_type = agp_generic_free_by_type,
1625 .agp_alloc_page = agp_generic_alloc_page,
1626 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001627 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628};
1629
Dave Jonese5524f32007-02-22 18:41:28 -05001630static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 .owner = THIS_MODULE,
1632 .aperture_sizes = intel_8xx_sizes,
1633 .size_type = U8_APER_SIZE,
1634 .num_aperture_sizes = 7,
1635 .configure = intel_860_configure,
1636 .fetch_size = intel_8xx_fetch_size,
1637 .cleanup = intel_8xx_cleanup,
1638 .tlb_flush = intel_8xx_tlbflush,
1639 .mask_memory = agp_generic_mask_memory,
1640 .masks = intel_generic_masks,
1641 .agp_enable = agp_generic_enable,
1642 .cache_flush = global_cache_flush,
1643 .create_gatt_table = agp_generic_create_gatt_table,
1644 .free_gatt_table = agp_generic_free_gatt_table,
1645 .insert_memory = agp_generic_insert_memory,
1646 .remove_memory = agp_generic_remove_memory,
1647 .alloc_by_type = agp_generic_alloc_by_type,
1648 .free_by_type = agp_generic_free_by_type,
1649 .agp_alloc_page = agp_generic_alloc_page,
1650 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001651 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652};
1653
Dave Jonese5524f32007-02-22 18:41:28 -05001654static const struct agp_bridge_driver intel_915_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 .owner = THIS_MODULE,
1656 .aperture_sizes = intel_i830_sizes,
1657 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04001658 .num_aperture_sizes = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 .needs_scratch_page = TRUE,
1660 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08001661 .fetch_size = intel_i9xx_fetch_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 .cleanup = intel_i915_cleanup,
1663 .tlb_flush = intel_i810_tlbflush,
1664 .mask_memory = intel_i810_mask_memory,
1665 .masks = intel_i810_masks,
1666 .agp_enable = intel_i810_agp_enable,
1667 .cache_flush = global_cache_flush,
1668 .create_gatt_table = intel_i915_create_gatt_table,
1669 .free_gatt_table = intel_i830_free_gatt_table,
1670 .insert_memory = intel_i915_insert_entries,
1671 .remove_memory = intel_i915_remove_entries,
1672 .alloc_by_type = intel_i830_alloc_by_type,
1673 .free_by_type = intel_i810_free_by_type,
1674 .agp_alloc_page = agp_generic_alloc_page,
1675 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001676 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677};
1678
Dave Jonese5524f32007-02-22 18:41:28 -05001679static const struct agp_bridge_driver intel_i965_driver = {
Eric Anholt65c25aa2006-09-06 11:57:18 -04001680 .owner = THIS_MODULE,
1681 .aperture_sizes = intel_i830_sizes,
1682 .size_type = FIXED_APER_SIZE,
1683 .num_aperture_sizes = 4,
1684 .needs_scratch_page = TRUE,
1685 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08001686 .fetch_size = intel_i9xx_fetch_size,
Eric Anholt65c25aa2006-09-06 11:57:18 -04001687 .cleanup = intel_i915_cleanup,
1688 .tlb_flush = intel_i810_tlbflush,
Linus Torvalds7d915a32006-11-22 09:37:54 -08001689 .mask_memory = intel_i965_mask_memory,
Eric Anholt65c25aa2006-09-06 11:57:18 -04001690 .masks = intel_i810_masks,
1691 .agp_enable = intel_i810_agp_enable,
1692 .cache_flush = global_cache_flush,
1693 .create_gatt_table = intel_i965_create_gatt_table,
1694 .free_gatt_table = intel_i830_free_gatt_table,
1695 .insert_memory = intel_i915_insert_entries,
1696 .remove_memory = intel_i915_remove_entries,
1697 .alloc_by_type = intel_i830_alloc_by_type,
1698 .free_by_type = intel_i810_free_by_type,
1699 .agp_alloc_page = agp_generic_alloc_page,
1700 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001701 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Eric Anholt65c25aa2006-09-06 11:57:18 -04001702};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
Dave Jonese5524f32007-02-22 18:41:28 -05001704static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 .owner = THIS_MODULE,
1706 .aperture_sizes = intel_8xx_sizes,
1707 .size_type = U8_APER_SIZE,
1708 .num_aperture_sizes = 7,
1709 .configure = intel_7505_configure,
1710 .fetch_size = intel_8xx_fetch_size,
1711 .cleanup = intel_8xx_cleanup,
1712 .tlb_flush = intel_8xx_tlbflush,
1713 .mask_memory = agp_generic_mask_memory,
1714 .masks = intel_generic_masks,
1715 .agp_enable = agp_generic_enable,
1716 .cache_flush = global_cache_flush,
1717 .create_gatt_table = agp_generic_create_gatt_table,
1718 .free_gatt_table = agp_generic_free_gatt_table,
1719 .insert_memory = agp_generic_insert_memory,
1720 .remove_memory = agp_generic_remove_memory,
1721 .alloc_by_type = agp_generic_alloc_by_type,
1722 .free_by_type = agp_generic_free_by_type,
1723 .agp_alloc_page = agp_generic_alloc_page,
1724 .agp_destroy_page = agp_generic_destroy_page,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001725 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726};
1727
1728static int find_i810(u16 device)
1729{
1730 struct pci_dev *i810_dev;
1731
1732 i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
1733 if (!i810_dev)
1734 return 0;
1735 intel_i810_private.i810_dev = i810_dev;
1736 return 1;
1737}
1738
1739static int find_i830(u16 device)
1740{
1741 struct pci_dev *i830_dev;
1742
1743 i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
1744 if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
1745 i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
1746 device, i830_dev);
1747 }
1748
1749 if (!i830_dev)
1750 return 0;
1751
1752 intel_i830_private.i830_dev = i830_dev;
1753 return 1;
1754}
1755
1756static int __devinit agp_intel_probe(struct pci_dev *pdev,
1757 const struct pci_device_id *ent)
1758{
1759 struct agp_bridge_data *bridge;
1760 char *name = "(unknown)";
1761 u8 cap_ptr = 0;
1762 struct resource *r;
1763
1764 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
1765
1766 bridge = agp_alloc_bridge();
1767 if (!bridge)
1768 return -ENOMEM;
1769
1770 switch (pdev->device) {
1771 case PCI_DEVICE_ID_INTEL_82443LX_0:
1772 bridge->driver = &intel_generic_driver;
1773 name = "440LX";
1774 break;
1775 case PCI_DEVICE_ID_INTEL_82443BX_0:
1776 bridge->driver = &intel_generic_driver;
1777 name = "440BX";
1778 break;
1779 case PCI_DEVICE_ID_INTEL_82443GX_0:
1780 bridge->driver = &intel_generic_driver;
1781 name = "440GX";
1782 break;
1783 case PCI_DEVICE_ID_INTEL_82810_MC1:
1784 name = "i810";
1785 if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
1786 goto fail;
1787 bridge->driver = &intel_810_driver;
1788 break;
1789 case PCI_DEVICE_ID_INTEL_82810_MC3:
1790 name = "i810 DC100";
1791 if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
1792 goto fail;
1793 bridge->driver = &intel_810_driver;
1794 break;
1795 case PCI_DEVICE_ID_INTEL_82810E_MC:
1796 name = "i810 E";
1797 if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
1798 goto fail;
1799 bridge->driver = &intel_810_driver;
1800 break;
1801 case PCI_DEVICE_ID_INTEL_82815_MC:
1802 /*
1803 * The i815 can operate either as an i810 style
1804 * integrated device, or as an AGP4X motherboard.
1805 */
1806 if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
1807 bridge->driver = &intel_810_driver;
1808 else
1809 bridge->driver = &intel_815_driver;
1810 name = "i815";
1811 break;
1812 case PCI_DEVICE_ID_INTEL_82820_HB:
1813 case PCI_DEVICE_ID_INTEL_82820_UP_HB:
1814 bridge->driver = &intel_820_driver;
1815 name = "i820";
1816 break;
1817 case PCI_DEVICE_ID_INTEL_82830_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001818 if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001820 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 bridge->driver = &intel_830mp_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 name = "830M";
1823 break;
1824 case PCI_DEVICE_ID_INTEL_82840_HB:
1825 bridge->driver = &intel_840_driver;
1826 name = "i840";
1827 break;
1828 case PCI_DEVICE_ID_INTEL_82845_HB:
1829 bridge->driver = &intel_845_driver;
1830 name = "i845";
1831 break;
1832 case PCI_DEVICE_ID_INTEL_82845G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001833 if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001835 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 name = "845G";
1838 break;
1839 case PCI_DEVICE_ID_INTEL_82850_HB:
1840 bridge->driver = &intel_850_driver;
1841 name = "i850";
1842 break;
1843 case PCI_DEVICE_ID_INTEL_82855PM_HB:
1844 bridge->driver = &intel_845_driver;
1845 name = "855PM";
1846 break;
1847 case PCI_DEVICE_ID_INTEL_82855GM_HB:
1848 if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
1849 bridge->driver = &intel_830_driver;
1850 name = "855";
1851 } else {
1852 bridge->driver = &intel_845_driver;
1853 name = "855GM";
1854 }
1855 break;
1856 case PCI_DEVICE_ID_INTEL_82860_HB:
1857 bridge->driver = &intel_860_driver;
1858 name = "i860";
1859 break;
1860 case PCI_DEVICE_ID_INTEL_82865_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001861 if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001863 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 name = "865";
1866 break;
1867 case PCI_DEVICE_ID_INTEL_82875_HB:
1868 bridge->driver = &intel_845_driver;
1869 name = "i875";
1870 break;
1871 case PCI_DEVICE_ID_INTEL_82915G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001872 if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001874 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 name = "915G";
1877 break;
1878 case PCI_DEVICE_ID_INTEL_82915GM_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001879 if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001881 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 name = "915GM";
1884 break;
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001885 case PCI_DEVICE_ID_INTEL_82945G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001886 if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001887 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001888 else
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001889 bridge->driver = &intel_845_driver;
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001890 name = "945G";
1891 break;
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001892 case PCI_DEVICE_ID_INTEL_82945GM_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001893 if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001894 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001895 else
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001896 bridge->driver = &intel_845_driver;
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001897 name = "945GM";
1898 break;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001899 case PCI_DEVICE_ID_INTEL_82946GZ_HB:
1900 if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
1901 bridge->driver = &intel_i965_driver;
1902 else
1903 bridge->driver = &intel_845_driver;
1904 name = "946GZ";
1905 break;
1906 case PCI_DEVICE_ID_INTEL_82965G_1_HB:
1907 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
1908 bridge->driver = &intel_i965_driver;
1909 else
1910 bridge->driver = &intel_845_driver;
1911 name = "965G";
1912 break;
1913 case PCI_DEVICE_ID_INTEL_82965Q_HB:
1914 if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
1915 bridge->driver = &intel_i965_driver;
1916 else
1917 bridge->driver = &intel_845_driver;
1918 name = "965Q";
1919 break;
1920 case PCI_DEVICE_ID_INTEL_82965G_HB:
1921 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
1922 bridge->driver = &intel_i965_driver;
1923 else
1924 bridge->driver = &intel_845_driver;
1925 name = "965G";
1926 break;
Wang Zhenyu4598af32007-04-09 08:51:36 +08001927 case PCI_DEVICE_ID_INTEL_82965GM_HB:
1928 if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG))
1929 bridge->driver = &intel_i965_driver;
1930 else
1931 bridge->driver = &intel_845_driver;
1932 name = "965GM";
1933 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 case PCI_DEVICE_ID_INTEL_7505_0:
1935 bridge->driver = &intel_7505_driver;
1936 name = "E7505";
1937 break;
1938 case PCI_DEVICE_ID_INTEL_7205_0:
1939 bridge->driver = &intel_7505_driver;
1940 name = "E7205";
1941 break;
1942 default:
1943 if (cap_ptr)
1944 printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
1945 pdev->device);
1946 agp_put_bridge(bridge);
1947 return -ENODEV;
1948 };
1949
1950 bridge->dev = pdev;
1951 bridge->capndx = cap_ptr;
1952
1953 if (bridge->driver == &intel_810_driver)
1954 bridge->dev_private_data = &intel_i810_private;
1955 else if (bridge->driver == &intel_830_driver)
1956 bridge->dev_private_data = &intel_i830_private;
1957
1958 printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
1959
1960 /*
1961 * The following fixes the case where the BIOS has "forgotten" to
1962 * provide an address range for the GART.
1963 * 20030610 - hamish@zot.org
1964 */
1965 r = &pdev->resource[0];
1966 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -05001967 if (pci_assign_resource(pdev, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 printk(KERN_ERR PFX "could not assign resource 0\n");
1969 agp_put_bridge(bridge);
1970 return -ENODEV;
1971 }
1972 }
1973
1974 /*
1975 * If the device has not been properly setup, the following will catch
1976 * the problem and should stop the system from crashing.
1977 * 20030610 - hamish@zot.org
1978 */
1979 if (pci_enable_device(pdev)) {
1980 printk(KERN_ERR PFX "Unable to Enable PCI device\n");
1981 agp_put_bridge(bridge);
1982 return -ENODEV;
1983 }
1984
1985 /* Fill in the mode register */
1986 if (cap_ptr) {
1987 pci_read_config_dword(pdev,
1988 bridge->capndx+PCI_AGP_STATUS,
1989 &bridge->mode);
1990 }
1991
1992 pci_set_drvdata(pdev, bridge);
1993 return agp_add_bridge(bridge);
1994
1995fail:
1996 printk(KERN_ERR PFX "Detected an Intel %s chipset, "
1997 "but could not find the secondary device.\n", name);
1998 agp_put_bridge(bridge);
1999 return -ENODEV;
2000}
2001
2002static void __devexit agp_intel_remove(struct pci_dev *pdev)
2003{
2004 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
2005
2006 agp_remove_bridge(bridge);
2007
2008 if (intel_i810_private.i810_dev)
2009 pci_dev_put(intel_i810_private.i810_dev);
2010 if (intel_i830_private.i830_dev)
2011 pci_dev_put(intel_i830_private.i830_dev);
2012
2013 agp_put_bridge(bridge);
2014}
2015
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002016#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017static int agp_intel_resume(struct pci_dev *pdev)
2018{
2019 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
2020
2021 pci_restore_state(pdev);
2022
Wang Zhenyu4b953202007-01-17 11:07:54 +08002023 /* We should restore our graphics device's config space,
2024 * as host bridge (00:00) resumes before graphics device (02:00),
2025 * then our access to its pci space can work right.
2026 */
2027 if (intel_i810_private.i810_dev)
2028 pci_restore_state(intel_i810_private.i810_dev);
2029 if (intel_i830_private.i830_dev)
2030 pci_restore_state(intel_i830_private.i830_dev);
2031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 if (bridge->driver == &intel_generic_driver)
2033 intel_configure();
2034 else if (bridge->driver == &intel_850_driver)
2035 intel_850_configure();
2036 else if (bridge->driver == &intel_845_driver)
2037 intel_845_configure();
2038 else if (bridge->driver == &intel_830mp_driver)
2039 intel_830mp_configure();
2040 else if (bridge->driver == &intel_915_driver)
2041 intel_i915_configure();
2042 else if (bridge->driver == &intel_830_driver)
2043 intel_i830_configure();
2044 else if (bridge->driver == &intel_810_driver)
2045 intel_i810_configure();
Dave Jones08da3f42006-09-10 21:09:26 -04002046 else if (bridge->driver == &intel_i965_driver)
2047 intel_i915_configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
2049 return 0;
2050}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002051#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
2053static struct pci_device_id agp_intel_pci_table[] = {
2054#define ID(x) \
2055 { \
2056 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
2057 .class_mask = ~0, \
2058 .vendor = PCI_VENDOR_ID_INTEL, \
2059 .device = x, \
2060 .subvendor = PCI_ANY_ID, \
2061 .subdevice = PCI_ANY_ID, \
2062 }
2063 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
2064 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
2065 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
2066 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
2067 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
2068 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
2069 ID(PCI_DEVICE_ID_INTEL_82815_MC),
2070 ID(PCI_DEVICE_ID_INTEL_82820_HB),
2071 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
2072 ID(PCI_DEVICE_ID_INTEL_82830_HB),
2073 ID(PCI_DEVICE_ID_INTEL_82840_HB),
2074 ID(PCI_DEVICE_ID_INTEL_82845_HB),
2075 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
2076 ID(PCI_DEVICE_ID_INTEL_82850_HB),
2077 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
2078 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
2079 ID(PCI_DEVICE_ID_INTEL_82860_HB),
2080 ID(PCI_DEVICE_ID_INTEL_82865_HB),
2081 ID(PCI_DEVICE_ID_INTEL_82875_HB),
2082 ID(PCI_DEVICE_ID_INTEL_7505_0),
2083 ID(PCI_DEVICE_ID_INTEL_7205_0),
2084 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
2085 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01002086 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00002087 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002088 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
2089 ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
2090 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
2091 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +08002092 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 { }
2094};
2095
2096MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
2097
2098static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 .name = "agpgart-intel",
2100 .id_table = agp_intel_pci_table,
2101 .probe = agp_intel_probe,
2102 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002103#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002105#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106};
2107
2108static int __init agp_intel_init(void)
2109{
2110 if (agp_off)
2111 return -EINVAL;
2112 return pci_register_driver(&agp_intel_pci_driver);
2113}
2114
2115static void __exit agp_intel_cleanup(void)
2116{
2117 pci_unregister_driver(&agp_intel_pci_driver);
2118}
2119
2120module_init(agp_intel_init);
2121module_exit(agp_intel_cleanup);
2122
2123MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
2124MODULE_LICENSE("GPL and additional rights");