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

📄 ne2000.c

📁 51单片机控制网卡实现上网程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
// ********************************************************
// ***                                                  ***
// *** This program is intended to demonstrate an       ***
// *** Internet appliance.  Communication with the      ***
// *** Internet will be via an NE2000 compatible        ***
// *** ethernet card.                                   ***
// ***                                                  ***
// ***                                                  ***
// ********************************************************

#include "hostmcu.h"
#include "8019.h"
#include "ylystd.h"

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

#define DEBUG 1

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

#define READ    FALSE
#define WRITE   TRUE


// NIC Other Defines
                                            // 8-bit mode - wasting ram but saving I/O count
#define RCV_BUF_START   0x40                // Room for three full ethernet packets
#define XMT_BUF_START   0x54                // Leave room for two full packet transmit buffers


// ********************************************************
// *** Protocol Defines                                 ***
// ********************************************************

#define ARP     0x0806
#define IP      0x0800

#define ICMP    0x01
#define TCP     0x06
#define UDP     0x17

#define ECHO    0x08
#define REPLY   0x00

#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20


// ********************************************************
// *** My IP address                                    ***
// ********************************************************

// 192.168.1.124

#define MY_IP0  192
#define MY_IP1  168
#define MY_IP2  1
#define MY_IP3  124

char tmpstr[128];

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

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

void    init_pic(void);
void    init_nic(void);
//void    myoutportb(u16_t address, u8_t  dat);
void    myoutportstr(u16_t address, u8_t *str);
void    myoutportw(u16_t address, u16_t dat);
//u8_t    myinportb(u16_t address);
void    remote_dma_setup(short w_r, u16_t address);
void    read_phy_addr(void);
short   poll_nic(void);
void    arp_response(void);
void    load_ethernet_header(void);
void    send_packet(u16_t len);
void    ping_response(void);
void    load_IP_header(u16_t IP_packet_length, u16_t IP_send_protocol);
void    tcp_response(void);
void    load_TCP_header(u16_t data_flags, u16_t tcp_chksum, u16_t tcp_length);
void    calc_chksum(u16_t dat);
void    tcp_listen(void);
void    tcp_syn_rcvd(void);
void    tcp_estab(void);

// ********************************************************
// *** Ethernet variables

u16_t  physical_address[6];
u16_t  source_address[6];

u16_t  my_ip[4];

// ********************************************************
// *** IP Header variables

u16_t  source_ip[4];
u16_t  dest_ip[4];
u16_t  version;
u16_t  IP_length;
u16_t  identification;
u16_t  fragment;
u16_t  IP_protocol;
u16_t  hdr_len;
u16_t  opt_len;
u16_t  chksum;


// ********************************************************
// *** ICMP - ECHO variables

u16_t  icmp_type;
u16_t  icmp_code;
u16_t  icmp_checksum;
u16_t  icmp_identifier;
u16_t  icmp_sequence;

// ********************************************************
// *** TCP Variables

u16_t  tcp_source_port;
u16_t  tcp_dest_port;
u16_t  seq[2];
u16_t  ack[2];
u16_t  offset;
u16_t    tcp_options;
u16_t  flags;
u16_t  window0;
u16_t  max_seg=0;
u16_t  tcp_data_len;

// ********************************************************
// *** Socket Variables

u16_t       xm_ack[2];
u16_t       xm_seq[2];
u16_t       port;
u16_t               ip[4];

enum tcp_states {LISTEN,
                SYN_SENT,
                SYN_RCVD,
                ESTAB,
                FIN_WAIT_1,
                FIN_WAIT_2,
                CLOSING,
                TIME_WAIT,
                CLOSE_WAIT,
                LAST_ACK,
                CLOSED} html_socket;

//tcp_states html_socket;                   // Create variable to track html socket state

void n2k_main(void) {

    my_ip[0] = MY_IP0;                      // Set my IP address
    my_ip[1] = MY_IP1;
    my_ip[2] = MY_IP2;
    my_ip[3] = MY_IP3;

    init_nic();                             // Initialize the NIC
    read_phy_addr();                        // Read the Physical Address from the NIC
    init_nic();                             // Initialize again.  This is a quick way to
                                            // set the Physical Address since we didn't have
                                            // it the first time
    myoutportb(TCR, 0x00);                      // Take the NIC out of Loop Back.  This is the
                                            // last step of the Initialization

    html_socket = LISTEN;
    
    while (TRUE)
    {
        poll_nic();
    }
}


