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

📄 pcibr_dvr.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		cnodeid = 0;		vertex_to_name(pcibr_vhdl, vname, sizeof(vname));		printk(KERN_WARNING "Invalid hwgraph node path specified:\n"			"    DEVICE_ADMIN: %s %s=%s\n",			vname, ADMIN_LBL_DMATRANS_NODE, node_val);	    }	}#endif	/* PIC_LATER */	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, _PAGESZ, 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	 */	spl_level = splhi();#if IOPGSIZE == 4096        if (IS_PIC_SOFT(pcibr_soft)) {            bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE;        } else {            bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE;        }#elif IOPGSIZE == 16384        if (IS_PIC_SOFT(pcibr_soft)) {            bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE;        } else {            bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE;        }#else	<<<Unable to deal with IOPGSIZE >>>;#endif	bridge->b_wid_control;		/* inval addr bug war */	splx(spl_level);	/* 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_map = rmallocmap(pcibr_soft->bs_int_ate_size);	pcibr_ate_free(pcibr_soft, 0, pcibr_soft->bs_int_ate_size);	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_map = rmallocmap(num_entries);	    pcibr_ate_free(pcibr_soft, pcibr_soft->bs_int_ate_size,			   num_entries - pcibr_soft->bs_int_ate_size);	}	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);    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);#ifdef BUS_INT_WAR_NOT_YET    request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid,			((hub_intr_t)xtalk_intr)->i_bit),				(intr_func_t)pcibr_error_intr_handler, 0, "PCIBR error",					(intr_arg_t) pcibr_soft);#endif    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;    } else {	int_enable_32 = bridge->b_int_enable | (BRIDGE_ISR_ERRORS & 0xffffffff);	int_enable = ((uint64_t)int_enable_32 & 0xffffffff);    }#ifdef BUS_INT_WAR_NOT_YET    {	extern void sn_add_polled_interrupt(int irq, int interval);        sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid,				((hub_intr_t)xtalk_intr)->i_bit), 20000);    }#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);    }    if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_C) {	int_enable &= ~BRIDGE_ISR_BAD_XRESP_PKT;    }#endif				/* BRIDGE_ERROR_INTR_WAR */#ifdef QL_SCSI_CTRL_WAR			/* for IP30 only */    /* Really a QL rev A issue, but all newer hearts have newer QLs.     * Forces all IO6/MSCSI to be new.     */    if (heart_rev() == HEART_REV_A)	int_enable &= ~BRIDGE_IMR_PCI_MST_TIMEOUT;#endif#ifdef BRIDGE1_TIMEOUT_WAR    if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) {	/*	 * Turn off these interrupts.  They can't be trusted in bridge 1	 */	int_enable &= ~(BRIDGE_IMR_XREAD_REQ_TIMEOUT |			BRIDGE_IMR_UNEXP_RESP);    }#endif#ifdef BRIDGE_B_DATACORR_WAR    /* WAR panic for Rev B silent data corruption.     * PIOERR turned off here because there is a problem     * with not re-arming it in pcibr_error_intr_handler.     * We don't get LLP error interrupts if we don't     * re-arm PIOERR interrupts! Just disable them here     */    if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_B) {	int_enable |= BRIDGE_IMR_LLP_REC_CBERR;	int_enable &= ~BRIDGE_ISR_PCIBUS_PIOERR;	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,		    "Turning on LLP_REC_CBERR for Rev B Bridge.\n"));    }#endif    /* PIC BRINGUP WAR (PV# 856864 & 856865): allow the tnums that are     * locked out to be freed up sooner (by timing out) so that the     * read tnums are never completely used up.     */    if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) {        int_enable &= ~PIC_ISR_PCIX_REQ_TOUT;        int_enable &= ~BRIDGE_ISR_XREAD_REQ_TIMEOUT;        bridge->b_wid_req_timeout = 0x750;    }    /*     * PIC BRINGUP WAR (PV# 856866, 859504, 861476, 861478): Don't use     * RRB0, RRB8, RRB1, and RRB9.  Assign them to DEVICE[2|3]--VCHAN3     * so they are not used     */    if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) {        bridge->b_even_resp |= 0x000f000f;        bridge->b_odd_resp |= 0x000f000f;    }    if (IS_PIC_SOFT(pcibr_soft)) {        bridge->p_int_enable_64 = (picreg_t)int_enable;    } else {        bridge->b_int_enable = (bridgereg_t)int_enable;    }    bridge->b_int_mode = 0;		/* do not send "clear interrupt" packets */    bridge->b_wid_tflush;		/* wait until Bridge PIO complete */    /*     * Depending on the rev of bridge, disable certain features.     * Easiest way seems to be to force the PCIBR_NOwhatever     * flag to be on for all DMA calls, which overrides any     * PCIBR_whatever flag or even the setting of whatever     * from the PCIIO_DMA_class flags (or even from the other     * PCIBR flags, since NO overrides YES).     */    pcibr_soft->bs_dma_flags = 0;    /* PREFETCH:     * Always completely disabled for REV.A;     * at "pcibr_prefetch_enable_rev", anyone     * asking for PCIIO_PREFETCH gets it.     * Between these two points, you have to ask     * for PCIBR_PREFETCH, which promises that     * your driver knows about known Bridge WARs.     */    if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_B)	pcibr_soft->bs_dma_flags |= PCIBR_NOPREFETCH;    else if (pcibr_soft->bs_rev_num < 		(BRIDGE_WIDGET_PART_NUM << 4 | pcibr_prefetch_enable_rev))	pcibr_soft->bs_dma_flags |= PCIIO_NOPREFETCH;    /* WRITE_GATHER:     * Disabled up to but not including the     * rev number in pcibr_wg_enable_rev. There     * is no "WAR range" as with prefetch.     */    if (pcibr_soft->bs_rev_num < 		(BRIDGE_WIDGET_PART_NUM << 4 | pcibr_wg_enable_rev))	pcibr_soft->bs_dma_flags |= PCIBR_NOWRITE_GATHER;    /* PIC only supports 64-bit direct mapping in PCI-X mode.  Since     * all PCI-X devices that initiate memory transactions must be     * capable of generating 64-bit addressed, we force 64-bit DMAs.     */    if (IS_PCIX(pcibr_soft)) {	pcibr_soft->bs_dma_flags |= PCIIO_DMA_A64;    }    {    pciio_win_map_t         win_map_p;    iopaddr_t               prom_base_addr = pcibr_soft->bs_xid << 24;    int                     prom_base_size = 0x1000000;    iopaddr_t               prom_base_limit = prom_base_addr + prom_base_size;     /* Allocate resource maps based on bus page size; for I/O and memory     * space, free all pages except those in the base area and in the     * range set by the PROM.      *     * PROM creates BAR addresses in this format: 0x0ws00000 where w is     * the widget number and s is the device register offset for the slot.     */    win_map_p = &pcibr_soft->bs_io_win_map;    pciio_device_win_map_new(win_map_p,			     PCIBR_BUS_IO_MAX + 1,			     PCIBR_BUS_IO_PAGE);    pciio_device_win_populate(win_map_p,			      PCIBR_BUS_IO_BASE,			      prom_base_addr - PCIBR_BUS_IO_BASE);    pciio_device_win_populate(win_map_p,			      prom_base_limit,			      (PCIBR_BUS_IO_MAX + 1) - prom_base_limit);    win_map_p = &pcibr_soft->bs_swin_map;    pciio_device_win_map_new(win_map_p,			     PCIBR_BUS_SWIN_MAX + 1,			     PCIBR_BUS_SWIN_PAGE);    pciio_device_win_populate(win_map_p,			      PCIBR_BUS_SWIN_BASE,			      (PCIBR_BUS_SWIN_MAX + 1) - PCIBR_BUS_SWIN_PAGE);    win_map_p = &pcibr_soft->bs_mem_win_map;    pciio_device_win_map_new(win_map_p,			     PCIBR_BUS_MEM_MAX + 1,			     PCIBR_BUS_MEM_PAGE);    pciio_device_win_populate(win_map_p,			      PCIBR_BUS_MEM_BASE,			      prom_base_addr - PCIBR_BUS_MEM_BASE);    pciio_device_win_populate(win_map_p,			      prom_base_limit,			      (PCIBR_BUS_MEM_MAX + 1) - prom_base_limit);    }    /* build "no-slot" connection point     */    pcibr_info = pcibr_device_info_new	(pcibr_soft, PCIIO_SLOT_NONE, PCIIO_FUNC_NONE,	 PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE);    noslot_conn = pciio_device_info_register	(pcibr_vhdl, &pcibr_info->f_c);    /* Remember the no slot connection point info for tearing it     * down during detach.     */ 

⌨️ 快捷键说明

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