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

📄 dm9000.c

📁 dm9000的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:

UINT16 DM9000_Initializtion(UINT8 *MAC_ADDR)
{
    UINT8 get_status;
    int i;
    /*
    1. To power on the internal PHY:
    iow ( 0x1F, 0x00 ); to set GPR (REG. 1FH) Bit [0]: PHYPD = 0
    The PHY is powered down at default. The power-up procedure will be needed to enable it by
    writing iow "0" to PHYPD (GP0 = 0). Please refer to the ch.3.4 about setting the GPIO pins.
     */
    iow(DM9KS_GPR, 0x00);
    delay(100);
    /*	
    2. To do a software reset for the DM9000A initial (see chapter 4.2):
    i. iow ( 0x00, 0x01 ); to set NCR (REG. 00) RST Bit [0] = 1 for a period time 10 us.
    ii. iow ( 0x00, 0x00 ); to clear NCR (REG. 00) RST Bit [0] = 0, or let it auto clear.
     */
    iow(DM9KS_NCR, 0x03);
    delay(100);
    iow(DM9KS_NCR, 0x03);
    delay(100);
    /*
    3. Program the NCR register. Choose normal mode by setting NCR (REG. 00) LBK Bit [2:1] =
    00b. The system designer can choose the network operations such as the internal MAC/ PHY
    loop-back mode, forced the external PHY Full/ half duplex mode or to force collisions, and the
    wake-up events enable. Please refer to the datasheet chapter 6.1 about the NCR setting.
     */
    get_status = ior(DM9KS_NCR);
    iow(DM9KS_NCR, 0x00);
    get_status = ior(DM9KS_NCR);
    iow(DM9KS_TCR, 0); /* TX Polling clear */
    /*
    4. To set the IMR register (REG. FFH) Bit [7] = 1 to enable the Pointer Auto Return function,
    which is the memory read/ write address pointer of the RX/ TX FIFO SRAM.
     */
    get_status = ior(DM9KS_IMR);
    iow(DM9KS_IMR, get_status | 0x80);
    /*
    5. Read the EEPROM data 3 words, for the individual Ethernet node address (if necessary).
     */
    iow(DM9KS_ETCR, 0); /* Early transmit disable */
    iow(DM9KS_TCCR, 0x07); /* TX UDP/TCP/IP checksum enable */
    iow(DM9KS_RCSR, 0x03); /* Receive checksum enable & discard checksum error
        packet */
    iow(0x39, 0x00); /* INT Pin Polarity Control 0: INT active high */
    /*
    6. Write 6-byte Ethernet node address into the Physical Address Registers (REG. 10H~15H).
     */
    iow(DM9KS_PA0, 0x00);
    iow(DM9KS_PA1, 0x01);
    iow(DM9KS_PA2, 0x02);
    iow(DM9KS_PA3, 0x03);
    iow(DM9KS_PA4, 0x04);
    iow(DM9KS_PA5, 0x05);
    for (i = 0; i < 6; i++)
        my_hwaddr[i] = MAC_ADDR[i];
    /*
    7. Write Hash Table 8 bytes into the Multicast Address Registers (REG. 16H ~ REG. 1DH).
     */
    iow(DM9KS_MA0, 0xFF);
    iow(DM9KS_MA1, 0xFF);
    iow(DM9KS_MA2, 0xFF);
    iow(DM9KS_MA3, 0xFF);
    iow(DM9KS_MA4, 0xFF);
    iow(DM9KS_MA5, 0xFF);
    iow(DM9KS_MA6, 0xFF);
    iow(DM9KS_MA7, 0xFF);
    /*
    8. To clear TX & INTR status by R/W1 the NSR REG. 01 and ISR REG. FEH registers. The Bit
    [2] TX1END, Bit [3] TX2END, and Bit [5] WAKEST will be cleared automatically by reading it
    or writing "1" back. Please refer to the datasheet chapter 6.2 & 6.33 about setting NSR & ISR.
     */
    get_status = ior(DM9KS_NSR);
    iow(DM9KS_NSR, get_status);
    get_status = ior(DM9KS_ISR);
    iow(DM9KS_ISR, get_status);
    /*
    9. To handle the NIC interrupts or polling service routines.
     */

    /*
    10. Program the IMR register (REG. FFH) Bit [0]/ Bit [1] to enable the RX/ TX interrupt.
     */
    iow(DM9KS_IMR, 0x81); // Enable RX interrupt mask
    /*
    11. Program the RCR register to enable RX. The RX function is enabled by setting the RXEN
    Bit [0] = 1 in the RX control register, RCR REG. 05. Please refer to the datasheet ch.6.6 RCR.
     */
    iow(DM9KS_RXCR, 0x31); /* RX enable */
    /*
    12. NIC is being activated and ready RX/ TX now.
     */

}

UINT8 send_frame(UCHAR *outbuf, UINT16 len)
{
    UINT8 TX_request, TX_status;
    UINT16 *eth, i, j, k, length, length_a;
    //edit by fae
    #if 1
        UINT16 save_mwr, calc_mwr, check_mwr;
    #endif
    j = 0;
    k = 0;
    length = len;

    //edit by fae
    #if 0
        TX_request = ior(DM9KS_TCR);
        if (TX_request &1)
        {
            TX_status = ior(DM9KS_NSR);
            while (!(TX_status &(4 | 8)))
            {
                TX_status = ior(DM9KS_NSR);
                j++;
                if (j > 10000)
                    break;
            }
        }
    #else
        while (ior(DM9KS_TCR) &0x01)
        {
            delay(5);
        }

        save_mwr = (ior(0xfb) << 8) | ior(0xfa);
        calc_mwr = save_mwr + length;
        if (length &0x01)
            calc_mwr++;
        if (calc_mwr > 0x0bff)
            calc_mwr -= 0x0c00;
    #endif

    iow(DM9KS_IMR, 0x80); /* RX interrupt enable */

    eth = (UINT16*)outbuf;

    DM9000_INDEX = DM9KS_MWCMD;
    if (Move_Fault_Flag == 1)
    {
        i = 0;
        length_a = 58;
        while (length_a)
        {
            if ((length_a % 2) == 1)
                length_a += 1;
            length_a -= 2;
            DM9000_DATA = outbuf[i] | (outbuf[i + 1] << 8);
            i += 2;
        }
        eth = (UINT16*)dm9k_pointer;	// 0
        move_eth_data(eth);
        eth = (UINT16*)(dm9k_pointer+192); // 768=0+768
        move_eth_data(eth);
        eth = (UINT16*)(dm9k_pointer+384); // 19968=768+19200
        move_eth_data(eth);
        eth = (UINT16*)(dm9k_pointer+576); // 20736=19968+768
        move_eth_data(eth);
        eth = (UINT16*)(dm9k_pointer+768); // 39936=20736+19200
        move_eth_data(eth);
        eth = (UINT16*)(dm9k_pointer+960); // 40704=39936+768
        move_eth_data(eth);
        DM9000_DATA = outbuf[1210] | (outbuf[1211] << 8);
        Move_Fault_Flag = 0;
    }
    else
    {
        i = 0;
        while (length)
        {
            if ((length % 2) == 1)
                length += 1;
            length -= 2;
            DM9000_DATA = outbuf[i] | (outbuf[i + 1] << 8);
            i += 2;
        }
    }

    iow(DM9KS_TXPLL, len &0xff);
    iow(DM9KS_TXPLH, ((len >> 8) &0xff));
    iow(DM9KS_TCR, 0x01);
    TX_status = ior(0x01);

    //edit by fae
    #if 0
        TX_status = ior(0x01);

        while (!(TX_status &(4 | 8)))
        {
            TX_status = ior(0x01);
            k++;
            if (k > 10000)
                break;
        }
    #else
        check_mwr = (ior(0xfb) << 8) | ior(0xfa);

        if (calc_mwr != check_mwr)
        {
            // print err info .....
            iow(0xfb, (calc_mwr >> 8) &0xff);
            iow(0xfa, calc_mwr &0xff);
        }
    #endif

    iow(DM9KS_IMR, 0x81); /* RX interrupt enable */
    return 0;
}

