blob: a3011de51f7c049438ae51fae97f3652522cf9a4 [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>
8#include <linux/pagemap.h>
9#include <linux/agp_backend.h>
10#include "agp.h"
11
Eric Anholt65c25aa2006-09-06 11:57:18 -040012#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
13#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
14#define PCI_DEVICE_ID_INTEL_82965G_1_HB 0x2980
15#define PCI_DEVICE_ID_INTEL_82965G_1_IG 0x2982
16#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
17#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
18#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
19#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
20
21#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
22 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
23 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
24 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
25
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027/* Intel 815 register */
28#define INTEL_815_APCONT 0x51
29#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
30
31/* Intel i820 registers */
32#define INTEL_I820_RDCR 0x51
33#define INTEL_I820_ERRSTS 0xc8
34
35/* Intel i840 registers */
36#define INTEL_I840_MCHCFG 0x50
37#define INTEL_I840_ERRSTS 0xc8
38
39/* Intel i850 registers */
40#define INTEL_I850_MCHCFG 0x50
41#define INTEL_I850_ERRSTS 0xc8
42
43/* intel 915G registers */
44#define I915_GMADDR 0x18
45#define I915_MMADDR 0x10
46#define I915_PTEADDR 0x1C
47#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
48#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
49
Eric Anholt65c25aa2006-09-06 11:57:18 -040050/* Intel 965G registers */
51#define I965_MSAC 0x62
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53/* Intel 7505 registers */
54#define INTEL_I7505_APSIZE 0x74
55#define INTEL_I7505_NCAPID 0x60
56#define INTEL_I7505_NISTAT 0x6c
57#define INTEL_I7505_ATTBASE 0x78
58#define INTEL_I7505_ERRSTS 0x42
59#define INTEL_I7505_AGPCTRL 0x70
60#define INTEL_I7505_MCHCFG 0x50
61
62static struct aper_size_info_fixed intel_i810_sizes[] =
63{
64 {64, 16384, 4},
65 /* The 32M mode still requires a 64k gatt */
66 {32, 8192, 4}
67};
68
69#define AGP_DCACHE_MEMORY 1
70#define AGP_PHYS_MEMORY 2
71
72static struct gatt_mask intel_i810_masks[] =
73{
74 {.mask = I810_PTE_VALID, .type = 0},
75 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
76 {.mask = I810_PTE_VALID, .type = 0}
77};
78
79static struct _intel_i810_private {
80 struct pci_dev *i810_dev; /* device one */
81 volatile u8 __iomem *registers;
82 int num_dcache_entries;
83} intel_i810_private;
84
85static int intel_i810_fetch_size(void)
86{
87 u32 smram_miscc;
88 struct aper_size_info_fixed *values;
89
90 pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
91 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
92
93 if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
94 printk(KERN_WARNING PFX "i810 is disabled\n");
95 return 0;
96 }
97 if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
98 agp_bridge->previous_size =
99 agp_bridge->current_size = (void *) (values + 1);
100 agp_bridge->aperture_size_idx = 1;
101 return values[1].size;
102 } else {
103 agp_bridge->previous_size =
104 agp_bridge->current_size = (void *) (values);
105 agp_bridge->aperture_size_idx = 0;
106 return values[0].size;
107 }
108
109 return 0;
110}
111
112static int intel_i810_configure(void)
113{
114 struct aper_size_info_fixed *current_size;
115 u32 temp;
116 int i;
117
118 current_size = A_SIZE_FIX(agp_bridge->current_size);
119
120 pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
121 temp &= 0xfff80000;
122
123 intel_i810_private.registers = ioremap(temp, 128 * 4096);
124 if (!intel_i810_private.registers) {
125 printk(KERN_ERR PFX "Unable to remap memory.\n");
126 return -ENOMEM;
127 }
128
129 if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
130 & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
131 /* This will need to be dynamically assigned */
132 printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
133 intel_i810_private.num_dcache_entries = 1024;
134 }
135 pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
136 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
137 writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
138 readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
139
140 if (agp_bridge->driver->needs_scratch_page) {
141 for (i = 0; i < current_size->num_entries; i++) {
142 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
143 readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
144 }
145 }
146 global_cache_flush();
147 return 0;
148}
149
150static void intel_i810_cleanup(void)
151{
152 writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
153 readl(intel_i810_private.registers); /* PCI Posting. */
154 iounmap(intel_i810_private.registers);
155}
156
157static void intel_i810_tlbflush(struct agp_memory *mem)
158{
159 return;
160}
161
162static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
163{
164 return;
165}
166
167/* Exists to support ARGB cursors */
168static void *i8xx_alloc_pages(void)
169{
170 struct page * page;
171
Linus Torvalds66c669b2006-11-22 14:55:29 -0800172 page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 if (page == NULL)
174 return NULL;
175
176 if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
177 global_flush_tlb();
178 __free_page(page);
179 return NULL;
180 }
181 global_flush_tlb();
182 get_page(page);
183 SetPageLocked(page);
184 atomic_inc(&agp_bridge->current_memory_agp);
185 return page_address(page);
186}
187
188static void i8xx_destroy_pages(void *addr)
189{
190 struct page *page;
191
192 if (addr == NULL)
193 return;
194
195 page = virt_to_page(addr);
196 change_page_attr(page, 4, PAGE_KERNEL);
197 global_flush_tlb();
198 put_page(page);
199 unlock_page(page);
200 free_pages((unsigned long)addr, 2);
201 atomic_dec(&agp_bridge->current_memory_agp);
202}
203
204static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
205 int type)
206{
207 int i, j, num_entries;
208 void *temp;
209
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100210 if (mem->page_count == 0)
211 return 0;
212
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 temp = agp_bridge->current_size;
214 num_entries = A_SIZE_FIX(temp)->num_entries;
215
Dave Jones6a92a4e2006-02-28 00:54:25 -0500216 if ((pg_start + mem->page_count) > num_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 return -EINVAL;
Dave Jones6a92a4e2006-02-28 00:54:25 -0500218
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
220 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
221 return -EBUSY;
222 }
223
224 if (type != 0 || mem->type != 0) {
225 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
226 /* special insert */
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100227 if (!mem->is_flushed) {
228 global_cache_flush();
229 mem->is_flushed = TRUE;
230 }
231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
233 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100235 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 agp_bridge->driver->tlb_flush(mem);
238 return 0;
239 }
Dave Jones6a92a4e2006-02-28 00:54:25 -0500240 if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 goto insert;
242 return -EINVAL;
243 }
244
245insert:
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100246 if (!mem->is_flushed) {
247 global_cache_flush();
248 mem->is_flushed = TRUE;
249 }
250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
252 writel(agp_bridge->driver->mask_memory(agp_bridge,
253 mem->memory[i], mem->type),
254 intel_i810_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 }
Thomas Hellstrom7f02d682006-12-27 13:16:49 +0100256 readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 agp_bridge->driver->tlb_flush(mem);
259 return 0;
260}
261
262static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
263 int type)
264{
265 int i;
266
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100267 if (mem->page_count == 0)
268 return 0;
269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
271 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100273 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 agp_bridge->driver->tlb_flush(mem);
276 return 0;
277}
278
279/*
280 * The i810/i830 requires a physical address to program its mouse
281 * pointer into hardware.
282 * However the Xserver still writes to it through the agp aperture.
283 */
284static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
285{
286 struct agp_memory *new;
287 void *addr;
288
289 if (pg_count != 1 && pg_count != 4)
290 return NULL;
291
292 switch (pg_count) {
293 case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
Alan Hourihane88d51962005-11-06 23:35:34 -0800294 global_flush_tlb();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 break;
296 case 4:
297 /* kludge to get 4 physical pages for ARGB cursor */
298 addr = i8xx_alloc_pages();
299 break;
300 default:
301 return NULL;
302 }
303
304 if (addr == NULL)
305 return NULL;
306
307 new = agp_create_memory(pg_count);
308 if (new == NULL)
309 return NULL;
310
Keir Fraser07eee782005-03-30 13:17:04 -0800311 new->memory[0] = virt_to_gart(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 if (pg_count == 4) {
313 /* kludge to get 4 physical pages for ARGB cursor */
314 new->memory[1] = new->memory[0] + PAGE_SIZE;
315 new->memory[2] = new->memory[1] + PAGE_SIZE;
316 new->memory[3] = new->memory[2] + PAGE_SIZE;
317 }
318 new->page_count = pg_count;
319 new->num_scratch_pages = pg_count;
320 new->type = AGP_PHYS_MEMORY;
321 new->physical = new->memory[0];
322 return new;
323}
324
325static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
326{
327 struct agp_memory *new;
328
329 if (type == AGP_DCACHE_MEMORY) {
330 if (pg_count != intel_i810_private.num_dcache_entries)
331 return NULL;
332
333 new = agp_create_memory(1);
334 if (new == NULL)
335 return NULL;
336
337 new->type = AGP_DCACHE_MEMORY;
338 new->page_count = pg_count;
339 new->num_scratch_pages = 0;
340 vfree(new->memory);
341 return new;
342 }
343 if (type == AGP_PHYS_MEMORY)
344 return alloc_agpphysmem_i8xx(pg_count, type);
345
346 return NULL;
347}
348
349static void intel_i810_free_by_type(struct agp_memory *curr)
350{
351 agp_free_key(curr->key);
Dave Jones6a92a4e2006-02-28 00:54:25 -0500352 if (curr->type == AGP_PHYS_MEMORY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 if (curr->page_count == 4)
Keir Fraser07eee782005-03-30 13:17:04 -0800354 i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
Alan Hourihane88d51962005-11-06 23:35:34 -0800355 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 agp_bridge->driver->agp_destroy_page(
Keir Fraser07eee782005-03-30 13:17:04 -0800357 gart_to_virt(curr->memory[0]));
Alan Hourihane88d51962005-11-06 23:35:34 -0800358 global_flush_tlb();
359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 vfree(curr->memory);
361 }
362 kfree(curr);
363}
364
365static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
366 unsigned long addr, int type)
367{
368 /* Type checking must be done elsewhere */
369 return addr | bridge->driver->masks[type].mask;
370}
371
372static struct aper_size_info_fixed intel_i830_sizes[] =
373{
374 {128, 32768, 5},
375 /* The 64M mode still requires a 128k gatt */
376 {64, 16384, 5},
377 {256, 65536, 6},
Eric Anholt65c25aa2006-09-06 11:57:18 -0400378 {512, 131072, 7},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379};
380
381static struct _intel_i830_private {
382 struct pci_dev *i830_dev; /* device one */
383 volatile u8 __iomem *registers;
384 volatile u32 __iomem *gtt; /* I915G */
Eric Anholtc41e0de2006-12-19 12:57:24 -0800385 /* gtt_entries is the number of gtt entries that are already mapped
386 * to stolen memory. Stolen memory is larger than the memory mapped
387 * through gtt_entries, as it includes some reserved space for the BIOS
388 * popup and for the GTT.
389 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 int gtt_entries;
391} intel_i830_private;
392
393static void intel_i830_init_gtt_entries(void)
394{
395 u16 gmch_ctrl;
396 int gtt_entries;
397 u8 rdct;
398 int local = 0;
399 static const int ddt[4] = { 0, 16, 32, 64 };
Eric Anholtc41e0de2006-12-19 12:57:24 -0800400 int size; /* reserved space (in kb) at the top of stolen memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
403
Eric Anholtc41e0de2006-12-19 12:57:24 -0800404 if (IS_I965) {
405 u32 pgetbl_ctl;
406
407 pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
408 &pgetbl_ctl);
409 /* The 965 has a field telling us the size of the GTT,
410 * which may be larger than what is necessary to map the
411 * aperture.
412 */
413 switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
414 case I965_PGETBL_SIZE_128KB:
415 size = 128;
416 break;
417 case I965_PGETBL_SIZE_256KB:
418 size = 256;
419 break;
420 case I965_PGETBL_SIZE_512KB:
421 size = 512;
422 break;
423 default:
424 printk(KERN_INFO PFX "Unknown page table size, "
425 "assuming 512KB\n");
426 size = 512;
427 }
428 size += 4; /* add in BIOS popup space */
429 } else {
430 /* On previous hardware, the GTT size was just what was
431 * required to map the aperture.
432 */
433 size = agp_bridge->driver->fetch_size() + 4;
434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
437 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
438 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
439 case I830_GMCH_GMS_STOLEN_512:
440 gtt_entries = KB(512) - KB(size);
441 break;
442 case I830_GMCH_GMS_STOLEN_1024:
443 gtt_entries = MB(1) - KB(size);
444 break;
445 case I830_GMCH_GMS_STOLEN_8192:
446 gtt_entries = MB(8) - KB(size);
447 break;
448 case I830_GMCH_GMS_LOCAL:
449 rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
450 gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
451 MB(ddt[I830_RDRAM_DDT(rdct)]);
452 local = 1;
453 break;
454 default:
455 gtt_entries = 0;
456 break;
457 }
458 } else {
459 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
460 case I855_GMCH_GMS_STOLEN_1M:
461 gtt_entries = MB(1) - KB(size);
462 break;
463 case I855_GMCH_GMS_STOLEN_4M:
464 gtt_entries = MB(4) - KB(size);
465 break;
466 case I855_GMCH_GMS_STOLEN_8M:
467 gtt_entries = MB(8) - KB(size);
468 break;
469 case I855_GMCH_GMS_STOLEN_16M:
470 gtt_entries = MB(16) - KB(size);
471 break;
472 case I855_GMCH_GMS_STOLEN_32M:
473 gtt_entries = MB(32) - KB(size);
474 break;
475 case I915_GMCH_GMS_STOLEN_48M:
476 /* Check it's really I915G */
477 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
Alan Hourihaned0de98f2005-05-31 19:50:49 +0100478 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +0000479 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
Eric Anholt65c25aa2006-09-06 11:57:18 -0400480 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 gtt_entries = MB(48) - KB(size);
482 else
483 gtt_entries = 0;
484 break;
485 case I915_GMCH_GMS_STOLEN_64M:
486 /* Check it's really I915G */
487 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
Alan Hourihaned0de98f2005-05-31 19:50:49 +0100488 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +0000489 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
Eric Anholt65c25aa2006-09-06 11:57:18 -0400490 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 gtt_entries = MB(64) - KB(size);
492 else
493 gtt_entries = 0;
494 default:
495 gtt_entries = 0;
496 break;
497 }
498 }
499 if (gtt_entries > 0)
500 printk(KERN_INFO PFX "Detected %dK %s memory.\n",
501 gtt_entries / KB(1), local ? "local" : "stolen");
502 else
503 printk(KERN_INFO PFX
504 "No pre-allocated video memory detected.\n");
505 gtt_entries /= KB(4);
506
507 intel_i830_private.gtt_entries = gtt_entries;
508}
509
510/* The intel i830 automatically initializes the agp aperture during POST.
511 * Use the memory already set aside for in the GTT.
512 */
513static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
514{
515 int page_order;
516 struct aper_size_info_fixed *size;
517 int num_entries;
518 u32 temp;
519
520 size = agp_bridge->current_size;
521 page_order = size->page_order;
522 num_entries = size->num_entries;
523 agp_bridge->gatt_table_real = NULL;
524
525 pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
526 temp &= 0xfff80000;
527
528 intel_i830_private.registers = ioremap(temp,128 * 4096);
529 if (!intel_i830_private.registers)
530 return -ENOMEM;
531
532 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
533 global_cache_flush(); /* FIXME: ?? */
534
535 /* we have to call this as early as possible after the MMIO base address is known */
536 intel_i830_init_gtt_entries();
537
538 agp_bridge->gatt_table = NULL;
539
540 agp_bridge->gatt_bus_addr = temp;
541
542 return 0;
543}
544
545/* Return the gatt table to a sane state. Use the top of stolen
546 * memory for the GTT.
547 */
548static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
549{
550 return 0;
551}
552
553static int intel_i830_fetch_size(void)
554{
555 u16 gmch_ctrl;
556 struct aper_size_info_fixed *values;
557
558 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
559
560 if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
561 agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
562 /* 855GM/852GM/865G has 128MB aperture size */
563 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
564 agp_bridge->aperture_size_idx = 0;
565 return values[0].size;
566 }
567
568 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
569
570 if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
571 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
572 agp_bridge->aperture_size_idx = 0;
573 return values[0].size;
574 } else {
575 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
576 agp_bridge->aperture_size_idx = 1;
577 return values[1].size;
578 }
579
580 return 0;
581}
582
583static int intel_i830_configure(void)
584{
585 struct aper_size_info_fixed *current_size;
586 u32 temp;
587 u16 gmch_ctrl;
588 int i;
589
590 current_size = A_SIZE_FIX(agp_bridge->current_size);
591
592 pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
593 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
594
595 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
596 gmch_ctrl |= I830_GMCH_ENABLED;
597 pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
598
599 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
600 readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
601
602 if (agp_bridge->driver->needs_scratch_page) {
603 for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
604 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
605 readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
606 }
607 }
608
609 global_cache_flush();
610 return 0;
611}
612
613static void intel_i830_cleanup(void)
614{
615 iounmap(intel_i830_private.registers);
616}
617
618static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
619{
620 int i,j,num_entries;
621 void *temp;
622
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100623 if (mem->page_count == 0)
624 return 0;
625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 temp = agp_bridge->current_size;
627 num_entries = A_SIZE_FIX(temp)->num_entries;
628
629 if (pg_start < intel_i830_private.gtt_entries) {
630 printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
631 pg_start,intel_i830_private.gtt_entries);
632
633 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
634 return -EINVAL;
635 }
636
637 if ((pg_start + mem->page_count) > num_entries)
638 return -EINVAL;
639
640 /* The i830 can't check the GTT for entries since its read only,
641 * depend on the caller to make the correct offset decisions.
642 */
643
644 if ((type != 0 && type != AGP_PHYS_MEMORY) ||
645 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
646 return -EINVAL;
647
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100648 if (!mem->is_flushed) {
649 global_cache_flush();
650 mem->is_flushed = TRUE;
651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
653 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
654 writel(agp_bridge->driver->mask_memory(agp_bridge,
655 mem->memory[i], mem->type),
656 intel_i830_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100658 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 agp_bridge->driver->tlb_flush(mem);
661 return 0;
662}
663
664static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
665 int type)
666{
667 int i;
668
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100669 if (mem->page_count == 0)
670 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
672 if (pg_start < intel_i830_private.gtt_entries) {
673 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
674 return -EINVAL;
675 }
676
677 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
678 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100680 readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 agp_bridge->driver->tlb_flush(mem);
683 return 0;
684}
685
686static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
687{
688 if (type == AGP_PHYS_MEMORY)
689 return alloc_agpphysmem_i8xx(pg_count, type);
690
691 /* always return NULL for other allocation types for now */
692 return NULL;
693}
694
695static int intel_i915_configure(void)
696{
697 struct aper_size_info_fixed *current_size;
698 u32 temp;
699 u16 gmch_ctrl;
700 int i;
701
702 current_size = A_SIZE_FIX(agp_bridge->current_size);
703
704 pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
705
706 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
707
708 pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
709 gmch_ctrl |= I830_GMCH_ENABLED;
710 pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
711
712 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
713 readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
714
715 if (agp_bridge->driver->needs_scratch_page) {
716 for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
717 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
718 readl(intel_i830_private.gtt+i); /* PCI Posting. */
719 }
720 }
721
722 global_cache_flush();
723 return 0;
724}
725
726static void intel_i915_cleanup(void)
727{
728 iounmap(intel_i830_private.gtt);
729 iounmap(intel_i830_private.registers);
730}
731
732static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
733 int type)
734{
735 int i,j,num_entries;
736 void *temp;
737
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100738 if (mem->page_count == 0)
739 return 0;
740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 temp = agp_bridge->current_size;
742 num_entries = A_SIZE_FIX(temp)->num_entries;
743
744 if (pg_start < intel_i830_private.gtt_entries) {
745 printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
746 pg_start,intel_i830_private.gtt_entries);
747
748 printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
749 return -EINVAL;
750 }
751
752 if ((pg_start + mem->page_count) > num_entries)
753 return -EINVAL;
754
755 /* The i830 can't check the GTT for entries since its read only,
756 * depend on the caller to make the correct offset decisions.
757 */
758
759 if ((type != 0 && type != AGP_PHYS_MEMORY) ||
760 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
761 return -EINVAL;
762
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100763 if (!mem->is_flushed) {
764 global_cache_flush();
765 mem->is_flushed = TRUE;
766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
769 writel(agp_bridge->driver->mask_memory(agp_bridge,
770 mem->memory[i], mem->type), intel_i830_private.gtt+j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100772 readl(intel_i830_private.gtt+j-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 agp_bridge->driver->tlb_flush(mem);
775 return 0;
776}
777
778static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
779 int type)
780{
781 int i;
782
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100783 if (mem->page_count == 0)
784 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
786 if (pg_start < intel_i830_private.gtt_entries) {
787 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
788 return -EINVAL;
789 }
790
791 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
792 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 }
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100794 readl(intel_i830_private.gtt+i-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 agp_bridge->driver->tlb_flush(mem);
797 return 0;
798}
799
Eric Anholtc41e0de2006-12-19 12:57:24 -0800800/* Return the aperture size by just checking the resource length. The effect
801 * described in the spec of the MSAC registers is just changing of the
802 * resource size.
803 */
804static int intel_i9xx_fetch_size(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
Eric Anholtc41e0de2006-12-19 12:57:24 -0800806 int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
807 int aper_size; /* size in megabytes */
808 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Eric Anholtc41e0de2006-12-19 12:57:24 -0800810 aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Eric Anholtc41e0de2006-12-19 12:57:24 -0800812 for (i = 0; i < num_sizes; i++) {
813 if (aper_size == intel_i830_sizes[i].size) {
814 agp_bridge->current_size = intel_i830_sizes + i;
815 agp_bridge->previous_size = agp_bridge->current_size;
816 return aper_size;
817 }
818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Eric Anholtc41e0de2006-12-19 12:57:24 -0800820 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821}
822
823/* The intel i915 automatically initializes the agp aperture during POST.
824 * Use the memory already set aside for in the GTT.
825 */
826static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
827{
828 int page_order;
829 struct aper_size_info_fixed *size;
830 int num_entries;
831 u32 temp, temp2;
832
833 size = agp_bridge->current_size;
834 page_order = size->page_order;
835 num_entries = size->num_entries;
836 agp_bridge->gatt_table_real = NULL;
837
838 pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
839 pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
840
841 intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
842 if (!intel_i830_private.gtt)
843 return -ENOMEM;
844
845 temp &= 0xfff80000;
846
847 intel_i830_private.registers = ioremap(temp,128 * 4096);
848 if (!intel_i830_private.registers)
849 return -ENOMEM;
850
851 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
852 global_cache_flush(); /* FIXME: ? */
853
854 /* we have to call this as early as possible after the MMIO base address is known */
855 intel_i830_init_gtt_entries();
856
857 agp_bridge->gatt_table = NULL;
858
859 agp_bridge->gatt_bus_addr = temp;
860
861 return 0;
862}
Linus Torvalds7d915a32006-11-22 09:37:54 -0800863
864/*
865 * The i965 supports 36-bit physical addresses, but to keep
866 * the format of the GTT the same, the bits that don't fit
867 * in a 32-bit word are shifted down to bits 4..7.
868 *
869 * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
870 * is always zero on 32-bit architectures, so no need to make
871 * this conditional.
872 */
873static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
874 unsigned long addr, int type)
875{
876 /* Shift high bits down */
877 addr |= (addr >> 28) & 0xf0;
878
879 /* Type checking must be done elsewhere */
880 return addr | bridge->driver->masks[type].mask;
881}
882
Eric Anholt65c25aa2006-09-06 11:57:18 -0400883/* The intel i965 automatically initializes the agp aperture during POST.
Eric Anholtc41e0de2006-12-19 12:57:24 -0800884 * Use the memory already set aside for in the GTT.
885 */
Eric Anholt65c25aa2006-09-06 11:57:18 -0400886static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
887{
888 int page_order;
889 struct aper_size_info_fixed *size;
890 int num_entries;
891 u32 temp;
892
893 size = agp_bridge->current_size;
894 page_order = size->page_order;
895 num_entries = size->num_entries;
896 agp_bridge->gatt_table_real = NULL;
897
898 pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
899
900 temp &= 0xfff00000;
901 intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
902
903 if (!intel_i830_private.gtt)
904 return -ENOMEM;
905
906
907 intel_i830_private.registers = ioremap(temp,128 * 4096);
908 if (!intel_i830_private.registers)
909 return -ENOMEM;
910
911 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
912 global_cache_flush(); /* FIXME: ? */
913
914 /* we have to call this as early as possible after the MMIO base address is known */
915 intel_i830_init_gtt_entries();
916
917 agp_bridge->gatt_table = NULL;
918
919 agp_bridge->gatt_bus_addr = temp;
920
921 return 0;
922}
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925static int intel_fetch_size(void)
926{
927 int i;
928 u16 temp;
929 struct aper_size_info_16 *values;
930
931 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
932 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
933
934 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
935 if (temp == values[i].size_value) {
936 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
937 agp_bridge->aperture_size_idx = i;
938 return values[i].size;
939 }
940 }
941
942 return 0;
943}
944
945static int __intel_8xx_fetch_size(u8 temp)
946{
947 int i;
948 struct aper_size_info_8 *values;
949
950 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
951
952 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
953 if (temp == values[i].size_value) {
954 agp_bridge->previous_size =
955 agp_bridge->current_size = (void *) (values + i);
956 agp_bridge->aperture_size_idx = i;
957 return values[i].size;
958 }
959 }
960 return 0;
961}
962
963static int intel_8xx_fetch_size(void)
964{
965 u8 temp;
966
967 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
968 return __intel_8xx_fetch_size(temp);
969}
970
971static int intel_815_fetch_size(void)
972{
973 u8 temp;
974
975 /* Intel 815 chipsets have a _weird_ APSIZE register with only
976 * one non-reserved bit, so mask the others out ... */
977 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
978 temp &= (1 << 3);
979
980 return __intel_8xx_fetch_size(temp);
981}
982
983static void intel_tlbflush(struct agp_memory *mem)
984{
985 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
986 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
987}
988
989
990static void intel_8xx_tlbflush(struct agp_memory *mem)
991{
992 u32 temp;
993 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
994 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
995 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
996 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
997}
998
999
1000static void intel_cleanup(void)
1001{
1002 u16 temp;
1003 struct aper_size_info_16 *previous_size;
1004
1005 previous_size = A_SIZE_16(agp_bridge->previous_size);
1006 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1007 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1008 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1009}
1010
1011
1012static void intel_8xx_cleanup(void)
1013{
1014 u16 temp;
1015 struct aper_size_info_8 *previous_size;
1016
1017 previous_size = A_SIZE_8(agp_bridge->previous_size);
1018 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1019 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1020 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1021}
1022
1023
1024static int intel_configure(void)
1025{
1026 u32 temp;
1027 u16 temp2;
1028 struct aper_size_info_16 *current_size;
1029
1030 current_size = A_SIZE_16(agp_bridge->current_size);
1031
1032 /* aperture size */
1033 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1034
1035 /* address to map to */
1036 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1037 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1038
1039 /* attbase - aperture base */
1040 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1041
1042 /* agpctrl */
1043 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1044
1045 /* paccfg/nbxcfg */
1046 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1047 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
1048 (temp2 & ~(1 << 10)) | (1 << 9));
1049 /* clear any possible error conditions */
1050 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
1051 return 0;
1052}
1053
1054static int intel_815_configure(void)
1055{
1056 u32 temp, addr;
1057 u8 temp2;
1058 struct aper_size_info_8 *current_size;
1059
1060 /* attbase - aperture base */
1061 /* the Intel 815 chipset spec. says that bits 29-31 in the
1062 * ATTBASE register are reserved -> try not to write them */
1063 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
1064 printk (KERN_EMERG PFX "gatt bus addr too high");
1065 return -EINVAL;
1066 }
1067
1068 current_size = A_SIZE_8(agp_bridge->current_size);
1069
1070 /* aperture size */
1071 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1072 current_size->size_value);
1073
1074 /* address to map to */
1075 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1076 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1077
1078 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
1079 addr &= INTEL_815_ATTBASE_MASK;
1080 addr |= agp_bridge->gatt_bus_addr;
1081 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
1082
1083 /* agpctrl */
1084 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1085
1086 /* apcont */
1087 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
1088 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
1089
1090 /* clear any possible error conditions */
1091 /* Oddness : this chipset seems to have no ERRSTS register ! */
1092 return 0;
1093}
1094
1095static void intel_820_tlbflush(struct agp_memory *mem)
1096{
1097 return;
1098}
1099
1100static void intel_820_cleanup(void)
1101{
1102 u8 temp;
1103 struct aper_size_info_8 *previous_size;
1104
1105 previous_size = A_SIZE_8(agp_bridge->previous_size);
1106 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
1107 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
1108 temp & ~(1 << 1));
1109 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1110 previous_size->size_value);
1111}
1112
1113
1114static int intel_820_configure(void)
1115{
1116 u32 temp;
1117 u8 temp2;
1118 struct aper_size_info_8 *current_size;
1119
1120 current_size = A_SIZE_8(agp_bridge->current_size);
1121
1122 /* aperture size */
1123 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1124
1125 /* address to map to */
1126 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1127 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1128
1129 /* attbase - aperture base */
1130 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1131
1132 /* agpctrl */
1133 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1134
1135 /* global enable aperture access */
1136 /* This flag is not accessed through MCHCFG register as in */
1137 /* i850 chipset. */
1138 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
1139 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
1140 /* clear any possible AGP-related error conditions */
1141 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
1142 return 0;
1143}
1144
1145static int intel_840_configure(void)
1146{
1147 u32 temp;
1148 u16 temp2;
1149 struct aper_size_info_8 *current_size;
1150
1151 current_size = A_SIZE_8(agp_bridge->current_size);
1152
1153 /* aperture size */
1154 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1155
1156 /* address to map to */
1157 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1158 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1159
1160 /* attbase - aperture base */
1161 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1162
1163 /* agpctrl */
1164 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1165
1166 /* mcgcfg */
1167 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
1168 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
1169 /* clear any possible error conditions */
1170 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
1171 return 0;
1172}
1173
1174static int intel_845_configure(void)
1175{
1176 u32 temp;
1177 u8 temp2;
1178 struct aper_size_info_8 *current_size;
1179
1180 current_size = A_SIZE_8(agp_bridge->current_size);
1181
1182 /* aperture size */
1183 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1184
Matthew Garrettb0825482005-07-29 14:03:39 -07001185 if (agp_bridge->apbase_config != 0) {
1186 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1187 agp_bridge->apbase_config);
1188 } else {
1189 /* address to map to */
1190 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1191 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1192 agp_bridge->apbase_config = temp;
1193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
1195 /* attbase - aperture base */
1196 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1197
1198 /* agpctrl */
1199 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1200
1201 /* agpm */
1202 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
1203 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1204 /* clear any possible error conditions */
1205 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
1206 return 0;
1207}
1208
1209static int intel_850_configure(void)
1210{
1211 u32 temp;
1212 u16 temp2;
1213 struct aper_size_info_8 *current_size;
1214
1215 current_size = A_SIZE_8(agp_bridge->current_size);
1216
1217 /* aperture size */
1218 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1219
1220 /* address to map to */
1221 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1222 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1223
1224 /* attbase - aperture base */
1225 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1226
1227 /* agpctrl */
1228 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1229
1230 /* mcgcfg */
1231 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
1232 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
1233 /* clear any possible AGP-related error conditions */
1234 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
1235 return 0;
1236}
1237
1238static int intel_860_configure(void)
1239{
1240 u32 temp;
1241 u16 temp2;
1242 struct aper_size_info_8 *current_size;
1243
1244 current_size = A_SIZE_8(agp_bridge->current_size);
1245
1246 /* aperture size */
1247 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1248
1249 /* address to map to */
1250 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1251 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1252
1253 /* attbase - aperture base */
1254 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1255
1256 /* agpctrl */
1257 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1258
1259 /* mcgcfg */
1260 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
1261 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
1262 /* clear any possible AGP-related error conditions */
1263 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
1264 return 0;
1265}
1266
1267static int intel_830mp_configure(void)
1268{
1269 u32 temp;
1270 u16 temp2;
1271 struct aper_size_info_8 *current_size;
1272
1273 current_size = A_SIZE_8(agp_bridge->current_size);
1274
1275 /* aperture size */
1276 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1277
1278 /* address to map to */
1279 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1280 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1281
1282 /* attbase - aperture base */
1283 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1284
1285 /* agpctrl */
1286 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1287
1288 /* gmch */
1289 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1290 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
1291 /* clear any possible AGP-related error conditions */
1292 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
1293 return 0;
1294}
1295
1296static int intel_7505_configure(void)
1297{
1298 u32 temp;
1299 u16 temp2;
1300 struct aper_size_info_8 *current_size;
1301
1302 current_size = A_SIZE_8(agp_bridge->current_size);
1303
1304 /* aperture size */
1305 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1306
1307 /* address to map to */
1308 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1309 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1310
1311 /* attbase - aperture base */
1312 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1313
1314 /* agpctrl */
1315 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1316
1317 /* mchcfg */
1318 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
1319 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
1320
1321 return 0;
1322}
1323
1324/* Setup function */
1325static struct gatt_mask intel_generic_masks[] =
1326{
1327 {.mask = 0x00000017, .type = 0}
1328};
1329
1330static struct aper_size_info_8 intel_815_sizes[2] =
1331{
1332 {64, 16384, 4, 0},
1333 {32, 8192, 3, 8},
1334};
1335
1336static struct aper_size_info_8 intel_8xx_sizes[7] =
1337{
1338 {256, 65536, 6, 0},
1339 {128, 32768, 5, 32},
1340 {64, 16384, 4, 48},
1341 {32, 8192, 3, 56},
1342 {16, 4096, 2, 60},
1343 {8, 2048, 1, 62},
1344 {4, 1024, 0, 63}
1345};
1346
1347static struct aper_size_info_16 intel_generic_sizes[7] =
1348{
1349 {256, 65536, 6, 0},
1350 {128, 32768, 5, 32},
1351 {64, 16384, 4, 48},
1352 {32, 8192, 3, 56},
1353 {16, 4096, 2, 60},
1354 {8, 2048, 1, 62},
1355 {4, 1024, 0, 63}
1356};
1357
1358static struct aper_size_info_8 intel_830mp_sizes[4] =
1359{
1360 {256, 65536, 6, 0},
1361 {128, 32768, 5, 32},
1362 {64, 16384, 4, 48},
1363 {32, 8192, 3, 56}
1364};
1365
1366static struct agp_bridge_driver intel_generic_driver = {
1367 .owner = THIS_MODULE,
1368 .aperture_sizes = intel_generic_sizes,
1369 .size_type = U16_APER_SIZE,
1370 .num_aperture_sizes = 7,
1371 .configure = intel_configure,
1372 .fetch_size = intel_fetch_size,
1373 .cleanup = intel_cleanup,
1374 .tlb_flush = intel_tlbflush,
1375 .mask_memory = agp_generic_mask_memory,
1376 .masks = intel_generic_masks,
1377 .agp_enable = agp_generic_enable,
1378 .cache_flush = global_cache_flush,
1379 .create_gatt_table = agp_generic_create_gatt_table,
1380 .free_gatt_table = agp_generic_free_gatt_table,
1381 .insert_memory = agp_generic_insert_memory,
1382 .remove_memory = agp_generic_remove_memory,
1383 .alloc_by_type = agp_generic_alloc_by_type,
1384 .free_by_type = agp_generic_free_by_type,
1385 .agp_alloc_page = agp_generic_alloc_page,
1386 .agp_destroy_page = agp_generic_destroy_page,
1387};
1388
1389static struct agp_bridge_driver intel_810_driver = {
1390 .owner = THIS_MODULE,
1391 .aperture_sizes = intel_i810_sizes,
1392 .size_type = FIXED_APER_SIZE,
1393 .num_aperture_sizes = 2,
1394 .needs_scratch_page = TRUE,
1395 .configure = intel_i810_configure,
1396 .fetch_size = intel_i810_fetch_size,
1397 .cleanup = intel_i810_cleanup,
1398 .tlb_flush = intel_i810_tlbflush,
1399 .mask_memory = intel_i810_mask_memory,
1400 .masks = intel_i810_masks,
1401 .agp_enable = intel_i810_agp_enable,
1402 .cache_flush = global_cache_flush,
1403 .create_gatt_table = agp_generic_create_gatt_table,
1404 .free_gatt_table = agp_generic_free_gatt_table,
1405 .insert_memory = intel_i810_insert_entries,
1406 .remove_memory = intel_i810_remove_entries,
1407 .alloc_by_type = intel_i810_alloc_by_type,
1408 .free_by_type = intel_i810_free_by_type,
1409 .agp_alloc_page = agp_generic_alloc_page,
1410 .agp_destroy_page = agp_generic_destroy_page,
1411};
1412
1413static struct agp_bridge_driver intel_815_driver = {
1414 .owner = THIS_MODULE,
1415 .aperture_sizes = intel_815_sizes,
1416 .size_type = U8_APER_SIZE,
1417 .num_aperture_sizes = 2,
1418 .configure = intel_815_configure,
1419 .fetch_size = intel_815_fetch_size,
1420 .cleanup = intel_8xx_cleanup,
1421 .tlb_flush = intel_8xx_tlbflush,
1422 .mask_memory = agp_generic_mask_memory,
1423 .masks = intel_generic_masks,
1424 .agp_enable = agp_generic_enable,
1425 .cache_flush = global_cache_flush,
1426 .create_gatt_table = agp_generic_create_gatt_table,
1427 .free_gatt_table = agp_generic_free_gatt_table,
1428 .insert_memory = agp_generic_insert_memory,
1429 .remove_memory = agp_generic_remove_memory,
1430 .alloc_by_type = agp_generic_alloc_by_type,
1431 .free_by_type = agp_generic_free_by_type,
1432 .agp_alloc_page = agp_generic_alloc_page,
1433 .agp_destroy_page = agp_generic_destroy_page,
1434};
1435
1436static struct agp_bridge_driver intel_830_driver = {
1437 .owner = THIS_MODULE,
1438 .aperture_sizes = intel_i830_sizes,
1439 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04001440 .num_aperture_sizes = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 .needs_scratch_page = TRUE,
1442 .configure = intel_i830_configure,
1443 .fetch_size = intel_i830_fetch_size,
1444 .cleanup = intel_i830_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 = intel_i830_create_gatt_table,
1451 .free_gatt_table = intel_i830_free_gatt_table,
1452 .insert_memory = intel_i830_insert_entries,
1453 .remove_memory = intel_i830_remove_entries,
1454 .alloc_by_type = intel_i830_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,
1458};
1459
1460static struct agp_bridge_driver intel_820_driver = {
1461 .owner = THIS_MODULE,
1462 .aperture_sizes = intel_8xx_sizes,
1463 .size_type = U8_APER_SIZE,
1464 .num_aperture_sizes = 7,
1465 .configure = intel_820_configure,
1466 .fetch_size = intel_8xx_fetch_size,
1467 .cleanup = intel_820_cleanup,
1468 .tlb_flush = intel_820_tlbflush,
1469 .mask_memory = agp_generic_mask_memory,
1470 .masks = intel_generic_masks,
1471 .agp_enable = agp_generic_enable,
1472 .cache_flush = global_cache_flush,
1473 .create_gatt_table = agp_generic_create_gatt_table,
1474 .free_gatt_table = agp_generic_free_gatt_table,
1475 .insert_memory = agp_generic_insert_memory,
1476 .remove_memory = agp_generic_remove_memory,
1477 .alloc_by_type = agp_generic_alloc_by_type,
1478 .free_by_type = agp_generic_free_by_type,
1479 .agp_alloc_page = agp_generic_alloc_page,
1480 .agp_destroy_page = agp_generic_destroy_page,
1481};
1482
1483static struct agp_bridge_driver intel_830mp_driver = {
1484 .owner = THIS_MODULE,
1485 .aperture_sizes = intel_830mp_sizes,
1486 .size_type = U8_APER_SIZE,
1487 .num_aperture_sizes = 4,
1488 .configure = intel_830mp_configure,
1489 .fetch_size = intel_8xx_fetch_size,
1490 .cleanup = intel_8xx_cleanup,
1491 .tlb_flush = intel_8xx_tlbflush,
1492 .mask_memory = agp_generic_mask_memory,
1493 .masks = intel_generic_masks,
1494 .agp_enable = agp_generic_enable,
1495 .cache_flush = global_cache_flush,
1496 .create_gatt_table = agp_generic_create_gatt_table,
1497 .free_gatt_table = agp_generic_free_gatt_table,
1498 .insert_memory = agp_generic_insert_memory,
1499 .remove_memory = agp_generic_remove_memory,
1500 .alloc_by_type = agp_generic_alloc_by_type,
1501 .free_by_type = agp_generic_free_by_type,
1502 .agp_alloc_page = agp_generic_alloc_page,
1503 .agp_destroy_page = agp_generic_destroy_page,
1504};
1505
1506static struct agp_bridge_driver intel_840_driver = {
1507 .owner = THIS_MODULE,
1508 .aperture_sizes = intel_8xx_sizes,
1509 .size_type = U8_APER_SIZE,
1510 .num_aperture_sizes = 7,
1511 .configure = intel_840_configure,
1512 .fetch_size = intel_8xx_fetch_size,
1513 .cleanup = intel_8xx_cleanup,
1514 .tlb_flush = intel_8xx_tlbflush,
1515 .mask_memory = agp_generic_mask_memory,
1516 .masks = intel_generic_masks,
1517 .agp_enable = agp_generic_enable,
1518 .cache_flush = global_cache_flush,
1519 .create_gatt_table = agp_generic_create_gatt_table,
1520 .free_gatt_table = agp_generic_free_gatt_table,
1521 .insert_memory = agp_generic_insert_memory,
1522 .remove_memory = agp_generic_remove_memory,
1523 .alloc_by_type = agp_generic_alloc_by_type,
1524 .free_by_type = agp_generic_free_by_type,
1525 .agp_alloc_page = agp_generic_alloc_page,
1526 .agp_destroy_page = agp_generic_destroy_page,
1527};
1528
1529static struct agp_bridge_driver intel_845_driver = {
1530 .owner = THIS_MODULE,
1531 .aperture_sizes = intel_8xx_sizes,
1532 .size_type = U8_APER_SIZE,
1533 .num_aperture_sizes = 7,
1534 .configure = intel_845_configure,
1535 .fetch_size = intel_8xx_fetch_size,
1536 .cleanup = intel_8xx_cleanup,
1537 .tlb_flush = intel_8xx_tlbflush,
1538 .mask_memory = agp_generic_mask_memory,
1539 .masks = intel_generic_masks,
1540 .agp_enable = agp_generic_enable,
1541 .cache_flush = global_cache_flush,
1542 .create_gatt_table = agp_generic_create_gatt_table,
1543 .free_gatt_table = agp_generic_free_gatt_table,
1544 .insert_memory = agp_generic_insert_memory,
1545 .remove_memory = agp_generic_remove_memory,
1546 .alloc_by_type = agp_generic_alloc_by_type,
1547 .free_by_type = agp_generic_free_by_type,
1548 .agp_alloc_page = agp_generic_alloc_page,
1549 .agp_destroy_page = agp_generic_destroy_page,
1550};
1551
1552static struct agp_bridge_driver intel_850_driver = {
1553 .owner = THIS_MODULE,
1554 .aperture_sizes = intel_8xx_sizes,
1555 .size_type = U8_APER_SIZE,
1556 .num_aperture_sizes = 7,
1557 .configure = intel_850_configure,
1558 .fetch_size = intel_8xx_fetch_size,
1559 .cleanup = intel_8xx_cleanup,
1560 .tlb_flush = intel_8xx_tlbflush,
1561 .mask_memory = agp_generic_mask_memory,
1562 .masks = intel_generic_masks,
1563 .agp_enable = agp_generic_enable,
1564 .cache_flush = global_cache_flush,
1565 .create_gatt_table = agp_generic_create_gatt_table,
1566 .free_gatt_table = agp_generic_free_gatt_table,
1567 .insert_memory = agp_generic_insert_memory,
1568 .remove_memory = agp_generic_remove_memory,
1569 .alloc_by_type = agp_generic_alloc_by_type,
1570 .free_by_type = agp_generic_free_by_type,
1571 .agp_alloc_page = agp_generic_alloc_page,
1572 .agp_destroy_page = agp_generic_destroy_page,
1573};
1574
1575static struct agp_bridge_driver intel_860_driver = {
1576 .owner = THIS_MODULE,
1577 .aperture_sizes = intel_8xx_sizes,
1578 .size_type = U8_APER_SIZE,
1579 .num_aperture_sizes = 7,
1580 .configure = intel_860_configure,
1581 .fetch_size = intel_8xx_fetch_size,
1582 .cleanup = intel_8xx_cleanup,
1583 .tlb_flush = intel_8xx_tlbflush,
1584 .mask_memory = agp_generic_mask_memory,
1585 .masks = intel_generic_masks,
1586 .agp_enable = agp_generic_enable,
1587 .cache_flush = global_cache_flush,
1588 .create_gatt_table = agp_generic_create_gatt_table,
1589 .free_gatt_table = agp_generic_free_gatt_table,
1590 .insert_memory = agp_generic_insert_memory,
1591 .remove_memory = agp_generic_remove_memory,
1592 .alloc_by_type = agp_generic_alloc_by_type,
1593 .free_by_type = agp_generic_free_by_type,
1594 .agp_alloc_page = agp_generic_alloc_page,
1595 .agp_destroy_page = agp_generic_destroy_page,
1596};
1597
1598static struct agp_bridge_driver intel_915_driver = {
1599 .owner = THIS_MODULE,
1600 .aperture_sizes = intel_i830_sizes,
1601 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04001602 .num_aperture_sizes = 4,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 .needs_scratch_page = TRUE,
1604 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08001605 .fetch_size = intel_i9xx_fetch_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 .cleanup = intel_i915_cleanup,
1607 .tlb_flush = intel_i810_tlbflush,
1608 .mask_memory = intel_i810_mask_memory,
1609 .masks = intel_i810_masks,
1610 .agp_enable = intel_i810_agp_enable,
1611 .cache_flush = global_cache_flush,
1612 .create_gatt_table = intel_i915_create_gatt_table,
1613 .free_gatt_table = intel_i830_free_gatt_table,
1614 .insert_memory = intel_i915_insert_entries,
1615 .remove_memory = intel_i915_remove_entries,
1616 .alloc_by_type = intel_i830_alloc_by_type,
1617 .free_by_type = intel_i810_free_by_type,
1618 .agp_alloc_page = agp_generic_alloc_page,
1619 .agp_destroy_page = agp_generic_destroy_page,
1620};
1621
Eric Anholt65c25aa2006-09-06 11:57:18 -04001622static struct agp_bridge_driver intel_i965_driver = {
1623 .owner = THIS_MODULE,
1624 .aperture_sizes = intel_i830_sizes,
1625 .size_type = FIXED_APER_SIZE,
1626 .num_aperture_sizes = 4,
1627 .needs_scratch_page = TRUE,
1628 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08001629 .fetch_size = intel_i9xx_fetch_size,
Eric Anholt65c25aa2006-09-06 11:57:18 -04001630 .cleanup = intel_i915_cleanup,
1631 .tlb_flush = intel_i810_tlbflush,
Linus Torvalds7d915a32006-11-22 09:37:54 -08001632 .mask_memory = intel_i965_mask_memory,
Eric Anholt65c25aa2006-09-06 11:57:18 -04001633 .masks = intel_i810_masks,
1634 .agp_enable = intel_i810_agp_enable,
1635 .cache_flush = global_cache_flush,
1636 .create_gatt_table = intel_i965_create_gatt_table,
1637 .free_gatt_table = intel_i830_free_gatt_table,
1638 .insert_memory = intel_i915_insert_entries,
1639 .remove_memory = intel_i915_remove_entries,
1640 .alloc_by_type = intel_i830_alloc_by_type,
1641 .free_by_type = intel_i810_free_by_type,
1642 .agp_alloc_page = agp_generic_alloc_page,
1643 .agp_destroy_page = agp_generic_destroy_page,
1644};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646static struct agp_bridge_driver intel_7505_driver = {
1647 .owner = THIS_MODULE,
1648 .aperture_sizes = intel_8xx_sizes,
1649 .size_type = U8_APER_SIZE,
1650 .num_aperture_sizes = 7,
1651 .configure = intel_7505_configure,
1652 .fetch_size = intel_8xx_fetch_size,
1653 .cleanup = intel_8xx_cleanup,
1654 .tlb_flush = intel_8xx_tlbflush,
1655 .mask_memory = agp_generic_mask_memory,
1656 .masks = intel_generic_masks,
1657 .agp_enable = agp_generic_enable,
1658 .cache_flush = global_cache_flush,
1659 .create_gatt_table = agp_generic_create_gatt_table,
1660 .free_gatt_table = agp_generic_free_gatt_table,
1661 .insert_memory = agp_generic_insert_memory,
1662 .remove_memory = agp_generic_remove_memory,
1663 .alloc_by_type = agp_generic_alloc_by_type,
1664 .free_by_type = agp_generic_free_by_type,
1665 .agp_alloc_page = agp_generic_alloc_page,
1666 .agp_destroy_page = agp_generic_destroy_page,
1667};
1668
1669static int find_i810(u16 device)
1670{
1671 struct pci_dev *i810_dev;
1672
1673 i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
1674 if (!i810_dev)
1675 return 0;
1676 intel_i810_private.i810_dev = i810_dev;
1677 return 1;
1678}
1679
1680static int find_i830(u16 device)
1681{
1682 struct pci_dev *i830_dev;
1683
1684 i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
1685 if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
1686 i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
1687 device, i830_dev);
1688 }
1689
1690 if (!i830_dev)
1691 return 0;
1692
1693 intel_i830_private.i830_dev = i830_dev;
1694 return 1;
1695}
1696
1697static int __devinit agp_intel_probe(struct pci_dev *pdev,
1698 const struct pci_device_id *ent)
1699{
1700 struct agp_bridge_data *bridge;
1701 char *name = "(unknown)";
1702 u8 cap_ptr = 0;
1703 struct resource *r;
1704
1705 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
1706
1707 bridge = agp_alloc_bridge();
1708 if (!bridge)
1709 return -ENOMEM;
1710
1711 switch (pdev->device) {
1712 case PCI_DEVICE_ID_INTEL_82443LX_0:
1713 bridge->driver = &intel_generic_driver;
1714 name = "440LX";
1715 break;
1716 case PCI_DEVICE_ID_INTEL_82443BX_0:
1717 bridge->driver = &intel_generic_driver;
1718 name = "440BX";
1719 break;
1720 case PCI_DEVICE_ID_INTEL_82443GX_0:
1721 bridge->driver = &intel_generic_driver;
1722 name = "440GX";
1723 break;
1724 case PCI_DEVICE_ID_INTEL_82810_MC1:
1725 name = "i810";
1726 if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
1727 goto fail;
1728 bridge->driver = &intel_810_driver;
1729 break;
1730 case PCI_DEVICE_ID_INTEL_82810_MC3:
1731 name = "i810 DC100";
1732 if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
1733 goto fail;
1734 bridge->driver = &intel_810_driver;
1735 break;
1736 case PCI_DEVICE_ID_INTEL_82810E_MC:
1737 name = "i810 E";
1738 if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
1739 goto fail;
1740 bridge->driver = &intel_810_driver;
1741 break;
1742 case PCI_DEVICE_ID_INTEL_82815_MC:
1743 /*
1744 * The i815 can operate either as an i810 style
1745 * integrated device, or as an AGP4X motherboard.
1746 */
1747 if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
1748 bridge->driver = &intel_810_driver;
1749 else
1750 bridge->driver = &intel_815_driver;
1751 name = "i815";
1752 break;
1753 case PCI_DEVICE_ID_INTEL_82820_HB:
1754 case PCI_DEVICE_ID_INTEL_82820_UP_HB:
1755 bridge->driver = &intel_820_driver;
1756 name = "i820";
1757 break;
1758 case PCI_DEVICE_ID_INTEL_82830_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001759 if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001761 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 bridge->driver = &intel_830mp_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 name = "830M";
1764 break;
1765 case PCI_DEVICE_ID_INTEL_82840_HB:
1766 bridge->driver = &intel_840_driver;
1767 name = "i840";
1768 break;
1769 case PCI_DEVICE_ID_INTEL_82845_HB:
1770 bridge->driver = &intel_845_driver;
1771 name = "i845";
1772 break;
1773 case PCI_DEVICE_ID_INTEL_82845G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001774 if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001776 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 name = "845G";
1779 break;
1780 case PCI_DEVICE_ID_INTEL_82850_HB:
1781 bridge->driver = &intel_850_driver;
1782 name = "i850";
1783 break;
1784 case PCI_DEVICE_ID_INTEL_82855PM_HB:
1785 bridge->driver = &intel_845_driver;
1786 name = "855PM";
1787 break;
1788 case PCI_DEVICE_ID_INTEL_82855GM_HB:
1789 if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
1790 bridge->driver = &intel_830_driver;
1791 name = "855";
1792 } else {
1793 bridge->driver = &intel_845_driver;
1794 name = "855GM";
1795 }
1796 break;
1797 case PCI_DEVICE_ID_INTEL_82860_HB:
1798 bridge->driver = &intel_860_driver;
1799 name = "i860";
1800 break;
1801 case PCI_DEVICE_ID_INTEL_82865_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001802 if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 bridge->driver = &intel_830_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001804 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 name = "865";
1807 break;
1808 case PCI_DEVICE_ID_INTEL_82875_HB:
1809 bridge->driver = &intel_845_driver;
1810 name = "i875";
1811 break;
1812 case PCI_DEVICE_ID_INTEL_82915G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001813 if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001815 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 name = "915G";
1818 break;
1819 case PCI_DEVICE_ID_INTEL_82915GM_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001820 if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001822 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 bridge->driver = &intel_845_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 name = "915GM";
1825 break;
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001826 case PCI_DEVICE_ID_INTEL_82945G_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001827 if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001828 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001829 else
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001830 bridge->driver = &intel_845_driver;
Alan Hourihaned0de98f2005-05-31 19:50:49 +01001831 name = "945G";
1832 break;
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001833 case PCI_DEVICE_ID_INTEL_82945GM_HB:
Dave Jones6a92a4e2006-02-28 00:54:25 -05001834 if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001835 bridge->driver = &intel_915_driver;
Dave Jones6a92a4e2006-02-28 00:54:25 -05001836 else
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001837 bridge->driver = &intel_845_driver;
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00001838 name = "945GM";
1839 break;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001840 case PCI_DEVICE_ID_INTEL_82946GZ_HB:
1841 if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
1842 bridge->driver = &intel_i965_driver;
1843 else
1844 bridge->driver = &intel_845_driver;
1845 name = "946GZ";
1846 break;
1847 case PCI_DEVICE_ID_INTEL_82965G_1_HB:
1848 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
1849 bridge->driver = &intel_i965_driver;
1850 else
1851 bridge->driver = &intel_845_driver;
1852 name = "965G";
1853 break;
1854 case PCI_DEVICE_ID_INTEL_82965Q_HB:
1855 if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
1856 bridge->driver = &intel_i965_driver;
1857 else
1858 bridge->driver = &intel_845_driver;
1859 name = "965Q";
1860 break;
1861 case PCI_DEVICE_ID_INTEL_82965G_HB:
1862 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
1863 bridge->driver = &intel_i965_driver;
1864 else
1865 bridge->driver = &intel_845_driver;
1866 name = "965G";
1867 break;
1868
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 case PCI_DEVICE_ID_INTEL_7505_0:
1870 bridge->driver = &intel_7505_driver;
1871 name = "E7505";
1872 break;
1873 case PCI_DEVICE_ID_INTEL_7205_0:
1874 bridge->driver = &intel_7505_driver;
1875 name = "E7205";
1876 break;
1877 default:
1878 if (cap_ptr)
1879 printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
1880 pdev->device);
1881 agp_put_bridge(bridge);
1882 return -ENODEV;
1883 };
1884
1885 bridge->dev = pdev;
1886 bridge->capndx = cap_ptr;
1887
1888 if (bridge->driver == &intel_810_driver)
1889 bridge->dev_private_data = &intel_i810_private;
1890 else if (bridge->driver == &intel_830_driver)
1891 bridge->dev_private_data = &intel_i830_private;
1892
1893 printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
1894
1895 /*
1896 * The following fixes the case where the BIOS has "forgotten" to
1897 * provide an address range for the GART.
1898 * 20030610 - hamish@zot.org
1899 */
1900 r = &pdev->resource[0];
1901 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -05001902 if (pci_assign_resource(pdev, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 printk(KERN_ERR PFX "could not assign resource 0\n");
1904 agp_put_bridge(bridge);
1905 return -ENODEV;
1906 }
1907 }
1908
1909 /*
1910 * If the device has not been properly setup, the following will catch
1911 * the problem and should stop the system from crashing.
1912 * 20030610 - hamish@zot.org
1913 */
1914 if (pci_enable_device(pdev)) {
1915 printk(KERN_ERR PFX "Unable to Enable PCI device\n");
1916 agp_put_bridge(bridge);
1917 return -ENODEV;
1918 }
1919
1920 /* Fill in the mode register */
1921 if (cap_ptr) {
1922 pci_read_config_dword(pdev,
1923 bridge->capndx+PCI_AGP_STATUS,
1924 &bridge->mode);
1925 }
1926
1927 pci_set_drvdata(pdev, bridge);
1928 return agp_add_bridge(bridge);
1929
1930fail:
1931 printk(KERN_ERR PFX "Detected an Intel %s chipset, "
1932 "but could not find the secondary device.\n", name);
1933 agp_put_bridge(bridge);
1934 return -ENODEV;
1935}
1936
1937static void __devexit agp_intel_remove(struct pci_dev *pdev)
1938{
1939 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
1940
1941 agp_remove_bridge(bridge);
1942
1943 if (intel_i810_private.i810_dev)
1944 pci_dev_put(intel_i810_private.i810_dev);
1945 if (intel_i830_private.i830_dev)
1946 pci_dev_put(intel_i830_private.i830_dev);
1947
1948 agp_put_bridge(bridge);
1949}
1950
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001951#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952static int agp_intel_resume(struct pci_dev *pdev)
1953{
1954 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
1955
1956 pci_restore_state(pdev);
1957
Wang Zhenyu4b953202007-01-17 11:07:54 +08001958 /* We should restore our graphics device's config space,
1959 * as host bridge (00:00) resumes before graphics device (02:00),
1960 * then our access to its pci space can work right.
1961 */
1962 if (intel_i810_private.i810_dev)
1963 pci_restore_state(intel_i810_private.i810_dev);
1964 if (intel_i830_private.i830_dev)
1965 pci_restore_state(intel_i830_private.i830_dev);
1966
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 if (bridge->driver == &intel_generic_driver)
1968 intel_configure();
1969 else if (bridge->driver == &intel_850_driver)
1970 intel_850_configure();
1971 else if (bridge->driver == &intel_845_driver)
1972 intel_845_configure();
1973 else if (bridge->driver == &intel_830mp_driver)
1974 intel_830mp_configure();
1975 else if (bridge->driver == &intel_915_driver)
1976 intel_i915_configure();
1977 else if (bridge->driver == &intel_830_driver)
1978 intel_i830_configure();
1979 else if (bridge->driver == &intel_810_driver)
1980 intel_i810_configure();
Dave Jones08da3f42006-09-10 21:09:26 -04001981 else if (bridge->driver == &intel_i965_driver)
1982 intel_i915_configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
1984 return 0;
1985}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04001986#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988static struct pci_device_id agp_intel_pci_table[] = {
1989#define ID(x) \
1990 { \
1991 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
1992 .class_mask = ~0, \
1993 .vendor = PCI_VENDOR_ID_INTEL, \
1994 .device = x, \
1995 .subvendor = PCI_ANY_ID, \
1996 .subdevice = PCI_ANY_ID, \
1997 }
1998 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
1999 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
2000 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
2001 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
2002 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
2003 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
2004 ID(PCI_DEVICE_ID_INTEL_82815_MC),
2005 ID(PCI_DEVICE_ID_INTEL_82820_HB),
2006 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
2007 ID(PCI_DEVICE_ID_INTEL_82830_HB),
2008 ID(PCI_DEVICE_ID_INTEL_82840_HB),
2009 ID(PCI_DEVICE_ID_INTEL_82845_HB),
2010 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
2011 ID(PCI_DEVICE_ID_INTEL_82850_HB),
2012 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
2013 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
2014 ID(PCI_DEVICE_ID_INTEL_82860_HB),
2015 ID(PCI_DEVICE_ID_INTEL_82865_HB),
2016 ID(PCI_DEVICE_ID_INTEL_82875_HB),
2017 ID(PCI_DEVICE_ID_INTEL_7505_0),
2018 ID(PCI_DEVICE_ID_INTEL_7205_0),
2019 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
2020 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01002021 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00002022 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002023 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
2024 ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
2025 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
2026 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 { }
2028};
2029
2030MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
2031
2032static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 .name = "agpgart-intel",
2034 .id_table = agp_intel_pci_table,
2035 .probe = agp_intel_probe,
2036 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002037#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002039#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040};
2041
2042static int __init agp_intel_init(void)
2043{
2044 if (agp_off)
2045 return -EINVAL;
2046 return pci_register_driver(&agp_intel_pci_driver);
2047}
2048
2049static void __exit agp_intel_cleanup(void)
2050{
2051 pci_unregister_driver(&agp_intel_pci_driver);
2052}
2053
2054module_init(agp_intel_init);
2055module_exit(agp_intel_cleanup);
2056
2057MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
2058MODULE_LICENSE("GPL and additional rights");