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

📄 lan91c111.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    for(index=0 ; index < pNbuf->length; index +=2)
    {
        *(uint16*)&ethframe->data[index] = LAN91C111_DATA;
    }

    /* Get control byte and odd byte if there is one */
    lastword = LAN91C111_DATA;
    
    if(lastword & 0x0020)
    {
        /* write last byte */
        ethframe->data[index] = (uint8)((lastword & 0xFF00)>>8);
        /* increase length by 1*/
        pNbuf->length++;
    }

    /* Issue "Remove and Release" command */
    while (LAN91C111_MMCR & LAN91C111_MMCR_BUSY);
    LAN91C111_MMCR = LAN91C111_MMCR_RELEASE;

    /* Call the appropriate handler */
    nif_protocol_handler(nif,ethframe->type,pNbuf);

    /* free the buffer */
    nif->rx_free(pNbuf);

    /* Return to ISR */
    return;
}

/********************************************************************/
int
lan91c111_handler (void * applefritter, NIF *nif)
{
    uint16 intstatus, oldIMR, oldBank, oldPTR;
    vuint32 intdone;

    intdone = FALSE;

    /* Save off Bank Select register */
    oldBank = LAN91C111_BSR;

    /* switch to Bank 2 */
    SMC_SELECT_BANK(2);

    /* Save off Address Pointer register */
    oldPTR = LAN91C111_PTR;

    /* read the interrupt mask register */
    oldIMR = LAN91C111_IMR;

    /* disable all interrupts */
    LAN91C111_IMR = 0;

    while(!intdone)
    {
        /* switch to Bank 2 */
        SMC_SELECT_BANK(2);

        /* read in interrupt status register */
        intstatus = (LAN91C111_ISR&0xFF00);

        if(LAN91C111_ISR_RCV_INT &intstatus)        
        {
            lan91c111_receive(applefritter, nif);
            ++nif->f_rx;

        }
        else if(LAN91C111_ISR_TX_INT &intstatus)        
        {
            /* Acknowledge TXINTR */
            LAN91C111_ISR = LAN91C111_ISR_TX_INT;
            ++nif->f_tx;
        }
        else if(LAN91C111_ISR_RX_OVRN_INT &intstatus)   
        {
            /* Acknowledge interrupt */
            LAN91C111_ISR = LAN91C111_ISR_RX_OVRN_INT;
        }

        else
            intdone = TRUE;

    } /* while(!intdone) */
    
    /* Make sure I am in Bank 2 */
    SMC_SELECT_BANK(2);
    
    /* Check to see if FIFO is emtpy */
    if(LAN91C111_PTR & LAN91C111_PTR_NOT_EMPTY)
    {
        return FALSE;
    }

    /* Restore Address Pointer register */
    LAN91C111_PTR = oldPTR; 

    
    /* Restore the interrupt mask register */
    LAN91C111_IMR = oldIMR;

    /* Restore Bank Select register */
    LAN91C111_BSR = oldBank;

    return TRUE;
}
/********************************************************************
 * Shutdown phy
 ********************************************************************/
static void lan91c111_phy_shutdown(void)
{
    unsigned int timeout;
    unsigned int j;

    // Reset the PHY, setting all other bits to zero
    lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG, PHY_CNTL_RST);

    // Wait for the reset to complete, or time out
    timeout = 6; // Wait up to 3 seconds
    while (timeout--)
        {
        if (!(lan91c111_read_phy_reg(PHYADDR, PHY_CNTL_REG) & PHY_CNTL_RST))
            {
            // reset complete
            break;
            }

        /* delay some time */
        for( j=0 ; j<100 ; j++);
        }

    if (timeout < 1)
        {
        printf("PHY reset timed out\n");
        return;
        }
}

/********************************************************************
 * Configures the specified PHY using Autonegotiation. Calls
 * smc_phy_fixed() if the user has requested a certain config.
 ********************************************************************/
static void lan91c111_phy_configure(void)
{
    unsigned int timeout;
    unsigned int j;
    uint16       status;

    // Reset the PHY, setting all other bits to zero
    lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG, PHY_CNTL_RST);

    // Wait for the reset to complete, or time out
    timeout = 6; // Wait up to 3 seconds
    while (timeout--)
        {
        if (!(lan91c111_read_phy_reg(PHYADDR, PHY_CNTL_REG) & PHY_CNTL_RST))
            {
            // reset complete
            break;
            }

        /* delay some time */
        for( j=0 ; j<100 ; j++);
        }

    if (timeout < 1)
        {
        printf("PHY reset timed out\n");
        return;
        }

    // Enable PHY Interrupts (for register 18)
    // Interrupts listed here are disabled
    lan91c111_write_phy_reg(PHYADDR, PHY_MASK_REG, PHY_INT_LNKFAIL
                                                |PHY_INT_INT
                                                |PHY_INT_LOSSSYNC
                                                |PHY_INT_CWRD
                                                |PHY_INT_SSD
                                                |PHY_INT_ESD    
                                                |PHY_INT_RPOL
                                                |PHY_INT_JAB    
                                                |PHY_INT_SPDDET
                                                |PHY_INT_DPLXDET);

    /* Configure the Receive/Phy Control register */
    SMC_SELECT_BANK(0);
    LAN91C111_RPC = LAN91C111_RPC_DEFAULT;


    // Update our Auto-Neg Advertisement Register
    lan91c111_write_phy_reg(PHYADDR, PHY_AD_REG, (PHY_AD_TX_FDX|PHY_AD_TX_HDX|PHY_AD_10_FDX|PHY_AD_10_HDX|PHY_AD_CSMA));        

    // Restart auto-negotiation process in order to advertise my caps
    lan91c111_write_phy_reg(PHYADDR, 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 = lan91c111_read_phy_reg(PHYADDR, PHY_STAT_REG);
        if (status & PHY_STAT_ANEG_ACK)
        {
            // auto-negotiate complete
            break;
        }

        /* delay some time */
        for( j=0 ; j<10000 ; j++);

        // Restart auto-negotiation if remote fault
        if (status & PHY_STAT_REM_FLT)
        {
            // Restart auto-negotiation
            lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG,
                PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
                PHY_CNTL_SPEED | PHY_CNTL_DPLX);
        }
    }
}

