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

📄 pcibr_error.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * Check if the address was allocated as part of the     * pcibr_piospace_alloc calls.     */    for (s = pcibr_soft->bs_min_slot; s < PCIBR_NUM_SLOTS(pcibr_soft); ++s) {	int                     nf = pcibr_soft->bs_slot[s].bss_ninfo;	pcibr_info_h            pcibr_infoh = pcibr_soft->bs_slot[s].bss_infos;	for (f = 0; f < nf; f++) {	    pcibr_info_t            pcibr_info = pcibr_infoh[f];	    if (!pcibr_info)		continue;	    piosp = pcibr_info->f_piospace;	    while (piosp) {		if ((piosp->start <= pciaddr) &&		    ((piosp->count + piosp->start) > pciaddr)) {		    if (spacep)			*spacep = piosp->space;		    if (offsetp)			*offsetp = pciaddr - piosp->start;		    return s;		}			/* endif match */		piosp = piosp->next;	    }				/* next piosp */	}				/* next func */    }					/* next slot */    /*     * Some other random address on the PCI bus ...     * we have no way of knowing whether this was     * a MEM or I/O access; so, for now, we just     * assume that the low 1G is MEM, the next     * 3G is I/O, and anything above the 4G limit     * is obviously MEM.     */    if (spacep)	*spacep = ((pciaddr < (1ul << 30)) ? PCIIO_SPACE_MEM :		   (pciaddr < (4ul << 30)) ? PCIIO_SPACE_IO :		   PCIIO_SPACE_MEM);    if (offsetp)	*offsetp = pciaddr;    return PCIIO_SLOT_NONE;}voidpcibr_error_cleanup(pcibr_soft_t pcibr_soft, int error_code){    bridge_t               *bridge = pcibr_soft->bs_base;    ASSERT(error_code & IOECODE_PIO);    error_code = error_code;    if (IS_PIC_SOFT(pcibr_soft)) {        bridge->p_int_rst_stat_64 = BRIDGE_IRR_PCI_GRP_CLR |				    PIC_PCIX_GRP_CLR |				    BRIDGE_IRR_MULTI_CLR;    } else {        bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR;    }    (void) bridge->b_wid_tflush;	/* flushbus */}/* * pcibr_error_extract *      Given the 'pcibr vertex handle' find out which slot *      the bridge status error address (from pcibr_soft info *      hanging off the vertex) *      allocated to, and return the slot number. *      While we have the info handy, construct the *      space code and offset as well. * * NOTE: if this routine is called, we don't know whether * the address is in CFG, MEM, or I/O space. We have to guess. * This will be the case on PIO stores, where the only way * we have of getting the address is to check the Bridge, which * stores the PCI address but not the space and not the xtalk * address (from which we could get it). * * XXX- this interface has no way to return the function * number on a multifunction card, even though that data * is available. */pciio_slot_tpcibr_error_extract(devfs_handle_t pcibr_vhdl,		    pciio_space_t *spacep,		    iopaddr_t *offsetp){    pcibr_soft_t            pcibr_soft = 0;    iopaddr_t               bserr_addr;    bridge_t               *bridge;    pciio_slot_t            slot = PCIIO_SLOT_NONE;    arbitrary_info_t	    rev;    /* Do a sanity check as to whether we really got a      * bridge vertex handle.     */    if (hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &rev) !=	GRAPH_SUCCESS) 	return(slot);    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    if (pcibr_soft) {	bridge = pcibr_soft->bs_base;	bserr_addr =	    bridge->b_pci_err_lower |	    ((uint64_t) (bridge->b_pci_err_upper &			   BRIDGE_ERRUPPR_ADDRMASK) << 32);	slot = pcibr_addr_toslot(pcibr_soft, bserr_addr,				 spacep, offsetp, NULL);    }    return slot;}/*ARGSUSED */voidpcibr_device_disable(pcibr_soft_t pcibr_soft, int devnum){    /*     * XXX     * Device failed to handle error. Take steps to     * disable this device ? HOW TO DO IT ?     *     * If there are any Read response buffers associated     * with this device, it's time to get them back!!     *     * We can disassociate any interrupt level associated     * with this device, and disable that interrupt level     *     * For now it's just a place holder     */}/* * pcibr_pioerror *      Handle PIO error that happened at the bridge pointed by pcibr_soft. * *      Queries the Bus interface attached to see if the device driver *      mapping the device-number that caused error can handle the *      situation. If so, it will clean up any error, and return *      indicating the error was handled. If the device driver is unable *      to handle the error, it expects the bus-interface to disable that *      device, and takes any steps needed here to take away any resources *      associated with this device. *//* BEM_ADD_IOE doesn't dump the whole ioerror, it just * decodes the PCI specific portions -- we count on our * callers to dump the raw IOE data. */#define BEM_ADD_IOE(ioe)						\	do {								\	    if (IOERROR_FIELDVALID(ioe, busspace)) {			\		iopaddr_t		spc;				\		iopaddr_t		win;				\		short			widdev;				\		iopaddr_t		busaddr;			\									\		IOERROR_GETVALUE(spc, ioe, busspace);			\		win = spc - PCIIO_SPACE_WIN(0);				\		IOERROR_GETVALUE(busaddr, ioe, busaddr);		\		IOERROR_GETVALUE(widdev, ioe, widgetdev);		\									\		switch (spc) {						\		case PCIIO_SPACE_CFG:					\		    printk("\tPCI Slot %d Func %d CFG space Offset 0x%lx\n",\			    	pciio_widgetdev_slot_get(widdev),	\	    			pciio_widgetdev_func_get(widdev),	\				busaddr);				\		    break;						\		case PCIIO_SPACE_IO:					\		    printk("\tPCI I/O space  Offset 0x%lx\n", busaddr);	\		    break;						\		case PCIIO_SPACE_MEM:					\		case PCIIO_SPACE_MEM32:					\		case PCIIO_SPACE_MEM64:					\		    printk("\tPCI MEM space Offset 0x%lx\n", busaddr);	\		    break;						\		default:						\		    if (win < 6) {					\		    printk("\tPCI Slot %d Func %d Window %ld Offset 0x%lx\n",\	    			pciio_widgetdev_slot_get(widdev),	\	    			pciio_widgetdev_func_get(widdev),	\			    	win,					\			    	busaddr);				\		    }							\		    break;						\		}							\	    }								\	} while (0)/*ARGSUSED */intpcibr_pioerror(		  pcibr_soft_t pcibr_soft,		  int error_code,		  ioerror_mode_t mode,		  ioerror_t *ioe){    int                     retval = IOERROR_HANDLED;    devfs_handle_t            pcibr_vhdl = pcibr_soft->bs_vhdl;    bridge_t               *bridge = pcibr_soft->bs_base;    iopaddr_t               bad_xaddr;    pciio_space_t           raw_space;	/* raw PCI space */    iopaddr_t               raw_paddr;	/* raw PCI address */    pciio_space_t           space;	/* final PCI space */    pciio_slot_t            slot;	/* final PCI slot, if appropriate */    pciio_function_t        func;	/* final PCI func, if appropriate */    iopaddr_t               offset;	/* final PCI offset */        int                     cs, cw, cf;    pciio_space_t           wx;    iopaddr_t               wb;    size_t                  ws;    iopaddr_t               wl;    /*     * We expect to have an "xtalkaddr" coming in,     * and need to construct the slot/space/offset.     */    IOERROR_GETVALUE(bad_xaddr, ioe, xtalkaddr);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn,                "pcibr_pioerror: pcibr_soft=0x%x, bad_xaddr=0x%x\n",		pcibr_soft, bad_xaddr));    slot = PCIIO_SLOT_NONE;    func = PCIIO_FUNC_NONE;    raw_space = PCIIO_SPACE_NONE;    raw_paddr = 0;    if ((bad_xaddr >= PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft)) &&	(bad_xaddr < PCIBR_TYPE1_CFG(pcibr_soft))) {	raw_paddr = bad_xaddr - PCIBR_BUS_TYPE0_CFG_DEV0(pcibr_soft);	slot = raw_paddr / BRIDGE_TYPE0_CFG_SLOT_OFF;	raw_paddr = raw_paddr % BRIDGE_TYPE0_CFG_SLOT_OFF;	raw_space = PCIIO_SPACE_CFG;    }    if ((bad_xaddr >= PCIBR_TYPE1_CFG(pcibr_soft)) &&	(bad_xaddr < (PCIBR_TYPE1_CFG(pcibr_soft) + 0x1000))) {	/* Type 1 config space:	 * slot and function numbers not known.	 * Perhaps we can read them back?	 */	raw_paddr = bad_xaddr - PCIBR_TYPE1_CFG(pcibr_soft);	raw_space = PCIIO_SPACE_CFG;    }    if ((bad_xaddr >= PCIBR_BRIDGE_DEVIO0(pcibr_soft)) &&	(bad_xaddr < PCIBR_BRIDGE_DEVIO(pcibr_soft, BRIDGE_DEV_CNT))) {	int                     x;	raw_paddr = bad_xaddr - PCIBR_BRIDGE_DEVIO0(pcibr_soft);	x = raw_paddr / BRIDGE_DEVIO_OFF;	raw_paddr %= BRIDGE_DEVIO_OFF;	/* first two devio windows are double-sized */	if ((x == 1) || (x == 3))	    raw_paddr += BRIDGE_DEVIO_OFF;	if (x > 0)	    x--;	if (x > 1)	    x--;	/* x is which devio reg; no guarantee	 * PCI slot x will be responding.	 * still need to figure out who decodes	 * space/offset on the bus.	 */	raw_space = pcibr_soft->bs_slot[x].bss_devio.bssd_space;	if (raw_space == PCIIO_SPACE_NONE) {	    /* Someone got an error because they	     * accessed the PCI bus via a DevIO(x)	     * window that pcibr has not yet assigned	     * to any specific PCI address. It is	     * quite possible that the Device(x)	     * register has been changed since they	     * made their access, but we will give it	     * our best decode shot.	     */	    raw_space = pcibr_soft->bs_slot[x].bss_device		& BRIDGE_DEV_DEV_IO_MEM		? PCIIO_SPACE_MEM		: PCIIO_SPACE_IO;	    raw_paddr +=		(pcibr_soft->bs_slot[x].bss_device &		 BRIDGE_DEV_OFF_MASK) <<		BRIDGE_DEV_OFF_ADDR_SHFT;	} else	    raw_paddr += pcibr_soft->bs_slot[x].bss_devio.bssd_base;    }    if ((bad_xaddr >= BRIDGE_PCI_MEM32_BASE) &&	(bad_xaddr <= BRIDGE_PCI_MEM32_LIMIT)) {	raw_space = PCIIO_SPACE_MEM32;	raw_paddr = bad_xaddr - BRIDGE_PCI_MEM32_BASE;    }    if ((bad_xaddr >= BRIDGE_PCI_MEM64_BASE) &&	(bad_xaddr <= BRIDGE_PCI_MEM64_LIMIT)) {	raw_space = PCIIO_SPACE_MEM64;	raw_paddr = bad_xaddr - BRIDGE_PCI_MEM64_BASE;    }    if ((bad_xaddr >= BRIDGE_PCI_IO_BASE) &&	(bad_xaddr <= BRIDGE_PCI_IO_LIMIT)) {	raw_space = PCIIO_SPACE_IO;	raw_paddr = bad_xaddr - BRIDGE_PCI_IO_BASE;    }    space = raw_space;    offset = raw_paddr;    if ((slot == PCIIO_SLOT_NONE) && (space != PCIIO_SPACE_NONE)) {	/* we've got a space/offset but not which	 * PCI slot decodes it. Check through our	 * notions of which devices decode where.	 *	 * Yes, this "duplicates" some logic in	 * pcibr_addr_toslot; the difference is,	 * this code knows which space we are in,	 * and can really really tell what is	 * going on (no guessing).	 */	for (cs = pcibr_soft->bs_min_slot; 		(cs < PCIBR_NUM_SLOTS(pcibr_soft)) && 					(slot == PCIIO_SLOT_NONE); cs++) {	    int                     nf = pcibr_soft->bs_slot[cs].bss_ninfo;	    pcibr_info_h            pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;	    for (cf = 0; (cf < nf) && (slot == PCIIO_SLOT_NONE); cf++) {		pcibr_info_t            pcibr_info = pcibr_infoh[cf];		if (!pcibr_info)		    continue;		for (cw = 0; (cw < 6) && (slot == PCIIO_SLOT_NONE); ++cw) {		    if (((wx = pcibr_info->f_window[cw].w_space) != PCIIO_SPACE_NONE) &&			((wb = pcibr_info->f_window[cw].w_base) != 0) &&			((ws = pcibr_info->f_window[cw].w_size) != 0) &&			((wl = wb + ws) > wb) &&			((wb <= offset) && (wl > offset))) {			/* MEM, MEM32 and MEM64 need to			 * compare as equal ...			 */			if ((wx == space) ||			    (((wx == PCIIO_SPACE_MEM) ||			      (wx == PCIIO_SPACE_MEM32) ||			      (wx == PCIIO_SPACE_MEM64)) &&			     ((space == PCIIO_SPACE_MEM) ||			      (space == PCIIO_SPACE_MEM32) ||			      (space == PCIIO_SPACE_MEM64)))) {			    slot = cs;			    func = cf;			    space = PCIIO_SPACE_WIN(cw);			    offset -= wb;			}		/* endif window space match */		    }			/* endif window valid and addr match */		}			/* next window unless slot set */	    }				/* next func unless slot set */	}				/* next slot unless slot set */	/* XXX- if slot is still -1, no PCI devices are	 * decoding here using their standard PCI BASE	 * registers. This would be a really good place	 * to cross-coordinate with the pciio PCI	 * address space allocation routines, to find	 * out if this address is "allocated" by any of	 * our subsidiary devices.	 */    }    /* Scan all piomap records on this PCI bus to update     * the TimeOut Counters on all matching maps. If we     * don't already know the slot number, take it from     * the first matching piomap. Note that we have to     * compare maps against raw_space and raw_paddr     * since space and offset could already be     * window-relative.     *     * There is a chance that one CPU could update     * through this path, and another CPU could also     * update due to an interrupt. Closing this hole     * would only result in the possibility of some     * errors never getting logged at all, and since the     * use for bp_toc is as a logical test rather than a     * strict count, the excess counts are not a     * problem.     */    for (cs = pcibr_soft->bs_min_slot; 				cs < PCIBR_NUM_SLOTS(pcibr_soft); ++cs) {	int 		nf = pcibr_soft->bs_slot[cs].bss_ninfo;	pcibr_info_h	pcibr_infoh = pcibr_soft->bs_slot[cs].bss_infos;	for (cf = 0; cf < nf; cf++) {	    pcibr_info_t 	pcibr_info = pcibr_infoh[cf];	    pcibr_piomap_t	map;    	    if (!pcibr_info)		continue;	    for (map = pcibr_info->f_piomap;	     map != NULL; map = map->bp_next) {	    wx = map->bp_space;

⌨️ 快捷键说明

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