📄 pci_bus_cvlink.c
字号:
/* $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 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/init.h>#include <linux/types.h>#include <linux/pci.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/cmn_err.h>#include <asm/sn/iobus.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/agent.h>#include <asm/sn/intr.h>#include <asm/sn/xtalk/xtalkaddrs.h>#include <asm/sn/klconfig.h>#include <asm/sn/io.h>#include <asm/sn/pci/pci_bus_cvlink.h>#include <asm/sn/pci/pciio.h>// #include <sys/ql.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/pci/pcibr_private.h>extern int bridge_rev_b_data_check_disable;#define MAX_PCI_XWIDGET 256devfs_handle_t busnum_to_xwidget[MAX_PCI_XWIDGET];nasid_t busnum_to_nid[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);/* * pci_bus_cvlink_init() - To be called once during initialization before * SGI IO Infrastructure init is called. */voidpci_bus_cvlink_init(void){ memset(busnum_to_xwidget, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET); memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); num_bridges = 0;}/* * 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 xwidget; devfs_handle_t pci_bus = NULL; /* * First get the xwidget vertex. */ xwidget = busnum_to_xwidget[busnum]; if (!xwidget) return (NULL); /* * Use devfs to get the pci vertex from xwidget. */ if (hwgraph_traverse(xwidget, EDGE_LBL_PCI, &pci_bus) != GRAPH_SUCCESS) { if (!pci_bus) { printk("pci_bus_to_vertex: Cannot find pci bus for given bus number %d\n", busnum); return (NULL); } } 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 = 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); if (func == 0) sprintf(name, "%d", slot); else sprintf(name, "%d%c", slot, 'a'+func); if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) { if (!device_vertex) { printk("devfn_to_vertex: Unable to get slot&func %s from pci vertex 0x%p\n", name, pci_bus); return(NULL); } } return(device_vertex);}/* * 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_sn1_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; } }}/* * sn1_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. */voidsn1_pci_fixup(int arg){ struct list_head *ln; struct pci_bus *pci_bus = NULL; struct pci_dev *device_dev = NULL; struct sn1_widget_sysdata *widget_sysdata; struct sn1_device_sysdata *device_sysdata; extern void sn1_pci_find_bios(void);unsigned long res; if (arg == 0) { sn1_pci_find_bios(); return; }#if 0{ devfs_handle_t bridge_vhdl = pci_bus_to_vertex(0); pcibr_soft_t pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl); bridge_t *bridge = pcibr_soft->bs_base;printk("Before Changing PIO Map Address:\n"); printk("pci_fixup_ioc3: Before devreg fixup\n"); printk("pci_fixup_ioc3: Devreg 0 0x%x\n", bridge->b_device[0].reg); printk("pci_fixup_ioc3: Devreg 1 0x%x\n", bridge->b_device[1].reg); printk("pci_fixup_ioc3: Devreg 2 0x%x\n", bridge->b_device[2].reg); printk("pci_fixup_ioc3: Devreg 3 0x%x\n", bridge->b_device[3].reg); printk("pci_fixup_ioc3: Devreg 4 0x%x\n", bridge->b_device[4].reg); printk("pci_fixup_ioc3: Devreg 5 0x%x\n", bridge->b_device[5].reg); printk("pci_fixup_ioc3: Devreg 6 0x%x\n", bridge->b_device[6].reg); printk("pci_fixup_ioc3: Devreg 7 0x%x\n", bridge->b_device[7].reg);}#endif done_probing = 1; if ( IS_RUNNING_ON_SIMULATOR() ) { printk("sn1_pci_fixup not supported on simulator.\n"); return; }#ifdef REAL_HARDWARE /* * 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 sn1_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 |= IO_SWIZ_BASE; ioport_resource.end |= (HSPEC_SWIZ_BASE-1); /* * 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; 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 sn1_device_sysdata), GFP_KERNEL); device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); device_sysdata->isa64 = 0; device_dev->sysdata = (void *) device_sysdata; set_sn1_pci64(device_dev); 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) {res = 0;res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);printk("Before pciio_pio_addr Base address %d = 0x%lx\n", idx, res); printk(" Changing device %d:%d resource start address from 0x%lx", PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn), device_dev->resource[idx].start); device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, PCIIO_BYTE_STREAM); } else continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -