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

📄 1

📁 aesop s3c2440a BSP for windowsce 6.0
💻
📖 第 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 the SMC9000 ethernet controller used for the Windows CE
    debug ethernet services, and bootloaders.

Functions:


Notes: 
    These routines are called at system init and other times when system calls aren't allowed, so
    they can't make any system calls.
    
--*/


// Note : The Odo SMC implementation sometimes encounters read errors if we
// optimize this routine.  So for now I'm just going to turn of all 
// optimizations.
#pragma optimize("", off)

#include <windows.h>
#include <halether.h>
#include <ceddk.h>
#include "smchw.h"
#include "smcsw.h"
#include "..\eboot\udp.h"

// The base address of the SMC registers.  Also, allow for a multiplier, since the Odo
// platform uses 32 bit accesses of the registers.
static BYTE volatile *pbEthernetBase;
static DWORD dwRegisterMultiplier;

#define ReadWord( wOffset ) READ_PORT_USHORT((PUSHORT)(pbEthernetBase + (wOffset*dwRegisterMultiplier)))
#define WriteWord( wOffset, Value ) WRITE_PORT_USHORT((PUSHORT)(pbEthernetBase + (wOffset*dwRegisterMultiplier)),(USHORT)(Value))

// If this is defined, broadcast frames will be discarded.  Since we need to process
// ARPs, leave broadcast filter off, and filter out packets as soon as we can.  This, since
// we have to take an interrupt anyway, looking at the first few bytes isn't that bad. If
// the SMC chip could be configured so that we didn't even get interrupts for broadcast
// packets, we might look at updating the ARP cache on the desktop and filtering out all
// broadcasts...
#define NO_BROADCAST 0

#define BROADCAST_FILTER_BIT 0x4000

// If any of the following bits are set in the received status word, discard frame
#if NO_BROADCAST
#define FRAME_FILTER  (0xAC00 | BROADCAST_FILTER_BIT)  // No broadcast
#else
#define FRAME_FILTER  0xAC00   // Allow broadcast
#endif

// For debugging, if defined, this will cause all Rx/Tx data to be dumped to debug serial port
#undef SMC_DUMP_FRAMES
#define SMC_DUMP_FRAMES

// Mask to use for interrupts
static UINT16 wIntMask;

// Controls whether we filter out broadcast packets (except ARP requests...)
static DWORD dwConfigOptions;

static void SendFrameError( char *pszPrefix, UINT16 wCompletionCode );
#ifdef SMC_DUMP_FRAMES
static void DumpEtherFrame( BYTE *pFrame, WORD cwFrameLength );
#endif





                                          
#define SMC_DEV_NAME    "SMC91111"           
#define SMC_PHY_ADDR    0x0000               
#define SMC_ALLOC_MAX_TRY       5            
#define SMC_TX_TIMEOUT          30           
                                             
#define SMC_PHY_CLOCK_DELAY 1000             
                                             
#define ETH_ZLEN 60                          
// This is called to initialze the ethernet low level driver.  The base address of the ethernet hardware
// is passed into the routine.  The routine will return TRUE for a successful initialization.






#define MII_REG         0x0008
#define MII_MSK_CRS100  0x4000 /* Disables CRS100 detection during tx half dup */
#define MII_MDOE        0x0008 /* MII Output Enable */
#define MII_MCLK        0x0004 /* MII Clock, pin MDCLK */
#define MII_MDI         0x0002 /* MII Input, pin MDI */
#define MII_MDO         0x0001 /* MII Output, pin MDO */


/* PHY Control Register */
#define PHY_CNTL_REG            0x00
#define PHY_CNTL_RST            0x8000  /* 1=PHY Reset */
#define PHY_CNTL_LPBK           0x4000  /* 1=PHY Loopback */
#define PHY_CNTL_SPEED          0x2000  /* 1=100Mbps, 0=10Mpbs */
#define PHY_CNTL_ANEG_EN        0x1000 /* 1=Enable Auto negotiation */
#define PHY_CNTL_PDN            0x0800  /* 1=PHY Power Down mode */
#define PHY_CNTL_MII_DIS        0x0400  /* 1=MII 4 bit interface disabled */
#define PHY_CNTL_ANEG_RST       0x0200 /* 1=Reset Auto negotiate */
#define PHY_CNTL_DPLX           0x0100  /* 1=Full Duplex, 0=Half Duplex */
#define PHY_CNTL_COLTST         0x0080  /* 1= MII Colision Test */

