static void __init pci_enable_swapping(struct pci_dev *dev) { unsigned int bus_id = (unsigned) dev->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], bus_to_wid[bus_id]); int slot = PCI_SLOT(dev->devfn); /* Turn on byte swapping */ bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bridge->b_widget.w_tflush; /* Flush */ }
/** * hub_pio_map - establish a HUB PIO mapping * * @hub: hub to perform PIO mapping on * @widget: widget ID to perform PIO mapping for * @xtalk_addr: xtalk_address that needs to be mapped * @size: size of the PIO mapping * **/ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, unsigned long xtalk_addr, size_t size) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); volatile hubreg_t junk; unsigned i; /* use small-window mapping if possible */ if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE) return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE); if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) { printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx" " too big (%ld)\n", nasid, widget, xtalk_addr, size); return 0; } xtalk_addr &= ~(BWIN_SIZE-1); for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) { if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used)) continue; /* * The code below does a PIO write to setup an ITTE entry. * * We need to prevent other CPUs from seeing our updated * memory shadow of the ITTE (in the piomap) until the ITTE * entry is actually set up; otherwise, another CPU might * attempt a PIO prematurely. * * Also, the only way we can know that an entry has been * received by the hub and can be used by future PIO reads/ * writes is by reading back the ITTE entry after writing it. * * For these two reasons, we PIO read back the ITTE entry * after we write it. */ IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr); junk = HUB_L(IIO_ITTE_GET(nasid, i)); return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE); } printk(KERN_WARNING "unable to establish PIO mapping for at" " hub %d widget %d addr 0x%lx\n", nasid, widget, xtalk_addr); return 0; }
/* * Setup pio structures needed for a particular hub. */ static void hub_pio_init(devfs_handle_t hubv) { xwidgetnum_t widget; hubinfo_t hubinfo; nasid_t nasid; int bigwin; hub_piomap_t hub_piomap; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; /* Initialize small window piomaps for this hub */ for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) { hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget); hub_piomap->hpio_xtalk_info.xp_target = widget; hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0; hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE; hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget); hub_piomap->hpio_hub = hubv; hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID; } /* Initialize big window piomaps for this hub */ for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin); hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE; hub_piomap->hpio_hub = hubv; hub_piomap->hpio_holdcnt = 0; hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW; IIO_ITTE_DISABLE(nasid, bigwin); } #ifdef BRINGUP hub_set_piomode(nasid, HUB_PIO_CONVEYOR); #else /* Set all the xwidgets in fire-and-forget mode * by default */ hub_set_piomode(nasid, HUB_PIO_FIRE_N_FORGET); #endif /* BRINGUP */ sv_init(&hubinfo->h_bwwait, SV_FIFO, "bigwin"); spinlock_init(&hubinfo->h_bwlock, "bigwin"); }
/* * 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 void set_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 }
static void __init pci_fixup_isp2x00(struct pci_dev *d) { unsigned int bus_id = (unsigned) d->bus->number; bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], bus_to_wid[bus_id]); bridgereg_t devreg; int i; int slot = PCI_SLOT(d->devfn); unsigned int start; unsigned short command; printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name); /* set the resource struct for this device */ start = (u32) (u64)bridge; /* yes, we want to lose the upper 32 bits here */ start |= BRIDGE_DEVIO(slot); d->resource[0].start = start; d->resource[0].end = d->resource[0].start + 0xff; d->resource[0].flags = IORESOURCE_IO; d->resource[1].start = start; d->resource[1].end = d->resource[0].start + 0xfff; d->resource[1].flags = IORESOURCE_MEM; /* * set the bridge device(x) reg for this device */ devreg = bridge->b_device[slot].reg; /* point device(x) to it appropriate small window */ devreg &= ~BRIDGE_DEV_OFF_MASK; devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; bridge->b_device[slot].reg = devreg; pci_enable_swapping(d); /* set card's base addr reg */ //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); /* I got these from booting irix on system...*/ pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start); //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); /* set cache line size */ pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); /* set pci bus timeout */ bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); bridge->b_wid_tflush; printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); /* set host error field */ bridge->b_int_host_err = 0x44; bridge->b_wid_tflush; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ for (i=0; i<8; i++) printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg); /* configure device to allow bus mastering, i/o and memory mapping */ pci_set_master(d); pci_read_config_word(d, PCI_COMMAND, &command); command |= PCI_COMMAND_MEMORY; command |= PCI_COMMAND_IO; pci_write_config_word(d, PCI_COMMAND, command); /*d->resource[1].flags |= 1;*/ }
/* * Initialize all I/O on the specified node. */ static void io_init_node(cnodeid_t cnodeid) { /*REFERENCED*/ vertex_hdl_t hubv, switchv, widgetv; struct xwidget_hwid_s hwid; hubinfo_t hubinfo; int is_xswitch; nodepda_t *npdap; struct semaphore *peer_sema = 0; uint32_t widget_partnum; cpuid_t c = 0; npdap = NODEPDA(cnodeid); /* * Get the "top" vertex for this node's hardware * graph; it will carry the per-hub hub-specific * data, and act as the crosstalk provider master. * It's canonical path is probably something of the * form /hw/module/%M/slot/%d/node */ hubv = cnodeid_to_vertex(cnodeid); DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap); ASSERT(hubv != GRAPH_VERTEX_NONE); /* * Read mfg info on this hub */ /* * If nothing connected to this hub's xtalk port, we're done. */ early_probe_for_widget(hubv, &hwid); if (hwid.part_num == XWIDGET_PART_NUM_NONE) { #ifdef PROBE_TEST if ((cnodeid == 1) || (cnodeid == 2)) { int index; for (index = 0; index < 600; index++) DBG("Interfering with device probing!!!\n"); } #endif /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); return; /* NOTREACHED */ } /* * attach our hub_provider information to hubv, * so we can use it as a crosstalk provider "master" * vertex. */ xtalk_provider_register(hubv, &hub_provider); xtalk_provider_startup(hubv); /* * Create a vertex to represent the crosstalk bus * attached to this hub, and a vertex to be used * as the connect point for whatever is out there * on the other side of our crosstalk connection. * * Crosstalk Switch drivers "climb up" from their * connection point to try and take over the switch * point. * * Of course, the edges and verticies may already * exist, in which case our net effect is just to * associate the "xtalk_" driver with the connection * point for the device. */ (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv); DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv); ASSERT(switchv != GRAPH_VERTEX_NONE); (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO); DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n"); /* * We need to find the widget id and update the basew_id field * accordingly. In particular, SN00 has direct connected bridge, * and hence widget id is Not 0. */ widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; if (widget_partnum == BRIDGE_WIDGET_PART_NUM || widget_partnum == XBRIDGE_WIDGET_PART_NUM){ npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum); } else if ((widget_partnum == XBOW_WIDGET_PART_NUM) || (widget_partnum == XXBOW_WIDGET_PART_NUM) || (widget_partnum == PXBOW_WIDGET_PART_NUM) ) { /* * Xbow control register does not have the widget ID field. * So, hard code the widget ID to be zero. */ DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum); npdap->basew_id = 0; } else { npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv); /*NOTREACHED*/ } { char widname[10]; sprintf(widname, "%x", npdap->basew_id); (void)hwgraph_path_add(switchv, widname, &widgetv); DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv); ASSERT(widgetv != GRAPH_VERTEX_NONE); } nodepda->basew_xc = widgetv; is_xswitch = xwidget_hwid_is_xswitch(&hwid); /* * Try to become the master of the widget. If this is an xswitch * with multiple hubs connected, only one will succeed. Mastership * of an xswitch is used only when touching registers on that xswitch. * The slave xwidgets connected to the xswitch can be owned by various * masters. */ if (device_master_set(widgetv, hubv) == 0) { /* Only one hub (thread) per Crosstalk device or switch makes * it to here. */ /* * Initialize whatever xwidget is hanging off our hub. * Whatever it is, it's accessible through widgetnum 0. */ hubinfo_get(hubv, &hubinfo); (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid); if (!is_xswitch) { /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ io_init_done(cnodeid,c); /* NOTREACHED */ } /* * Special handling for Crosstalk Switches (e.g. xbow). * We need to do things in roughly the following order: * 1) Initialize xswitch hardware (done above) * 2) Determine which hubs are available to be widget masters * 3) Discover which links are active from the xswitch * 4) Assign xwidgets hanging off the xswitch to hubs * 5) Initialize all xwidgets on the xswitch */ DBG("call volunteer_for_widgets\n"); volunteer_for_widgets(switchv, hubv); /* If there's someone else on this crossbow, recognize him */ if (npdap->xbow_peer != INVALID_NASID) { nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer)); peer_sema = &peer_npdap->xbow_sema; DBG("call volunteer_for_widgets again\n"); volunteer_for_widgets(switchv, peer_npdap->node_vertex); } assign_widgets_to_volunteers(switchv, hubv); /* Signal that we're done */ if (peer_sema) { up(peer_sema); } } else { /* Wait 'til master is done assigning widgets. */ down(&npdap->xbow_sema); } #ifdef PROBE_TEST if ((cnodeid == 1) || (cnodeid == 2)) { int index; for (index = 0; index < 500; index++) DBG("Interfering with device probing!!!\n"); } #endif /* Now both nodes can safely inititialize widgets */ io_init_xswitch_widgets(switchv, cnodeid); io_link_xswitch_widgets(switchv, cnodeid); /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ io_init_done(cnodeid,c); DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid); }
void __init pcibr_setup(cnodeid_t nid) { int i, start, num; unsigned long masterwid; bridge_t *bridge; volatile u64 hubreg; nasid_t nasid, masternasid; xwidget_part_num_t partnum; widgetreg_t widget_id; static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; /* * If the master is doing this for headless node, nothing to do. * This is because currently we require at least one of the hubs * (master hub) connected to the xbow to have at least one enabled * cpu to receive intrs. Else we need an array bus_to_intrnasid[] * that bridge_startup() needs to use to target intrs. All dma is * routed thru the widget of the master hub. The master hub wid * is selectable by WIDGET_A below. */ if (nid != get_compact_nodeid()) return; /* * find what's on our local node */ spin_lock(&pcibr_setup_lock); start = num_bridges; /* Remember where we start from */ nasid = COMPACT_TO_NASID_NODEID(nid); hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (hubreg & IIO_LLP_CSR_IS_UP) { /* link is up */ widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", smp_processor_id(), nasid, partnum); if (partnum == BRIDGE_WIDGET_PART_NUM) { /* * found direct connected bridge so must be Origin200 */ printk("...is bridge\n"); num_bridges = 1; bus_to_wid[0] = 0x8; bus_to_nid[0] = 0; masterwid = 0xa; bus_to_baddr[0] = 0xa100000000000000UL; } else if (partnum == XBOW_WIDGET_PART_NUM) { lboard_t *brd; klxbow_t *xbow_p; /* * found xbow, so may have multiple bridges * need to probe xbow */ printk("...is xbow\n"); if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8)) == NULL) printk("argh\n"); else printk("brd = 0x%lx\n", (unsigned long) brd); if ((xbow_p = (klxbow_t *) find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) printk("argh\n"); else { /* * Okay, here's a xbow. Lets arbitrate and find * out if we should initialize it. Set enabled * hub connected at highest or lowest widget as * master. */ #ifdef WIDGET_A i = HUB_WIDGET_ID_MAX + 1; do { i--; } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #else i = HUB_WIDGET_ID_MIN - 1; do { i++; } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #endif masterwid = i; masternasid = XBOW_PORT_NASID(xbow_p, i); if (nasid == masternasid) for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) continue; if (XBOW_PORT_TYPE_IO(xbow_p, i)) { widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); if (partnum == BRIDGE_WIDGET_PART_NUM) { printk("widget 0x%x is a bridge\n", i); bus_to_wid[num_bridges] = i; bus_to_nid[num_bridges] = nasid; bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ num_bridges++; } } } } } else if (partnum == XXBOW_WIDGET_PART_NUM) { /* * found xbridge, assume ibrick for now */ printk("...is xbridge\n"); bus_to_wid[0] = 0xb; bus_to_wid[1] = 0xe; bus_to_wid[2] = 0xf; bus_to_nid[0] = 0; bus_to_nid[1] = 0; bus_to_nid[2] = 0; bus_to_baddr[0] = 0xa100000000000000UL; bus_to_baddr[1] = 0xa100000000000000UL; bus_to_baddr[2] = 0xa100000000000000UL; masterwid = 0xa; num_bridges = 3; } } num = num_bridges - start; spin_unlock(&pcibr_setup_lock); /* * set bridge registers */ for (i = start; i < (start + num); i++) { DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n", i, i, bus_to_wid[i], i, bus_to_nid[i]); bus_to_cpu[i] = smp_processor_id(); /* * point to this bridge */ bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]); /* * Clear all pending interrupts. */ bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); /* * Until otherwise set up, assume all interrupts are from slot 0 */ bridge->b_int_device = (u32) 0x0; /* * swap pio's to pci mem and io space (big windows) */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP; bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. */ bridge->b_int_mode = 0x0; /* Don't clear ints */ bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } }