generic.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,075 行 · 第 1/2 页

C
1,075
字号
	return cmd;}EXPORT_SYMBOL(agp_collect_device_status);void agp_device_command(u32 command, int agp_v3){	struct pci_dev *device = NULL;	int mode;	mode = command & 0x7;	if (agp_v3)		mode *= 4;	while ((device = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device)) != NULL) {		u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP);		if (!agp)			continue;		printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",				agp_v3 ? 3 : 2, pci_name(device), mode);		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);	}}EXPORT_SYMBOL(agp_device_command);void get_agp_version(struct agp_bridge_data *bridge){	u32 ncapid;	/* Exit early if already set by errata workarounds. */	if (agp_bridge->major_version != 0)		return;	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid);	agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;	agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;}EXPORT_SYMBOL(get_agp_version);void agp_generic_enable(u32 mode){	u32 command, temp;	u32 agp3;	get_agp_version(agp_bridge);	printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",				agp_bridge->major_version,				agp_bridge->minor_version,				agp_bridge->dev->slot_name);	pci_read_config_dword(agp_bridge->dev,		      agp_bridge->capndx + PCI_AGP_STATUS, &command);	command = agp_collect_device_status(mode, command);	command |= AGPSTAT_AGP_ENABLE;	/* Do AGP version specific frobbing. */	if(agp_bridge->major_version >= 3) {		pci_read_config_dword(agp_bridge->dev,			agp_bridge->capndx+AGPSTAT, &agp3);		/* Check to see if we are operating in 3.0 mode */		if (agp3 & AGPSTAT_MODE_3_0) {			/* If we have 3.5, we can do the isoch stuff. */			if (agp_bridge->minor_version >= 5)				agp_3_5_enable(agp_bridge);			agp_device_command(command, TRUE);			return;		} else {		    /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/		    command &= ~(7<<10) ;		    pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);		    temp |= (1<<9);		    pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp);		    printk (KERN_INFO PFX "Device is in legacy mode,"				" falling back to 2.x\n");		}	}	/* AGP v<3 */	agp_device_command(command, FALSE);}EXPORT_SYMBOL(agp_generic_enable);int agp_generic_create_gatt_table(void){	char *table;	char *table_end;	int size;	int page_order;	int num_entries;	int i;	void *temp;	struct page *page;	/* The generic routines can't handle 2 level gatt's */	if (agp_bridge->driver->size_type == LVL2_APER_SIZE)		return -EINVAL;	table = NULL;	i = agp_bridge->aperture_size_idx;	temp = agp_bridge->current_size;	size = page_order = num_entries = 0;	if (agp_bridge->driver->size_type != FIXED_APER_SIZE) {		do {			switch (agp_bridge->driver->size_type) {			case U8_APER_SIZE:				size = A_SIZE_8(temp)->size;				page_order =				    A_SIZE_8(temp)->page_order;				num_entries =				    A_SIZE_8(temp)->num_entries;				break;			case U16_APER_SIZE:				size = A_SIZE_16(temp)->size;				page_order = A_SIZE_16(temp)->page_order;				num_entries = A_SIZE_16(temp)->num_entries;				break;			case U32_APER_SIZE:				size = A_SIZE_32(temp)->size;				page_order = A_SIZE_32(temp)->page_order;				num_entries = A_SIZE_32(temp)->num_entries;				break;				/* This case will never really happen. */			case FIXED_APER_SIZE:			case LVL2_APER_SIZE:			default:				size = page_order = num_entries = 0;				break;			}			table = (char *) __get_free_pages(GFP_KERNEL,							  page_order);			if (table == NULL) {				i++;				switch (agp_bridge->driver->size_type) {				case U8_APER_SIZE:					agp_bridge->current_size = A_IDX8(agp_bridge);					break;				case U16_APER_SIZE:					agp_bridge->current_size = A_IDX16(agp_bridge);					break;				case U32_APER_SIZE:					agp_bridge->current_size = A_IDX32(agp_bridge);					break;					/* This case will never really happen. */				case FIXED_APER_SIZE:				case LVL2_APER_SIZE:				default:					agp_bridge->current_size =					    agp_bridge->current_size;					break;				}				temp = agp_bridge->current_size;			} else {				agp_bridge->aperture_size_idx = i;			}		} while (!table && (i < agp_bridge->driver->num_aperture_sizes));	} else {		size = ((struct aper_size_info_fixed *) temp)->size;		page_order = ((struct aper_size_info_fixed *) temp)->page_order;		num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;		table = (char *) __get_free_pages(GFP_KERNEL, page_order);	}	if (table == NULL)		return -ENOMEM;	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)		SetPageReserved(page);	agp_bridge->gatt_table_real = (u32 *) table;	agp_gatt_table = (void *)table;	agp_bridge->driver->cache_flush();	agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),					(PAGE_SIZE * (1 << page_order)));	agp_bridge->driver->cache_flush();	if (agp_bridge->gatt_table == NULL) {		for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)			ClearPageReserved(page);		free_pages((unsigned long) table, page_order);		return -ENOMEM;	}	agp_bridge->gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real);	/* AK: bogus, should encode addresses > 4GB */	for (i = 0; i < num_entries; i++)		agp_bridge->gatt_table[i] = (unsigned long) agp_bridge->scratch_page;	return 0;}EXPORT_SYMBOL(agp_generic_create_gatt_table);int agp_generic_free_gatt_table(void){	int page_order;	char *table, *table_end;	void *temp;	struct page *page;	temp = agp_bridge->current_size;	switch (agp_bridge->driver->size_type) {	case U8_APER_SIZE:		page_order = A_SIZE_8(temp)->page_order;		break;	case U16_APER_SIZE:		page_order = A_SIZE_16(temp)->page_order;		break;	case U32_APER_SIZE:		page_order = A_SIZE_32(temp)->page_order;		break;	case FIXED_APER_SIZE:		page_order = A_SIZE_FIX(temp)->page_order;		break;	case LVL2_APER_SIZE:		/* The generic routines can't deal with 2 level gatt's */		return -EINVAL;		break;	default:		page_order = 0;		break;	}	/* Do not worry about freeing memory, because if this is	 * called, then all agp memory is deallocated and removed	 * from the table. */	iounmap(agp_bridge->gatt_table);	table = (char *) agp_bridge->gatt_table_real;	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)		ClearPageReserved(page);	free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);	agp_gatt_table = NULL;	agp_bridge->gatt_table = NULL;	agp_bridge->gatt_table_real = NULL;	agp_bridge->gatt_bus_addr = 0;	return 0;}EXPORT_SYMBOL(agp_generic_free_gatt_table);int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type){	int num_entries;	size_t i;	off_t j;	void *temp;	temp = agp_bridge->current_size;	switch (agp_bridge->driver->size_type) {	case U8_APER_SIZE:		num_entries = A_SIZE_8(temp)->num_entries;		break;	case U16_APER_SIZE:		num_entries = A_SIZE_16(temp)->num_entries;		break;	case U32_APER_SIZE:		num_entries = A_SIZE_32(temp)->num_entries;		break;	case FIXED_APER_SIZE:		num_entries = A_SIZE_FIX(temp)->num_entries;		break;	case LVL2_APER_SIZE:		/* The generic routines can't deal with 2 level gatt's */		return -EINVAL;		break;	default:		num_entries = 0;		break;	}	num_entries -= agp_memory_reserved/PAGE_SIZE;	if (num_entries < 0) num_entries = 0;	if (type != 0 || mem->type != 0) {		/* The generic routines know nothing of memory types */		return -EINVAL;	}	/* AK: could wrap */	if ((pg_start + mem->page_count) > num_entries)		return -EINVAL;	j = pg_start;	while (j < (pg_start + mem->page_count)) {		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) {			return -EBUSY;		}		j++;	}	if (mem->is_flushed == FALSE) {		agp_bridge->driver->cache_flush();		mem->is_flushed = TRUE;	}	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)		agp_bridge->gatt_table[j] =				agp_bridge->driver->mask_memory(						mem->memory[i], mem->type);	agp_bridge->driver->tlb_flush(mem);	return 0;}EXPORT_SYMBOL(agp_generic_insert_memory);int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type){	size_t i;	if (type != 0 || mem->type != 0) {		/* The generic routines know nothing of memory types */		return -EINVAL;	}	/* AK: bogus, should encode addresses > 4GB */	for (i = pg_start; i < (mem->page_count + pg_start); i++) {		agp_bridge->gatt_table[i] =		    (unsigned long) agp_bridge->scratch_page;	}	agp_bridge->driver->tlb_flush(mem);	return 0;}EXPORT_SYMBOL(agp_generic_remove_memory);struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type){	return NULL;}EXPORT_SYMBOL(agp_generic_alloc_by_type);void agp_generic_free_by_type(struct agp_memory *curr){	if (curr->memory != NULL)		vfree(curr->memory);	agp_free_key(curr->key);	kfree(curr);}EXPORT_SYMBOL(agp_generic_free_by_type);/* * Basic Page Allocation Routines - * These routines handle page allocation and by default they reserve the allocated * memory.  They also handle incrementing the current_memory_agp value, Which is checked * against a maximum value. */void *agp_generic_alloc_page(void){	struct page * page;	page = alloc_page(GFP_KERNEL);	if (page == NULL)		return NULL;	map_page_into_agp(page);	get_page(page);	SetPageLocked(page);	atomic_inc(&agp_bridge->current_memory_agp);	return page_address(page);}EXPORT_SYMBOL(agp_generic_alloc_page);void agp_generic_destroy_page(void *addr){	struct page *page;	if (addr == NULL)		return;	page = virt_to_page(addr);	unmap_page_from_agp(page);	put_page(page);	unlock_page(page);	free_page((unsigned long)addr);	atomic_dec(&agp_bridge->current_memory_agp);}EXPORT_SYMBOL(agp_generic_destroy_page);/* End Basic Page Allocation Routines *//** * agp_enable  -  initialise the agp point-to-point connection. * * @mode:	agp mode register value to configure with. */void agp_enable(u32 mode){	if (agp_bridge->type == NOT_SUPPORTED)		return;	agp_bridge->driver->agp_enable(mode);}EXPORT_SYMBOL(agp_enable);#ifdef CONFIG_SMPstatic void ipi_handler(void *null){	flush_agp_cache();}#endifvoid global_cache_flush(void){#ifdef CONFIG_SMP	if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)		panic(PFX "timed out waiting for the other CPUs!\n");#else	flush_agp_cache();#endif}EXPORT_SYMBOL(global_cache_flush);unsigned long agp_generic_mask_memory(unsigned long addr, int type){	/* memory type is ignored in the generic routine */	if (agp_bridge->driver->masks)		return addr | agp_bridge->driver->masks[0].mask;	else		return addr;}EXPORT_SYMBOL(agp_generic_mask_memory);/* * These functions are implemented according to the AGPv3 spec, * which covers implementation details that had previously been * left open. */int agp3_generic_fetch_size(void){	u16 temp_size;	int i;	struct aper_size_info_16 *values;	pci_read_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, &temp_size);	values = A_SIZE_16(agp_bridge->driver->aperture_sizes);	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {		if (temp_size == values[i].size_value) {			agp_bridge->previous_size =				agp_bridge->current_size = (void *) (values + i);			agp_bridge->aperture_size_idx = i;			return values[i].size;		}	}	return 0;}EXPORT_SYMBOL(agp3_generic_fetch_size);void agp3_generic_tlbflush(struct agp_memory *mem){	u32 ctrl;	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl);	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_GTLBEN);	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl);}EXPORT_SYMBOL(agp3_generic_tlbflush);int agp3_generic_configure(void){	u32 temp;	struct aper_size_info_16 *current_size;	current_size = A_SIZE_16(agp_bridge->current_size);	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);	/* set aperture size */	pci_write_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, current_size->size_value);	/* set gart pointer */	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPGARTLO, agp_bridge->gatt_bus_addr);	/* enable aperture and GTLB */	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp | AGPCTRL_APERENB | AGPCTRL_GTLBEN);	return 0;}EXPORT_SYMBOL(agp3_generic_configure);void agp3_generic_cleanup(void){	u32 ctrl;	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl);	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_APERENB);}EXPORT_SYMBOL(agp3_generic_cleanup);struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] ={	{4096, 1048576, 10,0x000},	{2048,  524288, 9, 0x800},	{1024,  262144, 8, 0xc00},	{ 512,  131072, 7, 0xe00},	{ 256,   65536, 6, 0xf00},	{ 128,   32768, 5, 0xf20},	{  64,   16384, 4, 0xf30},	{  32,    8192, 3, 0xf38},	{  16,    4096, 2, 0xf3c},	{   8,    2048, 1, 0xf3e},	{   4,    1024, 0, 0xf3f}};EXPORT_SYMBOL(agp3_generic_sizes);

⌨️ 快捷键说明

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