//------------------------------------------------------------------------
// This function gets an incoming Ethernet frame from the 8900.
// There may be more than 1 waiting but just allocate memory for
// one and read one in.  Use the 8900 to queue incoming packets.
//------------------------------------------------------------------------
UINT8 rcve_frame(UINT16 RxEvent)
{
    int i, j;
    UINT16 rxlen, mydata, RX_length;
    UINT8 *inbuf, DA[6], SA[6], MAC_Addr[6], RX_ready, INT_status, RX_status;

    //edit by fae
    #if 1
        UINT16 save_mrr, calc_mrr, check_mrr;
    #endif

    inbuf = ETH_Rbuf;

    //	INT_status = ior(DM9KS_ISR); /* got DM9000A interrupt status in ISR REG. FEH */
    //	if (INT_status & 0x01)
    //	{
    ior(DM9KS_MRCMDX);
    save_mrr = (ior(0xf5) << 8) | ior(0xf4);
    RX_ready = ior(DM9KS_MRCMDX);
    if (RX_ready ==0x1)
    {
    	do
    	{
            DM9000_INDEX = DM9KS_MRCMD;
            RX_status = DM9000_DATA;
            RX_length = DM9000_DATA;
            eth_len = RX_length;
            //edit by fae
            #if 0
                if (RX_length > PKTSIZE_ALIGN)
                    return 0;
            #else
                calc_mrr = save_mrr + 4+RX_length;
                if (RX_length &0x01)
                    calc_mrr++;
                if (calc_mrr > 0x3fff)
                    calc_mrr -= 0x3400;
    
                if (RX_length > PKTSIZE_ALIGN)
                {
                    iow(0xf5, (calc_mrr >> 8) &0xff);
                    iow(0xf4, calc_mrr &0xff);
                    return 0;
                }
            #endif
            j = 0;
            for (i = 0; i < 3; i++)
            {
                mydata = DM9000_DATA;
                DA[j] = mydata &0xff;
                DA[j + 1] = mydata >> 8;
                j += 2;
            }
            j = 0;
            for (i = 0; i < 3; i++)
            {
                mydata = DM9000_DATA;
                SA[j] = mydata &0xff;
                SA[j + 1] = mydata >> 8;
                j += 2;
            }
            for (i = 0; i < 6; i++)
                *inbuf++ = DA[i];
            for (i = 0; i < 6; i++)
                *inbuf++ = SA[i];
    
            for (i = (RX_length - 12) >> 1; i > 0; i--)
            {
                mydata = DM9000_DATA;
                *inbuf++ = mydata &0xff;
                *inbuf++ = mydata >> 8;
            }
            //edit by fae
            #if 1
                check_mrr = (ior(0xf5) << 8) | ior(0xf4);
    
                if (calc_mrr != check_mrr)
                {
                    // print err info .....
                    iow(0xf5, (calc_mrr >> 8) &0xff);
                    iow(0xf4, calc_mrr &0xff);
                }
            #endif
            if((RX_length - 4) > 0)
            	TCT_Activate_HISR(ETH_HISR);           
    	}while(ior(DM9KS_MRCMDX)==0x1);
    	 //return (RX_length - 4); //减去校验和4个字节
    }
    else if(RX_ready != 0)
    {
    	iow(DM9KS_RXCR, 0x30); /* RX enable */
    	iow(DM9KS_NCR, 0x03);
    	delay(100);
    	iow(DM9KS_NCR, 0x03);
    	delay(100);
    	iow(DM9KS_RXCR, 0x31); /* RX enable */
        return (0);
    }
    //    	iow(DM9KS_ISR,0x01);/* clear the PR Bit [0] latched in ISR REG. FEH */		
    //	}
}


void eth_send(UCHAR *outbuf, UCHAR *hwaddr)
{
    ETH_HEADER eth;
    UCHAR i, j, k;


    // eth = (ETH_HEADER *)outbuf;	
    // Add 14 byte Ethernet header
    //memcpy(eth.dest_hwaddr,hwaddr,6);
    eth.dest_hwaddr[0] = hwaddr[0];
    eth.dest_hwaddr[1] = hwaddr[1];
    eth.dest_hwaddr[2] = hwaddr[2];
    eth.dest_hwaddr[3] = hwaddr[3];
    eth.dest_hwaddr[4] = hwaddr[4];
    eth.dest_hwaddr[5] = hwaddr[5];
    // DA
    //memcpy(eth.source_hwaddr,my_hwaddr,6);
    eth.source_hwaddr[0] = my_hwaddr[0];
    eth.source_hwaddr[1] = my_hwaddr[1];
    eth.source_hwaddr[2] = my_hwaddr[2];
    eth.source_hwaddr[3] = my_hwaddr[3];
    eth.source_hwaddr[4] = my_hwaddr[4];
    eth.source_hwaddr[5] = my_hwaddr[5];
    // SA
    eth.frame_type = ETH_ptype;
    // TYPE
    i = 0;
    for (j = 0; j < 6; j++)
        outbuf[i++] = eth.dest_hwaddr[j];
    for (j = 0; j < 6; j++)
        outbuf[i++] = eth.source_hwaddr[j];
    outbuf[i++] = eth.frame_type >> 8;
    outbuf[i++] = eth.frame_type &0xff;

    // We just added 14 bytes to length
    send_frame(outbuf, (ETH_len + 14));
}

//------------------------------------------------------------------------
// This is the handler for incoming Ethernet frames
//	This is designed to handle standard Ethernet (RFC 893) frames
// See "TCP/IP Illustrated, Volume 1" Sect 2.2
//------------------------------------------------------------------------


