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

📄 ns8390.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 2 页
字号:

    /* stop the nic */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_RD_AB
        | NS8390_CR_STP
        ) ;
}

/********************************************************************/
static int
ns8390_send (NIF *nif,
    HWA_ADDR_P  eth_dest,
    HWA_ADDR_P  eth_src,
    uint16      eth_type,
    NBUF        *pNbuf)
{
    /*
     * This routine transmits one frame.  This routine only accepts
     * 6-byte Ethernet addresses.
     */
    int mod_data_length, index;
    NS8390 *ns8390;
    uint8 old_ipl;

    ns8390 = nif->nic;

    /*
     * The format of an Ethernet frame looks like:
     *
     *   00 01 02 03 04 05
     *  +--+--+--+--+--+--+
     *  |  |  |  |  |  |  | destination ethernet address
     *  +--+--+--+--+--+--+
     *   06 07 08 09 0A 0B
     *  +--+--+--+--+--+--+
     *  |  |  |  |  |  |  | source ethernet address
     *  +--+--+--+--+--+--+
     *   0C 0D
     *  +--+--+
     *  |  |  | type (IP = 0x0800)
     *  +--+--+
     *   0E 0F ...
     *  +--+--+--+--+--+--+
     *  |  |  |  |  |  |  | data (min of 46 octets, max of 1500)
     *  +--+--+--+--+--+--+
     *
     *  +--+--+--+--+
     *  |  |  |  |  | 32-bit CRC (generated by hardware)
     *  +--+--+--+--+
     *
     * NOTE:  The NS8390 takes care of pre-amble, and is programmed
     * to generate the 32-bit CRC.
     *
     * NOTE:  The minimum size of data transmitted in an ethernet
     * frame is 46 octets (bytes).
     */

    /*
     * Check for valid length of data.
     */
    if ((pNbuf->length > nif->mtu) || (pNbuf->length <= 0))
    {
        return 0;
    }
    mod_data_length = pNbuf->length;
    if (mod_data_length < ETH_MIN_SIZE)
        mod_data_length = ETH_MIN_SIZE;
#if (defined(NS8390_16BIT))
    if (mod_data_length & 0x0001)
        ++mod_data_length;  /* make it align to 16 bits */
#endif

    /*
     * During the course of loading a frame into the NS8390, we
     * can not have interrupts occur, especially those from the
     * NS8390 receiver!
     */
    old_ipl = asm_set_ipl(6);

    /*
     * Load starting address and length into the DMA registers.
     */
    set_dma_write_at (ns8390,(DEFAULT_TPSR << 8), mod_data_length+14);

    /*
     * Write destination ethernet address.
     */
#if (defined(NS8390_8BIT))
    NS8390_WR_DATA8(ns8390, eth_dest[0]);
    NS8390_WR_DATA8(ns8390, eth_dest[1]);
    NS8390_WR_DATA8(ns8390, eth_dest[2]);
    NS8390_WR_DATA8(ns8390, eth_dest[3]);
    NS8390_WR_DATA8(ns8390, eth_dest[4]);
    NS8390_WR_DATA8(ns8390, eth_dest[5]);
#elif (defined(NS8390_16BIT))
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[0]));
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[2]));
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[4]));
#else
#error
#endif

    /*
     * Write source ethernet address.
     */
#if (defined(NS8390_8BIT))
    NS8390_WR_DATA8(ns8390, eth_src[0]);
    NS8390_WR_DATA8(ns8390, eth_src[1]);
    NS8390_WR_DATA8(ns8390, eth_src[2]);
    NS8390_WR_DATA8(ns8390, eth_src[3]);
    NS8390_WR_DATA8(ns8390, eth_src[4]);
    NS8390_WR_DATA8(ns8390, eth_src[5]);
#elif (defined(NS8390_16BIT))
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[0]));
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[2]));
    NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[4]));
#else
#error
#endif

    /*
     * Write frame type.
     */
#if (defined(NS8390_8BIT))
    NS8390_WR_DATA8(ns8390, ((eth_type & 0x0000FF00) >> 8));
    NS8390_WR_DATA8(ns8390, (eth_type & 0x000000FF));
#elif (defined(NS8390_16BIT))
    NS8390_WR_DATA16(ns8390, eth_type);
#else
#error
#endif


    /*
     * Write the data.
     */
#if (defined(NS8390_8BIT))
    for (index = 0; index < pNbuf->length; ++index)
    {
        NS8390_WR_DATA8(ns8390, pNbuf->data[ETH_HDR_SIZE + index]);
    }
    for (index = pNbuf->length; index < ETH_MIN_SIZE; ++index)
    {
        NS8390_WR_DATA8(ns8390, 0);
    }
#elif (defined(NS8390_16BIT))
    for (index = 0; (index + 1) < pNbuf->length; index += 2)
    {
        NS8390_WR_DATA16(ns8390, *((uint16 *)&pNbuf->data[ETH_HDR_SIZE + index]));
    }
    if (pNbuf->length & 0x0001)
    {
        /* odd number of bytes to transmit */
        NS8390_WR_DATA16(ns8390, (pNbuf->data[ETH_HDR_SIZE + pNbuf->length - 1]<<8));
        ++pNbuf->length;    /* for zero pad below */
    }
    for (index = pNbuf->length; index < ETH_MIN_SIZE; index += 2)
    {
        NS8390_WR_DATA16(ns8390, 0);
    }
#else
#error
#endif

    /*
     * Load Transmit Start Pointer Register and Transmit Byte Count
     * Registers.
     */
    NS8390_WR_P0_TPSR(ns8390, DEFAULT_TPSR);
    NS8390_WR_P0_TBCR0(ns8390, ((mod_data_length + 14) & 0x000000FF));
    NS8390_WR_P0_TBCR1(ns8390,
        (((mod_data_length + 14) & 0x0000FF00) >> 8));

    /*
     * Turn the transmitter on!  We're done!
     */
    NS8390_WR_CR(ns8390, 0
        | NS8390_CR_PAGE0
        | NS8390_CR_STA
        | NS8390_CR_TXP
        | NS8390_CR_RD_AB
        ) ;

    /* Free the network buffer */
    nif->tx_free(pNbuf);

    /* We can allow interrupts again */
    asm_set_ipl(old_ipl);

    return TRUE;
}

/********************************************************************/
static void
ns8390_receive (NS8390 *ns8390, NIF *nif)
{
    /*
     * This command pulls one frame from the card.
     */
    int index, current, receive_status, np_pointer, a,b, receive_count;
    eth_frame_hdr *ethframe;
    NBUF *pNbuf;

    /* Prepare to read from the local buffer memory */
    current = nif->next_receive;
    set_dma_read_at (ns8390, current, 4);

    /*
     * Read the Status bytes and Ethernet frame from the
     * local buffer memory.  The DMA hardware automatically
     * increments the DMA pointers.
     */
#if (defined(NS8390_8BIT))
    receive_status = NS8390_RD_DATA8(ns8390) & 0x00FF;
    np_pointer = NS8390_RD_DATA8(ns8390) & 0x00FF;
    a = (NS8390_DATAPORT(ns8390) & 0x00FF);
    b = (NS8390_DATAPORT(ns8390) & 0x00FF);
    receive_count = ((b << 8) | a);
#elif (defined(NS8390_16BIT))
    a = NS8390_RD_DATA16(ns8390);
    b = NS8390_RD_DATA16(ns8390);

#if (defined(NS8390_ENDIAN_BIG))
    receive_status = (a & 0x00FF);
    np_pointer = ((a & 0xFF00)>>8);
    receive_count = (((b & 0x00FF) << 8) | ((b&0xFF00)>>8));
#elif (defined(NS8390_ENDIAN_LITTLE))
    np_pointer = (a & 0x00FF);
    receive_status = ((a & 0xFF00)>>8);
    receive_count = (((b & 0x00FF) << 8) | ((b&0xFF00)>>8));
#else
#error "ENDIAN"
#endif

#else
#error
#endif

    /* Record next packet pointer and adjust circular queue */
    nif->next_receive = (np_pointer << 8);
    if ((np_pointer-1) <= DEFAULT_PSTART)
        NS8390_WR_P0_BNRY(ns8390, DEFAULT_PSTOP-1);
    else
        NS8390_WR_P0_BNRY(ns8390, np_pointer-1);

    /* This frame has errors! */
    if ((receive_status & NS8390_RSR_PRX) != NS8390_RSR_PRX)
    {
        ++nif->f_rx_err;
        return;
    }

    /* Process the frame */
    set_dma_read_at(ns8390, current+4, 6 + 6 + 2);

    /* Obtain system RAM buffer for the frame */
    if ((pNbuf = nif->rx_alloc()) == NULL)
        return;

    ethframe = (eth_frame_hdr *)&pNbuf->data[ETH_HDR_OFFSET];

    /* Read the frame from the local buffer */
#if (defined(NS8390_8BIT))
    ethframe->dest[0] = NS8390_RD_DATA8(ns8390);
    ethframe->dest[1] = NS8390_RD_DATA8(ns8390);
    ethframe->dest[2] = NS8390_RD_DATA8(ns8390);
    ethframe->dest[3] = NS8390_RD_DATA8(ns8390);
    ethframe->dest[4] = NS8390_RD_DATA8(ns8390);
    ethframe->dest[5] = NS8390_RD_DATA8(ns8390);

    ethframe->src[0] = NS8390_RD_DATA8(ns8390);
    ethframe->src[1] = NS8390_RD_DATA8(ns8390);
    ethframe->src[2] = NS8390_RD_DATA8(ns8390);
    ethframe->src[3] = NS8390_RD_DATA8(ns8390);
    ethframe->src[4] = NS8390_RD_DATA8(ns8390);
    ethframe->src[5] = NS8390_RD_DATA8(ns8390);

    a = (NS8390_RD_DATA8(ns8390) & 0x00FF);
    b = (NS8390_RD_DATA8(ns8390) & 0x00FF);
    ethframe->type = (uint16)((a << 8) | b);
#elif (defined(NS8390_16BIT))
    *(uint16 *)&ethframe->dest[0] = NS8390_RD_DATA16(ns8390);
    *(uint16 *)&ethframe->dest[2] = NS8390_RD_DATA16(ns8390);
    *(uint16 *)&ethframe->dest[4] = NS8390_RD_DATA16(ns8390);

    *(uint16 *)&ethframe->src[0] = NS8390_RD_DATA16(ns8390);
    *(uint16 *)&ethframe->src[2] = NS8390_RD_DATA16(ns8390);
    *(uint16 *)&ethframe->src[4] = NS8390_RD_DATA16(ns8390);

    ethframe->type = NS8390_RD_DATA16(ns8390);
#else
#error
#endif

    if (!nif_protocol_exist(nif,ethframe->type))
    {
        nif->rx_free(pNbuf);
        return;
    }

    pNbuf->length = receive_count - (4 + 6 + 6 + 2);
    set_dma_read_at(ns8390, current+18, pNbuf->length);

#if (defined(NS8390_8BIT))
    for (index = 0; index < pNbuf->length; ++index)
    {
        ethframe->data[index] = NS8390_RD_DATA8(ns8390);
    }
#elif (defined(NS8390_16BIT))
    for (index = 0; index < pNbuf->length; index += 2)
    {
        *(uint16 *)&ethframe->data[index] = NS8390_RD_DATA16(ns8390);
    }
#else
#error
#endif

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

    /****************************************************************
     Higher level protocols must save off the data if they need to 
     keep it around for processing.
    *****************************************************************/
    nif->rx_free(pNbuf);
}

