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

📄 tioca_provider.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. */#include <linux/types.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <asm/sn/sn_sal.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>u32 tioca_gart_found;EXPORT_SYMBOL(tioca_gart_found);	/* used by agp-sgi */LIST_HEAD(tioca_list);EXPORT_SYMBOL(tioca_list);	/* used by agp-sgi */static int tioca_gart_init(struct tioca_kernel *);/** * tioca_gart_init - Initialize SGI TIOCA GART * @tioca_common: ptr to common prom/kernel struct identifying the  * * If the indicated tioca has devices present, initialize its associated * GART MMR's and kernel memory. */static inttioca_gart_init(struct tioca_kernel *tioca_kern){	u64 ap_reg;	u64 offset;	struct page *tmp;	struct tioca_common *tioca_common;	struct tioca __iomem *ca_base;	tioca_common = tioca_kern->ca_common;	ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;	if (list_empty(tioca_kern->ca_devices))		return 0;	ap_reg = 0;	/*	 * Validate aperature size	 */	switch (CA_APERATURE_SIZE >> 20) {	case 4:		ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT);	/* 4MB */		break;	case 8:		ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT);	/* 8MB */		break;	case 16:		ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT);	/* 16MB */		break;	case 32:		ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT);	/* 32 MB */		break;	case 64:		ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT);	/* 64 MB */		break;	case 128:		ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT);	/* 128 MB */		break;	case 256:		ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT);	/* 256 MB */		break;	case 512:		ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT);	/* 512 MB */		break;	case 1024:		ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT);	/* 1GB */		break;	case 2048:		ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT);	/* 2GB */		break;	case 4096:		ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT);	/* 4 GB */		break;	default:		printk(KERN_ERR "%s:  Invalid CA_APERATURE_SIZE "		       "0x%lx\n", __FUNCTION__, (ulong) CA_APERATURE_SIZE);		return -1;	}	/*	 * Set up other aperature parameters	 */	if (PAGE_SIZE >= 16384) {		tioca_kern->ca_ap_pagesize = 16384;		ap_reg |= CA_GART_PAGE_SIZE;	} else {		tioca_kern->ca_ap_pagesize = 4096;	}	tioca_kern->ca_ap_size = CA_APERATURE_SIZE;	tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE;	tioca_kern->ca_gart_entries =	    tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize;	ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI);	ap_reg |= tioca_kern->ca_ap_bus_base;	/*	 * Allocate and set up the GART	 */	tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64);	tmp =	    alloc_pages_node(tioca_kern->ca_closest_node,			     GFP_KERNEL | __GFP_ZERO,			     get_order(tioca_kern->ca_gart_size));	if (!tmp) {		printk(KERN_ERR "%s:  Could not allocate "		       "%lu bytes (order %d) for GART\n",		       __FUNCTION__,		       tioca_kern->ca_gart_size,		       get_order(tioca_kern->ca_gart_size));		return -ENOMEM;	}	tioca_kern->ca_gart = page_address(tmp);	tioca_kern->ca_gart_coretalk_addr =	    PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart));	/*	 * Compute PCI/AGP convenience fields 	 */	offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE;	tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE;	tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE;	tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize;	tioca_kern->ca_pcigart_base =	    tioca_kern->ca_gart_coretalk_addr + offset;	tioca_kern->ca_pcigart =	    &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start];	tioca_kern->ca_pcigart_entries =	    tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;	tioca_kern->ca_pcigart_pagemap =	    kzalloc(tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);	if (!tioca_kern->ca_pcigart_pagemap) {		free_pages((unsigned long)tioca_kern->ca_gart,			   get_order(tioca_kern->ca_gart_size));		return -1;	}	offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE;	tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE;	tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE;	tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize;	tioca_kern->ca_gfxgart_base =	    tioca_kern->ca_gart_coretalk_addr + offset;	tioca_kern->ca_gfxgart =	    &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start];	tioca_kern->ca_gfxgart_entries =	    tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize;	/*	 * various control settings:	 *      use agp op-combining	 *      use GET semantics to fetch memory	 *      participate in coherency domain	 * 	DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029	 */	__sn_setq_relaxed(&ca_base->ca_control1,			CA_AGPDMA_OP_ENB_COMBDELAY);	/* PV895469 ? */	__sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);	__sn_setq_relaxed(&ca_base->ca_control2,			(0x2ull << CA_GART_MEM_PARAM_SHFT));	tioca_kern->ca_gart_iscoherent = 1;	__sn_clrq_relaxed(&ca_base->ca_control2,	    		(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB));	/*	 * Unmask GART fetch error interrupts.  Clear residual errors first.	 */	writeq(CA_GART_FETCH_ERR, &ca_base->ca_int_status_alias);	writeq(CA_GART_FETCH_ERR, &ca_base->ca_mult_error_alias);	__sn_clrq_relaxed(&ca_base->ca_int_mask, CA_GART_FETCH_ERR);	/*	 * Program the aperature and gart registers in TIOCA	 */	writeq(ap_reg, &ca_base->ca_gart_aperature);	writeq(tioca_kern->ca_gart_coretalk_addr|1, &ca_base->ca_gart_ptr_table);	return 0;}/** * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions * @tioca_kernel: structure representing the CA * * Given a CA, scan all attached functions making sure they all support * FastWrite.  If so, enable FastWrite for all functions and the CA itself. */voidtioca_fastwrite_enable(struct tioca_kernel *tioca_kern){	int cap_ptr;	u32 reg;	struct tioca __iomem *tioca_base;	struct pci_dev *pdev;	struct tioca_common *common;	common = tioca_kern->ca_common;	/*	 * Scan all vga controllers on this bus making sure they all	 * support FW.  If not, return.	 */	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))			continue;		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);		if (!cap_ptr)			return;	/* no AGP CAP means no FW */		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, &reg);		if (!(reg & PCI_AGP_STATUS_FW))			return;	/* function doesn't support FW */	}	/*	 * Set fw for all vga fn's	 */	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))			continue;		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, &reg);		reg |= PCI_AGP_COMMAND_FW;		pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg);	}	/*	 * Set ca's fw to match	 */	tioca_base = (struct tioca __iomem*)common->ca_common.bs_base;	__sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);}EXPORT_SYMBOL(tioca_fastwrite_enable);	/* used by agp-sgi *//** * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode * @paddr: system physical address * * Map @paddr into 64-bit CA bus space.  No device context is necessary. * Bits 53:0 come from the coretalk address.  We just need to mask in the * following optional bits of the 64-bit pci address: * * 63:60 - Coretalk Packet Type -  0x1 for Mem Get/Put (coherent) *                                 0x2 for PIO (non-coherent) *                                 We will always use 0x1 * 55:55 - Swap bytes		   Currently unused */static u64tioca_dma_d64(unsigned long paddr){	dma_addr_t bus_addr;	bus_addr = PHYS_TO_TIODMA(paddr);	BUG_ON(!bus_addr);	BUG_ON(bus_addr >> 54);	/* Set upper nibble to Cache Coherent Memory op */	bus_addr |= (1UL << 60);	return bus_addr;}/** * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode * @pdev: linux pci_dev representing the function * @paddr: system physical address * * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info. * * The CA agp 48 bit direct address falls out as follows: * * When direct mapping AGP addresses, the 48 bit AGP address is * constructed as follows: * * [47:40] - Low 8 bits of the page Node ID extracted from coretalk *              address [47:40].  The upper 8 node bits are fixed *              and come from the xxx register bits [5:0] * [39:38] - Chiplet ID extracted from coretalk address [39:38] * [37:00] - node offset extracted from coretalk address [37:00] *  * Since the node id in general will be non-zero, and the chiplet id * will always be non-zero, it follows that the device must support * a dma mask of at least 0xffffffffff (40 bits) to target node 0 * and in general should be 0xffffffffffff (48 bits) to target nodes * up to 255.  Nodes above 255 need the support of the xxx register, * and so a given CA can only directly target nodes in the range * xxx - xxx+255. */static u64tioca_dma_d48(struct pci_dev *pdev, u64 paddr){	struct tioca_common *tioca_common;	struct tioca __iomem *ca_base;	u64 ct_addr;	dma_addr_t bus_addr;	u32 node_upper;	u64 agp_dma_extn;	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;	ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base;	ct_addr = PHYS_TO_TIODMA(paddr);	if (!ct_addr)		return 0;	bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffffUL);	node_upper = ct_addr >> 48;

⌨️ 快捷键说明

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