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

📄 pcibr.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
     * that we can actually meet, by     * decreasing the ending allocation     * for whichever channel wants     * more RRBs. If both want the same     * number, cut the second channel.     * NOTE: do not change the allocation for     * a channel that was passed as NULL.     */    while ((delta_vchan0 + delta_vchan1) > avail_rrbs) {	if (count_vchan0 &&	    (!count_vchan1 ||	     ((orig_vchan0 + delta_vchan0) >	      (orig_vchan1 + delta_vchan1))))	    delta_vchan0--;	else	    delta_vchan1--;    }    /* Figure final RRB allocations     */    final_vchan0 = orig_vchan0 + delta_vchan0;    final_vchan1 = orig_vchan1 + delta_vchan1;    /* If either channel wants RRBs but our actions     * would leave it with none, declare an error,     * but DO NOT change any RRB allocations.     */    if ((desired_vchan0 && !final_vchan0) ||	(desired_vchan1 && !final_vchan1)) {	error = -1;    } else {	/* Commit the allocations: free, then alloc.	 */	if (delta_vchan0 < 0)	    (void) do_pcibr_rrb_free(bridge, pciio_slot, -delta_vchan0);	if (delta_vchan1 < 0)	    (void) do_pcibr_rrb_free(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, -delta_vchan1);	if (delta_vchan0 > 0)	    (void) do_pcibr_rrb_alloc(bridge, pciio_slot, delta_vchan0);	if (delta_vchan1 > 0)	    (void) do_pcibr_rrb_alloc(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, delta_vchan1);	/* Return final values to caller.	 */	if (count_vchan0)	    *count_vchan0 = final_vchan0;	if (count_vchan1)	    *count_vchan1 = final_vchan1;	/* prevent automatic changes to this slot's RRBs	 */	pcibr_soft->bs_rrb_fixed |= 1 << pciio_slot;	/* Track the actual allocations, release	 * any further reservations, and update the	 * number of available RRBs.	 */	pcibr_soft->bs_rrb_valid[pciio_slot] = final_vchan0;	pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL] = final_vchan1;	pcibr_soft->bs_rrb_avail[pciio_slot & 1] =	    pcibr_soft->bs_rrb_avail[pciio_slot & 1]	    + pcibr_soft->bs_rrb_res[pciio_slot]	    - delta_vchan0	    - delta_vchan1;	pcibr_soft->bs_rrb_res[pciio_slot] = 0;#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 long           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;    pcibr_soft_t            pcibr_soft = NULL;    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 long           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 long           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 long           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) {	new = (new            & ~BRIDGE_DEV_BARRIER)      /* barrier off */            | BRIDGE_DEV_PREF;          /* prefetch on */    }    if (flags & PCIIO_DMA_CMD) {        new = ((new            & ~BRIDGE_DEV_PREF)         /* prefetch off */            & ~BRIDGE_DEV_WRGA_BITS)    /* write gather off */            | BRIDGE_DEV_BARRIER;       /* barrier on */    }    /* Generic detail flags     */    if (flags & PCIIO_WRITE_GATHER)

⌨️ 快捷键说明

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