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

📄 pcibr_slot.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                     pciio_slot_t slot){    pcibr_soft_t	pcibr_soft;    pcibr_info_h	pcibr_infoh;    int			nfunc;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))	return(EINVAL);    nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;    pcibr_device_info_free(pcibr_vhdl, slot);    pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;    DELA(pcibr_infoh,nfunc);    pcibr_soft->bs_slot[slot].bss_ninfo = 0;    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(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;    iopaddr_t		pci_io_fb, pci_io_fl;    iopaddr_t		pci_lo_fb, pci_lo_fl;    iopaddr_t		pci_hi_fb, pci_hi_fl;    size_t              align;    iopaddr_t           mask;    int		    	nbars;    int		       	nfunc;    int			func;    int			win;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))	return(EINVAL);    bridge = pcibr_soft->bs_base;    /* Get the current values for the allocated PCI address spaces */    PCI_ADDR_SPACE_LIMITS_LOAD();    if (as_debug)#ifdef LATER    PCI_ADDR_SPACE_LIMITS_PRINT();#endif    /* 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 < 2) ? 0x200000 : 0x100000;    mask = -align;    pci_io_fb = (pci_io_fb + align - 1) & mask;    pci_hi_fb = (pci_hi_fb + align - 1) & mask;    for (func = 0; func < nfunc; ++func) {	cfg_p                   cfgw;	cfg_p                   wptr;	pciio_space_t           space;	iopaddr_t               base;	size_t                  size;	cfg_p                   pci_cfg_cmd_reg_p;	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 = bridge->b_type0_cfg_dev[slot].f[func].l;	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;	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) {#if DEBUG && PCI_DEBUG		printk("pcibr: slot %d func %d window %d is in %d[0x%x..0x%x], alloc by prom\n",			slot, func, win, space, base, base + size - 1);#endif		continue;		/* already allocated */	    }	    align = size;		/* ie. 0x00001000 */	    if (align < _PAGESZ)		align = _PAGESZ;	/* ie. 0x00004000 */	    mask = -align;		/* ie. 0xFFFFC000 */	    switch (space) {	    case PCIIO_SPACE_IO:		base = (pci_io_fb + align - 1) & mask;		if ((base + size) > pci_io_fl) {		    base = 0;		    break;		}		pci_io_fb = base + size;		break;			    case PCIIO_SPACE_MEM:#ifdef SN1_LITTLE_ENDIAN		if ((wptr[((win*4)^4)/4] & PCI_BA_MEM_LOCATION) ==#else		if ((wptr[win] & PCI_BA_MEM_LOCATION) ==#endif  /* LITTLE_ENDIAN */		    PCI_BA_MEM_1MEG) {		    /* allocate from 20-bit PCI space */		    base = (pci_lo_fb + align - 1) & mask;		    if ((base + size) > pci_lo_fl) {			base = 0;			break;		    }		    pci_lo_fb = base + size;		} else {		    /* allocate from 32-bit or 64-bit PCI space */		    base = (pci_hi_fb + align - 1) & mask;		    if ((base + size) > pci_hi_fl) {			base = 0;			break;		    }		    pci_hi_fb = base + size;		}		break;			    default:		base = 0;#if DEBUG && PCI_DEBUG		printk("pcibr: slot %d window %d had bad space code %d\n",			slot, win, space);#endif	    }	    pcibr_info->f_window[win].w_base = base;#ifdef SN1_LITTLE_ENDIAN	    wptr[((win*4)^4)/4] = base;#if DEBUG && PCI_DEBUG		printk("Setting base address 0x%p base 0x%x\n", &(wptr[((win*4)^4)/4]), base);#endif#else	    wptr[win] = base;#endif  /* LITTLE_ENDIAN */#if DEBUG && PCI_DEBUG	    if (base >= size)		printk("pcibr: slot %d func %d window %d is in %d [0x%x..0x%x], alloc by pcibr\n",			slot, func, win, space, base, base + size - 1);	    else		printk("pcibr: slot %d func %d window %d, unable to alloc 0x%x in 0x%p\n",			slot, func, win, size, space);#endif	}				/* next base */	/*	 * Allocate space for the EXPANSION ROM	 * NOTE: DO NOT DO THIS ON AN IOC3,	 * as it blows the system away.	 */	base = size = 0;	if ((pcibr_soft->bs_slot[slot].bss_vendor_id != IOC3_VENDOR_ID_NUM) ||	    (pcibr_soft->bs_slot[slot].bss_device_id != IOC3_DEVICE_ID_NUM)) {	    wptr = cfgw + PCI_EXPANSION_ROM / 4;#ifdef SN1_LITTLE_ENDIAN	    wptr[1] = 0xFFFFF000;	    mask = wptr[1];#else	    *wptr = 0xFFFFF000;	    mask = *wptr;#endif  /* LITTLE_ENDIAN */	    if (mask & 0xFFFFF000) {		size = mask & -mask;		align = size;		if (align < _PAGESZ)		    align = _PAGESZ;		mask = -align;		base = (pci_hi_fb + align - 1) & mask;		if ((base + size) > pci_hi_fl)		    base = size = 0;		else {		    pci_hi_fb = base + size;#ifdef SN1_LITTLE_ENDIAN		    wptr[1] = base;#else		    *wptr = base;#endif  /* LITTLE_ENDIAN */#if DEBUG && PCI_DEBUG		    printk("%s/%d ROM in 0x%lx..0x%lx (alloc by pcibr)\n",			    pcibr_soft->bs_name, slot,			    base, base + size - 1);#endif		}	    }	}	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 it's 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_p = cfgw + PCI_CFG_COMMAND / 4;	pci_cfg_cmd_reg = *pci_cfg_cmd_reg_p;#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)	    *pci_cfg_cmd_reg_p = pci_cfg_cmd_reg | pci_cfg_cmd_reg_add;	    }				/* next func */    /* Now that we have allocated new chunks of PCI address spaces to this     * card we need to update the bookkeeping values which indicate     * the current PCI address space allocations.     */    PCI_ADDR_SPACE_LIMITS_STORE();    return(0);}/* * pcibr_slot_device_init * 	Setup the device register in the bridge for this PCI slot. */intpcibr_slot_device_init(devfs_handle_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 || !PCIBR_VALID_SLOT(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;    devreg |= BRIDGE_DEV_COH | BRIDGE_DEV_VIRTUAL_EN;#ifdef LITTLE_ENDIAN    devreg |= BRIDGE_DEV_DEV_SWAP;#endif    pcibr_soft->bs_slot[slot].bss_device = devreg;    bridge->b_device[slot].reg = devreg;#if DEBUG && PCI_DEBUG	printk("pcibr Device(%d): 0x%lx\n", slot, bridge->b_device[slot].reg);#endif#if DEBUG && PCI_DEBUG    printk("pcibr: PCI space allocation done.\n");#endif    return(0);}/* * pcibr_slot_guest_info_init *	Setup the host/guest relations for a PCI slot. */intpcibr_slot_guest_info_init(devfs_handle_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 || !PCIBR_VALID_SLOT(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);}/* * pcibr_slot_call_device_attach *	This calls the associated driver attach routine for the PCI * 	card in this slot. */intpcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl,			      pciio_slot_t slot,			      int          drv_flags){    pcibr_soft_t	pcibr_soft;    pcibr_info_h	pcibr_infoh;    pcibr_info_t	pcibr_info;    async_attach_t	aa = NULL;    int			func;    devfs_handle_t	xconn_vhdl,conn_vhdl;    int			nfunc;    int                 error_func;    int                 error_slot = 0;    int                 error = ENODEV;    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))	return(EINVAL);

⌨️ 快捷键说明

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