📄 pcibr_dvr.c
字号:
picreg_t int_enable_64; unsigned rrb_fixed = 0; int spl_level;#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); extern unsigned char Is_pic_on_this_nasid[512]; async_attach_t aa = NULL; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum)); aa = async_attach_get_info(xconn_vhdl); 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, &pcibr_fops, NULL); 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; BZERO(pcibr_soft, 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; if (is_xbridge(bridge)) { pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_XBRIDGE; } else if (is_pic(bridge)) { pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC; } else { pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_BRIDGE; } 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); /* set whether it is a PIC or not */ Is_pic_on_this_nasid[nasid] = (IS_PIC_SOFT(pcibr_soft)) ? 1 : 0; 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: pcibr_soft->bs_first_slot = 0; pcibr_soft->bs_last_slot = 1; pcibr_soft->bs_last_reset = 1; break; case MODULE_PEBRICK: 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: * * 0 1 2 3 4 5 6 7 slot# * * x scsi x x ioc3 usb x x O300 Ibrick * * x == never occupied * E == external (add-in) slot * */ pcibr_soft->bs_first_slot = 1; /* Ibrick first slot == 1 */ if (pcibr_soft->bs_xid == 0xe) { pcibr_soft->bs_last_slot = 2; pcibr_soft->bs_last_reset = 2; } else { pcibr_soft->bs_last_slot = 6; } break; default: break; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: %cbrick, slots %d-%d\n", MODULE_GET_BTCHAR(pcibr_soft->bs_moduleid), pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot)); } /* * Initialize bridge and bus locks */ spin_lock_init(&pcibr_soft->bs_lock);#ifdef PIC_LATER mrinit(pcibr_soft->bs_bus_lock, "bus_lock");#endif /* * If we have one, process the hints structure. */ if (pcibr_hints) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, pcibr_vhdl, "pcibr_attach2: pcibr_hints=0x%x\n", pcibr_hints)); rrb_fixed = pcibr_hints->ph_rrb_fixed; pcibr_soft->bs_rrb_fixed = rrb_fixed; if (pcibr_hints->ph_intr_bits) { pcibr_soft->bs_intr_bits = pcibr_hints->ph_intr_bits; } for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { int hslot = pcibr_hints->ph_host_slot[slot] - 1; if (hslot < 0) { pcibr_soft->bs_slot[slot].host_slot = slot; } else { pcibr_soft->bs_slot[slot].has_host = 1; pcibr_soft->bs_slot[slot].host_slot = hslot; } } } /* * Set-up initial values for state fields */ for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE; pcibr_soft->bs_slot[slot].bss_devio.bssd_ref_cnt = 0; pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET; pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET; pcibr_soft->bs_slot[slot].bss_ext_ates_active = ATOMIC_INIT(0); pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] = -1; } for (ibit = 0; ibit < 8; ++ibit) { pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_soft = pcibr_soft; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_list = NULL; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_stat = &(bridge->b_int_status); pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_ibit = ibit; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_hdlrcnt = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_shared = 0; pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_connected = 0; } /* * connect up our error handler. PIC has 2 busses (thus resulting in 2 * pcibr_soft structs under 1 widget), so only register a xwidget error * handler for PIC's bus0. NOTE: for PIC pcibr_error_handler_wrapper() * is a wrapper routine we register that will call the real error handler * pcibr_error_handler() with the correct pcibr_soft struct. */ if (IS_PIC_SOFT(pcibr_soft)) { if (busnum == 0) { xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft); } } else { xwidget_error_register(xconn_vhdl, pcibr_error_handler, pcibr_soft); } /* * Initialize various Bridge registers. */ /* * On pre-Rev.D bridges, set the PCI_RETRY_CNT * to zero to avoid dropping stores. (#475347) */ if (rev < BRIDGE_PART_REV_D) bridge->b_bus_timeout &= ~BRIDGE_BUS_PCI_RETRY_MASK; /* * Clear all pending interrupts. */ bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); /* Initialize some PIC specific registers. */ if (IS_PIC_SOFT(pcibr_soft)) { picreg_t pic_ctrl_reg = bridge->p_wid_control_64; /* Bridges Requester ID: bus = busnum, dev = 0, func = 0 */ pic_ctrl_reg &= ~PIC_CTRL_BUS_NUM_MASK; pic_ctrl_reg |= PIC_CTRL_BUS_NUM(busnum); pic_ctrl_reg &= ~PIC_CTRL_DEV_NUM_MASK; pic_ctrl_reg &= ~PIC_CTRL_FUN_NUM_MASK; pic_ctrl_reg &= ~PIC_CTRL_NO_SNOOP; pic_ctrl_reg &= ~PIC_CTRL_RELAX_ORDER; /* enable parity checking on PICs internal RAM */ pic_ctrl_reg |= PIC_CTRL_PAR_EN_RESP; pic_ctrl_reg |= PIC_CTRL_PAR_EN_ATE; /* PIC BRINGUP WAR (PV# 862253): dont enable write request * parity checking. */ if (!PCIBR_WAR_ENABLED(PV862253, pcibr_soft)) { pic_ctrl_reg |= PIC_CTRL_PAR_EN_REQ; } bridge->p_wid_control_64 = pic_ctrl_reg; } /* * Until otherwise set up, * assume all interrupts are * from slot 7(Bridge/Xbridge) or 3(PIC). * XXX. Not sure why we're doing this, made change for PIC * just to avoid setting reserved bits. */ if (IS_PIC_SOFT(pcibr_soft)) bridge->b_int_device = (uint32_t) 0x006db6db; else bridge->b_int_device = (uint32_t) 0xffffffff; { bridgereg_t dirmap; paddr_t paddr; iopaddr_t xbase; xwidgetnum_t xport; iopaddr_t offset; int num_entries = 0; int entry; cnodeid_t cnodeid; nasid_t nasid;#ifdef PIC_LATER char *node_val; devfs_handle_t node_vhdl; char vname[MAXDEVNAME];#endif /* Set the Bridge's 32-bit PCI to XTalk * Direct Map register to the most useful * value we can determine. Note that we * must use a single xid for all of: * direct-mapped 32-bit DMA accesses * direct-mapped 64-bit DMA accesses * DMA accesses through the PMU * interrupts * This is the only way to guarantee that * completion interrupts will reach a CPU * after all DMA data has reached memory. * (Of course, there may be a few special * drivers/controlers that explicitly manage * this ordering problem.) */ cnodeid = 0; /* default node id */ /* * Determine the base address node id to be used for all 32-bit * Direct Mapping I/O. The default is node 0, but this can be changed * via a DEVICE_ADMIN directive and the PCIBUS_DMATRANS_NODE * attribute in the irix.sm config file. A device driver can obtain * this node value via a call to pcibr_get_dmatrans_node(). */#ifdef PIC_LATER// This probably needs to be addressed - pfg node_val = device_admin_info_get(pcibr_vhdl, ADMIN_LBL_DMATRANS_NODE); if (node_val != NULL) { node_vhdl = hwgraph_path_to_vertex(node_val); if (node_vhdl != GRAPH_VERTEX_NONE) { cnodeid = nodevertex_to_cnodeid(node_vhdl); } if ((node_vhdl == GRAPH_VERTEX_NONE) || (cnodeid == CNODEID_NONE)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -