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

📄 pci_bus_cvlink.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id$ * * 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) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved. */#include <linux/config.h>#include <linux/init.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/pci_ids.h>#include <linux/sched.h>#include <linux/ioport.h>#include <asm/sn/types.h>#include <asm/sn/hack.h>#include <asm/sn/sgi.h>#include <asm/sn/io.h>#include <asm/sn/driver.h>#include <asm/sn/iograph.h>#include <asm/param.h>#include <asm/sn/pio.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/sn_private.h>#include <asm/sn/addrs.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/hcl_util.h>#include <asm/sn/intr.h>#include <asm/sn/xtalk/xtalkaddrs.h>#include <asm/sn/klconfig.h>#include <asm/sn/nodepda.h>#include <asm/sn/pci/pciio.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/pci/pci_bus_cvlink.h>#include <asm/sn/simulator.h>#include <asm/sn/sn_cpuid.h>extern int bridge_rev_b_data_check_disable;devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET];nasid_t busnum_to_nid[MAX_PCI_XWIDGET];void * busnum_to_atedmamaps[MAX_PCI_XWIDGET];unsigned char num_bridges;static int done_probing = 0;static int pci_bus_map_create(devfs_handle_t xtalk);devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);extern unsigned char Is_pic_on_this_nasid[512];extern void sn_init_irq_desc(void);/* * For the given device, initialize whether it is a PIC device. */static voidset_isPIC(struct sn_device_sysdata *device_sysdata){	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);	device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);;}/* * pci_bus_cvlink_init() - To be called once during initialization before  *	SGI IO Infrastructure init is called. */voidpci_bus_cvlink_init(void){	extern void ioconfig_bus_init(void);	memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);	memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET);	memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET);	num_bridges = 0;	// ioconfig_bus_init();}/* * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated  *	pci bus vertex from the SGI IO Infrastructure. */devfs_handle_tpci_bus_to_vertex(unsigned char busnum){	devfs_handle_t	pci_bus = NULL;	/*	 * First get the xwidget vertex.	 */	pci_bus = busnum_to_pcibr_vhdl[busnum];	return(pci_bus);}/* * devfn_to_vertex() - returns the vertex of the device given the bus, slot,  *	and function numbers. */devfs_handle_tdevfn_to_vertex(unsigned char busnum, unsigned int devfn){	int slot = 0;	int func = 0;	char	name[16];	devfs_handle_t  pci_bus = NULL;	devfs_handle_t	device_vertex = (devfs_handle_t)NULL;	/*	 * Go get the pci bus vertex.	 */	pci_bus = pci_bus_to_vertex(busnum);	if (!pci_bus) {		/*		 * During probing, the Linux pci code invents non existant		 * bus numbers and pci_dev structures and tries to access		 * them to determine existance. Don't crib during probing.		 */		if (done_probing)			printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum);		return(NULL);	}	/*	 * Go get the slot&function vertex.	 * Should call pciio_slot_func_to_name() when ready.	 */	slot = PCI_SLOT(devfn);	func = PCI_FUNC(devfn);	/*	 * For a NON Multi-function card the name of the device looks like:	 * ../pci/1, ../pci/2 ..	 */	if (func == 0) {        	sprintf(name, "%d", slot);		if (hwgraph_traverse(pci_bus, name, &device_vertex) == 			GRAPH_SUCCESS) {			if (device_vertex) {				return(device_vertex);			}		}	}				/*	 * This maybe a multifunction card.  It's names look like:	 * ../pci/1a, ../pci/1b, etc.	 */	sprintf(name, "%d%c", slot, 'a'+func);	if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) {		if (!device_vertex) {			return(NULL);		}	}	return(device_vertex);}/* * For the given device, initialize the addresses for both the Device(x) Flush  * Write Buffer register and the Xbow Flush Register for the port the PCI bus  * is connected. */static voidset_flush_addresses(struct pci_dev *device_dev, 	struct sn_device_sysdata *device_sysdata){	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);	pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    	bridge_t               *bridge = pcibr_soft->bs_base;	nasid_t			nasid;	/*	 * Get the nasid from the bridge.	 */	nasid = NASID_GET(device_sysdata->dma_buf_sync);	if (IS_PIC_DEVICE(device_dev)) {		device_sysdata->dma_buf_sync = (volatile unsigned int *)			&bridge->b_wr_req_buf[pciio_slot].reg;		device_sysdata->xbow_buf_sync = (volatile unsigned int *)			XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0),			pcibr_soft->bs_xid);	} else {		/*		 * Accessing Xbridge and Xbow register when SHUB swapoper is on!.		 */		device_sysdata->dma_buf_sync = (volatile unsigned int *)			((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4);		device_sysdata->xbow_buf_sync = (volatile unsigned int *)			((uint64_t)(XBOW_PRIO_LINKREGS_PTR(			NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4);	}#ifdef DEBUG	printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", 		device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync);printk("set_flush_addresses: dma_buf_sync\n");	while((volatile unsigned int )*device_sysdata->dma_buf_sync);printk("set_flush_addresses: xbow_buf_sync\n");	while((volatile unsigned int )*device_sysdata->xbow_buf_sync);#endif}/* * Most drivers currently do not properly tell the arch specific pci dma * interfaces whether they can handle A64. Here is where we privately * keep track of this. */static void __initset_sn_pci64(struct pci_dev *dev){	unsigned short vendor = dev->vendor;	unsigned short device = dev->device;	if (vendor == PCI_VENDOR_ID_QLOGIC) {		if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) ||				(device == PCI_DEVICE_ID_QLOGIC_ISP2200)) {			SET_PCIA64(dev);			return;		}	}	if (vendor == PCI_VENDOR_ID_SGI) {		if (device == PCI_DEVICE_ID_SGI_IOC3) {			SET_PCIA64(dev);			return;		}	}}/* * sn_pci_fixup() - This routine is called when platform_pci_fixup() is  *	invoked at the end of pcibios_init() to link the Linux pci  *	infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c * *	Other platform specific fixup can also be done here. */voidsn_pci_fixup(int arg){	struct list_head *ln;	struct pci_bus *pci_bus = NULL;	struct pci_dev *device_dev = NULL;	struct sn_widget_sysdata *widget_sysdata;	struct sn_device_sysdata *device_sysdata;	pciio_intr_t intr_handle;	int cpuid, bit;	devfs_handle_t device_vertex;	pciio_intr_line_t lines;	extern void sn_pci_find_bios(void);	extern int numnodes;	int cnode;	extern void io_sh_swapper(int, int);	for (cnode = 0; cnode < numnodes; cnode++) {		if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )			io_sh_swapper((cnodeid_to_nasid(cnode)), 0);	}	if (arg == 0) {#ifdef CONFIG_PROC_FS		extern void register_sn_partition_id(void);		extern void register_sn_serial_numbers(void);#endif		sn_init_irq_desc();		sn_pci_find_bios();		for (cnode = 0; cnode < numnodes; cnode++) {			extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int);			intr_init_vecblk(NODEPDA(cnode), cnode, 0);		} 		/*		 * When we return to generic Linux, Swapper is always on ..		 */		for (cnode = 0; cnode < numnodes; cnode++) {			if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )				io_sh_swapper((cnodeid_to_nasid(cnode)), 1);		}#ifdef CONFIG_PROC_FS		register_sn_partition_id();		register_sn_serial_numbers();#endif		return;	}	done_probing = 1;	/*	 * Initialize the pci bus vertex in the pci_bus struct.	 */	for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {		pci_bus = pci_bus_b(ln);		widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), 					GFP_KERNEL);		widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number);		pci_bus->sysdata = (void *)widget_sysdata;	}	/* 	 * set the root start and end so that drivers calling check_region()	 * won't see a conflict	 */	ioport_resource.start  = 0xc000000000000000;	ioport_resource.end =    0xcfffffffffffffff;	/*	 * Set the root start and end for Mem Resource.	 */	iomem_resource.start = 0;	iomem_resource.end = 0xffffffffffffffff;	/*	 * Initialize the device vertex in the pci_dev struct.	 */	pci_for_each_dev(device_dev) {		unsigned int irq;		int idx;		u16 cmd;		devfs_handle_t vhdl;		unsigned long size;		extern int bit_pos_to_irq(int);		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&				device_dev->device == PCI_DEVICE_ID_SGI_IOC3) {			extern void pci_fixup_ioc3(struct pci_dev *d);			pci_fixup_ioc3(device_dev);		}		/* Set the device vertex */		device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),					GFP_KERNEL);		device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);		device_sysdata->isa64 = 0;		/*		 * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush 		 * register addresses.		 */		(void) set_flush_addresses(device_dev, device_sysdata);		device_dev->sysdata = (void *) device_sysdata;		set_sn_pci64(device_dev);		set_isPIC(device_sysdata);		pci_read_config_word(device_dev, PCI_COMMAND, &cmd);		/*		 * Set the resources address correctly.  The assumption here 		 * is that the addresses in the resource structure has been		 * read from the card and it was set in the card by our		 * Infrastructure ..		 */		vhdl = device_sysdata->vhdl;		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {			size = 0;			size = device_dev->resource[idx].end -				device_dev->resource[idx].start;			if (size) {				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);				device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET;			}			else				continue;			device_dev->resource[idx].end = 				device_dev->resource[idx].start + size;#ifdef BRINGUP2			printk("Device Vendor 0x%x, resource[%d] PIO Address = 0x%lx\n", device_dev->vendor, idx, (long)device_dev->resource[idx].start);#endif			if (device_dev->resource[idx].flags & IORESOURCE_IO)				cmd |= PCI_COMMAND_IO;			if (device_dev->resource[idx].flags & IORESOURCE_MEM)				cmd |= PCI_COMMAND_MEMORY;		}		/*		 * Now handle the ROM resource ..		 */#if 0	/*	 * Software WAR for a Software BUG.	 * This is only temporary.	 * See PV 872791	 */		size = device_dev->resource[PCI_ROM_RESOURCE].end -

⌨️ 快捷键说明

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