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

📄 pcibr_rrb.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
    if ( is_pic(bridge) ) {	/* wait until RRB has no outstanduing XIO packets. */	while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) {		;				/* XXX- beats on bridge. bad idea? */	}	/* if the RRB has data, drain it. */	if (status & BRIDGE_RRB_VALID(rrb)) {		bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb);		/* wait until RRB is no longer valid. */		while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) {			;				/* XXX- beats on bridge. bad idea? */		}	}    }    else {	if (io_get_sh_swapper(NASID_GET(bridge))) {		while ((status = BRIDGE_REG_GET32((&bridge->b_resp_status))) & BRIDGE_RRB_INUSE(rrb)) {			;                               /* XXX- beats on bridge. bad idea? */		}		/* if the RRB has data, drain it. */		if (status & BRIDGE_RRB_VALID(rrb)) {			BRIDGE_REG_SET32((&bridge->b_resp_clear)) = __swab32(BRIDGE_RRB_CLEAR(rrb));			/* wait until RRB is no longer valid. */			while ((status = BRIDGE_REG_GET32((&bridge->b_resp_status))) & BRIDGE_RRB_VALID(rrb)) {				;                           /* XXX- beats on bridge. bad idea? */			}		}	} else { /* io_get_sh_swapper(NASID_GET(bridge)) */		while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) {			;                               /* XXX- beats on bridge. bad idea? */		}		/* if the RRB has data, drain it. */		if (status & BRIDGE_RRB_VALID(rrb)) {			bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb);			/* wait until RRB is no longer valid. */			while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) {				;                           /* XXX- beats on bridge. bad idea? */			}		}	}    }}/*  * Flush the specified rrb by calling do_pcibr_rrb_clear().  This * routine is just a wrapper to make sure the rrb is disabled  * before calling do_pcibr_rrb_clear(). */voiddo_pcibr_rrb_flush(bridge_t *bridge, int rrbn){    reg_p	 rrbp = &bridge->b_rrb_map[rrbn & 1].reg;    bridgereg_t	 rrbv;    int		 shft = (RRB_SIZE * (rrbn >> 1));    unsigned long	 ebit = RRB_ENABLE_BIT(bridge) << shft;    if ( is_pic(bridge) ) {	rrbv = *rrbp;    }    else {	if (io_get_sh_swapper(NASID_GET(bridge))) {		rrbv = BRIDGE_REG_GET32((&rrbp));	} else {		rrbv = *rrbp;	}    }    if (rrbv & ebit) {    	if ( is_pic(bridge) ) {		*rrbp = rrbv & ~ebit;	}	else {		if (io_get_sh_swapper(NASID_GET(bridge))) {			BRIDGE_REG_SET32((&rrbp)) = __swab32((rrbv & ~ebit));		} else {			*rrbp = rrbv & ~ebit;		}	}    }    do_pcibr_rrb_clear(bridge, rrbn);    if (rrbv & ebit) {	if ( is_pic(bridge) ) {		*rrbp = rrbv;	}	else {		if (io_get_sh_swapper(NASID_GET(bridge))) {			BRIDGE_REG_SET32((&rrbp)) = __swab32(rrbv);		} else {			*rrbp = rrbv;		}	}    }}voiddo_pcibr_rrb_autoalloc(pcibr_soft_t pcibr_soft,		       int slot,		       int vchan, 		       int more_rrbs){    bridge_t               *bridge = pcibr_soft->bs_base;    int                     got;    for (got = 0; got < more_rrbs; ++got) {	if (pcibr_soft->bs_rrb_res[slot] > 0)	    pcibr_soft->bs_rrb_res[slot]--;	else if (pcibr_soft->bs_rrb_avail[slot & 1] > 0)	    pcibr_soft->bs_rrb_avail[slot & 1]--;	else	    break;	if (do_pcibr_rrb_alloc(bridge, slot, vchan, 1) < 0)	    break;	pcibr_soft->bs_rrb_valid[slot][vchan]++;    }    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl,		"do_pcibr_rrb_autoalloc: added %d (of %d requested) RRBs "		"to slot %d, vchan %d\n", got, more_rrbs, 		PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), vchan));    pcibr_rrb_debug("do_pcibr_rrb_autoalloc", pcibr_soft);}/* * Flush all the rrb's assigned to the specified connection point. */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  slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);    bridge_t	 *bridge = pcibr_soft->bs_base;    bridgereg_t tmp;    uint16_t enable_bit, pdev_bits, rrb_bits, rrb_mask;    int rrb_index;    unsigned long s;    enable_bit = RRB_ENABLE_BIT(bridge);    pdev_bits = SLOT_2_PDEV(bridge, slot);    rrb_bits = enable_bit | pdev_bits;    rrb_mask = enable_bit | ((NUM_PDEV_BITS(bridge) << 1) - 1);    tmp = bridge->b_rrb_map[SLOT_2_RRB_REG(bridge, slot)].reg;    s = pcibr_lock(pcibr_soft);    for (rrb_index = 0; rrb_index < 8; rrb_index++) {	int evn_odd = SLOT_2_RRB_REG(bridge, slot);	if ((tmp & rrb_mask) == rrb_bits)	    do_pcibr_rrb_flush(bridge, (2 * rrb_index) + evn_odd);	tmp = (tmp >> RRB_SIZE);    }    pcibr_unlock(pcibr_soft, s);}/* * Device driver interface to flush the write buffers for a specified * device hanging off the bridge. */intpcibr_wrb_flush(devfs_handle_t pconn_vhdl){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    pciio_slot_t            pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    volatile bridgereg_t   *wrb_flush;    wrb_flush = &(bridge->b_wr_req_buf[pciio_slot].reg);    if ( IS_PIC_SOFT(pcibr_soft) ) {	while (*wrb_flush)		;    }    else {	if (io_get_sh_swapper(NASID_GET(bridge))) {		while (BRIDGE_REG_GET32((wrb_flush)));	} else {		while (*wrb_flush)			;	}    }    return(0);}/* * Device driver interface to request RRBs for a specified device * hanging off a Bridge.  The driver requests the total number of * RRBs it would like for the normal channel (vchan0) and for the * "virtual channel" (vchan1).  The actual number allocated to each * channel is returned. * * If we cannot allocate at least one RRB to a channel that needs * at least one, return -1 (failure).  Otherwise, satisfy the request * as best we can and return 0. */intpcibr_rrb_alloc(devfs_handle_t pconn_vhdl,		int *count_vchan0,		int *count_vchan1){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    pciio_slot_t            pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    int                     desired_vchan0;    int                     desired_vchan1;    int                     orig_vchan0;    int                     orig_vchan1;    int                     delta_vchan0;    int                     delta_vchan1;    int                     final_vchan0;    int                     final_vchan1;    int                     avail_rrbs;    int                     res_rrbs;    int			    vchan_total;    int			    vchan;    unsigned long                s;    int                     error;    /*     * TBD: temper request with admin info about RRB allocation,     * and according to demand from other devices on this Bridge.     *     * One way of doing this would be to allocate two RRBs     * for each device on the bus, before any drivers start     * asking for extras. This has the weakness that one     * driver might not give back an "extra" RRB until after     * another driver has already failed to get one that     * it wanted.     */    s = pcibr_lock(pcibr_soft);    vchan_total = NUMBER_VCHANNELS(bridge);    /* Save the boot-time RRB configuration for this slot */    if (pcibr_soft->bs_rrb_valid_dflt[pciio_slot][VCHAN0] < 0) {	for (vchan = 0; vchan < vchan_total; vchan++) 	    pcibr_soft->bs_rrb_valid_dflt[pciio_slot][vchan] =		    pcibr_soft->bs_rrb_valid[pciio_slot][vchan];        pcibr_soft->bs_rrb_res_dflt[pciio_slot] =                pcibr_soft->bs_rrb_res[pciio_slot];                      }    /* How many RRBs do we own? */    orig_vchan0 = pcibr_soft->bs_rrb_valid[pciio_slot][VCHAN0];    orig_vchan1 = pcibr_soft->bs_rrb_valid[pciio_slot][VCHAN1];    /* How many RRBs do we want? */    desired_vchan0 = count_vchan0 ? *count_vchan0 : orig_vchan0;    desired_vchan1 = count_vchan1 ? *count_vchan1 : orig_vchan1;    /* How many RRBs are free? */    avail_rrbs = pcibr_soft->bs_rrb_avail[pciio_slot & 1]	+ pcibr_soft->bs_rrb_res[pciio_slot];    /* Figure desired deltas */    delta_vchan0 = desired_vchan0 - orig_vchan0;    delta_vchan1 = desired_vchan1 - orig_vchan1;    /* Trim back deltas to something     * 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, VCHAN0, -delta_vchan0);	if (delta_vchan1 < 0)	    (void) do_pcibr_rrb_free(bridge, pciio_slot, VCHAN1, -delta_vchan1);	if (delta_vchan0 > 0)	    (void) do_pcibr_rrb_alloc(bridge, pciio_slot, VCHAN0, delta_vchan0);	if (delta_vchan1 > 0)	    (void) do_pcibr_rrb_alloc(bridge, pciio_slot, VCHAN1, 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][VCHAN0] = final_vchan0;	pcibr_soft->bs_rrb_valid[pciio_slot][VCHAN1] = final_vchan1;

⌨️ 快捷键说明

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