📄 pcibr_dvr.c
字号:
pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif pcibr_info->f_att_det_error = error; pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT; } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT; } #ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif}/* * pcibr_driver_unreg_callback * CDL will call this function for each device found in the PCI * registry that matches the vendor/device IDs supported by * the driver being unregistered. The device's connection vertex * and the driver's detach function return status enable the * slot's device status to be set. */voidpcibr_driver_unreg_callback(vertex_hdl_t pconn_vhdl, int key1, int key2, int error){ pciio_info_t pciio_info; pcibr_info_t pcibr_info; vertex_hdl_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; /* Do not set slot status for vendor/device ID wildcard drivers */ if ((key1 == -1) || (key2 == -1)) return; pciio_info = pciio_info_get(pconn_vhdl); pcibr_info = pcibr_info_get(pconn_vhdl); pcibr_vhdl = pciio_info_master_get(pciio_info); slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif pcibr_info->f_att_det_error = error; pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT; } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT; }#ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif}/* * build a convenience link path in the * form of ".../<iobrick>/bus/<busnum>" * * returns 1 on success, 0 otherwise * * depends on hwgraph separator == '/' */intpcibr_bus_cnvlink(vertex_hdl_t f_c){ char dst[MAXDEVNAME]; char *dp = dst; char *cp, *xp; int widgetnum; char pcibus[8]; vertex_hdl_t nvtx, svtx; int rv; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n")); if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME)) { return 0; } /* dst example == /hw/module/001c02/Pbrick/xtalk/8/pci/direct */ /* find the widget number */ xp = strstr(dst, "/"EDGE_LBL_XTALK"/"); if (xp == NULL) { return 0; } widgetnum = simple_strtoul(xp+7, NULL, 0); if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) { return 0; } /* remove "/pci/direct" from path */ cp = strstr(dst, "/" EDGE_LBL_PCI "/" EDGE_LBL_DIRECT); if (cp == NULL) { return 0; } *cp = (char)NULL; /* get the vertex for the widget */ if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx)) { return 0; } *xp = (char)NULL; /* remove "/xtalk/..." from path */ /* dst example now == /hw/module/001c02/Pbrick */ /* get the bus number */ strcat(dst, "/"); strcat(dst, EDGE_LBL_BUS); sprintf(pcibus, "%d", p_busnum[widgetnum]); /* link to bus to widget */ rv = hwgraph_path_add(NULL, dp, &nvtx); if (GRAPH_SUCCESS == rv) rv = hwgraph_edge_add(nvtx, svtx, pcibus); return (rv == GRAPH_SUCCESS);}/* * pcibr_attach: called every time the crosstalk * infrastructure is asked to initialize a widget * that matches the part number we handed to the * registration routine above. *//*ARGSUSED */intpcibr_attach(vertex_hdl_t xconn_vhdl){ /* REFERENCED */ graph_error_t rc; vertex_hdl_t pcibr_vhdl; bridge_t *bridge; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, xconn_vhdl, "pcibr_attach\n")); bridge = (bridge_t *) xtalk_piotrans_addr(xconn_vhdl, NULL, 0, sizeof(bridge_t), 0); /* * Create the vertex for the PCI bus, which we * will also use to hold the pcibr_soft and * which will be the "master" vertex for all the * pciio connection points we will hang off it. * This needs to happen before we call nic_bridge_vertex_info * as we are some of the *_vmc functions need access to the edges. * * Opening this vertex will provide access to * the Bridge registers themselves. */ rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl); ASSERT(rc == GRAPH_SUCCESS); pciio_provider_register(pcibr_vhdl, &pcibr_provider); pciio_provider_startup(pcibr_vhdl); return pcibr_attach2(xconn_vhdl, bridge, pcibr_vhdl, 0, NULL);}/*ARGSUSED */intpcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge, vertex_hdl_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp){ /* REFERENCED */ vertex_hdl_t ctlr_vhdl; bridgereg_t id; int rev; pcibr_soft_t pcibr_soft; pcibr_info_t pcibr_info; xwidget_info_t info; xtalk_intr_t xtalk_intr; int slot; int ibit; vertex_hdl_t noslot_conn; char devnm[MAXDEVNAME], *s; pcibr_hints_t pcibr_hints; uint64_t int_enable; picreg_t int_enable_64; unsigned rrb_fixed = 0;#if PCI_FBBE int fast_back_to_back_enable;#endif nasid_t nasid; int iobrick_type_get_nasid(nasid_t nasid); int iobrick_module_get_nasid(nasid_t nasid); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum)); ctlr_vhdl = NULL; ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER, 0, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, (struct file_operations *)&pcibr_fops, (void *)pcibr_vhdl); ASSERT(ctlr_vhdl != NULL); /* * Get the hint structure; if some NIC callback * marked this vertex as "hands-off" then we * just return here, before doing anything else. */ pcibr_hints = pcibr_hints_get(xconn_vhdl, 0); if (pcibr_hints && pcibr_hints->ph_hands_off) return -1; /* generic operations disabled */ id = bridge->b_wid_id; rev = XWIDGET_PART_REV_NUM(id); hwgraph_info_add_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, (arbitrary_info_t) rev); /* * allocate soft state structure, fill in some * fields, and hook it up to our vertex. */ NEW(pcibr_soft); if (ret_softp) *ret_softp = pcibr_soft; memset(pcibr_soft, 0, sizeof *pcibr_soft); pcibr_soft_set(pcibr_vhdl, pcibr_soft); pcibr_soft->bs_conn = xconn_vhdl; pcibr_soft->bs_vhdl = pcibr_vhdl; pcibr_soft->bs_base = bridge; pcibr_soft->bs_rev_num = rev; pcibr_soft->bs_intr_bits = (pcibr_intr_bits_f *)pcibr_intr_bits; pcibr_soft->bs_min_slot = 0; /* lowest possible slot# */ pcibr_soft->bs_max_slot = 7; /* highest possible slot# */ pcibr_soft->bs_busnum = busnum; pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC; switch(pcibr_soft->bs_bridge_type) { case PCIBR_BRIDGETYPE_BRIDGE: pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES; pcibr_soft->bs_bridge_mode = 0; /* speed is not available in bridge */ break; case PCIBR_BRIDGETYPE_PIC: pcibr_soft->bs_min_slot = 0; pcibr_soft->bs_max_slot = 3; pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES; pcibr_soft->bs_bridge_mode = (((bridge->p_wid_stat_64 & PIC_STAT_PCIX_SPEED) >> 33) | ((bridge->p_wid_stat_64 & PIC_STAT_PCIX_ACTIVE) >> 33)); /* We have to clear PIC's write request buffer to avoid parity * errors. See PV#854845. */ { int i; for (i=0; i < PIC_WR_REQ_BUFSIZE; i++) { bridge->p_wr_req_lower[i] = 0; bridge->p_wr_req_upper[i] = 0; bridge->p_wr_req_parity[i] = 0; } } break; case PCIBR_BRIDGETYPE_XBRIDGE: pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES; pcibr_soft->bs_bridge_mode = ((bridge->b_wid_control & BRIDGE_CTRL_PCI_SPEED) >> 3); break; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: pcibr_soft=0x%x, mode=0x%x\n", pcibr_soft, pcibr_soft->bs_bridge_mode)); pcibr_soft->bsi_err_intr = 0; /* Bridges up through REV C * are unable to set the direct * byteswappers to BYTE_STREAM. */ if (pcibr_soft->bs_rev_num <= BRIDGE_PART_REV_C) { pcibr_soft->bs_pio_end_io = PCIIO_WORD_VALUES; pcibr_soft->bs_pio_end_mem = PCIIO_WORD_VALUES; }#if PCIBR_SOFT_LIST /* * link all the pcibr_soft structs */ { pcibr_list_p self; NEW(self); self->bl_soft = pcibr_soft; self->bl_vhdl = pcibr_vhdl; self->bl_next = pcibr_list; pcibr_list = self; }#endif /* PCIBR_SOFT_LIST */ /* * get the name of this bridge vertex and keep the info. Use this * only where it is really needed now: like error interrupts. */ s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME); pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL); strcpy(pcibr_soft->bs_name, s); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: %s ASIC: rev %s (code=0x%x)\n", IS_XBRIDGE_SOFT(pcibr_soft) ? "XBridge" : IS_PIC_SOFT(pcibr_soft) ? "PIC" : "Bridge", (rev == BRIDGE_PART_REV_A) ? "A" : (rev == BRIDGE_PART_REV_B) ? "B" : (rev == BRIDGE_PART_REV_C) ? "C" : (rev == BRIDGE_PART_REV_D) ? "D" : (rev == XBRIDGE_PART_REV_A) ? "A" : (rev == XBRIDGE_PART_REV_B) ? "B" : (IS_PIC_PART_REV_A(rev)) ? "A" : "unknown", rev, pcibr_soft->bs_name)); info = xwidget_info_get(xconn_vhdl); pcibr_soft->bs_xid = xwidget_info_id_get(info); pcibr_soft->bs_master = xwidget_info_master_get(info); pcibr_soft->bs_mxid = xwidget_info_masterid_get(info); pcibr_soft->bs_first_slot = pcibr_soft->bs_min_slot; pcibr_soft->bs_last_slot = pcibr_soft->bs_max_slot; /* * Bridge can only reset slots 0, 1, 2, and 3. Ibrick internal * slots 4, 5, 6, and 7 must be reset as a group, so do not * reset them. */ pcibr_soft->bs_last_reset = 3; nasid = NASID_GET(bridge); if ((pcibr_soft->bs_bricktype = iobrick_type_get_nasid(nasid)) < 0) printk(KERN_WARNING "0x%p: Unknown bricktype : 0x%x\n", (void *)xconn_vhdl, (unsigned int)pcibr_soft->bs_bricktype); pcibr_soft->bs_moduleid = iobrick_module_get_nasid(nasid); if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { case MODULE_PXBRICK: case MODULE_IXBRICK: case MODULE_OPUSBRICK: pcibr_soft->bs_first_slot = 0; pcibr_soft->bs_last_slot = 1; pcibr_soft->bs_last_reset = 1; /* If Bus 1 has IO9 then there are 4 devices in that bus. Note * we figure this out from klconfig since the kernel has yet to * probe */ if (pcibr_widget_to_bus(pcibr_vhdl) == 1) { lboard_t *brd = (lboard_t *)KL_CONFIG_INFO(nasid); while (brd) { if (brd->brd_flags & LOCAL_MASTER_IO6) { pcibr_soft->bs_last_slot = 3; pcibr_soft->bs_last_reset = 3; } brd = KLCF_NEXT(brd); } } break; case MODULE_PBRICK: pcibr_soft->bs_first_slot = 1; pcibr_soft->bs_last_slot = 2; pcibr_soft->bs_last_reset = 2; break; case MODULE_IBRICK: /* * Here's the current baseio layout for SN1 style systems: *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -