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

📄 pcibr.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#if PCIBR_RRB_DEBUG	printk("pcibr_rrb_alloc: slot %d set to %d+%d; %d+%d free\n",		pciio_slot, final_vchan0, final_vchan1,		pcibr_soft->bs_rrb_avail[0],		pcibr_soft->bs_rrb_avail[1]);	for (pciio_slot = 0; pciio_slot < 8; ++pciio_slot)	    printk("\t%d+%d+%d",		    0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot],		    0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL],		    pcibr_soft->bs_rrb_res[pciio_slot]);	printk("\n");#endif	error = 0;    }    pcibr_unlock(pcibr_soft, s);    return error;}/* * Device driver interface to check the current state * of the RRB allocations. * *   pconn_vhdl is your PCI connection point (specifies which *      PCI bus and which slot). * *   count_vchan0 points to where to return the number of RRBs *      assigned to the primary DMA channel, used by all DMA *      that does not explicitly ask for the alternate virtual *      channel. * *   count_vchan1 points to where to return the number of RRBs *      assigned to the secondary DMA channel, used when *      PCIBR_VCHAN1 and PCIIO_DMA_A64 are specified. * *   count_reserved points to where to return the number of RRBs *      that have been automatically reserved for your device at *      startup, but which have not been assigned to a *      channel. RRBs must be assigned to a channel to be used; *      this can be done either with an explicit pcibr_rrb_alloc *      call, or automatically by the infrastructure when a DMA *      translation is constructed. Any call to pcibr_rrb_alloc *      will release any unassigned reserved RRBs back to the *      free pool. * *   count_pool points to where to return the number of RRBs *      that are currently unassigned and unreserved. This *      number can (and will) change as other drivers make calls *      to pcibr_rrb_alloc, or automatically allocate RRBs for *      DMA beyond their initial reservation. * * NULL may be passed for any of the return value pointers * the caller is not interested in. * * The return value is "0" if all went well, or "-1" if * there is a problem. Additionally, if the wrong vertex * is passed in, one of the subsidiary support functions * could panic with a "bad pciio fingerprint." */intpcibr_rrb_check(devfs_handle_t pconn_vhdl,		int *count_vchan0,		int *count_vchan1,		int *count_reserved,		int *count_pool){    pciio_info_t            pciio_info;    pciio_slot_t            pciio_slot;    pcibr_soft_t            pcibr_soft;    unsigned                s;    int                     error = -1;    if ((pciio_info = pciio_info_get(pconn_vhdl)) &&	(pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info)) &&	((pciio_slot = pciio_info_slot_get(pciio_info)) < 8)) {	s = pcibr_lock(pcibr_soft);	if (count_vchan0)	    *count_vchan0 =		pcibr_soft->bs_rrb_valid[pciio_slot];	if (count_vchan1)	    *count_vchan1 =		pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL];	if (count_reserved)	    *count_reserved =		pcibr_soft->bs_rrb_res[pciio_slot];	if (count_pool)	    *count_pool =		pcibr_soft->bs_rrb_avail[pciio_slot & 1];	error = 0;	pcibr_unlock(pcibr_soft, s);    }    return error;}/* pcibr_alloc_all_rrbs allocates all the rrbs available in the quantities * requested for each of the devies.  The evn_odd argument indicates whether * allcoation for the odd or even rrbs is requested and next group of four pairse * are the amount to assign to each device (they should sum to <= 8) and * whether to set the viritual bit for that device (1 indictaes yes, 0 indicates no) * the devices in order are either 0, 2, 4, 6 or 1, 3, 5, 7 * if even_odd is even we alloc even rrbs else we allocate odd rrbs * returns 0 if no errors else returns -1 */intpcibr_alloc_all_rrbs(devfs_handle_t vhdl, int even_odd,		     int dev_1_rrbs, int virt1, int dev_2_rrbs, int virt2,		     int dev_3_rrbs, int virt3, int dev_4_rrbs, int virt4){    devfs_handle_t            pcibr_vhdl;#ifdef colin    pcibr_soft_t            pcibr_soft;#else    pcibr_soft_t	pcibr_soft = NULL;#endif    bridge_t               *bridge = NULL;    uint32_t              rrb_setting = 0;    int                     rrb_shift = 7;    uint32_t              cur_rrb;    int                     dev_rrbs[4];    int                     virt[4];    int                     i, j;    unsigned                s;    if (GRAPH_SUCCESS ==	hwgraph_traverse(vhdl, EDGE_LBL_PCI, &pcibr_vhdl)) {	pcibr_soft = pcibr_soft_get(pcibr_vhdl);	if (pcibr_soft)	    bridge = pcibr_soft->bs_base;	hwgraph_vertex_unref(pcibr_vhdl);    }    if (bridge == NULL)	bridge = (bridge_t *) xtalk_piotrans_addr	    (vhdl, NULL, 0, sizeof(bridge_t), 0);    even_odd &= 1;    dev_rrbs[0] = dev_1_rrbs;    dev_rrbs[1] = dev_2_rrbs;    dev_rrbs[2] = dev_3_rrbs;    dev_rrbs[3] = dev_4_rrbs;    virt[0] = virt1;    virt[1] = virt2;    virt[2] = virt3;    virt[3] = virt4;    if ((dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs) > 8) {	return -1;    }    if ((dev_1_rrbs < 0) || (dev_2_rrbs < 0) || (dev_3_rrbs < 0) || (dev_4_rrbs < 0)) {	return -1;    }    /* walk through rrbs */    for (i = 0; i < 4; i++) {	if (virt[i]) {	    cur_rrb = i | 0xc;	    cur_rrb = cur_rrb << (rrb_shift * 4);	    rrb_shift--;	    rrb_setting = rrb_setting | cur_rrb;	    dev_rrbs[i] = dev_rrbs[i] - 1;	}	for (j = 0; j < dev_rrbs[i]; j++) {	    cur_rrb = i | 0x8;	    cur_rrb = cur_rrb << (rrb_shift * 4);	    rrb_shift--;	    rrb_setting = rrb_setting | cur_rrb;	}    }    if (pcibr_soft)	s = pcibr_lock(pcibr_soft);    bridge->b_rrb_map[even_odd].reg = rrb_setting;    if (pcibr_soft) {	pcibr_soft->bs_rrb_fixed |= 0x55 << even_odd;	/* since we've "FIXED" the allocations	 * for these slots, we probably can dispense	 * with tracking avail/res/valid data, but	 * keeping it up to date helps debugging.	 */	pcibr_soft->bs_rrb_avail[even_odd] =	    8 - (dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs);	pcibr_soft->bs_rrb_res[even_odd + 0] = 0;	pcibr_soft->bs_rrb_res[even_odd + 2] = 0;	pcibr_soft->bs_rrb_res[even_odd + 4] = 0;	pcibr_soft->bs_rrb_res[even_odd + 6] = 0;	pcibr_soft->bs_rrb_valid[even_odd + 0] = dev_1_rrbs - virt1;	pcibr_soft->bs_rrb_valid[even_odd + 2] = dev_2_rrbs - virt2;	pcibr_soft->bs_rrb_valid[even_odd + 4] = dev_3_rrbs - virt3;	pcibr_soft->bs_rrb_valid[even_odd + 6] = dev_4_rrbs - virt4;	pcibr_soft->bs_rrb_valid[even_odd + 0 + PCIBR_RRB_SLOT_VIRTUAL] = virt1;	pcibr_soft->bs_rrb_valid[even_odd + 2 + PCIBR_RRB_SLOT_VIRTUAL] = virt2;	pcibr_soft->bs_rrb_valid[even_odd + 4 + PCIBR_RRB_SLOT_VIRTUAL] = virt3;	pcibr_soft->bs_rrb_valid[even_odd + 6 + PCIBR_RRB_SLOT_VIRTUAL] = virt4;	pcibr_unlock(pcibr_soft, s);    }    return 0;}/* *    pcibr_rrb_flush: chase down all the RRBs assigned *      to the specified connection point, and flush *      them. */voidpcibr_rrb_flush(devfs_handle_t pconn_vhdl){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    unsigned                s;    reg_p                   rrbp;    unsigned                rrbm;    int                     i;    int                     rrbn;    unsigned                sval;    unsigned                mask;    sval = BRIDGE_RRB_EN | (pciio_slot >> 1);    mask = BRIDGE_RRB_EN | BRIDGE_RRB_PDEV;    rrbn = pciio_slot & 1;    rrbp = &bridge->b_rrb_map[rrbn].reg;    s = pcibr_lock(pcibr_soft);    rrbm = *rrbp;    for (i = 0; i < 8; ++i) {	if ((rrbm & mask) == sval)	    do_pcibr_rrb_flush(bridge, rrbn);	rrbm >>= 4;	rrbn += 2;    }    pcibr_unlock(pcibr_soft, s);}/* ===================================================================== *    Device(x) register management *//* pcibr_try_set_device: attempt to modify Device(x) * for the specified slot on the specified bridge * as requested in flags, limited to the specified * bits. Returns which BRIDGE bits were in conflict, * or ZERO if everything went OK. * * Caller MUST hold pcibr_lock when calling this function. */LOCAL intpcibr_try_set_device(pcibr_soft_t pcibr_soft,		     pciio_slot_t slot,		     unsigned flags,		     bridgereg_t mask){    bridge_t               *bridge;    pcibr_soft_slot_t       slotp;    bridgereg_t             old;    bridgereg_t             new;    bridgereg_t             chg;    bridgereg_t             bad;    bridgereg_t             badpmu;    bridgereg_t             badd32;    bridgereg_t             badd64;    bridgereg_t             fix;    unsigned                s;    bridgereg_t             xmask;    xmask = mask;    if (pcibr_soft->bs_xbridge) {    	if (mask == BRIDGE_DEV_PMU_BITS)		xmask = XBRIDGE_DEV_PMU_BITS;	if (mask == BRIDGE_DEV_D64_BITS)		xmask = XBRIDGE_DEV_D64_BITS;    }    slotp = &pcibr_soft->bs_slot[slot];    s = pcibr_lock(pcibr_soft);    bridge = pcibr_soft->bs_base;    old = slotp->bss_device;    /* figure out what the desired     * Device(x) bits are based on     * the flags specified.     */    new = old;    /* Currently, we inherit anything that     * the new caller has not specified in     * one way or another, unless we take     * action here to not inherit.     *     * This is needed for the "swap" stuff,     * since it could have been set via     * pcibr_endian_set -- altho note that     * any explicit PCIBR_BYTE_STREAM or     * PCIBR_WORD_VALUES will freely override     * the effect of that call (and vice     * versa, no protection either way).     *     * I want to get rid of pcibr_endian_set     * in favor of tracking DMA endianness     * using the flags specified when DMA     * channels are created.     */#define	BRIDGE_DEV_WRGA_BITS	(BRIDGE_DEV_PMU_WRGA_EN | BRIDGE_DEV_DIR_WRGA_EN)#define	BRIDGE_DEV_SWAP_BITS	(BRIDGE_DEV_SWAP_PMU | BRIDGE_DEV_SWAP_DIR)    /* Do not use Barrier, Write Gather,     * or Prefetch unless asked.     * Leave everything else as it     * was from the last time.     */    new = new	& ~BRIDGE_DEV_BARRIER	& ~BRIDGE_DEV_WRGA_BITS	& ~BRIDGE_DEV_PREF	;    /* Generic macro flags     */    if (flags & PCIIO_DMA_DATA) {#ifdef colin	new = new	    & ~BRIDGE_DEV_BARRIER	/* barrier off */	    | BRIDGE_DEV_PREF;		/* prefetch on */#else	new = (new            & ~BRIDGE_DEV_BARRIER)      /* barrier off */            | BRIDGE_DEV_PREF;          /* prefetch on */#endif    }    if (flags & PCIIO_DMA_CMD) {#ifdef colin	new = new	    & ~BRIDGE_DEV_PREF		/* prefetch off */	    & ~BRIDGE_DEV_WRGA_BITS	/* write gather off */	    | BRIDGE_DEV_BARRIER;	/* barrier on */#else        new = ((new            & ~BRIDGE_DEV_PREF)         /* prefetch off */            & ~BRIDGE_DEV_WRGA_BITS)    /* write gather off */            | BRIDGE_DEV_BARRIER;       /* barrier on */#endif    }    /* Generic detail flags     */    if (flags & PCIIO_WRITE_GATHER)	new |= BRIDGE_DEV_WRGA_BITS;    if (flags & PCIIO_NOWRITE_GATHER)	new &= ~BRIDGE_DEV_WRGA_BITS;    if (flags & PCIIO_PREFETCH)	new |= BRIDGE_DEV_PREF;    if (flags & PCIIO_NOPREFETCH)	new &= ~BRIDGE_DEV_PREF;    if (flags & PCIBR_WRITE_GATHER)	new |= BRIDGE_DEV_WRGA_BITS;    if (flags & PCIBR_NOWRITE_GATHER)	new &= ~BRIDGE_DEV_WRGA_BITS;    if (flags & PCIIO_BYTE_STREAM)	new |= (pcibr_soft->bs_xbridge) ? 			BRIDGE_DEV_SWAP_DIR : BRIDGE_DEV_SWAP_BITS;    if (flags & PCIIO_WORD_VALUES)	new &= (pcibr_soft->bs_xbridge) ? 			~BRIDGE_DEV_SWAP_DIR : ~BRIDGE_DEV_SWAP_BITS;    /* Provider-specific flags     */    if (flags & PCIBR_PREFETCH)	new |= BRIDGE_DEV_PREF;    if (flags & PCIBR_NOPREFETCH)	new &= ~BRIDGE_DEV_PREF;    if (flags & PCIBR_PRECISE)	new |= BRIDGE_DEV_PRECISE;    if (flags & PCIBR_NOPRECISE)	new &= ~BRIDGE_DEV_PRECISE;    if (flags & PCIBR_BARRIER)	new |= BRIDGE_DEV_BARRIER;    if (flags & PCIBR_NOBARRIER)	new &= ~BRIDGE_DEV_BARRIER;    if (flags & PCIBR_64BIT)	new |= BRIDGE_DEV_DEV_SIZE;    if (flags & PCIBR_NO64BIT)	new &= ~BRIDGE_DEV_DEV_SIZE;    chg = old ^ new;				/* what are we changing, */    chg &= xmask;				/* of the interesting bits */    if (chg) {	badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0;	if (pcibr_soft->bs_xbridge) {		badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0;		badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0;	} else {		badpmu = slotp->bss_pmu_uctr ? (BRIDGE_DEV_PMU_BITS & chg) : 0;		badd64 = slotp->bss_d64_uctr ? (BRIDGE_DEV_D64_BITS & chg) : 0;	}	bad = badpmu | badd32 | badd64;

⌨️ 快捷键说明

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