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

📄 chip.c

📁 IMX开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
//  Use of this source code is subject to the terms of the Microsoft end-user
//  license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
//  If you did not accept the terms of the EULA, you are not authorized to use
//  this source code. For a copy of the EULA, please see the LICENSE.RTF on
//  your install media.
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//  File:  chip.c
//
//  Implementation of CS8900 Driver
//
//  This file implements the chip specific functions for CS8900
//
//------------------------------------------------------------------------------
#include "cs8900a.h"

//------------------------------------------------------------------------------
// External Functions
//------------------------------------------------------------------------------
extern PBSP_CS8900_REG g_pCS8900Reg;
extern CRITICAL_SECTION gCS8900BufCs;

//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_RETRY   100000

#define CRC_POLYNOMIAL_SPECIAL 0xEDB88320

//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Static MAC Address if EEPROM not found, set to :12-13-17-28-2701
static const UINT8 gMACAddr[6] = {0x12, 0x13, 0x17, 0x28, 0x27, 0x01} ;
extern CRITICAL_SECTION gCS8900RegCs;

//------------------------------------------------------------------------------
// Local Variables
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// Function: ReadCs8900Register
//
// This function reads the contents of the CS8900 register.
//
// Parameters:
//      RegisterOffset
//          [in] Offset from the base address
//
// Returns:
//      Return Value at the address
//
//------------------------------------------------------------------------------
WORD ReadCs8900Register(WORD RegisterOffset)
{
    WORD Value;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +ReadCs8900Register\r\n")));

	EnterCriticalSection (&gCS8900RegCs);
    NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), RegisterOffset );
    NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_DATA_0), &Value );
	LeaveCriticalSection (&gCS8900RegCs);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +ReadCs8900Register [0x%.8X]\r\n"), Value));
    return Value;

}

//------------------------------------------------------------------------------
//
// Function: WriteCs8900Register
//
// This function writes the contents to the CS8900 register.
//
// Parameters:
//      RegisterOffset
//          [in] Offset from the base address
//
//      Value
//          [in] Contents to be written
//
// Returns:
//      none
//
//------------------------------------------------------------------------------
void WriteCs8900Register(WORD RegisterOffset, WORD Value)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +WriteCs8900Register\r\n")));

	EnterCriticalSection (&gCS8900RegCs);
    NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), RegisterOffset );
    NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_DATA_0), Value );
	LeaveCriticalSection (&gCS8900RegCs);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -WriteCs8900Register\r\n")));
}

