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

📄 pcibr_slot.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	slotp->resp_p_int_host = bridge->p_int_addr_64[slot];    } else {	slotp->resp_b_int_enable = bridge->b_int_enable;	slotp->resp_b_int_host = bridge->b_int_addr[slot].addr;    }    if (COPYOUT(slotp, respp, sizeof(*respp))) {        return(EFAULT);    }    snia_kmem_free(slotp, sizeof(*slotp));    return(0);}/* * pcibr_slot_query *	Return information about the PCI slot maintained by the infrastructure. *	Information is requested in the request structure. * *      Information returned in the response structure: *		Slot hwgraph name *		Vendor/Device info *		Base register info *		Interrupt mapping from device pins to the bridge pins *		Devio register *		Software RRB info *		RRB register info *		Host/Gues info *		PCI Bus #,slot #, function # *		Slot provider hwgraph name *		Provider Functions *		Error handler *		DMA mapping usage counters *		DMA direct translation info *		External SSRAM workaround info */intpcibr_slot_query(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp){    pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);    pciio_slot_t            slot;    pciio_slot_t            tmp_slot;    pcibr_slot_info_resp_t  respp = reqp->req_respp.query;    int                     size = reqp->req_size;    int                     error = 0;    /* Make sure that we are dealing with a bridge device vertex */    if (!pcibr_soft) {        return(PCI_NOT_A_BRIDGE);    }    /* req_slot is the 'external' slot number, convert for internal use */    slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl,                "pcibr_slot_query: pcibr_soft=0x%x, slot=%d, reqp=0x%x\n",                pcibr_soft, slot, reqp));    /* Make sure that we have a valid PCI slot number or PCIIO_SLOT_NONE */    if ((!PCIBR_VALID_SLOT(pcibr_soft, slot)) && (slot != PCIIO_SLOT_NONE)) {        return(PCI_NOT_A_SLOT);    }    /* Do not allow a query of a slot in a shoehorn */    if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) {       return(PCI_SLOT_IN_SHOEHORN);    }    /* Return information for the requested PCI slot */    if (slot != PCIIO_SLOT_NONE) {        if (size < sizeof(*respp)) {            return(PCI_RESP_AREA_TOO_SMALL);        }#ifdef PIC_LATER        /* Acquire read access to the bus */        mrlock(pcibr_soft->bs_bus_lock, MR_ACCESS, PZERO);#endif        error = pcibr_slot_info_return(pcibr_soft, slot, respp);#ifdef PIC_LATER        /* Release the bus lock */        mrunlock(pcibr_soft->bs_bus_lock);#endif        return(error);    }    /* Return information for all the slots */    for (tmp_slot = pcibr_soft->bs_min_slot; 		tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); tmp_slot++) {        if (size < sizeof(*respp)) {            return(PCI_RESP_AREA_TOO_SMALL);        }#ifdef PIC_LATER        /* Acquire read access to the bus */        mrlock(pcibr_soft->bs_bus_lock, MR_ACCESS, PZERO);#endif        error = pcibr_slot_info_return(pcibr_soft, tmp_slot, respp);#ifdef PCI_LATER        /* Release the bus lock */        mrunlock(pcibr_soft->bs_bus_lock);#endif        if (error) {            return(error);        }        ++respp;        size -= sizeof(*respp);    }    return(error);}#if 0/* * pcibr_slot_reset *	Reset the PCI device in the particular slot. * *      The Xbridge does not comply with the PCI Specification *      when resetting an indiviaudl slot.  An individual slot is *      is reset by toggling the slot's bit in the Xbridge Control *      Register.  The Xbridge will assert the target slot's  *      (non-bussed) RST signal, but does not assert the (bussed)  *      REQ64 signal as required by the specification.   As *      designed, the Xbridge cannot assert the REQ64 signal *      becuase it may interfere with a bus transaction in progress. *      The practical effects of this Xbridge implementation is *      device dependent;  it probably will not adversely effect *      32-bit cards, but may disable 64-bit data transfers by those *      cards that normally support 64-bit data transfers.   * *      The Xbridge will assert REQ64 when all four slots are reset *      by simultaneously toggling all four slot reset bits in the *      Xbridge Control Register.  This is basically a PCI bus reset *      and asserting the (bussed) REQ64 signal will not interfere *      with any bus transactions in progress. * *      The Xbridge (and the SN0 Bridge) support resetting only *      four PCI bus slots via the (X)bridge Control Register. * *      To reset an individual slot for the PCI Hot-Plug feature *      use the L1 console commands to power-down and then  *      power-up the slot, or use the kernel infrastructure *      functions to power-down/up the slot when they are *      implemented for SN1. */intpcibr_slot_reset(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){	pcibr_soft_t		 pcibr_soft = pcibr_soft_get(pcibr_vhdl);	bridge_t		*bridge;	bridgereg_t		 ctrlreg,tmp;	volatile bridgereg_t	*wrb_flush;	if (!pcibr_soft)		return(EINVAL);	if (!PCIBR_VALID_SLOT(pcibr_soft, slot))		return(EINVAL);	/* Enable the DMA operations from this device of the xtalk widget	 * (PCI host bridge in this case).	 */	xtalk_widgetdev_enable(pcibr_soft->bs_conn, slot);	/* Set the reset slot bit in the bridge's wid control register	 * to reset the PCI slot 	 */	bridge = pcibr_soft->bs_base;	/* Read the bridge widget control and clear out the reset pin	 * bit for the corresponding slot. 	 */	tmp = ctrlreg = bridge->b_wid_control;	tmp &= ~BRIDGE_CTRL_RST_PIN(slot); 	bridge->b_wid_control = tmp;	tmp = bridge->b_wid_control;	/* Restore the old control register back.	 * NOTE : PCI card gets reset when the reset pin bit	 * changes from 0 (set above) to 1 (going to be set now).	 */	bridge->b_wid_control = ctrlreg;	/* Flush the write buffers if any !! */	wrb_flush = &(bridge->b_wr_req_buf[slot].reg);	while (*wrb_flush);	return(0);}#endif#define PROBE_LOCK 0	/* FIXME: we're attempting to lock around accesses			 * to b_int_enable.   This hangs pcibr_probe_slot()			 *//* * 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;    unsigned                lt_time;    int                     nbars;    cfg_p                   wptr;    cfg_p                   pcix_cap;    int                     win;    pciio_space_t           space;    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(pcibr_soft, 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);    /* Try to read the device-id/vendor-id from the config space */    cfgw = pcibr_slot_config_addr(bridge, slot, 0);#if PROBE_LOCK    s = pcibr_lock(pcibr_soft);#endif    if (pcibr_probe_slot(bridge, cfgw, &idword)) 	return(ENODEV);#if PROBE_LOCK    pcibr_unlock(pcibr_soft, s);#endif    slotp = &pcibr_soft->bs_slot[slot];    slotp->slot_status |= SLOT_POWER_UP;    vendor = 0xFFFF & idword;    device = 0xFFFF & (idword >> 16);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PROBE, pcibr_vhdl,		"pcibr_slot_info_init: slot=%d, vendor=0x%x, device=0x%x\n",		PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), vendor, device));    /* If the vendor id is not valid then the slot is not populated     * and we are done.     */    if (vendor == 0xFFFF) 	return(ENODEV);			        htype = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), 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 = pcibr_func_config_addr(bridge, 0, slot, func, 0);#if PROBE_LOCK            s = pcibr_lock(pcibr_soft);#endif	    if (pcibr_probe_slot(bridge, cfgw, &idwords[func])) {		pfail |= 1 << func;		continue;	    }#if PROBE_LOCK            pcibr_unlock(pcibr_soft, s);#endif	    vendor = 0xFFFF & idwords[func];	    if (vendor == 0xFFFF) {		pfail |= 1 << func;		continue;	    }	    nfunc = func + 1;	    rfunc = 0;	}        cfgw = pcibr_slot_config_addr(bridge, slot, 0);    }    NEWA(pcibr_infoh, nfunc);        pcibr_soft->bs_slot[slot].bss_ninfo = nfunc;    pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh;    for (func = 0; func < nfunc; ++func) {	unsigned                cmd_reg;		if (func) {	    if (pfail & (1 << func))		continue;	    	    idword = idwords[func];	    cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0);	    	    device = 0xFFFF & (idword >> 16);	    htype = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_HEADER_TYPE, 1);	    rfunc = func;	}	htype &= 0x7f;	if (htype != 0x00) {	    printk(KERN_WARNING 		"%s pcibr: pci slot %d func %d has strange header type 0x%x\n",		    pcibr_soft->bs_name, slot, func, htype);	    nbars = 2;	} else {	    nbars = PCI_CFG_BASE_ADDRS;	}	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_CONFIG, pcibr_vhdl,                "pcibr_slot_info_init: slot=%d, func=%d, cfgw=0x%x\n",		PCIBR_DEVICE_TO_SLOT(pcibr_soft,slot), func, cfgw));#ifdef PIC_LATER        /*         * Check for a Quad ATM PCI "card" and return all the PCI bus         * memory and I/O space.  This will work-around an apparent         * hardware problem with the Quad ATM XIO card handling large         * PIO addresses.  Releasing all the space for use by the card         * will lower the PIO addresses with the PCI bus address space.         * This is OK since the PROM did not assign any BAR addresses.          *         * Only release all the PCI bus addresses once.         *         */        if ((vendor == LINC_VENDOR_ID_NUM) && (device == LINC_DEVICE_ID_NUM)) {            iopaddr_t               prom_base_addr = pcibr_soft->bs_xid << 24;            int                     prom_base_size = 0x1000000;            if (!(pcibr_soft->bs_bus_addr_status & PCIBR_BUS_ADDR_MEM_FREED)) {		pciio_device_win_populate(&pcibr_soft->bs_mem_win_map,					  prom_base_addr, prom_base_size);                pcibr_soft->bs_bus_addr_status |= PCIBR_BUS_ADDR_MEM_FREED;            }            if (!(pcibr_soft->bs_bus_addr_status & PCIBR_BUS_ADDR_IO_FREED)) {		pciio_device_win_populate(&pcibr_soft->bs_io_win_map,					  prom_base_addr, prom_base_size);                pcibr_soft->bs_bus_addr_status |= PCIBR_BUS_ADDR_IO_FREED;            }        }#endif	/* PIC_LATER */	/* 	 * If the latency timer has already been set, by prom or by the	 * card itself, use that value.  Otherwise look at the device's	 * 'min_gnt' and attempt to calculate a latency time. 	 *	 * NOTE: For now if the device is on the 'real time' arbitration	 * ring we dont set the latency timer.  	 *	 * WAR: SGI's IOC3 and RAD devices target abort if you write a 	 * single byte into their config space.  So don't set the Latency	 * Timer for these devices	 */	lt_time = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_LATENCY_TIMER, 1);	if ((lt_time == 0) && !(bridge->b_device[slot].reg & BRIDGE_DEV_RT) &&	    !((vendor == IOC3_VENDOR_ID_NUM) && 	      (#ifdef PIC_LATER	       (device == IOC3_DEVICE_ID_NUM) ||	       (device == LINC_DEVICE_ID_NUM) ||#endif	       (device == 0x5 /* RAD_DEV */)))) {	     unsigned	min_gnt;	     unsigned	min_gnt_mult;	    	    /* 'min_gnt' indicates how long of a burst period a device	     * needs in increments of 250ns.  But latency timer is in	     * PCI clock cycles, so a conversion is needed.	     */	    min_gnt = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_MIN_GNT, 1);	    if (IS_133MHZ(pcibr_soft))		min_gnt_mult = 32;	/* 250ns @ 133MHz in clocks */	    else if (IS_100MHZ(pcibr_soft))		min_gnt_mult = 24;	/* 250ns @ 100MHz in clocks */	    else if (IS_66MHZ(pcibr_soft))		min_gnt_mult = 16;	/* 250ns @ 66MHz, in clocks */	    else

⌨️ 快捷键说明

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