/* PHY Status Register */
#define PHY_STAT_REG            0x01
#define PHY_STAT_CAP_T4         0x8000  /* 1=100Base-T4 capable */
#define PHY_STAT_CAP_TXF        0x4000  /* 1=100Base-X full duplex capable */
#define PHY_STAT_CAP_TXH        0x2000  /* 1=100Base-X half duplex capable */
#define PHY_STAT_CAP_TF         0x1000  /* 1=10Mbps full duplex capable */
#define PHY_STAT_CAP_TH         0x0800  /* 1=10Mbps half duplex capable */
#define PHY_STAT_CAP_SUPR       0x0040  /* 1=recv mgmt frames with not preamble */
#define PHY_STAT_ANEG_ACK       0x0020  /* 1=ANEG has completed */
#define PHY_STAT_REM_FLT        0x0010  /* 1=Remote Fault detected */
#define PHY_STAT_CAP_ANEG       0x0008  /* 1=Auto negotiate capable */
#define PHY_STAT_LINK           0x0004  /* 1=valid link */
#define PHY_STAT_JAB            0x0002  /* 1=10Mbps jabber condition */
#define PHY_STAT_EXREG          0x0001  /* 1=extended registers implemented */

/* PHY Identifier Registers */
#define PHY_ID1_REG             0x02    /* PHY Identifier 1 */
#define PHY_ID2_REG             0x03    /* PHY Identifier 2 */

/* PHY Auto-Negotiation Advertisement Register */
#define PHY_AD_REG              0x04
#define PHY_AD_NP               0x8000  /* 1=PHY requests exchange of Next Page */
#define PHY_AD_ACK              0x4000  /* 1=got link code word from remote */
#define PHY_AD_RF               0x2000  /* 1=advertise remote fault */
#define PHY_AD_T4               0x0200  /* 1=PHY is capable of 100Base-T4 */
#define PHY_AD_TX_FDX           0x0100  /* 1=PHY is capable of 100Base-TX FDPLX */
#define PHY_AD_TX_HDX           0x0080  /* 1=PHY is capable of 100Base-TX HDPLX */
#define PHY_AD_10_FDX           0x0040  /* 1=PHY is capable of 10Base-T FDPLX */
#define PHY_AD_10_HDX           0x0020  /* 1=PHY is capable of 10Base-T HDPLX */
#define PHY_AD_CSMA             0x0001  /* 1=PHY is capable of 802.3 CMSA */

/* PHY Auto-negotiation Remote End Capability Register */
#define PHY_RMT_REG             0x05
/* Uses same bit definitions as PHY_AD_REG */

/* PHY Configuration Register 1 */
#define PHY_CFG1_REG            0x10
#define PHY_CFG1_LNKDIS         0x8000  /* 1=Rx Link Detect Function disabled */
#define PHY_CFG1_XMTDIS         0x4000  /* 1=TP Transmitter Disabled */
#define PHY_CFG1_XMTPDN         0x2000  /* 1=TP Transmitter Powered Down */
#define PHY_CFG1_BYPSCR         0x0400  /* 1=Bypass scrambler/descrambler */
#define PHY_CFG1_UNSCDS         0x0200  /* 1=Unscramble Idle Reception Disable */
#define PHY_CFG1_EQLZR          0x0100  /* 1=Rx Equalizer Disabled */
#define PHY_CFG1_CABLE          0x0080  /* 1=STP(150ohm), 0=UTP(100ohm) */
#define PHY_CFG1_RLVL0          0x0040  /* 1=Rx Squelch level reduced by 4.5db */
#define PHY_CFG1_TLVL_SHIFT     2       /* Transmit Output Level Adjust */
#define PHY_CFG1_TLVL_MASK      0x003C
#define PHY_CFG1_TRF_MASK       0x0003  /* Transmitter Rise/Fall time */

/* PHY Configuration Register 2 */
#define PHY_CFG2_REG            0x11
#define PHY_CFG2_APOLDIS        0x0020  /* 1=Auto Polarity Correction disabled */
#define PHY_CFG2_JABDIS         0x0010  /* 1=Jabber disabled */
#define PHY_CFG2_MREG           0x0008  /* 1=Multiple register access (MII mgt) */
#define PHY_CFG2_INTMDIO        0x0004  /* 1=Interrupt signaled with MDIO pulseo */

/* PHY Status Output (and Interrupt status) Register */
#define PHY_INT_REG             0x12    /* Status Output (Interrupt Status) */
#define PHY_INT_INT             0x8000  /* 1=bits have changed since last read */
#define PHY_INT_LNKFAIL         0x4000  /* 1=Link Not detected */
#define PHY_INT_LOSSSYNC        0x2000  /* 1=Descrambler has lost sync */
#define PHY_INT_CWRD            0x1000  /* 1=Invalid 4B5B code detected on rx */
#define PHY_INT_SSD             0x0800  /* 1=No Start Of Stream detected on rx */
#define PHY_INT_ESD             0x0400  /* 1=No End Of Stream detected on rx */
#define PHY_INT_RPOL            0x0200  /* 1=Reverse Polarity detected */
#define PHY_INT_JAB             0x0100  /* 1=Jabber detected */
#define PHY_INT_SPDDET          0x0080  /* 1=100Base-TX mode, 0=10Base-T mode */
#define PHY_INT_DPLXDET         0x0040  /* 1=Device in Full Duplex */

