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

📄 dec21140.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

Abstract:  
    Routines for DEC21140 NIC used by bootloader download and 
    ether debug.
    
Functions:


Notes: 

    
--*/

#include <windows.h>
#include <halether.h>
#include <wdm.h>
#include "dec21140.h"


#define MIN_DMA_SIZE    0x20000     // Minimum DMA buffer possible.
#define DEC21140_SETUP_PERFECT_ENTRIES  16  // # of perfect match entries

//  Forward declaration...
void    DEC21140ModeSetByAutoNegotiation(void);
BOOL    EEPROMReadMAC(WORD *wMAC);


/////////////////////////////////////////////////////////////////////////////////
//
//

#define __DEC21140_DUMP_TX_DESCRIPTOR__ 1
#ifdef  __DEC21140_DUMP_TX_DESCRIPTOR__
    static void DumpTxDescriptor (PTX_DESCRIPTOR_FORMAT pTxHead);
#endif


#define __DEC21140_DUMP_RX_DESCRIPTOR__ 1
#ifdef  __DEC21140_DUMP_RX_DESCRIPTOR__
    static void DumpRxDescriptor (PRX_DESCRIPTOR_FORMAT pRxHead);
#endif


#define __DEC21140_DUMP_MEMORY__    1
#ifdef  __DEC21140_DUMP_MEMORY__
    static void DumpMemory (PBYTE   pSource, DWORD  dwLength);
#endif


/////////////////////////////////////////////////////////////////////////////////
//  External Functions that must be there...
//

//extern void   localDEBUGMSG(const unsigned char *sz, ...);
#define localDEBUGMSG EdbgOutputDebugString

extern  DWORD   OEMEthGetMSecs (void);



/////////////////////////////////////////////////////////////////////////////////
//  Misc defines
//
#define  CSR0_OFFSET     0x00
#define  CSR1_OFFSET     0x08
#define  CSR2_OFFSET     0x10
#define  CSR3_OFFSET     0x18
#define  CSR4_OFFSET     0x20
#define  CSR5_OFFSET     0x28
#define  CSR6_OFFSET     0x30
#define  CSR7_OFFSET     0x38
#define  CSR8_OFFSET     0x40
#define  CSR9_OFFSET     0x48
#define  CSR10_OFFSET    0x50
#define  CSR11_OFFSET    0x58
#define  CSR12_OFFSET    0x60
#define  CSR13_OFFSET    0x68
#define  CSR14_OFFSET    0x70
#define  CSR15_OFFSET    0x78

#define  CSR0_REG       (PULONG)(g_pIOBase + CSR0_OFFSET)
#define  CSR1_REG       (PULONG)(g_pIOBase + CSR1_OFFSET)
#define  CSR2_REG       (PULONG)(g_pIOBase + CSR2_OFFSET)
#define  CSR3_REG       (PULONG)(g_pIOBase + CSR3_OFFSET)
#define  CSR4_REG       (PULONG)(g_pIOBase + CSR4_OFFSET)
#define  CSR5_REG       (PULONG)(g_pIOBase + CSR5_OFFSET)
#define  CSR6_REG       (PULONG)(g_pIOBase + CSR6_OFFSET)
#define  CSR7_REG       (PULONG)(g_pIOBase + CSR7_OFFSET)
#define  CSR8_REG       (PULONG)(g_pIOBase + CSR8_OFFSET)
#define  CSR9_REG       (PULONG)(g_pIOBase + CSR9_OFFSET)
#define  CSR10_REG      (PULONG)(g_pIOBase + CSR10_OFFSET)
#define  CSR11_REG      (PULONG)(g_pIOBase + CSR11_OFFSET)
#define  CSR12_REG      (PULONG)(g_pIOBase + CSR12_OFFSET)
#define  CSR13_REG      (PULONG)(g_pIOBase + CSR13_OFFSET)
#define  CSR14_REG      (PULONG)(g_pIOBase + CSR14_OFFSET)
#define  CSR15_REG      (PULONG)(g_pIOBase + CSR15_OFFSET)

