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

📄 pcibr_error.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (f = 0; f < nf; f++) {	    pcibr_info_t            pcibr_info = pcibr_infoh[f];	    if (!pcibr_info)		continue;	    for (w = 0; w < 6; w++) {		if (pcibr_info->f_window[w].w_space		    == PCIIO_SPACE_NONE) {		    continue;		}		base = pcibr_info->f_window[w].w_base;		size = pcibr_info->f_window[w].w_size;		if ((pciaddr >= base) && (pciaddr < (base + size))) {		    if (spacep)			*spacep = PCIIO_SPACE_WIN(w);		    if (offsetp)			*offsetp = pciaddr - base;		    if (funcp)			*funcp = f;		    return s;		}			/* endif match */	    }				/* next window */	}				/* next func */    }					/* next slot */    /*     * Check if the address was allocated as part of the     * pcibr_piospace_alloc calls.     */    for (s = 0; s < 8; 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;    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. */#define BEM_ADD_STR(s)	printk("%s", (s))#define BEM_ADD_VAR(v)	printk("\t%20s: 0x%x\n", #v, (v))#define BEM_ADD_REG(r)	printk("\t%20s: %R\n", #r, (r), r ## _desc)#define BEM_ADD_NSPC(n,s)	printk("\t%20s: %R\n", n, s, space_desc)#define BEM_ADD_SPC(s)		BEM_ADD_NSPC(#s, s)/* 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)) {			\		unsigned		spc;				\		unsigned		win;				\									\		spc = IOERROR_GETVALUE(ioe, busspace);			\		win = spc - PCIIO_SPACE_WIN(0);				\									\		switch (spc) {						\		case PCIIO_SPACE_CFG:					\		    printk(					\			    "\tPCI Slot %d Func %d CFG space Offset 0x%x\n",	\	    pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)),	\	    pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)),	\			    IOERROR_GETVALUE(ioe, busaddr));		\		    break;						\		case PCIIO_SPACE_IO:					\		    printk(					\			    "\tPCI I/O space  Offset 0x%x\n",		\			    IOERROR_GETVALUE(ioe, busaddr));		\		    break;						\		case PCIIO_SPACE_MEM:					\		case PCIIO_SPACE_MEM32:					\		case PCIIO_SPACE_MEM64:					\		    printk(					\			    "\tPCI MEM space Offset 0x%x\n",		\			    IOERROR_GETVALUE(ioe, busaddr));		\		    break;						\		default:						\		    if (win < 6) {					\		    printk(					\			    "\tPCI Slot %d Func %d Window %d Offset 0x%x\n",\	    pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, widgetdev)),	\	    pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, widgetdev)),	\			    win,					\			    IOERROR_GETVALUE(ioe, 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.     */    bad_xaddr = IOERROR_GETVALUE(ioe, xtalkaddr);    slot = PCIIO_SLOT_NONE;    func = PCIIO_FUNC_NONE;    raw_space = PCIIO_SPACE_NONE;    raw_paddr = 0;    if ((bad_xaddr >= BRIDGE_TYPE0_CFG_DEV0) &&	(bad_xaddr < BRIDGE_TYPE1_CFG)) {	raw_paddr = bad_xaddr - BRIDGE_TYPE0_CFG_DEV0;	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 >= BRIDGE_TYPE1_CFG) &&	(bad_xaddr < (BRIDGE_TYPE1_CFG + 0x1000))) {	/* Type 1 config space:	 * slot and function numbers not known.	 * Perhaps we can read them back?	 */	raw_paddr = bad_xaddr - BRIDGE_TYPE1_CFG;	raw_space = PCIIO_SPACE_CFG;    }    if ((bad_xaddr >= BRIDGE_DEVIO0) &&	(bad_xaddr < BRIDGE_DEVIO(BRIDGE_DEV_CNT))) {	int                     x;	raw_paddr = bad_xaddr - BRIDGE_DEVIO0;	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 = 0; (cs < 8) && (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 = 0; cs < 8; ++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;	    wb = map->bp_pciaddr;	    ws = map->bp_mapsz;	    cw = wx - PCIIO_SPACE_WIN(0);	    if (cw < 6) {		wb += pcibr_soft->bs_slot[cs].bss_window[cw].bssw_base;		wx = pcibr_soft->bs_slot[cs].bss_window[cw].bssw_space;

⌨️ 快捷键说明

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