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

📄 pci_bus_cvlink.c

📁 linux-2.4.29操作系统的源码
💻 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) 1992 - 1997, 2000-2003 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/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>#include <asm/sn/arch.h>extern int bridge_rev_b_data_check_disable;vertex_hdl_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;extern irqpda_t *irqpdaindr;static int pci_bus_map_create(vertex_hdl_t xtalk, int brick_type, char * io_moduleid);vertex_hdl_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);extern void register_pcibr_intr(int irq, pcibr_intr_t intr);void sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot);/* * 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(vertex_hdl_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. */vertex_hdl_tpci_bus_to_vertex(unsigned char busnum){	vertex_hdl_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. */vertex_hdl_tdevfn_to_vertex(unsigned char busnum, unsigned int devfn){	int slot = 0;	int func = 0;	char	name[16];	vertex_hdl_t  pci_bus = NULL;	vertex_hdl_t	device_vertex = (vertex_hdl_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-existent		 * bus numbers and pci_dev structures and tries to access		 * them to determine existence. 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);}struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS];// Initialize the data structures for flushing write buffers after a PIO read.// The theory is: // Take an unused int. pin and associate it with a pin that is in use.// After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush// on the in use pin.  This will prevent the race condition between PIO read responses and // DMA writes.voidsn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot) {	nasid_t nasid; 	unsigned long dnasid;	int wid_num;	int bus;	struct sn_flush_device_list *p;	bridge_t *b;	bridgereg_t dev_sel;	extern int isIO9(int);	int bwin;	int i;	nasid = NASID_GET(start);	wid_num = SWIN_WIDGETNUM(start);	bus = (start >> 23) & 0x1;	bwin = BWIN_WINDOWNUM(start);	if (flush_nasid_list[nasid].widget_p == NULL) {		flush_nasid_list[nasid].widget_p = (struct sn_flush_device_list **)kmalloc((HUB_WIDGET_ID_MAX+1) *			sizeof(struct sn_flush_device_list *), GFP_KERNEL);		if (flush_nasid_list[nasid].widget_p <= 0)			BUG(); /* Cannot afford to run out of memory. */		memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *));	}	if (bwin > 0) {		bwin--;		switch (bwin) {			case 0:				flush_nasid_list[nasid].iio_itte1 = HUB_L(IIO_ITTE_GET(nasid, 0));				wid_num = ((flush_nasid_list[nasid].iio_itte1) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte1 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 1:				flush_nasid_list[nasid].iio_itte2 = HUB_L(IIO_ITTE_GET(nasid, 1));				wid_num = ((flush_nasid_list[nasid].iio_itte2) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte2 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 2:				flush_nasid_list[nasid].iio_itte3 = HUB_L(IIO_ITTE_GET(nasid, 2));				wid_num = ((flush_nasid_list[nasid].iio_itte3) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte3 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 3:				flush_nasid_list[nasid].iio_itte4 = HUB_L(IIO_ITTE_GET(nasid, 3));				wid_num = ((flush_nasid_list[nasid].iio_itte4) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte4 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 4:				flush_nasid_list[nasid].iio_itte5 = HUB_L(IIO_ITTE_GET(nasid, 4));				wid_num = ((flush_nasid_list[nasid].iio_itte5) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte5 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 5:				flush_nasid_list[nasid].iio_itte6 = HUB_L(IIO_ITTE_GET(nasid, 5));				wid_num = ((flush_nasid_list[nasid].iio_itte6) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte6 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;			case 6:				flush_nasid_list[nasid].iio_itte7 = HUB_L(IIO_ITTE_GET(nasid, 6));				wid_num = ((flush_nasid_list[nasid].iio_itte7) >> 8) & 0xf;				bus = flush_nasid_list[nasid].iio_itte7 & 0xf;				if (bus == 0x4 || bus == 0x8)					bus = 0;				else					bus = 1;				break;		}	}	// if it's IO9, bus 1, we don't care about slots 1, 3, and 4.  This is	// because these are the IOC4 slots and we don't flush them.	if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) {		return;	}	if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) {		flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc(			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL);		if (flush_nasid_list[nasid].widget_p[wid_num] <= 0)			BUG(); /* Cannot afford to run out of memory. */		memset(flush_nasid_list[nasid].widget_p[wid_num], 0, 			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list));		p = &flush_nasid_list[nasid].widget_p[wid_num][0];		for (i=0; i<DEV_PER_WIDGET;i++) {			p->bus = -1;			p->pin = -1;			p++;		}	}	p = &flush_nasid_list[nasid].widget_p[wid_num][0];	for (i=0;i<DEV_PER_WIDGET; i++) {		if (p->pin == pin && p->bus == bus) break;		if (p->pin < 0) {			p->pin = pin;			p->bus = bus;			break;		}		p++;	}	for (i=0; i<PCI_ROM_RESOURCE; i++) {		if (p->bar_list[i].start == 0) {			p->bar_list[i].start = start;			p->bar_list[i].end = end;			break;		}	}	b = (bridge_t *)(NODE_SWIN_BASE(nasid, wid_num) | (bus << 23) );	// If it's IO9, then slot 2 maps to slot 7 and slot 6 maps to slot 8.	// To see this is non-trivial.  By drawing pictures and reading manuals and talking	// to HW guys, we can see that on IO9 bus 1, slots 7 and 8 are always unused.	// Further, since we short-circuit slots  1, 3, and 4 above, we only have to worry	// about the case when there is a card in slot 2.  A multifunction card will appear	// to be in slot 6 (from an interrupt point of view) also.  That's the  most we'll	// have to worry about.  A four function card will overload the interrupt lines in	// slot 2 and 6.  	// We also need to special case the 12160 device in slot 3.  Fortunately, we have	// a spare intr. line for pin 4, so we'll use that for the 12160.	// All other buses have slot 3 and 4 and slots 7 and 8 unused.  Since we can only	// see slots 1 and 2 and slots 5 and 6 coming through here for those buses (this	// is true only on Pxbricks with 2 physical slots per bus), we just need to add	// 2 to the slot number to find an unused slot.	// We have convinced ourselves that we will never see a case where two different cards	// in two different slots will ever share an interrupt line, so there is no need to	// special case this.	if (isIO9(nasid) && wid_num == 0xc && bus == 0) {		if (slot == 2) {			p->force_int_addr = (unsigned long)&b->b_force_always[6].intr;			dev_sel = b->b_int_device;			dev_sel |= (1<<18);			b->b_int_device = dev_sel;			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));			b->p_int_addr_64[6] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | 				(dnasid << 36) | (0xfUL << 48);		} else  if (slot == 3) { /* 12160 SCSI device in IO9 */			p->force_int_addr = (unsigned long)&b->b_force_always[4].intr;			dev_sel = b->b_int_device;			dev_sel |= (2<<12);			b->b_int_device = dev_sel;			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));			b->p_int_addr_64[4] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | 				(dnasid << 36) | (0xfUL << 48);		} else { /* slot == 6 */			p->force_int_addr = (unsigned long)&b->b_force_always[7].intr;			dev_sel = b->b_int_device;			dev_sel |= (5<<21);			b->b_int_device = dev_sel;			dnasid = NASID_GET(virt_to_phys(&p->flush_addr));			b->p_int_addr_64[7] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | 				(dnasid << 36) | (0xfUL << 48);		}	} else {		p->force_int_addr = (unsigned long)&b->b_force_always[pin + 2].intr;		dev_sel = b->b_int_device;		dev_sel |= ((slot - 1) << ( pin * 3) );		b->b_int_device = dev_sel;		dnasid = NASID_GET(virt_to_phys(&p->flush_addr));		b->p_int_addr_64[pin + 2] = (virt_to_phys(&p->flush_addr) & 0xfffffffff) | 			(dnasid << 36) | (0xfUL << 48);	}}/* * 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;		}	}}/* * 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;	vertex_hdl_t device_vertex;	pciio_intr_line_t lines;	extern void sn_pci_find_bios(void);	extern int numnodes;	int cnode;	if (arg == 0) {#ifdef CONFIG_PROC_FS		extern void register_sn_procfs(void);#endif		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);		} #ifdef CONFIG_PROC_FS		register_sn_procfs();#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), 

⌨️ 快捷键说明

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