⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i460-agp.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	WR_FLUSH_GATT(j - 1);	return 0;}static int i460_remove_memory_small_io_page(struct agp_memory *mem,				off_t pg_start, int type){	int i;	pr_debug("i460_remove_memory_small_io_page(mem=%p, pg_start=%ld, type=%d)\n",		 mem, pg_start, type);	pg_start = I460_IOPAGES_PER_KPAGE * pg_start;	for (i = pg_start; i < (pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count); i++)		WR_GATT(i, 0);	WR_FLUSH_GATT(i - 1);	return 0;}#if I460_LARGE_IO_PAGES/* * These functions are called when the I/O (GART) page size exceeds PAGE_SIZE. * * This situation is interesting since AGP memory allocations that are smaller than a * single GART page are possible.  The i460.lp_desc array tracks partial allocation of the * large GART pages to work around this issue. * * i460.lp_desc[pg_num].refcount tracks the number of kernel pages in use within GART page * pg_num.  i460.lp_desc[pg_num].paddr is the physical address of the large page and * i460.lp_desc[pg_num].alloced_map is a bitmap of kernel pages that are in use (allocated). */static int i460_alloc_large_page (struct lp_desc *lp){	unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT;	size_t map_size;	void *lpage;	lpage = (void *) __get_free_pages(GFP_KERNEL, order);	if (!lpage) {		printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n");		return -ENOMEM;	}	map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8;	lp->alloced_map = kmalloc(map_size, GFP_KERNEL);	if (!lp->alloced_map) {		free_pages((unsigned long) lpage, order);		printk(KERN_ERR PFX "Out of memory, we're in trouble...\n");		return -ENOMEM;	}	memset(lp->alloced_map, 0, map_size);	lp->paddr = virt_to_phys(lpage);	lp->refcount = 0;	atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);	return 0;}static void i460_free_large_page (struct lp_desc *lp){	kfree(lp->alloced_map);	lp->alloced_map = NULL;	free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);	atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);}static int i460_insert_memory_large_io_page (struct agp_memory *mem,				off_t pg_start, int type){	int i, start_offset, end_offset, idx, pg, num_entries;	struct lp_desc *start, *end, *lp;	void *temp;	temp = agp_bridge->current_size;	num_entries = A_SIZE_8(temp)->num_entries;	/* Figure out what pg_start means in terms of our large GART pages */	start	 	= &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];	end 		= &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];	start_offset 	= pg_start % I460_KPAGES_PER_IOPAGE;	end_offset 	= (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;	if (end > i460.lp_desc + num_entries) {		printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");		return -EINVAL;	}	/* Check if the requested region of the aperture is free */	for (lp = start; lp <= end; ++lp) {		if (!lp->alloced_map)			continue;	/* OK, the entire large page is available... */		for (idx = ((lp == start) ? start_offset : 0);		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);		     idx++)		{			if (test_bit(idx, lp->alloced_map))				return -EBUSY;		}	}	for (lp = start, i = 0; lp <= end; ++lp) {		if (!lp->alloced_map) {			/* Allocate new GART pages... */			if (i460_alloc_large_page(lp) < 0)				return -ENOMEM;			pg = lp - i460.lp_desc;			WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0));			WR_FLUSH_GATT(pg);		}		for (idx = ((lp == start) ? start_offset : 0);		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);		     idx++, i++)		{			mem->memory[i] = lp->paddr + idx*PAGE_SIZE;			__set_bit(idx, lp->alloced_map);			++lp->refcount;		}	}	return 0;}static int i460_remove_memory_large_io_page (struct agp_memory *mem,				off_t pg_start, int type){	int i, pg, start_offset, end_offset, idx, num_entries;	struct lp_desc *start, *end, *lp;	void *temp;	temp = agp_bridge->driver->current_size;	num_entries = A_SIZE_8(temp)->num_entries;	/* Figure out what pg_start means in terms of our large GART pages */	start	 	= &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];	end 		= &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];	start_offset 	= pg_start % I460_KPAGES_PER_IOPAGE;	end_offset 	= (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;	for (i = 0, lp = start; lp <= end; ++lp) {		for (idx = ((lp == start) ? start_offset : 0);		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);		     idx++, i++)		{			mem->memory[i] = 0;			__clear_bit(idx, lp->alloced_map);			--lp->refcount;		}		/* Free GART pages if they are unused */		if (lp->refcount == 0) {			pg = lp - i460.lp_desc;			WR_GATT(pg, 0);			WR_FLUSH_GATT(pg);			i460_free_large_page(lp);		}	}	return 0;}/* Wrapper routines to call the approriate {small_io_page,large_io_page} function */static int i460_insert_memory (struct agp_memory *mem,				off_t pg_start, int type){	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)		return i460_insert_memory_small_io_page(mem, pg_start, type);	else		return i460_insert_memory_large_io_page(mem, pg_start, type);}static int i460_remove_memory (struct agp_memory *mem,				off_t pg_start, int type){	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)		return i460_remove_memory_small_io_page(mem, pg_start, type);	else		return i460_remove_memory_large_io_page(mem, pg_start, type);}/* * If the I/O (GART) page size is bigger than the kernel page size, we don't want to * allocate memory until we know where it is to be bound in the aperture (a * multi-kernel-page alloc might fit inside of an already allocated GART page). * * Let's just hope nobody counts on the allocated AGP memory being there before bind time * (I don't think current drivers do)... */static void *i460_alloc_page (void){	void *page;	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)		page = agp_generic_alloc_page();	else		/* Returning NULL would cause problems */		/* AK: really dubious code. */		page = (void *)~0UL;	return page;}static void i460_destroy_page (void *page){	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)		agp_generic_destroy_page(page);}#endif /* I460_LARGE_IO_PAGES */static unsigned long i460_mask_memory (unsigned long addr, int type){	/* Make sure the returned address is a valid GATT entry */	return (agp_bridge->driver->masks[0].mask		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12));}struct agp_bridge_driver intel_i460_driver = {	.owner			= THIS_MODULE,	.aperture_sizes		= i460_sizes,	.size_type		= U8_APER_SIZE,	.num_aperture_sizes	= 3,	.configure		= i460_configure,	.fetch_size		= i460_fetch_size,	.cleanup		= i460_cleanup,	.tlb_flush		= i460_tlb_flush,	.mask_memory		= i460_mask_memory,	.masks			= i460_masks,	.agp_enable		= agp_generic_enable,	.cache_flush		= global_cache_flush,	.create_gatt_table	= i460_create_gatt_table,	.free_gatt_table	= i460_free_gatt_table,#if I460_LARGE_IO_PAGES	.insert_memory		= i460_insert_memory,	.remove_memory		= i460_remove_memory,	.agp_alloc_page		= i460_alloc_page,	.agp_destroy_page	= i460_destroy_page,#else	.insert_memory		= i460_insert_memory_small_io_page,	.remove_memory		= i460_remove_memory_small_io_page,	.agp_alloc_page		= agp_generic_alloc_page,	.agp_destroy_page	= agp_generic_destroy_page,#endif	.alloc_by_type		= agp_generic_alloc_by_type,	.free_by_type		= agp_generic_free_by_type,	.cant_use_aperture	= 1,};static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,					  const struct pci_device_id *ent){	struct agp_bridge_data *bridge;	u8 cap_ptr;	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);	if (!cap_ptr)		return -ENODEV;	bridge = agp_alloc_bridge();	if (!bridge)		return -ENOMEM;	bridge->driver = &intel_i460_driver;	bridge->dev = pdev;	bridge->capndx = cap_ptr;	pci_set_drvdata(pdev, bridge);	return agp_add_bridge(bridge);}static void __devexit agp_intel_i460_remove(struct pci_dev *pdev){	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);	agp_remove_bridge(bridge);	agp_put_bridge(bridge);}static struct pci_device_id agp_intel_i460_pci_table[] = {	{	.class		= (PCI_CLASS_BRIDGE_HOST << 8),	.class_mask	= ~0,	.vendor		= PCI_VENDOR_ID_INTEL,	.device		= PCI_DEVICE_ID_INTEL_84460GX,	.subvendor	= PCI_ANY_ID,	.subdevice	= PCI_ANY_ID,	},	{ }};MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table);static struct pci_driver agp_intel_i460_pci_driver = {	.name		= "agpgart-intel-i460",	.id_table	= agp_intel_i460_pci_table,	.probe		= agp_intel_i460_probe,	.remove		= __devexit_p(agp_intel_i460_remove),};static int __init agp_intel_i460_init(void){	return pci_module_init(&agp_intel_i460_pci_driver);}static void __exit agp_intel_i460_cleanup(void){	pci_unregister_driver(&agp_intel_i460_pci_driver);}module_init(agp_intel_i460_init);module_exit(agp_intel_i460_cleanup);MODULE_AUTHOR("Chris Ahna <Christopher.J.Ahna@intel.com>");MODULE_LICENSE("GPL and additional rights");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -