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

📄 smc.c

📁 aesop s3c2440a BSP for windowsce 6.0
💻 C
📖 第 1 页 / 共 4 页
字号:
        smc_wait_ms (500);      /* wait 500 millisecs */






        /* Configure the Receive/Phy Control register */
        WriteWord( BANKSEL_REG, BANK0 );        
        WriteWord ( RPC_REG ,RPC_DEFAULT);

        /* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */
        my_phy_caps = smc_read_phy_register (PHY_STAT_REG);
        my_ad_caps = PHY_AD_CSMA;       /* I am CSMA capable */

        if (my_phy_caps & PHY_STAT_CAP_T4) {
                my_ad_caps |= PHY_AD_T4;
        }
        if (my_phy_caps & PHY_STAT_CAP_TXF) {
                my_ad_caps |= PHY_AD_TX_FDX;
        }
        if (my_phy_caps & PHY_STAT_CAP_TXH) {
                my_ad_caps |= PHY_AD_TX_HDX;
        }
        if (my_phy_caps & PHY_STAT_CAP_TF) {
                my_ad_caps |= PHY_AD_10_FDX;
        }
        if (my_phy_caps & PHY_STAT_CAP_TH) {
                my_ad_caps |= PHY_AD_10_HDX;
        }
        /* Update our Auto-Neg Advertisement Register */
        smc_write_phy_register (PHY_AD_REG, my_ad_caps);

        /* Read the register back.  Without this, it appears that when */
        /* auto-negotiation is restarted, sometimes it isn't ready and */
        /* the link does not come up. */
        smc_read_phy_register(PHY_AD_REG);

        EdbgOutputDebugString ("%s:phy caps=0x%x\n", SMC_DEV_NAME, my_phy_caps);      /*0x7809*/
        EdbgOutputDebugString ("%s:phy advertised caps=0x%x\n", SMC_DEV_NAME, my_ad_caps);    /*0x01e1*/

        /* Restart auto-negotiation process in order to advertise my caps */
        smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST);



        /* Wait for the auto-negotiation to complete.  This may take from */
        /* 2 to 3 seconds. */
        /* Wait for the reset to complete, or time out */
        timeout = 20;           /* Wait up to 10 seconds */
        while (timeout--) 
        {
                status = smc_read_phy_register (PHY_STAT_REG);
                if (status & PHY_STAT_ANEG_ACK) 
                {
                        EdbgOutputDebugString ("%s:PHY auto-negotiate complete\n", SMC_DEV_NAME);
                        /* auto-negotiate complete */
                        break;
                }

                smc_wait_ms (500);      /* wait 500 millisecs */

                /* Restart auto-negotiation if remote fault */
                if (status & PHY_STAT_REM_FLT) 
                {
                        EdbgOutputDebugString ("%s:PHY remote fault detected\n", SMC_DEV_NAME);

                        /* Restart auto-negotiation */
                        EdbgOutputDebugString("%s:PHY restarting auto-negotiation\n",SMC_DEV_NAME);
                        smc_write_phy_register (PHY_CNTL_REG,
                                                PHY_CNTL_ANEG_EN |
                                                PHY_CNTL_ANEG_RST |
                                                PHY_CNTL_SPEED |
                                                PHY_CNTL_DPLX);
                }
        }

        EdbgOutputDebugString ("%s:PHY_STAT_REG : 0x%x\n", SMC_DEV_NAME, status);
        if (timeout < 1) {
                EdbgOutputDebugString("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME);
                EdbgOutputDebugString("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME);
                failed = 1;
        }

        /* Fail if we detected an auto-negotiate remote fault */
        if (status & PHY_STAT_REM_FLT) 
        {
                EdbgOutputDebugString("PHY remote fault detected\n");
                failed = 1;
        }

        /* Re-Configure the Receive/Phy Control register */
        WriteWord( RPC_REG,RPC_DEFAULT);
        EdbgOutputDebugString("%s:RPC_DEFAULT : 0x%x\n", SMC_DEV_NAME, RPC_DEFAULT);

smc_phy_configure_exit:
return;

}

#endif

#if 1



/* Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low */
#define CONFIG_DEFAULT  (CFG_EPH_POWER_EN | CFG_NO_WAIT)


#define SMC_inw(r)     ReadWord(r)
#define  SMC_inb(r)     (((r)&1) ? SMC_inw((r)&~1)>>8 : SMC_inw(r)&0xFF)

#define SMC_outw(d,r)  WriteWord(r,d)
void SMC_outb(BYTE d,WORD r)   
{
   WORD __d = (BYTE)(d);  
   WORD __w = SMC_inw((r)&~1);
   __w &= ((r)&1) ? 0x00FF : 0xFF00;
   __w |= ((r)&1) ? __d<<8 : __d; 
   WriteWord((r)&~1,__w); 
}

void SMC_insw(r,b,l) 
{      
	int __i ;  
        WORD *__b2;  
        __b2 = (WORD *) b;  
        for (__i = 0; __i < l; __i++) 
	{  
            *(__b2 + __i) = SMC_inw(r);  
            SMC_inw(0);  
        };  
}
void SMC_outsw(r,b,l)
{ 
   int __i; 
   WORD *__b2;
   __b2 = (WORD *) b;
   for (__i = 0; __i < l; __i++) 
   { 
      SMC_outw( *(__b2 + __i), r); 
   } \
}
#define SMC_SELECT_BANK(x)  { SMC_outw( x, BANKSEL_REG ); }

static void udelay(unsigned int us)
{
    volatile int i;
    volatile int i2;
    
    for(i=0 ; (unsigned int)i < us ; i++)
    {
	 for(i2=0;i2<10;i2++)
	 {
	 }
    }
}

static void smc_enable()
{
        EdbgOutputDebugString("%s:smc_enable\n", SMC_DEV_NAME);
        SMC_SELECT_BANK( 0 );
        /* see the header file for options in TCR/RCR DEFAULT*/
        SMC_outw( TCR_DEFAULT, TCR_REG );
        SMC_outw( RCR_DEFAULT, RCR_REG );

}
static void smc_wait_mmu_release_complete (void)
{
        int count = 0;

        /* assume bank 2 selected */
        while (SMC_inw (MMU_CMD_REG) & MC_BUSY) {
                udelay (1);     /* Wait until not busy */
                if (++count > 200)
                        break;
        }
}

static void smc_reset (void)
{
        EdbgOutputDebugString ("%s:smc_reset\n", SMC_DEV_NAME);

        /* This resets the registers mostly to defaults, but doesn't
           affect EEPROM.  That seems unnecessary */
        SMC_SELECT_BANK (0);
        SMC_outw (RCR_SOFTRST, RCR_REG);

        /* Setup the Configuration Register */
        /* This is necessary because the CONFIG_REG is not affected */
        /* by a soft reset */

        SMC_SELECT_BANK (1);
        SMC_outw (CONFIG_DEFAULT, CONFIG_REG);

        /* Release from possible power-down state */
        /* Configuration register is not affected by Soft Reset */
        SMC_outw (SMC_inw (CONFIG_REG) | CFG_EPH_POWER_EN, CONFIG_REG);


        /* this should pause enough for the chip to be happy */
        udelay (10);

        SMC_SELECT_BANK (0);
        /* Disable transmit and receive functionality */
        SMC_outw (RCR_CLEAR, RCR_REG);
        SMC_outw (TCR_CLEAR, TCR_REG);

        /* set the control register */
        SMC_SELECT_BANK (1);
        SMC_outw (CTL_DEFAULT, CONTROL_REG);

        /* Reset the MMU */
        SMC_SELECT_BANK (2);
        smc_wait_mmu_release_complete ();
        SMC_outw (MC_RESET, MMU_CMD_REG);
        while (SMC_inw (MMU_CMD_REG) & MC_BUSY)
                udelay (1);     /* Wait until not busy */

        /* Note:  It doesn't seem that waiting for the MMU busy is needed here,
           but this is a place where future chipsets _COULD_ break.  Be wary
           of issuing another MMU command right after this */

        /* Disable all interrupts */
        SMC_outb (0, IM_REG);
}



int eth_init(USHORT *MacAddr) 
{
        int i;
        BYTE *mac = (BYTE*)MacAddr;
        EdbgOutputDebugString ("%s:smc_open\n", SMC_DEV_NAME);
        EdbgOutputDebugString("%s:smc_open\n", SMC_DEV_NAME);
        /* reset the hardware */
        smc_reset ();
        smc_enable ();

        /* Configure the PHY */
        smc_phy_configure ();

        SMC_SELECT_BANK (1);

        for (i = 0; i < 6; i++)
            SMC_outb (*(mac+i), MACADDR0_REG + i);

        return 0;
}

#endif


BOOL
SMCInit( BYTE *pbBaseAddress, DWORD dwMultiplier, USHORT MacAddr[3]) 
{
    WORD i;
    DWORD dwStartTime;
    USHORT wBSR, wConfig;

    if (! pbBaseAddress)
    {
EdbgOutputDebugString( "BASEADDRESS error\r\n");
        return FALSE;
    } 
    
    pbEthernetBase = pbBaseAddress;
    dwRegisterMultiplier = 0x1;   //dwMultiplier;

    // DANGER - May have to wait 750 usec after reset while EEPROM info loads (Pg 50 of the SMC91C94 spec).
    // until this occurs, SMC registers are inaccessible.
    
    smc_reset ();
    smc_enable ();

    SMC_SELECT_BANK (1);
    dwStartTime = OEMEthGetSecs();
    while( ReadWord( CONTROL_REG ) & 0x0003 && OEMEthGetSecs() - dwStartTime < 2);

    // Verify the I/O base.  The upper byte of the BSR always reads 0x33, use this.
    // For Odo, the bus cycles will time out and garbage values will be returned.
    wBSR = ReadWord(BANKSEL_REG);
EdbgOutputDebugString ("0xA700030e=0x%x\n",*(volatile UINT16 *)0xA700030e);
    if ((wBSR & 0xFF00) != 0x3300) {
        EdbgOutputDebugString("SMC card not detected, I/O base 0x%X, BSR: 0x%X\n",pbEthernetBase,wBSR);
        return FALSE;
    }
    EdbgOutputDebugString( "SMC Ethernet card detected at I/O base 0x%X\r\n",pbEthernetBase);

    // Read the MAC address from the 91C94.  This should have been read in from the EEPROM during reset


    // Set SQUELCH bit - this changes the threshold for a valid signal from 300mV to 180mV.
    // This is to attempt to fix problems we have seen with some (usually 8 port) hubs.
    wConfig = ReadWord(CONFIG_REG);
    wConfig |= CFG_NO_WAIT;
    wConfig |= CFG_EPH_POWER_EN;
    
    WriteWord(CONFIG_REG, wConfig);
    EdbgOutputDebugString("SMC config reg val: %X\n",wConfig);
    
    // Initialize the control register
    WriteWord( CONTROL_REG, CONTROL_REG_INIT );

    for(i = 0; i < 6; i++)
       SMC_outb (*((BYTE*)MacAddr+i), MACADDR0_REG + i);

    // Initialize memory configuration register
    SMC_SELECT_BANK (0);
    WriteWord( MCR_REG, MCR_REG_INIT );

    // Initialize transmit control register
    WriteWord( TCR_REG, TCR_REG_INIT );

    // Initialize interrupt mask register (all ints disabled to start)
    SMC_SELECT_BANK (2);
    WriteWord( SMC91111_INT_REG, 0);

    // The receive register should be the last thing initialzed so that we don't start
    //  getting Frames before we're ready for them.
    
    // Initialize the Receive Control Register (Pg 39 of the SMC91C94 spec):
    SMC_SELECT_BANK (0);
    WriteWord( RCR_REG, RCR_REG_INIT );

    WriteWord( RCR_REG, (RCR_RXEN|RCR_STRIP_CRC) );

    EdbgOutputDebugString("SMC Reset complete2\r\n");
    
    // Even if the card is present, it likes to have a second to stabilize before the first transmission
    while( OEMEthGetSecs() - dwStartTime < 2 );
    

#if 0
    smc_write_phy_register (0x00,0x00);
    EdbgOutputDebugString( "----%x\r\n",smc_read_phy_register (0x00));
    EdbgOutputDebugString( "----%x\r\n",smc_read_phy_register (0x01));
    EdbgOutputDebugString( "----%x\r\n",smc_read_phy_register (0x02));
    EdbgOutputDebugString( "----%x\r\n",smc_read_phy_register (0x03));
    EdbgOutputDebugString( "----%x\r\n",smc_read_phy_register (0x04));
#endif

    smc_phy_configure ();

    return TRUE;
}

// Interrupts left disabled at init, call this function to turn them on
void
SMCEnableInts()
{
    // Only enable receive interrupts (we poll for Tx completion)
    wIntMask = RCV_INTM;
    SMC_SELECT_BANK (2);
    WriteWord( SMC91111_INT_REG, wIntMask );
}

void
SMCDisableInts()
{
    wIntMask = 0;
    SMC_SELECT_BANK (2);
    WriteWord( SMC91111_INT_REG, wIntMask );
}

DWORD
SMCGetPendingInterrupts()
{
    WORD wInts;
    DWORD dwRet = 0;
    UINT16 wBankSave;

    // I need to save/restore the affected registers in the 91C94
    wBankSave = ReadWord( BANKSEL_REG );
    SMC_SELECT_BANK (2);
    wInts = ReadWord(SMC91111_INT_REG);

    // Just check for Rx int

⌨️ 快捷键说明

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