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

📄 pcibr_dvr.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *    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(devfs_handle_t xconn_vhdl){    /* REFERENCED */    graph_error_t           rc;    devfs_handle_t            pcibr_vhdl;    devfs_handle_t            ctlr_vhdl;    bridge_t               *bridge = NULL;    bridgereg_t             id;    int                     rev;    pcibr_soft_t            pcibr_soft;    pcibr_info_t            pcibr_info;    xwidget_info_t          info;    xtalk_intr_t            xtalk_intr;    device_desc_t           dev_desc = (device_desc_t)0;    int                     slot;    int                     ibit;    devfs_handle_t            noslot_conn;    char                    devnm[MAXDEVNAME], *s;    pcibr_hints_t           pcibr_hints;    bridgereg_t             b_int_enable;    unsigned                rrb_fixed = 0;    iopaddr_t               pci_io_fb, pci_io_fl;    iopaddr_t               pci_lo_fb, pci_lo_fl;    iopaddr_t               pci_hi_fb, pci_hi_fl;    int                     spl_level;#ifdef LATER    char		    *nicinfo = (char *)0;#endif#if PCI_FBBE    int                     fast_back_to_back_enable;#endif    l1sc_t		    *scp;    nasid_t		    nasid;    async_attach_t          aa = NULL;    aa = async_attach_get_info(xconn_vhdl);#if DEBUG && ATTACH_DEBUG    printk("pcibr_attach: xconn_vhdl=  %p\n", xconn_vhdl);    {	int pos;	char dname[256];	pos = devfs_generate_path(xconn_vhdl, dname, 256);	printk("%s : path= %s \n", __FUNCTION__, &dname[pos]);    }#endif    /* Setup the PRB for the bridge in CONVEYOR BELT     * mode. PRBs are setup in default FIRE-AND-FORGET     * mode during the initialization.     */    hub_device_flags_set(xconn_vhdl, HUB_PIO_CONVEYOR);    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);    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);    /*     * decode the nic, and hang its stuff off our     * connection point where other drivers can get     * at it.     */#ifdef LATER    nicinfo = BRIDGE_VERTEX_MFG_INFO(xconn_vhdl, (nic_data_t) & bridge->b_nic);#endif    /*     * 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);    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;    if (is_xbridge(bridge)) {	pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;	pcibr_soft->bs_xbridge = 1;    } else {	pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES;	pcibr_soft->bs_xbridge = 0;    }    nasid = NASID_GET(bridge);    scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc;    pcibr_soft->bs_l1sc = scp;    pcibr_soft->bs_moduleid = iobrick_module_get(scp);    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    {	pcibr_list_p            self;	NEW(self);	self->bl_soft = pcibr_soft;	self->bl_vhdl = pcibr_vhdl;	self->bl_next = pcibr_list;	self->bl_next = swap_ptr((void **) &pcibr_list, (void *)self);    }#endif    /*     * 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);#if SHOW_REVS || DEBUG#if !DEBUG    if (kdebug)#endif	printk("%sBridge ASIC: rev %s (code=0x%x) at %s\n",		is_xbridge(bridge) ? "X" : "",		(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" :		"unknown",		rev, pcibr_soft->bs_name);#endif    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);    /*     * Init bridge lock.     */    spin_lock_init(&pcibr_soft->bs_lock);    /*     * If we have one, process the hints structure.     */    if (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 = 0; slot < 8; ++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 = 0; slot < 8; ++slot) {	pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE;	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);    }    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_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;    }    /*     * 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);    /*     * Until otherwise set up,     * assume all interrupts are     * from slot 7.     */    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;	/* 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, _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	bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE;#elif IOPGSIZE == 16384	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(bridge))		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 PCIBR_ATE_DEBUG	printk("pcibr_attach: %d INTERNAL ATEs\n", pcibr_soft->bs_int_ate_size);#endif	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);#if PCIBR_ATE_DEBUG	    printk("pcibr_attach: %d EXTERNAL ATEs\n",		    num_entries - pcibr_soft->bs_int_ate_size);#endif	}    }    {	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

⌨️ 快捷键说明

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