#ifdef MIPS
#define TO_REAL(Addr)   ((Addr & 0x1fffffff) + dwMEM_OFFSET)
#define TO_VIRT(Addr)   ((Addr | 0xA0000000) - dwMEM_OFFSET)
#else
#define TO_REAL(Addr)   (Addr)
#define TO_VIRT(Addr)   (Addr)
#endif


/////////////////////////////////////////////////////////////////////////////////
//  Local Variables...
//
static      BYTE                    pbEthernetAddr[6];      //  Local copy of MAC address
volatile    PCSR                    pCSR;                   //  pointer to 21140 Control and Status Register
PUCHAR g_pIOBase = NULL;

volatile    PRX_DESCRIPTOR_FORMAT   pRxDesc;                //  pointer to RX Descriptor head.
volatile    PRX_DESCRIPTOR_FORMAT   pCurrentRxDesc;         //  pointer to current RX Descriptor that Rx may use.

volatile    PTX_DESCRIPTOR_FORMAT   pTxDesc;                //  pointer to TX Descriptor head.
volatile    PTX_DESCRIPTOR_FORMAT   pCurrentTxDesc;         //  pointer to current TX Descriptor that Tx may use.

static      DWORD                   dwMEM_OFFSET;


//  These used to be constants.
//  To make this a true hardware independent library, user needs to provide these addresses...

volatile    DWORD   dwTRANSMIT_DESCRIPTORS_HEAD;        
volatile    DWORD   dwRECEIVE_DESCRIPTORS_HEAD;     
volatile    DWORD   dwTRANSMIT_BUFFER_START;
volatile    DWORD   dwRECEIVE_BUFFER_START;         

//  Then we will calculate the following...

static  DWORD   dwTRANSMIT_RING_SIZE;                           
static  DWORD   dwRECEIVE_RING_SIZE;        


//  Forward declaration...
BOOL    DEC21140SetupPerfectFilter (PUCHAR pucMulticastAddresses, DWORD dwNoOfAddresses);


/////////////////////////////////////////////////////////////////////////////////
//  Delay - Spin for the asked amount of time in MilliSecond.
//  Input: dwMilliSecond === Delay required in MilliSecond.
//  Oh well, simply spin...
//
void    Delay (DWORD dwMilliSecond)
{   
    //  Need to find a better way...
    //  But should be okay for ether debug purposes...
    while (dwMilliSecond--)
        {
            READ_PORT_ULONG(CSR9_REG);
        }

}   // Delay()



/////////////////////////////////////////////////////////////////////////////////
//  MIIRead() - 
//  On ICS1890, it's written:
//  Management Interface uses a serial bit stream with a specified frame 
//  structure and protocol as defined:
//  -   Preamble    [32 ones]
//  -   SOF         [01]
//  -   OpCode      [10(read) ; 01(write)]
//  -   Address     [5 bits]
//  -   Register    [5 bits]
//  -   TA          [2 bits]
//  -   Data        [16 bits]
//  -   Idle        [at least 1 bit]
//
//
//  CSR9 controls:
//  +-----------------+-----------------+-----------------+-----------------+
//  | MII Management  | MII Management  | MII Management  | MII Management  |
//  | Data In         | Operation Mode  | Write Data      | Clock           |
//  +-----------------+-----------------+-----------------+-----------------+
//          19                 18                17               16
//  

