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