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

📄 pcibr.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	    }            if (COPYIN(arg, &req, sizeof(req))) {                error = EFAULT;                break;            }            error = pcibr_slot_query(pcibr_vhdl, &req);	    break;	}#endif	/* LATER */    default:	break;    }    return error;}voidpcibr_freeblock_sub(iopaddr_t *free_basep,		    iopaddr_t *free_lastp,		    iopaddr_t base,		    size_t size){    iopaddr_t               free_base = *free_basep;    iopaddr_t               free_last = *free_lastp;    iopaddr_t               last = base + size - 1;    if ((last < free_base) || (base > free_last));	/* free block outside arena */    else if ((base <= free_base) && (last >= free_last))	/* free block contains entire arena */	*free_basep = *free_lastp = 0;    else if (base <= free_base)	/* free block is head of arena */	*free_basep = last + 1;    else if (last >= free_last)	/* free block is tail of arena */	*free_lastp = base - 1;    /*     * We are left with two regions: the free area     * in the arena "below" the block, and the free     * area in the arena "above" the block. Keep     * the one that is bigger.     */    else if ((base - free_base) > (free_last - last))	*free_lastp = base - 1;		/* keep lower chunk */    else	*free_basep = last + 1;		/* keep upper chunk */}/* Convert from ssram_bits in control register to number of SSRAM entries */#define ATE_NUM_ENTRIES(n) _ate_info[n]/* Possible choices for number of ATE entries in Bridge's SSRAM */LOCAL int               _ate_info[] ={    0,					/* 0 entries */    8 * 1024,				/* 8K entries */    16 * 1024,				/* 16K entries */    64 * 1024				/* 64K entries */};#define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))#define ATE_PROBE_VALUE 0x0123456789abcdefULL/* * Determine the size of this bridge's external mapping SSRAM, and set * the control register appropriately to reflect this size, and initialize * the external SSRAM. */LOCAL intpcibr_init_ext_ate_ram(bridge_t *bridge){    int                     largest_working_size = 0;    int                     num_entries, entry;    int                     i, j;    bridgereg_t             old_enable, new_enable;    int                     s;    /* Probe SSRAM to determine its size. */    old_enable = bridge->b_int_enable;    new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;    bridge->b_int_enable = new_enable;    for (i = 1; i < ATE_NUM_SIZES; i++) {	/* Try writing a value */	bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE;	/* Guard against wrap */	for (j = 1; j < i; j++)	    bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0;	/* See if value was written */	if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE)	    largest_working_size = i;    }    bridge->b_int_enable = old_enable;    bridge->b_wid_tflush;		/* wait until Bridge PIO complete */    /*     * ensure that we write and read without any interruption.     * The read following the write is required for the Bridge war     */    s = splhi();    bridge->b_wid_control = (bridge->b_wid_control	& ~BRIDGE_CTRL_SSRAM_SIZE_MASK)	| BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);    bridge->b_wid_control;		/* inval addr bug war */    splx(s);    num_entries = ATE_NUM_ENTRIES(largest_working_size);#if PCIBR_ATE_DEBUG    if (num_entries)	printk("bridge at 0x%x: clearing %d external ATEs\n", bridge, num_entries);    else	printk("bridge at 0x%x: no externa9422l ATE RAM found\n", bridge);#endif    /* Initialize external mapping entries */    for (entry = 0; entry < num_entries; entry++)	bridge->b_ext_ate_ram[entry] = 0;    return (num_entries);}/* * Allocate "count" contiguous Bridge Address Translation Entries * on the specified bridge to be used for PCI to XTALK mappings. * Indices in rm map range from 1..num_entries.  Indicies returned * to caller range from 0..num_entries-1. * * Return the start index on success, -1 on failure. */LOCAL intpcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count){    int                     index = 0;    index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);/* printk("Colin: pcibr_ate_alloc - index %d count %d \n", index, count); */    if (!index && pcibr_soft->bs_ext_ate_map)	index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count);    /* rmalloc manages resources in the 1..n     * range, with 0 being failure.     * pcibr_ate_alloc manages resources     * in the 0..n-1 range, with -1 being failure.     */    return index - 1;}LOCAL voidpcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count)/* Who says there's no such thing as a free meal? :-) */{    /* note the "+1" since rmalloc handles 1..n but     * we start counting ATEs at zero.     *//* printk("Colin: pcibr_ate_free - index %d count %d\n", index, count); */    rmfree((index < pcibr_soft->bs_int_ate_size)	   ? pcibr_soft->bs_int_ate_map	   : pcibr_soft->bs_ext_ate_map,	   count, index + 1);}LOCAL pcibr_info_tpcibr_info_get(devfs_handle_t vhdl){    return (pcibr_info_t) pciio_info_get(vhdl);}pcibr_info_tpcibr_device_info_new(			 pcibr_soft_t pcibr_soft,			 pciio_slot_t slot,			 pciio_function_t rfunc,			 pciio_vendor_id_t vendor,			 pciio_device_id_t device){    pcibr_info_t            pcibr_info;    pciio_function_t        func;    int                     ibit;    func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc;    NEW(pcibr_info);    pciio_device_info_new(&pcibr_info->f_c,			  pcibr_soft->bs_vhdl,			  slot, rfunc,			  vendor, device);    if (slot != PCIIO_SLOT_NONE) {	/*	 * Currently favored mapping from PCI	 * slot number and INTA/B/C/D to Bridge	 * PCI Interrupt Bit Number:	 *	 *     SLOT     A B C D	 *      0       0 4 0 4	 *      1       1 5 1 5	 *      2       2 6 2 6	 *      3       3 7 3 7	 *      4       4 0 4 0	 *      5       5 1 5 1	 *      6       6 2 6 2	 *      7       7 3 7 3	 *	 * XXX- allow pcibr_hints to override default	 * XXX- allow ADMIN to override pcibr_hints	 */	for (ibit = 0; ibit < 4; ++ibit)	    pcibr_info->f_ibit[ibit] =		(slot + 4 * ibit) & 7;	/*	 * Record the info in the sparse func info space.	 */	if (func < pcibr_soft->bs_slot[slot].bss_ninfo)	    pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info;    }    return pcibr_info;}voidpcibr_device_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){    pcibr_soft_t	pcibr_soft = pcibr_soft_get(pcibr_vhdl);    pcibr_info_t	pcibr_info;    pciio_function_t	func;    pcibr_soft_slot_t	slotp = &pcibr_soft->bs_slot[slot];    int			nfunc = slotp->bss_ninfo;    for (func = 0; func < nfunc; func++) {	pcibr_info = slotp->bss_infos[func];	if (!pcibr_info) 	    continue;	slotp->bss_infos[func] = 0;	pciio_device_info_unregister(pcibr_vhdl, &pcibr_info->f_c);	pciio_device_info_free(&pcibr_info->f_c);	DEL(pcibr_info);    }    /* Clear the DEVIO(x) for this slot */    slotp->bss_devio.bssd_space = PCIIO_SPACE_NONE;    slotp->bss_devio.bssd_base = PCIBR_D32_BASE_UNSET;    slotp->bss_device  = 0;        /* Reset the mapping usage counters */    slotp->bss_pmu_uctr = 0;    slotp->bss_d32_uctr = 0;    slotp->bss_d64_uctr = 0;    /* Clear the Direct translation info */    slotp->bss_d64_base = PCIBR_D64_BASE_UNSET;    slotp->bss_d64_flags = 0;    slotp->bss_d32_base = PCIBR_D32_BASE_UNSET;    slotp->bss_d32_flags = 0;    /* Clear out shadow info necessary for the external SSRAM workaround */    slotp->bss_ext_ates_active = ATOMIC_INIT(0);    slotp->bss_cmd_pointer = 0;    slotp->bss_cmd_shadow = 0;}/*  * PCI_ADDR_SPACE_LIMITS_LOAD *	Gets the current values of  *		pci io base,  *		pci io last, *		pci low memory base, *		pci low memory last, *		pci high memory base, * 		pci high memory last */#define PCI_ADDR_SPACE_LIMITS_LOAD()			\    pci_io_fb = pcibr_soft->bs_spinfo.pci_io_base;	\    pci_io_fl = pcibr_soft->bs_spinfo.pci_io_last;	\    pci_lo_fb = pcibr_soft->bs_spinfo.pci_swin_base;	\    pci_lo_fl = pcibr_soft->bs_spinfo.pci_swin_last;	\    pci_hi_fb = pcibr_soft->bs_spinfo.pci_mem_base;	\    pci_hi_fl = pcibr_soft->bs_spinfo.pci_mem_last;/* * PCI_ADDR_SPACE_LIMITS_STORE *	Sets the current values of *		pci io base,  *		pci io last, *		pci low memory base, *		pci low memory last, *		pci high memory base, * 		pci high memory last */#define PCI_ADDR_SPACE_LIMITS_STORE()			\    pcibr_soft->bs_spinfo.pci_io_base = pci_io_fb;	\    pcibr_soft->bs_spinfo.pci_io_last = pci_io_fl;	\    pcibr_soft->bs_spinfo.pci_swin_base = pci_lo_fb;	\    pcibr_soft->bs_spinfo.pci_swin_last = pci_lo_fl;	\    pcibr_soft->bs_spinfo.pci_mem_base = pci_hi_fb;	\    pcibr_soft->bs_spinfo.pci_mem_last = pci_hi_fl;#define PCI_ADDR_SPACE_LIMITS_PRINT()			\    printf("+++++++++++++++++++++++\n"			\	   "IO base 0x%x last 0x%x\n"			\	   "SWIN base 0x%x last 0x%x\n"			\	   "MEM base 0x%x last 0x%x\n"			\	   "+++++++++++++++++++++++\n",			\	   pcibr_soft->bs_spinfo.pci_io_base,		\	   pcibr_soft->bs_spinfo.pci_io_last,		\	   pcibr_soft->bs_spinfo.pci_swin_base,		\	   pcibr_soft->bs_spinfo.pci_swin_last,		\	   pcibr_soft->bs_spinfo.pci_mem_base,		\	   pcibr_soft->bs_spinfo.pci_mem_last);/* * pcibr_slot_info_init *	Probe for this slot and see if it is populated. *	If it is populated initialize the generic PCI infrastructural * 	information associated with this particular PCI device. */intpcibr_slot_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;    bridge_t		   *bridge;    cfg_p                   cfgw;    unsigned                idword;    unsigned                pfail;    unsigned                idwords[8];    pciio_vendor_id_t       vendor;    pciio_device_id_t       device;    unsigned                htype;    cfg_p                   wptr;    int                     win;    pciio_space_t           space;    iopaddr_t		    pci_io_fb,	pci_io_fl;    iopaddr_t		    pci_lo_fb,  pci_lo_fl;    iopaddr_t		    pci_hi_fb,  pci_hi_fl;    int			    nfunc;    pciio_function_t	    rfunc;    int			    func;    devfs_handle_t	    conn_vhdl;    pcibr_soft_slot_t	    slotp;        /* Get the basic software information required to proceed */    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (!pcibr_soft)	return(EINVAL);    bridge = pcibr_soft->bs_base;    if (!PCIBR_VALID_SLOT(slot))	return(EINVAL);    /* If we have a host slot (eg:- IOC3 has 2 PCI slots and the initialization     * is done by the host slot then we are done.     */    if (pcibr_soft->bs_slot[slot].has_host) {	return(0);        }    /* Check for a slot with any system critical functions */    if (pcibr_is_slot_sys_critical(pcibr_vhdl, slot))        return(EPERM);    /* Load the current values of allocated PCI address spaces */    PCI_ADDR_SPACE_LIMITS_LOAD();        /* Try to read the device-id/vendor-id from the config space */    cfgw = bridge->b_type0_cfg_dev[slot].l;    if (pcibr_probe_slot(bridge, cfgw, &idword)) 	return(ENODEV);    slotp = &pcibr_soft->bs_slot[slot];    slotp->slot_status |= SLOT_POWER_UP;    vendor = 0xFFFF & idword;    /* If the vendor id is not valid then the slot is not populated     * and we are done.     */    if (vendor == 0xFFFF) 	return(ENODEV);			        device = 0xFFFF & (idword >> 16);    htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1);    nfunc = 1;    rfunc = PCIIO_FUNC_NONE;    pfail = 0;    /* NOTE: if a card claims to be multifunction     * but only responds to config space 0, treat     * it as a unifunction card.     */    if (htype & 0x80) {		/* MULTIFUNCTION */	for (func = 1; func < 8; ++func) {	    cfgw = bridge->b_type0_cfg_dev[slot].f[func].l;	    if (pcibr_probe_slot(bridge, cfgw, &idwords[func])) {		pfail |= 1 << func;		continue;	    }	    vendor = 0xFFFF & idwords[func];	    if (vendor == 0xFFFF) {		pfail |= 1 << func;		continue;	    }	    nfunc = func + 1;	    rfunc = 0;	}	cfgw = bridge->b_type0_cfg_dev[slot]

⌨️ 快捷键说明

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