📄 ne2000.c
字号:
// ********************************************************
// *** ***
// *** 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 + -