/********************************************************************
 * Writes a register to the MII Management serial interface
 ********************************************************************/
static void lan91c111_write_phy_reg(uint8 phyaddr, uint8 phyreg, uint16 phydata)
{
    uint16 oldBank;
    uint32 i,j;
    uint16 mask;
    uint16 mii_reg;
    uint16 bits[65];
    uint32 clk_idx = 0;

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

    // Start code <01>
    bits[clk_idx++] = LAN91C111_MII_MDOE;
    bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

    // Write command <01>
    bits[clk_idx++] = LAN91C111_MII_MDOE;
    bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

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

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

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

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

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

    // Write out 16 bits of data, msb first
    mask = 0x8000;
    for (i = 0; i < 16; ++i)
        {
        if (phydata & mask)
            bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
        else
            bits[clk_idx++] = LAN91C111_MII_MDOE;

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

    // Save the current bank
    oldBank = LAN91C111_BSR;

    // Select bank 3
    SMC_SELECT_BANK(3);

    // Get the current MII register value
    mii_reg = LAN91C111_MII;

    // Turn off all MII Interface bits
    mii_reg &= ~(LAN91C111_MII_MDOE|LAN91C111_MII_MCLK|LAN91C111_MII_MDI|LAN91C111_MII_MDO);

    // Clock all cycles
    for (i = 0; i < sizeof bits; ++i)
        {
        // Clock Low - output data
        LAN91C111_MII = (mii_reg | bits[i]);
        for(j=0 ; j<4000 ;j++);
        
        // Clock Hi - input data
        LAN91C111_MII = (mii_reg | bits[i] | LAN91C111_MII_MCLK);
        for(j=0 ; j<4000 ;j++);

        bits[i] |=  (LAN91C111_MII & LAN91C111_MII_MDI);        
        }

    // Return to idle state
    // Set clock to low, data to low, and output tristated
    LAN91C111_MII = mii_reg;
    for(j=0 ; j<1000 ;j++);

    // Restore original bank select
//  SMC_SELECT_BANK(oldBank);
    LAN91C111_BSR = oldBank;

}

/********************************************************************
 * Reads a register from the MII Management serial interface
 ********************************************************************/
static uint16
lan91c111_read_phy_reg(uint8 phyaddr, uint8 phyreg)
{
    uint16 oldBank;
    uint32 i,j;
    uint8 mask;
    uint16 mii_reg;
    uint16 bits[64];
    uint32 clk_idx = 0;
    uint32 input_idx;
    uint16 phydata;

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

    // Start code <01>
    bits[clk_idx++] = LAN91C111_MII_MDOE;
    bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

    // Read command <10>
    bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
    bits[clk_idx++] = LAN91C111_MII_MDOE;

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

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

    // Output the phy register number, msb first
    mask = (uint8)0x10;
    for (i = 0; i < 5; ++i)
        {
        if (phyreg & mask)
            bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
        else
            bits[clk_idx++] = LAN91C111_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 = LAN91C111_BSR;

    // Select bank 3
    SMC_SELECT_BANK(3);

    // Get the current MII register value
    mii_reg = LAN91C111_MII;

    // Turn off all MII Interface bits
    mii_reg &= ~(LAN91C111_MII_MDOE|LAN91C111_MII_MCLK|LAN91C111_MII_MDI|LAN91C111_MII_MDO);

    // Clock all 64 cycles
    for (i = 0; i < sizeof bits; ++i)
        {
        // Clock Low - output data
        LAN91C111_MII = ( mii_reg | bits[i] );
        for(j=0 ; j<4000 ;j++);

        // Clock Hi - input data
        LAN91C111_MII = ( mii_reg | bits[i] | LAN91C111_MII_MCLK );
        for(j=0 ; j<4000 ;j++)
        {}
        bits[i] |= (LAN91C111_MII & LAN91C111_MII_MDI);
        }

    // Return to idle state
    // Set clock to low, data to low, and output tristated
    LAN91C111_MII = mii_reg;
    for(j=0 ; j<1000 ;j++);

    // Restore original bank select
//  SMC_SELECT_BANK( oldBank );
    LAN91C111_BSR = oldBank;

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

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

    return(phydata);    
}

/********************************************************************/

⌨️ 快捷键说明

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