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

📄 ns8390.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * File:        ns8390.c
 * Purpose:     Device driver for the National Semiconductor 8390
 *              Ethernet chipset used in NE2000 type NICs.
 *
 * Notes:       This driver was actually developed on a Winbond
 *              W89C906 chipset, a reportedly-identical clone.
 *
 */

#include "src/include/dbug.h"
#include "src/include/dev/ns8390.h"
#include "src/uif/net/net.h"
#include "src/dev/ethernet/ns8390p.h"

#ifndef NS8390_8BIT
#define NS8390_16BIT
#endif

#ifdef NS8390_16BIT
#if     (!defined(NS8390_ENDIAN_BIG) && !defined(NS8390_ENDIAN_LITTLE))
#error "Must define NS8390_ENDIAN"
#endif
#endif

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

/*
 * The local buffer memory management algorithms treat the
 * buffer as a circular queue with blocks of size 256 bytes.
 * The following define regions of the local buffer memory
 * in terms of blocks.  Thus the values given below are
 * actually the MSB of a 16-bit address into the local
 * buffer memory.  For most cards, there is 16Kbytes of local
 * buffer memory starting at 0x4000 and ending at 0x7FFF.
 * In addition, there is 32 bytes of EEPROM residing at 0x0000
 * which contains the Ethernet Address and some manufacturer
 * information.
 */

/*
 * 256 * 6 = 1536 which is enough room for one packet for TX.
 * This scheme gives TX enough buffer space for transmitting
 * one packet, and the rest to the receiver logic.  This
 * simplifies the code necessary to manage the queue.
 */
#if (defined(NS8390_8BIT))
#define DEFAULT_TPSR    (0x40)
#define DEFAULT_PSTART  (0x46)
#define DEFAULT_PSTOP   (0x60)
#elif (defined(NS8390_16BIT))
#define DEFAULT_TPSR    (0x40)
#define DEFAULT_PSTART  (0x46)
#define DEFAULT_PSTOP   (0x80)
#else
#error "Unsupported NS8390_WIDTH in ns8390.c"
#endif

/********************************************************************/
static void
set_dma_read_at (NS8390 *ns8390, int addr, int size)
{
    /*
     * Prepare to do a Remote DMA read.  When this routine exits,
     * it leaves the CR in Page 0.
     */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_AB
        | NS8390_CR_STA
        ) ;

    NS8390_WR_P0_RBCR1(ns8390, ((size & 0x0000FF00) >> 8));
    NS8390_WR_P0_RBCR0(ns8390, ((size & 0x000000FF)));

    NS8390_WR_P0_RSAR1(ns8390, ((addr & 0x0000FF00) >> 8));
    NS8390_WR_P0_RSAR0(ns8390, ((addr & 0x000000FF)));

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_RD
        | NS8390_CR_STA
        ) ;
}

/********************************************************************/
static void
set_dma_write_at (NS8390 *ns8390, int addr, int size)
{
    /*
     * Initialize the Remote DMA Write sequence properly. (See National
     * Semiconductor documentation.)  When this routine exists, it
     * leaves the CR at Page 0.
     */
    volatile int dummy_read;

    set_dma_read_at(ns8390, DEFAULT_PSTART, 2);
#if     (defined(NS8390_8BIT))
    dummy_read = NS8390_RD_DATA8(ns8390);
    /* dummy_read = NS8390_RD_DATA8(ns8390); */
#elif   (defined(NS8390_16BIT))
    dummy_read = NS8390_RD_DATA16(ns8390);
#else
#error
#endif

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_AB
        | NS8390_CR_STA
        ) ;

    NS8390_WR_P0_RBCR1(ns8390, ((size & 0x0000FF00) >> 8));
    NS8390_WR_P0_RBCR0(ns8390, ((size & 0x000000FF)));

    NS8390_WR_P0_RSAR1(ns8390, ((addr & 0x0000FF00) >> 8));
    NS8390_WR_P0_RSAR0(ns8390, ((addr & 0x000000FF)));

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_WR
        | NS8390_CR_STA
        ) ;
}