void init_nic(void){

    myoutportb(CR, 0x21);                       // Page 0, Abort DMA, Stop NIC

    delay_ms(25);                           // Wait for it to stop
    myoutportb(NIC_RESET, 0xFF);                // Reset the NIC
    delay_ms(25);                           // Wait for it to reset

    myoutportb(DCR, 0x48);                      // byte DMA, Byte order 8086,
                                            // Dual 16-bit DMA mode, Normal Operation
                                            // Send CMD not executed, FIFO theshold 8 bytes

    myoutportb(RBCR0, 0x00);                    // Clear remote byte count registers
    myoutportb(RBCR1, 0x00);

    myoutportb(RCR, 0x0C);                      // Monitor off, Promiscuous off
                                            // Accept Multicast, Accept Broadcast
                                            // Reject Runts, Reject Errors

    myoutportb(TCR, 0x02);                      // Internal Loop Back

    myoutportb(BNDRY,   RCV_BUF_START);         // Start of Buffer RAM
    myoutportb(PSTART, RCV_BUF_START);          // Start of Buffer RAM
    myoutportb(PSTOP,   XMT_BUF_START);         // 8-bit mode so we need room for transmit buffers
    

    myoutportb(ISR, 0xFF);                      // Clear Interrupt Status Register
    myoutportb(IMR, 0x00);                      // Setup Interrupt Mask Register (No Interrupts)

    myoutportb(CR, 0x61);                       // Page 1

    myoutportb(PAR0, physical_address[0]);      // Physical_Address is not initialized on the
    myoutportb(PAR1, physical_address[1]);      // first pass.  We need to read it from the
    myoutportb(PAR2, physical_address[2]);      // EPROM and set it later
    myoutportb(PAR3, physical_address[3]);
    myoutportb(PAR4, physical_address[4]);
    myoutportb(PAR5, physical_address[5]);

    myoutportb(CURR, 0x40);

    myoutportb(CR, 0x22);                       // Put the NIC in Start mode
                                            // We're still in Loop Back so nothing should happen    
}

// ********************************************************
void  myoutportstr(u16_t address, u8_t *str)
{
    u16_t idx;
    for(idx=0;idx<strlen(str);idx++)
    {
        myoutportb(address,(u8_t)str[idx]);
    }
}
// ********************************************************
// *** myoutportw                                       ***
// *** Output one word of 'dat' to the specified       ***
// *** 'address'                                        ***
// ********************************************************

void myoutportw(u16_t address, u16_t dat) {

    u16_t prev_chksum;                  // Declare temporary storage for checksum

    prev_chksum = chksum;                   // Keep a copy of the current checksum

    myoutportb(address,dat>>8);
    myoutportb(address,dat);

    chksum += dat;                         // Add the dat word to the checksum
    if (chksum < prev_chksum )              // Check if a carry was generated
        chksum++;                           // Do the ones compliment if requred

}

// ********************************************************
void calc_chksum(u16_t dat) {

    u16_t prev_chksum;

    chksum += dat;
    if (chksum < prev_chksum)
        chksum ++;
    }

// ********************************************************
void remote_dma_setup(short w_r, u16_t address){

    myoutportb(CR, 0x22);                       // Abort Remote DMA
    myoutportb(RBCR0, 0xFF);                    // Set maximum number of bytes to read/write
    myoutportb(RBCR1, 0xFF);
    myoutportb(RSAR0, address);
    myoutportb(RSAR1, address>>8);

    if (w_r) {
        myoutportb(CR, 0x12);
        }
    else {
        myoutportb(CR, 0x0A);
        }
    }

// ********************************************************
void read_phy_addr(void) {
    u16_t ignore;

    remote_dma_setup(FALSE, 0x0000);

    physical_address[0] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);
    physical_address[1] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);
    physical_address[2] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);
    physical_address[3] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);
    physical_address[4] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);
    physical_address[5] = myinportb(NIC_DATA);
    ignore = myinportb(NIC_DATA);

    ignore=ignore;

    }

// ********************************************************
short poll_nic(void) {

    u16_t in, out;
    u16_t i;
    u16_t status, next_ptr;
    u16_t type;
    u16_t kind;



    myoutportb(CR, 0x62);                       // Page 1
    in = myinportb(CURR);                       // Get the current input pointer
    myoutportb(CR, 0x22);                       // Page 0
    out = myinportb(BNDRY);                 // Get the current output pointer

    if (in != out) {

        // *** Data is present so we better retrieve it
        remote_dma_setup(READ, (u16_t)out<<8);

        /*status = */
        myinportb(NIC_DATA);
        next_ptr = myinportb(NIC_DATA);

        // *** Clear out the byte count and dest address
        for (i=0 ; i<8 ; i++)
            myinportb(NIC_DATA);

        // *** Retrieve source hardware address
        for (i=0 ; i<6 ; i++)
            source_address[i] = myinportb(NIC_DATA);

        // *** Retrieve ethernet message type
        type = (u16_t)myinportb(NIC_DATA)<<8;
        type = type + myinportb(NIC_DATA);

        switch (type) {

            case ARP:

                #if DEBUG == 1
                    trans_str("ARP");
                #endif

                // discard unneeded bytes (address space, protocol address space,
                //                          length of hardware address, length of
                //                          protocol address, opcode)

                for (i=0; i<8 ; i++)
                    myinportb(NIC_DATA);

                // discard source hardware address (we already have it)

                for (i=0; i<6 ; i++)
                    myinportb(NIC_DATA);

                // get ip address of packet source

                for (i=0; i<4 ; i++)
                    source_ip[i] = myinportb(NIC_DATA);

                // discard target hardware address (probably not valid anyway)

                for (i=0; i<6 ; i++)
                    myinportb(NIC_DATA);

                // get ip address of destination

                for (i=0; i<4 ; i++)
                    dest_ip[i] = myinportb(NIC_DATA);

⌨️ 快捷键说明

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