📄 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-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 + -