Engravity-CDU / Mbed 2 deprecated EasyWebCR

Dependencies:   mbed

Fork of EasyWebCR by Igor Skochinsky

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcpip.c Source File

tcpip.c

00001 /******************************************************************
00002  *****                                                        *****
00003  *****  Name: tcpip.c                                         *****
00004  *****  Ver.: 1.0                                             *****
00005  *****  Date: 07/05/2001                                      *****
00006  *****  Auth: Andreas Dannenberg                              *****
00007  *****        HTWK Leipzig                                    *****
00008  *****        university of applied sciences                  *****
00009  *****        Germany                                         *****
00010  *****        adannenb@et.htwk-leipzig.de                     *****
00011  *****  Func: implements the TCP/IP-stack and provides a      *****
00012  *****        simple API to the user                          *****
00013  *****                                                        *****
00014  ******************************************************************/
00015 
00016 // Modifications by Code Red Technologies for NXP LPC1768
00017 // Throughout file, functions of form xxx8900() renamed xxx_EthMAC()
00018 // Other changes commented in place
00019 
00020 #include "tcpip.h"
00021 
00022 //CodeRed - added header for LPC ethernet controller
00023 #include "ethmac.h" 
00024 // CodeRed - added library string handling header
00025 #include <string.h>
00026 
00027 // CodeRed - added NXP LPC register definitions header
00028 //#include "LPC17xx.h"
00029 
00030 #include "mbed.h"
00031 
00032 unsigned short MyIP[] =                    // "MYIP1.MYIP2.MYIP3.MYIP4"
00033 {
00034   MYIP_1 + (MYIP_2 << 8),
00035   MYIP_3 + (MYIP_4 << 8)
00036 };
00037 
00038 unsigned short SubnetMask[] =              // "SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
00039 {
00040   SUBMASK_1 + (SUBMASK_2 << 8),
00041   SUBMASK_3 + (SUBMASK_4 << 8)
00042 };
00043 
00044 unsigned short GatewayIP[] =               // "GWIP1.GWIP2.GWIP3.GWIP4"
00045 {
00046   GWIP_1 + (GWIP_2 << 8),
00047   GWIP_3 + (GWIP_4 << 8)
00048 };
00049 
00050 // the next 3 buffers must be word-aligned!
00051 // (here the 'RecdIPFrameLength' above does that)
00052 unsigned short _TxFrame1[(ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + MAX_TCP_TX_DATA_SIZE)/2];
00053 unsigned short _TxFrame2[(ETH_HEADER_SIZE + MAX_ETH_TX_DATA_SIZE)/2];
00054 unsigned short _RxTCPBuffer[MAX_TCP_RX_DATA_SIZE/2]; // space for incoming TCP-data
00055 
00056 unsigned short TxFrame1Size;              // bytes to send in TxFrame1
00057 unsigned char TxFrame2Size;               // bytes to send in TxFrame2
00058 
00059 unsigned char TransmitControl;
00060 #define SEND_FRAME1                    0x01
00061 #define SEND_FRAME2                    0x02
00062 
00063 unsigned char TCPFlags;
00064 #define TCP_ACTIVE_OPEN                0x01      // easyWEB shall initiate a connection
00065 #define IP_ADDR_RESOLVED               0x02      // IP sucessfully resolved to MAC
00066 #define TCP_TIMER_RUNNING              0x04
00067 #define TIMER_TYPE_RETRY               0x08
00068 #define TCP_CLOSE_REQUESTED            0x10
00069 
00070 // easyWEB's internal variables
00071 TTCPStateMachine TCPStateMachine;         // perhaps the most important var at all ;-)
00072 TLastFrameSent LastFrameSent;             // retransmission type
00073 
00074 unsigned short ISNGenHigh;                // upper word of our Initial Sequence Number
00075 unsigned long TCPSeqNr;                   // next sequence number to send
00076 unsigned long TCPUNASeqNr;                // last unaknowledged sequence number
00077                                                  // incremented AFTER sending data
00078 unsigned long TCPAckNr;                   // next seq to receive and ack to send
00079                                                  // incremented AFTER receiving data
00080 unsigned char TCPTimer;                   // inc'd each 262ms
00081 unsigned char RetryCounter;               // nr. of retransmissions
00082 
00083 // properties of the just received frame
00084 unsigned short RecdFrameLength;           // EMAC reported frame length
00085 unsigned short RecdFrameMAC[3];           // 48 bit MAC
00086 unsigned short RecdFrameIP[2];            // 32 bit IP
00087 unsigned short RecdIPFrameLength;         // 16 bit IP packet length
00088 
00089 // easyWEB-API global vars and flags
00090 unsigned short TCPRxDataCount;            // nr. of bytes rec'd
00091 unsigned short TCPTxDataCount;            // nr. of bytes to send
00092 
00093 unsigned short TCPLocalPort;              // TCP ports
00094 unsigned short TCPRemotePort;
00095 
00096 unsigned short RemoteMAC[3];              // MAC and IP of current TCP-session
00097 unsigned short RemoteIP[2];
00098 
00099 unsigned char SocketStatus;
00100 
00101 void  Start_SysTick10ms(void);
00102 
00103 // Code Red - moved myMAC definition in from original cs8900.h
00104 unsigned char MyMAC[6] =   // "M1-M2-M3-M4-M5-M6"
00105 {
00106   MYMAC_6, MYMAC_5, MYMAC_4,
00107   MYMAC_3, MYMAC_2, MYMAC_1
00108 };
00109 
00110 // easyWEB-API function
00111 // initalizes the LAN-controller, reset flags, starts timer-ISR
00112 
00113 void TCPLowLevelInit(void)
00114 {
00115 // CodeRed - comment out original 8900 specific code
00116 /*    
00117   BCSCTL1 &= ~DIVA0;                             // ACLK = XT1 / 4 = 2 MHz
00118   BCSCTL1 |= DIVA1;
00119   TACTL = ID1 | ID0 | TASSEL0 | TAIE;            // stop timer, use ACLK / 8 = 250 kHz, gen. int.
00120   TACTL |= MC1;                                  // start timer in continuous up-mode
00121   _EINT();                                       // enable interrupts
00122   
00123   Init8900();
00124 */
00125   LPC_GPIO1->FIODIR = 1 << 25;               // P1.25 defined as Output (LED)
00126     
00127   Start_SysTick10ms();    // Start SysTick timer running (10ms ticks)
00128   
00129   Init_EthMAC();
00130     
00131   TransmitControl = 0;
00132   TCPFlags = 0;
00133   TCPStateMachine = CLOSED;
00134   SocketStatus = 0;
00135 }
00136 
00137 // easyWEB-API function
00138 // does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming
00139 // connection)
00140 
00141 void TCPPassiveOpen(void)
00142 {
00143   if (TCPStateMachine == CLOSED)
00144   {
00145     TCPFlags &= ~TCP_ACTIVE_OPEN;                // let's do a passive open!
00146     TCPStateMachine = LISTENING;
00147     SocketStatus = SOCK_ACTIVE;                  // reset, socket now active
00148   }
00149 }
00150 
00151 // easyWEB-API function
00152 // does an active open (tries to establish a connection between
00153 // 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')
00154 
00155 void TCPActiveOpen(void)
00156 {
00157   if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING))
00158   {
00159     TCPFlags |= TCP_ACTIVE_OPEN;                 // let's do an active open!
00160     TCPFlags &= ~IP_ADDR_RESOLVED;               // we haven't opponents MAC yet
00161   
00162     PrepareARP_REQUEST();                        // ask for MAC by sending a broadcast
00163     LastFrameSent = ARP_REQUEST;
00164     TCPStartRetryTimer();
00165     SocketStatus = SOCK_ACTIVE;                  // reset, socket now active    
00166   }
00167 }
00168 
00169 // easyWEB-API function
00170 // closes an open connection
00171 
00172 void TCPClose(void)
00173 {
00174   switch (TCPStateMachine)
00175   {
00176     case LISTENING :
00177     case SYN_SENT :
00178     {
00179       TCPStateMachine = CLOSED;
00180       TCPFlags = 0;
00181       SocketStatus = 0;
00182       break;
00183     }
00184     case SYN_RECD :
00185     case ESTABLISHED :
00186     {
00187       TCPFlags |= TCP_CLOSE_REQUESTED;
00188       break;
00189     }
00190   }
00191 }
00192 
00193 // easyWEB-API function
00194 // releases the receive-buffer and allows easyWEB to store new data
00195 // NOTE: rx-buffer MUST be released periodically, else the other TCP
00196 //       get no ACKs for the data it sent
00197 
00198 void TCPReleaseRxBuffer(void)
00199 {
00200   SocketStatus &= ~SOCK_DATA_AVAILABLE;
00201 }
00202 
00203 // easyWEB-API function
00204 // transmitts data stored in 'TCP_TX_BUF'
00205 // NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'
00206 //       * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'
00207 
00208 void TCPTransmitTxBuffer(void)
00209 {
00210   if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT))
00211     if (SocketStatus & SOCK_TX_BUF_RELEASED)
00212     {
00213       SocketStatus &= ~SOCK_TX_BUF_RELEASED;               // occupy tx-buffer
00214       TCPUNASeqNr += TCPTxDataCount;                       // advance UNA
00215       
00216       TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount;
00217       TransmitControl |= SEND_FRAME1;
00218       
00219       LastFrameSent = TCP_DATA_FRAME;
00220       TCPStartRetryTimer();
00221     }
00222 }
00223 
00224 // CodeRed - New function to check if received frame
00225 // was a broadcast message
00226 
00227 // Reads the length of the received ethernet frame and checks if the 
00228 // destination address is a broadcast message or not
00229 unsigned int BroadcastMessage(void)
00230 {
00231   unsigned short FrameDestination[3]; // to hold 48 bit MAC address
00232 
00233   RecdFrameLength = StartReadingFrame();
00234 
00235   // Read destination address
00236   CopyFromFrame_EthMAC(&FrameDestination,  6);
00237   // Save it for reply
00238   CopyFromFrame_EthMAC(&RecdFrameMAC, 6);          
00239 
00240   if ((FrameDestination[0] == 0xFFFF) && 
00241       (FrameDestination[1] == 0xFFFF) && 
00242       (FrameDestination[2] == 0xFFFF)) { 
00243     return(1); // Broadcast message
00244   } else {
00245     return (0);
00246   }
00247 }
00248 
00249 
00250 // easyWEB's 'main()'-function
00251 // must be called from user program periodically (the often - the better)
00252 // handles network, TCP/IP-stack and user events
00253 
00254 void DoNetworkStuff(void)
00255 {
00256 // CodeRed - comment out original cs8900 code
00257 /*
00258     unsigned int ActRxEvent;                       // copy of cs8900's RxEvent-Register
00259 
00260   Write8900(ADD_PORT, PP_RxEvent);               // point to RxEvent
00261   ActRxEvent = Read8900(DATA_PORT);              // read, implied skip the last frame
00262 
00263   if (ActRxEvent & RX_OK)
00264   {
00265     if (ActRxEvent & RX_IA) ProcessEthIAFrame();
00266     if (ActRxEvent & RX_BROADCAST) ProcessEthBroadcastFrame();
00267   }
00268 */
00269     
00270   // Check to see if packet received
00271   if (CheckIfFrameReceived())                     
00272   {
00273     // Was it a broadcast message?  
00274     if (BroadcastMessage()) {
00275       ProcessEthBroadcastFrame();
00276     } 
00277     else {
00278       ProcessEthIAFrame(); 
00279     }
00280     // now release ethernet controller buffer
00281     StopReadingFrame();                             
00282   }
00283   
00284   
00285 // CodeRed - now back to original code
00286   
00287   if (TCPFlags & TCP_TIMER_RUNNING)
00288     if (TCPFlags & TIMER_TYPE_RETRY)
00289     {
00290       if (TCPTimer > RETRY_TIMEOUT)
00291       {
00292         TCPRestartTimer();                       // set a new timeout
00293 
00294         if (RetryCounter)
00295         {
00296           TCPHandleRetransmission();             // resend last frame
00297           RetryCounter--;
00298         }
00299         else
00300         {
00301           TCPStopTimer();
00302           TCPHandleTimeout();
00303         }
00304       }
00305     }
00306     else if (TCPTimer > FIN_TIMEOUT)
00307     {
00308       TCPStateMachine = CLOSED;
00309       TCPFlags = 0;                              // reset all flags, stop retransmission...
00310       SocketStatus &= SOCK_DATA_AVAILABLE;       // clear all flags but data available
00311     }
00312 
00313   switch (TCPStateMachine)
00314   {
00315     case CLOSED :
00316     case LISTENING :
00317     {
00318       if (TCPFlags & TCP_ACTIVE_OPEN)            // stack has to open a connection?
00319         if (TCPFlags & IP_ADDR_RESOLVED)         // IP resolved?
00320           if (!(TransmitControl & SEND_FRAME2))  // buffer free?
00321           {
00322 // CodeRed - change TAR -> TOTC to use LPC1768 clock
00323 //            TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN
00324                TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN
00325             TCPUNASeqNr = TCPSeqNr;
00326             TCPAckNr = 0;                                       // we don't know what to ACK!
00327             TCPUNASeqNr++;                                      // count SYN as a byte
00328             PrepareTCP_FRAME(TCP_CODE_SYN);                     // send SYN frame
00329             LastFrameSent = TCP_SYN_FRAME;
00330             TCPStartRetryTimer();                               // we NEED a retry-timeout
00331             TCPStateMachine = SYN_SENT;
00332           }
00333       break;
00334     }
00335     case SYN_RECD :
00336     case ESTABLISHED :
00337     {
00338       if (TCPFlags & TCP_CLOSE_REQUESTED)                  // user has user initated a close?
00339         if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))   // buffers free?
00340           if (TCPSeqNr == TCPUNASeqNr)                          // all data ACKed?
00341           {
00342             TCPUNASeqNr++;
00343             PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
00344             LastFrameSent = TCP_FIN_FRAME;
00345             TCPStartRetryTimer();
00346             TCPStateMachine = FIN_WAIT_1;
00347           }
00348       break;
00349     }
00350     case CLOSE_WAIT :
00351     {
00352       if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))     // buffers free?
00353         if (TCPSeqNr == TCPUNASeqNr)                            // all data ACKed?
00354         {
00355           TCPUNASeqNr++;                                        // count FIN as a byte
00356           PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);        // we NEED a retry-timeout
00357           LastFrameSent = TCP_FIN_FRAME;                        // time to say goodbye...
00358           TCPStartRetryTimer();
00359           TCPStateMachine = LAST_ACK;
00360         }
00361       break;
00362     }
00363   }
00364 
00365   if (TransmitControl & SEND_FRAME2)
00366   {
00367     RequestSend(TxFrame2Size);
00368 
00369     if (Rdy4Tx())                                // NOTE: when using a very fast MCU, maybe
00370       SendFrame2();                              // the CS8900 isn't ready yet, include
00371     else {                                       // a kind of timer or counter here
00372       TCPStateMachine = CLOSED;
00373       SocketStatus = SOCK_ERR_ETHERNET;          // indicate an error to user
00374       TCPFlags = 0;                              // clear all flags, stop timers etc.
00375     }
00376 
00377     TransmitControl &= ~SEND_FRAME2;             // clear tx-flag
00378   }
00379 
00380   if (TransmitControl & SEND_FRAME1)
00381   {
00382     PrepareTCP_DATA_FRAME();                     // build frame w/ actual SEQ, ACK....
00383     RequestSend(TxFrame1Size);
00384   
00385     if (Rdy4Tx())                                // CS8900 ready to accept our frame?
00386       SendFrame1();                              // (see note above)
00387     else {
00388       TCPStateMachine = CLOSED;
00389       SocketStatus = SOCK_ERR_ETHERNET;          // indicate an error to user
00390       TCPFlags = 0;                              // clear all flags, stop timers etc.
00391     }
00392 
00393     TransmitControl &= ~SEND_FRAME1;             // clear tx-flag
00394   }
00395 }
00396 
00397 // easyWEB internal function
00398 // handles an incoming broadcast frame
00399 
00400 void ProcessEthBroadcastFrame(void)
00401 {
00402 // CodeRed - change from int to short
00403 //  unsigned int TargetIP[2];
00404   unsigned short TargetIP[2];
00405 
00406 // CodeRed - remove CS8900 specific code block  
00407 /*
00408   // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
00409   ReadHB1ST8900(RX_FRAME_PORT);                  // ignore RxStatus Word
00410   RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame 
00411     
00412   DummyReadFrame8900(6);                         // ignore DA (FF-FF-FF-FF-FF-FF)
00413   CopyFromFrame8900(&RecdFrameMAC, 6);           // store SA (for our answer)
00414 // Code Red - end of CS8900 specific block
00415 */
00416   
00417   if (ReadFrameBE_EthMAC() == FRAME_ARP)            // get frame type, check for ARP
00418     if (ReadFrameBE_EthMAC() == HARDW_ETH10)        // Ethernet frame
00419       if (ReadFrameBE_EthMAC() == FRAME_IP)         // check protocol
00420         if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN)   // check HLEN, PLEN
00421           if (ReadFrameBE_EthMAC() == OP_ARP_REQUEST)
00422           {
00423             DummyReadFrame_EthMAC(6);               // ignore sender's hardware address
00424             CopyFromFrame_EthMAC(&RecdFrameIP, 4);  // read sender's protocol address
00425             DummyReadFrame_EthMAC(6);               // ignore target's hardware address
00426             CopyFromFrame_EthMAC(&TargetIP, 4);     // read target's protocol address
00427             if (!memcmp(&MyIP, &TargetIP, 4))    // is it for us?
00428               PrepareARP_ANSWER();               // yes->create ARP_ANSWER frame
00429           }
00430 }
00431 
00432 // easyWEB internal function
00433 // handles an incoming frame that passed CS8900's address filter
00434 // (individual addressed = IA)
00435 
00436 void ProcessEthIAFrame(void)
00437 {
00438 // CodeRed - change from int to short
00439 //unsigned int TargetIP[2];
00440   unsigned short TargetIP[2];
00441   unsigned char ProtocolType;
00442 // CodeRed - next few lines not needed for LPC1768 port
00443 /*  
00444   // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
00445   ReadHB1ST_EthMAC(RX_FRAME_PORT);                  // ignore RxStatus Word
00446   RecdFrameLength = ReadHB1ST_EthMAC(RX_FRAME_PORT);// get real length of frame 
00447   
00448   DummyReadFrame_EthMAC(6);                         // ignore DA
00449   CopyFromFrame_EthMAC(&RecdFrameMAC, 6);           // store SA (for our answer)
00450 */
00451   switch (ReadFrameBE_EthMAC())                     // get frame type
00452   {
00453     case FRAME_ARP :                             // check for ARP
00454     {
00455       if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
00456         if (ReadFrameBE_EthMAC() == HARDW_ETH10)         // check for the right prot. etc.
00457           if (ReadFrameBE_EthMAC() == FRAME_IP)
00458             if (ReadFrameBE_EthMAC() == IP_HLEN_PLEN)
00459               if (ReadFrameBE_EthMAC() == OP_ARP_ANSWER)
00460               {
00461                 TCPStopTimer();                       // OK, now we've the MAC we wanted ;-)
00462                 CopyFromFrame_EthMAC(&RemoteMAC, 6);     // extract opponents MAC
00463                 TCPFlags |= IP_ADDR_RESOLVED;
00464               }
00465       break;
00466     }
00467     case FRAME_IP :                                        // check for IP-type
00468     {
00469       if ((ReadFrameBE_EthMAC() & 0xFF00 ) == IP_VER_IHL)     // IPv4, IHL=5 (20 Bytes Header)
00470       {                                                    // ignore Type Of Service
00471         RecdIPFrameLength = ReadFrameBE_EthMAC();             // get IP frame's length
00472         ReadFrameBE_EthMAC();                                 // ignore identification
00473 
00474         if (!(ReadFrameBE_EthMAC() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK)))  // only unfragm. frames
00475         {
00476 // CodeRed - add mask
00477 //        ProtocolType = ReadFrameBE_EthMAC() ;                // get protocol, ignore TTL            
00478           ProtocolType = ReadFrameBE_EthMAC() & 0xFF ;                // get protocol, ignore TTL
00479           ReadFrameBE_EthMAC();                               // ignore checksum
00480           CopyFromFrame_EthMAC(&RecdFrameIP, 4);              // get source IP
00481           CopyFromFrame_EthMAC(&TargetIP, 4);                 // get destination IP
00482 
00483           if (!memcmp(&MyIP, &TargetIP, 4))                // is it for us?
00484             switch (ProtocolType) {
00485               case PROT_ICMP : { ProcessICMPFrame(); break; }
00486               case PROT_TCP  : { ProcessTCPFrame(); break; }
00487               case PROT_UDP  : break;                      // not implemented!
00488             }
00489         }      
00490       }
00491       break;
00492     }
00493   }
00494 }
00495 
00496 // easyWEB internal function
00497 // we've just rec'd an ICMP-frame (Internet Control Message Protocol)
00498 // check what to do and branch to the appropriate sub-function
00499 
00500 void ProcessICMPFrame(void)
00501 {
00502 // CodeRed - change from int to short
00503 //unsigned int ICMPTypeAndCode;    
00504   unsigned short ICMPTypeAndCode;
00505 
00506   ICMPTypeAndCode = ReadFrameBE_EthMAC();           // get Message Type and Code
00507   ReadFrameBE_EthMAC();                             // ignore ICMP checksum
00508 
00509   switch (ICMPTypeAndCode >> 8) {                // check type
00510     case ICMP_ECHO :                             // is echo request?
00511     {
00512       PrepareICMP_ECHO_REPLY();                  // echo as much as we can...
00513       break;
00514     }
00515   }
00516 }
00517 
00518 // easyWEB internal function
00519 // we've just rec'd an TCP-frame (Transmission Control Protocol)
00520 // this function mainly implements the TCP state machine according to RFC793
00521 
00522 void ProcessTCPFrame(void)
00523 {
00524 // CodeRed - change from int to short    
00525 /*  unsigned int TCPSegSourcePort;                 // segment's source port
00526   unsigned int TCPSegDestPort;                   // segment's destination port
00527   unsigned long TCPSegSeq;                       // segment's sequence number
00528   unsigned long TCPSegAck;                       // segment's acknowledge number
00529   unsigned int TCPCode;                          // TCP code and header length
00530   unsigned char TCPHeaderSize;                   // real TCP header length
00531   unsigned int NrOfDataBytes;                    // real number of data
00532 */
00533   unsigned short TCPSegSourcePort;                 // segment's source port
00534   unsigned short TCPSegDestPort;                   // segment's destination port
00535   unsigned long TCPSegSeq;                       // segment's sequence number
00536   unsigned long TCPSegAck;                       // segment's acknowledge number
00537   unsigned short TCPCode;                          // TCP code and header length
00538   unsigned char TCPHeaderSize;                   // real TCP header length
00539   unsigned short NrOfDataBytes;                    // real number of data
00540   
00541   
00542   TCPSegSourcePort = ReadFrameBE_EthMAC();                    // get ports
00543   TCPSegDestPort = ReadFrameBE_EthMAC();
00544 
00545   if (TCPSegDestPort != TCPLocalPort) return;              // drop segment if port doesn't match
00546 
00547   TCPSegSeq = (unsigned long)ReadFrameBE_EthMAC() << 16;      // get segment sequence nr.
00548   TCPSegSeq |= ReadFrameBE_EthMAC();
00549 
00550   TCPSegAck = (unsigned long)ReadFrameBE_EthMAC() << 16;      // get segment acknowledge nr.
00551   TCPSegAck |= ReadFrameBE_EthMAC();
00552 
00553   TCPCode = ReadFrameBE_EthMAC();                             // get control bits, header length...
00554 
00555   TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10;         // header length in bytes
00556   NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize;     // seg. text length
00557 
00558   if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return;        // packet too large for us :...-(
00559 
00560   if (TCPHeaderSize > TCP_HEADER_SIZE)                     // ignore options if any
00561     DummyReadFrame_EthMAC(TCPHeaderSize - TCP_HEADER_SIZE);
00562 
00563   switch (TCPStateMachine)                                 // implement the TCP state machine
00564   {
00565     case CLOSED :
00566     {
00567       if (!(TCPCode & TCP_CODE_RST))
00568       {
00569         TCPRemotePort = TCPSegSourcePort;
00570         memcpy(&RemoteMAC, &RecdFrameMAC, 6);              // save opponents MAC and IP
00571         memcpy(&RemoteIP, &RecdFrameIP, 4);                // for later use
00572 
00573         if (TCPCode & TCP_CODE_ACK)                        // make the reset sequence
00574         {                                                  // acceptable to the other
00575           TCPSeqNr = TCPSegAck;                            // TCP
00576           PrepareTCP_FRAME(TCP_CODE_RST);
00577         }
00578         else
00579         {
00580           TCPSeqNr = 0;
00581           TCPAckNr = TCPSegSeq + NrOfDataBytes;
00582           if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
00583           PrepareTCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK);
00584         }
00585       }
00586       break;
00587     }  
00588     case LISTENING :
00589     {
00590       if (!(TCPCode & TCP_CODE_RST))                       // ignore segment containing RST
00591       {
00592         TCPRemotePort = TCPSegSourcePort;
00593         memcpy(&RemoteMAC, &RecdFrameMAC, 6);              // save opponents MAC and IP
00594         memcpy(&RemoteIP, &RecdFrameIP, 4);                // for later use
00595 
00596         if (TCPCode & TCP_CODE_ACK)                        // reset a bad
00597         {                                                  // acknowledgement
00598           TCPSeqNr = TCPSegAck;
00599           PrepareTCP_FRAME(TCP_CODE_RST);
00600         }
00601         else if (TCPCode & TCP_CODE_SYN)
00602         {
00603           TCPAckNr = TCPSegSeq + 1;                           // get remote ISN, next byte we expect
00604 // CodeRed - change TAR -> TOTC to use LPC1768 clock
00605 //          TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN
00606           TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (LPC_TIM0->TC & 0xFFFF); // set local ISN
00607           TCPUNASeqNr = TCPSeqNr + 1;                         // one byte out -> increase by one
00608           PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
00609           LastFrameSent = TCP_SYN_ACK_FRAME;
00610           TCPStartRetryTimer();
00611           TCPStateMachine = SYN_RECD;
00612         }
00613       }
00614       break;
00615     }
00616     case SYN_SENT :
00617     {
00618       if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break;  // drop segment if its IP doesn't belong
00619                                                       // to current session
00620 
00621       if (TCPSegSourcePort != TCPRemotePort) break;   // drop segment if port doesn't match
00622       
00623       if (TCPCode & TCP_CODE_ACK)                // ACK field significant?
00624         if (TCPSegAck != TCPUNASeqNr)            // is our ISN ACKed?
00625         {
00626           if (!(TCPCode & TCP_CODE_RST))
00627           {
00628             TCPSeqNr = TCPSegAck;
00629             PrepareTCP_FRAME(TCP_CODE_RST);
00630           }
00631           break;                                 // drop segment
00632         }
00633 
00634       if (TCPCode & TCP_CODE_RST)                // RST??
00635       {
00636         if (TCPCode & TCP_CODE_ACK)              // if ACK was acceptable, reset
00637         {                                        // connection
00638           TCPStateMachine = CLOSED;
00639           TCPFlags = 0;                          // reset all flags, stop retransmission...
00640           SocketStatus = SOCK_ERR_CONN_RESET;
00641         }
00642         break;                                   // drop segment
00643       }
00644         
00645       if (TCPCode & TCP_CODE_SYN)                // SYN??
00646       {
00647         TCPAckNr = TCPSegSeq;                    // get opponents ISN
00648         TCPAckNr++;                              // inc. by one...
00649 
00650         if (TCPCode & TCP_CODE_ACK)
00651         {
00652           TCPStopTimer();                        // stop retransmission, other TCP got our SYN
00653           TCPSeqNr = TCPUNASeqNr;                // advance our sequence number
00654 
00655           PrepareTCP_FRAME(TCP_CODE_ACK);        // ACK this ISN
00656           TCPStateMachine = ESTABLISHED;
00657           SocketStatus |= SOCK_CONNECTED;
00658           SocketStatus |= SOCK_TX_BUF_RELEASED;  // user may send data now :-)
00659         }
00660         else
00661         {
00662           TCPStopTimer();
00663           PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);   // our SYN isn't ACKed yet,
00664           LastFrameSent = TCP_SYN_ACK_FRAME;               // now continue with sending
00665           TCPStartRetryTimer();                            // SYN_ACK frames
00666           TCPStateMachine = SYN_RECD;
00667         }
00668       }
00669       break;
00670     }
00671     default :
00672     {
00673       if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break;  // drop segment if IP doesn't belong
00674                                                       // to current session
00675 
00676       if (TCPSegSourcePort != TCPRemotePort) break;   // drop segment if port doesn't match
00677 
00678       if (TCPSegSeq != TCPAckNr) break;               // drop if it's not the segment we expect
00679             
00680       if (TCPCode & TCP_CODE_RST)                // RST??
00681       {
00682         TCPStateMachine = CLOSED;                // close the state machine
00683         TCPFlags = 0;                            // reset all flags, stop retransmission...
00684         SocketStatus = SOCK_ERR_CONN_RESET;      // indicate an error to user
00685         break;
00686       }
00687 
00688       if (TCPCode & TCP_CODE_SYN)                // SYN??
00689       {
00690         PrepareTCP_FRAME(TCP_CODE_RST);          // is NOT allowed here! send a reset,
00691         TCPStateMachine = CLOSED;                // close connection...
00692         TCPFlags = 0;                            // reset all flags, stop retransmission...
00693         SocketStatus = SOCK_ERR_REMOTE;          // fatal error!
00694         break;                                   // ...and drop the frame
00695       }
00696 
00697       if (!(TCPCode & TCP_CODE_ACK)) break;      // drop segment if the ACK bit is off
00698 
00699       if (TCPSegAck == TCPUNASeqNr)              // is our last data sent ACKed?
00700       {
00701         TCPStopTimer();                          // stop retransmission
00702         TCPSeqNr = TCPUNASeqNr;                  // advance our sequence number
00703 
00704         switch (TCPStateMachine)                 // change state if necessary
00705         {
00706           case SYN_RECD :                        // ACK of our SYN?
00707           {
00708             TCPStateMachine = ESTABLISHED;       // user may send data now :-)
00709             SocketStatus |= SOCK_CONNECTED;
00710             break;
00711           }
00712           case FIN_WAIT_1 : { TCPStateMachine = FIN_WAIT_2; break; } // ACK of our FIN?
00713           case CLOSING :    { TCPStateMachine = TIME_WAIT; break; }  // ACK of our FIN?
00714           case LAST_ACK :                                            // ACK of our FIN?
00715           {
00716             TCPStateMachine = CLOSED;
00717             TCPFlags = 0;                        // reset all flags, stop retransmission...
00718             SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
00719             break;
00720           }
00721           case TIME_WAIT :
00722           {
00723             PrepareTCP_FRAME(TCP_CODE_ACK);      // ACK a retransmission of remote FIN
00724             TCPRestartTimer();                   // restart TIME_WAIT timeout
00725             break;
00726           }
00727         }
00728         
00729         if (TCPStateMachine == ESTABLISHED)      // if true, give the frame buffer back
00730           SocketStatus |= SOCK_TX_BUF_RELEASED;  // to user
00731       }
00732 
00733       if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == FIN_WAIT_1) || (TCPStateMachine == FIN_WAIT_2))
00734         if (NrOfDataBytes)                                 // data available?
00735           if (!(SocketStatus & SOCK_DATA_AVAILABLE))       // rx data-buffer empty?
00736           {
00737             DummyReadFrame_EthMAC(6);                         // ignore window, checksum, urgent pointer
00738 // CodeRed - removed unrequired &     
00739 //           CopyFromFrame_EthMAC(&RxTCPBuffer, NrOfDataBytes);// fetch data and
00740             CopyFromFrame_EthMAC(RxTCPBuffer, NrOfDataBytes);// fetch data and
00741     
00742             TCPRxDataCount = NrOfDataBytes;                // ...tell the user...
00743             SocketStatus |= SOCK_DATA_AVAILABLE;           // indicate the new data to user
00744             TCPAckNr += NrOfDataBytes;
00745             PrepareTCP_FRAME(TCP_CODE_ACK);                // ACK rec'd data
00746           }
00747               
00748       if (TCPCode & TCP_CODE_FIN)                // FIN??
00749       {
00750         switch (TCPStateMachine)
00751         {
00752           case SYN_RECD :
00753           case ESTABLISHED :
00754           {
00755             TCPStateMachine = CLOSE_WAIT;
00756             break;
00757           }
00758           case FIN_WAIT_1 :
00759           {                                      // if our FIN was ACKed, we automatically
00760             TCPStateMachine = CLOSING;           // enter FIN_WAIT_2 (look above) and therefore
00761             SocketStatus &= ~SOCK_CONNECTED;     // TIME_WAIT
00762             break;
00763           }
00764           case FIN_WAIT_2 :
00765           {
00766             TCPStartTimeWaitTimer();
00767             TCPStateMachine = TIME_WAIT;
00768             SocketStatus &= ~SOCK_CONNECTED;            
00769             break;
00770           }
00771           case TIME_WAIT :
00772           {
00773             TCPRestartTimer();
00774             break;
00775           }
00776         }
00777         TCPAckNr++;                              // ACK remote's FIN flag
00778         PrepareTCP_FRAME(TCP_CODE_ACK);
00779       }
00780     }
00781   }
00782 }
00783 
00784 // easyWEB internal function
00785 // prepares the TxFrame2-buffer to send an ARP-request
00786 
00787 void PrepareARP_REQUEST(void)
00788 {
00789   // Ethernet
00790     
00791 // CodeRed - added char cast    
00792 //    memset(&TxFrame2[ETH_DA_OFS], 0xFF, 6); 
00793   memset(&TxFrame2[ETH_DA_OFS], (char)0xFF, 6);                  // we don't know opposites MAC!
00794   memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
00795 // Code Red - int-> short  
00796 //  *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
00797   *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
00798 
00799   // ARP
00800   
00801 // CodeRed - int-> short  
00802 /*  *(unsigned int *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
00803   *(unsigned int *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
00804   *(unsigned int *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
00805   *(unsigned int *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST);
00806 */
00807   *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
00808   *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
00809   *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
00810   *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST);
00811 
00812   memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
00813   memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
00814   memset(&TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6);           // we don't know opposites MAC!
00815 
00816   if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) || ((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1]))
00817     memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &GatewayIP, 4);   // IP not in subnet, use gateway
00818   else
00819     memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4);    // other IP is next to us...
00820 
00821   TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
00822   TransmitControl |= SEND_FRAME2;
00823 }
00824 
00825 // easyWEB internal function
00826 // prepares the TxFrame2-buffer to send an ARP-answer (reply)
00827 
00828 void PrepareARP_ANSWER(void)
00829 {
00830   // Ethernet
00831   memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
00832   memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
00833 // CodeRed - int-> short  
00834 //  *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
00835   *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
00836 
00837   // ARP
00838 
00839 // CodeRed - int-> short  
00840 /*  *(unsigned int *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
00841   *(unsigned int *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
00842   *(unsigned int *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
00843   *(unsigned int *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER);
00844 */  
00845   *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
00846   *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
00847   *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
00848   *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER);
00849   memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
00850   memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
00851   memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6);
00852   memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4);
00853 
00854   TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
00855   TransmitControl |= SEND_FRAME2;
00856 }
00857 
00858 // easyWEB internal function
00859 // prepares the TxFrame2-buffer to send an ICMP-echo-reply
00860 
00861 void PrepareICMP_ECHO_REPLY(void)
00862 {
00863 // CodeRed - int-> short  
00864 //  unsigned int ICMPDataCount;
00865   unsigned short ICMPDataCount;
00866   
00867   if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE)                      // don't overload TX-buffer
00868     ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
00869   else
00870     ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
00871 
00872   // Ethernet
00873   memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
00874   memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
00875 
00876 // CodeRed - int-> short   
00877 //  *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
00878   *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
00879   
00880   // IP 
00881   
00882 // CodeRed - int-> short  
00883 /*  *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
00884   WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
00885   *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0;
00886   *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
00887   *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
00888   *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
00889   memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
00890   memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
00891   *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
00892 */
00893   *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
00894   WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
00895   *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
00896   *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
00897   *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
00898   *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
00899   memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
00900   memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
00901   *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
00902 
00903   // ICMP
00904   
00905 // CodeRed - int-> short   
00906 /*  *(unsigned int *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
00907   *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;                   // initialize checksum field
00908 
00909   CopyFromFrame8900(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);        // get data to echo...
00910   *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
00911 */
00912   *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
00913   *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;                   // initialize checksum field
00914 
00915   CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);        // get data to echo...
00916   *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
00917   
00918   
00919   // ICMP
00920 
00921 // Code Red - int-> short   
00922   /*  *(unsigned int *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
00923   *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;                   // initialize checksum field
00924 
00925   CopyFromFrame8900(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);        // get data to echo...
00926   *(unsigned int *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
00927 */
00928   *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
00929   *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;                   // initialize checksum field
00930 
00931   CopyFromFrame_EthMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);        // get data to echo...
00932   *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
00933   
00934   
00935   TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
00936   TransmitControl |= SEND_FRAME2;
00937 }
00938 
00939 // easyWEB internal function
00940 // prepares the TxFrame2-buffer to send a general TCP frame
00941 // the TCPCode-field is passed as an argument
00942 
00943 // CodeRed - int-> short
00944 //void PrepareTCP_FRAME(unsigned int TCPCode)
00945 void PrepareTCP_FRAME(unsigned short TCPCode)
00946 {
00947   // Ethernet
00948   memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
00949   memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
00950 
00951 // CodeRed - int-> short   
00952 //  *(unsigned int *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
00953   *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
00954   
00955   // IP
00956 
00957 // Code Red - int-> short   
00958 /*  *(unsigned int *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
00959 
00960   if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
00961     *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
00962   else
00963     *(unsigned int *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
00964     
00965   *(unsigned int *)&TxFrame2[IP_IDENT_OFS] = 0;
00966   *(unsigned int *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
00967   *(unsigned int *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
00968   *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
00969   memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
00970   memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
00971   *(unsigned int *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
00972 */
00973   *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
00974 
00975   if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
00976     *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
00977   else
00978     *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
00979     
00980   *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
00981   *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
00982   *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
00983   *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
00984   memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
00985   memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
00986   *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
00987   
00988   // TCP
00989   WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort);
00990   WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort);
00991 
00992   WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr);
00993   WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr);
00994 
00995 // CodeRed - int-> short   
00996 /*    *(unsigned int *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);    // data bytes to accept
00997   *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = 0;             // initalize checksum
00998   *(unsigned int *)&TxFrame2[TCP_URGENT_OFS] = 0;
00999 
01000   if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
01001   {
01002     *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode);   // TCP header length = 24
01003     *(unsigned int *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS);             // MSS option
01004     *(unsigned int *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
01005     *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
01006     TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
01007   }
01008   else
01009   {
01010     *(unsigned int *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode);   // TCP header length = 20
01011     *(unsigned int *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
01012     TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
01013   }
01014 */
01015   *(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);    // data bytes to accept
01016   *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0;             // initalize checksum
01017   *(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0;
01018 
01019   if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
01020   {
01021     *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode);   // TCP header length = 24
01022     *(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS);             // MSS option
01023     *(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
01024     *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
01025     TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
01026   }
01027   else
01028   {
01029     *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode);   // TCP header length = 20
01030     *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
01031     TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
01032   }  
01033   TransmitControl |= SEND_FRAME2;
01034 }
01035 
01036 // easyWEB internal function
01037 // prepares the TxFrame1-buffer to send a payload-packet
01038 
01039 void PrepareTCP_DATA_FRAME(void)
01040 {
01041   // Ethernet
01042   memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
01043   memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
01044 // Code Red - int-> short    
01045 //  *(unsigned int *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
01046   *(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
01047   
01048   // IP
01049   
01050 // CodeRed - int-> short   
01051 /*  *(unsigned int *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
01052   WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
01053   *(unsigned int *)&TxFrame1[IP_IDENT_OFS] = 0;
01054   *(unsigned int *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
01055   *(unsigned int *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
01056   *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; 
01057   memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
01058   memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
01059   *(unsigned int *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
01060 */
01061   *(unsigned short *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
01062   WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
01063   *(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0;
01064   *(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
01065   *(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
01066   *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0; 
01067   memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
01068   memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
01069   *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
01070   
01071   
01072   // TCP
01073   WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort);
01074   WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort);
01075 
01076   WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr);
01077   WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr);
01078 // CodeRed - int-> short  
01079 /*  *(unsigned int *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK);   // TCP header length = 20
01080   *(unsigned int *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);       // data bytes to accept
01081   *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = 0; 
01082   *(unsigned int *)&TxFrame1[TCP_URGENT_OFS] = 0;
01083   *(unsigned int *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);
01084 */
01085   *(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK);   // TCP header length = 20
01086   *(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);       // data bytes to accept
01087   *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0; 
01088   *(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0;
01089   *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);
01090 
01091 }
01092 
01093 // easyWEB internal function
01094 // calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header
01095 // will be included.
01096 
01097 // CodeRed - int-> short  
01098 //unsigned int CalcChecksum(void *Start, unsigned int Count, unsigned char IsTCP)
01099 unsigned short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP)
01100 {
01101 // Code Red - added pStart
01102     unsigned short *pStart;
01103     unsigned long Sum = 0;
01104 
01105   if (IsTCP) {                                   // if we've a TCP frame...
01106     Sum += MyIP[0];                              // ...include TCP pseudo-header
01107     Sum += MyIP[1];
01108     Sum += RemoteIP[0];
01109     Sum += RemoteIP[1];
01110     Sum += SwapBytes(Count);                     // TCP header length plus data length
01111     Sum += SWAPB(PROT_TCP);
01112   }
01113 
01114 // Code Red - modified to correct expression  
01115 /*  while (Count > 1) {                            // sum words
01116     Sum += *((unsigned int *)Start)++;
01117     Count -= 2;
01118   }
01119 
01120   if (Count)                                     // add left-over byte, if any
01121     Sum += *(unsigned char *)Start;
01122 */
01123   
01124   pStart = (unsigned short *)Start;
01125   while (Count > 1) {                            // sum words
01126     Sum += *pStart++;
01127     Count -= 2;
01128   }
01129 
01130   if (Count)                                     // add left-over byte, if any
01131     Sum += *(unsigned char *)pStart;
01132 
01133   
01134   while (Sum >> 16)                              // fold 32-bit sum to 16 bits
01135     Sum = (Sum & 0xFFFF) + (Sum >> 16);
01136   
01137   return ~Sum;
01138 }
01139 
01140 // easyWEB internal function
01141 // starts the timer as a retry-timer (used for retransmission-timeout)
01142 
01143 void TCPStartRetryTimer(void)
01144 {
01145   TCPTimer = 0;
01146   RetryCounter = MAX_RETRYS;
01147   TCPFlags |= TCP_TIMER_RUNNING;
01148   TCPFlags |= TIMER_TYPE_RETRY;
01149 }
01150 
01151 // easyWEB internal function
01152 // starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)
01153 
01154 void TCPStartTimeWaitTimer(void)
01155 {
01156   TCPTimer = 0;
01157   TCPFlags |= TCP_TIMER_RUNNING;
01158   TCPFlags &= ~TIMER_TYPE_RETRY;  
01159 }
01160 
01161 // easyWEB internal function
01162 // restarts the timer
01163 
01164 void TCPRestartTimer(void)
01165 {
01166   TCPTimer = 0;
01167 }
01168 
01169 // easyWEB internal function
01170 // stopps the timer
01171 
01172 void TCPStopTimer(void)
01173 {
01174   TCPFlags &= ~TCP_TIMER_RUNNING;
01175 }
01176 
01177 // easyWEB internal function
01178 // if a retransmission-timeout occured, check which packet
01179 // to resend.
01180 
01181 void TCPHandleRetransmission(void)
01182 {
01183   switch (LastFrameSent)
01184   {
01185     case ARP_REQUEST :       { PrepareARP_REQUEST(); break; }
01186     case TCP_SYN_FRAME :     { PrepareTCP_FRAME(TCP_CODE_SYN); break; }
01187     case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; }
01188     case TCP_FIN_FRAME :     { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; }
01189     case TCP_DATA_FRAME :    { TransmitControl |= SEND_FRAME1; break; }
01190   }
01191 }
01192 
01193 // easyWEB internal function
01194 // if all retransmissions failed, close connection and indicate an error
01195 
01196 void TCPHandleTimeout(void)
01197 {
01198   TCPStateMachine = CLOSED;
01199 
01200   if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
01201     SocketStatus = SOCK_ERR_ARP_TIMEOUT;         // indicate an error to user
01202   else
01203     SocketStatus = SOCK_ERR_TCP_TIMEOUT;
01204 
01205   TCPFlags = 0;                                  // clear all flags
01206 }
01207 
01208 
01209 // CodeRed - TCPClockHandler() replaced
01210 /*
01211 // easyWEB internal function
01212 // function executed every 0.262s by the MCU. used for the
01213 // inital sequence number generator (ISN) and the TCP-timer
01214 
01215 interrupt [TIMERA1_VECTOR] void TCPClockHandler(void)
01216 {
01217   if (TAIV == 10)                                // check for timer overflow, reset int.-flag
01218   {
01219     ISNGenHigh++;                                // upper 16 bits of initial sequence number
01220     TCPTimer++;                                  // timer for retransmissions
01221   }
01222 }
01223 */
01224 
01225 // easyWEB internal function
01226 // function executed every 0.210s by the MCU. used for the
01227 // inital sequence number generator (ISN) and the TCP-timer
01228 
01229 void TCPClockHandler(void)
01230 {
01231     ISNGenHigh++;                                // upper 16 bits of initial sequence number
01232     TCPTimer++;                                  // timer for retransmissions
01233 }
01234 
01235 
01236 // easyWEB internal function
01237 // transfers the contents of 'TxFrame1'-Buffer to the CS8900A
01238 
01239 void SendFrame1(void)
01240 {
01241 // CodeRed - updated for LPC1768 port
01242 // CopyToFrame8900(&TxFrame1, TxFrame1Size);
01243   CopyToFrame_EthMAC(TxFrame1, TxFrame1Size);
01244 }
01245 
01246 // easyWEB internal function
01247 // transfers the contents of 'TxFrame2'-Buffer to the CS8900A
01248 
01249 void SendFrame2(void)
01250 {
01251 // CodeRed - updated for LPC1768 port    
01252 // CopyToFrame8900(&TxFrame2, TxFrame2Size);
01253   CopyToFrame_EthMAC(TxFrame2, TxFrame2Size);
01254 }
01255 
01256 // easyWEB internal function
01257 // help function to write a WORD in big-endian byte-order
01258 // to MCU-memory
01259 
01260 // CodeRed - int->short
01261 //void WriteWBE(unsigned char *Add, unsigned int Data)
01262 void WriteWBE(unsigned char *Add, unsigned short Data)
01263 {
01264   *Add++ = Data >> 8;
01265 // Code Red - added cast
01266 //  *Add = Data;
01267   *Add = (char)Data;
01268 }
01269 
01270 // easyWEB internal function
01271 // help function to write a DWORD in big-endian byte-order
01272 // to MCU-memory
01273 
01274 void WriteDWBE(unsigned char *Add, unsigned long Data)
01275 {
01276   *Add++ = Data >> 24;
01277   *Add++ = Data >> 16;
01278   *Add++ = Data >> 8;
01279   *Add = Data;
01280 }
01281 
01282 // easyWEB internal function
01283 // help function to swap the byte order of a WORD
01284 
01285 // CodeRed - int->short
01286 //unsigned int SwapBytes(unsigned int Data)
01287 unsigned short SwapBytes(unsigned short Data)
01288 {
01289   return (Data >> 8) | (Data << 8);
01290 }
01291