WORD MIIRead (BYTE bRegAddr) 
{
    WORD    wValue;
    DWORD   wData;  
    int     i;  

    // Start with clock low and MDIO high   
        WRITE_PORT_ULONG(CSR9_REG, 0x00020000);

    // 32 cycles with MDIO = '1'
    for( i = 0; i < 32; i++ ) 
    {
        WRITE_PORT_ULONG(CSR9_REG, 0x00030000);         
        WRITE_PORT_ULONG(CSR9_REG, 0x00020000);     
    }

    // Start of frame 01
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00020000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00030000);     


    // Read cycle 10
    WRITE_PORT_ULONG(CSR9_REG, 0x00020000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00030000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000);     
    

    // Physical address of 00001.
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00000000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00010000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00020000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00030000);
    

    // Register address
    for( i = 4; i >= 0; i-- ) 
    {
        if (bRegAddr & (1 << i)) 
        {
            WRITE_PORT_ULONG(CSR9_REG, 0x00020000); 
            WRITE_PORT_ULONG(CSR9_REG, 0x00030000);                     
        }
        else 
        {
            WRITE_PORT_ULONG(CSR9_REG, 0x00000000);                     
            WRITE_PORT_ULONG(CSR9_REG, 0x00010000);                     
        }
    }

    // Two cycle turnaround time
    WRITE_PORT_ULONG(CSR9_REG, 0x00040000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00050000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00040000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00050000);

    
    // Read out the data bits
    wValue = 0;

    for( i = 0; i < 16; i++ )   
    {
        wValue <<= 1;

        WRITE_PORT_ULONG(CSR9_REG, 0x00040000);                     
        wData = READ_PORT_ULONG(CSR9_REG);
        WRITE_PORT_ULONG(CSR9_REG, 0x00050000);     

        wData = (wData >> 19);
        wValue |= (WORD) (wData & 1);       
    }

    // Two cycle at the end to make sure it's now Idle
    WRITE_PORT_ULONG(CSR9_REG, 0x00040000); 
    WRITE_PORT_ULONG(CSR9_REG, 0x00050000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00040000);     
    WRITE_PORT_ULONG(CSR9_REG, 0x00050000);         
    
    return wValue;
}




/////////////////////////////////////////////////////////////////////////////////
//  HWStopAdapter -   Stop the adapter by resetting the chip through CSR0[0]
//                  
static void
HWStopAdapter(void)
{
    CSR6_21140 CSR6;
    CSR0_21140 CSR0;

    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.PortSelect = 1;                    //  Select MII/SYM port.
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

    CSR0.dwReg = READ_PORT_ULONG(CSR0_REG); 
    CSR0.dwReg |= SOFTWARE_RESET;
    WRITE_PORT_ULONG(CSR0_REG, CSR0.dwReg);

    Delay (12000);

    CSR6.dwReg = READ_PORT_ULONG(CSR6_REG);
    CSR6.TransmitThresholdMode = 1;
    WRITE_PORT_ULONG(CSR6_REG, CSR6.dwReg);

}   // HWStopAdapter()



/////////////////////////////////////////////////////////////////////////////////
//  HWInit  -   completely initialize the hardware and leave it in a state that is ready to transmit and receive
//              packets.
//  

