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

📄 intel-agp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Intel AGPGART routines. *//* * Intel(R) 855GM/852GM and 865G support added by David Dawes * <dawes@tungstengraphics.com>. * * Intel(R) 915G/915GM support added by Alan Hourihane * <alanh@tungstengraphics.com>. */#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/pagemap.h>#include <linux/agp_backend.h>#include "agp.h"/* Intel 815 register */#define INTEL_815_APCONT	0x51#define INTEL_815_ATTBASE_MASK	~0x1FFFFFFF/* Intel i820 registers */#define INTEL_I820_RDCR		0x51#define INTEL_I820_ERRSTS	0xc8/* Intel i840 registers */#define INTEL_I840_MCHCFG	0x50#define INTEL_I840_ERRSTS	0xc8/* Intel i850 registers */#define INTEL_I850_MCHCFG	0x50#define INTEL_I850_ERRSTS	0xc8/* intel 915G registers */#define I915_GMADDR	0x18#define I915_MMADDR	0x10#define I915_PTEADDR	0x1C#define I915_GMCH_GMS_STOLEN_48M	(0x6 << 4)#define I915_GMCH_GMS_STOLEN_64M	(0x7 << 4)/* Intel 7505 registers */#define INTEL_I7505_APSIZE	0x74#define INTEL_I7505_NCAPID	0x60#define INTEL_I7505_NISTAT	0x6c#define INTEL_I7505_ATTBASE	0x78#define INTEL_I7505_ERRSTS	0x42#define INTEL_I7505_AGPCTRL	0x70#define INTEL_I7505_MCHCFG	0x50static struct aper_size_info_fixed intel_i810_sizes[] ={	{64, 16384, 4},	/* The 32M mode still requires a 64k gatt */	{32, 8192, 4}};#define AGP_DCACHE_MEMORY	1#define AGP_PHYS_MEMORY		2static struct gatt_mask intel_i810_masks[] ={	{.mask = I810_PTE_VALID, .type = 0},	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},	{.mask = I810_PTE_VALID, .type = 0}};static struct _intel_i810_private {	struct pci_dev *i810_dev;	/* device one */	volatile u8 __iomem *registers;	int num_dcache_entries;} intel_i810_private;static int intel_i810_fetch_size(void){	u32 smram_miscc;	struct aper_size_info_fixed *values;	pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);	if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {		printk(KERN_WARNING PFX "i810 is disabled\n");		return 0;	}	if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {		agp_bridge->previous_size =			agp_bridge->current_size = (void *) (values + 1);		agp_bridge->aperture_size_idx = 1;		return values[1].size;	} else {		agp_bridge->previous_size =			agp_bridge->current_size = (void *) (values);		agp_bridge->aperture_size_idx = 0;		return values[0].size;	}	return 0;}static int intel_i810_configure(void){	struct aper_size_info_fixed *current_size;	u32 temp;	int i;	current_size = A_SIZE_FIX(agp_bridge->current_size);	pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);	temp &= 0xfff80000;	intel_i810_private.registers = ioremap(temp, 128 * 4096);	if (!intel_i810_private.registers) {		printk(KERN_ERR PFX "Unable to remap memory.\n");		return -ENOMEM;	}	if ((readl(intel_i810_private.registers+I810_DRAM_CTL)		& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {		/* This will need to be dynamically assigned */		printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");		intel_i810_private.num_dcache_entries = 1024;	}	pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);	writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);	readl(intel_i810_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */	if (agp_bridge->driver->needs_scratch_page) {		for (i = 0; i < current_size->num_entries; i++) {			writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));			readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI posting. */		}	}	global_cache_flush();	return 0;}static void intel_i810_cleanup(void){	writel(0, intel_i810_private.registers+I810_PGETBL_CTL);	readl(intel_i810_private.registers);	/* PCI Posting. */	iounmap(intel_i810_private.registers);}static void intel_i810_tlbflush(struct agp_memory *mem){	return;}static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode){	return;}/* Exists to support ARGB cursors */static void *i8xx_alloc_pages(void){	struct page * page;	page = alloc_pages(GFP_KERNEL, 2);	if (page == NULL)		return NULL;	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {		global_flush_tlb();		__free_page(page);		return NULL;	}	global_flush_tlb();	get_page(page);	SetPageLocked(page);	atomic_inc(&agp_bridge->current_memory_agp);	return page_address(page);}static void i8xx_destroy_pages(void *addr){	struct page *page;	if (addr == NULL)		return;	page = virt_to_page(addr);	change_page_attr(page, 4, PAGE_KERNEL);	global_flush_tlb();	put_page(page);	unlock_page(page);	free_pages((unsigned long)addr, 2);	atomic_dec(&agp_bridge->current_memory_agp);}static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,				int type){	int i, j, num_entries;	void *temp;	temp = agp_bridge->current_size;	num_entries = A_SIZE_FIX(temp)->num_entries;	if ((pg_start + mem->page_count) > num_entries) {		return -EINVAL;	}	for (j = pg_start; j < (pg_start + mem->page_count); j++) {		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))			return -EBUSY;	}	if (type != 0 || mem->type != 0) {		if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {			/* special insert */			global_cache_flush();			for (i = pg_start; i < (pg_start + mem->page_count); i++) {				writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));				readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */			}			global_cache_flush();			agp_bridge->driver->tlb_flush(mem);			return 0;		}		if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))			goto insert;		return -EINVAL;	}insert:	global_cache_flush();	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {		writel(agp_bridge->driver->mask_memory(agp_bridge,			mem->memory[i], mem->type),			intel_i810_private.registers+I810_PTE_BASE+(j*4));		readl(intel_i810_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */	}	global_cache_flush();	agp_bridge->driver->tlb_flush(mem);	return 0;}static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,				int type){	int i;	for (i = pg_start; i < (mem->page_count + pg_start); i++) {		writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));		readl(intel_i810_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */	}	global_cache_flush();	agp_bridge->driver->tlb_flush(mem);	return 0;}/* * The i810/i830 requires a physical address to program its mouse * pointer into hardware. * However the Xserver still writes to it through the agp aperture. */static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type){	struct agp_memory *new;	void *addr;	if (pg_count != 1 && pg_count != 4)		return NULL;	switch (pg_count) {	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);		global_flush_tlb();		break;	case 4:		/* kludge to get 4 physical pages for ARGB cursor */		addr = i8xx_alloc_pages();		break;	default:		return NULL;	}	if (addr == NULL)		return NULL;	new = agp_create_memory(pg_count);	if (new == NULL)		return NULL;	new->memory[0] = virt_to_gart(addr);	if (pg_count == 4) {		/* kludge to get 4 physical pages for ARGB cursor */		new->memory[1] = new->memory[0] + PAGE_SIZE;		new->memory[2] = new->memory[1] + PAGE_SIZE;		new->memory[3] = new->memory[2] + PAGE_SIZE;	}	new->page_count = pg_count;	new->num_scratch_pages = pg_count;	new->type = AGP_PHYS_MEMORY;	new->physical = new->memory[0];	return new;}static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type){	struct agp_memory *new;	if (type == AGP_DCACHE_MEMORY) {		if (pg_count != intel_i810_private.num_dcache_entries)			return NULL;		new = agp_create_memory(1);		if (new == NULL)			return NULL;		new->type = AGP_DCACHE_MEMORY;		new->page_count = pg_count;		new->num_scratch_pages = 0;		vfree(new->memory);		return new;	}	if (type == AGP_PHYS_MEMORY)		return alloc_agpphysmem_i8xx(pg_count, type);	return NULL;}static void intel_i810_free_by_type(struct agp_memory *curr){	agp_free_key(curr->key);	if(curr->type == AGP_PHYS_MEMORY) {		if (curr->page_count == 4)			i8xx_destroy_pages(gart_to_virt(curr->memory[0]));		else {			agp_bridge->driver->agp_destroy_page(				 gart_to_virt(curr->memory[0]));			global_flush_tlb();		}		vfree(curr->memory);	}	kfree(curr);}static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,	unsigned long addr, int type){	/* Type checking must be done elsewhere */	return addr | bridge->driver->masks[type].mask;}static struct aper_size_info_fixed intel_i830_sizes[] ={	{128, 32768, 5},	/* The 64M mode still requires a 128k gatt */	{64, 16384, 5},	{256, 65536, 6},};static struct _intel_i830_private {	struct pci_dev *i830_dev;		/* device one */	volatile u8 __iomem *registers;	volatile u32 __iomem *gtt;		/* I915G */	int gtt_entries;} intel_i830_private;static void intel_i830_init_gtt_entries(void){	u16 gmch_ctrl;	int gtt_entries;	u8 rdct;	int local = 0;	static const int ddt[4] = { 0, 16, 32, 64 };	int size;	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);	/* We obtain the size of the GTT, which is also stored (for some	 * reason) at the top of stolen memory. Then we add 4KB to that	 * for the video BIOS popup, which is also stored in there. */	size = agp_bridge->driver->fetch_size() + 4;	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {		case I830_GMCH_GMS_STOLEN_512:			gtt_entries = KB(512) - KB(size);			break;		case I830_GMCH_GMS_STOLEN_1024:			gtt_entries = MB(1) - KB(size);			break;		case I830_GMCH_GMS_STOLEN_8192:			gtt_entries = MB(8) - KB(size);			break;		case I830_GMCH_GMS_LOCAL:			rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);			gtt_entries = (I830_RDRAM_ND(rdct) + 1) *					MB(ddt[I830_RDRAM_DDT(rdct)]);			local = 1;			break;		default:			gtt_entries = 0;			break;		}	} else {		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {		case I855_GMCH_GMS_STOLEN_1M:			gtt_entries = MB(1) - KB(size);			break;		case I855_GMCH_GMS_STOLEN_4M:			gtt_entries = MB(4) - KB(size);			break;		case I855_GMCH_GMS_STOLEN_8M:			gtt_entries = MB(8) - KB(size);			break;		case I855_GMCH_GMS_STOLEN_16M:			gtt_entries = MB(16) - KB(size);			break;		case I855_GMCH_GMS_STOLEN_32M:			gtt_entries = MB(32) - KB(size);			break;		case I915_GMCH_GMS_STOLEN_48M:			/* Check it's really I915G */			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)				gtt_entries = MB(48) - KB(size);			else				gtt_entries = 0;			break;		case I915_GMCH_GMS_STOLEN_64M:			/* Check it's really I915G */			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)				gtt_entries = MB(64) - KB(size);			else				gtt_entries = 0;		default:			gtt_entries = 0;			break;		}	}	if (gtt_entries > 0)		printk(KERN_INFO PFX "Detected %dK %s memory.\n",		       gtt_entries / KB(1), local ? "local" : "stolen");	else		printk(KERN_INFO PFX		       "No pre-allocated video memory detected.\n");	gtt_entries /= KB(4);	intel_i830_private.gtt_entries = gtt_entries;}/* The intel i830 automatically initializes the agp aperture during POST. * Use the memory already set aside for in the GTT. */static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge){	int page_order;	struct aper_size_info_fixed *size;	int num_entries;	u32 temp;	size = agp_bridge->current_size;

⌨️ 快捷键说明

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