📄 xllp_ethernet.c
字号:
Output Arguments:
None
Return Value:
None
*******************************************************************************/
static
void XllpEthernetInterruptHandler(void)
{
XLLP_UINT8_T intStatus, maskRegister, wBankSave;
wBankSave = XllpEthernetReadByte( XLLP_LAN91C111_BANK_SELECT );
// Get the Interrupt Status Register.
XllpEthernetSelectRegisterBank (BANK2);
intStatus = XllpEthernetReadByte(XLLP_LAN91C111_INT_STATS);
// Get the Interrupt Mask Register.
maskRegister = XllpEthernetReadByte(XLLP_LAN91C111_INT_MASK);
// Disable interrupts.
XllpEthernetWriteByte(0, XLLP_LAN91C111_INT_MASK);
// Check for receive overrun errors
if (intStatus & XLLP_LAN91C111_IST_RX_OVRN_INT)
{
DM_CwDbgPrintf(DM_CW_LAN91C111_1, " Error Rx overrun");
// Acknowledge the Receive Overrun interrupt.
XllpEthernetWriteByte(XLLP_LAN91C111_ACK_RX_OVRN_INT, XLLP_LAN91C111_INT_ACK);
LOGERROR(&loggedError,
ERR_L_LAN91C111, ERR_S_RECEIVE, ERR_T_NORECEIVE,
intStatus, 0, 0);
}
// Check for receive interrupt.
if (intStatus & XLLP_LAN91C111_IST_RCV_INT)
{
// Set the flag indicating a frame has been received.
XllpEthernetSetRxIntFlag(XLLP_TRUE);
// Clear the Receive Interrupt bit mask.
maskRegister &= ~XLLP_LAN91C111_MSK_RCV_INT;
}
// Update the Interrupt Mask Register.
XllpEthernetWriteByte(maskRegister, XLLP_LAN91C111_INT_MASK);
XllpEthernetWriteByte(wBankSave, XLLP_LAN91C111_BANK_SELECT);
}
/******************************************************************************
Function Name:
XllpEthernetReceivePacket
Description:
This function receives a packet of data, gets the frame data and places
the data into the user's buffer
Global Register Modified:
None
Input Arguments:
P_XLLP_UINT32_T buffer - a data buffer where the frame data will be stored
Output Arguments:
P_XLLP_INT rxCount - a number of bytes received in the frame
Return Value:
XLLP_UINT32_T - error code if frame has not been received correctly, zero if success.
*******************************************************************************/
XLLP_UINT32_T XllpEthernetReceivePacket(P_XLLP_UINT32_T buffer, P_XLLP_INT32_T rxCount)
{
XLLP_UINT16_T statusWord, wControlWord;
XLLP_UINT16_T frameType;
XLLP_UINT16_T x = 0;
P_XLLP_UINT16_T dataP;
XLLP_UINT16_T count = 0;
XLLP_BOOL_T fDropFrame = XLLP_FALSE;
XLLP_UINT16_T wPointerRegVal;
// Notes:
// The ODDFRM bit in the Receive Frame Status word and the ODD bit in the Control Byte
// DO NOT function properly with Revision A of the LAN91C111 chip.
// These bits are always clear regardless of the number of bytes in the received frame.
// It is not set when the received frame has an odd number of bytes.
// If the Pointer Register's AUTO INCR bit is set to auto-increment on the accesses
// to the Data Register, the care should be taken to the fact that it will increment
// by one on every byte access, by two on every word access, and by four on every
// double word access to the Data Register. The problem is that on each 16-bit access
// to the Data register the XScale chip would make two, 16-bit reads from the
// Ethernet Controller, and the Pointer register would be incremented by four.
// The solution would be not to use AUTO INCR fearture or to use 32-bit access,
// and take care of the frames that are not multiple of four.
// The 32-bit reads, most likely, will give us a maximum performance.
// Clear the error log.
loggedError = 0;
XllpEthernetSetRxIntFlag(XLLP_FALSE);
// Check for received frames.
XllpEthernetInterruptHandler();
// Process all received frames.
if (RxFlag)
{
// Setup for Receive, Auto Increment and Read access.
XllpEthernetSelectRegisterBank (BANK2);
wPointerRegVal = XLLP_LAN91C111_PTR_RX_FRAME_NO_AUTO_INC;
XllpEthernetWriteWord(wPointerRegVal, XLLP_LAN91C111_POINTER);
// Get status word.
statusWord = XllpEthernetReadWord16(XLLP_LAN91C111_DATA_HIGH);
wPointerRegVal += 2;
// Check for broadcast frames.
if (statusWord & XLLP_LAN91C111_FRAME_FILTER)
{
fDropFrame = XLLP_TRUE;
}
else
{
fDropFrame = XLLP_FALSE;
// Process the frame, get the pointer to the user buffer.
dataP = (P_XLLP_UINT16_T)buffer;
XllpEthernetWriteWord(wPointerRegVal, XLLP_LAN91C111_POINTER);
// Get the packet byte count, which is the byte count minus the
// status word, byte count and control byte.
*rxCount = (XLLP_UINT16_T)((XllpEthernetReadWord16(XLLP_LAN91C111_DATA_HIGH) & 0x7FF) - 6);
wPointerRegVal += 2;
// Check we have enough room to store the receive packet.
if (*rxCount > XLLP_ETHERNET_MAX_LENGTH)
{
fDropFrame = XLLP_TRUE;
goto ReleaseFrame;
}
x = 0;
// Filter out all broadcast packets except ARPs.
if(statusWord & XLLP_LAN91C111_BROD_CAST)
{
// Get the ethernet frame header
for (; x < sizeof(EthernetFrameHeader); x++)
{
XllpEthernetWriteWord(wPointerRegVal, XLLP_LAN91C111_POINTER);
*dataP++ = XllpEthernetReadWord16(XLLP_LAN91C111_DATA_HIGH);
wPointerRegVal += 2;
}
// Check the protocol type.
frameType = ntohs(((XllpEthernetHeaderT *)buffer)->frameType);
if ((frameType != XLLP_ETHERNET_TYPE_ARP) && (frameType != XLLP_ETHERNET_TYPE_IP))
{
fDropFrame = XLLP_TRUE;
goto ReleaseFrame;
}
}
for (; x < (*rxCount >> 1); x++)
{
XllpEthernetWriteWord(wPointerRegVal, XLLP_LAN91C111_POINTER);
*dataP++ = XllpEthernetReadWord16(XLLP_LAN91C111_DATA_HIGH);
wPointerRegVal += 2;
}
XllpEthernetWriteWord(wPointerRegVal, XLLP_LAN91C111_POINTER);
wControlWord = XllpEthernetReadWord16(XLLP_LAN91C111_DATA_HIGH);
wPointerRegVal += 2;
if (wControlWord & 0x2000)
{
*dataP = (XLLP_UINT8_T)wControlWord;
(*rxCount)++;
} else if (statusWord & XLLP_LAN91C111_ODD_FRM)
{
*dataP = (XLLP_UINT8_T)wControlWord;
(*rxCount)++;
}
}
ReleaseFrame:
// Now deallocate the page.
XllpEthernetDeallocateRxPacket();
// Re-enable RX interrupts if using them.
if (wIntMask & XLLP_LAN91C111_MSK_RCV_INT)
{
XllpEthernetEnableRxInterrupt();
}
XllpEthernetSetRxIntFlag(XLLP_FALSE);
// Check for errors.
if (statusWord & XLLP_LAN91C111_TOO_SHORT)
{
DM_CwDbgPrintf(DM_CW_LAN91C111_1, " Rx Frame too short");
LOGERROR(&loggedError,
ERR_L_LAN91C111, ERR_S_RECEIVE, ERR_T_BADRANGE,
statusWord, 0, 1);
}
if (statusWord & XLLP_LAN91C111_TOO_LONG)
{
DM_CwDbgPrintf(DM_CW_LAN91C111_1, " Rx Frame too long");
LOGERROR(&loggedError,
ERR_L_LAN91C111, ERR_S_RECEIVE, ERR_T_BADRANGE,
statusWord, 0, 2);
}
if (statusWord & XLLP_LAN91C111_BAD_CRC)
{
DM_CwDbgPrintf(DM_CW_LAN91C111_1, " Rx Frame Bad CRC");
LOGERROR(&loggedError,
ERR_L_LAN91C111, ERR_S_RECEIVE, ERR_T_CRC,
statusWord, 0, 3);
}
if (statusWord & XLLP_LAN91C111_ALGN_ERR)
{
DM_CwDbgPrintf(DM_CW_LAN91C111_1, " Rx Frame Align Error");
LOGERROR(&loggedError,
ERR_L_LAN91C111, ERR_S_RECEIVE, ERR_T_ILLALIGN,
statusWord, 0, 4);
}
// Check dump flag.
if (dumpFlag)
{
// Display received frame.
printf(" Receive Packet:\r\n");
XllpEthernetDumpFrame((P_XLLP_UINT8_T)buffer, count - XLLP_ETHERNET_CRC_LEN);
}
if(!fDropFrame)
{
// Take away CRC value.
//
// Return the receive count.
*rxCount -= XLLP_ETHERNET_CRC_LEN;
return (0);
}
}
*rxCount = 0;
return (0);
}
/******************************************************************************
Function Name:
XllpEthernetDumpRegisters
Description:
This function prints the information from the ethernet controller registers
Global Register Modified:
Ethernet Bank Select Register
Input Arguments:
None
Output Arguments:
None
Return Value:
None
*******************************************************************************/
void XllpEthernetDumpRegisters(void)
{
P_XLLP_VUINT32_T ioRegsP = XllpEthernetGetPointerToIORegistersBase(); // Get pointer to I/O space
XLLP_UINT16_T bank0, bank1, bank2, bank3;
XLLP_INT32_T x;
printf(" LAN91C111 Bank Registers at %08x:\r\n", (int)ioRegsP);
printf(" Offset Bank0 Bank1 Bank2 Bank3\r\n");
for (x = 0; x < 16; x+=2)
{
// Select bank 0 register.
XllpEthernetSelectRegisterBank (BANK0);
// Read register contains.
bank0 = XllpEthernetReadWord16(x);
// Select bank 1 register.
XllpEthernetSelectRegisterBank (BANK1);
// Read register contains.
bank1 = XllpEthernetReadWord16(x);
// Select bank 2 register.
XllpEthernetSelectRegisterBank (BANK2);
// Read register contains.
bank2 = XllpEthernetReadWord16(x);
// Select bank 3 register.
XllpEthernetSelectRegisterBank (BANK3);
// Read register contains.
bank3 = XllpEthernetReadWord16(x);
printf(" %02X %04X %04X %04X %04X\r\n",
(int)x, bank0, bank1, bank2, bank3);
}
XllpEthernetSelectRegisterBank (BANK0);
printf(" LAN91C111 Registers Complete\r\n");
}
/******************************************************************************
Function Name:
XllpEthernetReadPhyRegister
Description:
This function prints the data stream used to read and write to the PHY registers
Global Register Modified:
None
Input Arguments:
P_XLLP_UCHAR_T bits - pointer to the data stream that needs to be displayed
XLLP_INT_T size - a size of the data stream
Output Arguments:
None
Return Value:
XLLP_UINT16_T - a value from the specified PHY register
*******************************************************************************/
static
void XllpEthernetDumpMIIStream(P_XLLP_UINT8_T bits, XLLP_INT32_T size)
{
XLLP_INT32_T i;
printf("BIT#:");
for (i = 0; i < size; ++i)
{
printf("%d", (int)i%10);
}
printf("\r\nMDOE:");
for (i = 0; i < size; ++i)
{
if (bits[i] & XLLP_LAN91C111_MGMT_MDOE)
printf("1");
else
printf("0");
}
printf("\r\nMDO :");
for (i = 0; i < size; ++i)
{
if (bits[i] & XLLP_LAN91C111_MGMT_MDO)
printf("1");
else
printf("0");
}
printf("\r\nMDI :");
for (i = 0; i < size; ++i)
{
if (bits[i] & XLLP_LAN91C111_MGMT_MDI)
printf("1");
else
printf("0");
}
printf("\r\n");
}
/******************************************************************************
Function Name:
XllpEthernetReadPhyRegister
Description:
This function reads the data from the specified PHY register
Global Register Modified:
Ethernet Bank Select Register
Input Arguments:
XLLP_UCHAR_T phyaddr - PHY Address
XLLP_UCHAR_T phyreg - PHY Register offset
Output Arguments:
None
Return Value:
XLLP_UINT16_T - a value from the specified PHY register
*******************************************************************************/
XLLP_UINT16_T XllpEthernetReadPhyRegister(XLLP_UINT8_T phyaddr,
XLLP_UINT8_T phyreg)
{
XLLP_INT32_T i;
XLLP_UINT8_T mask;
XLLP_UINT16_T mii_reg;
XLLP_UINT8_T bits[64];
XLLP_INT32_T clk_idx = 0;
XLLP_INT32_T input_idx;
XLLP_UINT16_T phydata;
// 32 consecutive ones on MDO to establish sync
for (i = 0; i < 32; ++i)
bit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -