--- /dev/null
+/*\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