/********************************************************************/
static void
read_eth_addr(NS8390 *ns8390, unsigned char *hwa)
{
    int i;
    unsigned char eeprom[32];

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STP
        | NS8390_CR_RD_AB   /* No DMA */
        ) ;

    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_FT_8B
        ) ;

    NS8390_WR_P0_RBCR1(ns8390, 0);
    NS8390_WR_P0_RBCR0(ns8390, 0);

    NS8390_WR_P0_IMR(ns8390, 0);    /* mask irqs */
    NS8390_WR_P0_ISR(ns8390, ~0);

    NS8390_WR_P0_RCR(ns8390, 0
        | NS8390_RCR_MON
        ) ;

    NS8390_WR_P0_TCR(ns8390, 0
        | NS8390_TCR_LOOP_I0
        ) ;

    NS8390_WR_P0_RBCR0(ns8390, 32); /* EEPROM size */
    NS8390_WR_P0_RBCR1(ns8390, 0);

    NS8390_WR_P0_RSAR0(ns8390, 0);  /* EEPROM address */
    NS8390_WR_P0_RSAR1(ns8390, 0);

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STA     /* Start   */
        | NS8390_CR_RD_RD   /* Read DMA */
        ) ;

    for (i = 0; i < 32; ++i)
    {
        eeprom[i] = NS8390_RD_DATA8(ns8390);
    }

    for (i = 0; i < 6; ++i)
    {
        hwa[i] = eeprom[(i*2)];
    }

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STP     /* Stop   */
        | NS8390_CR_RD_AB   /* No DMA */
        ) ;
}

/********************************************************************/
static int
ns8390_reset (NIF *nif)
{
    /*
     * This routine sets up the chipset for use.  The procedure
     * implemented below is *mandatory*, as stated by National.
     */
    NS8390 *ns8390;

    ns8390 = nif->nic;

    /*
     * Step 1)  Select register page 0.  Stop the part.
     */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STP
        | NS8390_CR_RD_AB
        ) ;

    /*
     * Step 2)  Configure the DCR for 8 or 16-bit mode, normal operation.
     */
#if (defined(NS8390_8BIT))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_FT_8B
        ) ;
#elif (defined(NS8390_16BIT))

#if (defined(NS8390_ENDIAN_BIG))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_WTS
        | NS8390_DCR_BOS
        | NS8390_DCR_FT_8B
        ) ;
#elif (defined(NS8390_ENDIAN_LITTLE))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_WTS
        | NS8390_DCR_FT_8B
        ) ;
#else
#error "ENDIAN"
#endif

