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

📄 xllp_ethernet.c

📁 Xcale270Bsp包,wince平台
💻 C
📖 第 1 页 / 共 5 页
字号:

  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 + -