/********************************************************************/
int
ns8390_handler (NS8390 *ns8390, NIF *nif)
{
    /* This is the Interrupt Service Routine for the NS 8390 */
    int isr;

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

    /* Verify part has interrupts pending */
    isr = NS8390_RD_P0_ISR(ns8390) & 0x00FF;
    if (!isr) 
    {
        return FALSE;
    }

    /* Check the source of interrupts, and handle it */
    if (isr & NS8390_ISR_PRX)
    {
        /* Ack as soon as possible so more RX IRQs recognized */
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_PRX);
        ns8390_receive(ns8390, nif);
        ++nif->f_rx;
    }
    if (isr & NS8390_ISR_PTX)
    {
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_PTX);
        ++nif->f_tx;
    }
    if (isr & NS8390_ISR_RXE)
    {
        printf("NS8390 RXE Receiver Error\n");
        /* ns8390_receive(ns8390, nif); */
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_RXE);
    }
    if (isr & NS8390_ISR_TXE)
    {
        printf("NS8390 TXE Transmitter Error\n");
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_TXE);
        ++nif->f_tx_err;
    }
    if (isr & NS8390_ISR_OVW)
    {
        printf("NS8390 OVW Buffer Overflow\n");
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_OVW);
        ++nif->f_rx_err;
    }
    if (isr & NS8390_ISR_CNT)
    {
        printf("NS8390 CNT\n");
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_CNT);
    }
    if (isr & NS8390_ISR_RDC)
    {
        NS8390_WR_P0_ISR(ns8390, NS8390_ISR_RDC);
    }

    return TRUE;
}
/********************************************************************/
int
ns8390_init (NIF *nif, void *base, int vector)
{
    nif_init(nif, "ns8390");
    nif->nic = base;
    nif->vector = vector;

    read_eth_addr(nif->nic,&nif->hwa[0]);
    nif->hwa_size = 6;
    nif->mtu = 1500;
    nif->reset = ns8390_reset;
    nif->start = ns8390_start;
    nif->stop = ns8390_stop;
    nif->send = ns8390_send;
    nif->receive = (void *)&ns8390_receive;
    nif->rx_alloc = nbuf_rx_allocate;
    nif->tx_alloc = nbuf_tx_allocate;
    nif->rx_free = nbuf_rx_release;
    nif->tx_free = nbuf_tx_release;
    return TRUE;
}
/********************************************************************/

⌨️ 快捷键说明

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