patch-2.4.4 linux/arch/ia64/sn/io/pci_bus_cvlink.c
Next file: linux/arch/ia64/sn/io/pci_dma.c
Previous file: linux/arch/ia64/sn/io/pci.c
Back to the patch index
Back to the overall index
- Lines: 490
- Date:
Thu Apr 12 12:16:35 2001
- Orig file:
v2.4.3/linux/arch/ia64/sn/io/pci_bus_cvlink.c
- Orig date:
Thu Jan 4 15:25:55 2001
diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pci_bus_cvlink.c linux/arch/ia64/sn/io/pci_bus_cvlink.c
@@ -16,7 +16,6 @@
#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>
@@ -32,23 +31,32 @@
#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;
+#include <asm/sn/pci/pci_bus_cvlink.h>
#define MAX_PCI_XWIDGET 256
-devfs_handle_t busnum_to_xwidget[MAX_PCI_XWIDGET];
+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 SN1_IOPORTS_UNIT 256
+#define MAX_IOPORTS 0xffff
+#define MAX_IOPORTS_CHUNKS (MAX_IOPORTS / SN1_IOPORTS_UNIT)
+struct ioports_to_tlbs_s ioports_to_tlbs[MAX_IOPORTS_CHUNKS];
+unsigned long sn1_allocate_ioports(unsigned long pci_address);
+
+
+
/*
* pci_bus_cvlink_init() - To be called once during initialization before
* SGI IO Infrastructure init is called.
@@ -56,9 +64,13 @@
void
pci_bus_cvlink_init(void)
{
-
- memset(busnum_to_xwidget, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);
+ 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;
}
@@ -70,27 +82,13 @@
pci_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);
- }
- }
-
+ pci_bus = busnum_to_pcibr_vhdl[busnum];
return(pci_bus);
}
@@ -138,7 +136,6 @@
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);
}
}
@@ -175,6 +172,61 @@
}
/*
+ * sn1_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 sn1_ioport_num = 0x100; /* Reserve room for Legacy stuff */
+unsigned long
+sn1_allocate_ioports(unsigned long pci_address)
+{
+
+ unsigned long ioport_index;
+
+ /*
+ * Just some idiot checking ..
+ */
+ if ( sn1_ioport_num > 0xffff ) {
+ printk("sn1_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 = sn1_ioport_num / SN1_IOPORTS_UNIT;
+ ioports_to_tlbs[ioport_index].ppn = pci_address;
+ ioports_to_tlbs[ioport_index].p = 1; /* Present Bit */
+ ioports_to_tlbs[ioport_index].ma = 5; /* Memory Attributes */
+ ioports_to_tlbs[ioport_index].a = 0; /* Set Data Access Bit Fault */
+ ioports_to_tlbs[ioport_index].d = 0; /* Dirty Bit */
+ ioports_to_tlbs[ioport_index].pl = 3;/* Privilege Level - All levels can R/W*/
+ ioports_to_tlbs[ioport_index].ar = 2; /* Access Rights - R/W only*/
+ ioports_to_tlbs[ioport_index].ed = 0; /* Exception Deferral Bit */
+ ioports_to_tlbs[ioport_index].ig = 0; /* Ignored */
+
+ printk("sn1_allocate_ioports: ioport_index 0x%x ioports_to_tlbs 0x%p\n", ioport_index, ioports_to_tlbs[ioport_index].ppn);
+
+ sn1_ioport_num += SN1_IOPORTS_UNIT;
+
+ return(sn1_ioport_num - SN1_IOPORTS_UNIT);
+}
+
+/*
* 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
@@ -189,6 +241,11 @@
struct pci_dev *device_dev = NULL;
struct sn1_widget_sysdata *widget_sysdata;
struct sn1_device_sysdata *device_sysdata;
+ unsigned long ioport;
+ pciio_intr_t intr_handle;
+ int cpuid, bit;
+ devfs_handle_t *device_vertex;
+ pciio_intr_line_t lines;
extern void sn1_pci_find_bios(void);
@@ -204,7 +261,6 @@
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);
@@ -280,16 +336,11 @@
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);
+ res = 0;
+ res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
+ device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, PCIIO_BYTE_STREAM);
+
+/* printk("sn1_pci_fixup: Mapped Address = 0x%p size = 0x%x\n", device_dev->resource[idx].start, size); */
}
else
continue;
@@ -304,13 +355,14 @@
device_dev->resource[idx].start & 0xfffff7ffffffffff;
device_dev->resource[idx].end =
device_dev->resource[idx].end & 0xfffff7ffffffffff;
- printk(" to 0x%lx\n", device_dev->resource[idx].start);
-res = 0;
-res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
-printk("After pciio_pio_addr Base address %d = 0x%lx\n", idx, res);
-
- if (device_dev->resource[idx].flags & IORESOURCE_IO)
+ res = 0;
+ res = pciio_config_get(vhdl, (unsigned) PCI_BASE_ADDRESS_0 + idx, 4);
+ if (device_dev->resource[idx].flags & IORESOURCE_IO) {
cmd |= PCI_COMMAND_IO;
+ ioport = sn1_allocate_ioports(device_dev->resource[idx].start);
+ /* device_dev->resource[idx].start = ioport; */
+ /* device_dev->resource[idx].end = ioport + SN1_IOPORTS_UNIT */
+ }
else if (device_dev->resource[idx].flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
@@ -319,9 +371,6 @@
*/
size = device_dev->resource[PCI_ROM_RESOURCE].end -
device_dev->resource[PCI_ROM_RESOURCE].start;
- printk(" Changing device %d:%d ROM resource start address from 0x%lx",
- PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),
- device_dev->resource[PCI_ROM_RESOURCE].start);
device_dev->resource[PCI_ROM_RESOURCE].start =
(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0,
size, 0, PCIIO_BYTE_STREAM);
@@ -341,24 +390,26 @@
/* bit gets dropped .. no harm */
pci_write_config_word(device_dev, PCI_COMMAND, cmd);
- printk(" to 0x%lx\n", device_dev->resource[PCI_ROM_RESOURCE].start);
+ pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, &lines);
+#ifdef BRINGUP
+ if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+ device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
+ lines = 1;
+ }
- /*
- * Set the irq correctly.
- * Bits 7:3 = slot
- * Bits 2:0 = function
- *
- * In the IRQ we will have:
- * Bits 24:16 = bus number
- * Bits 15:8 = slot|func number
- */
- irq = 0;
- irq = (irq | (device_dev->devfn << 8));
- irq = (irq | ( (device_dev->bus->number & 0xff) << 16) );
+#endif
+
+ device_sysdata = (struct sn1_device_sysdata *)device_dev->sysdata;
+ device_vertex = device_sysdata->vhdl;
+
+ intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex);
+
+ bit = intr_handle->pi_irq;
+ cpuid = intr_handle->pi_cpu;
+ irq = bit_pos_to_irq(bit);
+ irq = irq + (cpuid << 8);
+ pciio_intr_connect(intr_handle, NULL, NULL, NULL);
device_dev->irq = irq;
-printk("sn1_pci_fixup: slot= %d fn= %d vendor= 0x%x device= 0x%x irq= 0x%x\n",
-PCI_SLOT(device_dev->devfn),PCI_FUNC(device_dev->devfn),device_dev->vendor,
-device_dev->device, device_dev->irq);
}
#endif /* REAL_HARDWARE */
@@ -369,7 +420,6 @@
pcibr_soft_t pcibr_soft = (pcibr_soft_t) hwgraph_fastinfo_get(bridge_vhdl);
bridge_t *bridge = pcibr_soft->bs_base;
-printk("After 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);
@@ -386,6 +436,25 @@
/*
* pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job.
+ *
+ * Linux PCI Bus numbers are assigned from lowest module_id numbers
+ * (rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to
+ * HUB_WIDGET_ID_MIN:
+ * widgetnum 15 gets lower Bus Number than widgetnum 14 etc.
+ *
+ * Given 2 modules 001c01 and 001c02 we get the following mappings:
+ * 001c01, widgetnum 15 = Bus number 0
+ * 001c01, widgetnum 14 = Bus number 1
+ * 001c02, widgetnum 15 = Bus number 3
+ * 001c02, widgetnum 14 = Bus number 4
+ * etc.
+ *
+ * The rational for starting Bus Number 0 with Widget number 15 is because
+ * the system boot disks are always connected via Widget 15 Slot 0 of the
+ * I-brick. Linux creates /dev/sd* devices(naming) strating from Bus Number 0
+ * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest
+ * module id(Master Cnode) of the system.
+ *
*/
static int
pci_bus_map_create(devfs_handle_t xtalk)
@@ -402,10 +471,21 @@
/*
* Loop throught this vertex and get the Xwidgets ..
*/
- for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+ for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {
+ {
+ int pos;
+ char dname[256];
+ pos = devfs_generate_path(xtalk, dname, 256);
+ printk("%s : path= %s\n", __FUNCTION__, &dname[pos]);
+ }
+
sprintf(pathname, "%d", widgetnum);
xwidget = NULL;
+ /*
+ * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+ * /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device
+ */
rv = hwgraph_traverse(xtalk, pathname, &xwidget);
if ( (rv != GRAPH_SUCCESS) ) {
if (!xwidget)
@@ -425,25 +505,35 @@
* Should not be any race here ...
*/
num_bridges++;
- busnum_to_xwidget[num_bridges - 1] = xwidget;
+ busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus;
/*
* Get the master node and from there get the NASID.
*/
master_node_vertex = device_master_get(xwidget);
if (!master_node_vertex) {
- printk(" **** pci_bus_map_create: Unable to get .master for vertex 0x%p **** \n", xwidget);
+ printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", xwidget);
}
hubinfo_get(master_node_vertex, &hubinfo);
if (!hubinfo) {
- printk(" **** pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p ****\n", master_node_vertex);
+ printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", master_node_vertex);
return(1);
} else {
busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid;
}
- printk("pci_bus_map_create: Found Hub nasid %d PCI Xwidget 0x%p widgetnum= %d\n", hubinfo->h_nasid, xwidget, widgetnum);
+ /*
+ * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+ */
+ busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc(
+ sizeof(struct sn1_dma_maps_s) * 512, GFP_KERNEL);
+ if (!busnum_to_atedmamaps[num_bridges - 1])
+ printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, xwidget);
+
+ memset(busnum_to_atedmamaps[num_bridges - 1], 0x0,
+ sizeof(struct sn1_dma_maps_s) * 512);
+
}
return(0);
@@ -468,6 +558,9 @@
graph_vertex_place_t placeptr = EDGE_PLACE_WANT_REAL_EDGES;
int rv = 0;
char name[256];
+ int master_iobrick;
+ moduleid_t iobrick_id;
+ int i;
/*
* Iterate throught each xtalk links in the system ..
@@ -480,42 +573,48 @@
devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module");
/*
- * Loop throught this directory "/devfs/hw/module/" and get each
- * of it's entry.
- */
- while (1) {
-
- /* Get vertex of component /dev/hw/<module_number> */
- memset((char *)name, '0', 256);
- module_comp = NULL;
- rv = hwgraph_edge_get_next(devfs_hdl, (char *)name, &module_comp, (uint *)&placeptr);
- if ((rv == 0) && (module_comp)) {
- /* Found a valid entry */
- node = NULL;
- rv = hwgraph_edge_get(module_comp, "node", &node);
-
- } else {
- printk("pci_bus_to_hcl_cvlink: No more Module Component.\n");
- return(0);
+ * To provide consistent(not persistent) device naming, we need to start
+ * bus number allocation from the C-Brick with the lowest module id e.g. 001c01
+ * with an attached I-Brick. Find the master_iobrick.
+ */
+ master_iobrick = -1;
+ for (i = 0; i < nummodules; i++) {
+ moduleid_t iobrick_id;
+ iobrick_id = iobrick_module_get(&modules[i]->elsc);
+ if (iobrick_id > 0) { /* Valid module id */
+ if (MODULE_GET_BTYPE(iobrick_id) == MODULE_IBRICK) {
+ master_iobrick = i;
+ break;
+ }
}
+ }
- if ( (rv != 0) || (!node) ){
- printk("pci_bus_to_hcl_cvlink: Module Component does not have node vertex.\n");
- continue;
- } else {
- xtalk = NULL;
- rv = hwgraph_edge_get(node, "xtalk", &xtalk);
- if ( (rv != 0) || (xtalk == NULL) ){
- printk("pci_bus_to_hcl_cvlink: Node has no xtalk vertex.\n");
- continue;
- }
+ /*
+ * The master_iobrick gets bus 0 and 1.
+ */
+ if (master_iobrick >= 0) {
+ memset(name, 0, 256);
+ format_module_id(name, modules[master_iobrick]->id, MODULE_FORMAT_BRIEF);
+ strcat(name, "/node/xtalk");
+ xtalk = NULL;
+ rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
+ pci_bus_map_create(xtalk);
+ }
+
+ /*
+ * Now go do the rest of the modules, starting from the C-Brick with the lowest
+ * module id, remembering to skip the master_iobrick, which was done above.
+ */
+ for (i = 0; i < nummodules; i++) {
+ if (i == master_iobrick) {
+ continue; /* Did the master_iobrick already. */
}
- printk("pci_bus_to_hcl_cvlink: Found Module %s node vertex = 0x%p xtalk vertex = 0x%p\n", name, node, xtalk);
- /*
- * Call routine to get the existing PCI Xwidget and create
- * the convenience link from "/devfs/hw/pci_bus/.."
- */
+ memset(name, 0, 256);
+ format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
+ strcat(name, "/node/xtalk");
+ xtalk = NULL;
+ rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
pci_bus_map_create(xtalk);
}
@@ -539,10 +638,8 @@
struct sn1_widget_sysdata *widget_sysdata;
struct sn1_device_sysdata *device_sysdata;
- printk("sgi_pci_intr_support: Called with requested_irq 0x%x\n", requested_irq);
-
if (!dev_desc || !bus_vertex || !device_vertex) {
- printk("sgi_pci_intr_support: Invalid parameter dev_desc 0x%p, bus_vertex 0x%p, device_vertex 0x%p\n", dev_desc, bus_vertex, device_vertex);
+ printk("WARNING: sgi_pci_intr_support: Invalid parameter dev_desc 0x%p, bus_vertex 0x%p, device_vertex 0x%p\n", dev_desc, bus_vertex, device_vertex);
return(-1);
}
@@ -577,15 +674,11 @@
if (pci_dev->vendor == PCI_VENDOR_ID_SGI &&
pci_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
*lines = 1;
- printk("%s : IOC3 HACK: lines= %d\n", __FUNCTION__, *lines);
}
#endif /* BRINGUP */
/* Not supported currently */
*dev_desc = NULL;
-
- printk("sgi_pci_intr_support: Device Descriptor 0x%p, Bus Vertex 0x%p, Interrupt Pins 0x%x, Device Vertex 0x%p\n", *dev_desc, *bus_vertex, *lines, *device_vertex);
-
return(0);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)