📄 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);#define SN_IOPORTS_UNIT 256#define MAX_IOPORTS 0xffff#define MAX_IOPORTS_CHUNKS (MAX_IOPORTS / SN_IOPORTS_UNIT)struct ioports_to_tlbs_s ioports_to_tlbs[MAX_IOPORTS_CHUNKS];unsigned long sn_allocate_ioports(unsigned long pci_address);extern void sn_init_irq_desc(void);/* * 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_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); memset(ioports_to_tlbs, 0x0, sizeof(ioports_to_tlbs)); 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 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-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);}/* * 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; 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(get_nasid(), 0), pcibr_soft->bs_xid);#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); while((volatile unsigned int )*device_sysdata->dma_buf_sync); 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_allocate_ioports() - This routine provides the allocation and * mappings between Linux style IOPORTs management. * * For simplicity sake, SN1 will allocate IOPORTs in chunks of * 256bytes .. irrespective of what the card desires. This may * have to change when we understand how to deal with legacy ioports * which are hardcoded in some drivers e.g. SVGA. * * Ofcourse, the SN1 IO Infrastructure has no concept of IOPORT numbers. * It will remain so. The IO Infrastructure will continue to map * IO Resource just like IRIX. When this is done, we map IOPORT * chunks to these resources. The Linux drivers will see and use real * IOPORT numbers. The various IOPORT access macros e.g. inb/outb etc. * does the munging of these IOPORT numbers to make a Uncache Virtual * Address. This address via the tlb entries generates the PCI Address * allocated by the SN1 IO Infrastructure Layer. */static unsigned long sn_ioport_num = 0x1000; /* Reserve room for Legacy stuff */unsigned longsn_allocate_ioports(unsigned long pci_address){ unsigned long ioport_index; /* * Just some idiot checking .. */ if ( sn_ioport_num > 0xffff ) { printk("sn_allocate_ioports: No more IO PORTS available\n"); return(-1); } /* * See Section 4.1.1.5 of Intel IA-64 Acrchitecture Software Developer's * Manual for details. */ ioport_index = sn_ioport_num / SN_IOPORTS_UNIT; ioports_to_tlbs[ioport_index].p = 1; /* Present Bit */ ioports_to_tlbs[ioport_index].rv_1 = 0; /* 1 Bit */ ioports_to_tlbs[ioport_index].ma = 4; /* Memory Attributes 3 bits*/ ioports_to_tlbs[ioport_index].a = 1; /* Set Data Access Bit Fault 1 Bit*/ ioports_to_tlbs[ioport_index].d = 1; /* Dirty Bit */ ioports_to_tlbs[ioport_index].pl = 0;/* Privilege Level - All levels can R/W*/ ioports_to_tlbs[ioport_index].ar = 3; /* Access Rights - R/W only*/ ioports_to_tlbs[ioport_index].ppn = pci_address >> 12; /* 4K page size */ ioports_to_tlbs[ioport_index].ed = 0; /* Exception Deferral Bit */ ioports_to_tlbs[ioport_index].ig = 0; /* Ignored */ /* printk("sn_allocate_ioports: ioport_index 0x%x ioports_to_tlbs 0x%p\n", ioport_index, ioports_to_tlbs[ioport_index]); */ sn_ioport_num += SN_IOPORTS_UNIT; return(sn_ioport_num - SN_IOPORTS_UNIT);}/* * 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;#ifdef SN_IOPORTS unsigned long ioport;#endif 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);#ifdef CONFIG_IA64_SGI_SN2 extern int numnodes; int cnode;#endif /* CONFIG_IA64_SGI_SN2 */ if (arg == 0) { sn_init_irq_desc(); sn_pci_find_bios();#ifdef CONFIG_IA64_SGI_SN2 for (cnode = 0; cnode < numnodes; cnode++) { extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int); intr_init_vecblk(NODEPDA(cnode), cnode, 0); } #endif /* CONFIG_IA64_SGI_SN2 */ 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("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; /* * 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 */#ifdef SN_IOPORTS ioport_resource.start = sn_ioport_num; ioport_resource.end = 0xffff;#else#if defined(CONFIG_IA64_SGI_SN1) if ( IS_RUNNING_ON_SIMULATOR() ) { /* * IDE legacy IO PORTs are supported in Medusa. * Just open up IO PORTs from 0 .. ioport_resource.end. */ ioport_resource.start = 0; } else { /* * We do not support Legacy IO PORT numbers. */ ioport_resource.start |= IO_SWIZ_BASE | __IA64_UNCACHED_OFFSET; } ioport_resource.end |= (HSPEC_SWIZ_BASE-1) | __IA64_UNCACHED_OFFSET;#else // Need something here for sn2.... ZXZXZX#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -