cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i460-agp.c (18895B)


      1/*
      2 * For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of
      3 * the "Intel 460GTX Chipset Software Developer's Manual":
      4 * http://www.intel.com/design/archives/itanium/downloads/248704.htm 
      5 */
      6/*
      7 * 460GX support by Chris Ahna <christopher.j.ahna@intel.com>
      8 * Clean up & simplification by David Mosberger-Tang <davidm@hpl.hp.com>
      9 */
     10#include <linux/module.h>
     11#include <linux/pci.h>
     12#include <linux/init.h>
     13#include <linux/string.h>
     14#include <linux/slab.h>
     15#include <linux/agp_backend.h>
     16#include <linux/log2.h>
     17
     18#include "agp.h"
     19
     20#define INTEL_I460_BAPBASE		0x98
     21#define INTEL_I460_GXBCTL		0xa0
     22#define INTEL_I460_AGPSIZ		0xa2
     23#define INTEL_I460_ATTBASE		0xfe200000
     24#define INTEL_I460_GATT_VALID		(1UL << 24)
     25#define INTEL_I460_GATT_COHERENT	(1UL << 25)
     26
     27/*
     28 * The i460 can operate with large (4MB) pages, but there is no sane way to support this
     29 * within the current kernel/DRM environment, so we disable the relevant code for now.
     30 * See also comments in ia64_alloc_page()...
     31 */
     32#define I460_LARGE_IO_PAGES		0
     33
     34#if I460_LARGE_IO_PAGES
     35# define I460_IO_PAGE_SHIFT		i460.io_page_shift
     36#else
     37# define I460_IO_PAGE_SHIFT		12
     38#endif
     39
     40#define I460_IOPAGES_PER_KPAGE		(PAGE_SIZE >> I460_IO_PAGE_SHIFT)
     41#define I460_KPAGES_PER_IOPAGE		(1 << (I460_IO_PAGE_SHIFT - PAGE_SHIFT))
     42#define I460_SRAM_IO_DISABLE		(1 << 4)
     43#define I460_BAPBASE_ENABLE		(1 << 3)
     44#define I460_AGPSIZ_MASK		0x7
     45#define I460_4M_PS			(1 << 1)
     46
     47/* Control bits for Out-Of-GART coherency and Burst Write Combining */
     48#define I460_GXBCTL_OOG		(1UL << 0)
     49#define I460_GXBCTL_BWC		(1UL << 2)
     50
     51/*
     52 * gatt_table entries are 32-bits wide on the i460; the generic code ought to declare the
     53 * gatt_table and gatt_table_real pointers a "void *"...
     54 */
     55#define RD_GATT(index)		readl((u32 *) i460.gatt + (index))
     56#define WR_GATT(index, val)	writel((val), (u32 *) i460.gatt + (index))
     57/*
     58 * The 460 spec says we have to read the last location written to make sure that all
     59 * writes have taken effect
     60 */
     61#define WR_FLUSH_GATT(index)	RD_GATT(index)
     62
     63static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
     64				       dma_addr_t addr, int type);
     65
     66static struct {
     67	void *gatt;				/* ioremap'd GATT area */
     68
     69	/* i460 supports multiple GART page sizes, so GART pageshift is dynamic: */
     70	u8 io_page_shift;
     71
     72	/* BIOS configures chipset to one of 2 possible apbase values: */
     73	u8 dynamic_apbase;
     74
     75	/* structure for tracking partial use of 4MB GART pages: */
     76	struct lp_desc {
     77		unsigned long *alloced_map;	/* bitmap of kernel-pages in use */
     78		int refcount;			/* number of kernel pages using the large page */
     79		u64 paddr;			/* physical address of large page */
     80		struct page *page; 		/* page pointer */
     81	} *lp_desc;
     82} i460;
     83
     84static const struct aper_size_info_8 i460_sizes[3] =
     85{
     86	/*
     87	 * The 32GB aperture is only available with a 4M GART page size.  Due to the
     88	 * dynamic GART page size, we can't figure out page_order or num_entries until
     89	 * runtime.
     90	 */
     91	{32768, 0, 0, 4},
     92	{1024, 0, 0, 2},
     93	{256, 0, 0, 1}
     94};
     95
     96static struct gatt_mask i460_masks[] =
     97{
     98	{
     99	  .mask = INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT,
    100	  .type = 0
    101	}
    102};
    103
    104static int i460_fetch_size (void)
    105{
    106	int i;
    107	u8 temp;
    108	struct aper_size_info_8 *values;
    109
    110	/* Determine the GART page size */
    111	pci_read_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL, &temp);
    112	i460.io_page_shift = (temp & I460_4M_PS) ? 22 : 12;
    113	pr_debug("i460_fetch_size: io_page_shift=%d\n", i460.io_page_shift);
    114
    115	if (i460.io_page_shift != I460_IO_PAGE_SHIFT) {
    116		printk(KERN_ERR PFX
    117			"I/O (GART) page-size %luKB doesn't match expected "
    118				"size %luKB\n",
    119			1UL << (i460.io_page_shift - 10),
    120			1UL << (I460_IO_PAGE_SHIFT));
    121		return 0;
    122	}
    123
    124	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
    125
    126	pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
    127
    128	/* Exit now if the IO drivers for the GART SRAMS are turned off */
    129	if (temp & I460_SRAM_IO_DISABLE) {
    130		printk(KERN_ERR PFX "GART SRAMS disabled on 460GX chipset\n");
    131		printk(KERN_ERR PFX "AGPGART operation not possible\n");
    132		return 0;
    133	}
    134
    135	/* Make sure we don't try to create an 2 ^ 23 entry GATT */
    136	if ((i460.io_page_shift == 0) && ((temp & I460_AGPSIZ_MASK) == 4)) {
    137		printk(KERN_ERR PFX "We can't have a 32GB aperture with 4KB GART pages\n");
    138		return 0;
    139	}
    140
    141	/* Determine the proper APBASE register */
    142	if (temp & I460_BAPBASE_ENABLE)
    143		i460.dynamic_apbase = INTEL_I460_BAPBASE;
    144	else
    145		i460.dynamic_apbase = AGP_APBASE;
    146
    147	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
    148		/*
    149		 * Dynamically calculate the proper num_entries and page_order values for
    150		 * the define aperture sizes. Take care not to shift off the end of
    151		 * values[i].size.
    152		 */
    153		values[i].num_entries = (values[i].size << 8) >> (I460_IO_PAGE_SHIFT - 12);
    154		values[i].page_order = ilog2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
    155	}
    156
    157	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
    158		/* Neglect control bits when matching up size_value */
    159		if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) {
    160			agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
    161			agp_bridge->aperture_size_idx = i;
    162			return values[i].size;
    163		}
    164	}
    165
    166	return 0;
    167}
    168
    169/* There isn't anything to do here since 460 has no GART TLB. */
    170static void i460_tlb_flush (struct agp_memory *mem)
    171{
    172	return;
    173}
    174
    175/*
    176 * This utility function is needed to prevent corruption of the control bits
    177 * which are stored along with the aperture size in 460's AGPSIZ register
    178 */
    179static void i460_write_agpsiz (u8 size_value)
    180{
    181	u8 temp;
    182
    183	pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
    184	pci_write_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ,
    185			      ((temp & ~I460_AGPSIZ_MASK) | size_value));
    186}
    187
    188static void i460_cleanup (void)
    189{
    190	struct aper_size_info_8 *previous_size;
    191
    192	previous_size = A_SIZE_8(agp_bridge->previous_size);
    193	i460_write_agpsiz(previous_size->size_value);
    194
    195	if (I460_IO_PAGE_SHIFT > PAGE_SHIFT)
    196		kfree(i460.lp_desc);
    197}
    198
    199static int i460_configure (void)
    200{
    201	union {
    202		u32 small[2];
    203		u64 large;
    204	} temp;
    205	size_t size;
    206	u8 scratch;
    207	struct aper_size_info_8 *current_size;
    208
    209	temp.large = 0;
    210
    211	current_size = A_SIZE_8(agp_bridge->current_size);
    212	i460_write_agpsiz(current_size->size_value);
    213
    214	/*
    215	 * Do the necessary rigmarole to read all eight bytes of APBASE.
    216	 * This has to be done since the AGP aperture can be above 4GB on
    217	 * 460 based systems.
    218	 */
    219	pci_read_config_dword(agp_bridge->dev, i460.dynamic_apbase, &(temp.small[0]));
    220	pci_read_config_dword(agp_bridge->dev, i460.dynamic_apbase + 4, &(temp.small[1]));
    221
    222	/* Clear BAR control bits */
    223	agp_bridge->gart_bus_addr = temp.large & ~((1UL << 3) - 1);
    224
    225	pci_read_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL, &scratch);
    226	pci_write_config_byte(agp_bridge->dev, INTEL_I460_GXBCTL,
    227			      (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC);
    228
    229	/*
    230	 * Initialize partial allocation trackers if a GART page is bigger than a kernel
    231	 * page.
    232	 */
    233	if (I460_IO_PAGE_SHIFT > PAGE_SHIFT) {
    234		size = current_size->num_entries * sizeof(i460.lp_desc[0]);
    235		i460.lp_desc = kzalloc(size, GFP_KERNEL);
    236		if (!i460.lp_desc)
    237			return -ENOMEM;
    238	}
    239	return 0;
    240}
    241
    242static int i460_create_gatt_table (struct agp_bridge_data *bridge)
    243{
    244	int page_order, num_entries, i;
    245	void *temp;
    246
    247	/*
    248	 * Load up the fixed address of the GART SRAMS which hold our GATT table.
    249	 */
    250	temp = agp_bridge->current_size;
    251	page_order = A_SIZE_8(temp)->page_order;
    252	num_entries = A_SIZE_8(temp)->num_entries;
    253
    254	i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
    255	if (!i460.gatt) {
    256		printk(KERN_ERR PFX "ioremap failed\n");
    257		return -ENOMEM;
    258	}
    259
    260	/* These are no good, the should be removed from the agp_bridge strucure... */
    261	agp_bridge->gatt_table_real = NULL;
    262	agp_bridge->gatt_table = NULL;
    263	agp_bridge->gatt_bus_addr = 0;
    264
    265	for (i = 0; i < num_entries; ++i)
    266		WR_GATT(i, 0);
    267	WR_FLUSH_GATT(i - 1);
    268	return 0;
    269}
    270
    271static int i460_free_gatt_table (struct agp_bridge_data *bridge)
    272{
    273	int num_entries, i;
    274	void *temp;
    275
    276	temp = agp_bridge->current_size;
    277
    278	num_entries = A_SIZE_8(temp)->num_entries;
    279
    280	for (i = 0; i < num_entries; ++i)
    281		WR_GATT(i, 0);
    282	WR_FLUSH_GATT(num_entries - 1);
    283
    284	iounmap(i460.gatt);
    285	return 0;
    286}
    287
    288/*
    289 * The following functions are called when the I/O (GART) page size is smaller than
    290 * PAGE_SIZE.
    291 */
    292
    293static int i460_insert_memory_small_io_page (struct agp_memory *mem,
    294				off_t pg_start, int type)
    295{
    296	unsigned long paddr, io_pg_start, io_page_size;
    297	int i, j, k, num_entries;
    298	void *temp;
    299
    300	pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
    301		 mem, pg_start, type, page_to_phys(mem->pages[0]));
    302
    303	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
    304		return -EINVAL;
    305
    306	io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
    307
    308	temp = agp_bridge->current_size;
    309	num_entries = A_SIZE_8(temp)->num_entries;
    310
    311	if ((io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count) > num_entries) {
    312		printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
    313		return -EINVAL;
    314	}
    315
    316	j = io_pg_start;
    317	while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) {
    318		if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) {
    319			pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n",
    320				 j, RD_GATT(j));
    321			return -EBUSY;
    322		}
    323		j++;
    324	}
    325
    326	io_page_size = 1UL << I460_IO_PAGE_SHIFT;
    327	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
    328		paddr = page_to_phys(mem->pages[i]);
    329		for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
    330			WR_GATT(j, i460_mask_memory(agp_bridge, paddr, mem->type));
    331	}
    332	WR_FLUSH_GATT(j - 1);
    333	return 0;
    334}
    335
    336static int i460_remove_memory_small_io_page(struct agp_memory *mem,
    337				off_t pg_start, int type)
    338{
    339	int i;
    340
    341	pr_debug("i460_remove_memory_small_io_page(mem=%p, pg_start=%ld, type=%d)\n",
    342		 mem, pg_start, type);
    343
    344	pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
    345
    346	for (i = pg_start; i < (pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count); i++)
    347		WR_GATT(i, 0);
    348	WR_FLUSH_GATT(i - 1);
    349	return 0;
    350}
    351
    352#if I460_LARGE_IO_PAGES
    353
    354/*
    355 * These functions are called when the I/O (GART) page size exceeds PAGE_SIZE.
    356 *
    357 * This situation is interesting since AGP memory allocations that are smaller than a
    358 * single GART page are possible.  The i460.lp_desc array tracks partial allocation of the
    359 * large GART pages to work around this issue.
    360 *
    361 * i460.lp_desc[pg_num].refcount tracks the number of kernel pages in use within GART page
    362 * pg_num.  i460.lp_desc[pg_num].paddr is the physical address of the large page and
    363 * i460.lp_desc[pg_num].alloced_map is a bitmap of kernel pages that are in use (allocated).
    364 */
    365
    366static int i460_alloc_large_page (struct lp_desc *lp)
    367{
    368	unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT;
    369	size_t map_size;
    370
    371	lp->page = alloc_pages(GFP_KERNEL, order);
    372	if (!lp->page) {
    373		printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n");
    374		return -ENOMEM;
    375	}
    376
    377	map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8;
    378	lp->alloced_map = kzalloc(map_size, GFP_KERNEL);
    379	if (!lp->alloced_map) {
    380		__free_pages(lp->page, order);
    381		printk(KERN_ERR PFX "Out of memory, we're in trouble...\n");
    382		return -ENOMEM;
    383	}
    384
    385	lp->paddr = page_to_phys(lp->page);
    386	lp->refcount = 0;
    387	atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
    388	return 0;
    389}
    390
    391static void i460_free_large_page (struct lp_desc *lp)
    392{
    393	kfree(lp->alloced_map);
    394	lp->alloced_map = NULL;
    395
    396	__free_pages(lp->page, I460_IO_PAGE_SHIFT - PAGE_SHIFT);
    397	atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
    398}
    399
    400static int i460_insert_memory_large_io_page (struct agp_memory *mem,
    401				off_t pg_start, int type)
    402{
    403	int i, start_offset, end_offset, idx, pg, num_entries;
    404	struct lp_desc *start, *end, *lp;
    405	void *temp;
    406
    407	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
    408		return -EINVAL;
    409
    410	temp = agp_bridge->current_size;
    411	num_entries = A_SIZE_8(temp)->num_entries;
    412
    413	/* Figure out what pg_start means in terms of our large GART pages */
    414	start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
    415	end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
    416	start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
    417	end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
    418
    419	if (end > i460.lp_desc + num_entries) {
    420		printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
    421		return -EINVAL;
    422	}
    423
    424	/* Check if the requested region of the aperture is free */
    425	for (lp = start; lp <= end; ++lp) {
    426		if (!lp->alloced_map)
    427			continue;	/* OK, the entire large page is available... */
    428
    429		for (idx = ((lp == start) ? start_offset : 0);
    430		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
    431		     idx++)
    432		{
    433			if (test_bit(idx, lp->alloced_map))
    434				return -EBUSY;
    435		}
    436	}
    437
    438	for (lp = start, i = 0; lp <= end; ++lp) {
    439		if (!lp->alloced_map) {
    440			/* Allocate new GART pages... */
    441			if (i460_alloc_large_page(lp) < 0)
    442				return -ENOMEM;
    443			pg = lp - i460.lp_desc;
    444			WR_GATT(pg, i460_mask_memory(agp_bridge,
    445						     lp->paddr, 0));
    446			WR_FLUSH_GATT(pg);
    447		}
    448
    449		for (idx = ((lp == start) ? start_offset : 0);
    450		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
    451		     idx++, i++)
    452		{
    453			mem->pages[i] = lp->page;
    454			__set_bit(idx, lp->alloced_map);
    455			++lp->refcount;
    456		}
    457	}
    458	return 0;
    459}
    460
    461static int i460_remove_memory_large_io_page (struct agp_memory *mem,
    462				off_t pg_start, int type)
    463{
    464	int i, pg, start_offset, end_offset, idx, num_entries;
    465	struct lp_desc *start, *end, *lp;
    466	void *temp;
    467
    468	temp = agp_bridge->current_size;
    469	num_entries = A_SIZE_8(temp)->num_entries;
    470
    471	/* Figure out what pg_start means in terms of our large GART pages */
    472	start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
    473	end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
    474	start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
    475	end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
    476
    477	for (i = 0, lp = start; lp <= end; ++lp) {
    478		for (idx = ((lp == start) ? start_offset : 0);
    479		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
    480		     idx++, i++)
    481		{
    482			mem->pages[i] = NULL;
    483			__clear_bit(idx, lp->alloced_map);
    484			--lp->refcount;
    485		}
    486
    487		/* Free GART pages if they are unused */
    488		if (lp->refcount == 0) {
    489			pg = lp - i460.lp_desc;
    490			WR_GATT(pg, 0);
    491			WR_FLUSH_GATT(pg);
    492			i460_free_large_page(lp);
    493		}
    494	}
    495	return 0;
    496}
    497
    498/* Wrapper routines to call the approriate {small_io_page,large_io_page} function */
    499
    500static int i460_insert_memory (struct agp_memory *mem,
    501				off_t pg_start, int type)
    502{
    503	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
    504		return i460_insert_memory_small_io_page(mem, pg_start, type);
    505	else
    506		return i460_insert_memory_large_io_page(mem, pg_start, type);
    507}
    508
    509static int i460_remove_memory (struct agp_memory *mem,
    510				off_t pg_start, int type)
    511{
    512	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
    513		return i460_remove_memory_small_io_page(mem, pg_start, type);
    514	else
    515		return i460_remove_memory_large_io_page(mem, pg_start, type);
    516}
    517
    518/*
    519 * If the I/O (GART) page size is bigger than the kernel page size, we don't want to
    520 * allocate memory until we know where it is to be bound in the aperture (a
    521 * multi-kernel-page alloc might fit inside of an already allocated GART page).
    522 *
    523 * Let's just hope nobody counts on the allocated AGP memory being there before bind time
    524 * (I don't think current drivers do)...
    525 */
    526static struct page *i460_alloc_page (struct agp_bridge_data *bridge)
    527{
    528	void *page;
    529
    530	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
    531		page = agp_generic_alloc_page(agp_bridge);
    532	} else
    533		/* Returning NULL would cause problems */
    534		/* AK: really dubious code. */
    535		page = (void *)~0UL;
    536	return page;
    537}
    538
    539static void i460_destroy_page (struct page *page, int flags)
    540{
    541	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
    542		agp_generic_destroy_page(page, flags);
    543	}
    544}
    545
    546#endif /* I460_LARGE_IO_PAGES */
    547
    548static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
    549				       dma_addr_t addr, int type)
    550{
    551	/* Make sure the returned address is a valid GATT entry */
    552	return bridge->driver->masks[0].mask
    553		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
    554}
    555
    556const struct agp_bridge_driver intel_i460_driver = {
    557	.owner			= THIS_MODULE,
    558	.aperture_sizes		= i460_sizes,
    559	.size_type		= U8_APER_SIZE,
    560	.num_aperture_sizes	= 3,
    561	.configure		= i460_configure,
    562	.fetch_size		= i460_fetch_size,
    563	.cleanup		= i460_cleanup,
    564	.tlb_flush		= i460_tlb_flush,
    565	.mask_memory		= i460_mask_memory,
    566	.masks			= i460_masks,
    567	.agp_enable		= agp_generic_enable,
    568	.cache_flush		= global_cache_flush,
    569	.create_gatt_table	= i460_create_gatt_table,
    570	.free_gatt_table	= i460_free_gatt_table,
    571#if I460_LARGE_IO_PAGES
    572	.insert_memory		= i460_insert_memory,
    573	.remove_memory		= i460_remove_memory,
    574	.agp_alloc_page		= i460_alloc_page,
    575	.agp_destroy_page	= i460_destroy_page,
    576#else
    577	.insert_memory		= i460_insert_memory_small_io_page,
    578	.remove_memory		= i460_remove_memory_small_io_page,
    579	.agp_alloc_page		= agp_generic_alloc_page,
    580	.agp_alloc_pages	= agp_generic_alloc_pages,
    581	.agp_destroy_page	= agp_generic_destroy_page,
    582	.agp_destroy_pages	= agp_generic_destroy_pages,
    583#endif
    584	.alloc_by_type		= agp_generic_alloc_by_type,
    585	.free_by_type		= agp_generic_free_by_type,
    586	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    587	.cant_use_aperture	= true,
    588};
    589
    590static int agp_intel_i460_probe(struct pci_dev *pdev,
    591				const struct pci_device_id *ent)
    592{
    593	struct agp_bridge_data *bridge;
    594	u8 cap_ptr;
    595
    596	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
    597	if (!cap_ptr)
    598		return -ENODEV;
    599
    600	bridge = agp_alloc_bridge();
    601	if (!bridge)
    602		return -ENOMEM;
    603
    604	bridge->driver = &intel_i460_driver;
    605	bridge->dev = pdev;
    606	bridge->capndx = cap_ptr;
    607
    608	printk(KERN_INFO PFX "Detected Intel 460GX chipset\n");
    609
    610	pci_set_drvdata(pdev, bridge);
    611	return agp_add_bridge(bridge);
    612}
    613
    614static void agp_intel_i460_remove(struct pci_dev *pdev)
    615{
    616	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
    617
    618	agp_remove_bridge(bridge);
    619	agp_put_bridge(bridge);
    620}
    621
    622static struct pci_device_id agp_intel_i460_pci_table[] = {
    623	{
    624	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
    625	.class_mask	= ~0,
    626	.vendor		= PCI_VENDOR_ID_INTEL,
    627	.device		= PCI_DEVICE_ID_INTEL_84460GX,
    628	.subvendor	= PCI_ANY_ID,
    629	.subdevice	= PCI_ANY_ID,
    630	},
    631	{ }
    632};
    633
    634MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table);
    635
    636static struct pci_driver agp_intel_i460_pci_driver = {
    637	.name		= "agpgart-intel-i460",
    638	.id_table	= agp_intel_i460_pci_table,
    639	.probe		= agp_intel_i460_probe,
    640	.remove		= agp_intel_i460_remove,
    641};
    642
    643static int __init agp_intel_i460_init(void)
    644{
    645	if (agp_off)
    646		return -EINVAL;
    647	return pci_register_driver(&agp_intel_i460_pci_driver);
    648}
    649
    650static void __exit agp_intel_i460_cleanup(void)
    651{
    652	pci_unregister_driver(&agp_intel_i460_pci_driver);
    653}
    654
    655module_init(agp_intel_i460_init);
    656module_exit(agp_intel_i460_cleanup);
    657
    658MODULE_AUTHOR("Chris Ahna <Christopher.J.Ahna@intel.com>");
    659MODULE_LICENSE("GPL and additional rights");