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

📄 pcibr_slot.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * pcibr_slot_pcix_rbar_init *	Allocate RBARs to the PCI-X functions on a given device */intpcibr_slot_pcix_rbar_init(pcibr_soft_t pcibr_soft,			    pciio_slot_t slot){    pcibr_info_h	 pcibr_infoh;    pcibr_info_t	 pcibr_info;    char		 tmp_str[256];    int		       	 nfunc;    int			 func;    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))	return(EINVAL);    if ((nfunc = pcibr_soft->bs_slot[slot].bss_ninfo) < 1)	return(EINVAL);    if (!(pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos))	return(EINVAL);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RBAR, pcibr_soft->bs_vhdl,		"pcibr_slot_pcix_rbar_init for slot %d\n", 		PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot)));    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RBAR, pcibr_soft->bs_vhdl,		"\tslot/func\trequested\tgiven\tinuse\tavail\n"));    for (func = 0; func < nfunc; ++func) {	cap_pcix_type0_t	*pcix_cap_p;	cap_pcix_stat_reg_t	*pcix_statreg_p;	cap_pcix_cmd_reg_t	*pcix_cmdreg_p;	int 			 num_rbar;	if (!(pcibr_info = pcibr_infoh[func]))	    continue;	if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE)	    continue;	if (!(pcix_cap_p = pcibr_info->f_pcix_cap))	    continue;	pcix_statreg_p = &pcix_cap_p->pcix_type0_status;	pcix_cmdreg_p = &pcix_cap_p->pcix_type0_command;	/* If there are enough RBARs to satify the number of "max outstanding 	 * transactions" each function requested (bs_pcix_rbar_percent_allowed	 * is 100%), then give each function what it requested, otherwise give 	 * the functions a "percentage of what they requested".	 */	if (pcibr_soft->bs_pcix_rbar_percent_allowed >= 100) {	    pcix_cmdreg_p->max_split = pcix_statreg_p->max_out_split;	    num_rbar = max_splittrans_to_numbuf[pcix_cmdreg_p->max_split];	    pcibr_soft->bs_pcix_rbar_inuse += num_rbar;	    pcibr_soft->bs_pcix_rbar_avail -= num_rbar;	    pcix_cmdreg_p->max_mem_read_cnt = pcix_statreg_p->max_mem_read_cnt;	} else {	    int index;	    /* index into max_splittrans_to_numbuf table */	    int max_out;    /* max outstanding transactions given to func */	    /* Calculate the percentage of RBARs this function can have.	     * NOTE: Every function gets at least 1 RBAR (thus the "+1").	     * bs_pcix_rbar_percent_allowed is the percentage of what was	     * requested less this 1 RBAR that all functions automatically 	     * gets	     */	    max_out = ((max_splittrans_to_numbuf[pcix_statreg_p->max_out_split]			* pcibr_soft->bs_pcix_rbar_percent_allowed) / 100) + 1;	    /* round down the newly caclulated max_out to a valid number in	     * max_splittrans_to_numbuf[]	     */	    for (index = 0; index < MAX_SPLIT_TABLE-1; index++)		if (max_splittrans_to_numbuf[index + 1] > max_out)		    break;	    pcix_cmdreg_p->max_split = index;	    num_rbar = max_splittrans_to_numbuf[pcix_cmdreg_p->max_split];	    pcibr_soft->bs_pcix_rbar_inuse += num_rbar;            pcibr_soft->bs_pcix_rbar_avail -= num_rbar;	    pcix_cmdreg_p->max_mem_read_cnt = pcix_statreg_p->max_mem_read_cnt;	}        /*         * The kernel only allows functions to have so many variable args,         * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printf         * arguments fails so sprintf() it into a temporary string.         */	if (pcibr_debug_mask & PCIBR_DEBUG_RBAR) {            sprintf(tmp_str,"\t  %d/%d   \t    %d    \t  %d  \t  %d  \t  %d\n",	            PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func,	            max_splittrans_to_numbuf[pcix_statreg_p->max_out_split],	            max_splittrans_to_numbuf[pcix_cmdreg_p->max_split],	            pcibr_soft->bs_pcix_rbar_inuse, 		    pcibr_soft->bs_pcix_rbar_avail);            PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RBAR, pcibr_soft->bs_vhdl, 		        "%s", tmp_str));	}    }    return(0);}int as_debug = 0;/* * pcibr_slot_addr_space_init *	Reserve chunks of PCI address space as required by  * 	the base registers in the card. */intpcibr_slot_addr_space_init(vertex_hdl_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;    iopaddr_t            mask;    int		       	 nbars;    int		       	 nfunc;    int			 func;    int			 win;    int                  rc = 0;    int			 align;    int			 align_slot;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft)	return(EINVAL);    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))	return(EINVAL);    bridge = pcibr_soft->bs_base;    /* allocate address space,     * for windows that have not been     * previously assigned.     */    if (pcibr_soft->bs_slot[slot].has_host) {	return(0);    }    nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;    if (nfunc < 1)	return(EINVAL);    pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;    if (!pcibr_infoh)	return(EINVAL);    /*     * Try to make the DevIO windows not     * overlap by pushing the "io" and "hi"     * allocation areas up to the next one     * or two megabyte bound. This also     * keeps them from being zero.     *     * DO NOT do this with "pci_lo" since     * the entire "lo" area is only a     * megabyte, total ...     */    align_slot = 0x100000;    align = align_slot;    for (func = 0; func < nfunc; ++func) {	cfg_p                   cfgw;	cfg_p                   wptr;	pciio_space_t           space;	iopaddr_t               base;	size_t                  size;#ifdef PCI_LATER	char			tmp_str[256];#endif	unsigned                pci_cfg_cmd_reg;	unsigned                pci_cfg_cmd_reg_add = 0;	pcibr_info = pcibr_infoh[func];	if (!pcibr_info)	    continue;	if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE)	    continue;	        cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0);	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;	if ((do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0)	    nbars = 2;	else	    nbars = PCI_CFG_BASE_ADDRS;	for (win = 0; win < nbars; ++win) {	    space = pcibr_info->f_window[win].w_space;	    base = pcibr_info->f_window[win].w_base;	    size = pcibr_info->f_window[win].w_size;	    	    if (size < 1)		continue;	    if (base >= size) {		/*         	 * The kernel only allows functions to have so many variable                 * args attempting to call PCIBR_DEBUG_ALWAYS() with more than         	 * 5 printf arguments fails so sprintf() it into a temporary 		 * string (tmp_str).         	 */#if defined(SUPPORT_PRINTING_R_FORMAT)		if (pcibr_debug_mask & PCIBR_DEBUG_BAR) {		    sprintf(tmp_str, "pcibr_slot_addr_space_init: slot=%d, "			"func=%d win %d is in %r [0x%x..0x%x], allocated by "			"prom\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot),			func, win, space, space_desc, base, base + size - 1);		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, 				"%s",tmp_str));		}#endif	/* SUPPORT_PRINTING_R_FORMAT */		continue;		/* already allocated */	    }	    align = (win) ? size : align_slot; 	    if (align < PAGE_SIZE)		align = PAGE_SIZE;        /* ie. 0x00004000 */ 	    switch (space) {	    case PCIIO_SPACE_IO:                base = pcibr_bus_addr_alloc(pcibr_soft,                                            &pcibr_info->f_window[win],                                            PCIIO_SPACE_IO,                                            0, size, align);                if (!base)                    rc = ENOSPC;		break;			    case PCIIO_SPACE_MEM:		if ((do_pcibr_config_get(wptr, (win * 4), 4) &		     PCI_BA_MEM_LOCATION) == PCI_BA_MEM_1MEG) { 		    /* allocate from 20-bit PCI space */                    base = pcibr_bus_addr_alloc(pcibr_soft,                                                &pcibr_info->f_window[win],                                                PCIIO_SPACE_MEM,                                                0, size, align);                    if (!base)                        rc = ENOSPC;		} else {		    /* allocate from 32-bit or 64-bit PCI space */                    base = pcibr_bus_addr_alloc(pcibr_soft,                                                &pcibr_info->f_window[win],                                                PCIIO_SPACE_MEM32,                                                0, size, align);		    if (!base) 			rc = ENOSPC;		}		break;			    default:		base = 0;		PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl,			    "pcibr_slot_addr_space_init: slot=%d, window %d "			    "had bad space code %d\n", 			    PCIBR_DEVICE_TO_SLOT(pcibr_soft,slot), win, space));	    }	    pcibr_info->f_window[win].w_base = base;	    do_pcibr_config_set(wptr, (win * 4), 4, base);#if defined(SUPPORT_PRINTING_R_FORMAT)	    if (pcibr_debug_mask & PCIBR_DEBUG_BAR) {                if (base >= size) {		    sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func="				    "%d, win %d is in %r[0x%x..0x%x], "				    "allocated by pcibr\n",				    PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 				    func, win, space, space_desc, base, 				    base + size - 1);		     PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, 				 "%s",tmp_str));	        }		else {		    sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func="				    "%d, win %d, unable to alloc 0x%x in %r\n",				    PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 				    func, win, size, space, space_desc);		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, 				"%s",tmp_str));	        }	    }#endif	/* SUPPORT_PRINTING_R_FORMAT */	}				/* next base */	/*	 * Allocate space for the EXPANSION ROM	 */	base = size = 0;	{	    wptr = cfgw + PCI_EXPANSION_ROM / 4;	    do_pcibr_config_set(wptr, 0, 4, 0xFFFFF000);	    mask = do_pcibr_config_get(wptr, 0, 4);	    if (mask & 0xFFFFF000) {		size = mask & -mask;                base = pcibr_bus_addr_alloc(pcibr_soft,                                            &pcibr_info->f_rwindow,                                            PCIIO_SPACE_MEM32,                                             0, size, align);		if (!base)		    rc = ENOSPC;		else {		    do_pcibr_config_set(wptr, 0, 4, base);		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl,				"pcibr_slot_addr_space_init: slot=%d, func=%d, "				"ROM in [0x%X..0x%X], allocated by pcibr\n",				PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 				func, base, base + size - 1));		}	    }	}	pcibr_info->f_rbase = base;	pcibr_info->f_rsize = size;	/*	 * if necessary, update the board's	 * command register to enable decoding	 * in the windows we added.	 *	 * There are some bits we always want to	 * be sure are set.	 */	pci_cfg_cmd_reg_add |= PCI_CMD_IO_SPACE;	/*	 * The Adaptec 1160 FC Controller WAR #767995:	 * The part incorrectly ignores the upper 32 bits of a 64 bit	 * address when decoding references to its registers so to	 * keep it from responding to a bus cycle that it shouldn't	 * we only use I/O space to get at it's registers.  Don't	 * enable memory space accesses on that PCI device.	 */	#define FCADP_VENDID 0x9004 /* Adaptec Vendor ID from fcadp.h */	#define FCADP_DEVID 0x1160  /* Adaptec 1160 Device ID from fcadp.h */	if ((pcibr_info->f_vendor != FCADP_VENDID) ||	    (pcibr_info->f_device != FCADP_DEVID))	    pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE;	pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER;	pci_cfg_cmd_reg = do_pcibr_config_get(cfgw, PCI_CFG_COMMAND, 4);#if PCI_FBBE	/* XXX- check here to see if dev can do fast-back-to-back */	if (!((pci_cfg_cmd_reg >> 16) & PCI_STAT_F_BK_BK_CAP))	    fast_back_to_back_enable = 0;#endif	pci_cfg_cmd_reg &= 0xFFFF;	if (pci_cfg_cmd_reg_add & ~pci_cfg_cmd_reg)	    do_pcibr_config_set(cfgw, PCI_CFG_COMMAND, 4, 				pci_cfg_cmd_reg | pci_cfg_cmd_reg_add);    }				/* next func */    return(rc);}/* * pcibr_slot_device_init * 	Setup the device register in the bridge for this PCI slot. */intpcibr_slot_device_init(vertex_hdl_t pcibr_vhdl,		       pciio_slot_t slot){    pcibr_soft_t	 pcibr_soft;    bridge_t		*bridge;    bridgereg_t		 devreg;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft)	return(EINVAL);    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))	return(EINVAL);    bridge = pcibr_soft->bs_base;    /*     * Adjustments to Device(x)     * and init of bss_device shadow     */    devreg = bridge->b_device[slot].reg;    devreg &= ~BRIDGE_DEV_PAGE_CHK_DIS;    /*     * PIC WAR. PV# 855271     * Don't enable virtual channels in the PIC by default.     * Can cause problems with 32-bit devices. (The bit is only intended     * for 64-bit devices).  We set the bit in pcibr_try_set_device()     * if we're 64-bit and requesting virtual channels.     */    if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV855271, pcibr_soft))	devreg |= BRIDGE_DEV_COH;    else	devreg |= BRIDGE_DEV_COH | BRIDGE_DEV_VIRTUAL_EN;    pcibr_soft->bs_slot[slot].bss_device = devreg;    bridge->b_device[slot].reg = devreg;#ifdef PIC_LATER    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pcibr_vhdl,		"pcibr_slot_device_init: Device(%d): %R\n",		slot, devreg, device_bits));#endif    return(0);}/* * pcibr_slot_guest_info_init *	Setup the host/guest relations for a PCI slot. */intpcibr_slot_guest_info_init(vertex_hdl_t pcibr_vhdl,			   pciio_slot_t	slot){    pcibr_soft_t	pcibr_soft;    pcibr_info_h	pcibr_infoh;    pcibr_info_t	pcibr_info;    pcibr_soft_slot_t	slotp;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft)	return(EINVAL);    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))	return(EINVAL);    slotp = &pcibr_soft->bs_slot[slot];    /* create info and verticies for guest slots;     * for compatibilitiy macros, create info     * for even unpopulated slots (but do not     * build verticies for them).     */    if (pcibr_soft->bs_slot[slot].bss_ninfo < 1) {	NEWA(pcibr_infoh, 1);	pcibr_soft->bs_slot[slot].bss_ninfo = 1;	pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh;	pcibr_info = pcibr_device_info_new	    (pcibr_soft, slot, PCIIO_FUNC_NONE,	     PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE);	if (pcibr_soft->bs_slot[slot].has_host) {	    slotp->slot_conn = pciio_device_info_register		(pcibr_vhdl, &pcibr_info->f_c);	}    }    /* generate host/guest relations     */    if (pcibr_soft->bs_slot[slot].has_host) {	int  host = pcibr_soft->bs_slot[slot].host_slot;	pcibr_soft_slot_t host_slotp = &pcibr_soft->bs_slot[host];	hwgraph_edge_add(slotp->slot_conn,			 host_slotp->slot_conn,			 EDGE_LBL_HOST);	/* XXX- only gives us one guest edge per	 * host. If/when we have a host with more than	 * one guest, we will need to figure out how	 * the host finds all its guests, and sorts	 * out which one is which.	 */	hwgraph_edge_add(host_slotp->slot_conn,			 slotp->slot_conn,			 EDGE_LBL_GUEST);    }    return(0);}/*

⌨️ 快捷键说明

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