www.pudn.com > PICTCPIP.rar > ethmod.c
/*///////////////////////////////////////////////////////////////////// // REALTEK RTL8019AS DRIVER // PACKET WHACKER // Author: Fred Eady // Version: 1.0 // Date: 10/13/01 // Description: ARP, PING, ECHO and Control, TCP /////////////////////////////////////////////////////////////////////*/ /*#include <16f877.h> #include*/ /*//#device PIC16F877 *=16*/ /*#include /*#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,WRT #use delay(clock=20000000) /*#use delay(clock=196620800) /*PICDEM.net* #use rs232(baud=2400,xmit=PIN_C6, rcv=PIN_C7) #use fast_io(A) #use fast_io(B) #use fast_io(C) #use fast_io(D) #use fast_io(E)*/ /*#define esc 0x1B /******************************************************************/ /* FUNCTION PROTOTYPES*/ /******************************************************************/ void show_aux_packet(); void dump_header(); void readwrite(); void bin2hex(binchar); void show_regs(); void show_packet(); void cls(); void application_code(); void tcp(); void assemble_ack(); void write_creg(int regaddr, int regdata); char read_creg(int regaddr); void get_packet(); void setipaddrs(); void cksum(); void echo_packet(); void send_tcp_packet(); void arp(); void icmp(); void udp(); /****************************************************************** //* IP ADDRESS DEFINITION //* This is the Ethernet Module IP address. //* You may change this to any valid address. /******************************************************************/ const unsigned char MYIP[4] = { 192,168,254,100 }; /******************************************************************/ /* HARDWARE (MAC) ADDRESS DEFINITION //* This is the Ethernet Module hardware address. //* You may change this to any valid address. //******************************************************************/ const unsigned char MYMAC[6] = { 0,'V','O','L','T','S' }; const unsigned char EDTP[23]={"\r\nEDTP Telnet Server>"}; /******************************************************************/ /* Receive Ring Buffer Header Layout //* This is the 4-byte header that resides infront of the //* data packet in the receive buffer. /*****************************************************************/ sreg unsigned char pageheader[4]; #define enetpacketstatus 0x00 #define nextblock_ptr 0x01 #define enetpacketLenL 0x02 #define enetpacketLenH 0x03 /****************************************************************** /* Ethernet Header Layout ******************************************************************/ sreg unsigned char packet[96]; /*//50 bytes of UDP data available*/ #define enetpacketDest0 0x00 /*//destination mac address*/ #define enetpacketDest1 0x01 #define enetpacketDest2 0x02 #define enetpacketDest3 0x03 #define enetpacketDest4 0x04 #define enetpacketDest5 0x05 #define enetpacketSrc0 0x06 /*//source mac address*/ #define enetpacketSrc1 0x07 #define enetpacketSrc2 0x08 #define enetpacketSrc3 0x09 #define enetpacketSrc4 0x0A #define enetpacketSrc5 0x0B #define enetpacketType0 0x0C /*type/length field*/ #define enetpacketType1 0x0D #define enetpacketData 0x0E /*IP data area begins here*/ /****************************************************************** //* ARP Layout //******************************************************************/ #define arp_hwtype 0x0E #define arp_prtype 0x10 #define arp_hwlen 0x12 #define arp_prlen 0x13 #define arp_op 0x14 #define arp_shaddr 0x16 /*arp source mac address*/ #define arp_sipaddr 0x1C /*arp source ip address*/ #define arp_thaddr 0x20 /*arp target mac address*/ #define arp_tipaddr 0x26 /*arp target ip address*/ /****************************************************************** //* IP Header Layout //******************************************************************/ #define ip_vers_len 0x0E /*/IP version and header length*/ #define ip_tos 0x0F /*/IP type of service*/ #define ip_pktlen 0x10 /*/packet length*/ #define ip_id 0x12 /*/datagram id*/ #define ip_frag_offset 0x14 /*/fragment offset*/ #define ip_ttl 0x16 /*/time to live*/ #define ip_proto 0x17 /*/protocol (ICMP=1, TCP=6, UDP=11)*/ #define ip_hdr_cksum 0x18 /*/header checksum*/ #define ip_srcaddr 0x1A /*/IP address of source*/ #define ip_destaddr 0x1E /*/IP addess of destination*/ #define ip_data 0x22 /*/IP data area*/ /****************************************************************** //* TCP Header Layout //******************************************************************/ #define TCP_srcport 0x22 /*/TCP source port*/ #define TCP_destport 0x24 /*/TCP destination port*/ #define TCP_seqnum 0x26 /*/sequence number*/ #define TCP_acknum 0x2A /*/acknowledgement number*/ #define TCP_hdrflags 0x2E /*/4-bit header len and flags*/ #define TCP_window 0x30 /*/window size*/ #define TCP_cksum 0x32 /*/TCP checksum*/ #define TCP_urgentptr 0x34 /*/urgent pointer*/ #define TCP_data 0x36 /*option/data*/ /****************************************************************** //* TCP Flags //* IN flags represent incoming bits //* OUT flags represent outgoing bits //******************************************************************/ #define FIN_IN packet[TCP_hdrflags+1].0 #define SYN_IN packet[TCP_hdrflags+1].1 #define RST_IN packet[TCP_hdrflags+1].2 #define PSH_IN packet[TCP_hdrflags+1].3 #define ACK_IN packet[TCP_hdrflags+1].4 #define URG_IN packet[TCP_hdrflags+1].5 #define FIN_OUT packet[TCP_hdrflags+1].0=1; #define SYN_OUT packet[TCP_hdrflags+1].1=1; #define RST_OUT packet[TCP_hdrflags+1].2=1; #define PSH_OUT packet[TCP_hdrflags+1].3=1; #define ACK_OUT packet[TCP_hdrflags+1].4=1; #define URG_OUT packet[TCP_hdrflags+1].5=1; /****************************************************************** //* Port Definitions //* This address is used by TCP and the Telnet function. //* This can be changed to any valid port number as long as //* you modify your code to recognize the new port number. //******************************************************************/ #define MY_PORT_ADDRESS 0x1F98 /* 8088 DECIMAL*/ /****************************************************************** //* IP Protocol Types //******************************************************************/ #define PROT_ICMP 0x01 #define PROT_TCP 0x06 #define PROT_UDP 0x11 /****************************************************************** //* ICMP Header //******************************************************************/ #define ICMP_type ip_data #define ICMP_code ICMP_type+1 #define ICMP_cksum ICMP_code+1 #define ICMP_id ICMP_cksum+2 #define ICMP_seqnum ICMP_id+2 #define ICMP_data ICMP_seqnum+2 /****************************************************************** //* UDP Header //;******************************************************************/ #define UDP_srcport ip_data #define UDP_destport UDP_srcport+2 #define UDP_len UDP_destport+2 #define UDP_cksum UDP_len+2 #define UDP_data UDP_cksum+2 /****************************************************************** //* REALTEK CONTROL REGISTER OFFSETS //* All offsets in Page 0 unless otherwise specified //******************************************************************/ #define CR 0x00 #define PSTART 0x01 #define PAR0 0x01 /* Page 1*/ #define CR9346 0x01 /* Page 3*/ #define PSTOP 0x02 #define BNRY 0x03 #define TSR 0x04 #define TPSR 0x04 #define TBCR0 0x05 #define NCR 0x05 #define TBCR1 0x06 #define ISR 0x07 #define CURR 0x07 /* Page 1*/ #define RSAR0 0x08 #define CRDA0 0x08 #define RSAR1 0x09 #define CRDAL 0x09 #define RBCR0 0x0A #define RBCR1 0x0B #define RSR 0x0C #define RCR 0x0C #define TCR 0x0D #define CNTR0 0x0D #define DCR 0x0E #define CNTR1 0x0E #define IMR 0x0F #define CNTR2 0x0F #define RDMAPORT 0X10 #define RSTPORT 0x18 /****************************************************************** //* RTL8019AS INITIAL REGISTER VALUES //******************************************************************/ #define rcrval 0x04 #define tcrval 0x00 #define dcrval 0x58 /* was 0x48*/ #define imrval 0x11 /* PRX and OVW interrupt enabled*/ #define txstart 0x40 #define rxstart 0x46 #define rxstop 0x60 /****************************************************************** //* RTL8019AS 9346 EEPROM PIN DEFINITIONS //******************************************************************/ #define cregaddr p0 #define cregdata p2 #define tocreg pm2=0x00; #define fromcreg pm2=0xFF; /****************************************************************** //* RTL8019AS 9346 EEPROM PIN DEFINITIONS //******************************************************************/ /*#define EESK PORTB,5 #define EEDI PORTB,6 #define EEDO PORTA,0*/ /****************************************************************** //* RTL8016AS PIN DEFINITIONS //******************************************************************/ #define INT0 p3.0 #define ior_pin p1.0 #define iow_pin p1.1 #define rst_pin p2.4 /****************************************************************** //* RTL8016AS ISR REGISTER DEFINITIONS //******************************************************************/ #define RST 0x07 #define RDC 0x06 #define OVW 0x04 #define PRX 0x00 /****************************************************************** //* PIC16F87X RAM Definitions //******************************************************************/ sreg unsigned char aux_data[16]; /*//received data area*/ sreg unsigned char *addr; sreg unsigned char byte_read,data_H,data_L; sreg unsigned char high_nibble, low_nibble, high_char, low_char,resend; sreg unsigned int i,txlen,rxlen,chksum16,hdrlen,tcplen,tcpdatalen_in; sreg unsigned int tcpdatalen_out,ISN,portaddr,ip_packet_len; sreg unsigned long hdr_chksum,my_seqnum,client_seqnum,incoming_ack,expected_ack; sreg unsigned short synflag,finflag; #define set_packet32(d,s) packet[d] = make8(s,3); \ packet[d+1] = make8(s,2); \ packet[d+2] = make8(s,1); \ packet[d+3]= make8(s,0); \ /****************************************************************** //* Application Code //* Your application code goes here. //* This particular code toggles the LED on PORT A bit 4 using //* Telnet. //******************************************************************/ void application_code() { if(aux_data[0] != 0x0A) tcpdatalen_out = tcpdatalen_in; if(aux_data[0] == 0x0A) tcpdatalen_out = 0x00; if(aux_data[0] == '0') /*;p3.0=1;/*bit_set(PORTA,4);*/ if (aux_data[0] == '1') /*;p3.0=0;/*bit_clear(PORTA,4);*/ if (aux_data[0] == 0x0D) { /*strcpy(packet[TCP_data],"EDTP[0]\r\nEDTP Telnet Server>");/ strcpy(packet[TCP_data],packet[4]);*/ tcpdatalen_out = 21; } } /****************************************************************** //* Perform ARP Response //* This routine supplies a requesting computer with the //* Ethernet modules's MAC (hardware) address. //******************************************************************/ void arp() { /*start the NIC*/ write_creg(CR,0x22); /*load beginning page for transmit buffer*/ write_creg(TPSR,txstart); /*set start address for remote DMA operation*/ write_creg(RSAR0,0x00); write_creg(RSAR1,0x40); /*clear the Interrupts*/ write_creg(ISR,0xFF); /*load data byte count for remote DMA*/ write_creg(RBCR0,0x3C); write_creg(RBCR1,0x00); /*do remote write operation*/ write_creg(CR,0x12); /*write destination MAC address*/ for(i=0;i<6;++i) write_creg(RDMAPORT,packet[enetpacketSrc0+i]); /*write source MAC address*/ for(i=0;i<6;++i) write_creg(RDMAPORT,MYMAC[i]); /*write typelen hwtype prtype hwlen prlen op:*/ addr = &packet[enetpacketType0]; packet[arp_op+1] = 0x02; for(i=0;i<10;++i) write_creg(RDMAPORT,*addr++); /*write ethernet module MAC address*/ for(i=0;i<6;++i) write_creg(RDMAPORT,MYMAC[i]); /*write ethernet module IP address*/ for(i=0;i<4;++i) write_creg(RDMAPORT,MYIP[i]); /*write remote MAC address*/ for(i=0;i<6;++i) write_creg(RDMAPORT,packet[enetpacketSrc0+i]); /*write remote IP address*/ for(i=0;i<4;++i) write_creg(RDMAPORT,packet[arp_sipaddr+i]); /*write some pad characters to fill out the packet to*/ /*the minimum length*/ for(i=0;i<0x12;++i) write_creg(RDMAPORT,0x00); /*make sure the DMA operation has successfully completed*/ byte_read = 0; while(!bit_test(byte_read,RDC)) read_creg(ISR); /*load number of bytes to be transmitted*/ write_creg(TBCR0,0x3C); write_creg(TBCR1,0x00); /*send the contents of the transmit buffer onto the network*/ write_creg(CR,0x24); } /****************************************************************** //* Perform ICMP Function //* This routine responds to a ping. //******************************************************************/ void icmp() { /*set echo reply*/ packet[ICMP_type]=0x00; packet[ICMP_code]=0x00; /*clear the ICMP checksum*/ packet[ICMP_cksum ]=0x00; packet[ICMP_cksum+1]=0x00; /*setup the IP header*/ setipaddrs(); /*calculate the ICMP checksum*/ hdr_chksum =0; hdrlen = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) - ((packet[ip_vers_len] & 0x0F) * 4); addr = &packet[ICMP_type]; cksum(); chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16)); packet[ICMP_cksum] = make8(chksum16,1); packet[ICMP_cksum+1] = make8(chksum16,0); /*send the ICMP packet along on its way*/ echo_packet(); } /****************************************************************** //* UDP Function //* This function uses a Visual Basic UDP program to echo the //* data back to the VB program and set or reset PORT A bit 4 //* under control of the VB program. //******************************************************************/ void udp() { /*port 7 is the well-known echo port*/ if(packet[UDP_destport] == 0x00 && packet[UDP_destport+1] ==0x07) { /*build the IP header*/ setipaddrs(); /*swap the UDP source and destination ports*/ data_L = packet[UDP_srcport]; packet[UDP_srcport] = packet[UDP_destport]; packet[UDP_destport] = data_L; data_L = packet[UDP_srcport+1]; packet[UDP_srcport+1] = packet[UDP_destport+1]; packet[UDP_destport+1] = data_L; /*calculate the UDP checksum*/ packet[UDP_cksum] = 0x00; packet[UDP_cksum+1] = 0x00; hdr_chksum =0; hdrlen = 0x08; addr = &packet[ip_srcaddr]; cksum(); hdr_chksum = hdr_chksum + packet[ip_proto]; hdrlen = 0x02; addr = &packet[UDP_len]; cksum(); hdrlen = make16(packet[UDP_len],packet[UDP_len+1]); addr = &packet[UDP_srcport]; cksum(); chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16)); packet[UDP_cksum] = make8(chksum16,1); packet[UDP_cksum+1] = make8(chksum16,0); /*echo the incoming data back to the VB program*/ echo_packet(); } /*buttons on the VB GUI are pointed towards port address 5000 decimal*/ else if(packet[UDP_destport] == 0x13 && packet[UDP_destport+1] == 0x88); { if(packet[UDP_data]) /*received a 0x00 from the VB program*/ bit_set(PORTA,4); else /*received a 0xFF from the VB program*/ bit_clear(PORTA,4); } } /****************************************************************** //* TCP Function //* This function uses TCP protocol to act as a Telnet server on //* port 8088 decimal. The application function is called with //* every incoming character. //******************************************************************/ void tcp() { /*assemble the destination port address from the incoming packet*/ portaddr = make16(packet[TCP_destport],packet[TCP_destport+1]); /*calculate the length of the data coming in with the packet*/ /*tcpdatalen_in = incoming packet length - incoming ip header length - incoming tcp header length*/ tcpdatalen_in = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) - ((packet[ip_vers_len] & 0x0F) * 4) - (((packet[TCP_hdrflags] & 0xF0) >> 4) * 4); /*If an ACK is recieved and the destination port address is valid and no data is in the packet*/ if(ACK_IN && portaddr == MY_PORT_ADDRESS && tcpdatalen_in == 0x00) { /*assemble the acknowledgment number from the incoming packet*/ incoming_ack =make32(packet[TCP_acknum],packet[TCP_acknum+1],packet[TCP_acknum+2],packet[TCP_acknum+3]); /*if the incoming packet is a result of session establishment*/ if(synflag) { /*clear the SYN flag*/ synflag = 0; /*the incoming acknowledgment is my new sequence number*/ my_seqnum = incoming_ack; /*send the Telnet server banner*/ /*limit the character count to 40 decimal*/ strcpy(packet[TCP_data],"EASY ETHERNET\r\n1=LED ON\r\n0=LED OFF\r\n>"); /*length of the banner message*/ tcpdatalen_out = 37; /*expect to get an acknowledgment of the banner message*/ expected_ack = my_seqnum +tcpdatalen_out; /*send the TCP/IP packet*/ send_tcp_packet(); } } /*if an ack is received and the port address is valid and there is data in the incoming packet*/ if(ACK_IN && portaddr == MY_PORT_ADDRESS && tcpdatalen_in) { for(i=0;i > 16)); packet[TCP_cksum] = make8(chksum16,1); packet[TCP_cksum+1] = make8(chksum16,0); echo_packet(); } /*this code segment processes a FIN from the Telnet client /*and acknowledges the FIN and any incoming data.*/ if(FIN_IN && portaddr == MY_PORT_ADDRESS) { if(tcpdatalen_in) { for(i=0;i > 16)); packet[TCP_cksum] = make8(chksum16,1); packet[TCP_cksum+1] = make8(chksum16,0); txlen = ip_packet_len + 14; if(txlen < 60) txlen = 60; data_L = make8(txlen,0); data_H = make8(txlen,1); write_creg(CR,0x22); write_creg(TPSR,txstart); write_creg(RSAR0,0x00); write_creg(RSAR1,0x40); write_creg(ISR,0xFF); write_creg(RBCR0,data_L); write_creg(RBCR1,data_H); write_creg(CR,0x12); for(i=0;i 0x09) high_char = high_nibble + 0x37; else high_char = high_nibble + 0x30; low_nibble = (binchar & 0x0F); if(low_nibble > 0x09) low_char = low_nibble + 0x37; else low_char = low_nibble + 0x30; } /****************************************************************** //* Used with Tera Term to clear the screen (VT-100 command) //******************************************************************/ void cls(void) { printf("%c[2J",esc); } /****************************************************************** //* show_packet //* This routine is for diagnostic purposes and displays //* the Packet Buffer memory in the PIC. //******************************************************************/ void show_packet() { cls(); printf("\r\n"); data_L = 0x00; for(i=0;i<96;++i) { bin2hex(packet[i]); printf(" %c%c",high_char,low_char); if(++data_L == 0x10) { data_L = 0x00; printf("\r\n"); } } } /****************************************************************** //* show_aux_packet //* This routine is a diagnostic that displays Auxillary //* Packet Buffer buffer memory in the PIC. //******************************************************************/ void show_aux_packet() { cls(); printf("\r\n"); data_L = 0x00; for(i=0;i<80;++i) { bin2hex(aux_data[i]); printf(" %c%c",high_char,low_char); if(++data_L == 0x10) { data_L = 0x00; printf("\r\n"); } } } /****************************************************************** //* Write to NIC Control Register //******************************************************************/ void write_creg(int regaddr, int regdata) { cregaddr = regaddr; cregdata = regdata; tocreg; iow_pin=0;/*bit_clear(iow_pin);*/ delay_cycles(1); iow_pin=1;/*bit_set(iow_pin);*/ fromcreg; } /****************************************************************** //* Read From NIC Control Register //******************************************************************/ char read_creg(int regaddr) { fromcreg; cregaddr = regaddr; ior_pin=0;/*bit_clear(ior_pin);*/ byte_read = input_d(); ior_pin=1;/*bit_set(ior_pin);*/ return(byte_read); } /****************************************************************** //* Detect EEPROM Clock from RTL8019AS //******************************************************************/ void clock_9346() { #asm chk_is_lo: btfss EESK goto chk_is_lo chk_is_hi: btfsc EESK goto chk_is_hi #endasm } /****************************************************************** //* Emulate the presence of a 9346 EEPROM //******************************************************************/ void fakeout_9346() { char reps,clocks,datum; #asm movlw 0x02 movwf reps reload: bcf EEDO movlw 0x03 /*0x03=half duplex 0x07=full duplex*/ movwf datum #endasm start_bit: clock_9346(); #asm btfss EEDI goto start_bit #endasm clock_9346(); #asm btfss EEDI goto start_bit #endasm clock_9346(); #asm btfsc EEDI goto start_bit movlw 0x06 movwf clocks #endasm addr: clock_9346(); #asm decfsz clocks,1 goto addr movlw 0x10 movwf clocks bcf C #endasm send: clock_9346(); #asm movf datum,0 movwf PORTA rrf datum,1 decfsz clocks,1 goto send decfsz reps,1 goto reload bcf EEDO #endasm } /****************************************************************** //* Handle Receive Ring Buffer Overrun //* No packets are recovered //******************************************************************/ void overrun() { read_creg(CR); data_L = byte_read; write_creg(CR,0x21); delay_ms(2); write_creg(RBCR0,0x00); write_creg(RBCR1,0x00); if(!bit_test(data_L,2)) resend = 0; else if(bit_test(data_L,2)) { read_creg(ISR); data_L = byte_read; if(bit_test(data_L,1) || bit_test(data_L,3)) resend = 0; else resend = 1; } write_creg(TCR,0x02); write_creg(CR,0x22); write_creg(BNRY,rxstart); write_creg(CR,0x62); write_creg(CURR,rxstart); write_creg(CR,0x22); write_creg(ISR,0x10); write_creg(TCR,tcrval); } /****************************************************************** //* Echo Packet Function //* This routine does not modify the incoming packet size and //* thus echoes the original packet structure. //******************************************************************/ void echo_packet() { write_creg(CR,0x22); write_creg(TPSR,txstart); write_creg(RSAR0,0x00); write_creg(RSAR1,0x40); write_creg(ISR,0xFF); write_creg(RBCR0,pageheader[enetpacketLenL] - 4 ); write_creg(RBCR1,pageheader[enetpacketLenH]); write_creg(CR,0x12); txlen = make16(pageheader[enetpacketLenH],pageheader[enetpacketLenL]) - 4; for(i=0;i > 16)); packet[ip_hdr_cksum] = make8(chksum16,1); packet[ip_hdr_cksum+1] = make8(chksum16,0); } /****************************************************************** //* CHECKSUM CALCULATION ROUTINE //******************************************************************/ void cksum() { while(hdrlen > 1) { data_H=*addr++; data_L=*addr++; chksum16=make16(data_H,data_L); hdr_chksum = hdr_chksum + chksum16; hdrlen -=2; } if(hdrlen > 0) { data_H=*addr; data_L=0x00; chksum16=make16(data_H,data_L); hdr_chksum = hdr_chksum + chksum16; } } /****************************************************************** //* Initialize the RTL8019AS //******************************************************************/ void init_RTL8019AS() { ADCON1 = 0x06; /*00000110 all digital to start*/ ADCON0 = 0; set_tris_C(0x85); set_tris_A(0x00); bit_clear(EEDO); set_tris_B(0xE0); /* setup address lines*/ cregaddr = 0x00; /* clear address lines*/ fromcreg; /* address lines = input*/ set_tris_E(0x00); /* setup IOW, IOR, RESET*/ iow_pin=1;/*bit_set(iow_pin); disable IOW*/ ior_pin=1;/*bit_set(ior_pin); disable IOR*/ rst_pinb=1;/*it_set(rst_pin); put NIC in reset*/ delay_ms(2); /* delay at least 1.6ms*/ rst_pinb=0;/*bit_clear(rst_pin); /* disable reset line*/ read_creg(RSTPORT); /* read contents of reset port*/ write_creg(RSTPORT,byte_read); /* do soft reset*/ delay_ms(10); /* give it time*/ read_creg(ISR); /* check for good soft reset*/ if(!bit_test(byte_read,RST)){ while(1){ printf("INIT FAILED\n\r"); } } write_creg(CR,0x21); /*stop the NIC, abort DMA, page 0*/ delay_ms(2); /*make sure nothing is coming in or going out*/ write_creg(DCR,dcrval); /*0x58*/ write_creg(RBCR0,0x00); /*clear the DMA byte counters*/ write_creg(RBCR1,0x00); write_creg(RCR,0x04); /*accept broadcast packets */ write_creg(TPSR,txstart); /*set transmit buffer start page */ write_creg(TCR,0x02); write_creg(PSTART,rxstart);//set receive buffer start page*/ write_creg(BNRY,rxstart); /*initialize the boundary */ write_creg(PSTOP,rxstop); /*set receive buffer stop page */ write_creg(CR,0x61); /*stop NIC and change control register page */ delay_ms(2); write_creg(CURR,rxstart); /*write NIC MAC (hardware) address */ for(i=0;i<6;++i) write_creg(PAR0+i, MYMAC[i]); write_creg(CR,0xC1); /*prepare to emulate 9346 EEPROM*/ write_creg(CR9346,0xC0); write_creg(CR9346,0x40); fakeout_9346(); /*emulate the 9348 */ delay_ms(10); write_creg(CR,0x21); /*stop the NIC and go to home page */ write_creg(DCR,dcrval); /*set FIFO threshold, enable Send Packet Command, */ write_creg(CR,0x22); /*start NIC */ write_creg(ISR,0xFF); /*clear interrupts*/ write_creg(IMR,imrval); /*unmask interrupts */ write_creg(TCR,tcrval); /*normal operation and enable CRC */ } /****************************************************************** //* MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN //******************************************************************/ void main() { init_RTL8019AS(); synflag = 0; finflag = 0; /****************************************************************** //* Look for a packet in the receive buffer ring //******************************************************************/ while(1) { /*start the NIC*/ write_creg(CR,0x22); /*wait for a good packet*/ while(!bit_test(INT0)); /*read the interrupt status register*/ read_creg(ISR); /*if the receive buffer has been overrun*/ if(bit_test(byte_read,OVW)) overrun(); /*if the receive buffer holds a good packet*/ if(bit_test(byte_read,PRX)) get_packet(); /*make sure the receive buffer ring is empty*/ /*if BNRY = CURR, the buffer is empty*/ read_creg(BNRY); data_L = byte_read; write_creg(CR,0x62); read_creg(CURR); data_H = byte_read; write_creg(CR,0x22); /*buffer is not empty.. get next packet*/ if(data_L != data_H) get_packet(); /*reset the interrupt bits*/ write_creg(ISR,0xFF); } }