static BOOL 
HWInit(void)
{   
    int     i;
    int     dwTxRingSize;
    int     dwRxRingSize;
    int     dwTxBufferStart;
    int     dwRxBufferStart;
    volatile    PTX_DESCRIPTOR_FORMAT   pTxHead;
    volatile    PRX_DESCRIPTOR_FORMAT   pRxHead;
    CSR0_21140  localCSR0;
    CSR6_21140  localCSR6;

    dwTxRingSize = dwTRANSMIT_RING_SIZE;
    dwRxRingSize = dwRECEIVE_RING_SIZE;
    dwTxBufferStart = TO_REAL(dwTRANSMIT_BUFFER_START);
    dwRxBufferStart = TO_REAL(dwRECEIVE_BUFFER_START);

    HWStopAdapter();                

    // ==========================================================================
    //  The descriptors are linked by circular linked list  
    //  They are basically one after another, and we use buffer address 2 as pointer to
    //  next descriptor.
    //  The last descriptor will link back to first descriptor.

    //  First stop, TX descriptors...
    //  Note: Initializing pTxDesc and pCurrentTxDesc for future global use...

    pTxHead = pTxDesc = pCurrentTxDesc = (PTX_DESCRIPTOR_FORMAT) dwTRANSMIT_DESCRIPTORS_HEAD;;
    memset (pTxHead, 0, (sizeof(TX_DESCRIPTOR_FORMAT) * dwTxRingSize));     

    for (i = 0 ; i < dwTxRingSize ; i++)
    {
        //  For each descriptor, this is what we need to set:
        //  -   The descriptor is now owned by Host TDES0[31]
        //  -   TDES1[24] set indicating second address is a chained address
        //  -   TDES1[25] set for last descriptor indicating a loop back.
        //  -   TDES2 will point to the buffer this descriptor points to.
        //  -   The next descriptor address in TDES3        
        
        pTxHead->TDES0.dwReg = pTxHead->TDES0.dwReg & DESC_OWNED_BY_HOST;       
        pTxHead->TDES1.dwReg = pTxHead->TDES1.dwReg | SECOND_ADDRESS_CHAINED;           
        

        pTxHead->TDES2 = dwTxBufferStart;
        dwTxBufferStart += MAX_BUFFER_SIZE;
    
        if (i == dwTxRingSize - 1)      
        {
            //  Last descriptor points to first descriptor...
            //  And indicates that this is the end of the ring...
            pTxHead->TDES1.TransmitEndOfRing = 1;
            pTxHead->TDES3 = TO_REAL((DWORD) pTxDesc);      
        }
        else
        {
            pTxHead->TDES3 = TO_REAL((DWORD) ((DWORD)pTxHead + sizeof(TX_DESCRIPTOR_FORMAT)));
            pTxHead = (PTX_DESCRIPTOR_FORMAT) TO_VIRT(pTxHead->TDES3);
        }       

    }       
    //DumpTxDescriptor (pTxDesc);


    // ==========================================================================
    //  Then, Rx descriptors...
    //  Note: Initializing pRxDesc for future global use...
    //
    
    pRxHead = pRxDesc = pCurrentRxDesc = (PRX_DESCRIPTOR_FORMAT) dwRECEIVE_DESCRIPTORS_HEAD;;
    memset (pRxHead, 0, (sizeof(RX_DESCRIPTOR_FORMAT) * dwRxRingSize)); 
    memset ((PBYTE)TO_VIRT(dwRxBufferStart), 0, dwRxRingSize * 1536);

    for (i = 0 ; i < dwRxRingSize ; i++)
    {
        //  For each descriptor, this is what we need to set:
        //  -   The descriptor is now owned by DEC21140 RDES0[31] = 1
        //  -   RDES1[24] set indicating second address is a chained address,       
        //  -   RDES1[25] set for last descriptor indicating a loop back.
        //  -   RDES2 will point to the buffer this descriptor points to.
        //  -   The next descriptor address in TDES3        
        
        pRxHead->RDES0.dwReg = pRxHead->RDES0.dwReg | DESC_OWNED_BY_DEC21140;
        pRxHead->RDES1.dwReg = pRxHead->RDES1.dwReg | SECOND_ADDRESS_CHAINED;
        pRxHead->RDES1.Buffer1Size = MAX_BUFFER_SIZE;
        
        pRxHead->RDES2 = dwRxBufferStart;

        dwRxBufferStart += MAX_BUFFER_SIZE;
    
        if (i == dwRxRingSize - 1)      
        {
            //  Last descriptor points to first descriptor...
            //  And indicates that this is the end of the ring...
            pRxHead->RDES1.ReceiveEndOfRing = 1;
            pRxHead->RDES3 = TO_REAL((DWORD) pRxDesc);      
        }
        else
        {
            pRxHead->RDES3 = TO_REAL((DWORD) ((DWORD)pRxHead + sizeof(RX_DESCRIPTOR_FORMAT)));
            pRxHead = (PRX_DESCRIPTOR_FORMAT) TO_VIRT(pRxHead->RDES3);
        }       
    }   
    // DumpRxDescriptor (pRxDesc);  


    // ==========================================================================   
    //  Set CSRs:
    //
    
    // enable the 21143 chip

⌨️ 快捷键说明

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