]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/WizNET_DEMO_TERN_186/tern_code/socket.c
adfc54814dd7b750bcc3741d7da93fd3708c9948
[freertos] / FreeRTOS / Demo / WizNET_DEMO_TERN_186 / tern_code / socket.c
1 /*\r
2 ********************************************************************************\r
3 * TERN, Inc.\r
4 * (c) Copyright 2005, http://www.tern.com\r
5 *\r
6 * MODIFIED BY RICHARD BARRY TO ADD SEMAPHORE FOR COMMUNICATION BETWEEN THE \r
7 * WIZnet ISR AND THE HTTP TASK.\r
8 *\r
9 * - Derived based on development version provided by Wiznet.\r
10 *\r
11 * Filename : socket.h\r
12 * Programmer(s):\r
13 * Created : 2002/06/20\r
14 * Modified :\r
15 *  2002/09/27 : - Renaming\r
16 *                              INT_STATUS --> INT_REG\r
17 *                              STATUS(i) --> INT_STATUS(i)\r
18 *                              C_STATUS(i) --> SOCK_STATUS(i)\r
19 *  2003/11/06 : Ported for use with TERN controller.  Note all byte access is at even addresses\r
20 *  2005/10/8  : Modified constants for easier initialization.\r
21 *\r
22 * Description : Header file of W3100A for TERN embedded controller\r
23 ********************************************************************************\r
24 */\r
25 /*\r
26 ###############################################################################\r
27 File Include Section\r
28 ###############################################################################\r
29 */\r
30 #include "i2chip_hw.h" \r
31 #include "socket.h"\r
32 #include "types.h"\r
33 #include <string.h>\r
34 #include <stdio.h>\r
35 \r
36 #include <FreeRTOS.h>\r
37 #include <semphr.h>\r
38 #include <portasm.h>\r
39 \r
40 \r
41 /*\r
42 ###############################################################################\r
43 Local Variable Declaration Section\r
44 ###############################################################################\r
45 */\r
46 u_char I_STATUS[4];                             // Store Interrupt Status according to channels\r
47 u_int Local_Port;                                  // Designate Local Port\r
48 union un_l2cval SEQ_NUM;                // Set initial sequence number\r
49 \r
50 u_long SMASK[MAX_SOCK_NUM];   // Variable to store MASK of Tx in each channel,\r
51                               // on setting dynamic memory size.\r
52 u_long RMASK[MAX_SOCK_NUM];   // Variable to store MASK of Rx in each channel,\r
53                               // on setting dynamic memory size.\r
54 int SSIZE[MAX_SOCK_NUM];      // Maximun Tx memory size by each channel\r
55 int RSIZE[MAX_SOCK_NUM];      // Maximun Rx memory size by each channel\r
56 \r
57 u_int SBUFBASEADDRESS[MAX_SOCK_NUM];   // Maximun Tx memory base address by each channel\r
58 u_int RBUFBASEADDRESS[MAX_SOCK_NUM];   // Maximun Rx memory base address by each channel\r
59 \r
60 /*\r
61 ###############################################################################\r
62 Function Implementation Section\r
63 ###############################################################################\r
64 */\r
65 \r
66 /*\r
67 ********************************************************************************\r
68 *               Interrupt handling function of the W3100A\r
69 *\r
70 * Description :\r
71 *   Stores the status information that each function waits for in the global variable I_STATUS\r
72 *   for transfer. I_STATUS stores the interrupt status value for each channel.\r
73 * Arguments   : None\r
74 * Returns     : None\r
75 * Note        : Internal Function\r
76 ********************************************************************************\r
77 */\r
78 \r
79 portBASE_TYPE prvProcessISR( void )\r
80 {\r
81 unsigned char status;\r
82 extern xSemaphoreHandle xTCPSemaphore;\r
83 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
84 \r
85 #ifdef I2CHIP_WINDOW\r
86 u_int current_window = i2chip_get_window();\r
87 #endif\r
88 \r
89 status = READ_VALUE(INT_REG);\r
90 \r
91 \r
92 if (status)\r
93   {\r
94   xHigherPriorityTaskWoken = pdTRUE;\r
95   // channel 0 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
96   if (status & 0x01)\r
97     {\r
98          I_STATUS[0] = READ_VALUE(INT_STATUS(0));\r
99 \r
100 //       if (I_STATUS[0] & SESTABLISHED)\r
101 //    ISR_ESTABLISHED(0);\r
102 //       if (I_STATUS[0] & SCLOSED)\r
103 //    ISR_CLOSED(0);\r
104 \r
105          WRITE_VALUE(INT_REG, 0x01);\r
106          }\r
107 \r
108   // channel 1 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
109   if (status & 0x02)\r
110     {\r
111          I_STATUS[1] = READ_VALUE(INT_STATUS(1));\r
112 \r
113 //       if (I_STATUS[1] & SESTABLISHED)\r
114 //    ISR_ESTABLISHED(1);\r
115 //       if (I_STATUS[1] & SCLOSED)\r
116 //    ISR_CLOSED(1);\r
117 \r
118          WRITE_VALUE(INT_REG, 0x02);\r
119          }\r
120 \r
121   // channel 2 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
122   if (status & 0x04)\r
123     {\r
124          I_STATUS[2] = READ_VALUE(INT_STATUS(2));\r
125 \r
126 //       if (I_STATUS[2] & SESTABLISHED)\r
127 //    ISR_ESTABLISHED(2);\r
128 //       if (I_STATUS[2] & SCLOSED)\r
129 //    ISR_CLOSED(2);\r
130 \r
131          WRITE_VALUE(INT_REG, 0x04);\r
132          }\r
133 \r
134   // channel 3 interrupt(sysinit, sockinit, established, closed, timeout, send_ok, recv_ok)\r
135   if (status & 0x08)\r
136     {\r
137          I_STATUS[3] = READ_VALUE(INT_STATUS(3));\r
138 \r
139 //       if (I_STATUS[3] & SESTABLISHED) ISR_ESTABLISHED(3);\r
140 //       if (I_STATUS[3] & SCLOSED) ISR_CLOSED(3);\r
141 \r
142          WRITE_VALUE(INT_REG, 0x08);\r
143          }\r
144 \r
145   // channel 0 receive interrupt\r
146   if (status & 0x10)\r
147     {\r
148 //       ISR_RX(0);\r
149          WRITE_VALUE(INT_REG, 0x10);\r
150          }\r
151 \r
152   // channel 1 receive interrupt\r
153   if (status & 0x20)\r
154     {\r
155 //       ISR_RX(1);\r
156          WRITE_VALUE(INT_REG, 0x20);\r
157          }\r
158 \r
159   // channel 2 receive interrupt\r
160   if (status & 0x40)\r
161     {\r
162 //       ISR_RX(2);\r
163          WRITE_VALUE(INT_REG, 0x40);\r
164          }\r
165 \r
166   // channel 3 receive interrupt\r
167   if (status & 0x80)\r
168     {\r
169 //       ISR_RX(3);\r
170          WRITE_VALUE(INT_REG, 0x80);\r
171          }\r
172   status = READ_VALUE(INT_REG);\r
173   }\r
174 \r
175 WRITE_VALUE(INT_REG, 0xFF);\r
176 \r
177 #ifdef I2CHIP_WINDOW\r
178 i2chip_set_window(current_window);\r
179 #endif\r
180 \r
181         if( xHigherPriorityTaskWoken == pdTRUE )\r
182     {\r
183                 xSemaphoreGiveFromISR( xTCPSemaphore, &xHigherPriorityTaskWoken );\r
184     }\r
185 \r
186         return xHigherPriorityTaskWoken;\r
187 }\r
188 \r
189 void far interrupt in4_isr_i2chip(void)\r
190 {\r
191         if( prvProcessISR() == pdTRUE )\r
192     {\r
193                 portEND_SWITCHING_ISR();\r
194     }\r
195 \r
196     INT_EOI;\r
197 }\r
198 \r
199 /*\r
200 ****************************************************************************************************\r
201 *               Established connection interrupt handling function.\r
202 *\r
203 * Description :\r
204 *   Called upon connection establishment, and may be inserted in user code if needed by\r
205 *   the programmer.\r
206 * Arguments   : None\r
207 * Returns     : None\r
208 * Note        : Internal Function\r
209 ****************************************************************************************************\r
210 */\r
211 /*\r
212 void ISR_ESTABLISHED(SOCKET s)\r
213 {\r
214 // TO ADD YOUR CODE\r
215 }\r
216 */\r
217 \r
218 /*\r
219 ****************************************************************************************************\r
220 *               Closed connection interrupt handling function\r
221 *\r
222 * Description :\r
223 *   Called upon connection closure, and may be inserted in user code if needed by the programmer.\r
224 * Arguments   : None\r
225 * Returns     : None\r
226 * Note        : Internal Function\r
227 ****************************************************************************************************\r
228 */\r
229 /*\r
230 void ISR_CLOSED(SOCKET s)\r
231 {\r
232 // TO ADD YOUR CODE\r
233 }\r
234 */\r
235 \r
236 /*\r
237 ****************************************************************************************************\r
238 *               Received data interrupt handling function\r
239 *\r
240 * Description :\r
241 *   Called upon receiving data, and may be inserted in user code if needed by the programmer.\r
242 * Arguments   : None\r
243 * Returns     : None\r
244 * Note        : Internal Function\r
245 ****************************************************************************************************\r
246 */\r
247 /*\r
248 void ISR_RX(SOCKET s)\r
249 {\r
250 // TO ADD YOUR CODE\r
251 }\r
252 */\r
253 \r
254 /*\r
255 ****************************************************************************************************\r
256 *              W3100A Initialization Function\r
257 *\r
258 * Description:  Reset of W3100A S/W and Registeration of i386 interrupt\r
259 * Arguments  : None.\r
260 * Returns    : None.\r
261 * Note       :\r
262 ****************************************************************************************************\r
263 */\r
264 void initW3100A(void)\r
265 {\r
266 \r
267 // Install interrupt handler for i2Chip\r
268 INT_INIT(in4_isr_i2chip);\r
269 \r
270 \r
271 Local_Port = 1000;         // This default value will be set if you didn't designate it when you\r
272                            // create a socket. If you don't designate port number and create a\r
273                            // socket continuously, the port number will be assigned with\r
274                            // incremented by one to Local_Port\r
275 SEQ_NUM.lVal = 4294967293ul;    // Sets the initial SEQ# to be used for TCP communication.\r
276                            // (It should be ramdom value)\r
277 WRITE_VALUE(COMMAND(0), CSW_RESET);   // Software RESET\r
278 }\r
279 \r
280 /*\r
281 ****************************************************************************************************\r
282 *               W3100A initialization function\r
283 *\r
284 * Description :\r
285 *   Sets the Tx, Rx memory size by each channel, source MAC, source IP, gateway, and subnet mask\r
286 *   to be used by the W3100A to the designated values.\r
287 *   May be called when reflecting modified network information or Tx, Rx memory size on the W3100A\r
288 *   Include Ping Request for ARP update (In case that a device embedding W3100A is directly\r
289 *     connected to Router)\r
290 * Arguments  : sbufsize - Tx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)\r
291 *                          bit 1-0 : Tx memory size of channel #0\r
292 *                          bit 3-2 : Tx memory size of channel #1\r
293 *                          bit 5-4 : Tx memory size of channel #2\r
294 *                          bit 7-6 : Tx memory size of channel #3\r
295 *              rbufsize - Rx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte)\r
296 *                          bit 1-0 : Rx memory size of channel #0\r
297 *                          bit 3-2 : Rx memory size of channel #1\r
298 *                          bit 5-4 : Rx memory size of channel #2\r
299 *                          bit 7-6 : Rx memory size of channel #3\r
300 * Returns    : None\r
301 * Note       : API Function\r
302 *              Maximum memory size for Tx, Rx in W3100A is 8KBytes,\r
303 *              In the range of 8KBytes, the memory size could be allocated dynamically by\r
304 *              each channel\r
305 *              Be attentive to sum of memory size shouldn't exceed 8Kbytes\r
306 *              and to data transmission and receiption from non-allocated channel may cause\r
307 *              some problems.\r
308 *              If 8KBytes memory already is assigned to centain channel, other 3 channels\r
309 *                couldn't be used, for there's no available memory.\r
310 *              If two 4KBytes memory are assigned to two each channels, other 2 channels couldn't\r
311 *                be used, for there's no available memory.\r
312 *              (Example of memory assignment)\r
313 *               sbufsize => 00000011, rbufsize => 00000011 :\r
314 *                 Assign 8KBytes for Tx and Rx to channel #0, Cannot use channel #1,#2,#3\r
315 *               sbufsize => 00001010, rbufsize => 00001010 :\r
316 *                 Assign 4KBytes for Tx and Rx to each channel #0,#1 respectively. Cannot use\r
317 *                 channel #2,#3\r
318 *               sbufsize => 01010101, rbufsize => 01010101 :\r
319 *                 Assign 2KBytes for Tx and Rx to each all channels respectively.\r
320 *               sbufsize => 00010110, rbufsize => 01010101 :\r
321 *                 Assign 4KBytes for Tx, 2KBytes for Rx to channel #0\r
322 *       s          2KBytes for Tx, 2KBytes for Rx to channel #1\r
323 *                 2KBytes for Tx, 2KBytes for Rx to channel #2\r
324 *                 2KBytes is available exclusively for Rx in channel #3. There's no memory for Tx.\r
325 ****************************************************************************************************\r
326 */\r
327 void sysinit(u_char sbufsize, u_char rbufsize)\r
328 {\r
329 char i;\r
330 int ssum,rsum;\r
331 \r
332 ssum = 0;\r
333 rsum = 0;\r
334 \r
335 // Set Tx memory size for each channel\r
336 WRITE_VALUE(TX_DMEM_SIZE, sbufsize);\r
337 \r
338 // Set Rx memory size for each channel\r
339 WRITE_VALUE(RX_DMEM_SIZE, rbufsize);\r
340 \r
341 // Set Base Address of Tx memory for channel #0\r
342 SBUFBASEADDRESS[0] = 0;\r
343 \r
344 // Set Base Address of Rx memory for channel #0\r
345 RBUFBASEADDRESS[0] = 0;\r
346 \r
347 // Set maximum memory size for Tx and Rx, mask, base address of memory by each channel\r
348 for(i = 0 ; i < MAX_SOCK_NUM; i++)\r
349   {\r
350   SSIZE[i] = 0;\r
351   RSIZE[i] = 0;\r
352   if(ssum < 8192)\r
353          {\r
354          switch((sbufsize >> i*2) & 0x03) // Set maximum Tx memory size\r
355                 {\r
356                 case 0:\r
357                   SSIZE[i] = 1024;\r
358                   SMASK[i] = 0x000003FF;\r
359                   break;\r
360 \r
361                 case 1:\r
362                   SSIZE[i] = 2048;\r
363                   SMASK[i] = 0x000007FF;\r
364                   break;\r
365 \r
366                 case 2:\r
367                   SSIZE[i] = 4096;\r
368                   SMASK[i] = 0x00000FFF;\r
369                   break;\r
370 \r
371                 case 3:\r
372                   SSIZE[i] = 8192;\r
373                   SMASK[i] = 0x00001FFF;\r
374                   break;\r
375                 }\r
376          }\r
377   if(rsum < 8192)\r
378          {\r
379          switch((rbufsize >> i*2) & 0x03)  // Set maximum Rx memory size\r
380                 {\r
381                 case 0:\r
382                   RSIZE[i] = 1024;\r
383                   RMASK[i] = 0x000003FF;\r
384                   break;\r
385 \r
386                 case 1:\r
387                   RSIZE[i] = 2048;\r
388                   RMASK[i] = 0x000007FF;\r
389                   break;\r
390 \r
391                 case 2:\r
392                   RSIZE[i] = 4096;\r
393                   RMASK[i] = 0x00000FFF;\r
394                   break;\r
395 \r
396                 case 3:\r
397                   RSIZE[i] = 8192;\r
398                   RMASK[i] = 0x00001FFF;\r
399                   break;\r
400                 }\r
401          }\r
402   ssum += SSIZE[i];\r
403   rsum += RSIZE[i];\r
404 \r
405   // Set base address of Tx and Rx memory for channel #1,#2,#3\r
406   if(i != 0)\r
407     {\r
408     SBUFBASEADDRESS[i] = ssum - SSIZE[i];\r
409     RBUFBASEADDRESS[i] = rsum - RSIZE[i];\r
410     }\r
411   }\r
412 \r
413   WRITE_VALUE(COMMAND(0), CSYS_INIT);\r
414 \r
415 while(!(I_STATUS[0] & SSYS_INIT_OK))\r
416   I2CHIP_POLL_ISR(in4_isr_i2chip);\r
417 \r
418 #ifdef __PING__\r
419   {\r
420   u_char xdata pingbuf[8];\r
421   setIPprotocol(0, IPPROTO_ICMP);\r
422   socket(0, SOCK_IPL_RAW, 3000,0);     // Create a socket for ARP update\r
423 \r
424   pingbuf[0] = 8;                      // ICMP TYPE\r
425   pingbuf[1] = 0;                      // ICMP CODE\r
426   pingbuf[2] = 0xf7;                   // CHECKSUM (already calculated)\r
427   pingbuf[3] = 0xfd;\r
428   pingbuf[4] = 0;                      // ID\r
429   pingbuf[5] = 1;\r
430   pingbuf[6] = 0;                      // SEQ #\r
431   pingbuf[7] = 1;\r
432   pingbuf[8] = 0;                      // Data 1 Byte\r
433 \r
434   sendto(0, pingbuf, 9, GATEWAY_PTR,3000);  // Ping Request\r
435   close(0);\r
436   printf("Route MAC Update Success");\r
437   }\r
438 #endif\r
439 }\r
440 \r
441 /*\r
442 ****************************************************************************************************\r
443 *              Function to set subnet mask\r
444 *\r
445 * Description:\r
446 * Arguments  : addr--> Pointer that has the value to be set\r
447 * Returns    : None.\r
448 * Note       :\r
449 ****************************************************************************************************\r
450 */\r
451 void setsubmask(u_char * addr)\r
452 {\r
453 u_char i;\r
454 u_char far* sm_ptr = SUBNET_MASK_PTR;   // We can only convert to 'regular'\r
455                                    // pointer if we're confident arithmetic\r
456                                    // won't take us out of current window.\r
457 \r
458 for (i = 0; i < 4; i++)\r
459   {\r
460   WRITE_VALUE(sm_ptr + SA_OFFSET(i), addr[i]);\r
461   }\r
462 }\r
463 \r
464 /*\r
465 ****************************************************************************************************\r
466 *               Function to set gateway IP\r
467 *\r
468 * Description:\r
469 * Arguments  : addr--> Pointer that has Gateway IP to be set\r
470 * Returns    : None.\r
471 * Note       :\r
472 ****************************************************************************************************\r
473 */\r
474 void setgateway(u_char * addr)\r
475 {\r
476 u_char i;\r
477 u_char far* gw_ptr = GATEWAY_PTR;   // We can only convert to 'regular'\r
478                                    // pointer if we're confident arithmetic\r
479                                    // won't take us out of current window.\r
480 for (i = 0; i < 4; i++)\r
481   {\r
482   WRITE_VALUE(gw_ptr + SA_OFFSET(i), addr[i]);\r
483   }\r
484 }\r
485 \r
486 /*\r
487 ****************************************************************************************************\r
488 *                 Function to set W3100A IP\r
489 *\r
490 * Description:\r
491 * Arguments  : addr--> Pointer that has Source IP to be set\r
492 * Returns    : None.\r
493 * Note       :\r
494 ****************************************************************************************************\r
495 */\r
496 void setIP(u_char * addr)\r
497 {\r
498 u_char i;\r
499 u_char far* src_ptr = SRC_IP_PTR;   // We can only convert to 'regular'\r
500                                    // pointer if we're confident arithmetic\r
501                                    // won't take us out of current window.\r
502 \r
503 for (i = 0; i < 4; i++)\r
504   {\r
505   WRITE_VALUE(src_ptr + SA_OFFSET(i), addr[i]);\r
506   }\r
507 }\r
508 \r
509 // DEBUG\r
510 void getIP(u_char* addr)\r
511 {\r
512 u_char i;\r
513 u_char far* src_ptr = SRC_IP_PTR;   // We can only convert to 'regular'\r
514                                    // pointer if we're confident arithmetic\r
515                                    // won't take us out of current window.\r
516 \r
517 for (i = 0; i < 4; i++)\r
518         addr[i] = READ_VALUE(src_ptr + SA_OFFSET(i));\r
519 }\r
520 \r
521 \r
522 /*\r
523 ****************************************************************************************************\r
524 *                Function to set MAC\r
525 *\r
526 * Description:\r
527 * Arguments  : addr--> Pointer that has MAC to be set\r
528 * Returns    : None.\r
529 * Note       :\r
530 ****************************************************************************************************\r
531 */\r
532 void setMACAddr(u_char * addr)\r
533 {\r
534 u_char i;\r
535 u_char far* ha_ptr = SRC_HA_PTR;   // We can only convert to 'regular'\r
536                                    // pointer if we're confident arithmetic\r
537                                    // won't take us out of current window.\r
538 \r
539 for (i = 0; i < 6; i++)\r
540   {\r
541   WRITE_VALUE(ha_ptr + SA_OFFSET(i), addr[i]);\r
542   }\r
543 }\r
544 \r
545 /*\r
546 ****************************************************************************************************\r
547 *                  Function to set TCP timeout\r
548 *\r
549 * Description: The function that used to adjust time to resend TCP\r
550 * Arguments  : val      --> Pointer that has the value to be set\r
551 *                                       Upper 2 byte:Initial timeout value\r
552 *                                       Last 1 byte:The count to retry till timeout\r
553 * Returns    : None.\r
554 * Note       :\r
555 ****************************************************************************************************\r
556 */\r
557 void settimeout(u_char * val)\r
558 {\r
559 u_char i;\r
560 u_char far* tout_ptr = TIMEOUT_PTR;   // We can only convert to 'regular'\r
561                                    // pointer if we're confident arithmetic\r
562                                    // won't take us out of current window.\r
563 \r
564 for (i = 0; i < 3; i++)\r
565   {\r
566   WRITE_VALUE(tout_ptr + SA_OFFSET(i), val[i]);\r
567   }\r
568 }\r
569 \r
570 /*\r
571 ****************************************************************************************************\r
572 *                 Function to set interrupt mask.\r
573 *\r
574 * Description:\r
575 * Arguments  : mask--> Mask value to be set ('1'-> interrupt )\r
576 * Returns    : None.\r
577 * Note       :\r
578 ****************************************************************************************************\r
579 */\r
580 void setINTMask(u_char mask)\r
581 {\r
582 WRITE_VALUE(INTMASK, mask);\r
583 }\r
584 \r
585 /*\r
586 ****************************************************************************************************\r
587 *                  Function to set enable in sending and receiving of broadcast data\r
588 *\r
589 * Description:  Enable to process of broadcating data in UDP or IP RAW mode.\r
590 * Arguments  : s        --> Channel No. to be set\r
591 * Returns    : None.\r
592 * Note       :\r
593 ****************************************************************************************************\r
594 */\r
595 void setbroadcast(SOCKET s)\r
596 {\r
597 u_char val = READ_VALUE(OPT_PROTOCOL(s));\r
598 WRITE_VALUE(OPT_PROTOCOL(s), val | SOCKOPT_BROADCAST);\r
599 }\r
600 \r
601 /*\r
602 ****************************************************************************************************\r
603 *                Function to set process protocol  in IP RAW mode.\r
604 *\r
605 * Description:\r
606 * Arguments  : s--> Channel No. to be set\r
607 *               tos-->Protocol Value to be set\r
608 * Returns    : None.\r
609 * Note       :\r
610 ****************************************************************************************************\r
611 */\r
612 void setTOS(SOCKET s, u_char tos)\r
613 {\r
614 WRITE_VALUE(TOS(s), tos);\r
615 }\r
616 \r
617 /*\r
618 ****************************************************************************************************\r
619 *               Upper layer protocol setup function in IP RAW Mode\r
620 *\r
621 * Description : Upper layer protocol setup function in protocol field of IP header when\r
622 *                    developing upper layer protocol like ICMP, IGMP, EGP etc. by using IP Protocol\r
623 * Arguments   : s          - Channel number\r
624 *               ipprotocol - Upper layer protocol setting value of IP Protocol\r
625 *                            (Possible to use designated IPPROTO_ in header file)\r
626 * Returns     : None\r
627 * Note        : API Function\r
628 *                  This function should be called before calling socket() that is, before\r
629 *                  socket initialization.\r
630 ****************************************************************************************************\r
631 */\r
632 void setIPprotocol(SOCKET s, u_char ipprotocol)\r
633 {\r
634 WRITE_VALUE(IP_PROTOCOL(s), ipprotocol);\r
635 }\r
636 \r
637 /*\r
638 ****************************************************************************************************\r
639 *              Initialization function to appropriate channel\r
640 *\r
641 * Description : Initialize designated channel and wait until W3100 has done.\r
642 * Arguments   : s - channel number\r
643 *               protocol - designate protocol for channel\r
644 *                          SOCK_STREAM(0x01) -> TCP.\r
645 *                          SOCK_DGRAM(0x02)  -> UDP.\r
646 *                          SOCK_IPL_RAW(0x03) -> IP LAYER RAW.\r
647 *                          SOCK_MACL_RAW(0x04) -> MAC LAYER RAW.\r
648 *               port     - designate source port for appropriate channel\r
649 *               flag     - designate option to be used in appropriate.\r
650 *                          SOCKOPT_BROADCAST(0x80) -> Send/receive broadcast message in UDP\r
651 *                          SOCKOPT_NDTIMEOUT(0x40) -> Use register value which designated TIMEOUT\r
652 *                            value\r
653 *                          SOCKOPT_NDACK(0x20)     -> When not using no delayed ack\r
654 *                          SOCKOPT_SWS(0x10)       -> When not using silly window syndrome\r
655 * Returns     : When succeeded : Channel number, failed :-1\r
656 * Note        : API Function\r
657 ****************************************************************************************************\r
658 */\r
659 char socket(SOCKET s, u_char protocol, u_int port, u_char flag)\r
660 {\r
661 u_char k;\r
662 \r
663 //Designate socket protocol and option\r
664 WRITE_VALUE(OPT_PROTOCOL(s), protocol | flag);\r
665 \r
666 // setup designated port number\r
667 if (port != 0)\r
668   {\r
669   k = (u_char)((port & 0xff00) >> 8);\r
670   WRITE_VALUE(SRC_PORT_PTR(s), k);\r
671   k = (u_char)(port & 0x00ff);\r
672   WRITE_VALUE(SRC_PORT_PTR(s) + SA_OFFSET(1), k);\r
673   }\r
674 else\r
675   {\r
676   // Designate random port number which is managed by local when you didn't designate source port\r
677   Local_Port++;\r
678 \r
679   WRITE_VALUE(SRC_PORT_PTR(s), (u_char)((Local_Port & 0xff00) >> 8));\r
680   WRITE_VALUE(SRC_PORT_PTR(s) + SA_OFFSET(1), (u_char)(Local_Port & 0x00ff));\r
681   }\r
682 \r
683 // SOCK_INIT\r
684 I_STATUS[s] = 0;\r
685 WRITE_VALUE(COMMAND(s), CSOCK_INIT);\r
686 \r
687 // Waiting Interrupt to CSOCK_INIT\r
688 while (I_STATUS[s] == 0)\r
689         I2CHIP_POLL_ISR(in4_isr_i2chip);\r
690 \r
691 if (!(I_STATUS[s] & SSOCK_INIT_OK))\r
692   return(-1);\r
693 \r
694 initseqnum(s);                                                  //  Use initial seq# with random number\r
695 \r
696 return(s);\r
697 }\r
698 \r
699 /*\r
700 ****************************************************************************************************\r
701 *               Connection establishing function to designated peer.\r
702 *\r
703 * Description : This function establish a connection to the peer by designated channel,\r
704 *     and wait until the connection is established successfully. (TCP client mode)\r
705 * Arguments   : s    - channel number\r
706 *               addr - destination IP Address\r
707 *               port - destination Port Number\r
708 * Returns     : when succeeded : 1, failed : -1\r
709 * Note        : API Function\r
710 ****************************************************************************************************\r
711 */\r
712 char connect(SOCKET s, u_char far * addr, u_int port)\r
713 {\r
714 \r
715 if (port != 0)\r
716   {                                             //designate destination port\r
717   WRITE_VALUE(DST_PORT_PTR(s), (u_char)((port & 0xff00) >> 8));\r
718   WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
719   }\r
720 else\r
721   return(-1);\r
722 \r
723   WRITE_VALUE(DST_IP_PTR(s), addr[0]);                          //designate destination IP address\r
724   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
725   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
726   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
727 \r
728 I_STATUS[s] = 0;\r
729 \r
730   WRITE_VALUE(COMMAND(s), CCONNECT);                                    // CONNECT\r
731   I2CHIP_POLL_ISR(in4_isr_i2chip);\r
732 \r
733 // Wait until connection is established successfully\r
734 while (I_STATUS[s] == 0)\r
735   {\r
736   // When failed, appropriate channel will be closed and return an error\r
737   if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
738     return -1;\r
739   }\r
740 \r
741 if (!(I_STATUS[s] & SESTABLISHED))\r
742   return(-1);\r
743 \r
744 return(1);\r
745 }\r
746 \r
747 /*\r
748 ****************************************************************************************************\r
749 *               Connection establishing function to designated peer. (Non-blocking Mode)\r
750 *\r
751 * Description : This function establish a connection to the peer by designated channel.\r
752 *\r
753 * Arguments   : s    - channel number\r
754 *               addr - destination IP Address\r
755 *               port - destination Port Number\r
756 * Returns     : when succeeded : 1, failed : -1\r
757 * Note        : API Function\r
758 ****************************************************************************************************\r
759 */\r
760 char NBconnect(SOCKET s, u_char far * addr, u_int port)\r
761 {\r
762 \r
763 if (port != 0)\r
764   {                                             //designate destination port\r
765         WRITE_VALUE(DST_PORT_PTR(s), (u_char) ((port & 0xff00) >> 8) );\r
766    WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
767   }\r
768 else\r
769   return(-1);\r
770 \r
771   WRITE_VALUE(DST_IP_PTR(s), addr[0]);                          //designate destination IP address\r
772   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
773   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
774   WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
775 \r
776 I_STATUS[s] = 0;\r
777 \r
778 WRITE_VALUE(COMMAND(s), CCONNECT);                                      // CONNECT\r
779 return(1);\r
780 }\r
781 \r
782 /*\r
783 ****************************************************************************************************\r
784 *            Waits for connection request from a peer (Blocking Mode)\r
785 *\r
786 * Description : Wait for connection request from a peer through designated channel (TCP Server mode)\r
787 * Arguments   : s    - channel number\r
788 *               addr - IP Address of the peer when a connection is established\r
789 *               port - Port number of the peer when a connection is established\r
790 * Returns     : When succeeded : 1, failed : -1\r
791 * Note        : API Function\r
792 ****************************************************************************************************\r
793 */\r
794 /*\r
795 char listen(SOCKET s, u_char far * addr, u_int far * port)\r
796 {\r
797 u_int i;\r
798 \r
799 I_STATUS[s] = 0;\r
800 \r
801 // LISTEN\r
802 COMMAND(s) = CLISTEN;\r
803 \r
804 // Wait until connection is established\r
805 while (I_STATUS[s] == 0)\r
806   {\r
807   // When failed to connect, the designated channel will be closed and return an error.\r
808   if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
809     return -1;\r
810   }\r
811 \r
812 // Receive IP address and port number of the peer connected\r
813 if (I_STATUS[s] & SESTABLISHED)\r
814   {\r
815   i = *DST_PORT_PTR(s);\r
816   *port = (u_int)((i & 0xff00) >> 8);\r
817   i = *(DST_PORT_PTR(s) + 2);\r
818   i = (u_int)(i & 0x00ff);\r
819   *port += (i << 8);\r
820 \r
821   addr[0] = *DST_IP_PTR(s);\r
822   addr[1] = *(DST_IP_PTR(s) + 2);\r
823   addr[2] = *(DST_IP_PTR(s) + 4);\r
824   addr[3] = *(DST_IP_PTR(s) + 6);\r
825   }\r
826 else\r
827   return(-1);\r
828 \r
829 return(1);\r
830 }\r
831 */\r
832 \r
833 /*\r
834 ****************************************************************************************************\r
835 *                Waits for connection request from a peer (Non-blocking Mode)\r
836 *\r
837 * Description : Wait for connection request from a peer through designated channel (TCP Server mode)\r
838 * Arguments   : s - channel number\r
839 * Returns     : None\r
840 * Note        : API Function\r
841 ****************************************************************************************************\r
842 */\r
843 char NBlisten(SOCKET s)\r
844 {\r
845 I_STATUS[s] = 0;\r
846 \r
847 // LISTEN\r
848 WRITE_VALUE(COMMAND(s), CLISTEN);\r
849 \r
850 return(1);\r
851 }\r
852 \r
853 /*\r
854 ****************************************************************************************************\r
855 *               Create random value for initial Seq# when establishing TCP connection\r
856 *\r
857 * Description : In this function, you can add some source codes to create random number for\r
858 *     initial Seq#. In real, TCP initial SEQ# should be random value.\r
859 *               (Currently, we're using static value in EVB/DK.)\r
860 * Arguments   : s - channel number\r
861 * Returns     : None\r
862 * Note        : API Function\r
863 ****************************************************************************************************\r
864 */\r
865 void initseqnum(SOCKET s)\r
866 {\r
867 // Designate initial seq#\r
868 // If you have random number generation function, assign random number instead of SEQ_NUM.lVal++.\r
869 SEQ_NUM.lVal++;\r
870 \r
871 //randomize();\r
872 //SEQ_NUM.lVal = rand();\r
873 \r
874 WRITE_VALUE(TX_WR_PTR(s), SEQ_NUM.cVal[0]);\r
875 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
876 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
877 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
878 delay0(2);\r
879 \r
880 WRITE_VALUE(TX_RD_PTR(s), SEQ_NUM.cVal[0]);\r
881 WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
882 WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
883 WRITE_VALUE(TX_RD_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
884 delay0(2);\r
885 \r
886 WRITE_VALUE(TX_ACK_PTR(s), SEQ_NUM.cVal[0]);\r
887 WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1), SEQ_NUM.cVal[1]);\r
888 WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2), SEQ_NUM.cVal[2]);\r
889 WRITE_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3), SEQ_NUM.cVal[3]);\r
890 delay0(2);\r
891 }\r
892 \r
893 /*\r
894 ****************************************************************************************************\r
895 *              Function for sending TCP data.\r
896 *\r
897 * Description : Function for sending TCP data and Composed of the send() and send_in() functions.\r
898 *     The send() function is an application I/F function.\r
899 *     It continues to call the send_in() function to complete the sending of the data up to the\r
900 *     size of the data to be sent when the application is called.\r
901 *     The send_in() function receives the return value (the size of the data sent), calculates\r
902 *     the size of the data to be sent, and calls the send_in() function again if there is any\r
903 *     data left to be sent.\r
904 * Arguments   : s   - channel number\r
905 *               buf - Pointer pointing data to send\r
906 *               len - data size to send\r
907 * Returns     : Succeed: sent data size, Failed:  -1;\r
908 * Note        : API Function\r
909 ****************************************************************************************************\r
910 */\r
911 int send(SOCKET s, u_char far * buf, u_int len)\r
912 {\r
913 int ptr, size;\r
914 u_char huge* huge_buf = (u_char huge*)buf;\r
915 u_char far*  local_buf = (u_char far*)huge_buf;    \r
916 \r
917 if (len <= 0)\r
918   return (0);\r
919 else\r
920   {\r
921   ptr = 0;\r
922   do\r
923     {\r
924          size = send_in(s, local_buf + ptr, len);\r
925          if (size == -1)\r
926       return -1;\r
927          len = len - size;\r
928          ptr += size;\r
929          } while ( len > 0);\r
930   }\r
931 return ptr;\r
932 }\r
933 \r
934 /*\r
935 ****************************************************************************************************\r
936 *              Internal function for sending TCP data.\r
937 *\r
938 * Description : Called by the send() function for TCP transmission.\r
939 *    It first calculates the free transmit buffer size\r
940 *    and compares it with the size of the data to be transmitted to determine the transmission size.\r
941 *    After calculating the data size, it copies data from TX_WR_PTR.\r
942 *    It waits if there is a previous send command in process.\r
943 *    When the send command is cleared, it updates the TX_WR_PTR up to the size to be transmitted\r
944      and performs the send command.\r
945 * Arguments   : s   - channel number\r
946 *               buf - Pointer pointing data to send\r
947 *               len - data size to send\r
948 * Returns     : Succeeded: sent data size, Failed: -1\r
949 * Note        : Internal Function\r
950 ****************************************************************************************************\r
951 */\r
952 int send_in(SOCKET s, u_char far * buf, u_int len)\r
953 {\r
954 u_char k;\r
955 u_int size;\r
956 union un_l2cval wr_ptr, ack_ptr;\r
957 unsigned int offset;\r
958 \r
959 S_START:\r
960 disable();            // CT: Shadow register access should not conflict with ISR.\r
961 k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
962 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
963 delay0(2);\r
964 wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
965 wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
966 wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
967 wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
968 \r
969 k = READ_VALUE(SHADOW_TXACK_PTR(s));\r
970 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
971 delay0(2);\r
972 ack_ptr.cVal[3] = READ_VALUE(TX_ACK_PTR(s));\r
973 ack_ptr.cVal[2] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1));\r
974 ack_ptr.cVal[1] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2));\r
975 ack_ptr.cVal[0] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3));\r
976 enable();\r
977 \r
978 // Suppress compiler errors that k is not used\r
979 k = k;\r
980 \r
981 //  Calculate send free buffer size\r
982 if (wr_ptr.lVal >= ack_ptr.lVal)\r
983   size = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));\r
984 else\r
985   size = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));\r
986 \r
987 // Recalulate after some delay because of error in pointer calculation\r
988 if (size > SSIZE[s])\r
989   {\r
990   if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
991     return -1;\r
992   delay_ms(1);\r
993          goto S_START;\r
994   }\r
995 \r
996 // Wait when previous sending has not finished yet and there's no free buffer\r
997 if (size == 0)\r
998   {\r
999   if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
1000     return -1;\r
1001 \r
1002   delay_ms(1);\r
1003   goto S_START;\r
1004   }\r
1005 else if (size < len)\r
1006   {\r
1007   len = size;\r
1008   }\r
1009 \r
1010 //  Calculate pointer to data copy\r
1011 offset = (UINT)(wr_ptr.lVal & SMASK[s]);\r
1012 \r
1013 // copy data\r
1014 write_data(s, buf, offset, len);\r
1015 \r
1016 while (READ_VALUE(COMMAND(s)) & CSEND)\r
1017   {\r
1018   // Confirm previous send command\r
1019   if (select(s, SEL_CONTROL) != SOCK_ESTABLISHED)\r
1020     return -1;\r
1021   }\r
1022 \r
1023 //  update tx_wr_ptr\r
1024 wr_ptr.lVal = wr_ptr.lVal + len;\r
1025 WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);\r
1026 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);\r
1027 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);\r
1028 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);\r
1029 \r
1030 delay0(1);\r
1031 \r
1032 // SEND\r
1033 WRITE_VALUE(COMMAND(s), CSEND);\r
1034 \r
1035 return(len);\r
1036 }\r
1037 \r
1038 /*\r
1039 ****************************************************************************************************\r
1040 *              TCP data receiving function.\r
1041 *\r
1042 * Description : This function is to clear out any received TCP data.\r
1043 * Arguments   : s   - channel number\r
1044 * Returns     : None\r
1045 * Note        : API Fcuntion\r
1046 ****************************************************************************************************\r
1047 */\r
1048 void recv_clear(SOCKET s)\r
1049 {\r
1050 u_char k;\r
1051 u_int size;\r
1052 union un_l2cval wr_ptr, rd_ptr;\r
1053 \r
1054 disable();\r
1055 k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
1056 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1057 delay0(2);\r
1058 wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
1059 wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
1060 wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
1061 wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
1062 \r
1063 k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
1064 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1065 delay0(2);\r
1066 rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
1067 rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
1068 rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
1069 rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
1070 enable();\r
1071 \r
1072 // Suppress compiler errors that k is not used\r
1073 k = k;\r
1074 \r
1075 //  calculate received data size\r
1076 if (wr_ptr.lVal >= rd_ptr.lVal)\r
1077   size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
1078 else\r
1079   size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
1080 \r
1081 // Update rx_rd_ptr\r
1082 rd_ptr.lVal += size;\r
1083 WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
1084 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
1085 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
1086 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
1087 \r
1088 // RECV\r
1089  WRITE_VALUE(COMMAND(s), CRECV);\r
1090 }\r
1091 \r
1092 /*\r
1093 ****************************************************************************************************\r
1094 *              TCP data receiving function.\r
1095 *\r
1096 * Description : This function is for receiving TCP data.\r
1097 *     The recv() function is an application I/F function. It will read up to len chars if there are\r
1098       enough characters in the buffer, otherwise will onl read the number of characters availiable\r
1099 * Arguments   : s   - channel number\r
1100 *               buf - Pointer where the data to be received is copied\r
1101 *               len - Size of the data to be received\r
1102 * Returns     : Succeeded: received data size, Failed: -1\r
1103 * Note        : API Fcuntion\r
1104 ****************************************************************************************************\r
1105 */\r
1106 int recv(SOCKET s, u_char far * buf, u_int len)\r
1107 {\r
1108 u_char k;\r
1109 u_int size;\r
1110 union un_l2cval wr_ptr, rd_ptr;\r
1111 unsigned int offset;\r
1112 \r
1113 // If out length is 0, then we do not need to do anything\r
1114 if (len <= 0)\r
1115   return (0);\r
1116 \r
1117 disable();\r
1118 k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
1119 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1120 delay0(2);\r
1121 wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
1122 wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
1123 wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
1124 wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
1125 \r
1126 k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
1127 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1128 delay0(2);\r
1129 rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
1130 rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
1131 rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
1132 rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
1133 enable();\r
1134 \r
1135 // Suppress compiler errors that k is not used\r
1136 k = k;\r
1137 \r
1138 //  calculate IIM7010A received data size\r
1139 if (wr_ptr.lVal == rd_ptr.lVal)\r
1140   return(0);\r
1141 else if (wr_ptr.lVal >= rd_ptr.lVal)\r
1142   size = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
1143 else\r
1144   size = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
1145 \r
1146 // Make sure we do not try to read more characters than what is availiable in the IIM7010 buffer\r
1147 if (size < len)\r
1148   len = size;\r
1149 \r
1150 // Calculate pointer to be copied received data\r
1151 offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
1152 \r
1153 // Copy received data\r
1154 size = read_data(s, offset, buf, len);\r
1155 \r
1156 // Update rx_rd_ptr\r
1157 rd_ptr.lVal += size;\r
1158 WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
1159 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
1160 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
1161 WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
1162 \r
1163 // RECV\r
1164  WRITE_VALUE(COMMAND(s), CRECV);\r
1165 return(size);\r
1166 }\r
1167 \r
1168 \r
1169 /*\r
1170 ****************************************************************************************************\r
1171 *               UDP data sending function.\r
1172 *\r
1173 * Description : Composed of the sendto()and sendto_in() functions.\r
1174 *    The send() function is an application I/F function.\r
1175 *    It continues to call the send_in() function to complete the sending of the data up to the\r
1176 *    size of the data to be sent\r
1177 *    when the application is called.Unlike TCP transmission, it designates the destination address\r
1178 *    and the port.\r
1179 * Arguments   : s    - channel port\r
1180 *               buf  - Pointer pointing data to send\r
1181 *               len  - data size to send\r
1182 *               addr - destination IP address to send data\r
1183 *               port - destination port number to send data\r
1184 * Returns     : Sent data size\r
1185 * Note        : API Function\r
1186 ****************************************************************************************************\r
1187 */\r
1188 u_int sendto(SOCKET s, u_char far * buf, u_int len, u_char * addr, u_int port)\r
1189 {\r
1190 //char val;\r
1191 u_int ptr, size;\r
1192 \r
1193 // Wait until previous send commnad has completed.\r
1194 while(READ_VALUE(COMMAND(s)) & CSEND)\r
1195   {\r
1196   if(select(s, SEL_CONTROL) == SOCK_CLOSED)\r
1197     return -1;  // Error.\r
1198   }\r
1199 \r
1200 // Designate destination port number.\r
1201 if (port != 0)\r
1202   {\r
1203   WRITE_VALUE(DST_PORT_PTR(s), (u_char)((port & 0xff00) >> 8));\r
1204   WRITE_VALUE(DST_PORT_PTR(s) + SA_OFFSET(1), (u_char)(port & 0x00ff));\r
1205   }\r
1206 \r
1207 //  Designate destination IP address\r
1208 WRITE_VALUE(DST_IP_PTR(s), addr[0]);\r
1209 WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(1), addr[1]);\r
1210 WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(2), addr[2]);\r
1211 WRITE_VALUE(DST_IP_PTR(s) + SA_OFFSET(3), addr[3]);\r
1212 \r
1213 if (len <= 0)\r
1214   return (0);\r
1215 else\r
1216   {\r
1217   ptr = 0;\r
1218   do\r
1219     {\r
1220          size = sendto_in(s, buf + ptr, len);\r
1221          len = len - size;\r
1222          ptr += size;\r
1223          } while ( len > 0);\r
1224   }\r
1225 return ptr;\r
1226 }\r
1227 \r
1228 /*\r
1229 ****************************************************************************************************\r
1230 *            UDP data sending function.\r
1231 *\r
1232 * Description : An internal function that is the same as the send_in() function of the TCP.\r
1233 * Arguments   : s   - Channel number\r
1234 *               buf - Pointer indicating the data to send\r
1235 *               len - data size to send\r
1236 * Returns     : Sent data size\r
1237 * Note        : Internal Function\r
1238 ****************************************************************************************************\r
1239 */\r
1240 u_int sendto_in(SOCKET s, u_char far * buf, u_int len)\r
1241 {\r
1242 u_char k;\r
1243 u_int size;\r
1244 union un_l2cval wr_ptr, rd_ptr;\r
1245 unsigned int offset;\r
1246 \r
1247 S2_START:\r
1248 disable();\r
1249 k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
1250 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1251 delay0(2);\r
1252 wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
1253 wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
1254 wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
1255 wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
1256 \r
1257 k = READ_VALUE(SHADOW_TXRD_PTR(s));\r
1258 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1259 delay0(2);\r
1260 rd_ptr.cVal[3] = READ_VALUE(TX_RD_PTR(s));\r
1261 rd_ptr.cVal[2] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(1));\r
1262 rd_ptr.cVal[1] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(2));\r
1263 rd_ptr.cVal[0] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(3));\r
1264 enable();\r
1265 \r
1266 // Suppress compiler errors that k is not used\r
1267 k = k;\r
1268 \r
1269 //  Calculate free buffer size to send\r
1270 if (wr_ptr.lVal >= rd_ptr.lVal)\r
1271   size = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));\r
1272 else\r
1273   size = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));\r
1274 \r
1275 //  Recalulate after some delay because of error in pointer caluation\r
1276 if (size > SSIZE[s])\r
1277   {\r
1278   delay_ms(1);\r
1279   goto S2_START;\r
1280   }\r
1281 \r
1282 // Wait when previous sending has not finished yet and there's no free buffer\r
1283 if (size == 0)\r
1284   {\r
1285   delay_ms(1);\r
1286   goto S2_START;\r
1287 \r
1288   }\r
1289 else if (size < len)\r
1290   {\r
1291   len = size;\r
1292   }\r
1293 \r
1294 // Calculate pointer to copy data pointer\r
1295 offset =(UINT)(wr_ptr.lVal & SMASK[s]);\r
1296 \r
1297 // copy data\r
1298 write_data(s, buf, offset, len);\r
1299 \r
1300 // Confirm previous send command\r
1301 while (READ_VALUE(COMMAND(s)) & CSEND)\r
1302   {\r
1303   if(select(s, SEL_CONTROL)==SOCK_CLOSED)\r
1304     return -1;                  // Error\r
1305   }\r
1306 \r
1307 // update tx_wr_ptr\r
1308 wr_ptr.lVal = wr_ptr.lVal + len;\r
1309 WRITE_VALUE(TX_WR_PTR(s), wr_ptr.cVal[3]);\r
1310 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(1), wr_ptr.cVal[2]);\r
1311 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(2), wr_ptr.cVal[1]);\r
1312 WRITE_VALUE(TX_WR_PTR(s) + SA_OFFSET(3), wr_ptr.cVal[0]);\r
1313 \r
1314 delay0(1);\r
1315 \r
1316 // SEND\r
1317 WRITE_VALUE(COMMAND(s), CSEND);\r
1318 \r
1319 return(len);\r
1320 }\r
1321 \r
1322 /*\r
1323 ****************************************************************************************************\r
1324 *             UDP data receiving function.\r
1325 *\r
1326 * Description : Function for receiving UDP and IP layer RAW mode data, and handling the data header.\r
1327 * Arguments   : s    - channel number\r
1328 *               buf  - Pointer where the data to be received is copied\r
1329 *               len  - Size of the data to be received\r
1330 *               addr - Peer IP address for receiving\r
1331 *               port - Peer port number for receiving\r
1332 * Returns     : Received data size\r
1333 * Note        : API Function\r
1334 ****************************************************************************************************\r
1335 */\r
1336 u_int recvfrom(SOCKET s, u_char far *buf, u_int len, u_char *addr, u_int *port)\r
1337 {\r
1338 struct _UDPHeader                                                                       // When receiving UDP data, header added by W3100A\r
1339   {\r
1340   union\r
1341          {\r
1342          struct\r
1343                 {\r
1344                 u_int size;\r
1345                 u_char addr[4];\r
1346                 u_int port;\r
1347                 } header;\r
1348          u_char stream[8];\r
1349     } u;\r
1350   } UDPHeader;\r
1351 \r
1352 u_int ret;\r
1353 union un_l2cval wr_ptr, rd_ptr;\r
1354 u_long size;\r
1355 u_char k;\r
1356 unsigned int offset;\r
1357 \r
1358 if(select(s,SEL_CONTROL)==SOCK_CLOSED)\r
1359   return -1;\r
1360 \r
1361 disable();\r
1362 k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
1363 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1364 delay0(2);\r
1365 wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
1366 wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
1367 wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
1368 wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
1369 \r
1370 k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
1371 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1372 delay0(2);\r
1373 rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
1374 rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
1375 rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
1376 rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
1377 enable();\r
1378 \r
1379 // Suppress compiler errors that k is not used\r
1380 k = k;\r
1381 \r
1382 // Calculate received data size\r
1383 if (len <= 0)\r
1384   return (0);\r
1385 else if (wr_ptr.lVal >= rd_ptr.lVal)\r
1386   size = wr_ptr.lVal - rd_ptr.lVal;\r
1387 else\r
1388   size = 0 - rd_ptr.lVal + wr_ptr.lVal;\r
1389 \r
1390 if (size == 0)\r
1391   return 0;\r
1392 \r
1393   // Calulate received data pointer\r
1394 offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
1395 \r
1396 // When UDP data\r
1397 if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_DGRAM)\r
1398   {\r
1399   // Copy W3100A UDP header\r
1400   read_data(s, offset, UDPHeader.u.stream, 8);\r
1401 \r
1402   // Read UDP Packet size\r
1403   size = UDPHeader.u.stream[0];\r
1404   size = (size << 8) + UDPHeader.u.stream[1];\r
1405 \r
1406   // Read IP address of the peer\r
1407   addr[0] = UDPHeader.u.header.addr[0];\r
1408   addr[1] = UDPHeader.u.header.addr[1];\r
1409   addr[2] = UDPHeader.u.header.addr[2];\r
1410   addr[3] = UDPHeader.u.header.addr[3];\r
1411 \r
1412   // Read Port number of the peer\r
1413   *port = UDPHeader.u.stream[6];\r
1414   *port = (*port << 8) + UDPHeader.u.stream[7];\r
1415 \r
1416   // Increase read pointer by 8, because already read as UDP header size\r
1417   rd_ptr.lVal += 8;\r
1418 \r
1419   // Calculate UDP data copy pointer\r
1420   offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
1421 \r
1422   // Calculate data size of current UDP Packet from UDP header\r
1423   size = size - 8;\r
1424 \r
1425   // Copy one UDP data packet to user-specific buffer\r
1426   ret = read_data(s, offset, buf, (u_int)size);\r
1427 \r
1428   // Increase read pointer by UDP packet data size\r
1429   rd_ptr.lVal += ret;\r
1430   }\r
1431 else if ((READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_IPL_RAW)   // When IP layer RAW mode data\r
1432   {\r
1433   // Copy W3100A IP Raw header\r
1434   read_data(s, offset, UDPHeader.u.stream, 6);\r
1435 \r
1436   // Read IP layer RAW Packet size\r
1437   size = UDPHeader.u.stream[0];\r
1438   size = (size << 8) + UDPHeader.u.stream[1];\r
1439 \r
1440   // Read IP address of the peer\r
1441   addr[0] = UDPHeader.u.header.addr[0];\r
1442   addr[1] = UDPHeader.u.header.addr[1];\r
1443   addr[2] = UDPHeader.u.header.addr[2];\r
1444   addr[3] = UDPHeader.u.header.addr[3];\r
1445 \r
1446   // Increase read pointer by 6, because already read as IP RAW header size\r
1447   rd_ptr.lVal += 6;\r
1448 \r
1449   // Calculate IP layer raw mode data pointer\r
1450   offset = ((UINT)(rd_ptr.lVal & RMASK[s]));\r
1451 \r
1452   // Copy one IP Raw data packet to user-specific buffer\r
1453   ret = read_data(s, offset, buf, (u_int)size);\r
1454   rd_ptr.lVal = rd_ptr.lVal + (ret - 4);\r
1455   }\r
1456 \r
1457   // Update rx_rd_ptr\r
1458   WRITE_VALUE(RX_RD_PTR(s), rd_ptr.cVal[3]);\r
1459   WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(1), rd_ptr.cVal[2]);\r
1460   WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(2), rd_ptr.cVal[1]);\r
1461   WRITE_VALUE(RX_RD_PTR(s) + SA_OFFSET(3), rd_ptr.cVal[0]);\r
1462 \r
1463   // RECV\r
1464   WRITE_VALUE(COMMAND(s), CRECV);\r
1465 \r
1466 // Real received size return\r
1467 return(ret);\r
1468 }\r
1469 \r
1470 /*\r
1471 ****************************************************************************************************\r
1472 *              Channel closing function.\r
1473 *\r
1474 * Description : Function for closing the connection of the designated channel.\r
1475 * Arguments   : s - channel number\r
1476 * Returns     : None\r
1477 * Note        : API Function\r
1478 ****************************************************************************************************\r
1479 */\r
1480 void close(SOCKET s)\r
1481 {\r
1482 u_int len;\r
1483 short sAttempts = 0;\r
1484 \r
1485 I_STATUS[s] = 0;\r
1486 \r
1487 if (select(s, SEL_CONTROL) == SOCK_CLOSED)\r
1488   return;          // Already closed\r
1489 \r
1490 // When closing, if there's data which have not processed, Insert some source codes to handle this\r
1491 // Or before application call close(), handle those data first and call close() later.\r
1492 \r
1493 len = select(s, SEL_SEND);\r
1494 if (len == SSIZE[s])\r
1495   {\r
1496   // CLOSE\r
1497   WRITE_VALUE(COMMAND(s), CCLOSE);\r
1498   // TODO: The 'SCLOSED' status value is only set briefly as part of the close,\r
1499   // and will otherwise quickly return to normal.  That means your code might\r
1500   // become 'stuck' at this point even if the packet has closed normally.\r
1501   // Rather than a while() call, it might be preferred to time out on this\r
1502   // close check and return to the application after some time.\r
1503   while(!(I_STATUS[s] & SCLOSED))\r
1504   {\r
1505           sAttempts++;\r
1506       if( sAttempts > 10 )\r
1507       {\r
1508         break;\r
1509       }\r
1510           I2CHIP_POLL_ISR(in4_isr_i2chip);\r
1511   }\r
1512   }\r
1513 }\r
1514 \r
1515 u_char tx_empty(SOCKET s)\r
1516 {\r
1517         return (select(s, SEL_SEND) == SSIZE[s]);\r
1518 }\r
1519 \r
1520 /*\r
1521 ****************************************************************************************************\r
1522 *              Channel closing function.\r
1523 *\r
1524 * Description : Function for closing the connection of the designated channel.\r
1525 * Arguments   : s - channel number\r
1526 * Returns     : None\r
1527 * Note        : API Function\r
1528 ****************************************************************************************************\r
1529 */\r
1530 char reset_sock(SOCKET s)\r
1531 {\r
1532 u_char c;\r
1533 \r
1534 c = 1 << s;\r
1535 \r
1536 // RESET\r
1537 WRITE_VALUE(RESETSOCK, c);\r
1538 return  (1);\r
1539 }\r
1540 \r
1541 /*\r
1542 ****************************************************************************************************\r
1543 *             Function handling the channel socket information.\r
1544 *\r
1545 * Description : Return socket information of designated channel\r
1546 * Arguments   : s    - channel number\r
1547 *               func - SEL_CONTROL(0x00) -> return socket status\r
1548 *                      SEL_SEND(0x01)    -> return free transmit buffer size\r
1549 *                      SEL_RECV(0x02)    -> return received data size\r
1550 * Returns     : socket status or free transmit buffer size or received data size\r
1551 * Note        : API Function\r
1552 ****************************************************************************************************\r
1553 */\r
1554 u_int select(SOCKET s, u_char func)\r
1555 {\r
1556 u_int val;\r
1557 union un_l2cval rd_ptr, wr_ptr, ack_ptr;\r
1558 u_char k;\r
1559 \r
1560 switch (func)\r
1561   {\r
1562   // socket status information\r
1563   case SEL_CONTROL :\r
1564          val = READ_VALUE(SOCK_STATUS(s));\r
1565          break;\r
1566 \r
1567   // Calculate send free buffer size\r
1568   case SEL_SEND :\r
1569          disable();\r
1570          k = READ_VALUE(SHADOW_TXWR_PTR(s));\r
1571          WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1572          delay0(2);\r
1573          wr_ptr.cVal[3] = READ_VALUE(TX_WR_PTR(s));\r
1574          wr_ptr.cVal[2] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(1));\r
1575          wr_ptr.cVal[1] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(2));\r
1576          wr_ptr.cVal[0] = READ_VALUE(TX_WR_PTR(s) + SA_OFFSET(3));\r
1577 \r
1578          if (( READ_VALUE(OPT_PROTOCOL(s)) & 0x07) == SOCK_STREAM)      // TCP\r
1579                 {\r
1580                 k = READ_VALUE(SHADOW_TXACK_PTR(s));\r
1581                 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1582                 delay0(2);\r
1583                 ack_ptr.cVal[3] = READ_VALUE(TX_ACK_PTR(s));\r
1584                 ack_ptr.cVal[2] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(1));\r
1585                 ack_ptr.cVal[1] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(2));\r
1586                 ack_ptr.cVal[0] = READ_VALUE(TX_ACK_PTR(s) + SA_OFFSET(3));\r
1587                 enable();\r
1588 \r
1589                 if (wr_ptr.lVal >= ack_ptr.lVal)\r
1590         val = (u_int)(SSIZE[s] - (wr_ptr.lVal - ack_ptr.lVal));\r
1591                 else\r
1592         val = (u_int)(SSIZE[s] - (0 - ack_ptr.lVal + wr_ptr.lVal));\r
1593                 }\r
1594          else                                                                                   // UDP, IP RAW ... (except TCP)\r
1595                 {\r
1596                 k = READ_VALUE(SHADOW_TXRD_PTR(s));\r
1597                 WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1598                 delay0(2);\r
1599                 rd_ptr.cVal[3] = READ_VALUE(TX_RD_PTR(s));\r
1600                 rd_ptr.cVal[2] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(1));\r
1601                 rd_ptr.cVal[1] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(2));\r
1602                 rd_ptr.cVal[0] = READ_VALUE(TX_RD_PTR(s) + SA_OFFSET(3));\r
1603                 enable();\r
1604 \r
1605                 if (wr_ptr.lVal >= rd_ptr.lVal)\r
1606         val = (u_int)(SSIZE[s] - (wr_ptr.lVal - rd_ptr.lVal));\r
1607                 else\r
1608         val = (u_int)(SSIZE[s] - (0 - rd_ptr.lVal + wr_ptr.lVal));\r
1609                 }\r
1610          break;\r
1611 \r
1612   //  Calculate received data size\r
1613   case SEL_RECV :\r
1614          disable();\r
1615          k = READ_VALUE(SHADOW_RXWR_PTR(s));\r
1616          WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1617          delay0(2);\r
1618          wr_ptr.cVal[3] = READ_VALUE(RX_WR_PTR(s));\r
1619          wr_ptr.cVal[2] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(1));\r
1620          wr_ptr.cVal[1] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(2));\r
1621          wr_ptr.cVal[0] = READ_VALUE(RX_WR_PTR(s) + SA_OFFSET(3));\r
1622 \r
1623          k = READ_VALUE(SHADOW_RXRD_PTR(s));\r
1624     WINDOW_RESTORE_BASE;  // Needed whenever we touch a shadow ptr; different window.\r
1625          delay0(2);\r
1626          rd_ptr.cVal[3] = READ_VALUE(RX_RD_PTR(s));\r
1627          rd_ptr.cVal[2] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(1));\r
1628          rd_ptr.cVal[1] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(2));\r
1629          rd_ptr.cVal[0] = READ_VALUE(RX_RD_PTR(s) + SA_OFFSET(3));\r
1630          enable();\r
1631 \r
1632          if (wr_ptr.lVal == rd_ptr.lVal)\r
1633       val = 0;\r
1634          else if (wr_ptr.lVal > rd_ptr.lVal)\r
1635       val = (u_int)(wr_ptr.lVal - rd_ptr.lVal);\r
1636          else\r
1637       val = (u_int)(0 - rd_ptr.lVal + wr_ptr.lVal);\r
1638          break;\r
1639 \r
1640   default :\r
1641          val = -1;\r
1642          break;\r
1643   }\r
1644 // Suppress compiler errors that k is not used\r
1645 k = k;\r
1646 return(val);\r
1647 }\r
1648 \r
1649 //\r
1650 //      unsigned char dma_read_i2chip (unsigned int i2_segm, unsigned int i2_offs,\r
1651 //      unsigned int cnt, unsigned int des_segm, unsigned int des_offs);\r
1652 //      Using DMA0 to read data from i2chip buffer into destination SRAM.\r
1653 //      where:\r
1654 //              unsigned int cnt = number of sectors, 512-byte per sector\r
1655 //              unsigned int des_segm = segment of destination SRAM data memory\r
1656 //              unsigned int des_offs = offset of destination SRAM data memory\r
1657 //              unsigned int i2_segm = segment of i2chip buffer mapped in memory\r
1658 //              unsigned int i2_offs = offset of i2chip buffer mapped in memory\r
1659 //       return DMA counter value\r
1660 //\r
1661 unsigned int dma_read_i2chip(u_char far* i2_src, u_char far* des, u_int cnt)\r
1662 {\r
1663         u_int des_segm, des_offs;\r
1664    u_int i2_segm, i2_offs;\r
1665    u_long temp;\r
1666 \r
1667    temp = ((long)FP_SEG(des) << 4) + ((long)FP_OFF(des));\r
1668    des_segm = (u_int)(temp >> 16);\r
1669    des_offs = (u_int)(temp & 0xffff);\r
1670 \r
1671    temp = ((long)FP_SEG(i2_src) << 4) + ((long)FP_OFF(i2_src));\r
1672    i2_segm = (u_int)(temp >> 16);\r
1673    i2_offs = (u_int)(temp & 0xffff);\r
1674 \r
1675         outport(0xffc6, des_segm);   /* D0DSTH destination SRAM segment */\r
1676         outport(0xffc4, des_offs);   /* D0DSTL destination SRAM offset */\r
1677         outport(0xffc2, i2_segm);   /* D0SRCH=SP0RD */\r
1678         outport(0xffc0, i2_offs);   /* D0SRCL=SP0RD */\r
1679         outport(0xffc8, cnt);   // D0TC counter\r
1680         outport(0xfff8,0x0504); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
1681 // DMA0 mem-mem, 16-bit, unsync, Start moving data line below\r
1682         outport(0xffca, 0xb60e);   /* D0CON 1011 0110 0000 1111 */\r
1683 //      outport(0xffca, 0xb42e);         // 1011 0100 0010 1110\r
1684         while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */\r
1685         outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
1686 return( inport(0xffc8) ); // counter\r
1687 }\r
1688 \r
1689 //\r
1690 //      unsigned int dma_write_i2chip (unsigned int src_segm, unsigned int src_offs,\r
1691 //      unsigned int cnt, unsigned int i2_segm, unsigned int i2_offs);\r
1692 //      Using DMA0 to write data from memory into i2chip.\r
1693 //      where:\r
1694 //              unsigned int cnt = number of 16-bit DMA transfers\r
1695 //              unsigned int src_segm = segment of the source SRAM data memory\r
1696 //              unsigned int src_offs = offset of the source SRAM data memory\r
1697 //              unsigned int i2_segm = segment of i2chip buffer mapped in memory\r
1698 //              unsigned int i2_offs = offset of i2chip buffer mapped in memory\r
1699 //       return DMA counter value\r
1700 //\r
1701 unsigned int dma_write_i2chip(u_char far* src, u_char far* i2_dest, u_int cnt)\r
1702 {\r
1703         u_int src_segm, src_offs;\r
1704    u_int i2_segm, i2_offs;\r
1705    u_long temp;\r
1706 \r
1707    temp = (FP_SEG(src) << 4) + (FP_OFF(src));\r
1708    src_segm = (u_int)(temp >> 4);\r
1709    src_offs = (u_int)(temp & 0xffff);\r
1710 \r
1711    temp = (FP_SEG(i2_dest) << 4) + (FP_OFF(i2_dest));\r
1712    i2_segm = (u_int)(temp >> 4);\r
1713    i2_offs = (u_int)(temp & 0xffff);\r
1714 \r
1715         outport(0xffc8, cnt);   // D0TC counter\r
1716         outport(0xffc6, i2_segm); // D0DSTH=i2chip buffer segment\r
1717         outport(0xffc4, i2_offs); // D0DSTL=i2chip buffer offset\r
1718         outport(0xffc2, src_segm);   /* D0SRCH=SP0RD */\r
1719         outport(0xffc0, src_offs);   /* D0SRCL=SP0RD */\r
1720 //      outport(0xfff8,0x050f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
1721 // DMA0 mem-mem, 16-bit, unsync, Start moving data line below\r
1722         outport(0xffca, 0xb60f);   /* D0CON 1011 0110 0000 1111 */\r
1723         while( inport(0xffc8) ); /* D0TC counter=0, DMA complete */\r
1724 //      outport(0xfff8,0x051f); // PLLCON, 0203=10M,050f=40M, 051f=80MHz\r
1725 \r
1726 return( inport(0xffc8) ); // counter\r
1727 }\r
1728 \r
1729 /*\r
1730 ****************************************************************************************************\r
1731 *              Copies the receive buffer data of the W3100A to the system buffer.\r
1732 *\r
1733 * Description : Copies the receive buffer data of the W3100A to the system buffer.\r
1734 *    It is called from the recv()or recvfrom() function.\r
1735 * Arguments   : s   - channel number\r
1736 *               src - receive buffer pointer of W3100A\r
1737 *               dst - system buffer pointer\r
1738 *               len - data size to copy\r
1739 * Returns     : copied data size\r
1740 * Note        : Internal Function\r
1741 ****************************************************************************************************\r
1742 */\r
1743 u_int read_data(SOCKET s, u_int offset, u_char far * dst, u_int len)\r
1744 {\r
1745         u_int i, size, size1;\r
1746    u_char far* src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,\r
1747                                         RBUFBASEADDRESS[s] + offset));\r
1748 //   src = (u_char far*)(MK_FP_WINDOW(RECV_DATA_BUF,\r
1749 //                                        0));\r
1750 \r
1751         if (len == 0)\r
1752    {\r
1753         WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
1754                 return 0;\r
1755    }\r
1756 \r
1757    if ((offset + len) > RSIZE[s])\r
1758    {\r
1759                 size = (u_int)(RSIZE[s] - offset);\r
1760 \r
1761                 if (size > TERN_RDMA_THRES)\r
1762                 {\r
1763                         dma_read_i2chip(src, dst, size);\r
1764                 }\r
1765                 else\r
1766       {\r
1767                         for (i = 0; i < size; i++)\r
1768                 {\r
1769                                 *dst++ = READ_VALUE(src);\r
1770             WINDOW_PTR_INC(src);\r
1771 \r
1772                         }\r
1773                 }\r
1774 \r
1775           size1 = len - size;\r
1776      src = (u_char far *)(MK_FP_WINDOW(RECV_DATA_BUF, (RBUFBASEADDRESS[s])));\r
1777 \r
1778      if (size1 > TERN_RDMA_THRES)\r
1779      {\r
1780                 dma_read_i2chip(src, dst, size);\r
1781           }\r
1782      else\r
1783           {\r
1784                         for (i = 0; i < size1; i++)\r
1785                 {\r
1786                                 *dst++ = READ_VALUE(src);\r
1787             WINDOW_PTR_INC(src);\r
1788                 }\r
1789                 }\r
1790         }\r
1791    else\r
1792    {\r
1793          if (len > TERN_RDMA_THRES)\r
1794     {\r
1795                 dma_read_i2chip(src, dst, size);\r
1796     }\r
1797     else\r
1798     {\r
1799                 for (i = 0; i < len; i++)\r
1800         {\r
1801                         *dst++ = READ_VALUE(src);\r
1802          WINDOW_PTR_INC(src);\r
1803                 }\r
1804     }\r
1805    }\r
1806    WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
1807         return len;\r
1808 }\r
1809 \r
1810 \r
1811 /*\r
1812 ****************************************************************************************************\r
1813 *              Copies the system buffer data to the transmit buffer of the W3100A.\r
1814 *\r
1815 * Description : Copies the system buffer data to the transmit buffer of the W3100A.\r
1816 *               It is called from the send_in()or sendto_in() function.\r
1817 * Arguments   : s   - channel number\r
1818 *               src - system buffer pointer\r
1819 *               dst - send buffer pointer of W3100A\r
1820 *               len - data size to copy\r
1821 * Returns     : copied data size\r
1822 * Note        : Internal Function\r
1823 ****************************************************************************************************\r
1824 */\r
1825 u_int write_data(SOCKET s, u_char far * src, u_int offset, u_int len)\r
1826 {\r
1827         u_int i, size, size1;\r
1828         u_char far* dst = (u_char far*)MK_FP_WINDOW(SEND_DATA_BUF,\r
1829                                   SBUFBASEADDRESS[s] + offset);\r
1830 \r
1831         if (len == 0)\r
1832    {\r
1833         WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
1834                 return 0;\r
1835    }\r
1836 \r
1837         if ((offset + len) > SSIZE[s])\r
1838    {\r
1839                 size = (u_int)(SSIZE[s] - offset);\r
1840 \r
1841                 for (i = 0; i < size; i++)\r
1842         {\r
1843                         WRITE_VALUE(dst, *src++);\r
1844          WINDOW_PTR_INC(dst);\r
1845                 }\r
1846 \r
1847                 size1 = len - size;\r
1848                 dst = (u_char far *)(MK_FP_WINDOW(SEND_DATA_BUF, (SBUFBASEADDRESS[s])));\r
1849 \r
1850                 for (i = 0; i < size1; i++)\r
1851         {\r
1852                         WRITE_VALUE(dst, *src++);\r
1853          WINDOW_PTR_INC(dst);\r
1854                 }\r
1855   }\r
1856   else\r
1857   {\r
1858         for (i = 0; i < len; i++)\r
1859         {\r
1860                         WRITE_VALUE(dst, *src++);\r
1861          WINDOW_PTR_INC(dst);\r
1862                 }\r
1863         }\r
1864    WINDOW_RESTORE_BASE;    // Needed whenever we do a call to MK_FP_WINDOW.\r
1865         return len;\r
1866 }\r
1867 \r
1868 \r
1869 \r