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

📄 pcibr_rrb.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    - delta_vchan0	    - delta_vchan1;	pcibr_soft->bs_rrb_res[pciio_slot] = 0;        /*         * Reserve enough RRBs so this slot's RRB configuration can be         * reset to its boot-time default following a hot-plug shut-down         */        res_rrbs =   (pcibr_soft->bs_rrb_valid_dflt[pciio_slot] -                      pcibr_soft->bs_rrb_valid[pciio_slot])                    + (pcibr_soft->bs_rrb_valid_dflt[pciio_slot +                                                    PCIBR_RRB_SLOT_VIRTUAL] -                      pcibr_soft->bs_rrb_valid[pciio_slot +                                               PCIBR_RRB_SLOT_VIRTUAL])                   + (pcibr_soft->bs_rrb_res_dflt[pciio_slot] -                      pcibr_soft->bs_rrb_res[pciio_slot]);         if (res_rrbs > 0) {             pcibr_soft->bs_rrb_res[pciio_slot] = res_rrbs;             pcibr_soft->bs_rrb_avail[pciio_slot & 1] =                 pcibr_soft->bs_rrb_avail[pciio_slot & 1]                 - res_rrbs;         } #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 devices.  The evn_odd argument indicates whether * allocation is for the odd or even rrbs. The next group of four argument * pairs indicate the amount of rrbs to be assigned to each device. The first * argument of each pair indicate the total number of rrbs to allocate for that * device. The second argument of each pair indicates how many rrb's from the * first argument should be assigned to the virtual channel. The total of all * of the first arguments should be <= 8. The second argument should be <= the * first argument. * if even_odd = 0 the devices in order are 0, 2, 4, 6  * if even_odd = 1 the devices in order are 1, 3, 5, 7 * 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 = (pcibr_soft_t)0;    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]) {		for( j = 0; j < virt[i]; j++) {			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);}/* * pcibr_slot_initial_rrb_alloc *	Allocate a default number of rrbs for this slot on  * 	the two channels.  This is dictated by the rrb allocation * 	strategy routine defined per platform. */intpcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl,			     pciio_slot_t slot){    pcibr_soft_t	 pcibr_soft;    pcibr_info_h	 pcibr_infoh;    pcibr_info_t	 pcibr_info;    bridge_t		*bridge;    int                  c0, c1, r;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))	return(EINVAL);    bridge = pcibr_soft->bs_base;    /* How may RRBs are on this slot?     */    c0 = do_pcibr_rrb_count_valid(bridge, slot);    c1 = do_pcibr_rrb_count_valid(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL);#if PCIBR_RRB_DEBUG    printk(	    "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%d\n",            slot, c0, c1);#endif    /* Do we really need any?     */    pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;    pcibr_info = pcibr_infoh[0];    if ((pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) &&	!pcibr_soft->bs_slot[slot].has_host) {	if (c0 > 0)	    do_pcibr_rrb_free(bridge, slot, c0);	if (c1 > 0)	    do_pcibr_rrb_free(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL, c1);	pcibr_soft->bs_rrb_valid[slot] = 0x1000;	pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0x1000;	return(ENODEV);    }    pcibr_soft->bs_rrb_avail[slot & 1] -= c0 + c1;    pcibr_soft->bs_rrb_valid[slot] = c0;    pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = c1;    pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0);    pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1);    r = 3 - (c0 + c1);    if (r > 0) {	pcibr_soft->bs_rrb_res[slot] = r;	pcibr_soft->bs_rrb_avail[slot & 1] -= r;    }#if PCIBR_RRB_DEBUG    printk("\t%d+%d+%d",	    0xFFF & pcibr_soft->bs_rrb_valid[slot],	    0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],	    pcibr_soft->bs_rrb_res[slot]);    printk("\n");#endif    return(0);}/* * pcibr_initial_rrb *      Assign an equal total number of RRBs to all candidate slots,  *      where the total is the sum of the number of RRBs assigned to *      the normal channel, the number of RRBs assigned to the virtual *      channel, and the number of RRBs assigned as reserved.  * *      A candidate slot is a populated slot on a non-SN1 system or  *      any existing (populated or empty) slot on an SN1 system. *      Empty SN1 slots need RRBs to support hot-plug operations. */intpcibr_initial_rrb(devfs_handle_t pcibr_vhdl,			     pciio_slot_t first, pciio_slot_t last){    pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);    bridge_t               *bridge = pcibr_soft->bs_base;    pciio_slot_t            slot;    int                     c0, c1;    int                     have[2][3];    int                     res[2];    int                     eo;    have[0][0] = have[0][1] = have[0][2] = 0;    have[1][0] = have[1][1] = have[1][2] = 0;    res[0] = res[1] = 0;    for (slot = 0; slot < 8; ++slot) {        /* Initial RRB management; give back RRBs in all non-existent slots */        (void) pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot);        /* Base calculations only on existing slots */        if ((slot >= first) && (slot <= last)) {            c0 = pcibr_soft->bs_rrb_valid[slot];            c1 = pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL];            if ((c0 + c1) < 3)                have[slot & 1][c0 + c1]++;        }    }    /* Initialize even/odd slot available RRB counts */    pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0);    pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1);    /*     * Calculate reserved RRBs for slots based on current RRB usage     */    for (eo = 0; eo < 2; eo++) {        if ((3 * have[eo][0] + 2 * have[eo][1] + have[eo][2]) <= pcibr_soft->bs_rrb_avail[eo])            res[eo] = 3;        else if ((2 * have[eo][0] + have[eo][1]) <= pcibr_soft->bs_rrb_avail[eo])            res[eo] = 2;        else if (have[eo][0] <= pcibr_soft->bs_rrb_avail[eo])            res[eo] = 1;        else            res[eo] = 0;    }    /* Assign reserved RRBs to existing slots */    for (slot = first; slot <= last; ++slot) {        int                     r;        c0 = pcibr_soft->bs_rrb_valid[slot];        c1 = pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL];        r = res[slot & 1] - (c0 + c1);        if (r > 0) {            pcibr_soft->bs_rrb_res[slot] = r;            pcibr_soft->bs_rrb_avail[slot & 1] -= r;            }    }#if PCIBR_RRB_DEBUG    printk("%v RRB MANAGEMENT: %d+%d free\n",            pcibr_vhdl,            pcibr_soft->bs_rrb_avail[0],            pcibr_soft->bs_rrb_avail[1]);    for (slot = first; slot <= last; ++slot)        printk("\tslot %d: %d+%d+%d", slot,                0xFFF & pcibr_soft->bs_rrb_valid[slot],                0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],                pcibr_soft->bs_rrb_res[slot]);    printk("\n");#endif    return 0;}

⌨️ 快捷键说明

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