//------------------------------------------------------------------------------
//
// Function: CheckForChip
//
// This function checks for the presence of CS8900 chip.
//
// Parameters:
//      pEthernet
//          [in] pointer to the CS8900 structure.
//
// Returns:
//      TRUE indicates success. FALSE indicates failure.
//
//------------------------------------------------------------------------------
WORD CheckForChip(pCs8900_t pEthernet)
{
    WORD Value;
    UINT32 i;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +CheckForChip\r\n")));

	/* The software reset does not work. The SELF_ST_SI_BUSY is never de-asserted
	 * and the subsequent for loop executes infinitely. 
	 */
    // Trigger a software reset
    // WriteCs8900Register(PKTPG_SELF_CTL,  SELF_CTL_RESET);

    for (i=MAX_RETRY; i>0; i--)
    {
        if (!(ReadCs8900Register(PKTPG_SELF_ST) & SELF_ST_SI_BUSY))
            break;
    }
    if (i <= 0)
    {
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A Reset0 Timeout.\r\n")));
        return FALSE;
    }

    for (i=MAX_RETRY; i>0; i--)
    {
        if ((ReadCs8900Register(PKTPG_SELF_ST) & SELF_ST_INIT_DONE))
            break;
    }
    if (i <= 0) {
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A Reset1 Timeout.\r\n")));
        return FALSE;
    }
    // end of chip reset
     // Read the address port (packet page pointer)
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
     //Add by Paul, Chao, I don't know why read first times will get invalid value, but just do it.
     //For safety reason, we read six times and reserve last value
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
     NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );

     DEBUGMSG(ZONE_INIT, (TEXT("CS8900:CheckForChip, NdisRawReadPortUshort(CS8900_PAGE_POINTER), Value=0x%x, 0x%x\r\n"), Value, (g_pCS8900Reg->CS8900_PAGE_POINTER)));
    if ( (Value & CS8900_PacketPage_Signature_Mask) == CS8900_PacketPage_Signature )
    {
        // Read the EISA Number and Product ID
        Value = ReadCs8900Register(PKTPG_EISA_NUM);
        if(Value != EISA_NUM_CRYSTAL)
        {
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900:EISA Registration Number Wrong! Expect=%x, Read=%x\r\n"),  EISA_NUM_CRYSTAL, Value));
            return FALSE;
        }

        Value = ReadCs8900Register(PKTPG_PRODUCT_ID);
        pEthernet->ChipRevsion = Value & PROD_REV_MASK;
        Value &= PROD_ID_MASK;
        if(Value!=PROD_ID_CS8900)
        {
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900:Product ID Wrong! Expect=%x, Read=%x\r\n"),  PROD_ID_CS8900, Value));
            return FALSE;
        }

    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -CheckForChip\r\n")));
    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: InitializeChip
//
// This function initializes the CS8900 chip.
//
// Parameters:
//      pEthernet
//          [in] pointer to the CS8900 structure.
//
// Returns:
//      TRUE indicates success.
//
//------------------------------------------------------------------------------
WORD InitializeChip(pCs8900_t pEthernet)
{

    WORD data;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +InitializeChip\r\n")));
    // Check for EEPROM presence
    data = ReadCs8900Register(PKTPG_SELF_ST);
    if ((data & SELF_ST_EEPROM_PRES) && (data & SELF_ST_EEPROM_OK))
    {
        *(UINT16 *)pEthernet->CurrentAddress = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_L);
        *(UINT16 *)(&pEthernet->CurrentAddress[2]) = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_M);
        *(UINT16 *)(&pEthernet->CurrentAddress[4]) = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_H);
    }
    else
    {
        if(pEthernet->CurrentAddress[0] == 0 && pEthernet->CurrentAddress[1] == 0 && pEthernet->CurrentAddress[3] == 0  && 
            pEthernet->CurrentAddress[4] == 0 && pEthernet->CurrentAddress[5] == 0 && pEthernet->CurrentAddress[6] == 0 )
        {
            *(UINT16 *)pEthernet->CurrentAddress = *(UINT16 *)gMACAddr;
            *(UINT16 *)(&pEthernet->CurrentAddress[2]) = *(UINT16 *)(&gMACAddr[2]);
            *(UINT16 *)(&pEthernet->CurrentAddress[4]) = *(UINT16 *)(&gMACAddr[4]);
        }
    }

    // Compare and write the current MAC address into CS8900 Individual Address register if
    // there is difference
    data = ReadCs8900Register(PKTPG_IND_ADDR);
    if(data!= *(UINT16 *)pEthernet->CurrentAddress)
    {
        WriteCs8900Register(PKTPG_IND_ADDR, *(UINT16 *)pEthernet->CurrentAddress);
    }
    
    data = ReadCs8900Register(PKTPG_IND_ADDR+2);
    if(data!= *(UINT16 *)(&pEthernet->CurrentAddress[2]) )
    {
        WriteCs8900Register(PKTPG_IND_ADDR+2, *(UINT16 *)(&pEthernet->CurrentAddress[2]));
    }
   
    data = ReadCs8900Register(PKTPG_IND_ADDR+4);
    if(data!= *(UINT16 *)(&pEthernet->CurrentAddress[4]))
    {
        WriteCs8900Register(PKTPG_IND_ADDR+4, *(UINT16 *)(&pEthernet->CurrentAddress[4]));
    }
    
    NdisMoveMemory(&pEthernet->PermanentAddress, &pEthernet->CurrentAddress, (ULONG)ETHER_ADDR_SIZE);

    WriteCs8900Register(PKTPG_SELF_CTL, SELF_CTL_HC1E); 
    WriteCs8900Register(PKTPG_LINE_CTL, LINE_CTL_10BASET); 

    // Don't use IOCHRDY pin
    data = ReadCs8900Register(PKTPG_BUS_CTL);
    data |= BUS_CTL_IOCHRDY;
    WriteCs8900Register(PKTPG_BUS_CTL, data); 

    data = RX_CFG_ALL_IE | 0x0800;      // enable crc in buffer too
    WriteCs8900Register(PKTPG_RX_CFG, data); // pg 53

    data = TX_CFG_16_COLL_IE |TX_CFG_JABBER_IE | TX_CFG_OUT_WIN_IE | TX_CFG_TX_OK_IE;
    WriteCs8900Register(PKTPG_TX_CFG, data); // pg 56

    data = BUF_CFG_RDY4TX_IE | BUF_CFG_TX_UNDR_IE | BUF_CFG_MISOFLO_IE | BUF_CFG_COLOFLO_IE;
    WriteCs8900Register(PKTPG_BUF_CFG, data); // pg 59

    // set filtering (pg55)
    data = ReadCs8900Register(PKTPG_RX_CTL);
    //Clear the broadcast, multicast and promiscuous bits
    data &= ~(RX_CTL_BCAST_A | RX_CTL_MCAST_A | RX_CTL_PROM_A);
    data |= RX_DEFAULT_CONFIGURATION;

    pEthernet->PacketFilter = data;

    WriteCs8900Register(PKTPG_RX_CTL, data);

    // Write the interrupt number to the register
    WriteCs8900Register(PKTPG_INT_NUM, (WORD)CS8900_INTERRUPT_NUM);

    // Enable reception and transmission of frames
    data = ReadCs8900Register(PKTPG_LINE_CTL);
    data |= (LCR_RX_ON | LCR_TX_ON);
    WriteCs8900Register(PKTPG_LINE_CTL, data);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -InitializeChip\r\n")));
    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: cs8900aReadFromEEPROM
//
// This function read the contents of EEPROM.
//
// Parameters:
//      pEthernet
//          [in] pointer to the CS8900 structure.
//
//      EEPROMAddress
//          [in] EEPROM address.
//
// Returns:
//      TRUE indicates success. FALSE indicates failure.
//
//------------------------------------------------------------------------------
WORD cs8900aReadFromEEPROM (pCs8900_t pEthernet, WORD EEPROMAddress)
{
    UINT32 i;
    WORD Value;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +cs8900aReadFromEEPROM\r\n")));
    if(pEthernet == NULL) {
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900: ReadFromEEPROM :: pEthernet NULL. \r\n")));
        return FALSE;
    }
    // Wait for NO BUSY signal

⌨️ 快捷键说明

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