#else
#error
#endif

    /*
     * Step 3)  Clear Remote Byte Counter Registers.
     */
    NS8390_WR_P0_RBCR0(ns8390, 0);
    NS8390_WR_P0_RBCR1(ns8390, 0);

    /*
     * Step 4)  Initalize RCR.  Allow Broadcasts.
     */
    NS8390_WR_P0_RCR(ns8390, 0
/*      | NS8390_RCR_AB*/       /* FIX !!!! */
/*      | NS8390_RCR_PRO */
        ) ;

    /*
     * Step 5)  Place NIC in loopback mode 1 or 2.
     */
    NS8390_WR_P0_TCR(ns8390, 0
        | NS8390_TCR_LOOP_I0
        ) ;

    /*
     * Step 6)  Initialize BNDRY, PSTART, and PSTOP.
     */
    NS8390_WR_P0_BNRY(ns8390, DEFAULT_PSTART);
    NS8390_WR_P0_PSTART(ns8390, DEFAULT_PSTART);
    NS8390_WR_P0_PSTOP(ns8390, DEFAULT_PSTOP);

    /*
     * Step 7)  Clear ISR.
     */
    NS8390_WR_P0_ISR(ns8390, 0
        | NS8390_ISR_PRX
        | NS8390_ISR_PTX
        | NS8390_ISR_RXE
        | NS8390_ISR_TXE
        | NS8390_ISR_OVW
        | NS8390_ISR_CNT
        | NS8390_ISR_RDC
        | NS8390_ISR_RST
        ) ;

    /*
     * Step 8)  Initialize IMR.
     */
    NS8390_WR_P0_IMR(ns8390, 0
        | NS8390_IMR_PRXE
/*      | NS8390_IMR_PTXE */
        | NS8390_IMR_RXEE
        | NS8390_IMR_TXEE
        | NS8390_IMR_OVWE
        | NS8390_IMR_CNTE
/*      | NS8390_IMR_RDCE */
        ) ;

    /*
     * Step 9)  Program CR for Register Page 1.  Initialize the
     * Station Physical Address, Multicast address, and CURR.
     */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE1
        | NS8390_CR_STP
        | NS8390_CR_RD_AB
        ) ;

    NS8390_WR_P1_PAR0(ns8390, nif->hwa[0]);
    NS8390_WR_P1_PAR1(ns8390, nif->hwa[1]);
    NS8390_WR_P1_PAR2(ns8390, nif->hwa[2]);
    NS8390_WR_P1_PAR3(ns8390, nif->hwa[3]);
    NS8390_WR_P1_PAR4(ns8390, nif->hwa[4]);
    NS8390_WR_P1_PAR5(ns8390, nif->hwa[5]);

    NS8390_WR_P1_CURR(ns8390, (DEFAULT_PSTART + 1));
    nif->next_receive = ((DEFAULT_PSTART + 1) << 8);

    /* No Multicasts */
    NS8390_WR_P1_MAR0(ns8390, 0);
    NS8390_WR_P1_MAR1(ns8390, 0);
    NS8390_WR_P1_MAR2(ns8390, 0);
    NS8390_WR_P1_MAR3(ns8390, 0);
    NS8390_WR_P1_MAR4(ns8390, 0);
    NS8390_WR_P1_MAR5(ns8390, 0);
    NS8390_WR_P1_MAR6(ns8390, 0);
    NS8390_WR_P1_MAR7(ns8390, 0);

    /*
     * Step 10)  Put NIC in START mode (NIC still in Loopback).
     */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STA
        | NS8390_CR_RD_AB
        ) ;

    /*
     * Step 11)  Initialize TCR.  NIC now ready.  NS recommends
     * placing the NIC in normal operation from loopback here.
     * This isn't done here so that an explict ns8390_start() is
     * needed to start receiving ethernet frames.
     */

    return TRUE;
}

/********************************************************************/
static void
ns8390_start (NIF *nif)
{
    /*
     * This routine allows the chipset to start receiving frames.
     */
    NS8390 *ns8390;

    ns8390 = nif->nic;

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STA
        | NS8390_CR_RD_AB
        ) ;

    NS8390_WR_P0_TCR(ns8390, 0
        | NS8390_TCR_LOOP_NO
        ) ;

#if (defined(NS8390_8BIT))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_LS
        | NS8390_DCR_FT_8B
        ) ;
#elif (defined(NS8390_16BIT))

#if (defined(NS8390_ENDIAN_BIG))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_LS
        | NS8390_DCR_WTS
        | NS8390_DCR_BOS
        | NS8390_DCR_FT_8B
        ) ;
#elif (defined(NS8390_ENDIAN_LITTLE))
    NS8390_WR_P0_DCR(ns8390, 0
        | NS8390_DCR_LS
        | NS8390_DCR_WTS
        | NS8390_DCR_FT_8B
        ) ;
#else
#error "ENDIAN"
#endif

#else
#error
#endif
}

/********************************************************************/
static void
ns8390_stop (NIF *nif)
{
    /*
     * This routine masks out all NS8390 interrupts, thereby
     * letting any remaining TX frames transmit, and preventing
     * the NS8390 from interrupting the host processor.  Because
     * there isn't any clean way of shutting this part down, this
     * is how we do it.  The NS8390 may continue to receive frames,
     * and fill its buffers, but the host won't know it.
     */
    int loop;
    NS8390 *ns8390 = nif->nic;

    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_AB
        | NS8390_CR_STA
        ) ;

    NS8390_WR_P0_IMR(ns8390, 0);
    NS8390_WR_P0_ISR(ns8390, ~0);

    /* hope this is long enough for 1 TX frame time */
    for (loop = 0; loop < 0x000010000; ++loop)
        ;

⌨️ 快捷键说明

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