/* PHY Interrupt/Status Mask Register */
#define PHY_MASK_REG            0x13    /* Interrupt Mask */
/* Uses the same bit definitions as PHY_INT_REG */


static void smc_udelay(unsigned int us)
{
    volatile int i;
    
    for(i=0 ; (unsigned int)i < us ; i++)
    {
    }
}
static WORD smc_read_phy_register (unsigned char phyreg)
{
        int oldBank;
        int i;
        BYTE mask;
        WORD mii_reg;
        BYTE bits[64];
        int clk_idx = 0;
        int input_idx;
        WORD phydata;
        BYTE phyaddr = SMC_PHY_ADDR;

        /* 32 consecutive ones on MDO to establish sync */
        for (i = 0; i < 32; ++i)
                bits[clk_idx++] = MII_MDOE | MII_MDO;

        /* Start code <01> */
        bits[clk_idx++] = MII_MDOE;
        bits[clk_idx++] = MII_MDOE | MII_MDO;

        /* Read command <10> */
        bits[clk_idx++] = MII_MDOE | MII_MDO;
        bits[clk_idx++] = MII_MDOE;

        /* Output the PHY address, msb first */
        mask = (BYTE) 0x10;
        for (i = 0; i < 5; ++i) {
                if (phyaddr & mask)
                        bits[clk_idx++] = MII_MDOE | MII_MDO;
                else
                        bits[clk_idx++] = MII_MDOE;

                /* Shift to next lowest bit */
                mask >>= 1;
        }

        /* Output the phy register number, msb first */
        mask = (BYTE) 0x10;
        for (i = 0; i < 5; ++i) {
                if (phyreg & mask)
                        bits[clk_idx++] = MII_MDOE | MII_MDO;
                else
                        bits[clk_idx++] = MII_MDOE;

                /* Shift to next lowest bit */
                mask >>= 1;
        }

        /* Tristate and turnaround (2 bit times) */
        bits[clk_idx++] = 0;
        /*bits[clk_idx++] = 0; */

        /* Input starts at this bit time */
        input_idx = clk_idx;

        /* Will input 16 bits */
        for (i = 0; i < 16; ++i)
                bits[clk_idx++] = 0;

        /* Final clock bit */
        bits[clk_idx++] = 0;

        /* Save the current bank */
        oldBank = ReadWord(BANKSEL_REG);

        /* Select bank 3 */
        WriteWord( BANKSEL_REG, BANK3 );

        /* Get the current MII register value */
        mii_reg = ReadWord (MII_REG);

        /* Turn off all MII Interface bits */
        mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO);

        /* Clock all 64 cycles */
        for (i = 0; i < sizeof bits; ++i) {
                /* Clock Low - output data */
                WriteWord (MII_REG, mii_reg | bits[i]);
                smc_udelay (SMC_PHY_CLOCK_DELAY);


                /* Clock Hi - input data */
                WriteWord ( MII_REG, mii_reg | bits[i] | MII_MCLK);
                smc_udelay (SMC_PHY_CLOCK_DELAY);
                bits[i] |= ReadWord (MII_REG) & MII_MDI;
        }

        /* Return to idle state */
        /* Set clock to low, data to low, and output tristated */
        WriteWord (MII_REG, mii_reg);
        smc_udelay (SMC_PHY_CLOCK_DELAY);

        /* Restore original bank select */
        WriteWord( BANKSEL_REG, oldBank );

        /* Recover input data */
        phydata = 0;
        for (i = 0; i < 16; ++i) {
                phydata <<= 1;

                if (bits[input_idx++] & MII_MDI)
                        phydata |= 0x0001;
        }


        return (phydata);
}


/*------------------------------------------------------------
 . Writes a register to the MII Management serial interface
 .-------------------------------------------------------------*/
static void smc_write_phy_register (BYTE phyreg, WORD phydata)
{
        int oldBank;
        int i;
        WORD mask;
        WORD mii_reg;
        BYTE bits[65];
        int clk_idx = 0;
        BYTE phyaddr = SMC_PHY_ADDR;

        /* 32 consecutive ones on MDO to establish sync */
        for (i = 0; i < 32; ++i)
                bits[clk_idx++] = MII_MDOE | MII_MDO;

        /* Start code <01> */
        bits[clk_idx++] = MII_MDOE;
        bits[clk_idx++] = MII_MDOE | MII_MDO;

        /* Write command <01> */
        bits[clk_idx++] = MII_MDOE;
        bits[clk_idx++] = MII_MDOE | MII_MDO;

        /* Output the PHY address, msb first */
        mask = (BYTE) 0x10;
        for (i = 0; i < 5; ++i) {
                if (phyaddr & mask)
                        bits[clk_idx++] = MII_MDOE | MII_MDO;
                else

⌨️ 快捷键说明

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