📄 pciiomaplib.c
字号:
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/
STATUS pciConfigOutByte
(
int busNo, /* bus number */
int deviceNo, /* device number */
int funcNo, /* function number */
int offset, /* offset into the configuration space */
char data /* data written to the offset */
)
{
UINT32 retval;
int mask = 0x000000ff;
int key;
int n;
UINT32 addr;
if (pciLibInitStatus != OK) /* sanity check */
return (ERROR);
key = intLock (); /* mutual exclusion start */
switch (pciConfigMech)
{
case PCI_MECHANISM_1:
PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
(offset & 0xfc) | 0x80000000);
PCI_OUT_BYTE ((pciConfigAddr1 + (offset & 0x3)), data);
break;
case PCI_MECHANISM_2:
PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
PCI_OUT_BYTE (pciConfigAddr1, busNo);
retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
(offset & 0xfc));
data = (data & mask) << ((offset & 0x03) * 8);
mask <<= (offset & 0x03) * 8;
retval = (retval & ~mask) | data;
PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
(offset & 0xfc)), retval);
PCI_OUT_BYTE (pciConfigAddr0, 0);
break;
case PCI_MECHANISM_3:
n = offset % 4;
IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */
addr = ((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3));
retval = PCI_IN_LONG (addr);
retval &= ~(0xFF << (n*8));
retval |= (data << (n*8));
PCI_OUT_LONG (addr, retval);
CLR_IDSEL; /* Clear IDSEL Lines */
break;
default:
break;
}
intUnlock (key); /* mutual exclusion stop */
return (OK);
}
/*******************************************************************************
*
* pciConfigOutWord - write one 16-bit word to the PCI configuration space
*
* This routine writes one 16-bit word to the PCI configuration space.
*
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/
STATUS pciConfigOutWord
(
int busNo, /* bus number */
int deviceNo, /* device number */
int funcNo, /* function number */
int offset, /* offset into the configuration space */
short data /* data written to the offset */
)
{
UINT32 retval;
int mask = 0x0000ffff;
int key;
int n;
UINT32 addr;
if (pciLibInitStatus != OK) /* sanity check */
return (ERROR);
key = intLock (); /* mutual exclusion start */
switch (pciConfigMech)
{
case PCI_MECHANISM_1:
PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
(offset & 0xfc) | 0x80000000);
PCI_OUT_WORD ((pciConfigAddr1 + (offset & 0x2)), data);
break;
case PCI_MECHANISM_2:
PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
PCI_OUT_BYTE (pciConfigAddr1, busNo);
retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
(offset & 0xfc));
data = (data & mask) << ((offset & 0x02) * 8);
mask <<= (offset & 0x02) * 8;
retval = (retval & ~mask) | data;
PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
(offset & 0xfc)), retval);
PCI_OUT_BYTE (pciConfigAddr0, 0);
break;
case PCI_MECHANISM_3:
n = offset % 4;
IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */
addr = ((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3));
retval = PCI_IN_LONG (addr);
retval &= ~(0xFFFF << (n*8));
retval |= (data << n*8);
PCI_OUT_LONG (addr, retval);
CLR_IDSEL; /* Clear IDSEL Lines */
break;
default:
break;
}
intUnlock (key); /* mutual exclusion stop */
return (OK);
}
/*******************************************************************************
*
* pciConfigOutLong - write one longword to the PCI configuration space
*
* This routine writes one longword to the PCI configuration space.
*
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/
STATUS pciConfigOutLong
(
int busNo, /* bus number */
int deviceNo, /* device number */
int funcNo, /* function number */
int offset, /* offset into the configuration space */
int data /* data written to the offset */
)
{
int key;
if (pciLibInitStatus != OK) /* sanity check */
return (ERROR);
key = intLock (); /* mutual exclusion start */
switch (pciConfigMech)
{
case PCI_MECHANISM_1:
PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
(offset & 0xfc) | 0x80000000);
PCI_OUT_LONG (pciConfigAddr1, data);
break;
case PCI_MECHANISM_2:
PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
PCI_OUT_BYTE (pciConfigAddr1, busNo);
PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
(offset & 0xfc)), data);
PCI_OUT_BYTE (pciConfigAddr0, 0);
break;
case PCI_MECHANISM_3:
IDSEL(busNo, deviceNo); /* Setup IDSEL Lines */
PCI_OUT_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
MAKE_CFG_ADDR(busNo, deviceNo, funcNo, offset), data);
CLR_IDSEL; /* Clear IDSEL Lines */
break;
default:
break;
}
intUnlock (key); /* mutual exclusion stop */
return (OK);
}
/*******************************************************************************
*
* pciSpecialCycle - generate a special cycle with a message
*
* This routine generates a special cycle with a message.
*
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/
STATUS pciSpecialCycle
(
int busNo, /* bus number */
int message /* data on AD[31:0] during the special cycle */
)
{
int deviceNo = 0x0000001f;
int funcNo = 0x00000007;
int key;
if (pciLibInitStatus != OK) /* sanity check */
return (ERROR);
key = intLock (); /* mutual exclusion start */
switch (pciConfigMech)
{
case PCI_MECHANISM_1:
PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
0x80000000);
PCI_OUT_LONG (pciConfigAddr1, message);
break;
case PCI_MECHANISM_2:
PCI_OUT_BYTE (pciConfigAddr0, 0xff);
PCI_OUT_BYTE (pciConfigAddr1, 0x00);
PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8)),
message);
PCI_OUT_BYTE (pciConfigAddr0, 0);
break;
default:
break;
}
intUnlock (key); /* mutual exclusion stop */
return (OK);
}
/*******************************************************************************
*
* 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 execute all
* interrupt handlers in the link list.
*
* RETURNS: N/A
*
*/
VOID pciInt
(
int irq /* IRQ associated to the PCI interrupt */
)
{
PCI_INT_RTN *pRtn;
for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
(* pRtn->routine) (pRtn->parameter);
}
/*******************************************************************************
*
* pciIntConnect - connect the interrupt handler to the PCI interrupt.
*
* This routine connects an interrupt handler to the PCI interrupt line(A - D).
* Link list is created if multiple handlers are assigned to the single PCI
* interrupt.
*
* RETURNS:
* OK, or ERROR if the interrupt handler cannot be built.
*
*/
STATUS pciIntConnect
(
VOIDFUNCPTR *vector, /* interrupt vector to attach to */
VOIDFUNCPTR routine, /* routine to be called */
int parameter /* parameter to be passed to routine */
)
{
int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;
PCI_INT_RTN *pRtn;
int oldLevel;
if (pciLibInitStatus != OK)
return (ERROR);
pRtn = (PCI_INT_RTN *)malloc (sizeof (PCI_INT_RTN));
if (pRtn == NULL)
return (ERROR);
pRtn->routine = routine;
pRtn->parameter = parameter;
oldLevel = intLock (); /* LOCK INTERRUPT */
dllAdd (&pciIntList[irq], &pRtn->node);
intUnlock (oldLevel); /* UNLOCK INTERRUPT */
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.
*
*/
STATUS pciIntDisconnect
(
VOIDFUNCPTR *vector, /* interrupt vector to attach to */
VOIDFUNCPTR routine /* routine to be called */
)
{
int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;
PCI_INT_RTN *pRtn;
int oldLevel;
if (pciLibInitStatus != OK)
return (ERROR);
for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
{
if (pRtn->routine == routine)
{
oldLevel = intLock (); /* LOCK INTERRUPT */
dllRemove (&pciIntList[irq], &pRtn->node);
intUnlock (oldLevel); /* UNLOCK INTERRUPT */
free ((char *)pRtn);
return (OK);
}
}
return (ERROR);
}
#endif /* defined(INCLUDE_PCI) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -