📄 pci_bus_cvlink.c
字号:
device_dev->resource[PCI_ROM_RESOURCE].start; if (size) { device_dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET; device_dev->resource[PCI_ROM_RESOURCE].end = device_dev->resource[PCI_ROM_RESOURCE].start + size; }#endif /* * Update the Command Word on the Card. */ cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ /* bit gets dropped .. no harm */ pci_write_config_word(device_dev, PCI_COMMAND, cmd); pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); if (device_dev->vendor == PCI_VENDOR_ID_SGI && device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) { lines = 1; } device_sysdata = (struct sn_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; irq = irq + (cpuid << 8); pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0); device_dev->irq = irq;#ifdef ajmtestintr { int slot = PCI_SLOT(device_dev->devfn); static int timer_set = 0; pcibr_intr_t pcibr_intr = (pcibr_intr_t)intr_handle; pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; extern void intr_test_handle_intr(int, void*, struct pt_regs *); if (!timer_set) { intr_test_set_timer(); timer_set = 1; } intr_test_register_irq(irq, pcibr_soft, slot); request_irq(irq, intr_test_handle_intr,0,NULL, NULL); }#endif } for (cnode = 0; cnode < numnodes; cnode++) { if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) io_sh_swapper((cnodeid_to_nasid(cnode)), 1); }}/* * linux_bus_cvlink() Creates a link between the Linux PCI Bus number * to the actual hardware component that it represents: * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci */voidlinux_bus_cvlink(void){ char name[8]; int index; for (index=0; index < MAX_PCI_XWIDGET; index++) { if (!busnum_to_pcibr_vhdl[index]) continue; sprintf(name, "%d", index); (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], name); }}/* * 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){ devfs_handle_t master_node_vertex = NULL; devfs_handle_t xwidget = NULL; devfs_handle_t pci_bus = NULL; hubinfo_t hubinfo = NULL; xwidgetnum_t widgetnum; char pathname[128]; graph_error_t rv; int bus; /* * Loop throught this vertex and get the Xwidgets .. */ /* PCI devices */ for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {#if 0 { int pos; char dname[256]; pos = devfs_generate_path(xtalk, dname, 256); printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); }#endif 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) { continue;} } sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); pci_bus = NULL; if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) if (!pci_bus) { continue;} /* * Assign the correct bus number and also the nasid of this * pci Xwidget. * * Should not be any race here ... */ num_bridges++; 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("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget); } hubinfo_get(master_node_vertex, &hubinfo); if (!hubinfo) { printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex); return(1); } else { busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; } /* * Pre assign DMA maps needed for 32 Bits Page Map DMA. */ busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc( sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, 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, (void *)xwidget); memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); } /* * PCIX devices * We number busses differently for PCI-X devices. * We start from Lowest Widget on up .. */ for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { /* Do both buses */ for ( bus = 0; bus < 2; bus++ ) { sprintf(pathname, "%d", widgetnum); xwidget = NULL; /* * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device */ rv = hwgraph_traverse(xtalk, pathname, &xwidget); if ( (rv != GRAPH_SUCCESS) ) { if (!xwidget) { continue; } } if ( bus == 0 ) sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); else sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); pci_bus = NULL; if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) if (!pci_bus) { continue; } /* * Assign the correct bus number and also the nasid of this * pci Xwidget. * * Should not be any race here ... */ num_bridges++; 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("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget); } hubinfo_get(master_node_vertex, &hubinfo); if (!hubinfo) { printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex); return(1); } else { busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; } /* * Pre assign DMA maps needed for 32 Bits Page Map DMA. */ busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc( sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, 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, (void *)xwidget); memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); } } return(0);}/* * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure * initialization has completed to set up the mappings between Xbridge * and logical pci bus numbers. We also set up the NASID for each of these * xbridges. * * Must be called before pci_init() is invoked. */intpci_bus_to_hcl_cvlink(void) { devfs_handle_t devfs_hdl = NULL; devfs_handle_t xtalk = NULL; int rv = 0; char name[256]; char tmp_name[256]; int master_iobrick; slabid_t master_slab; int i, ii; extern nasid_t master_baseio_nasid; extern nasid_t get_master_baseio_nasid(void); /* * Iterate throught each xtalk links in the system .. * /hw/module/001c01/slab/0/node/xtalk/ 8|9|10|11|12|13|14|15 * * /hw/module/001c01/slab/0/node/xtalk/15 -> /hw/module/001c01/slab/0/Ibrick/xtalk/15 * * What if it is not pci? */ devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module"); /* * 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_baseio_nasid = get_master_baseio_nasid(); master_iobrick = -1; master_slab = -1; if ( master_baseio_nasid >= 0 ) { /* Valid nasid, need the slab ID */ for (i = 0; i < nummodules; i++) { extern int iobrick_module_get_nasid(nasid_t); moduleid_t iobrick_id; nasid_t nasid = -1; int n = 0; for ( n = 0; n < modules[i]->nodecnt; n++ ) { nasid = cnodeid_to_nasid(modules[i]->nodes[n]); iobrick_id = iobrick_module_get_nasid(nasid); if (iobrick_id > 0) { /* Valid module id */ if ( master_baseio_nasid == nasid ) { master_iobrick = i; master_slab = geo_slab(modules[i]->geoid[n]); printk("pci_bus_to_hcl_cvlink: Found Master Base IO Brick type %d Master Base I/O nasid %d Master Cbrick Index %d Slab %d\n", MODULE_GET_BTYPE(iobrick_id), master_baseio_nasid, master_iobrick, master_slab); break; } } } if (master_slab >= 0) break; } } else { /* Not sure which nasid it is - call failed, so make a guess */ for (i = 0; i < nummodules; i++) { extern int iobrick_module_get_nasid(nasid_t); moduleid_t iobrick_id; nasid_t nasid = -1; int n = 0; for ( n = 0; n < modules[i]->nodecnt; n++ ) { nasid = cnodeid_to_nasid(modules[i]->nodes[n]); iobrick_id = iobrick_module_get_nasid(nasid); if (iobrick_id > 0) { /* Valid module id */ if ( (MODULE_GET_BTYPE(iobrick_id) == MODULE_IBRICK) || (MODULE_GET_BTYPE(iobrick_id) == MODULE_PXBRICK) || (MODULE_GET_BTYPE(iobrick_id) == MODULE_PBRICK) ) { master_iobrick = i; master_baseio_nasid = nasid; master_slab = geo_slab(modules[i]->geoid[n]); printk("pci_bus_to_hcl_cvlink: Found Master Base IO Brick type %d Master Cbrick Index %d Slab %d\n", MODULE_GET_BTYPE(iobrick_id), master_iobrick, master_slab); break; } } } if (master_iobrick >= 0) break; } } if (master_iobrick == -1) { panic("Unable to find the Master BaseIO PCI/PCIX Bus\n"); } /* * The master_iobrick gets bus 0 and 1. */ if (master_iobrick >= 0) { memset(name, 0, 256); memset(tmp_name, 0, 256); format_module_id(name, modules[master_iobrick]->id, MODULE_FORMAT_BRIEF); sprintf(tmp_name, "/slab/%d/node/xtalk", master_slab); strcat(name, tmp_name); 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++) { for ( ii = 0; ii < MAX_SLABS; ii++ ) { if ((i == master_iobrick) && (master_slab == ii)) continue; /* Did the master_iobrick/slab already. */ memset(name, 0, 256); memset(tmp_name, 0, 256); format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF); sprintf(tmp_name, "/slab/%d/node/xtalk", ii); strcat(name, tmp_name); xtalk = NULL; rv = hwgraph_edge_get(devfs_hdl, name, &xtalk); pci_bus_map_create(xtalk); } } /* * Create the Linux PCI bus number vertex link. */ (void)linux_bus_cvlink(); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -