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

📄 sgi-agp.c

📁 linux-2.6.15.6
💻 C
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved. *//* * SGI TIOCA AGPGART routines. * */#include <linux/acpi.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/agp_backend.h>#include <asm/sn/addrs.h>#include <asm/sn/io.h>#include <asm/sn/pcidev.h>#include <asm/sn/pcibus_provider_defs.h>#include <asm/sn/tioca_provider.h>#include "agp.h"extern int agp_memory_reserved;extern uint32_t tioca_gart_found;extern struct list_head tioca_list;static struct agp_bridge_data **sgi_tioca_agp_bridges;/* * The aperature size and related information is set up at TIOCA init time. * Values for this table will be extracted and filled in at * sgi_tioca_fetch_size() time. */static struct aper_size_info_fixed sgi_tioca_sizes[] = {	{0, 0, 0},};static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge){	struct page *page;	int nid;	struct tioca_kernel *info =	    (struct tioca_kernel *)bridge->dev_private_data;	nid = info->ca_closest_node;	page = alloc_pages_node(nid, GFP_KERNEL, 0);	if (page == NULL) {		return 0;	}	get_page(page);	SetPageLocked(page);	atomic_inc(&agp_bridge->current_memory_agp);	return page_address(page);}/* * Flush GART tlb's.  Cannot selectively flush based on memory so the mem * arg is ignored. */static void sgi_tioca_tlbflush(struct agp_memory *mem){	tioca_tlbflush(mem->bridge->dev_private_data);}/* * Given an address of a host physical page, turn it into a valid gart * entry. */static unsigned longsgi_tioca_mask_memory(struct agp_bridge_data *bridge,		      unsigned long addr, int type){	return tioca_physpage_to_gart(addr);}static void sgi_tioca_agp_enable(struct agp_bridge_data *bridge, u32 mode){	tioca_fastwrite_enable(bridge->dev_private_data);}/* * sgi_tioca_configure() doesn't have anything to do since the base CA driver * has alreay set up the GART. */static int sgi_tioca_configure(void){	return 0;}/* * Determine gfx aperature size.  This has already been determined by the * CA driver init, so just need to set agp_bridge values accordingly. */static int sgi_tioca_fetch_size(void){	struct tioca_kernel *info =	    (struct tioca_kernel *)agp_bridge->dev_private_data;	sgi_tioca_sizes[0].size = info->ca_gfxap_size / MB(1);	sgi_tioca_sizes[0].num_entries = info->ca_gfxgart_entries;	return sgi_tioca_sizes[0].size;}static int sgi_tioca_create_gatt_table(struct agp_bridge_data *bridge){	struct tioca_kernel *info =	    (struct tioca_kernel *)bridge->dev_private_data;	bridge->gatt_table_real = (u32 *) info->ca_gfxgart;	bridge->gatt_table = bridge->gatt_table_real;	bridge->gatt_bus_addr = info->ca_gfxgart_base;	return 0;}static int sgi_tioca_free_gatt_table(struct agp_bridge_data *bridge){	return 0;}static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,				   int type){	int num_entries;	size_t i;	off_t j;	void *temp;	struct agp_bridge_data *bridge;	u64 *table;	bridge = mem->bridge;	if (!bridge)		return -EINVAL;	table = (u64 *)bridge->gatt_table;	temp = bridge->current_size;	switch (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:		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) {		return -EINVAL;	}	if ((pg_start + mem->page_count) > num_entries)		return -EINVAL;	j = pg_start;	while (j < (pg_start + mem->page_count)) {		if (table[j])			return -EBUSY;		j++;	}	if (mem->is_flushed == FALSE) {		bridge->driver->cache_flush();		mem->is_flushed = TRUE;	}	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {		table[j] =		    bridge->driver->mask_memory(bridge, mem->memory[i],						mem->type);	}	bridge->driver->tlb_flush(mem);	return 0;}static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,				   int type){	size_t i;	struct agp_bridge_data *bridge;	u64 *table;	bridge = mem->bridge;	if (!bridge)		return -EINVAL;	if (type != 0 || mem->type != 0) {		return -EINVAL;	}	table = (u64 *)bridge->gatt_table;	for (i = pg_start; i < (mem->page_count + pg_start); i++) {		table[i] = 0;	}	bridge->driver->tlb_flush(mem);	return 0;}static void sgi_tioca_cache_flush(void){}/* * Cleanup.  Nothing to do as the CA driver owns the GART. */static void sgi_tioca_cleanup(void){}static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev){	struct agp_bridge_data *bridge;	list_for_each_entry(bridge, &agp_bridges, list) {		if (bridge->dev->bus == pdev->bus)			break;	}	return bridge;}struct agp_bridge_driver sgi_tioca_driver = {	.owner = THIS_MODULE,	.size_type = U16_APER_SIZE,	.configure = sgi_tioca_configure,	.fetch_size = sgi_tioca_fetch_size,	.cleanup = sgi_tioca_cleanup,	.tlb_flush = sgi_tioca_tlbflush,	.mask_memory = sgi_tioca_mask_memory,	.agp_enable = sgi_tioca_agp_enable,	.cache_flush = sgi_tioca_cache_flush,	.create_gatt_table = sgi_tioca_create_gatt_table,	.free_gatt_table = sgi_tioca_free_gatt_table,	.insert_memory = sgi_tioca_insert_memory,	.remove_memory = sgi_tioca_remove_memory,	.alloc_by_type = agp_generic_alloc_by_type,	.free_by_type = agp_generic_free_by_type,	.agp_alloc_page = sgi_tioca_alloc_page,	.agp_destroy_page = agp_generic_destroy_page,	.cant_use_aperture = 1,	.needs_scratch_page = 0,	.num_aperture_sizes = 1,};static int __devinit agp_sgi_init(void){	unsigned int j;	struct tioca_kernel *info;	struct pci_dev *pdev = NULL;	if (tioca_gart_found)		printk(KERN_INFO PFX "SGI TIO CA GART driver initialized.\n");	else		return 0;	sgi_tioca_agp_bridges =	    (struct agp_bridge_data **)kmalloc(tioca_gart_found *					       sizeof(struct agp_bridge_data *),					       GFP_KERNEL);	j = 0;	list_for_each_entry(info, &tioca_list, ca_list) {		struct list_head *tmp;		if (list_empty(info->ca_devices))			continue;		list_for_each(tmp, info->ca_devices) {			u8 cap_ptr;			pdev = pci_dev_b(tmp);			if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))				continue;			cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);			if (!cap_ptr)				continue;		}		sgi_tioca_agp_bridges[j] = agp_alloc_bridge();		printk(KERN_INFO PFX "bridge %d = 0x%p\n", j,		       sgi_tioca_agp_bridges[j]);		if (sgi_tioca_agp_bridges[j]) {			sgi_tioca_agp_bridges[j]->dev = pdev;			sgi_tioca_agp_bridges[j]->dev_private_data = info;			sgi_tioca_agp_bridges[j]->driver = &sgi_tioca_driver;			sgi_tioca_agp_bridges[j]->gart_bus_addr =			    info->ca_gfxap_base;			sgi_tioca_agp_bridges[j]->mode = (0x7D << 24) |	/* 126 requests */			    (0x1 << 9) |	/* SBA supported */			    (0x1 << 5) |	/* 64-bit addresses supported */			    (0x1 << 4) |	/* FW supported */			    (0x1 << 3) |	/* AGP 3.0 mode */			    0x2;	/* 8x transfer only */			sgi_tioca_agp_bridges[j]->current_size =			    sgi_tioca_agp_bridges[j]->previous_size =			    (void *)&sgi_tioca_sizes[0];			agp_add_bridge(sgi_tioca_agp_bridges[j]);		}		j++;	}	agp_find_bridge = &sgi_tioca_find_bridge;	return 0;}static void __devexit agp_sgi_cleanup(void){	if(sgi_tioca_agp_bridges)		kfree(sgi_tioca_agp_bridges);	sgi_tioca_agp_bridges=NULL;}module_init(agp_sgi_init);module_exit(agp_sgi_cleanup);MODULE_LICENSE("GPL and additional rights");

⌨️ 快捷键说明

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