blob: f499c5e0ca5481e8cfa7d5982c75673f965bea46 [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>
Borislav Petkov48a719c2010-01-22 16:01:04 +010011#include <asm/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include "agp.h"
13
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +080014int intel_agp_enabled;
15EXPORT_SYMBOL(intel_agp_enabled);
16
Zhenyu Wang17661682009-07-27 12:59:57 +010017/*
18 * If we have Intel graphics, we're not going to have anything other than
19 * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
20 * on the Intel IOMMU support (CONFIG_DMAR).
21 * Only newer chipsets need to bother with this, of course.
22 */
23#ifdef CONFIG_DMAR
24#define USE_PCI_DMA_API 1
25#endif
26
Carlos Martíne914a362008-01-24 10:34:09 +100027#define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588
28#define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a
Eric Anholt65c25aa2006-09-06 11:57:18 -040029#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
30#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
Zhenyu Wang9119f852008-01-23 15:49:26 +100031#define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980
32#define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982
Eric Anholt65c25aa2006-09-06 11:57:18 -040033#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
34#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
35#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
36#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
Wang Zhenyu4598af32007-04-09 08:51:36 +080037#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
38#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
Zhenyu Wangdde47872007-07-26 09:18:09 +080039#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
Wang Zhenyuc8eebfd2007-05-31 11:34:06 +080040#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
Zhenyu Wangdde47872007-07-26 09:18:09 +080041#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
Wang Zhenyudf80b142007-05-31 11:51:12 +080042#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
Adam Jackson107f5172009-12-03 17:14:41 -050043#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010
44#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011
45#define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000
46#define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001
Wang Zhenyu874808c62007-06-06 11:16:25 +080047#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
48#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
49#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
50#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
51#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
52#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
Fabian Henze38d8a952009-09-08 00:59:58 +080053#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
54#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
Zhenyu Wang99d32bd2008-07-30 12:26:50 -070055#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
56#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
Adam Jackson107f5172009-12-03 17:14:41 -050057#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
58#define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02
Zhenyu Wang25ce77a2008-06-19 14:17:58 +100059#define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10
60#define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12
61#define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20
62#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
Zhenyu Wanga50ccc62008-11-17 14:39:00 +080063#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
64#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
Adam Jackson107f5172009-12-03 17:14:41 -050065#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
66#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
67#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
68#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
Dave Airlie3ff99162009-12-08 14:03:47 +100069#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
Adam Jackson107f5172009-12-03 17:14:41 -050070#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
Eric Anholt1089e302009-10-22 16:10:52 -070071#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
72#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
Eric Anholt954bce52010-01-07 16:21:46 -080073#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
74#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
Eric Anholt65c25aa2006-09-06 11:57:18 -040075
Dave Airlief011ae72008-01-25 11:23:04 +100076/* cover 915 and 945 variants */
77#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
78 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \
79 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \
80 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \
81 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \
82 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB)
83
Eric Anholt65c25aa2006-09-06 11:57:18 -040084#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
Dave Airlief011ae72008-01-25 11:23:04 +100085 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \
86 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
87 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
88 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -070089 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040090
Wang Zhenyu874808c62007-06-06 11:16:25 +080091#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
92 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
Shaohua Li21778322009-02-23 15:19:16 +080093 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -050094 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
95 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Shaohua Li21778322009-02-23 15:19:16 +080096
Adam Jackson107f5172009-12-03 17:14:41 -050097#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
98 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040099
Adam Jackson107f5172009-12-03 17:14:41 -0500100#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000101 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -0700102 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
Zhenyu Wanga50ccc62008-11-17 14:39:00 +0800103 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
Zhenyu Wang32cb0552009-06-05 15:38:36 +0800104 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
Fabian Henze38d8a952009-09-08 00:59:58 +0800105 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -0500106 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
107 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
Dave Airlie3ff99162009-12-08 14:03:47 +1000108 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
Eric Anholt1089e302009-10-22 16:10:52 -0700109 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
Eric Anholt954bce52010-01-07 16:21:46 -0800110 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
111 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000112
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100113extern int agp_memory_reserved;
114
115
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116/* Intel 815 register */
117#define INTEL_815_APCONT 0x51
118#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
119
120/* Intel i820 registers */
121#define INTEL_I820_RDCR 0x51
122#define INTEL_I820_ERRSTS 0xc8
123
124/* Intel i840 registers */
125#define INTEL_I840_MCHCFG 0x50
126#define INTEL_I840_ERRSTS 0xc8
127
128/* Intel i850 registers */
129#define INTEL_I850_MCHCFG 0x50
130#define INTEL_I850_ERRSTS 0xc8
131
132/* intel 915G registers */
133#define I915_GMADDR 0x18
134#define I915_MMADDR 0x10
135#define I915_PTEADDR 0x1C
136#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
137#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000138#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
139#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
140#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
141#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
142#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
143#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
144
Dave Airlie6c00a612007-10-29 18:06:10 +1000145#define I915_IFPADDR 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Eric Anholt65c25aa2006-09-06 11:57:18 -0400147/* Intel 965G registers */
148#define I965_MSAC 0x62
Dave Airlie6c00a612007-10-29 18:06:10 +1000149#define I965_IFPADDR 0x70
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151/* Intel 7505 registers */
152#define INTEL_I7505_APSIZE 0x74
153#define INTEL_I7505_NCAPID 0x60
154#define INTEL_I7505_NISTAT 0x6c
155#define INTEL_I7505_ATTBASE 0x78
156#define INTEL_I7505_ERRSTS 0x42
157#define INTEL_I7505_AGPCTRL 0x70
158#define INTEL_I7505_MCHCFG 0x50
159
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800160#define SNB_GMCH_CTRL 0x50
161#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
162#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
163#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
164#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
165#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
166#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
167#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
168#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
169#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
170#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
171#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
172#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
173#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
174#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
175#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
176#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
177#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
Eric Anholt285aca82010-03-18 11:24:06 -0700178#define SNB_GTT_SIZE_0M (0 << 8)
179#define SNB_GTT_SIZE_1M (1 << 8)
180#define SNB_GTT_SIZE_2M (2 << 8)
181#define SNB_GTT_SIZE_MASK (3 << 8)
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800182
Dave Jonese5524f32007-02-22 18:41:28 -0500183static const struct aper_size_info_fixed intel_i810_sizes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
185 {64, 16384, 4},
186 /* The 32M mode still requires a 64k gatt */
187 {32, 8192, 4}
188};
189
190#define AGP_DCACHE_MEMORY 1
191#define AGP_PHYS_MEMORY 2
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100192#define INTEL_AGP_CACHED_MEMORY 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194static struct gatt_mask intel_i810_masks[] =
195{
196 {.mask = I810_PTE_VALID, .type = 0},
197 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100198 {.mask = I810_PTE_VALID, .type = 0},
199 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
200 .type = INTEL_AGP_CACHED_MEMORY}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201};
202
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800203static struct _intel_private {
204 struct pci_dev *pcidev; /* device one */
205 u8 __iomem *registers;
206 u32 __iomem *gtt; /* I915G */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 int num_dcache_entries;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800208 /* gtt_entries is the number of gtt entries that are already mapped
209 * to stolen memory. Stolen memory is larger than the memory mapped
210 * through gtt_entries, as it includes some reserved space for the BIOS
211 * popup and for the GTT.
212 */
213 int gtt_entries; /* i830+ */
David Woodhousefc619012009-12-02 11:00:05 +0000214 int gtt_total_size;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000215 union {
216 void __iomem *i9xx_flush_page;
217 void *i8xx_flush_page;
218 };
219 struct page *i8xx_page;
Dave Airlie6c00a612007-10-29 18:06:10 +1000220 struct resource ifp_resource;
Dave Airlie4d64dd92008-01-23 15:34:29 +1000221 int resource_valid;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800222} intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Zhenyu Wang17661682009-07-27 12:59:57 +0100224#ifdef USE_PCI_DMA_API
David Woodhousec2980d82009-07-29 08:39:26 +0100225static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
Zhenyu Wang17661682009-07-27 12:59:57 +0100226{
David Woodhousec2980d82009-07-29 08:39:26 +0100227 *ret = pci_map_page(intel_private.pcidev, page, 0,
228 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100229 if (pci_dma_mapping_error(intel_private.pcidev, *ret))
230 return -EINVAL;
231 return 0;
232}
233
David Woodhousec2980d82009-07-29 08:39:26 +0100234static void intel_agp_unmap_page(struct page *page, dma_addr_t dma)
Zhenyu Wang17661682009-07-27 12:59:57 +0100235{
David Woodhousec2980d82009-07-29 08:39:26 +0100236 pci_unmap_page(intel_private.pcidev, dma,
237 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100238}
239
David Woodhouse91b8e302009-07-29 08:49:12 +0100240static void intel_agp_free_sglist(struct agp_memory *mem)
241{
David Woodhousef6927752009-07-29 09:28:45 +0100242 struct sg_table st;
David Woodhouse91b8e302009-07-29 08:49:12 +0100243
David Woodhousef6927752009-07-29 09:28:45 +0100244 st.sgl = mem->sg_list;
245 st.orig_nents = st.nents = mem->page_count;
246
247 sg_free_table(&st);
248
David Woodhouse91b8e302009-07-29 08:49:12 +0100249 mem->sg_list = NULL;
250 mem->num_sg = 0;
251}
252
Zhenyu Wang17661682009-07-27 12:59:57 +0100253static int intel_agp_map_memory(struct agp_memory *mem)
254{
David Woodhousef6927752009-07-29 09:28:45 +0100255 struct sg_table st;
Zhenyu Wang17661682009-07-27 12:59:57 +0100256 struct scatterlist *sg;
257 int i;
258
259 DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
260
David Woodhousef6927752009-07-29 09:28:45 +0100261 if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
Zhenyu Wang17661682009-07-27 12:59:57 +0100262 return -ENOMEM;
Zhenyu Wang17661682009-07-27 12:59:57 +0100263
David Woodhousef6927752009-07-29 09:28:45 +0100264 mem->sg_list = sg = st.sgl;
265
Zhenyu Wang17661682009-07-27 12:59:57 +0100266 for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg))
267 sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0);
268
269 mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
270 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100271 if (unlikely(!mem->num_sg)) {
272 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100273 return -ENOMEM;
274 }
275 return 0;
276}
277
278static void intel_agp_unmap_memory(struct agp_memory *mem)
279{
280 DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
281
282 pci_unmap_sg(intel_private.pcidev, mem->sg_list,
283 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100284 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100285}
286
287static void intel_agp_insert_sg_entries(struct agp_memory *mem,
288 off_t pg_start, int mask_type)
289{
290 struct scatterlist *sg;
291 int i, j;
292
293 j = pg_start;
294
295 WARN_ON(!mem->num_sg);
296
297 if (mem->num_sg == mem->page_count) {
298 for_each_sg(mem->sg_list, sg, mem->page_count, i) {
299 writel(agp_bridge->driver->mask_memory(agp_bridge,
300 sg_dma_address(sg), mask_type),
301 intel_private.gtt+j);
302 j++;
303 }
304 } else {
Daniel Mack3ad2f3f2010-02-03 08:01:28 +0800305 /* sg may merge pages, but we have to separate
Zhenyu Wang17661682009-07-27 12:59:57 +0100306 * per-page addr for GTT */
307 unsigned int len, m;
308
309 for_each_sg(mem->sg_list, sg, mem->num_sg, i) {
310 len = sg_dma_len(sg) / PAGE_SIZE;
311 for (m = 0; m < len; m++) {
312 writel(agp_bridge->driver->mask_memory(agp_bridge,
313 sg_dma_address(sg) + m * PAGE_SIZE,
314 mask_type),
315 intel_private.gtt+j);
316 j++;
317 }
318 }
319 }
320 readl(intel_private.gtt+j-1);
321}
322
323#else
324
325static void intel_agp_insert_sg_entries(struct agp_memory *mem,
326 off_t pg_start, int mask_type)
327{
328 int i, j;
Eric Anholte3deb202009-11-02 15:33:05 -0800329 u32 cache_bits = 0;
330
Eric Anholt954bce52010-01-07 16:21:46 -0800331 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
332 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
333 {
Eric Anholte3deb202009-11-02 15:33:05 -0800334 cache_bits = I830_PTE_SYSTEM_CACHED;
335 }
Zhenyu Wang17661682009-07-27 12:59:57 +0100336
337 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
338 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100339 page_to_phys(mem->pages[i]), mask_type),
Zhenyu Wang17661682009-07-27 12:59:57 +0100340 intel_private.gtt+j);
341 }
342
343 readl(intel_private.gtt+j-1);
344}
345
346#endif
347
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348static int intel_i810_fetch_size(void)
349{
350 u32 smram_miscc;
351 struct aper_size_info_fixed *values;
352
353 pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
354 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
355
356 if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700357 dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 return 0;
359 }
360 if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
361 agp_bridge->previous_size =
362 agp_bridge->current_size = (void *) (values + 1);
363 agp_bridge->aperture_size_idx = 1;
364 return values[1].size;
365 } else {
366 agp_bridge->previous_size =
367 agp_bridge->current_size = (void *) (values);
368 agp_bridge->aperture_size_idx = 0;
369 return values[0].size;
370 }
371
372 return 0;
373}
374
375static int intel_i810_configure(void)
376{
377 struct aper_size_info_fixed *current_size;
378 u32 temp;
379 int i;
380
381 current_size = A_SIZE_FIX(agp_bridge->current_size);
382
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800383 if (!intel_private.registers) {
384 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Dave Jonese4ac5e42007-02-04 17:37:42 -0500385 temp &= 0xfff80000;
386
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800387 intel_private.registers = ioremap(temp, 128 * 4096);
388 if (!intel_private.registers) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700389 dev_err(&intel_private.pcidev->dev,
390 "can't remap memory\n");
Dave Jonese4ac5e42007-02-04 17:37:42 -0500391 return -ENOMEM;
392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800395 if ((readl(intel_private.registers+I810_DRAM_CTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
397 /* This will need to be dynamically assigned */
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700398 dev_info(&intel_private.pcidev->dev,
399 "detected 4MB dedicated video ram\n");
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800400 intel_private.num_dcache_entries = 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800402 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800404 writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
405 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 if (agp_bridge->driver->needs_scratch_page) {
408 for (i = 0; i < current_size->num_entries; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800409 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
Keith Packard44d49442008-10-14 17:18:45 -0700411 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 }
413 global_cache_flush();
414 return 0;
415}
416
417static void intel_i810_cleanup(void)
418{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800419 writel(0, intel_private.registers+I810_PGETBL_CTL);
420 readl(intel_private.registers); /* PCI Posting. */
421 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422}
423
424static void intel_i810_tlbflush(struct agp_memory *mem)
425{
426 return;
427}
428
429static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
430{
431 return;
432}
433
434/* Exists to support ARGB cursors */
Dave Airlie07613ba2009-06-12 14:11:41 +1000435static struct page *i8xx_alloc_pages(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
Dave Airlief011ae72008-01-25 11:23:04 +1000437 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Linus Torvalds66c669b2006-11-22 14:55:29 -0800439 page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 if (page == NULL)
441 return NULL;
442
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100443 if (set_pages_uc(page, 4) < 0) {
444 set_pages_wb(page, 4);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100445 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 return NULL;
447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 get_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 atomic_inc(&agp_bridge->current_memory_agp);
Dave Airlie07613ba2009-06-12 14:11:41 +1000450 return page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451}
452
Dave Airlie07613ba2009-06-12 14:11:41 +1000453static void i8xx_destroy_pages(struct page *page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
Dave Airlie07613ba2009-06-12 14:11:41 +1000455 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 return;
457
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100458 set_pages_wb(page, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 put_page(page);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100460 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 atomic_dec(&agp_bridge->current_memory_agp);
462}
463
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100464static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
465 int type)
466{
467 if (type < AGP_USER_TYPES)
468 return type;
469 else if (type == AGP_USER_CACHED_MEMORY)
470 return INTEL_AGP_CACHED_MEMORY;
471 else
472 return 0;
473}
474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
476 int type)
477{
478 int i, j, num_entries;
479 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100480 int ret = -EINVAL;
481 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100483 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100484 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 temp = agp_bridge->current_size;
487 num_entries = A_SIZE_FIX(temp)->num_entries;
488
Dave Jones6a92a4e2006-02-28 00:54:25 -0500489 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100490 goto out_err;
491
Dave Jones6a92a4e2006-02-28 00:54:25 -0500492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100494 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
495 ret = -EBUSY;
496 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100500 if (type != mem->type)
501 goto out_err;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100502
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100503 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
504
505 switch (mask_type) {
506 case AGP_DCACHE_MEMORY:
507 if (!mem->is_flushed)
508 global_cache_flush();
509 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
510 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800511 intel_private.registers+I810_PTE_BASE+(i*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100512 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800513 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100514 break;
515 case AGP_PHYS_MEMORY:
516 case AGP_NORMAL_MEMORY:
517 if (!mem->is_flushed)
518 global_cache_flush();
519 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
520 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100521 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800522 intel_private.registers+I810_PTE_BASE+(j*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100523 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800524 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100525 break;
526 default:
527 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
530 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100531out:
532 ret = 0;
533out_err:
Dave Airlie9516b032008-06-19 10:42:17 +1000534 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100535 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536}
537
538static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
539 int type)
540{
541 int i;
542
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100543 if (mem->page_count == 0)
544 return 0;
545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800547 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800549 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 agp_bridge->driver->tlb_flush(mem);
552 return 0;
553}
554
555/*
556 * The i810/i830 requires a physical address to program its mouse
557 * pointer into hardware.
558 * However the Xserver still writes to it through the agp aperture.
559 */
560static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
561{
562 struct agp_memory *new;
Dave Airlie07613ba2009-06-12 14:11:41 +1000563 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 switch (pg_count) {
Dave Airlie07613ba2009-06-12 14:11:41 +1000566 case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 break;
568 case 4:
569 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000570 page = i8xx_alloc_pages();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 break;
572 default:
573 return NULL;
574 }
575
Dave Airlie07613ba2009-06-12 14:11:41 +1000576 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 return NULL;
578
579 new = agp_create_memory(pg_count);
580 if (new == NULL)
581 return NULL;
582
Dave Airlie07613ba2009-06-12 14:11:41 +1000583 new->pages[0] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 if (pg_count == 4) {
585 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000586 new->pages[1] = new->pages[0] + 1;
587 new->pages[2] = new->pages[1] + 1;
588 new->pages[3] = new->pages[2] + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 }
590 new->page_count = pg_count;
591 new->num_scratch_pages = pg_count;
592 new->type = AGP_PHYS_MEMORY;
Dave Airlie07613ba2009-06-12 14:11:41 +1000593 new->physical = page_to_phys(new->pages[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 return new;
595}
596
597static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
598{
599 struct agp_memory *new;
600
601 if (type == AGP_DCACHE_MEMORY) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800602 if (pg_count != intel_private.num_dcache_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 return NULL;
604
605 new = agp_create_memory(1);
606 if (new == NULL)
607 return NULL;
608
609 new->type = AGP_DCACHE_MEMORY;
610 new->page_count = pg_count;
611 new->num_scratch_pages = 0;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100612 agp_free_page_array(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 return new;
614 }
615 if (type == AGP_PHYS_MEMORY)
616 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 return NULL;
618}
619
620static void intel_i810_free_by_type(struct agp_memory *curr)
621{
622 agp_free_key(curr->key);
Dave Jones6a92a4e2006-02-28 00:54:25 -0500623 if (curr->type == AGP_PHYS_MEMORY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 if (curr->page_count == 4)
Dave Airlie07613ba2009-06-12 14:11:41 +1000625 i8xx_destroy_pages(curr->pages[0]);
Alan Hourihane88d51962005-11-06 23:35:34 -0800626 else {
Dave Airlie07613ba2009-06-12 14:11:41 +1000627 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000628 AGP_PAGE_DESTROY_UNMAP);
Dave Airlie07613ba2009-06-12 14:11:41 +1000629 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000630 AGP_PAGE_DESTROY_FREE);
Alan Hourihane88d51962005-11-06 23:35:34 -0800631 }
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100632 agp_free_page_array(curr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 }
634 kfree(curr);
635}
636
637static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +0100638 dma_addr_t addr, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
640 /* Type checking must be done elsewhere */
641 return addr | bridge->driver->masks[type].mask;
642}
643
644static struct aper_size_info_fixed intel_i830_sizes[] =
645{
646 {128, 32768, 5},
647 /* The 64M mode still requires a 128k gatt */
648 {64, 16384, 5},
649 {256, 65536, 6},
Eric Anholt65c25aa2006-09-06 11:57:18 -0400650 {512, 131072, 7},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651};
652
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653static void intel_i830_init_gtt_entries(void)
654{
655 u16 gmch_ctrl;
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800656 int gtt_entries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 u8 rdct;
658 int local = 0;
659 static const int ddt[4] = { 0, 16, 32, 64 };
Eric Anholtc41e0de2006-12-19 12:57:24 -0800660 int size; /* reserved space (in kb) at the top of stolen memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Dave Airlief011ae72008-01-25 11:23:04 +1000662 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Eric Anholtc41e0de2006-12-19 12:57:24 -0800664 if (IS_I965) {
665 u32 pgetbl_ctl;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800666 pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
Eric Anholtc41e0de2006-12-19 12:57:24 -0800667
Eric Anholtc41e0de2006-12-19 12:57:24 -0800668 /* The 965 has a field telling us the size of the GTT,
669 * which may be larger than what is necessary to map the
670 * aperture.
671 */
672 switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
673 case I965_PGETBL_SIZE_128KB:
674 size = 128;
675 break;
676 case I965_PGETBL_SIZE_256KB:
677 size = 256;
678 break;
679 case I965_PGETBL_SIZE_512KB:
680 size = 512;
681 break;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +1000682 case I965_PGETBL_SIZE_1MB:
683 size = 1024;
684 break;
685 case I965_PGETBL_SIZE_2MB:
686 size = 2048;
687 break;
688 case I965_PGETBL_SIZE_1_5MB:
689 size = 1024 + 512;
690 break;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800691 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700692 dev_info(&intel_private.pcidev->dev,
693 "unknown page table size, assuming 512KB\n");
Eric Anholtc41e0de2006-12-19 12:57:24 -0800694 size = 512;
695 }
696 size += 4; /* add in BIOS popup space */
Adam Jackson107f5172009-12-03 17:14:41 -0500697 } else if (IS_G33 && !IS_PINEVIEW) {
Wang Zhenyu874808c62007-06-06 11:16:25 +0800698 /* G33's GTT size defined in gmch_ctrl */
699 switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
700 case G33_PGETBL_SIZE_1M:
701 size = 1024;
702 break;
703 case G33_PGETBL_SIZE_2M:
704 size = 2048;
705 break;
706 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700707 dev_info(&agp_bridge->dev->dev,
708 "unknown page table size 0x%x, assuming 512KB\n",
Wang Zhenyu874808c62007-06-06 11:16:25 +0800709 (gmch_ctrl & G33_PGETBL_SIZE_MASK));
710 size = 512;
711 }
712 size += 4;
Adam Jackson107f5172009-12-03 17:14:41 -0500713 } else if (IS_G4X || IS_PINEVIEW) {
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000714 /* On 4 series hardware, GTT stolen is separate from graphics
Eric Anholt82e14a62008-10-14 11:28:58 -0700715 * stolen, ignore it in stolen gtt entries counting. However,
716 * 4KB of the stolen memory doesn't get mapped to the GTT.
717 */
718 size = 4;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800719 } else {
720 /* On previous hardware, the GTT size was just what was
721 * required to map the aperture.
722 */
723 size = agp_bridge->driver->fetch_size() + 4;
724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
727 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
728 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
729 case I830_GMCH_GMS_STOLEN_512:
730 gtt_entries = KB(512) - KB(size);
731 break;
732 case I830_GMCH_GMS_STOLEN_1024:
733 gtt_entries = MB(1) - KB(size);
734 break;
735 case I830_GMCH_GMS_STOLEN_8192:
736 gtt_entries = MB(8) - KB(size);
737 break;
738 case I830_GMCH_GMS_LOCAL:
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800739 rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
741 MB(ddt[I830_RDRAM_DDT(rdct)]);
742 local = 1;
743 break;
744 default:
745 gtt_entries = 0;
746 break;
747 }
Eric Anholt954bce52010-01-07 16:21:46 -0800748 } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
749 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800750 /*
751 * SandyBridge has new memory control reg at 0x50.w
Eric Anholt1089e302009-10-22 16:10:52 -0700752 */
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800753 u16 snb_gmch_ctl;
754 pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
755 switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
756 case SNB_GMCH_GMS_STOLEN_32M:
757 gtt_entries = MB(32) - KB(size);
758 break;
759 case SNB_GMCH_GMS_STOLEN_64M:
760 gtt_entries = MB(64) - KB(size);
761 break;
762 case SNB_GMCH_GMS_STOLEN_96M:
763 gtt_entries = MB(96) - KB(size);
764 break;
765 case SNB_GMCH_GMS_STOLEN_128M:
766 gtt_entries = MB(128) - KB(size);
767 break;
768 case SNB_GMCH_GMS_STOLEN_160M:
769 gtt_entries = MB(160) - KB(size);
770 break;
771 case SNB_GMCH_GMS_STOLEN_192M:
772 gtt_entries = MB(192) - KB(size);
773 break;
774 case SNB_GMCH_GMS_STOLEN_224M:
775 gtt_entries = MB(224) - KB(size);
776 break;
777 case SNB_GMCH_GMS_STOLEN_256M:
778 gtt_entries = MB(256) - KB(size);
779 break;
780 case SNB_GMCH_GMS_STOLEN_288M:
781 gtt_entries = MB(288) - KB(size);
782 break;
783 case SNB_GMCH_GMS_STOLEN_320M:
784 gtt_entries = MB(320) - KB(size);
785 break;
786 case SNB_GMCH_GMS_STOLEN_352M:
787 gtt_entries = MB(352) - KB(size);
788 break;
789 case SNB_GMCH_GMS_STOLEN_384M:
790 gtt_entries = MB(384) - KB(size);
791 break;
792 case SNB_GMCH_GMS_STOLEN_416M:
793 gtt_entries = MB(416) - KB(size);
794 break;
795 case SNB_GMCH_GMS_STOLEN_448M:
796 gtt_entries = MB(448) - KB(size);
797 break;
798 case SNB_GMCH_GMS_STOLEN_480M:
799 gtt_entries = MB(480) - KB(size);
800 break;
801 case SNB_GMCH_GMS_STOLEN_512M:
802 gtt_entries = MB(512) - KB(size);
803 break;
804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 } else {
Dave Airliee67aa272007-09-18 22:46:35 -0700806 switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 case I855_GMCH_GMS_STOLEN_1M:
808 gtt_entries = MB(1) - KB(size);
809 break;
810 case I855_GMCH_GMS_STOLEN_4M:
811 gtt_entries = MB(4) - KB(size);
812 break;
813 case I855_GMCH_GMS_STOLEN_8M:
814 gtt_entries = MB(8) - KB(size);
815 break;
816 case I855_GMCH_GMS_STOLEN_16M:
817 gtt_entries = MB(16) - KB(size);
818 break;
819 case I855_GMCH_GMS_STOLEN_32M:
820 gtt_entries = MB(32) - KB(size);
821 break;
822 case I915_GMCH_GMS_STOLEN_48M:
823 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000824 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 gtt_entries = MB(48) - KB(size);
826 else
827 gtt_entries = 0;
828 break;
829 case I915_GMCH_GMS_STOLEN_64M:
830 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000831 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 gtt_entries = MB(64) - KB(size);
833 else
834 gtt_entries = 0;
Wang Zhenyu874808c62007-06-06 11:16:25 +0800835 break;
836 case G33_GMCH_GMS_STOLEN_128M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000837 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800838 gtt_entries = MB(128) - KB(size);
839 else
840 gtt_entries = 0;
841 break;
842 case G33_GMCH_GMS_STOLEN_256M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000843 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800844 gtt_entries = MB(256) - KB(size);
845 else
846 gtt_entries = 0;
847 break;
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000848 case INTEL_GMCH_GMS_STOLEN_96M:
849 if (IS_I965 || IS_G4X)
850 gtt_entries = MB(96) - KB(size);
851 else
852 gtt_entries = 0;
853 break;
854 case INTEL_GMCH_GMS_STOLEN_160M:
855 if (IS_I965 || IS_G4X)
856 gtt_entries = MB(160) - KB(size);
857 else
858 gtt_entries = 0;
859 break;
860 case INTEL_GMCH_GMS_STOLEN_224M:
861 if (IS_I965 || IS_G4X)
862 gtt_entries = MB(224) - KB(size);
863 else
864 gtt_entries = 0;
865 break;
866 case INTEL_GMCH_GMS_STOLEN_352M:
867 if (IS_I965 || IS_G4X)
868 gtt_entries = MB(352) - KB(size);
869 else
870 gtt_entries = 0;
871 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 default:
873 gtt_entries = 0;
874 break;
875 }
876 }
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700877 if (gtt_entries > 0) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700878 dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 gtt_entries / KB(1), local ? "local" : "stolen");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700880 gtt_entries /= KB(4);
881 } else {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700882 dev_info(&agp_bridge->dev->dev,
883 "no pre-allocated video memory detected\n");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700884 gtt_entries = 0;
885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800887 intel_private.gtt_entries = gtt_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888}
889
Dave Airlie2162e6a2007-11-21 16:36:31 +1000890static void intel_i830_fini_flush(void)
891{
892 kunmap(intel_private.i8xx_page);
893 intel_private.i8xx_flush_page = NULL;
894 unmap_page_from_agp(intel_private.i8xx_page);
Dave Airlie2162e6a2007-11-21 16:36:31 +1000895
896 __free_page(intel_private.i8xx_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +1000897 intel_private.i8xx_page = NULL;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000898}
899
900static void intel_i830_setup_flush(void)
901{
Dave Airlie4d64dd92008-01-23 15:34:29 +1000902 /* return if we've already set the flush mechanism up */
903 if (intel_private.i8xx_page)
904 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000905
906 intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
Dave Airlief011ae72008-01-25 11:23:04 +1000907 if (!intel_private.i8xx_page)
Dave Airlie2162e6a2007-11-21 16:36:31 +1000908 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000909
Dave Airlie2162e6a2007-11-21 16:36:31 +1000910 intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
911 if (!intel_private.i8xx_flush_page)
912 intel_i830_fini_flush();
913}
914
Eric Anholte517a5e2009-09-10 17:48:48 -0700915/* The chipset_flush interface needs to get data that has already been
916 * flushed out of the CPU all the way out to main memory, because the GPU
917 * doesn't snoop those buffers.
918 *
919 * The 8xx series doesn't have the same lovely interface for flushing the
920 * chipset write buffers that the later chips do. According to the 865
921 * specs, it's 64 octwords, or 1KB. So, to get those previous things in
922 * that buffer out, we just fill 1KB and clflush it out, on the assumption
923 * that it'll push whatever was in there out. It appears to work.
924 */
Dave Airlie2162e6a2007-11-21 16:36:31 +1000925static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
926{
927 unsigned int *pg = intel_private.i8xx_flush_page;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000928
Eric Anholte517a5e2009-09-10 17:48:48 -0700929 memset(pg, 0, 1024);
Dave Airlief011ae72008-01-25 11:23:04 +1000930
Borislav Petkov48a719c2010-01-22 16:01:04 +0100931 if (cpu_has_clflush)
Eric Anholte517a5e2009-09-10 17:48:48 -0700932 clflush_cache_range(pg, 1024);
Borislav Petkov48a719c2010-01-22 16:01:04 +0100933 else if (wbinvd_on_all_cpus() != 0)
934 printk(KERN_ERR "Timed out waiting for cache flush.\n");
Dave Airlie2162e6a2007-11-21 16:36:31 +1000935}
936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937/* The intel i830 automatically initializes the agp aperture during POST.
938 * Use the memory already set aside for in the GTT.
939 */
940static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
941{
942 int page_order;
943 struct aper_size_info_fixed *size;
944 int num_entries;
945 u32 temp;
946
947 size = agp_bridge->current_size;
948 page_order = size->page_order;
949 num_entries = size->num_entries;
950 agp_bridge->gatt_table_real = NULL;
951
Dave Airlief011ae72008-01-25 11:23:04 +1000952 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 temp &= 0xfff80000;
954
Dave Airlief011ae72008-01-25 11:23:04 +1000955 intel_private.registers = ioremap(temp, 128 * 4096);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800956 if (!intel_private.registers)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return -ENOMEM;
958
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800959 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 global_cache_flush(); /* FIXME: ?? */
961
962 /* we have to call this as early as possible after the MMIO base address is known */
963 intel_i830_init_gtt_entries();
964
965 agp_bridge->gatt_table = NULL;
966
967 agp_bridge->gatt_bus_addr = temp;
968
969 return 0;
970}
971
972/* Return the gatt table to a sane state. Use the top of stolen
973 * memory for the GTT.
974 */
975static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
976{
977 return 0;
978}
979
980static int intel_i830_fetch_size(void)
981{
982 u16 gmch_ctrl;
983 struct aper_size_info_fixed *values;
984
985 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
986
987 if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
988 agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
989 /* 855GM/852GM/865G has 128MB aperture size */
990 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
991 agp_bridge->aperture_size_idx = 0;
992 return values[0].size;
993 }
994
Dave Airlief011ae72008-01-25 11:23:04 +1000995 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
998 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
999 agp_bridge->aperture_size_idx = 0;
1000 return values[0].size;
1001 } else {
1002 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
1003 agp_bridge->aperture_size_idx = 1;
1004 return values[1].size;
1005 }
1006
1007 return 0;
1008}
1009
1010static int intel_i830_configure(void)
1011{
1012 struct aper_size_info_fixed *current_size;
1013 u32 temp;
1014 u16 gmch_ctrl;
1015 int i;
1016
1017 current_size = A_SIZE_FIX(agp_bridge->current_size);
1018
Dave Airlief011ae72008-01-25 11:23:04 +10001019 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1021
Dave Airlief011ae72008-01-25 11:23:04 +10001022 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001024 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001026 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1027 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 if (agp_bridge->driver->needs_scratch_page) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001030 for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
1031 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 }
Keith Packard44d49442008-10-14 17:18:45 -07001033 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
1035
1036 global_cache_flush();
Dave Airlie2162e6a2007-11-21 16:36:31 +10001037
1038 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 return 0;
1040}
1041
1042static void intel_i830_cleanup(void)
1043{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001044 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045}
1046
Dave Airlief011ae72008-01-25 11:23:04 +10001047static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
1048 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
Dave Airlief011ae72008-01-25 11:23:04 +10001050 int i, j, num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001052 int ret = -EINVAL;
1053 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001055 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001056 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 temp = agp_bridge->current_size;
1059 num_entries = A_SIZE_FIX(temp)->num_entries;
1060
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001061 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001062 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1063 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1064 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001066 dev_info(&intel_private.pcidev->dev,
1067 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001068 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
1070
1071 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001072 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074 /* The i830 can't check the GTT for entries since its read only,
1075 * depend on the caller to make the correct offset decisions.
1076 */
1077
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001078 if (type != mem->type)
1079 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001081 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1082
1083 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1084 mask_type != INTEL_AGP_CACHED_MEMORY)
1085 goto out_err;
1086
1087 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001088 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1091 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +01001092 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001093 intel_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001095 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001097
1098out:
1099 ret = 0;
1100out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001101 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001102 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
Dave Airlief011ae72008-01-25 11:23:04 +10001105static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
1106 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
1108 int i;
1109
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001110 if (mem->page_count == 0)
1111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001113 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001114 dev_info(&intel_private.pcidev->dev,
1115 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return -EINVAL;
1117 }
1118
1119 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001120 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001122 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 agp_bridge->driver->tlb_flush(mem);
1125 return 0;
1126}
1127
Dave Airlief011ae72008-01-25 11:23:04 +10001128static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 if (type == AGP_PHYS_MEMORY)
1131 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 /* always return NULL for other allocation types for now */
1133 return NULL;
1134}
1135
Dave Airlie6c00a612007-10-29 18:06:10 +10001136static int intel_alloc_chipset_flush_resource(void)
1137{
1138 int ret;
1139 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
1140 PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
1141 pcibios_align_resource, agp_bridge->dev);
Dave Airlie6c00a612007-10-29 18:06:10 +10001142
Dave Airlie2162e6a2007-11-21 16:36:31 +10001143 return ret;
Dave Airlie6c00a612007-10-29 18:06:10 +10001144}
1145
1146static void intel_i915_setup_chipset_flush(void)
1147{
1148 int ret;
1149 u32 temp;
1150
1151 pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
1152 if (!(temp & 0x1)) {
1153 intel_alloc_chipset_flush_resource();
Dave Airlie4d64dd92008-01-23 15:34:29 +10001154 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001155 pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
1156 } else {
1157 temp &= ~1;
1158
Dave Airlie4d64dd92008-01-23 15:34:29 +10001159 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001160 intel_private.ifp_resource.start = temp;
1161 intel_private.ifp_resource.end = temp + PAGE_SIZE;
1162 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001163 /* some BIOSes reserve this area in a pnp some don't */
1164 if (ret)
1165 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001166 }
1167}
1168
1169static void intel_i965_g33_setup_chipset_flush(void)
1170{
1171 u32 temp_hi, temp_lo;
1172 int ret;
1173
1174 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
1175 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
1176
1177 if (!(temp_lo & 0x1)) {
1178
1179 intel_alloc_chipset_flush_resource();
1180
Dave Airlie4d64dd92008-01-23 15:34:29 +10001181 intel_private.resource_valid = 1;
Andrew Morton1fa4db72007-11-29 10:00:48 +10001182 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4,
1183 upper_32_bits(intel_private.ifp_resource.start));
Dave Airlie6c00a612007-10-29 18:06:10 +10001184 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
Dave Airlie6c00a612007-10-29 18:06:10 +10001185 } else {
1186 u64 l64;
Dave Airlief011ae72008-01-25 11:23:04 +10001187
Dave Airlie6c00a612007-10-29 18:06:10 +10001188 temp_lo &= ~0x1;
1189 l64 = ((u64)temp_hi << 32) | temp_lo;
1190
Dave Airlie4d64dd92008-01-23 15:34:29 +10001191 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001192 intel_private.ifp_resource.start = l64;
1193 intel_private.ifp_resource.end = l64 + PAGE_SIZE;
1194 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001195 /* some BIOSes reserve this area in a pnp some don't */
1196 if (ret)
1197 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001198 }
1199}
1200
Dave Airlie2162e6a2007-11-21 16:36:31 +10001201static void intel_i9xx_setup_flush(void)
1202{
Dave Airlie4d64dd92008-01-23 15:34:29 +10001203 /* return if already configured */
1204 if (intel_private.ifp_resource.start)
1205 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +10001206
Dave Airlie4d64dd92008-01-23 15:34:29 +10001207 /* setup a resource for this object */
Dave Airlie2162e6a2007-11-21 16:36:31 +10001208 intel_private.ifp_resource.name = "Intel Flush Page";
1209 intel_private.ifp_resource.flags = IORESOURCE_MEM;
1210
1211 /* Setup chipset flush for 915 */
Zhenyu Wang7d15ddf2008-06-20 11:48:06 +10001212 if (IS_I965 || IS_G33 || IS_G4X) {
Dave Airlie2162e6a2007-11-21 16:36:31 +10001213 intel_i965_g33_setup_chipset_flush();
1214 } else {
1215 intel_i915_setup_chipset_flush();
1216 }
1217
1218 if (intel_private.ifp_resource.start) {
1219 intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
1220 if (!intel_private.i9xx_flush_page)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001221 dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
Dave Airlie2162e6a2007-11-21 16:36:31 +10001222 }
1223}
1224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225static int intel_i915_configure(void)
1226{
1227 struct aper_size_info_fixed *current_size;
1228 u32 temp;
1229 u16 gmch_ctrl;
1230 int i;
1231
1232 current_size = A_SIZE_FIX(agp_bridge->current_size);
1233
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001234 pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
1236 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1237
Dave Airlief011ae72008-01-25 11:23:04 +10001238 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001240 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001242 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1243 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245 if (agp_bridge->driver->needs_scratch_page) {
David Woodhousefc619012009-12-02 11:00:05 +00001246 for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001247 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 }
Keith Packard44d49442008-10-14 17:18:45 -07001249 readl(intel_private.gtt+i-1); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 }
1251
1252 global_cache_flush();
Dave Airlie6c00a612007-10-29 18:06:10 +10001253
Dave Airlie2162e6a2007-11-21 16:36:31 +10001254 intel_i9xx_setup_flush();
Dave Airlief011ae72008-01-25 11:23:04 +10001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return 0;
1257}
1258
1259static void intel_i915_cleanup(void)
1260{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001261 if (intel_private.i9xx_flush_page)
1262 iounmap(intel_private.i9xx_flush_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001263 if (intel_private.resource_valid)
1264 release_resource(&intel_private.ifp_resource);
1265 intel_private.ifp_resource.start = 0;
1266 intel_private.resource_valid = 0;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001267 iounmap(intel_private.gtt);
1268 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269}
1270
Dave Airlie6c00a612007-10-29 18:06:10 +10001271static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
1272{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001273 if (intel_private.i9xx_flush_page)
1274 writel(1, intel_private.i9xx_flush_page);
Dave Airlie6c00a612007-10-29 18:06:10 +10001275}
1276
Dave Airlief011ae72008-01-25 11:23:04 +10001277static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
1278 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279{
Zhenyu Wang17661682009-07-27 12:59:57 +01001280 int num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001282 int ret = -EINVAL;
1283 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001285 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001286 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 temp = agp_bridge->current_size;
1289 num_entries = A_SIZE_FIX(temp)->num_entries;
1290
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001291 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001292 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1293 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1294 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001296 dev_info(&intel_private.pcidev->dev,
1297 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001298 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
1301 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001302 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Zhenyu Wang17661682009-07-27 12:59:57 +01001304 /* The i915 can't check the GTT for entries since it's read only;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 * depend on the caller to make the correct offset decisions.
1306 */
1307
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001308 if (type != mem->type)
1309 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001311 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1312
1313 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1314 mask_type != INTEL_AGP_CACHED_MEMORY)
1315 goto out_err;
1316
1317 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001318 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Zhenyu Wang17661682009-07-27 12:59:57 +01001320 intel_agp_insert_sg_entries(mem, pg_start, mask_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001322
1323 out:
1324 ret = 0;
1325 out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001326 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001327 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328}
1329
Dave Airlief011ae72008-01-25 11:23:04 +10001330static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
1331 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
1333 int i;
1334
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001335 if (mem->page_count == 0)
1336 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001338 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001339 dev_info(&intel_private.pcidev->dev,
1340 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return -EINVAL;
1342 }
1343
Dave Airlief011ae72008-01-25 11:23:04 +10001344 for (i = pg_start; i < (mem->page_count + pg_start); i++)
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001345 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Dave Airlief011ae72008-01-25 11:23:04 +10001346
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001347 readl(intel_private.gtt+i-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 agp_bridge->driver->tlb_flush(mem);
1350 return 0;
1351}
1352
Eric Anholtc41e0de2006-12-19 12:57:24 -08001353/* Return the aperture size by just checking the resource length. The effect
1354 * described in the spec of the MSAC registers is just changing of the
1355 * resource size.
1356 */
1357static int intel_i9xx_fetch_size(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02001359 int num_sizes = ARRAY_SIZE(intel_i830_sizes);
Eric Anholtc41e0de2006-12-19 12:57:24 -08001360 int aper_size; /* size in megabytes */
1361 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001363 aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Eric Anholtc41e0de2006-12-19 12:57:24 -08001365 for (i = 0; i < num_sizes; i++) {
1366 if (aper_size == intel_i830_sizes[i].size) {
1367 agp_bridge->current_size = intel_i830_sizes + i;
1368 agp_bridge->previous_size = agp_bridge->current_size;
1369 return aper_size;
1370 }
1371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Eric Anholtc41e0de2006-12-19 12:57:24 -08001373 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374}
1375
1376/* The intel i915 automatically initializes the agp aperture during POST.
1377 * Use the memory already set aside for in the GTT.
1378 */
1379static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1380{
1381 int page_order;
1382 struct aper_size_info_fixed *size;
1383 int num_entries;
1384 u32 temp, temp2;
Zhenyu Wang47406222007-09-11 15:23:58 -07001385 int gtt_map_size = 256 * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 size = agp_bridge->current_size;
1388 page_order = size->page_order;
1389 num_entries = size->num_entries;
1390 agp_bridge->gatt_table_real = NULL;
1391
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001392 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Dave Airlief011ae72008-01-25 11:23:04 +10001393 pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Zhenyu Wang47406222007-09-11 15:23:58 -07001395 if (IS_G33)
1396 gtt_map_size = 1024 * 1024; /* 1M on G33 */
1397 intel_private.gtt = ioremap(temp2, gtt_map_size);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001398 if (!intel_private.gtt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 return -ENOMEM;
1400
David Woodhousefc619012009-12-02 11:00:05 +00001401 intel_private.gtt_total_size = gtt_map_size / 4;
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 temp &= 0xfff80000;
1404
Dave Airlief011ae72008-01-25 11:23:04 +10001405 intel_private.registers = ioremap(temp, 128 * 4096);
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001406 if (!intel_private.registers) {
1407 iounmap(intel_private.gtt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 return -ENOMEM;
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001411 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 global_cache_flush(); /* FIXME: ? */
1413
1414 /* we have to call this as early as possible after the MMIO base address is known */
1415 intel_i830_init_gtt_entries();
1416
1417 agp_bridge->gatt_table = NULL;
1418
1419 agp_bridge->gatt_bus_addr = temp;
1420
1421 return 0;
1422}
Linus Torvalds7d915a32006-11-22 09:37:54 -08001423
1424/*
1425 * The i965 supports 36-bit physical addresses, but to keep
1426 * the format of the GTT the same, the bits that don't fit
1427 * in a 32-bit word are shifted down to bits 4..7.
1428 *
1429 * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
1430 * is always zero on 32-bit architectures, so no need to make
1431 * this conditional.
1432 */
1433static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +01001434 dma_addr_t addr, int type)
Linus Torvalds7d915a32006-11-22 09:37:54 -08001435{
1436 /* Shift high bits down */
1437 addr |= (addr >> 28) & 0xf0;
1438
1439 /* Type checking must be done elsewhere */
1440 return addr | bridge->driver->masks[type].mask;
1441}
1442
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001443static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
1444{
Eric Anholt285aca82010-03-18 11:24:06 -07001445 u16 snb_gmch_ctl;
1446
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001447 switch (agp_bridge->dev->device) {
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07001448 case PCI_DEVICE_ID_INTEL_GM45_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001449 case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001450 case PCI_DEVICE_ID_INTEL_Q45_HB:
1451 case PCI_DEVICE_ID_INTEL_G45_HB:
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08001452 case PCI_DEVICE_ID_INTEL_G41_HB:
Fabian Henze38d8a952009-09-08 00:59:58 +08001453 case PCI_DEVICE_ID_INTEL_B43_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001454 case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
1455 case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
1456 case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
Dave Airlie3ff99162009-12-08 14:03:47 +10001457 case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
Eric Anholt285aca82010-03-18 11:24:06 -07001458 *gtt_offset = *gtt_size = MB(2);
1459 break;
Eric Anholt1089e302009-10-22 16:10:52 -07001460 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
Eric Anholt954bce52010-01-07 16:21:46 -08001461 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
Eric Anholt285aca82010-03-18 11:24:06 -07001462 *gtt_offset = MB(2);
1463
1464 pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
1465 switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
1466 default:
1467 case SNB_GTT_SIZE_0M:
1468 printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
1469 *gtt_size = MB(0);
1470 break;
1471 case SNB_GTT_SIZE_1M:
1472 *gtt_size = MB(1);
1473 break;
1474 case SNB_GTT_SIZE_2M:
1475 *gtt_size = MB(2);
1476 break;
1477 }
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001478 break;
1479 default:
1480 *gtt_offset = *gtt_size = KB(512);
1481 }
1482}
1483
Eric Anholt65c25aa2006-09-06 11:57:18 -04001484/* The intel i965 automatically initializes the agp aperture during POST.
Eric Anholtc41e0de2006-12-19 12:57:24 -08001485 * Use the memory already set aside for in the GTT.
1486 */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001487static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
1488{
Dave Airlie62c96b92008-06-19 14:27:53 +10001489 int page_order;
1490 struct aper_size_info_fixed *size;
1491 int num_entries;
1492 u32 temp;
1493 int gtt_offset, gtt_size;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001494
Dave Airlie62c96b92008-06-19 14:27:53 +10001495 size = agp_bridge->current_size;
1496 page_order = size->page_order;
1497 num_entries = size->num_entries;
1498 agp_bridge->gatt_table_real = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001499
Dave Airlie62c96b92008-06-19 14:27:53 +10001500 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001501
Dave Airlie62c96b92008-06-19 14:27:53 +10001502 temp &= 0xfff00000;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001503
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001504 intel_i965_get_gtt_range(&gtt_offset, &gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001505
Dave Airlie62c96b92008-06-19 14:27:53 +10001506 intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001507
Dave Airlie62c96b92008-06-19 14:27:53 +10001508 if (!intel_private.gtt)
1509 return -ENOMEM;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +10001510
David Woodhousefc619012009-12-02 11:00:05 +00001511 intel_private.gtt_total_size = gtt_size / 4;
1512
Dave Airlie62c96b92008-06-19 14:27:53 +10001513 intel_private.registers = ioremap(temp, 128 * 4096);
1514 if (!intel_private.registers) {
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001515 iounmap(intel_private.gtt);
1516 return -ENOMEM;
1517 }
Eric Anholt65c25aa2006-09-06 11:57:18 -04001518
Dave Airlie62c96b92008-06-19 14:27:53 +10001519 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
1520 global_cache_flush(); /* FIXME: ? */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001521
Dave Airlie62c96b92008-06-19 14:27:53 +10001522 /* we have to call this as early as possible after the MMIO base address is known */
1523 intel_i830_init_gtt_entries();
Eric Anholt65c25aa2006-09-06 11:57:18 -04001524
Dave Airlie62c96b92008-06-19 14:27:53 +10001525 agp_bridge->gatt_table = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001526
Dave Airlie62c96b92008-06-19 14:27:53 +10001527 agp_bridge->gatt_bus_addr = temp;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001528
Dave Airlie62c96b92008-06-19 14:27:53 +10001529 return 0;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001530}
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533static int intel_fetch_size(void)
1534{
1535 int i;
1536 u16 temp;
1537 struct aper_size_info_16 *values;
1538
1539 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
1540 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
1541
1542 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1543 if (temp == values[i].size_value) {
1544 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
1545 agp_bridge->aperture_size_idx = i;
1546 return values[i].size;
1547 }
1548 }
1549
1550 return 0;
1551}
1552
1553static int __intel_8xx_fetch_size(u8 temp)
1554{
1555 int i;
1556 struct aper_size_info_8 *values;
1557
1558 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
1559
1560 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1561 if (temp == values[i].size_value) {
1562 agp_bridge->previous_size =
1563 agp_bridge->current_size = (void *) (values + i);
1564 agp_bridge->aperture_size_idx = i;
1565 return values[i].size;
1566 }
1567 }
1568 return 0;
1569}
1570
1571static int intel_8xx_fetch_size(void)
1572{
1573 u8 temp;
1574
1575 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1576 return __intel_8xx_fetch_size(temp);
1577}
1578
1579static int intel_815_fetch_size(void)
1580{
1581 u8 temp;
1582
1583 /* Intel 815 chipsets have a _weird_ APSIZE register with only
1584 * one non-reserved bit, so mask the others out ... */
1585 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1586 temp &= (1 << 3);
1587
1588 return __intel_8xx_fetch_size(temp);
1589}
1590
1591static void intel_tlbflush(struct agp_memory *mem)
1592{
1593 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
1594 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1595}
1596
1597
1598static void intel_8xx_tlbflush(struct agp_memory *mem)
1599{
1600 u32 temp;
1601 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1602 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
1603 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1604 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
1605}
1606
1607
1608static void intel_cleanup(void)
1609{
1610 u16 temp;
1611 struct aper_size_info_16 *previous_size;
1612
1613 previous_size = A_SIZE_16(agp_bridge->previous_size);
1614 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1615 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1616 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1617}
1618
1619
1620static void intel_8xx_cleanup(void)
1621{
1622 u16 temp;
1623 struct aper_size_info_8 *previous_size;
1624
1625 previous_size = A_SIZE_8(agp_bridge->previous_size);
1626 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1627 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1628 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1629}
1630
1631
1632static int intel_configure(void)
1633{
1634 u32 temp;
1635 u16 temp2;
1636 struct aper_size_info_16 *current_size;
1637
1638 current_size = A_SIZE_16(agp_bridge->current_size);
1639
1640 /* aperture size */
1641 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1642
1643 /* address to map to */
1644 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1645 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1646
1647 /* attbase - aperture base */
1648 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1649
1650 /* agpctrl */
1651 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1652
1653 /* paccfg/nbxcfg */
1654 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1655 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
1656 (temp2 & ~(1 << 10)) | (1 << 9));
1657 /* clear any possible error conditions */
1658 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
1659 return 0;
1660}
1661
1662static int intel_815_configure(void)
1663{
1664 u32 temp, addr;
1665 u8 temp2;
1666 struct aper_size_info_8 *current_size;
1667
1668 /* attbase - aperture base */
1669 /* the Intel 815 chipset spec. says that bits 29-31 in the
1670 * ATTBASE register are reserved -> try not to write them */
1671 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001672 dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 return -EINVAL;
1674 }
1675
1676 current_size = A_SIZE_8(agp_bridge->current_size);
1677
1678 /* aperture size */
1679 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1680 current_size->size_value);
1681
1682 /* address to map to */
1683 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1684 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1685
1686 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
1687 addr &= INTEL_815_ATTBASE_MASK;
1688 addr |= agp_bridge->gatt_bus_addr;
1689 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
1690
1691 /* agpctrl */
1692 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1693
1694 /* apcont */
1695 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
1696 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
1697
1698 /* clear any possible error conditions */
1699 /* Oddness : this chipset seems to have no ERRSTS register ! */
1700 return 0;
1701}
1702
1703static void intel_820_tlbflush(struct agp_memory *mem)
1704{
1705 return;
1706}
1707
1708static void intel_820_cleanup(void)
1709{
1710 u8 temp;
1711 struct aper_size_info_8 *previous_size;
1712
1713 previous_size = A_SIZE_8(agp_bridge->previous_size);
1714 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
1715 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
1716 temp & ~(1 << 1));
1717 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1718 previous_size->size_value);
1719}
1720
1721
1722static int intel_820_configure(void)
1723{
1724 u32 temp;
1725 u8 temp2;
1726 struct aper_size_info_8 *current_size;
1727
1728 current_size = A_SIZE_8(agp_bridge->current_size);
1729
1730 /* aperture size */
1731 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1732
1733 /* address to map to */
1734 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1735 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1736
1737 /* attbase - aperture base */
1738 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1739
1740 /* agpctrl */
1741 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1742
1743 /* global enable aperture access */
1744 /* This flag is not accessed through MCHCFG register as in */
1745 /* i850 chipset. */
1746 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
1747 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
1748 /* clear any possible AGP-related error conditions */
1749 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
1750 return 0;
1751}
1752
1753static int intel_840_configure(void)
1754{
1755 u32 temp;
1756 u16 temp2;
1757 struct aper_size_info_8 *current_size;
1758
1759 current_size = A_SIZE_8(agp_bridge->current_size);
1760
1761 /* aperture size */
1762 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1763
1764 /* address to map to */
1765 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1766 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1767
1768 /* attbase - aperture base */
1769 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1770
1771 /* agpctrl */
1772 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1773
1774 /* mcgcfg */
1775 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
1776 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
1777 /* clear any possible error conditions */
1778 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
1779 return 0;
1780}
1781
1782static int intel_845_configure(void)
1783{
1784 u32 temp;
1785 u8 temp2;
1786 struct aper_size_info_8 *current_size;
1787
1788 current_size = A_SIZE_8(agp_bridge->current_size);
1789
1790 /* aperture size */
1791 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1792
Matthew Garrettb0825482005-07-29 14:03:39 -07001793 if (agp_bridge->apbase_config != 0) {
1794 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1795 agp_bridge->apbase_config);
1796 } else {
1797 /* address to map to */
1798 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1799 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1800 agp_bridge->apbase_config = temp;
1801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803 /* attbase - aperture base */
1804 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1805
1806 /* agpctrl */
1807 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1808
1809 /* agpm */
1810 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
1811 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1812 /* clear any possible error conditions */
1813 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
Dave Airlie2162e6a2007-11-21 16:36:31 +10001814
1815 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 return 0;
1817}
1818
1819static int intel_850_configure(void)
1820{
1821 u32 temp;
1822 u16 temp2;
1823 struct aper_size_info_8 *current_size;
1824
1825 current_size = A_SIZE_8(agp_bridge->current_size);
1826
1827 /* aperture size */
1828 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1829
1830 /* address to map to */
1831 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1832 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1833
1834 /* attbase - aperture base */
1835 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1836
1837 /* agpctrl */
1838 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1839
1840 /* mcgcfg */
1841 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
1842 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
1843 /* clear any possible AGP-related error conditions */
1844 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
1845 return 0;
1846}
1847
1848static int intel_860_configure(void)
1849{
1850 u32 temp;
1851 u16 temp2;
1852 struct aper_size_info_8 *current_size;
1853
1854 current_size = A_SIZE_8(agp_bridge->current_size);
1855
1856 /* aperture size */
1857 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1858
1859 /* address to map to */
1860 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1861 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1862
1863 /* attbase - aperture base */
1864 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1865
1866 /* agpctrl */
1867 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1868
1869 /* mcgcfg */
1870 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
1871 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
1872 /* clear any possible AGP-related error conditions */
1873 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
1874 return 0;
1875}
1876
1877static int intel_830mp_configure(void)
1878{
1879 u32 temp;
1880 u16 temp2;
1881 struct aper_size_info_8 *current_size;
1882
1883 current_size = A_SIZE_8(agp_bridge->current_size);
1884
1885 /* aperture size */
1886 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1887
1888 /* address to map to */
1889 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1890 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1891
1892 /* attbase - aperture base */
1893 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1894
1895 /* agpctrl */
1896 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1897
1898 /* gmch */
1899 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1900 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
1901 /* clear any possible AGP-related error conditions */
1902 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
1903 return 0;
1904}
1905
1906static int intel_7505_configure(void)
1907{
1908 u32 temp;
1909 u16 temp2;
1910 struct aper_size_info_8 *current_size;
1911
1912 current_size = A_SIZE_8(agp_bridge->current_size);
1913
1914 /* aperture size */
1915 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1916
1917 /* address to map to */
1918 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1919 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1920
1921 /* attbase - aperture base */
1922 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1923
1924 /* agpctrl */
1925 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1926
1927 /* mchcfg */
1928 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
1929 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
1930
1931 return 0;
1932}
1933
1934/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -05001935static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936{
1937 {.mask = 0x00000017, .type = 0}
1938};
1939
Dave Jonese5524f32007-02-22 18:41:28 -05001940static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
1942 {64, 16384, 4, 0},
1943 {32, 8192, 3, 8},
1944};
1945
Dave Jonese5524f32007-02-22 18:41:28 -05001946static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947{
1948 {256, 65536, 6, 0},
1949 {128, 32768, 5, 32},
1950 {64, 16384, 4, 48},
1951 {32, 8192, 3, 56},
1952 {16, 4096, 2, 60},
1953 {8, 2048, 1, 62},
1954 {4, 1024, 0, 63}
1955};
1956
Dave Jonese5524f32007-02-22 18:41:28 -05001957static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958{
1959 {256, 65536, 6, 0},
1960 {128, 32768, 5, 32},
1961 {64, 16384, 4, 48},
1962 {32, 8192, 3, 56},
1963 {16, 4096, 2, 60},
1964 {8, 2048, 1, 62},
1965 {4, 1024, 0, 63}
1966};
1967
Dave Jonese5524f32007-02-22 18:41:28 -05001968static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969{
1970 {256, 65536, 6, 0},
1971 {128, 32768, 5, 32},
1972 {64, 16384, 4, 48},
1973 {32, 8192, 3, 56}
1974};
1975
Dave Jonese5524f32007-02-22 18:41:28 -05001976static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 .owner = THIS_MODULE,
1978 .aperture_sizes = intel_generic_sizes,
1979 .size_type = U16_APER_SIZE,
1980 .num_aperture_sizes = 7,
1981 .configure = intel_configure,
1982 .fetch_size = intel_fetch_size,
1983 .cleanup = intel_cleanup,
1984 .tlb_flush = intel_tlbflush,
1985 .mask_memory = agp_generic_mask_memory,
1986 .masks = intel_generic_masks,
1987 .agp_enable = agp_generic_enable,
1988 .cache_flush = global_cache_flush,
1989 .create_gatt_table = agp_generic_create_gatt_table,
1990 .free_gatt_table = agp_generic_free_gatt_table,
1991 .insert_memory = agp_generic_insert_memory,
1992 .remove_memory = agp_generic_remove_memory,
1993 .alloc_by_type = agp_generic_alloc_by_type,
1994 .free_by_type = agp_generic_free_by_type,
1995 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08001996 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08001998 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001999 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000};
2001
Dave Jonese5524f32007-02-22 18:41:28 -05002002static const struct agp_bridge_driver intel_810_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 .owner = THIS_MODULE,
2004 .aperture_sizes = intel_i810_sizes,
2005 .size_type = FIXED_APER_SIZE,
2006 .num_aperture_sizes = 2,
Joe Perchesc7258012008-03-26 14:10:02 -07002007 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 .configure = intel_i810_configure,
2009 .fetch_size = intel_i810_fetch_size,
2010 .cleanup = intel_i810_cleanup,
2011 .tlb_flush = intel_i810_tlbflush,
2012 .mask_memory = intel_i810_mask_memory,
2013 .masks = intel_i810_masks,
2014 .agp_enable = intel_i810_agp_enable,
2015 .cache_flush = global_cache_flush,
2016 .create_gatt_table = agp_generic_create_gatt_table,
2017 .free_gatt_table = agp_generic_free_gatt_table,
2018 .insert_memory = intel_i810_insert_entries,
2019 .remove_memory = intel_i810_remove_entries,
2020 .alloc_by_type = intel_i810_alloc_by_type,
2021 .free_by_type = intel_i810_free_by_type,
2022 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002023 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002025 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002026 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027};
2028
Dave Jonese5524f32007-02-22 18:41:28 -05002029static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 .owner = THIS_MODULE,
2031 .aperture_sizes = intel_815_sizes,
2032 .size_type = U8_APER_SIZE,
2033 .num_aperture_sizes = 2,
2034 .configure = intel_815_configure,
2035 .fetch_size = intel_815_fetch_size,
2036 .cleanup = intel_8xx_cleanup,
2037 .tlb_flush = intel_8xx_tlbflush,
2038 .mask_memory = agp_generic_mask_memory,
2039 .masks = intel_generic_masks,
2040 .agp_enable = agp_generic_enable,
2041 .cache_flush = global_cache_flush,
2042 .create_gatt_table = agp_generic_create_gatt_table,
2043 .free_gatt_table = agp_generic_free_gatt_table,
2044 .insert_memory = agp_generic_insert_memory,
2045 .remove_memory = agp_generic_remove_memory,
2046 .alloc_by_type = agp_generic_alloc_by_type,
2047 .free_by_type = agp_generic_free_by_type,
2048 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002049 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002051 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002052 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053};
2054
Dave Jonese5524f32007-02-22 18:41:28 -05002055static const struct agp_bridge_driver intel_830_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 .owner = THIS_MODULE,
2057 .aperture_sizes = intel_i830_sizes,
2058 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002059 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002060 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 .configure = intel_i830_configure,
2062 .fetch_size = intel_i830_fetch_size,
2063 .cleanup = intel_i830_cleanup,
2064 .tlb_flush = intel_i810_tlbflush,
2065 .mask_memory = intel_i810_mask_memory,
2066 .masks = intel_i810_masks,
2067 .agp_enable = intel_i810_agp_enable,
2068 .cache_flush = global_cache_flush,
2069 .create_gatt_table = intel_i830_create_gatt_table,
2070 .free_gatt_table = intel_i830_free_gatt_table,
2071 .insert_memory = intel_i830_insert_entries,
2072 .remove_memory = intel_i830_remove_entries,
2073 .alloc_by_type = intel_i830_alloc_by_type,
2074 .free_by_type = intel_i810_free_by_type,
2075 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002076 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002078 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002079 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002080 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081};
2082
Dave Jonese5524f32007-02-22 18:41:28 -05002083static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 .owner = THIS_MODULE,
2085 .aperture_sizes = intel_8xx_sizes,
2086 .size_type = U8_APER_SIZE,
2087 .num_aperture_sizes = 7,
2088 .configure = intel_820_configure,
2089 .fetch_size = intel_8xx_fetch_size,
2090 .cleanup = intel_820_cleanup,
2091 .tlb_flush = intel_820_tlbflush,
2092 .mask_memory = agp_generic_mask_memory,
2093 .masks = intel_generic_masks,
2094 .agp_enable = agp_generic_enable,
2095 .cache_flush = global_cache_flush,
2096 .create_gatt_table = agp_generic_create_gatt_table,
2097 .free_gatt_table = agp_generic_free_gatt_table,
2098 .insert_memory = agp_generic_insert_memory,
2099 .remove_memory = agp_generic_remove_memory,
2100 .alloc_by_type = agp_generic_alloc_by_type,
2101 .free_by_type = agp_generic_free_by_type,
2102 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002103 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002105 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002106 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107};
2108
Dave Jonese5524f32007-02-22 18:41:28 -05002109static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 .owner = THIS_MODULE,
2111 .aperture_sizes = intel_830mp_sizes,
2112 .size_type = U8_APER_SIZE,
2113 .num_aperture_sizes = 4,
2114 .configure = intel_830mp_configure,
2115 .fetch_size = intel_8xx_fetch_size,
2116 .cleanup = intel_8xx_cleanup,
2117 .tlb_flush = intel_8xx_tlbflush,
2118 .mask_memory = agp_generic_mask_memory,
2119 .masks = intel_generic_masks,
2120 .agp_enable = agp_generic_enable,
2121 .cache_flush = global_cache_flush,
2122 .create_gatt_table = agp_generic_create_gatt_table,
2123 .free_gatt_table = agp_generic_free_gatt_table,
2124 .insert_memory = agp_generic_insert_memory,
2125 .remove_memory = agp_generic_remove_memory,
2126 .alloc_by_type = agp_generic_alloc_by_type,
2127 .free_by_type = agp_generic_free_by_type,
2128 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002129 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002131 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002132 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133};
2134
Dave Jonese5524f32007-02-22 18:41:28 -05002135static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 .owner = THIS_MODULE,
2137 .aperture_sizes = intel_8xx_sizes,
2138 .size_type = U8_APER_SIZE,
2139 .num_aperture_sizes = 7,
2140 .configure = intel_840_configure,
2141 .fetch_size = intel_8xx_fetch_size,
2142 .cleanup = intel_8xx_cleanup,
2143 .tlb_flush = intel_8xx_tlbflush,
2144 .mask_memory = agp_generic_mask_memory,
2145 .masks = intel_generic_masks,
2146 .agp_enable = agp_generic_enable,
2147 .cache_flush = global_cache_flush,
2148 .create_gatt_table = agp_generic_create_gatt_table,
2149 .free_gatt_table = agp_generic_free_gatt_table,
2150 .insert_memory = agp_generic_insert_memory,
2151 .remove_memory = agp_generic_remove_memory,
2152 .alloc_by_type = agp_generic_alloc_by_type,
2153 .free_by_type = agp_generic_free_by_type,
2154 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002155 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002157 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002158 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159};
2160
Dave Jonese5524f32007-02-22 18:41:28 -05002161static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 .owner = THIS_MODULE,
2163 .aperture_sizes = intel_8xx_sizes,
2164 .size_type = U8_APER_SIZE,
2165 .num_aperture_sizes = 7,
2166 .configure = intel_845_configure,
2167 .fetch_size = intel_8xx_fetch_size,
2168 .cleanup = intel_8xx_cleanup,
2169 .tlb_flush = intel_8xx_tlbflush,
2170 .mask_memory = agp_generic_mask_memory,
2171 .masks = intel_generic_masks,
2172 .agp_enable = agp_generic_enable,
2173 .cache_flush = global_cache_flush,
2174 .create_gatt_table = agp_generic_create_gatt_table,
2175 .free_gatt_table = agp_generic_free_gatt_table,
2176 .insert_memory = agp_generic_insert_memory,
2177 .remove_memory = agp_generic_remove_memory,
2178 .alloc_by_type = agp_generic_alloc_by_type,
2179 .free_by_type = agp_generic_free_by_type,
2180 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002181 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002183 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002184 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002185 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186};
2187
Dave Jonese5524f32007-02-22 18:41:28 -05002188static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 .owner = THIS_MODULE,
2190 .aperture_sizes = intel_8xx_sizes,
2191 .size_type = U8_APER_SIZE,
2192 .num_aperture_sizes = 7,
2193 .configure = intel_850_configure,
2194 .fetch_size = intel_8xx_fetch_size,
2195 .cleanup = intel_8xx_cleanup,
2196 .tlb_flush = intel_8xx_tlbflush,
2197 .mask_memory = agp_generic_mask_memory,
2198 .masks = intel_generic_masks,
2199 .agp_enable = agp_generic_enable,
2200 .cache_flush = global_cache_flush,
2201 .create_gatt_table = agp_generic_create_gatt_table,
2202 .free_gatt_table = agp_generic_free_gatt_table,
2203 .insert_memory = agp_generic_insert_memory,
2204 .remove_memory = agp_generic_remove_memory,
2205 .alloc_by_type = agp_generic_alloc_by_type,
2206 .free_by_type = agp_generic_free_by_type,
2207 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002208 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002210 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002211 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212};
2213
Dave Jonese5524f32007-02-22 18:41:28 -05002214static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 .owner = THIS_MODULE,
2216 .aperture_sizes = intel_8xx_sizes,
2217 .size_type = U8_APER_SIZE,
2218 .num_aperture_sizes = 7,
2219 .configure = intel_860_configure,
2220 .fetch_size = intel_8xx_fetch_size,
2221 .cleanup = intel_8xx_cleanup,
2222 .tlb_flush = intel_8xx_tlbflush,
2223 .mask_memory = agp_generic_mask_memory,
2224 .masks = intel_generic_masks,
2225 .agp_enable = agp_generic_enable,
2226 .cache_flush = global_cache_flush,
2227 .create_gatt_table = agp_generic_create_gatt_table,
2228 .free_gatt_table = agp_generic_free_gatt_table,
2229 .insert_memory = agp_generic_insert_memory,
2230 .remove_memory = agp_generic_remove_memory,
2231 .alloc_by_type = agp_generic_alloc_by_type,
2232 .free_by_type = agp_generic_free_by_type,
2233 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002234 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002236 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002237 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238};
2239
Dave Jonese5524f32007-02-22 18:41:28 -05002240static const struct agp_bridge_driver intel_915_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 .owner = THIS_MODULE,
2242 .aperture_sizes = intel_i830_sizes,
2243 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002244 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002245 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08002247 .fetch_size = intel_i9xx_fetch_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 .cleanup = intel_i915_cleanup,
2249 .tlb_flush = intel_i810_tlbflush,
2250 .mask_memory = intel_i810_mask_memory,
2251 .masks = intel_i810_masks,
2252 .agp_enable = intel_i810_agp_enable,
2253 .cache_flush = global_cache_flush,
2254 .create_gatt_table = intel_i915_create_gatt_table,
2255 .free_gatt_table = intel_i830_free_gatt_table,
2256 .insert_memory = intel_i915_insert_entries,
2257 .remove_memory = intel_i915_remove_entries,
2258 .alloc_by_type = intel_i830_alloc_by_type,
2259 .free_by_type = intel_i810_free_by_type,
2260 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002261 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002263 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002264 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002265 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002266#ifdef USE_PCI_DMA_API
2267 .agp_map_page = intel_agp_map_page,
2268 .agp_unmap_page = intel_agp_unmap_page,
2269 .agp_map_memory = intel_agp_map_memory,
2270 .agp_unmap_memory = intel_agp_unmap_memory,
2271#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272};
2273
Dave Jonese5524f32007-02-22 18:41:28 -05002274static const struct agp_bridge_driver intel_i965_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002275 .owner = THIS_MODULE,
2276 .aperture_sizes = intel_i830_sizes,
2277 .size_type = FIXED_APER_SIZE,
2278 .num_aperture_sizes = 4,
2279 .needs_scratch_page = true,
Dave Airlie0e480e52008-06-19 14:57:31 +10002280 .configure = intel_i915_configure,
2281 .fetch_size = intel_i9xx_fetch_size,
Dave Airlie62c96b92008-06-19 14:27:53 +10002282 .cleanup = intel_i915_cleanup,
2283 .tlb_flush = intel_i810_tlbflush,
2284 .mask_memory = intel_i965_mask_memory,
2285 .masks = intel_i810_masks,
2286 .agp_enable = intel_i810_agp_enable,
2287 .cache_flush = global_cache_flush,
2288 .create_gatt_table = intel_i965_create_gatt_table,
2289 .free_gatt_table = intel_i830_free_gatt_table,
2290 .insert_memory = intel_i915_insert_entries,
2291 .remove_memory = intel_i915_remove_entries,
2292 .alloc_by_type = intel_i830_alloc_by_type,
2293 .free_by_type = intel_i810_free_by_type,
2294 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002295 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002296 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002297 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002298 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002299 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002300#ifdef USE_PCI_DMA_API
2301 .agp_map_page = intel_agp_map_page,
2302 .agp_unmap_page = intel_agp_unmap_page,
2303 .agp_map_memory = intel_agp_map_memory,
2304 .agp_unmap_memory = intel_agp_unmap_memory,
2305#endif
Eric Anholt65c25aa2006-09-06 11:57:18 -04002306};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
Dave Jonese5524f32007-02-22 18:41:28 -05002308static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 .owner = THIS_MODULE,
2310 .aperture_sizes = intel_8xx_sizes,
2311 .size_type = U8_APER_SIZE,
2312 .num_aperture_sizes = 7,
2313 .configure = intel_7505_configure,
2314 .fetch_size = intel_8xx_fetch_size,
2315 .cleanup = intel_8xx_cleanup,
2316 .tlb_flush = intel_8xx_tlbflush,
2317 .mask_memory = agp_generic_mask_memory,
2318 .masks = intel_generic_masks,
2319 .agp_enable = agp_generic_enable,
2320 .cache_flush = global_cache_flush,
2321 .create_gatt_table = agp_generic_create_gatt_table,
2322 .free_gatt_table = agp_generic_free_gatt_table,
2323 .insert_memory = agp_generic_insert_memory,
2324 .remove_memory = agp_generic_remove_memory,
2325 .alloc_by_type = agp_generic_alloc_by_type,
2326 .free_by_type = agp_generic_free_by_type,
2327 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002328 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002330 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002331 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332};
2333
Wang Zhenyu874808c62007-06-06 11:16:25 +08002334static const struct agp_bridge_driver intel_g33_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002335 .owner = THIS_MODULE,
2336 .aperture_sizes = intel_i830_sizes,
2337 .size_type = FIXED_APER_SIZE,
2338 .num_aperture_sizes = 4,
2339 .needs_scratch_page = true,
2340 .configure = intel_i915_configure,
2341 .fetch_size = intel_i9xx_fetch_size,
2342 .cleanup = intel_i915_cleanup,
2343 .tlb_flush = intel_i810_tlbflush,
2344 .mask_memory = intel_i965_mask_memory,
2345 .masks = intel_i810_masks,
2346 .agp_enable = intel_i810_agp_enable,
2347 .cache_flush = global_cache_flush,
2348 .create_gatt_table = intel_i915_create_gatt_table,
2349 .free_gatt_table = intel_i830_free_gatt_table,
2350 .insert_memory = intel_i915_insert_entries,
2351 .remove_memory = intel_i915_remove_entries,
2352 .alloc_by_type = intel_i830_alloc_by_type,
2353 .free_by_type = intel_i810_free_by_type,
2354 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002355 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002356 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002357 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002358 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002359 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002360#ifdef USE_PCI_DMA_API
2361 .agp_map_page = intel_agp_map_page,
2362 .agp_unmap_page = intel_agp_unmap_page,
2363 .agp_map_memory = intel_agp_map_memory,
2364 .agp_unmap_memory = intel_agp_unmap_memory,
2365#endif
Wang Zhenyu874808c62007-06-06 11:16:25 +08002366};
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002367
2368static int find_gmch(u16 device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369{
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002370 struct pci_dev *gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002372 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
2373 if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
2374 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
Dave Airlief011ae72008-01-25 11:23:04 +10002375 device, gmch_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 }
2377
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002378 if (!gmch_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 return 0;
2380
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002381 intel_private.pcidev = gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 return 1;
2383}
2384
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002385/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
2386 * driver and gmch_driver must be non-null, and find_gmch will determine
2387 * which one should be used if a gmch_chip_id is present.
2388 */
2389static const struct intel_driver_description {
2390 unsigned int chip_id;
2391 unsigned int gmch_chip_id;
Wang Zhenyu88889852007-06-14 10:01:04 +08002392 unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002393 char *name;
2394 const struct agp_bridge_driver *driver;
2395 const struct agp_bridge_driver *gmch_driver;
2396} intel_agp_chipsets[] = {
Wang Zhenyu88889852007-06-14 10:01:04 +08002397 { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
2398 { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
2399 { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
2400 { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002401 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002402 { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002403 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002404 { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002405 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002406 { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
2407 &intel_815_driver, &intel_810_driver },
2408 { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
2409 { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
2410 { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002411 &intel_830mp_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002412 { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
2413 { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
2414 { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002415 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002416 { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
Stefan Husemann347486b2009-04-13 14:40:10 -07002417 { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854",
2418 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002419 { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
2420 { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002421 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002422 { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
2423 { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002424 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002425 { PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
Carlos Martíne914a362008-01-24 10:34:09 +10002426 { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, 0, "E7221 (i915)",
2427 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002428 { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002429 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002430 { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002431 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002432 { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002433 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002434 { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002435 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002436 { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002437 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002438 { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002439 NULL, &intel_i965_driver },
Zhenyu Wang9119f852008-01-23 15:49:26 +10002440 { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002441 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002442 { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002443 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002444 { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002445 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002446 { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002447 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002448 { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002449 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002450 { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
2451 { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
2452 { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002453 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002454 { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002455 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002456 { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002457 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002458 { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002459 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002460 { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002461 NULL, &intel_g33_driver },
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002462 { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
Adam Jackson107f5172009-12-03 17:14:41 -05002463 "GM45", NULL, &intel_i965_driver },
2464 { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0,
2465 "Eaglelake", NULL, &intel_i965_driver },
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002466 { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0,
2467 "Q45/Q43", NULL, &intel_i965_driver },
2468 { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
2469 "G45/G43", NULL, &intel_i965_driver },
Fabian Henze38d8a952009-09-08 00:59:58 +08002470 { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
2471 "B43", NULL, &intel_i965_driver },
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002472 { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
2473 "G41", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002474 { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002475 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002476 { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002477 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002478 { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002479 "HD Graphics", NULL, &intel_i965_driver },
Dave Airlie3ff99162009-12-08 14:03:47 +10002480 { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002481 "HD Graphics", NULL, &intel_i965_driver },
Eric Anholt1089e302009-10-22 16:10:52 -07002482 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
2483 "Sandybridge", NULL, &intel_i965_driver },
Eric Anholt954bce52010-01-07 16:21:46 -08002484 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
2485 "Sandybridge", NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002486 { 0, 0, 0, NULL, NULL, NULL }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002487};
2488
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489static int __devinit agp_intel_probe(struct pci_dev *pdev,
2490 const struct pci_device_id *ent)
2491{
2492 struct agp_bridge_data *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 u8 cap_ptr = 0;
2494 struct resource *r;
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +08002495 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
2497 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
2498
2499 bridge = agp_alloc_bridge();
2500 if (!bridge)
2501 return -ENOMEM;
2502
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002503 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
2504 /* In case that multiple models of gfx chip may
2505 stand on same host bridge type, this can be
2506 sure we detect the right IGD. */
Wang Zhenyu88889852007-06-14 10:01:04 +08002507 if (pdev->device == intel_agp_chipsets[i].chip_id) {
2508 if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
2509 find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
2510 bridge->driver =
2511 intel_agp_chipsets[i].gmch_driver;
2512 break;
2513 } else if (intel_agp_chipsets[i].multi_gmch_chip) {
2514 continue;
2515 } else {
2516 bridge->driver = intel_agp_chipsets[i].driver;
2517 break;
2518 }
2519 }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002520 }
2521
2522 if (intel_agp_chipsets[i].name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002524 dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
2525 pdev->vendor, pdev->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 agp_put_bridge(bridge);
2527 return -ENODEV;
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002528 }
2529
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002530 if (bridge->driver == NULL) {
Wang Zhenyu47d46372007-06-21 13:43:18 +08002531 /* bridge has no AGP and no IGD detected */
2532 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002533 dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
2534 intel_agp_chipsets[i].gmch_chip_id);
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002535 agp_put_bridge(bridge);
2536 return -ENODEV;
Dave Airlief011ae72008-01-25 11:23:04 +10002537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
2539 bridge->dev = pdev;
2540 bridge->capndx = cap_ptr;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002541 bridge->dev_private_data = &intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002543 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
2545 /*
2546 * The following fixes the case where the BIOS has "forgotten" to
2547 * provide an address range for the GART.
2548 * 20030610 - hamish@zot.org
2549 */
2550 r = &pdev->resource[0];
2551 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -05002552 if (pci_assign_resource(pdev, 0)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002553 dev_err(&pdev->dev, "can't assign resource 0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 agp_put_bridge(bridge);
2555 return -ENODEV;
2556 }
2557 }
2558
2559 /*
2560 * If the device has not been properly setup, the following will catch
2561 * the problem and should stop the system from crashing.
2562 * 20030610 - hamish@zot.org
2563 */
2564 if (pci_enable_device(pdev)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002565 dev_err(&pdev->dev, "can't enable PCI device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 agp_put_bridge(bridge);
2567 return -ENODEV;
2568 }
2569
2570 /* Fill in the mode register */
2571 if (cap_ptr) {
2572 pci_read_config_dword(pdev,
2573 bridge->capndx+PCI_AGP_STATUS,
2574 &bridge->mode);
2575 }
2576
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002577 if (bridge->driver->mask_memory == intel_i965_mask_memory) {
David Woodhouseec402ba2009-11-18 10:22:46 +00002578 if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36)))
2579 dev_err(&intel_private.pcidev->dev,
2580 "set gfx device dma mask 36bit failed!\n");
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002581 else
2582 pci_set_consistent_dma_mask(intel_private.pcidev,
2583 DMA_BIT_MASK(36));
2584 }
David Woodhouseec402ba2009-11-18 10:22:46 +00002585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 pci_set_drvdata(pdev, bridge);
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +08002587 err = agp_add_bridge(bridge);
2588 if (!err)
2589 intel_agp_enabled = 1;
2590 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591}
2592
2593static void __devexit agp_intel_remove(struct pci_dev *pdev)
2594{
2595 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
2596
2597 agp_remove_bridge(bridge);
2598
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002599 if (intel_private.pcidev)
2600 pci_dev_put(intel_private.pcidev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
2602 agp_put_bridge(bridge);
2603}
2604
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002605#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606static int agp_intel_resume(struct pci_dev *pdev)
2607{
2608 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
Keith Packarda8c84df2008-07-31 15:48:07 +10002609 int ret_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 if (bridge->driver == &intel_generic_driver)
2612 intel_configure();
2613 else if (bridge->driver == &intel_850_driver)
2614 intel_850_configure();
2615 else if (bridge->driver == &intel_845_driver)
2616 intel_845_configure();
2617 else if (bridge->driver == &intel_830mp_driver)
2618 intel_830mp_configure();
2619 else if (bridge->driver == &intel_915_driver)
2620 intel_i915_configure();
2621 else if (bridge->driver == &intel_830_driver)
2622 intel_i830_configure();
2623 else if (bridge->driver == &intel_810_driver)
2624 intel_i810_configure();
Dave Jones08da3f42006-09-10 21:09:26 -04002625 else if (bridge->driver == &intel_i965_driver)
2626 intel_i915_configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Keith Packarda8c84df2008-07-31 15:48:07 +10002628 ret_val = agp_rebind_memory();
2629 if (ret_val != 0)
2630 return ret_val;
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 return 0;
2633}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002634#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636static struct pci_device_id agp_intel_pci_table[] = {
2637#define ID(x) \
2638 { \
2639 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
2640 .class_mask = ~0, \
2641 .vendor = PCI_VENDOR_ID_INTEL, \
2642 .device = x, \
2643 .subvendor = PCI_ANY_ID, \
2644 .subdevice = PCI_ANY_ID, \
2645 }
2646 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
2647 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
2648 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
2649 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
2650 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
2651 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
2652 ID(PCI_DEVICE_ID_INTEL_82815_MC),
2653 ID(PCI_DEVICE_ID_INTEL_82820_HB),
2654 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
2655 ID(PCI_DEVICE_ID_INTEL_82830_HB),
2656 ID(PCI_DEVICE_ID_INTEL_82840_HB),
2657 ID(PCI_DEVICE_ID_INTEL_82845_HB),
2658 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
2659 ID(PCI_DEVICE_ID_INTEL_82850_HB),
Stefan Husemann347486b2009-04-13 14:40:10 -07002660 ID(PCI_DEVICE_ID_INTEL_82854_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
2662 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
2663 ID(PCI_DEVICE_ID_INTEL_82860_HB),
2664 ID(PCI_DEVICE_ID_INTEL_82865_HB),
2665 ID(PCI_DEVICE_ID_INTEL_82875_HB),
2666 ID(PCI_DEVICE_ID_INTEL_7505_0),
2667 ID(PCI_DEVICE_ID_INTEL_7205_0),
Carlos Martíne914a362008-01-24 10:34:09 +10002668 ID(PCI_DEVICE_ID_INTEL_E7221_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
2670 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01002671 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00002672 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002673 ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002674 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
2675 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002676 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
Zhenyu Wang9119f852008-01-23 15:49:26 +10002677 ID(PCI_DEVICE_ID_INTEL_82G35_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002678 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
2679 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +08002680 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002681 ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
Wang Zhenyu874808c62007-06-06 11:16:25 +08002682 ID(PCI_DEVICE_ID_INTEL_G33_HB),
2683 ID(PCI_DEVICE_ID_INTEL_Q35_HB),
2684 ID(PCI_DEVICE_ID_INTEL_Q33_HB),
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002685 ID(PCI_DEVICE_ID_INTEL_GM45_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002686 ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002687 ID(PCI_DEVICE_ID_INTEL_Q45_HB),
2688 ID(PCI_DEVICE_ID_INTEL_G45_HB),
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002689 ID(PCI_DEVICE_ID_INTEL_G41_HB),
Fabian Henze38d8a952009-09-08 00:59:58 +08002690 ID(PCI_DEVICE_ID_INTEL_B43_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002691 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
2692 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
2693 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
Dave Airlie3ff99162009-12-08 14:03:47 +10002694 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
Eric Anholt1089e302009-10-22 16:10:52 -07002695 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
Eric Anholt954bce52010-01-07 16:21:46 -08002696 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 { }
2698};
2699
2700MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
2701
2702static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 .name = "agpgart-intel",
2704 .id_table = agp_intel_pci_table,
2705 .probe = agp_intel_probe,
2706 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002707#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002709#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710};
2711
2712static int __init agp_intel_init(void)
2713{
2714 if (agp_off)
2715 return -EINVAL;
2716 return pci_register_driver(&agp_intel_pci_driver);
2717}
2718
2719static void __exit agp_intel_cleanup(void)
2720{
2721 pci_unregister_driver(&agp_intel_pci_driver);
2722}
2723
2724module_init(agp_intel_init);
2725module_exit(agp_intel_cleanup);
2726
Dave Jonesf4432c52008-10-20 13:31:45 -04002727MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728MODULE_LICENSE("GPL and additional rights");