void ethuser_send(UCHAR *outbuf, UINT len, UCHAR nr)
{
    TCP_HEADER tcp;
    IP_HEADER ip;
    ULONG sum;
    UINT result;

    // Fill in TCP segment header
    // tcp = (TCP_HEADER *)(outbuf + 34);
    // ip = (IP_HEADER *)(outbuf + 14);

    tcp.source_port = APPL_PORT1;
    tcp.dest_port = conxn[nr].port;
    tcp.sequence = conxn[nr].my_sequence;
    tcp.ack_number = conxn[nr].his_sequence;

    // Header is always 20 bytes long
    tcp.flags = 0x5000 | FLG_ACK | FLG_PSH;
    //tcp.window=1024;
    tcp.window = 8192;
    tcp.checksum = 0;
    tcp.urgent_ptr = 0;
    outbuf[34] = tcp.source_port >> 8;
    outbuf[35] = tcp.source_port &0xff;
    outbuf[36] = tcp.dest_port >> 8;
    outbuf[37] = tcp.dest_port &0xff;
    outbuf[38] = tcp.sequence >> 24;
    outbuf[39] = (tcp.sequence >> 16) &0xff;
    outbuf[40] = (tcp.sequence >> 8) &0xff;
    outbuf[41] = tcp.sequence &0xff;
    outbuf[42] = tcp.ack_number >> 24;
    outbuf[43] = (tcp.ack_number >> 16) &0xff;
    outbuf[44] = (tcp.ack_number >> 8) &0xff;
    outbuf[45] = tcp.ack_number &0xff;
    outbuf[46] = tcp.flags >> 8;
    outbuf[47] = tcp.flags &0xff;
    outbuf[48] = tcp.window >> 8;
    outbuf[49] = tcp.window &0xff;
    outbuf[50] = tcp.checksum >> 8;
    outbuf[51] = tcp.checksum &0xff;
    outbuf[52] = tcp.urgent_ptr >> 8;
    outbuf[53] = tcp.urgent_ptr &0xff;

    // Compute checksum including 12 bytes of pseudoheader
    // Must pre-fill 2 items in ip header to do this
    ip.dest_ipaddr = conxn[nr].ipaddr;
    ip.source_ipaddr = my_ipaddr;
    outbuf[26] = ip.source_ipaddr >> 24;
    outbuf[27] = (ip.source_ipaddr >> 16) &0xff;
    outbuf[28] = (ip.source_ipaddr >> 8) &0xff;
    outbuf[29] = ip.source_ipaddr &0xff;
    outbuf[30] = ip.dest_ipaddr >> 24;
    outbuf[31] = (ip.dest_ipaddr >> 16) &0xff;
    outbuf[32] = (ip.dest_ipaddr >> 8) &0xff;
    outbuf[33] = ip.dest_ipaddr &0xff;

    // Sum source_ipaddr, dest_ipaddr, and entire TCP message
    sum = (ULONG)cksum(outbuf + 26, 8+len);

    // Add in the rest of pseudoheader which is
    // protocol id and TCP segment length
    sum += (ULONG)0x0006;
    sum += (ULONG)len;

    // In case there was a carry, add it back around
    result = (UINT)(sum + (sum >> 16));
    tcp.checksum = ~result;
    outbuf[50] = tcp.checksum >> 8;
    outbuf[51] = tcp.checksum &0xff;

    IP_protocol = 6;
    IP_len = len;

    ip_send(outbuf, conxn[nr].ipaddr);

    // (Re)start TCP retransmit timer
    conxn[nr].timer = TCP_TIMEOUT;
}

UINT user_server_1(UCHAR *inbuf, UINT header_len, UCHAR nr, UCHAR resend)
{
    UCHAR *tcp_data, i;
    UINT16 len;

    if (nr == NO_CONNECTION)
        return 0;

    if (!resend)
    {
        tcp_data = inbuf + 34+header_len;
        //memcpy(conxn[nr].query,tcp_data,20);
        for (i = 0; i < 20; i++)
            conxn[nr].query[i] = tcp_data[i];
        conxn[nr].old_sequence = conxn[nr].my_sequence;
    }
    // If this is a resend, set sequence number to what it was
    // the last time we sent this
    else
    {
        tcp_data = inbuf;
        conxn[nr].my_sequence = conxn[nr].old_sequence;
    }
    len = user_server(inbuf, header_len, nr, resend);
    //conxn[nr].my_sequence+=len;
}

⌨️ 快捷键说明

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