📄 ixp425pciintlib.c
字号:
/* ixp425PciIntLib.c - PCI interrupts driver for the IXP425 *//* Copyright 2002 Wind River Systems, Inc. *//*modification history--------------------01b,14aug03,scm remove diab warnings...01a,05jun02,jb initial version...*//*DESCRIPTIONThis code handles the PCI Interrupts INTA#...INTD#. The code herein permits client code to bind to these interrupts, and handles the invocation of attached routines when the associated interrupt goes off. In addition to the standard PCI interrupts, this module provides services for handling interrupts associated with error conditions in the PCI controller.In order for the functionality defined herein to be available, INCLUDE_PCI must be defined in config.h.SH INITIALIZATIONThe function sysPciInit(), which should be called fromsysHwInit() to initialize the PCI unit on the IXP425.The function sysPciAssignAddrs() should be called from sysHwInit() after the call to sysPciInit to initialise devices on the PCI bus.INCLUDE FILES:ixp425Pci.h ixp425Pci_p.hSEE ALSO:.I "PCI Local Bus Specification, Revision 2.2, December 18, 1998"ixp425Pci.c*/#include "vxWorks.h"#include "config.h" #include "dllLib.h" #include "stdio.h"#include "ixp425Pci.h"#include "ixp425Pci_p.h"extern void pciAtpIsr (int param);extern void pciPtaIsr (int param);LOCAL UINT32 pciInternalIsrInvocations = 0;LOCAL UINT32 pciIsrInvocations = 0;DL_LIST pciIntList[PCI_IRQ_LINES]; /* linked list of int handlers */DL_LIST pciCallbackList; /* linked list of callback error handlers *//********************************************************************************* pciInt - interrupt handler for shared PCI interrupt.** This routine executes multiple interrupt handlers for a PCI interrupt.* Each interrupt handler must check the device dependent interrupt status bit* to determine the source of the interrupt, since it simply executes all* interrupt handlers in the link list.** RETURNS: N/A**/voidpciInt (UINT32 pciIntIndex) { PCI_INT_RTN *pRtn; for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[pciIntIndex]); pRtn != NULL; pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node)) { (* pRtn->routine) (pRtn->parameter); } /*clear the status in the GPIO ISR*/ if(pciIntIndex == IXP425_PCI_INTA_INDEX) { ixp425GPIOIntStatusClear(IXP425_PCI_INTA_PIN); } else if(pciIntIndex == IXP425_PCI_INTB_INDEX) { ixp425GPIOIntStatusClear(IXP425_PCI_INTB_PIN); } else if(pciIntIndex == IXP425_PCI_INTC_INDEX) { ixp425GPIOIntStatusClear(IXP425_PCI_INTC_PIN); } else if(pciIntIndex == IXP425_PCI_INTD_INDEX) { ixp425GPIOIntStatusClear(IXP425_PCI_INTD_PIN); } pciIsrInvocations++;}/********************************************************************************* pciIntConnect - connect the interrupt handler to the PCI interrupt.** This routine connects an interrupt handler to the PCI interrupt line (A - D).** RETURNS:* OK, or ERROR if there is insufficient memory to store the interrupt descriptor.**/STATUS pciIntConnect (VOIDFUNCPTR *vector, /* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ UINT32 parameter) /* parameter to be passed to routine */ { UINT32 irq = IVEC_TO_INUM ((UINT32)vector); UINT32 index; PCI_INT_RTN *pRtn; UINT32 key; if (pciLibInitStatus != OK) { return (ERROR); } pRtn = (PCI_INT_RTN *)malloc (sizeof (PCI_INT_RTN)); if (pRtn == NULL) { return (ERROR); } switch (irq) { case IXP425_PCI_INTA_INTERRUPT_NUM: index = IXP425_PCI_INTA_INDEX; break; case IXP425_PCI_INTB_INTERRUPT_NUM: index = IXP425_PCI_INTB_INDEX; break; case IXP425_PCI_INTC_INTERRUPT_NUM: index = IXP425_PCI_INTC_INDEX; break; case IXP425_PCI_INTD_INTERRUPT_NUM: index = IXP425_PCI_INTD_INDEX; break; default: return (ERROR); } pRtn->routine = routine; pRtn->parameter = parameter; key = intLock (); dllAdd (&pciIntList[index], &pRtn->node); intUnlock (key); return (OK);}/********************************************************************************* pciIntDisconnect - disconnect the interrupt handler from the PCI interrupt.** This routine disconnects the interrupt handler from the PCI interrupt line.** RETURNS:* OK, or ERROR if the interrupt handler cannot be removed/does not exist in the list.**/STATUS pciIntDisconnect (VOIDFUNCPTR *vector, /* interrupt vector to attach to */ VOIDFUNCPTR routine) /* routine to be called */ { UINT32 irq = IVEC_TO_INUM ((UINT32)vector); PCI_INT_RTN *pRtn; UINT32 key; UINT32 index; if (pciLibInitStatus != OK) { return (ERROR); } switch (irq) { case IXP425_PCI_INTA_INTERRUPT_NUM: index = IXP425_PCI_INTA_INDEX; break; case IXP425_PCI_INTB_INTERRUPT_NUM: index = IXP425_PCI_INTB_INDEX; break; case IXP425_PCI_INTC_INTERRUPT_NUM: index = IXP425_PCI_INTC_INDEX; break; case IXP425_PCI_INTD_INTERRUPT_NUM: index = IXP425_PCI_INTD_INDEX; break; default: return (ERROR); } for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[index]); pRtn != NULL; pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node)) { if (pRtn->routine == routine) { key = intLock (); dllRemove (&pciIntList[index], &pRtn->node); intUnlock (key); free ((UINT8 *)pRtn); return (OK); } } return (ERROR);}/********************************************************************************* pciInternalIsr - interrupt handler for internal PCI interrupt.** This routine handles the internal PCI interrupt by invoking all registered* callbacks and then attempting to clear the error condition.* RETURNS: N/A**/void pciInternalIsr (UINT32 irq) { PCI_CALLBACK_INT_RTN *pRtn; PciStatus status=OK; UINT32 regval; REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, regval); #ifdef INCLUDE_PCI_DMA /*fast path the dma interrupts*/ if (regval & PCI_ISR_APDC) { /*Invoke ATP DMA ISR*/ pciAtpIsr(0); status = PCI_APDC; } else if (regval & PCI_ISR_PADC) { /*Invoke PTA DMA ISR*/ pciPtaIsr(0); status = PCI_PADC; } else#endif { if (regval & PCI_ISR_PSE) { status = PCI_ERR_PSE; } else if (regval & PCI_ISR_PFE) { status = PCI_ERR_PFE; } else if (regval & PCI_ISR_PPE) { status = PCI_ERR_PPE; } else if (regval & PCI_ISR_AHBE) { status = PCI_ERR_AHBE; } for (pRtn = (PCI_CALLBACK_INT_RTN *)DLL_FIRST (&pciCallbackList); pRtn != NULL; pRtn = (PCI_CALLBACK_INT_RTN *)DLL_NEXT (&pRtn->node)) { (* pRtn->routine) (status, 0); } } /*store the error status for display from another function*/ lastError=status; /*clear the error status in pci_isr, note that pci_isr is "write one to clear" for all error indicators, and read only otherwise, so this works ok.*/ REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, regval); pciInternalIsrInvocations++; }/********************************************************************************* pciErrorCallbackRegister - connect the interrupt handler to the PCI pcc_int** This routine connects an interrupt handler to the PCI internal interrupt pcc_int** RETURNS:* OK, or ERROR if there is insufficient memory to store the interrupt descriptor**/STATUS pciErrorCallbackRegister (PCICALLBACKFUNC routine){ PCI_CALLBACK_INT_RTN *pRtn; UINT32 key; if (pciLibInitStatus != OK) { return (ERROR); } pRtn = (PCI_CALLBACK_INT_RTN *)malloc (sizeof (PCI_CALLBACK_INT_RTN)); if (pRtn == NULL) { return (ERROR); } pRtn->routine = routine; key = intLock (); dllAdd (&pciCallbackList, &pRtn->node); intUnlock (key); return (OK);}/********************************************************************************* pciIntShow - Display statistics relating to PCI interrupts** This routine displays statistics such as the number of invocations of the * PCI internal ISR, and the PCI ISR which dispatches INTA..INTD.**/voidpciIntShow(){ UINT32 i; printf("IXP425 PCI interrupt statistics:\n"); printf("Number of invocations of the INTA..INTD ISR: %d\n", pciIsrInvocations); printf("Number of invocations of the internal ISR: %d\n", pciInternalIsrInvocations); if (pciInternalIsrInvocations > 0) { printf ("Last error code handled by the internal ISR: %d\n", lastError); } printf ("Number of error interrupt callbacks registered is: %d\n", dllCount(&pciCallbackList)); for (i=0; i < PCI_IRQ_LINES; i++) { printf ("Number of callbacks registered for PCI interrupt %d is %d\n", i, dllCount(&pciIntList[i])); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -