]> git.sur5r.net Git - freertos/commitdiff
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@10 1d2547de-c912-0410-9cb9...
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 27 May 2006 16:53:42 +0000 (16:53 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 27 May 2006 16:53:42 +0000 (16:53 +0000)
Demo/WizNET_DEMO_TERN_186/tern_code/i2chip_hw.c [new file with mode: 0644]
Demo/WizNET_DEMO_TERN_186/tern_code/socket.c [new file with mode: 0644]

diff --git a/Demo/WizNET_DEMO_TERN_186/tern_code/i2chip_hw.c b/Demo/WizNET_DEMO_TERN_186/tern_code/i2chip_hw.c
new file mode 100644 (file)
index 0000000..eb513ef
--- /dev/null
@@ -0,0 +1,239 @@
+/*\r
+********************************************************************************\r
+* TERN, Inc.\r
+* (c) Copyright 2005, http://www.tern.com\r
+*\r
+* - Created to support i2chip module on a variety of TERN hardware platforms.\r
+********************************************************************************\r
+*/\r
+\r
+#include <embedded.h>\r
+#include "i2chip_hw.h"\r
+\r
+#ifdef I2CHIP_MMC\r
+#include "mmc.h"\r
+#endif\r
+\r
+void i2chip_init(void)\r
+{\r
+\r
+#ifdef TERN_586\r
+/*\r
+       poke(MMCR,_BOOTCSCTL_,peek(MMCR,_BOOTCSCTL_)&0xffc9);   // ROM 1 wait\r
+       poke(MMCR,_ROMCS2CTL_,peek(MMCR,_ROMCS2CTL_)&0xffc8);   // SRAM 0 wait\r
+\r
+       pokeb(MMCR,     _GPCSRT_, 24); // set the GP CS recovery time, 12 works\r
+       pokeb(MMCR,     _GPCSPW_, 128); // set the GP CS width, 64 works\r
+       pokeb(MMCR,     _GPCSOFF_, 16); // set the GP CS offset, 8 works\r
+       pokeb(MMCR,     _GPRDW_, 80); // set the GP RD pulse width, 50 works\r
+       pokeb(MMCR,     _GPRDOFF_, 30); // set the GP RD offset, 15 works\r
+       pokeb(MMCR,     _GPWRW_, 80); // set the GP WR pulse width, 50\r
+       pokeb(MMCR,     _GPWROFF_, 30); // set the GP WR offset, 15\r
+*/\r
+\r
+#ifdef TERN_5E\r
+       pokeb(MMCR,     _GPCSDW_, peekb(MMCR, _GPCSDW_)&0xf7); // set /CS3-/CSM Data Width=8\r
+       pokeb(MMCR,     _CSPFS_, peekb(MMCR, _CSPFS_)|0x08); // set the GP CS3 PIN Function\r
+       poke(MMCR,      _PAR15_, 0x2000); // set CS3 I/O region\r
+       poke(MMCR,      _PAR15_+2, 0x2dff); // set CS3 I/O region, 512 bytes\r
+\r
+       pokeb(MMCR,     _GPCSDW_, peekb(MMCR, _GPCSDW_)&0x7f); // CS7=J4.3 Data Width=8, /CSI\r
+//     pokeb(MMCR,     _GPCSDW_, peekb(MMCR, _GPCSDW_)|0x80); // CS7=J4.3 Data Width=16\r
+       pokeb(MMCR,     _CSPFS_, peekb(MMCR, _CSPFS_)|0x80); // set the GP CS7 PIN Function\r
+       poke(MMCR,      _PAR7_, 0x4000); // set CS7 I/O region\r
+       poke(MMCR,      _PAR7_+2, 0x3dff); // set CS7 I/O region, 512 bytes\r
+#else\r
+   // If it's not 5E, then it must be 5P... in which case, we use PCS0 and\r
+   // PCS1 as the chip-selects.\r
+       pokeb(MMCR,     _GPCSDW_, peekb(MMCR, _GPCSDW_)&0xfe); // CS0 Data Width=8\r
+       poke(MMCR, _PIOPFS31_16_, peek(MMCR,_PIOPFS31_16_)|0x0800); // P27=/CS0\r
+       poke(MMCR,      _PAR13_, 0x1800); // CS0 I/O region\r
+       poke(MMCR,      _PAR13_+2, 0x21ff); // CS0 I/O RW, 512 bytes, start 0x1800\r
+#endif\r
+\r
+a      HLPRsetvect(0x47, (void far *) spu_m_isr);\r
+       HLPRsetvect(0x4f, (void far *) spu_1_isr);\r
+       HLPRsetvect(0x57, (void far *) spu_2_isr);\r
+#endif  // 186, or RE\r
+\r
+#ifdef TERN_186\r
+   pio_init(18, 0);    //      P18=CTS1 for /PCS2\r
+\r
+#ifdef TERN_16_BIT\r
+       outport(0xfff2, 2);     // AUXCON, MCS, Bus 16-bit\r
+#endif\r
+\r
+#ifdef I2CHIP_MCS_DIRECT\r
+       outport(0xffa0,0xc0bf);                                                      // UMCS, 256K ROM, disable AD15-0\r
+       outport(0xfff0,inport(0xfff0)|0x4000 );        // SYSCON, MCS0 0x80000-0xbffff\r
+       outport(0xffa8,0xa0bf );                                                // MPCS, MCS0=P14, 64KB, PCS I/O,\r
+       outport(0xffa6,0x81ff);                                                      // MMCS, base 0x80000,\r
+       outport(0xffa2,0x7fbf);                                                 // 512K RAM,\r
+       outport(0xffa4,0x007d);                                                      // PACS, base 0,\r
+       \r
+#else\r
+\r
+       outport( 0xffa0,0xc0bf); // UMCS, 256K ROM, 3 wait, disable AD15-0\r
+       outport( 0xfff0,inport(0xfff0)|0x4000 ); // SYSCON, MCS0 0x80000-0xbffff\r
+//   outport( 0xffa8,0xa0bc ); // MPCS, MCS0=P14, 64KB, PCS I/O 0 wait\r
+//     outport( 0xffa8,0xa0bd ); // MPCS, MCS0=P14, 64KB, PCS I/O 1 wait\r
+       outport( 0xffa8,0xa0bf ); // MPCS, MCS0=P14, 64KB, PCS I/O 1 wait\r
+#endif // I2CHIP_MCS_DIRECT\r
+\r
+#ifndef TERN_RE   // 80 MHz R- boards can't tolerate zero wait state.\r
+       outport( 0xffa6,0x81ff ); // MMCS, base 0x80000\r
+       outport(0xffa2,0x7fbe); // 512K RAM, 0 wait states\r
+       outport(0xffa4,0x007d); // PACS, base 0, 0 wait\r
+#endif\r
+       pio_init(14,0);                                                                              //  Enable /MCS0\r
+\r
+#endif // TERN_186\r
+\r
+\r
+#ifdef I2CHIP_WINDOW\r
+#ifdef I2CHIP_SHIFTED_ADDRESS\r
+       pio_init(12, 2); // Configure P12 as A7, an output we'll be using.\r
+   pio_wr(12, 0);   // Set A7 low, initially.\r
+#endif\r
+       WINDOW_RESTORE_BASE;    // Equivalent to calling mmc_window(7, 0);\r
+#endif\r
+}\r
+\r
+#ifdef I2CHIP_WINDOW\r
+\r
+void i2chip_set_page(u_int page)\r
+{\r
+       u_int new_page = page;\r
+\r
+#ifdef   I2CHIP_SHIFTED_ADDRESS\r
+       if (page & 0x01)   // ... we're checking the right-most bit in the page.\r
+       outport(0xff74, inport(0xff74) | 0x1000 ); // Using P12 as A7...\r
+   else\r
+       outport(0xff74, inport(0xff74) & 0xefff );\r
+\r
+   new_page = page >> 1;\r
+#endif\r
+\r
+#ifdef   I2CHIP_MMC\r
+       mmc_window(7, new_page);   // See mmc.c\r
+#endif\r
+#ifdef   I2CHIP_P51\r
+       p51_window(new_page);\r
+#endif\r
+}\r
+\r
+static u_int s_addr = 0xffff;\r
+u_char far* i2chip_mkptr(u_int addr)\r
+{\r
+       if ((s_addr & 0xff00) == (addr & 0xff00)) // No point... no point...\r
+               return MK_FP(WINDOW_BASE_SEGM, addr & 0xff);\r
+\r
+       s_addr = addr ;\r
+\r
+       // So the argument to this function is... what again?\r
+   // I think it should be the highest 16-bits... or, in other words,\r
+   // FP_SEG of a huge ptr.\r
+   // Ok, and the *return* value should be a UINT value for the new\r
+   // segment address to be used, if it's at all needed.  TODO\r
+   I2CHIP_SET_PAGE(s_addr >> 8);  // Portable version\r
+//     outportb(0x00, addr>>8); // quicker version\r
+\r
+       return MK_FP(WINDOW_BASE_SEGM, addr & 0xff);\r
+}\r
+\r
+void i2chip_set_window(u_int window_addr)\r
+{\r
+       s_addr = window_addr;\r
+   I2CHIP_SET_PAGE(s_addr >> 8);\r
+}\r
+\r
+// Still inside #define I2CHIP_WINDOW ...\r
+\r
+u_int i2chip_get_window(void)\r
+{\r
+   return s_addr & 0xff00;\r
+}\r
+\r
+void i2chip_push_window(u_int addr)\r
+{\r
+       I2CHIP_SET_PAGE(addr>>8);\r
+}\r
+\r
+void i2chip_pop_window(void)\r
+{\r
+       I2CHIP_SET_PAGE(s_addr >> 8);\r
+}\r
+\r
+#ifdef I2CHIP_WINDOW_IO\r
+u_char   io_read_value(u_char far* addr)\r
+{\r
+       // return value ... we assume the page is already set.  So, instead,\r
+   // we just go ahead and output valeu.\r
+   return inportb(I2CHIP_BASE_SEG + (FP_OFF(addr) & 0xff));\r
+}\r
+\r
+void     io_write_value(u_char far* addr, u_char value)\r
+{\r
+       // Get the last whatever bytes... and write value.\r
+       outportb(I2CHIP_BASE_SEG + (FP_OFF(addr) & 0xff), value);\r
+}\r
+\r
+#endif // I2CHIP_WINDOW_IO\r
+\r
+\r
+#ifdef   I2CHIP_P51\r
+void p51_window(unsigned int page)\r
+{\r
+asm xor ax, ax\r
+asm mov ax, page\r
+#ifdef   I2CHIP_WINDOW_IO\r
+asm mov dx, 1040h\r
+asm out dx, al\r
+#else\r
+asm out 040h, al\r
+#endif\r
+// use J1.19=/CS6\r
+}\r
+#endif  // I2CHIP_P51\r
+\r
+#endif // I2CHIP_WINDOW\r
+\r
+#ifdef TERN_586\r
+/*\r
+//     Function: spu_m_isr\r
+//     P22=Master PIC IR7, interrupt vector=0x47, /INTA\r
+*/\r
+void interrupt far spu_m_isr(void)\r
+{\r
+disable();\r
+// Issue the EOI to interrupt controller\r
+outportb(_MPICOCW2_IO,0x67); // Specific EQI for master IR7\r
+enable();\r
+}\r
+\r
+/*\r
+//     Function: spu_1_isr\r
+//     P10=slave1 PIC IR7, Master IR2, interrupt vector=0x4f, /INTC\r
+*/\r
+void interrupt far spu_1_isr(void)\r
+{\r
+disable();\r
+// Issue the EOI to interrupt controller\r
+       outportb(_S1PICOCW2_IO,0x67);   // Specific EOI for slave 1 IR7\r
+       outportb(_MPICOCW2_IO,0x62); // Specific EQI for master IR2\r
+enable();\r
+}\r
+\r
+/*\r
+//     Function: spu_2_isr\r
+//     P20=Slave2 PIC IR7, Master IR5, interrupt vector=0x57, GPIRQ7=PIO16 GP timer1\r
+*/\r
+void interrupt far spu_2_isr(void)\r
+{\r
+disable();\r
+// Issue the EOI to interrupt controller\r
+       outportb(_S2PICOCW2_IO,0x67);   // Specific EOI for slave 1 IR7\r
+       outportb(_MPICOCW2_IO,0x65); // Specific EQI for master IR5\r
+enable();\r
+}\r
+#endif\r
diff --git a/Demo/WizNET_DEMO_TERN_186/tern_code/socket.c b/Demo/WizNET_DEMO_TERN_186/tern_code/socket.c
new file mode 100644 (file)
index 0000000..8cbd8eb
--- /dev/null
@@ -0,0 +1,1870 @@
+/*\r
+********************************************************************************\r
+* TERN, Inc.\r
+* (c) Copyright 2005, http://www.tern.com\r
+*\r
+* MODIFIED BY RICHARD BARRY TO ADD SEMAPHORE FOR COMMUNICATION BETWEEN THE \r
+* WIZnet ISR AND THE HTTP TASK.\r
+*\r
+* - Derived based on development version provided by Wiznet.\r
+*\r
+* Filename : socket.h\r
+* Programmer(s):\r
+* Created : 2002/06/20\r
+* Modified :\r
+*  2002/09/27 : - Renaming\r
+*                             INT_STATUS --> INT_REG\r
+*                             STATUS(i) --> INT_STATUS(i)\r
+*                             C_STATUS(i) --> SOCK_STATUS(i)\r
+*  2003/11/06 : Ported for use with TERN controller.  Note all byte access is at even addresses\r
+*  2005/10/8  : Modified constants for easier initialization.\r
+*\r
+* Description : Header file of W3100A for TERN embedded controller\r
+********************************************************************************\r
+*/\r
+/*\r
+###############################################################################\r
+File Include Section\r
+###############################################################################\r
+*/\r
+#include "i2chip_hw.h" \r
+#include "socket.h"\r
+#include "types.h"\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+#include <FreeRTOS.h>\r
+#include <semphr.h>\r
+#include <portasm.h>\r
+\r
+\r
+/*\r
+###############################################################################\r
+Local Variable Declaration Section\r
+###############################################################################\r
+*/\r
+u_char I_STATUS[4];                            // Store Interrupt Status according to channels\r
+u_int Local_Port;                                 // Designate Local Port\r
+union un_l2cval        SEQ_NUM;                // Set initial sequence number\r
+\r
+u_long SMASK[MAX_SOCK_NUM];   // Variable to store MASK of Tx in each channel,\r
+                              // on setting dynamic memory size.\r
+u_long RMASK[MAX_SOCK_NUM];   // Variable to store MASK of Rx in each channel,\r
+                              // on setting dynamic memory size.\r
+int SSIZE[MAX_SOCK_NUM];      // Maximun Tx memory size by each channel\r
+int RSIZE[MAX_SOCK_NUM];      // Maximun Rx memory size by each channel\r
+\r
+u_int SBUFBASEADDRESS[MAX_SOCK_NUM];   // Maximun Tx memory base address by each channel\r
+u_int RBUFBASEADDRESS[MAX_SOCK_NUM];   // Maximun Rx memory base address by each channel\r
+\r
+/*\r
+###############################################################################\r
+Function Implementation Section\r
+###############################################################################\r
+*/\r
+\r
+/*\r
+********************************************************************************\r
+*               Interrupt handling function of the W3100A\r
+*\r
+* Description :\r
+*   Stores the status information that each function waits for in the global variable I_STATUS\r
+*   for transfer. I_STATUS stores the interrupt status value for each channel.\r
+* Arguments   : None\r
+* Returns     : None\r
+* Note        : Internal Function\r
+********************************************************************************\r
+*/\r
+\r
+portBASE_TYPE prvProcessISR( void )\r
+{\r
+unsigned char status;\r
+extern xSemaphoreHandle xTCPSemaphore;\r
+portBASE_TYPE xSwitchRequired = pdFALSE;\r
+\r
+#ifdef I2CHIP_WINDOW\r
+u_int current_window = i2chip_get_window();\r
+#endif\r
+\r
+status = READ_VALUE(INT_REG);\r
+\r
+\r
+if (status)\r
+  {\r
+  xSwitchRequired = pdTRUE;\r
+  // channel 0 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
+  if (status & 0x01)\r
+    {\r
+        I_STATUS[0] = READ_VALUE(INT_STATUS(0));\r
+\r
+//      if (I_STATUS[0] & SESTABLISHED)\r
+//    ISR_ESTABLISHED(0);\r
+//      if (I_STATUS[0] & SCLOSED)\r
+//    ISR_CLOSED(0);\r
+\r
+        WRITE_VALUE(INT_REG, 0x01);\r
+        }\r
+\r
+  // channel 1 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
+  if (status & 0x02)\r
+    {\r
+        I_STATUS[1] = READ_VALUE(INT_STATUS(1));\r
+\r
+//      if (I_STATUS[1] & SESTABLISHED)\r
+//    ISR_ESTABLISHED(1);\r
+//      if (I_STATUS[1] & SCLOSED)\r
+//    ISR_CLOSED(1);\r
+\r
+        WRITE_VALUE(INT_REG, 0x02);\r
+        }\r
+\r
+  // channel 2 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
+  if (status & 0x04)\r
+    {\r
+        I_STATUS[2] = READ_VALUE(INT_STATUS(2));\r
+\r
+//      if (I_STATUS[2] & SESTABLISHED)\r
+//    ISR_ESTABLISHED(2);\r
+//      if (I_STATUS[2] & SCLOSED)\r
+//    ISR_CLOSED(2);\r
+\r
+        WRITE_VALUE(INT_REG, 0x04);\r
+        }\r
+\r
+  // channel 3 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
+  if (status & 0x08)\r
+    {\r
+        I_STATUS[3] = READ_VALUE(INT_STATUS(3));\r
+\r
+//      if (I_STATUS[3] & SESTABLISHED) ISR_ESTABLISHED(3);\r
+//      if (I_STATUS[3] & SCLOSED) ISR_CLOSED(3);\r
+\r
+        WRITE_VALUE(INT_REG, 0x08);\r
+        }\r
+\r
+  // channel 0 receive interrupt\r
+  if (status & 0x10)\r
+    {\r
+//      ISR_RX(0);\r
+        WRITE_VALUE(INT_REG, 0x10);\r
+        }\r
+\r
+  // channel 1 receive interrupt\r
+  if (status & 0x20)\r
+    {\r
+//      ISR_RX(1);\r
+        WRITE_VALUE(INT_REG, 0x20);\r
+        }\r
+\r
+  // channel 2 receive interrupt\r
+  if (status & 0x40)\r
+    {\r
+//      ISR_RX(2);\r
+        WRITE_VALUE(INT_REG, 0x40);\r
+        }\r
+\r
+  // channel 3 receive interrupt\r
+  if (status & 0x80)\r
+    {\r
+//      ISR_RX(3);\r
+        WRITE_VALUE(INT_REG, 0x80);\r
+        }\r
+  status = READ_VALUE(INT_REG);\r
+  }\r
+\r
+WRITE_VALUE(INT_REG, 0xFF);\r
+\r
+#ifdef I2CHIP_WINDOW\r
+i2chip_set_window(current_window);\r
+#endif\r
+\r
+       if( xSwitchRequired == pdTRUE )\r
+    {\r
+               xSwitchRequired = xSemaphoreGiveFromISR( xTCPSemaphore, pdFALSE );\r
+    }\r
+\r
+       return xSwitchRequired;\r
+}\r
+\r
+void far interrupt in4_isr_i2chip(void)\r
+{\r
+       if( prvProcessISR() == pdTRUE )\r
+    {\r
+               portEND_SWITCHING_ISR();\r
+    }\r
+\r
+    INT_EOI;\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Established connection interrupt handling function.\r
+*\r
+* Description :\r
+*   Called upon connection establishment, and may be inserted in user code if needed by\r
+*   the programmer.\r
+* Arguments   : None\r
+* Returns     : None\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+/*\r
+void ISR_ESTABLISHED(SOCKET s)\r
+{\r
+// TO ADD YOUR CODE\r
+}\r
+*/\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Closed connection interrupt handling function\r
+*\r
+* Description :\r
+*   Called upon connection closure, and may be inserted in user code if needed by the programmer.\r
+* Arguments   : None\r
+* Returns     : None\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+/*\r
+void ISR_CLOSED(SOCKET s)\r
+{\r
+// TO ADD YOUR CODE\r
+}\r
+*/\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Received data interrupt handling function\r
+*\r
+* Description :\r
+*   Called upon receiving data, and may be inserted in user code if needed by the programmer.\r
+* Arguments   : None\r
+* Returns     : None\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+/*\r
+void ISR_RX(SOCKET s)\r
+{\r
+// TO ADD YOUR CODE\r
+}\r
+*/\r
+\r
+/*\r
+****************************************************************************************************\r
+*              W3100A Initialization Function\r
+*\r
+* Description:  Reset of W3100A S/W and Registeration of i386 interrupt\r
+* Arguments  : None.\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void initW3100A(void)\r
+{\r
+\r
+// Install interrupt handler for i2Chip\r
+INT_INIT(in4_isr_i2chip);\r
+\r
+\r
+Local_Port = 1000;         // This default value will be set if you didn't designate it when you\r
+                           // create a socket. If you don't designate port number and create a\r
+                           // socket continuously, the port number will be assigned with\r
+                           // incremented by one to Local_Port\r
+SEQ_NUM.lVal = 4294967293ul;   // Sets the initial SEQ# to be used for TCP communication.\r
+                           // (It should be ramdom value)\r
+WRITE_VALUE(COMMAND(0), CSW_RESET);   // Software RESET\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               W3100A initialization function\r
+*\r
+* Description :\r
+*   Sets the Tx, Rx memory size by each channel, source MAC, source IP, gateway, and subnet mask\r
+*   to be used by the W3100A to the designated values.\r
+*   May be called when reflecting modified network information or Tx, Rx memory size on the W3100A\r
+*   Include Ping Request for ARP update (In case that a device embedding W3100A is directly\r
+*     connected to Router)\r
+* Arguments  : sbufsize - Tx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)\r
+*                          bit 1-0 : Tx memory size of channel #0\r
+*                          bit 3-2 : Tx memory size of channel #1\r
+*                          bit 5-4 : Tx memory size of channel #2\r
+*                          bit 7-6 : Tx memory size of channel #3\r
+*              rbufsize - Rx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)\r
+*                          bit 1-0 : Rx memory size of channel #0\r
+*                          bit 3-2 : Rx memory size of channel #1\r
+*                          bit 5-4 : Rx memory size of channel #2\r
+*                          bit 7-6 : Rx memory size of channel #3\r
+* Returns    : None\r
+* Note       : API Function\r
+*              Maximum memory size for Tx, Rx in W3100A is 8KBytes,\r
+*              In the range of 8KBytes, the memory size could be allocated dynamically by\r
+*              each channel\r
+*              Be attentive to sum of memory size shouldn't exceed 8Kbytes\r
+*              and to data transmission and receiption from non-allocated channel may cause\r
+*              some problems.\r
+*              If 8KBytes memory already is assigned to centain channel, other 3 channels\r
+*                couldn't be used, for there's no available memory.\r
+*              If two 4KBytes memory are assigned to two each channels, other 2 channels couldn't\r
+*                be used, for there's no available memory.\r
+*              (Example of memory assignment)\r
+*               sbufsize => 00000011, rbufsize => 00000011 :\r
+*                 Assign 8KBytes for Tx and Rx to channel #0, Cannot use channel #1,#2,#3\r
+*               sbufsize => 00001010, rbufsize => 00001010 :\r
+*                 Assign 4KBytes for Tx and Rx to each channel #0,#1 respectively. Cannot use\r
+*                 channel #2,#3\r
+*               sbufsize => 01010101, rbufsize => 01010101 :\r
+*                 Assign 2KBytes for Tx and Rx to each all channels respectively.\r
+*               sbufsize => 00010110, rbufsize => 01010101 :\r
+*                 Assign 4KBytes for Tx, 2KBytes for Rx to channel #0\r
+*       s          2KBytes for Tx, 2KBytes for Rx to channel #1\r
+*                 2KBytes for Tx, 2KBytes for Rx to channel #2\r
+*                 2KBytes is available exclusively for Rx in channel #3. There's no memory for Tx.\r
+****************************************************************************************************\r
+*/\r
+void sysinit(u_char sbufsize, u_char rbufsize)\r
+{\r
+char i;\r
+int ssum,rsum;\r
+\r
+ssum = 0;\r
+rsum = 0;\r
+\r
+// Set Tx memory size for each channel\r
+WRITE_VALUE(TX_DMEM_SIZE, sbufsize);\r
+\r
+// Set Rx memory size for each channel\r
+WRITE_VALUE(RX_DMEM_SIZE, rbufsize);\r
+\r
+// Set Base Address of Tx memory for channel #0\r
+SBUFBASEADDRESS[0] = 0;\r
+\r
+// Set Base Address of Rx memory for channel #0\r
+RBUFBASEADDRESS[0] = 0;\r
+\r
+// Set maximum memory size for Tx and Rx, mask, base address of memory by each channel\r
+for(i = 0 ; i < MAX_SOCK_NUM; i++)\r
+  {\r
+  SSIZE[i] = 0;\r
+  RSIZE[i] = 0;\r
+  if(ssum < 8192)\r
+        {\r
+        switch((sbufsize >> i*2) & 0x03) // Set maximum Tx memory size\r
+               {\r
+               case 0:\r
+                 SSIZE[i] = 1024;\r
+                 SMASK[i] = 0x000003FF;\r
+                 break;\r
+\r
+               case 1:\r
+                 SSIZE[i] = 2048;\r
+                 SMASK[i] = 0x000007FF;\r
+                 break;\r
+\r
+               case 2:\r
+                 SSIZE[i] = 4096;\r
+                 SMASK[i] = 0x00000FFF;\r
+                 break;\r
+\r
+               case 3:\r
+                 SSIZE[i] = 8192;\r
+                 SMASK[i] = 0x00001FFF;\r
+                 break;\r
+               }\r
+        }\r
+  if(rsum < 8192)\r
+        {\r
+        switch((rbufsize >> i*2) & 0x03)  // Set maximum Rx memory size\r
+               {\r
+               case 0:\r
+                 RSIZE[i] = 1024;\r
+                 RMASK[i] = 0x000003FF;\r
+                 break;\r
+\r
+               case 1:\r
+                 RSIZE[i] = 2048;\r
+                 RMASK[i] = 0x000007FF;\r
+                 break;\r
+\r
+               case 2:\r
+                 RSIZE[i] = 4096;\r
+                 RMASK[i] = 0x00000FFF;\r
+                 break;\r
+\r
+               case 3:\r
+                 RSIZE[i] = 8192;\r
+                 RMASK[i] = 0x00001FFF;\r
+                 break;\r
+               }\r
+        }\r
+  ssum += SSIZE[i];\r
+  rsum += RSIZE[i];\r
+\r
+  // Set base address of Tx and Rx memory for channel #1,#2,#3\r
+  if(i != 0)\r
+    {\r
+    SBUFBASEADDRESS[i] = ssum - SSIZE[i];\r
+    RBUFBASEADDRESS[i] = rsum - RSIZE[i];\r
+    }\r
+  }\r
+\r
+  WRITE_VALUE(COMMAND(0), CSYS_INIT);\r
+\r
+while(!(I_STATUS[0] & SSYS_INIT_OK))\r
+  I2CHIP_POLL_ISR(in4_isr_i2chip);\r
+\r
+#ifdef __PING__\r
+  {\r
+  u_char xdata pingbuf[8];\r
+  setIPprotocol(0, IPPROTO_ICMP);\r
+  socket(0, SOCK_IPL_RAW, 3000,0);     // Create a socket for ARP update\r
+\r
+  pingbuf[0] = 8;                      // ICMP TYPE\r
+  pingbuf[1] = 0;                      // ICMP CODE\r
+  pingbuf[2] = 0xf7;                   // CHECKSUM (already calculated)\r
+  pingbuf[3] = 0xfd;\r
+  pingbuf[4] = 0;                      // ID\r
+  pingbuf[5] = 1;\r
+  pingbuf[6] = 0;                      // SEQ #\r
+  pingbuf[7] = 1;\r
+  pingbuf[8] = 0;                      // Data 1 Byte\r
+\r
+  sendto(0, pingbuf, 9, GATEWAY_PTR,3000);  // Ping Request\r
+  close(0);\r
+  printf("Route MAC Update Success");\r
+  }\r
+#endif\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Function to set subnet mask\r
+*\r
+* Description:\r
+* Arguments  : addr--> Pointer that has the value to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setsubmask(u_char * addr)\r
+{\r
+u_char i;\r
+u_char far* sm_ptr = SUBNET_MASK_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+\r
+for (i = 0; i < 4; i++)\r
+  {\r
+  WRITE_VALUE(sm_ptr + SA_OFFSET(i), addr[i]);\r
+  }\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Function to set gateway IP\r
+*\r
+* Description:\r
+* Arguments  : addr--> Pointer that has Gateway IP to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setgateway(u_char * addr)\r
+{\r
+u_char i;\r
+u_char far* gw_ptr = GATEWAY_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+for (i = 0; i < 4; i++)\r
+  {\r
+  WRITE_VALUE(gw_ptr + SA_OFFSET(i), addr[i]);\r
+  }\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*                 Function to set W3100A IP\r
+*\r
+* Description:\r
+* Arguments  : addr--> Pointer that has Source IP to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setIP(u_char * addr)\r
+{\r
+u_char i;\r
+u_char far* src_ptr = SRC_IP_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+\r
+for (i = 0; i < 4; i++)\r
+  {\r
+  WRITE_VALUE(src_ptr + SA_OFFSET(i), addr[i]);\r
+  }\r
+}\r
+\r
+// DEBUG\r
+void getIP(u_char* addr)\r
+{\r
+u_char i;\r
+u_char far* src_ptr = SRC_IP_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+\r
+for (i = 0; i < 4; i++)\r
+       addr[i] = READ_VALUE(src_ptr + SA_OFFSET(i));\r
+}\r
+\r
+\r
+/*\r
+****************************************************************************************************\r
+*                Function to set MAC\r
+*\r
+* Description:\r
+* Arguments  : addr--> Pointer that has MAC to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setMACAddr(u_char * addr)\r
+{\r
+u_char i;\r
+u_char far* ha_ptr = SRC_HA_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+\r
+for (i = 0; i < 6; i++)\r
+  {\r
+  WRITE_VALUE(ha_ptr + SA_OFFSET(i), addr[i]);\r
+  }\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*                  Function to set TCP timeout\r
+*\r
+* Description: The function that used to adjust time to resend TCP\r
+* Arguments  : val     --> Pointer that has the value to be set\r
+*                                      Upper 2 byte:Initial timeout value\r
+*                                      Last 1 byte:The count to retry till timeout\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void settimeout(u_char * val)\r
+{\r
+u_char i;\r
+u_char far* tout_ptr = TIMEOUT_PTR;   // We can only convert to 'regular'\r
+                                   // pointer if we're confident arithmetic\r
+                                   // won't take us out of current window.\r
+\r
+for (i = 0; i < 3; i++)\r
+  {\r
+  WRITE_VALUE(tout_ptr + SA_OFFSET(i), val[i]);\r
+  }\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*                 Function to set interrupt mask.\r
+*\r
+* Description:\r
+* Arguments  : mask--> Mask value to be set ('1'-> interrupt )\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setINTMask(u_char mask)\r
+{\r
+WRITE_VALUE(INTMASK, mask);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*                  Function to set enable in sending and receiving of broadcast data\r
+*\r
+* Description:  Enable to process of broadcating data in UDP or IP RAW mode.\r
+* Arguments  : s       --> Channel No. to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setbroadcast(SOCKET s)\r
+{\r
+u_char val = READ_VALUE(OPT_PROTOCOL(s));\r
+WRITE_VALUE(OPT_PROTOCOL(s), val | SOCKOPT_BROADCAST);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*                Function to set process protocol  in IP RAW mode.\r
+*\r
+* Description:\r
+* Arguments  : s--> Channel No. to be set\r
+*              tos-->Protocol Value to be set\r
+* Returns    : None.\r
+* Note       :\r
+****************************************************************************************************\r
+*/\r
+void setTOS(SOCKET s, u_char tos)\r
+{\r
+WRITE_VALUE(TOS(s), tos);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Upper layer protocol setup function in IP RAW Mode\r
+*\r
+* Description : Upper layer protocol setup function in protocol field of IP header when\r
+*                    developing upper layer protocol like ICMP, IGMP, EGP etc. by using IP Protocol\r
+* Arguments   : s          - Channel number\r
+*               ipprotocol - Upper layer protocol setting value of IP Protocol\r
+*                            (Possible to use designated IPPROTO_ in header file)\r
+* Returns     : None\r
+* Note        : API Function\r
+*                  This function should be called before calling socket() that is, before\r
+*                  socket initialization.\r
+****************************************************************************************************\r
+*/\r
+void setIPprotocol(SOCKET s, u_char ipprotocol)\r
+{\r
+WRITE_VALUE(IP_PROTOCOL(s), ipprotocol);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Initialization function to appropriate channel\r
+*\r
+* Description : Initialize designated channel and wait until W3100 has done.\r
+* Arguments   : s - channel number\r
+*               protocol - designate protocol for channel\r
+*                          SOCK_STREAM(0x01) -> TCP.\r
+*                          SOCK_DGRAM(0x02)  -> UDP.\r
+*                          SOCK_IPL_RAW(0x03) -> IP LAYER RAW.\r
+*                          SOCK_MACL_RAW(0x04) -> MAC LAYER RAW.\r
+*               port     - designate source port for appropriate channel\r
+*               flag     - designate option to be used in appropriate.\r
+*                          SOCKOPT_BROADCAST(0x80) -> Send/receive broadcast message in UDP\r
+*                          SOCKOPT_NDTIMEOUT(0x40) -> Use register value which designated TIMEOUT\r
+*                            value\r
+*                          SOCKOPT_NDACK(0x20)     -> When not using no delayed ack\r
+*                          SOCKOPT_SWS(0x10)       -> When not using silly window syndrome\r
+* Returns     : When succeeded : Channel number, failed :-1\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+char socket(SOCKET s, u_char protocol, u_int port, u_char flag)\r
+{\r
+u_char k;\r
+\r
+//Designate socket protocol and option\r
+WRITE_VALUE(OPT_PROTOCOL(s), protocol | flag);\r
+\r
+// setup designated port number\r
+if (port != 0)\r
+  {\r
+  k = (u_char)((port & 0xff00) >> 8);\r
+  WRITE_VALUE(SRC_PORT_PTR(s), k);\r
+  k = (u_char)(port & 0x00ff);\r
+  WRITE_VALUE(SRC_PORT_PTR(s) + SA_OFFSET(1), k);\r
+  }\r
+else\r
+  {\r
+  // Designate random port number which is managed by local when you didn't designate source port\r
+  Local_Port++;\r
+\r
+  WRITE_VALUE(SRC_PORT_PTR(s), (u_char)((Local_Port & 0xff00) >> 8));\r
+  WRITE_VALUE(SRC_PORT_PTR(s) + SA_OFFSET(1), (u_char)(Local_Port & 0x00ff));\r
+  }\r
+\r
+// SOCK_INIT\r
+I_STATUS[s] = 0;\r
+WRITE_VALUE(COMMAND(s), CSOCK_INIT);\r
+\r
+// Waiting Interrupt to CSOCK_INIT\r
+while (I_STATUS[s] == 0)\r
+       I2CHIP_POLL_ISR(in4_isr_i2chip);\r
+\r
+if (!(I_STATUS[s] & SSOCK_INIT_OK))\r
+  return(-1);\r
+\r
+initseqnum(s);                                                 //  Use initial seq# with random number\r
+\r
+return(s);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Connection establishing function to designated peer.\r
+*\r
+* Description : This function establish a connection to the peer by designated channel,\r
+*     and wait until the connection is established successfully. (TCP client mode)\r
+* Arguments   : s    - channel number\r
+*               addr - destination IP Address\r
+*               port - destination Port Number\r
+* Returns     : when succeeded : 1, failed : -1\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+char connect(SOCKET s, u_char far * addr, u_int port)\r
+{\r
+\r
+if (port != 0)\r
+  {                                            //designate destination port\r
+  WRITE_VALUE(DST_PORT_PTR(s), (u_char)((port & 0xff00) >> 8));\r
+  WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
+  }\r
+else\r
+  return(-1);\r
+\r
+  WRITE_VALUE(DST_IP_PTR(s), addr[0]);                         //designate destination IP address\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
+\r
+I_STATUS[s] = 0;\r
+\r
+  WRITE_VALUE(COMMAND(s), CCONNECT);                                   // CONNECT\r
+  I2CHIP_POLL_ISR(in4_isr_i2chip);\r
+\r
+// Wait until connection is established successfully\r
+while (I_STATUS[s] == 0)\r
+  {\r
+  // When failed, appropriate channel will be closed and return an error\r
+  if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
+    return -1;\r
+  }\r
+\r
+if (!(I_STATUS[s] & SESTABLISHED))\r
+  return(-1);\r
+\r
+return(1);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Connection establishing function to designated peer. (Non-blocking Mode)\r
+*\r
+* Description : This function establish a connection to the peer by designated channel.\r
+*\r
+* Arguments   : s    - channel number\r
+*               addr - destination IP Address\r
+*               port - destination Port Number\r
+* Returns     : when succeeded : 1, failed : -1\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+char NBconnect(SOCKET s, u_char far * addr, u_int port)\r
+{\r
+\r
+if (port != 0)\r
+  {                                            //designate destination port\r
+       WRITE_VALUE(DST_PORT_PTR(s), (u_char) ((port & 0xff00) >> 8) );\r
+   WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
+  }\r
+else\r
+  return(-1);\r
+\r
+  WRITE_VALUE(DST_IP_PTR(s), addr[0]);                         //designate destination IP address\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
+  WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
+\r
+I_STATUS[s] = 0;\r
+\r
+WRITE_VALUE(COMMAND(s), CCONNECT);                                     // CONNECT\r
+return(1);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*            Waits for connection request from a peer (Blocking Mode)\r
+*\r
+* Description : Wait for connection request from a peer through designated channel (TCP Server mode)\r
+* Arguments   : s    - channel number\r
+*               addr - IP Address of the peer when a connection is established\r
+*               port - Port number of the peer when a connection is established\r
+* Returns     : When succeeded : 1, failed : -1\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+/*\r
+char listen(SOCKET s, u_char far * addr, u_int far * port)\r
+{\r
+u_int i;\r
+\r
+I_STATUS[s] = 0;\r
+\r
+// LISTEN\r
+COMMAND(s) = CLISTEN;\r
+\r
+// Wait until connection is established\r
+while (I_STATUS[s] == 0)\r
+  {\r
+  // When failed to connect, the designated channel will be closed and return an error.\r
+  if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
+    return -1;\r
+  }\r
+\r
+// Receive IP address and port number of the peer connected\r
+if (I_STATUS[s] & SESTABLISHED)\r
+  {\r
+  i = *DST_PORT_PTR(s);\r
+  *port = (u_int)((i & 0xff00) >> 8);\r
+  i = *(DST_PORT_PTR(s) + 2);\r
+  i = (u_int)(i & 0x00ff);\r
+  *port += (i << 8);\r
+\r
+  addr[0] = *DST_IP_PTR(s);\r
+  addr[1] = *(DST_IP_PTR(s) + 2);\r
+  addr[2] = *(DST_IP_PTR(s) + 4);\r
+  addr[3] = *(DST_IP_PTR(s) + 6);\r
+  }\r
+else\r
+  return(-1);\r
+\r
+return(1);\r
+}\r
+*/\r
+\r
+/*\r
+****************************************************************************************************\r
+*                Waits for connection request from a peer (Non-blocking Mode)\r
+*\r
+* Description : Wait for connection request from a peer through designated channel (TCP Server mode)\r
+* Arguments   : s - channel number\r
+* Returns     : None\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+char NBlisten(SOCKET s)\r
+{\r
+I_STATUS[s] = 0;\r
+\r
+// LISTEN\r
+WRITE_VALUE(COMMAND(s), CLISTEN);\r
+\r
+return(1);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*               Create random value for initial Seq# when establishing TCP connection\r
+*\r
+* Description : In this function, you can add some source codes to create random number for\r
+*     initial Seq#. In real, TCP initial SEQ# should be random value.\r
+*               (Currently, we're using static value in EVB/DK.)\r
+* Arguments   : s - channel number\r
+* Returns     : None\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+void initseqnum(SOCKET s)\r
+{\r
+// Designate initial seq#\r
+// If you have random number generation function, assign random number instead of SEQ_NUM.lVal++.\r
+SEQ_NUM.lVal++;\r
+\r
+//randomize();\r
+//SEQ_NUM.lVal = rand();\r
+\r
+WRITE_VALUE(TX_WR_PTR(s), SEQ_NUM.cVal[0]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
+delay0(2);\r
+\r
+WRITE_VALUE(TX_RD_PTR(s), SEQ_NUM.cVal[0]);\r
+WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
+WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
+WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
+delay0(2);\r
+\r
+WRITE_VALUE(TX_ACK_PTR(s), SEQ_NUM.cVal[0]);\r
+WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
+WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
+WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
+delay0(2);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Function for sending TCP data.\r
+*\r
+* Description : Function for sending TCP data and Composed of the send() and send_in() functions.\r
+*     The send() function is an application I/F function.\r
+*     It continues to call the send_in() function to complete the sending of the data up to the\r
+*     size of the data to be sent when the application is called.\r
+*     The send_in() function receives the return value (the size of the data sent), calculates\r
+*     the size of the data to be sent, and calls the send_in() function again if there is any\r
+*     data left to be sent.\r
+* Arguments   : s   - channel number\r
+*               buf - Pointer pointing data to send\r
+*               len - data size to send\r
+* Returns     : Succeed: sent data size, Failed:  -1;\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+int send(SOCKET s, u_char far * buf, u_int len)\r
+{\r
+int ptr, size;\r
+u_char huge* huge_buf = (u_char huge*)buf;\r
+u_char far*  local_buf = (u_char far*)huge_buf;    \r
+\r
+if (len <= 0)\r
+  return (0);\r
+else\r
+  {\r
+  ptr = 0;\r
+  do\r
+    {\r
+        size = send_in(s, local_buf + ptr, len);\r
+        if (size == -1)\r
+      return -1;\r
+        len = len - size;\r
+        ptr += size;\r
+        } while ( len > 0);\r
+  }\r
+return ptr;\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Internal function for sending TCP data.\r
+*\r
+* Description : Called by the send() function for TCP transmission.\r
+*    It first calculates the free transmit buffer size\r
+*    and compares it with the size of the data to be transmitted to determine the transmission size.\r
+*    After calculating the data size, it copies data from TX_WR_PTR.\r
+*    It waits if there is a previous send command in process.\r
+*    When the send command is cleared, it updates the TX_WR_PTR up to the size to be transmitted\r
+     and performs the send command.\r
+* Arguments   : s   - channel number\r
+*               buf - Pointer pointing data to send\r
+*               len - data size to send\r
+* Returns     : Succeeded: sent data size, Failed: -1\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+int send_in(SOCKET s, u_char far * buf, u_int len)\r
+{\r
+u_char k;\r
+u_int size;\r
+union un_l2cval wr_ptr, ack_ptr;\r
+unsigned int offset;\r
+\r
+S_START:\r
+disable();            // CT: Shadow register access should not conflict with ISR.\r
+k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
+wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
+wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
+wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+k = READ_VALUE(SHADOW_TXACK_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+ack_ptr.cVal[3] = READ_VALUE(TX_ACK_PTR(s));\r
+ack_ptr.cVal[2] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1));\r
+ack_ptr.cVal[1] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2));\r
+ack_ptr.cVal[0] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3));\r
+enable();\r
+\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+\r
+//  Calculate send free buffer size\r
+if (wr_ptr.lVal >= ack_ptr.lVal)\r
+  size = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));\r
+else\r
+  size = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));\r
+\r
+// Recalulate after some delay because of error in pointer calculation\r
+if (size > SSIZE[s])\r
+  {\r
+  if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
+    return -1;\r
+  delay_ms(1);\r
+        goto S_START;\r
+  }\r
+\r
+// Wait when previous sending has not finished yet and there's no free buffer\r
+if (size == 0)\r
+  {\r
+  if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
+    return -1;\r
+\r
+  delay_ms(1);\r
+  goto S_START;\r
+  }\r
+else if (size < len)\r
+  {\r
+  len = size;\r
+  }\r
+\r
+//  Calculate pointer to data copy\r
+offset = (UINT)(wr_ptr.lVal & SMASK[s]);\r
+\r
+// copy data\r
+write_data(s, buf, offset, len);\r
+\r
+while (READ_VALUE(COMMAND(s)) & CSEND)\r
+  {\r
+  // Confirm previous send command\r
+  if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
+    return -1;\r
+  }\r
+\r
+//  update tx_wr_ptr\r
+wr_ptr.lVal = wr_ptr.lVal + len;\r
+WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);\r
+\r
+delay0(1);\r
+\r
+// SEND\r
+WRITE_VALUE(COMMAND(s), CSEND);\r
+\r
+return(len);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              TCP data receiving function.\r
+*\r
+* Description : This function is to clear out any received TCP data.\r
+* Arguments   : s   - channel number\r
+* Returns     : None\r
+* Note        : API Fcuntion\r
+****************************************************************************************************\r
+*/\r
+void recv_clear(SOCKET s)\r
+{\r
+u_char k;\r
+u_int size;\r
+union un_l2cval wr_ptr, rd_ptr;\r
+\r
+disable();\r
+k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
+wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
+wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
+wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
+rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
+rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
+rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
+enable();\r
+\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+\r
+//  calculate received data size\r
+if (wr_ptr.lVal >= rd_ptr.lVal)\r
+  size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
+else\r
+  size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
+\r
+// Update rx_rd_ptr\r
+rd_ptr.lVal += size;\r
+WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
+\r
+// RECV\r
+ WRITE_VALUE(COMMAND(s), CRECV);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              TCP data receiving function.\r
+*\r
+* Description : This function is for receiving TCP data.\r
+*     The recv() function is an application I/F function. It will read up to len chars if there are\r
+      enough characters in the buffer, otherwise will onl read the number of characters availiable\r
+* Arguments   : s   - channel number\r
+*               buf - Pointer where the data to be received is copied\r
+*               len - Size of the data to be received\r
+* Returns     : Succeeded: received data size, Failed: -1\r
+* Note        : API Fcuntion\r
+****************************************************************************************************\r
+*/\r
+int recv(SOCKET s, u_char far * buf, u_int len)\r
+{\r
+u_char k;\r
+u_int size;\r
+union un_l2cval wr_ptr, rd_ptr;\r
+unsigned int offset;\r
+\r
+// If out length is 0, then we do not need to do anything\r
+if (len <= 0)\r
+  return (0);\r
+\r
+disable();\r
+k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
+wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
+wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
+wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
+rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
+rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
+rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
+enable();\r
+\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+\r
+//  calculate IIM7010A received data size\r
+if (wr_ptr.lVal == rd_ptr.lVal)\r
+  return(0);\r
+else if (wr_ptr.lVal >= rd_ptr.lVal)\r
+  size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
+else\r
+  size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
+\r
+// Make sure we do not try to read more characters than what is availiable in the IIM7010 buffer\r
+if (size < len)\r
+  len = size;\r
+\r
+// Calculate pointer to be copied received data\r
+offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
+\r
+// Copy received data\r
+size = read_data(s, offset, buf, len);\r
+\r
+// Update rx_rd_ptr\r
+rd_ptr.lVal += size;\r
+WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
+WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
+\r
+// RECV\r
+ WRITE_VALUE(COMMAND(s), CRECV);\r
+return(size);\r
+}\r
+\r
+\r
+/*\r
+****************************************************************************************************\r
+*               UDP data sending function.\r
+*\r
+* Description : Composed of the sendto()and sendto_in() functions.\r
+*    The send() function is an application I/F function.\r
+*    It continues to call the send_in() function to complete the sending of the data up to the\r
+*    size of the data to be sent\r
+*    when the application is called.Unlike TCP transmission, it designates the destination address\r
+*    and the port.\r
+* Arguments   : s    - channel port\r
+*               buf  - Pointer pointing data to send\r
+*               len  - data size to send\r
+*               addr - destination IP address to send data\r
+*               port - destination port number to send data\r
+* Returns     : Sent data size\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+u_int sendto(SOCKET s, u_char far * buf, u_int len, u_char * addr, u_int port)\r
+{\r
+//char val;\r
+u_int ptr, size;\r
+\r
+// Wait until previous send commnad has completed.\r
+while(READ_VALUE(COMMAND(s)) & CSEND)\r
+  {\r
+  if(select(s, SEL_CONTROL) == SOCK_CLOSED)\r
+    return -1; // Error.\r
+  }\r
+\r
+// Designate destination port number.\r
+if (port != 0)\r
+  {\r
+  WRITE_VALUE(DST_PORT_PTR(s), (u_char)((port & 0xff00) >> 8));\r
+  WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
+  }\r
+\r
+//  Designate destination IP address\r
+WRITE_VALUE(DST_IP_PTR(s), addr[0]);\r
+WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
+WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
+WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
+\r
+if (len <= 0)\r
+  return (0);\r
+else\r
+  {\r
+  ptr = 0;\r
+  do\r
+    {\r
+        size = sendto_in(s, buf + ptr, len);\r
+        len = len - size;\r
+        ptr += size;\r
+        } while ( len > 0);\r
+  }\r
+return ptr;\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*            UDP data sending function.\r
+*\r
+* Description : An internal function that is the same as the send_in() function of the TCP.\r
+* Arguments   : s   - Channel number\r
+*               buf - Pointer indicating the data to send\r
+*               len - data size to send\r
+* Returns     : Sent data size\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+u_int sendto_in(SOCKET s, u_char far * buf, u_int len)\r
+{\r
+u_char k;\r
+u_int size;\r
+union un_l2cval wr_ptr, rd_ptr;\r
+unsigned int offset;\r
+\r
+S2_START:\r
+disable();\r
+k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
+wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
+wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
+wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+k = READ_VALUE(SHADOW_TXRD_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+rd_ptr.cVal[3] = READ_VALUE(TX_RD_PTR(s));\r
+rd_ptr.cVal[2] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(1));\r
+rd_ptr.cVal[1] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(2));\r
+rd_ptr.cVal[0] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(3));\r
+enable();\r
+\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+\r
+//  Calculate free buffer size to send\r
+if (wr_ptr.lVal >= rd_ptr.lVal)\r
+  size = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));\r
+else\r
+  size = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));\r
+\r
+//  Recalulate after some delay because of error in pointer caluation\r
+if (size > SSIZE[s])\r
+  {\r
+  delay_ms(1);\r
+  goto S2_START;\r
+  }\r
+\r
+// Wait when previous sending has not finished yet and there's no free buffer\r
+if (size == 0)\r
+  {\r
+  delay_ms(1);\r
+  goto S2_START;\r
+\r
+  }\r
+else if (size < len)\r
+  {\r
+  len = size;\r
+  }\r
+\r
+// Calculate pointer to copy data pointer\r
+offset =(UINT)(wr_ptr.lVal & SMASK[s]);\r
+\r
+// copy data\r
+write_data(s, buf, offset, len);\r
+\r
+// Confirm previous send command\r
+while (READ_VALUE(COMMAND(s)) & CSEND)\r
+  {\r
+  if(select(s, SEL_CONTROL)==SOCK_CLOSED)\r
+    return -1;                  // Error\r
+  }\r
+\r
+// update tx_wr_ptr\r
+wr_ptr.lVal = wr_ptr.lVal + len;\r
+WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);\r
+WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);\r
+\r
+delay0(1);\r
+\r
+// SEND\r
+WRITE_VALUE(COMMAND(s), CSEND);\r
+\r
+return(len);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*             UDP data receiving function.\r
+*\r
+* Description : Function for receiving UDP and IP layer RAW mode data, and handling the data header.\r
+* Arguments   : s    - channel number\r
+*               buf  - Pointer where the data to be received is copied\r
+*               len  - Size of the data to be received\r
+*               addr - Peer IP address for receiving\r
+*               port - Peer port number for receiving\r
+* Returns     : Received data size\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+u_int recvfrom(SOCKET s, u_char far *buf, u_int len, u_char *addr, u_int *port)\r
+{\r
+struct _UDPHeader                                                                      // When receiving UDP data, header added by W3100A\r
+  {\r
+  union\r
+        {\r
+        struct\r
+               {\r
+               u_int size;\r
+               u_char addr[4];\r
+               u_int port;\r
+               } header;\r
+        u_char stream[8];\r
+    } u;\r
+  } UDPHeader;\r
+\r
+u_int ret;\r
+union un_l2cval wr_ptr, rd_ptr;\r
+u_long size;\r
+u_char k;\r
+unsigned int offset;\r
+\r
+if(select(s,SEL_CONTROL)==SOCK_CLOSED)\r
+  return -1;\r
+\r
+disable();\r
+k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
+wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
+wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
+wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
+WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+delay0(2);\r
+rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
+rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
+rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
+rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
+enable();\r
+\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+\r
+// Calculate received data size\r
+if (len <= 0)\r
+  return (0);\r
+else if (wr_ptr.lVal >= rd_ptr.lVal)\r
+  size = wr_ptr.lVal - rd_ptr.lVal;\r
+else\r
+  size = 0 - rd_ptr.lVal + wr_ptr.lVal;\r
+\r
+if (size == 0)\r
+  return 0;\r
+\r
+  // Calulate received data pointer\r
+offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
+\r
+// When UDP data\r
+if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_DGRAM)\r
+  {\r
+  // Copy W3100A UDP header\r
+  read_data(s, offset, UDPHeader.u.stream, 8);\r
+\r
+  // Read UDP Packet size\r
+  size = UDPHeader.u.stream[0];\r
+  size = (size << 8) + UDPHeader.u.stream[1];\r
+\r
+  // Read IP address of the peer\r
+  addr[0] = UDPHeader.u.header.addr[0];\r
+  addr[1] = UDPHeader.u.header.addr[1];\r
+  addr[2] = UDPHeader.u.header.addr[2];\r
+  addr[3] = UDPHeader.u.header.addr[3];\r
+\r
+  // Read Port number of the peer\r
+  *port = UDPHeader.u.stream[6];\r
+  *port = (*port << 8) + UDPHeader.u.stream[7];\r
+\r
+  // Increase read pointer by 8, because already read as UDP header size\r
+  rd_ptr.lVal += 8;\r
+\r
+  // Calculate UDP data copy pointer\r
+  offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
+\r
+  // Calculate data size of current UDP Packet from UDP header\r
+  size = size - 8;\r
+\r
+  // Copy one UDP data packet to user-specific buffer\r
+  ret = read_data(s, offset, buf, (u_int)size);\r
+\r
+  // Increase read pointer by UDP packet data size\r
+  rd_ptr.lVal += ret;\r
+  }\r
+else if ((READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_IPL_RAW)  // When IP layer RAW mode data\r
+  {\r
+  // Copy W3100A IP Raw header\r
+  read_data(s, offset, UDPHeader.u.stream, 6);\r
+\r
+  // Read IP layer RAW Packet size\r
+  size = UDPHeader.u.stream[0];\r
+  size = (size << 8) + UDPHeader.u.stream[1];\r
+\r
+  // Read IP address of the peer\r
+  addr[0] = UDPHeader.u.header.addr[0];\r
+  addr[1] = UDPHeader.u.header.addr[1];\r
+  addr[2] = UDPHeader.u.header.addr[2];\r
+  addr[3] = UDPHeader.u.header.addr[3];\r
+\r
+  // Increase read pointer by 6, because already read as IP RAW header size\r
+  rd_ptr.lVal += 6;\r
+\r
+  // Calculate IP layer raw mode data pointer\r
+  offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
+\r
+  // Copy one IP Raw data packet to user-specific buffer\r
+  ret = read_data(s, offset, buf, (u_int)size);\r
+  rd_ptr.lVal = rd_ptr.lVal + (ret - 4);\r
+  }\r
+\r
+  // Update rx_rd_ptr\r
+  WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
+  WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
+  WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
+  WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
+\r
+  // RECV\r
+  WRITE_VALUE(COMMAND(s), CRECV);\r
+\r
+// Real received size return\r
+return(ret);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Channel closing function.\r
+*\r
+* Description : Function for closing the connection of the designated channel.\r
+* Arguments   : s - channel number\r
+* Returns     : None\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+void close(SOCKET s)\r
+{\r
+u_int len;\r
+short sAttempts = 0;\r
+\r
+I_STATUS[s] = 0;\r
+\r
+if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
+  return;         // Already closed\r
+\r
+// When closing, if there's data which have not processed, Insert some source codes to handle this\r
+// Or before application call close(), handle those data first and call close() later.\r
+\r
+len = select(s, SEL_SEND);\r
+if (len == SSIZE[s])\r
+  {\r
+  // CLOSE\r
+  WRITE_VALUE(COMMAND(s), CCLOSE);\r
+  // TODO: The 'SCLOSED' status value is only set briefly as part of the close,\r
+  // and will otherwise quickly return to normal.  That means your code might\r
+  // become 'stuck' at this point even if the packet has closed normally.\r
+  // Rather than a while() call, it might be preferred to time out on this\r
+  // close check and return to the application after some time.\r
+  while(!(I_STATUS[s] & SCLOSED))\r
+  {\r
+         sAttempts++;\r
+      if( sAttempts > 10 )\r
+      {\r
+       break;\r
+      }\r
+         I2CHIP_POLL_ISR(in4_isr_i2chip);\r
+      vTaskDelay( 1 );\r
+  }\r
+  }\r
+}\r
+\r
+u_char tx_empty(SOCKET s)\r
+{\r
+       return (select(s, SEL_SEND) == SSIZE[s]);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Channel closing function.\r
+*\r
+* Description : Function for closing the connection of the designated channel.\r
+* Arguments   : s - channel number\r
+* Returns     : None\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+char reset_sock(SOCKET s)\r
+{\r
+u_char c;\r
+\r
+c = 1 << s;\r
+\r
+// RESET\r
+WRITE_VALUE(RESETSOCK, c);\r
+return (1);\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*             Function handling the channel socket information.\r
+*\r
+* Description : Return socket information of designated channel\r
+* Arguments   : s    - channel number\r
+*               func - SEL_CONTROL(0x00) -> return socket status\r
+*                      SEL_SEND(0x01)    -> return free transmit buffer size\r
+*                      SEL_RECV(0x02)    -> return received data size\r
+* Returns     : socket status or free transmit buffer size or received data size\r
+* Note        : API Function\r
+****************************************************************************************************\r
+*/\r
+u_int select(SOCKET s, u_char func)\r
+{\r
+u_int val;\r
+union un_l2cval rd_ptr, wr_ptr, ack_ptr;\r
+u_char k;\r
+\r
+switch (func)\r
+  {\r
+  // socket status information\r
+  case SEL_CONTROL :\r
+        val = READ_VALUE(SOCK_STATUS(s));\r
+        break;\r
+\r
+  // Calculate send free buffer size\r
+  case SEL_SEND :\r
+        disable();\r
+        k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
+        WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+        delay0(2);\r
+        wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
+        wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
+        wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
+        wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+        if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_STREAM)      // TCP\r
+               {\r
+               k = READ_VALUE(SHADOW_TXACK_PTR(s));\r
+               WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+               delay0(2);\r
+               ack_ptr.cVal[3] = READ_VALUE(TX_ACK_PTR(s));\r
+               ack_ptr.cVal[2] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1));\r
+               ack_ptr.cVal[1] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2));\r
+               ack_ptr.cVal[0] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3));\r
+               enable();\r
+\r
+               if (wr_ptr.lVal >= ack_ptr.lVal)\r
+        val = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));\r
+               else\r
+        val = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));\r
+               }\r
+        else                                                                                   // UDP, IP RAW ... (except TCP)\r
+               {\r
+               k = READ_VALUE(SHADOW_TXRD_PTR(s));\r
+               WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+               delay0(2);\r
+               rd_ptr.cVal[3] = READ_VALUE(TX_RD_PTR(s));\r
+               rd_ptr.cVal[2] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(1));\r
+               rd_ptr.cVal[1] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(2));\r
+               rd_ptr.cVal[0] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(3));\r
+               enable();\r
+\r
+               if (wr_ptr.lVal >= rd_ptr.lVal)\r
+        val = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));\r
+               else\r
+        val = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));\r
+               }\r
+        break;\r
+\r
+  //  Calculate received data size\r
+  case SEL_RECV :\r
+        disable();\r
+        k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
+        WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+        delay0(2);\r
+        wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
+        wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
+        wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
+        wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
+\r
+        k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
+    WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
+        delay0(2);\r
+        rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
+        rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
+        rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
+        rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
+        enable();\r
+\r
+        if (wr_ptr.lVal == rd_ptr.lVal)\r
+      val = 0;\r
+        else if (wr_ptr.lVal > rd_ptr.lVal)\r
+      val = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
+        else\r
+      val = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
+        break;\r
+\r
+  default :\r
+        val = -1;\r
+        break;\r
+  }\r
+// Suppress compiler errors that k is not used\r
+k = k;\r
+return(val);\r
+}\r
+\r
+//\r
+//     unsigned char dma_read_i2chip (unsigned int i2_segm, unsigned int i2_offs,\r
+//     unsigned int cnt, unsigned int des_segm, unsigned int des_offs);\r
+//     Using DMA0 to read data from i2chip buffer into destination SRAM.\r
+//     where:\r
+//             unsigned int cnt = number of sectors, 512-byte per sector\r
+//             unsigned int des_segm = segment of destination SRAM data memory\r
+//             unsigned int des_offs = offset of destination SRAM data memory\r
+//             unsigned int i2_segm = segment of i2chip buffer mapped in memory\r
+//             unsigned int i2_offs = offset of i2chip buffer mapped in memory\r
+//      return DMA counter value\r
+//\r
+unsigned int dma_read_i2chip(u_char far* i2_src, u_char far* des, u_int cnt)\r
+{\r
+       u_int des_segm, des_offs;\r
+   u_int i2_segm, i2_offs;\r
+   u_long temp;\r
+\r
+   temp = ((long)FP_SEG(des) << 4) + ((long)FP_OFF(des));\r
+   des_segm = (u_int)(temp >> 16);\r
+   des_offs = (u_int)(temp & 0xffff);\r
+\r
+   temp = ((long)FP_SEG(i2_src) << 4) + ((long)FP_OFF(i2_src));\r
+   i2_segm = (u_int)(temp >> 16);\r
+   i2_offs = (u_int)(temp & 0xffff);\r
+\r
+       outport(0xffc6, des_segm);   /* D0DSTH destination SRAM segment */\r
+       outport(0xffc4, des_offs);   /* D0DSTL destination SRAM offset */\r
+       outport(0xffc2, i2_segm);   /* D0SRCH=SP0RD */\r
+       outport(0xffc0, i2_offs);   /* D0SRCL=SP0RD */\r
+       outport(0xffc8, cnt);   // D0TC counter\r
+       outport(0xfff8,0x0504); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
+// DMA0 mem-mem, 16-bit, unsync, Start moving data line below\r
+       outport(0xffca, 0xb60e);   /* D0CON 1011 0110 0000 1111 */\r
+//     outport(0xffca, 0xb42e);         // 1011 0100 0010 1110\r
+       while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */\r
+       outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
+return( inport(0xffc8) ); // counter\r
+}\r
+\r
+//\r
+//     unsigned int dma_write_i2chip (unsigned int src_segm, unsigned int src_offs,\r
+//     unsigned int cnt, unsigned int i2_segm, unsigned int i2_offs);\r
+//     Using DMA0 to write data from memory into i2chip.\r
+//     where:\r
+//             unsigned int cnt = number of 16-bit DMA transfers\r
+//             unsigned int src_segm = segment of the source SRAM data memory\r
+//             unsigned int src_offs = offset of the source SRAM data memory\r
+//             unsigned int i2_segm = segment of i2chip buffer mapped in memory\r
+//             unsigned int i2_offs = offset of i2chip buffer mapped in memory\r
+//      return DMA counter value\r
+//\r
+unsigned int dma_write_i2chip(u_char far* src, u_char far* i2_dest, u_int cnt)\r
+{\r
+       u_int src_segm, src_offs;\r
+   u_int i2_segm, i2_offs;\r
+   u_long temp;\r
+\r
+   temp = (FP_SEG(src) << 4) + (FP_OFF(src));\r
+   src_segm = (u_int)(temp >> 4);\r
+   src_offs = (u_int)(temp & 0xffff);\r
+\r
+   temp = (FP_SEG(i2_dest) << 4) + (FP_OFF(i2_dest));\r
+   i2_segm = (u_int)(temp >> 4);\r
+   i2_offs = (u_int)(temp & 0xffff);\r
+\r
+       outport(0xffc8, cnt);   // D0TC counter\r
+       outport(0xffc6, i2_segm); // D0DSTH=i2chip buffer segment\r
+       outport(0xffc4, i2_offs); // D0DSTL=i2chip buffer offset\r
+       outport(0xffc2, src_segm);   /* D0SRCH=SP0RD */\r
+       outport(0xffc0, src_offs);   /* D0SRCL=SP0RD */\r
+//     outport(0xfff8,0x050f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
+// DMA0 mem-mem, 16-bit, unsync, Start moving data line below\r
+       outport(0xffca, 0xb60f);   /* D0CON 1011 0110 0000 1111 */\r
+       while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */\r
+//     outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
+\r
+return( inport(0xffc8) ); // counter\r
+}\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Copies the receive buffer data of the W3100A to the system buffer.\r
+*\r
+* Description : Copies the receive buffer data of the W3100A to the system buffer.\r
+*    It is called from the recv()or recvfrom() function.\r
+* Arguments   : s   - channel number\r
+*               src - receive buffer pointer of W3100A\r
+*               dst - system buffer pointer\r
+*               len - data size to copy\r
+* Returns     : copied data size\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+u_int read_data(SOCKET s, u_int offset, u_char far * dst, u_int len)\r
+{\r
+       u_int i, size, size1;\r
+   u_char far* src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,\r
+                                        RBUFBASEADDRESS[s] + offset));\r
+//   src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,\r
+//                                        0));\r
+\r
+       if (len == 0)\r
+   {\r
+       WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
+               return 0;\r
+   }\r
+\r
+   if ((offset + len) > RSIZE[s])\r
+   {\r
+               size = (u_int)(RSIZE[s] - offset);\r
+\r
+               if (size > TERN_RDMA_THRES)\r
+               {\r
+                       dma_read_i2chip(src, dst, size);\r
+               }\r
+               else\r
+      {\r
+                       for (i = 0; i < size; i++)\r
+               {\r
+                               *dst++ = READ_VALUE(src);\r
+            WINDOW_PTR_INC(src);\r
+\r
+                       }\r
+               }\r
+\r
+         size1 = len - size;\r
+     src = (u_char far *)(MK_FP_WINDOW(RECV_DATA_BUF, (RBUFBASEADDRESS[s])));\r
+\r
+     if (size1 > TERN_RDMA_THRES)\r
+     {\r
+               dma_read_i2chip(src, dst, size);\r
+         }\r
+     else\r
+         {\r
+                       for (i = 0; i < size1; i++)\r
+               {\r
+                               *dst++ = READ_VALUE(src);\r
+            WINDOW_PTR_INC(src);\r
+               }\r
+               }\r
+       }\r
+   else\r
+   {\r
+        if (len > TERN_RDMA_THRES)\r
+    {\r
+               dma_read_i2chip(src, dst, size);\r
+    }\r
+    else\r
+    {\r
+               for (i = 0; i < len; i++)\r
+       {\r
+                       *dst++ = READ_VALUE(src);\r
+         WINDOW_PTR_INC(src);\r
+               }\r
+    }\r
+   }\r
+   WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
+       return len;\r
+}\r
+\r
+\r
+/*\r
+****************************************************************************************************\r
+*              Copies the system buffer data to the transmit buffer of the W3100A.\r
+*\r
+* Description : Copies the system buffer data to the transmit buffer of the W3100A.\r
+*               It is called from the send_in()or sendto_in() function.\r
+* Arguments   : s   - channel number\r
+*               src - system buffer pointer\r
+*               dst - send buffer pointer of W3100A\r
+*               len - data size to copy\r
+* Returns     : copied data size\r
+* Note        : Internal Function\r
+****************************************************************************************************\r
+*/\r
+u_int write_data(SOCKET s, u_char far * src, u_int offset, u_int len)\r
+{\r
+       u_int i, size, size1;\r
+       u_char far* dst = (u_char far*)MK_FP_WINDOW(SEND_DATA_BUF,\r
+                                  SBUFBASEADDRESS[s] + offset);\r
+\r
+       if (len == 0)\r
+   {\r
+       WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
+               return 0;\r
+   }\r
+\r
+       if ((offset + len) > SSIZE[s])\r
+   {\r
+               size = (u_int)(SSIZE[s] - offset);\r
+\r
+               for (i = 0; i < size; i++)\r
+       {\r
+                       WRITE_VALUE(dst, *src++);\r
+         WINDOW_PTR_INC(dst);\r
+               }\r
+\r
+               size1 = len - size;\r
+               dst = (u_char far *)(MK_FP_WINDOW(SEND_DATA_BUF, (SBUFBASEADDRESS[s])));\r
+\r
+               for (i = 0; i < size1; i++)\r
+       {\r
+                       WRITE_VALUE(dst, *src++);\r
+         WINDOW_PTR_INC(dst);\r
+               }\r
+  }\r
+  else\r
+  {\r
+       for (i = 0; i < len; i++)\r
+       {\r
+                       WRITE_VALUE(dst, *src++);\r
+         WINDOW_PTR_INC(dst);\r
+               }\r
+       }\r
+   WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
+       return len;\r
+}\r
+\r
+\r
+\r