⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcibr_dvr.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	     *    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;        case MODULE_CGBRICK:            pcibr_soft->bs_first_slot = 0;            pcibr_soft->bs_last_slot = 0;            pcibr_soft->bs_last_reset = 0;            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);	}    }    /*     * 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;    {	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;	/* 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 */	nasid = COMPACT_TO_NASID_NODEID(cnodeid);	paddr = NODE_OFFSET(nasid) + 0;	/* currently, we just assume that if we ask	 * for a DMA mapping to "zero" the XIO	 * host will transmute this into a request	 * for the lowest hunk of memory.	 */	xbase = xtalk_dmatrans_addr(xconn_vhdl, 0,				    paddr, PAGE_SIZE, 0);	if (xbase != XIO_NOWHERE) {	    if (XIO_PACKED(xbase)) {		xport = XIO_PORT(xbase);		xbase = XIO_ADDR(xbase);	    } else		xport = pcibr_soft->bs_mxid;	    offset = xbase & ((1ull << BRIDGE_DIRMAP_OFF_ADDRSHFT) - 1ull);	    xbase >>= BRIDGE_DIRMAP_OFF_ADDRSHFT;	    dirmap = xport << BRIDGE_DIRMAP_W_ID_SHFT;	    if (xbase)		dirmap |= BRIDGE_DIRMAP_OFF & xbase;	    else if (offset >= (512 << 20))		dirmap |= BRIDGE_DIRMAP_ADD512;	    bridge->b_dir_map = dirmap;	}	/*	 * Set bridge's idea of page size according to the system's	 * idea of "IO page size".  TBD: The idea of IO page size	 * should really go away.	 */	/*	 * ensure that we write and read without any interruption.	 * The read following the write is required for the Bridge war	 */#if IOPGSIZE == 4096        if (IS_PIC_SOFT(pcibr_soft)) {            bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE;        } #elif IOPGSIZE == 16384        if (IS_PIC_SOFT(pcibr_soft)) {            bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE;        }#else	<<<Unable to deal with IOPGSIZE >>>;#endif	bridge->b_wid_control;		/* inval addr bug war */	/* Initialize internal mapping entries */	for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++) {	    bridge->b_int_ate_ram[entry].wr = 0;	}	/*	 * Determine if there's external mapping SSRAM on this	 * bridge.  Set up Bridge control register appropriately,	 * inititlize SSRAM, and set software up to manage RAM	 * entries as an allocatable resource.	 *	 * Currently, we just use the rm* routines to manage ATE	 * allocation.  We should probably replace this with a	 * Best Fit allocator.	 *	 * For now, if we have external SSRAM, avoid using	 * the internal ssram: we can't turn PREFETCH on	 * when we use the internal SSRAM; and besides,	 * this also guarantees that no allocation will	 * straddle the internal/external line, so we	 * can increment ATE write addresses rather than	 * recomparing against BRIDGE_INTERNAL_ATES every	 * time.	 */	if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft))		num_entries = 0;	else		num_entries = pcibr_init_ext_ate_ram(bridge);	/* we always have 128 ATEs (512 for Xbridge) inside the chip	 * even if disabled for debugging.	 */	pcibr_soft->bs_int_ate_resource.start = 0;	pcibr_soft->bs_int_ate_resource.end = pcibr_soft->bs_int_ate_size - 1;	if (num_entries > pcibr_soft->bs_int_ate_size) {#if PCIBR_ATE_NOTBOTH			/* for debug -- forces us to use external ates */	    printk("pcibr_attach: disabling internal ATEs.\n");	    pcibr_ate_alloc(pcibr_soft, pcibr_soft->bs_int_ate_size);#endif	   pcibr_soft->bs_ext_ate_resource.start = pcibr_soft->bs_int_ate_size;	   pcibr_soft->bs_ext_ate_resource.end = num_entries;	}        pcibr_soft->bs_allocated_ate_res = (void *) kmalloc(pcibr_soft->bs_int_ate_size * sizeof(unsigned long), GFP_KERNEL);	memset(pcibr_soft->bs_allocated_ate_res, 0x0, pcibr_soft->bs_int_ate_size * sizeof(unsigned long));	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_vhdl,		    "pcibr_attach2: %d ATEs, %d internal & %d external\n",		    num_entries ? num_entries : pcibr_soft->bs_int_ate_size,		    pcibr_soft->bs_int_ate_size,		    num_entries ? num_entries-pcibr_soft->bs_int_ate_size : 0));    }    {	bridgereg_t             dirmap;	iopaddr_t               xbase;	/*	 * now figure the *real* xtalk base address	 * that dirmap sends us to.	 */	dirmap = bridge->b_dir_map;	if (dirmap & BRIDGE_DIRMAP_OFF)	    xbase = (iopaddr_t)(dirmap & BRIDGE_DIRMAP_OFF)			<< BRIDGE_DIRMAP_OFF_ADDRSHFT;	else if (dirmap & BRIDGE_DIRMAP_ADD512)	    xbase = 512 << 20;	else	    xbase = 0;	pcibr_soft->bs_dir_xbase = xbase;	/* it is entirely possible that we may, at this	 * point, have our dirmap pointing somewhere	 * other than our "master" port.	 */	pcibr_soft->bs_dir_xport =	    (dirmap & BRIDGE_DIRMAP_W_ID) >> BRIDGE_DIRMAP_W_ID_SHFT;    }    /* pcibr sources an error interrupt;     * figure out where to send it.     *     * If any interrupts are enabled in bridge,     * then the prom set us up and our interrupt     * has already been reconnected in mlreset     * above.     *     * Need to set the D_INTR_ISERR flag     * in the dev_desc used for allocating the     * error interrupt, so our interrupt will     * be properly routed and prioritized.     *     * If our crosstalk provider wants to     * fix widget error interrupts to specific     * destinations, D_INTR_ISERR is how it     * knows to do this.     */    xtalk_intr = xtalk_intr_alloc(xconn_vhdl, (device_desc_t)0, pcibr_vhdl);	{		int irq = ((hub_intr_t)xtalk_intr)->i_bit;		int cpu = ((hub_intr_t)xtalk_intr)->i_cpuid;		intr_unreserve_level(cpu, irq);		((hub_intr_t)xtalk_intr)->i_bit = SGI_PCIBR_ERROR;	}    ASSERT(xtalk_intr != NULL);    pcibr_soft->bsi_err_intr = xtalk_intr;    /*     * On IP35 with XBridge, we do some extra checks in pcibr_setwidint     * in order to work around some addressing limitations.  In order     * for that fire wall to work properly, we need to make sure we     * start from a known clean state.     */    pcibr_clearwidint(bridge);    xtalk_intr_connect(xtalk_intr, (intr_func_t) pcibr_error_intr_handler,		(intr_arg_t) pcibr_soft, (xtalk_intr_setfunc_t)pcibr_setwidint, (void *)bridge);    request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, "PCIBR error",					(intr_arg_t) pcibr_soft);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_vhdl,		"pcibr_setwidint: b_wid_int_upper=0x%x, b_wid_int_lower=0x%x\n",		bridge->b_wid_int_upper, bridge->b_wid_int_lower));    /*     * now we can start handling error interrupts;     * enable all of them.     * NOTE: some PCI ints may already be enabled.     */    /* We read the INT_ENABLE register as a 64bit picreg_t for PIC and a     * 32bit bridgereg_t for BRIDGE, but always process the result as a     * 64bit value so the code can be "common" for both PIC and BRIDGE...     */    if (IS_PIC_SOFT(pcibr_soft)) {	int_enable_64 = bridge->p_int_enable_64 | BRIDGE_ISR_ERRORS;        int_enable = (uint64_t)int_enable_64;#ifdef PFG_TEST	int_enable = (uint64_t)0x7ffffeff7ffffeff;#endif    } #if BRIDGE_ERROR_INTR_WAR    if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) {	/*	 * We commonly get master timeouts when talking to ql.	 * We also see RESP_XTALK_ERROR and LLP_TX_RETRY interrupts.	 * Insure that these are all disabled for now.	 */	int_enable &= ~(BRIDGE_IMR_PCI_MST_TIMEOUT |			BRIDGE_ISR_RESP_XTLK_ERR |			BRIDGE_ISR_LLP_TX_RETRY);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -