2 Copyright (c) 2010 jimmikaelkael <jimmikaelkael@wanadoo.fr>
3 Licenced under Academic Free License version 3.0
18 static g_param_t
*g_param
;
20 static u8 tcp_sndbuf
[1514] __attribute__((aligned(64))); // MTU
21 static u8 tcp_rcvbuf
[4096] __attribute__((aligned(64))); // MTU
22 static void *p_rcptbuf
;
23 static u16 rcptbuf_size
;
24 static int tcp_mutex
= -1;
25 static int tcp_listen
= 0;
35 static u32 next_seqnum
;
38 #define TIMEOUT (3000*1000)
39 iop_sys_clock_t timeout_sysclock
;
40 static int timeout_flag
= 0;
41 static int tcp_reply_flag
= 0;
43 static u16 tcp_port_src
= 8209;
45 //-------------------------------------------------------------------------
46 static unsigned int timer_intr_handler(void *args
)
49 iSignalSema(tcp_mutex
);
51 iSetAlarm(&timeout_sysclock
, timer_intr_handler
, NULL
);
53 return (unsigned int)args
;
56 //-------------------------------------------------------------------------
57 void tcp_init(g_param_t
*gparam
)
61 tcpip_pkt_t
*tcp_pkt
= (tcpip_pkt_t
*)tcp_sndbuf
;
63 // Initialize the static elements of our TCP packet
64 mips_memcpy(tcp_pkt
->eth
.addr_dst
, g_param
->eth_addr_dst
, 12); // hardware MAC addresses
65 tcp_pkt
->eth
.type
= 0x0008; // Network byte order: 0x800
66 tcp_pkt
->ip
.hlen
= 0x45; // IPv4
69 tcp_pkt
->ip
.flags
= 0x40; // Don't fragment
70 tcp_pkt
->ip
.frag_offset
= 0;
71 tcp_pkt
->ip
.ttl
= TTL
;
72 tcp_pkt
->ip
.proto
= IP_PROTO_TCP
;
73 mips_memcpy(&tcp_pkt
->ip
.addr_src
.addr
, &g_param
->ip_addr_src
, 4);
74 mips_memcpy(&tcp_pkt
->ip
.addr_dst
.addr
, &g_param
->ip_addr_dst
, 4);
75 tcp_pkt
->tcp_port_src
= IP_PORT(tcp_port_src
);
76 tcp_pkt
->tcp_port_dst
= g_param
->ip_port_dst
;
77 tcp_pkt
->tcp_wndsize
= htons(TCPWND_SIZE
);
80 tcp_mutex
= CreateMutex(IOP_MUTEX_LOCKED
);
82 USec2SysClock(TIMEOUT
, &timeout_sysclock
);
83 SetAlarm(&timeout_sysclock
, timer_intr_handler
, NULL
);
86 //-------------------------------------------------------------------------
87 int tcp_output(void *buf
, int size
, int hdata_flag
)
93 tcp_pkt
= (tcpip_pkt_t
*)tcp_sndbuf
;
94 pktsize
= size
+ sizeof(tcpip_pkt_t
);
96 tcp_pkt
->ip
.len
= htons(pktsize
- 14); // Subtract the ethernet header
99 tcp_pkt
->ip
.csum
= inet_chksum(&tcp_pkt
->ip
, 20); // Checksum the IP header (20 bytes)
101 CpuSuspendIntr(&oldstate
);
102 u32 seqno
= htona((u8
*)&seq_num
);
103 mips_memcpy(tcp_pkt
->tcp_seq_num
, &seqno
, 4);
104 u32 ackno
= htona((u8
*)&ack_num
);
105 mips_memcpy(tcp_pkt
->tcp_ack_num
, &ackno
, 4);
106 CpuResumeIntr(oldstate
);
108 tcp_pkt
->tcp_hdrlen
= (hdata_flag
? 20+size
: 20) << 2;
110 mips_memcpy(&tcp_sndbuf
[54], buf
, size
);
112 tcp_pkt
->tcp_flags
= TCP_FLAG
;
113 tcp_pkt
->tcp_csum
= 0;
114 tcp_pkt
->tcp_csum
= inet_chksum_pseudo(&tcp_sndbuf
[34], &g_param
->ip_addr_src
, &g_param
->ip_addr_dst
, 20+size
);
116 CpuSuspendIntr(&oldstate
);
117 next_seqnum
= seq_num
+ (TCP_FLAG
==SYN
? 1 : size
);
118 while (smap_xmit(tcp_pkt
, pktsize
) != 0);
119 CpuResumeIntr(oldstate
);
124 //-------------------------------------------------------------------------
125 int tcp_input(void *buf
, int size
) /// !!! Intr Context !!!
130 tcpip_pkt_t
*tcp_pkt
= (tcpip_pkt_t
*)buf
;
132 if (inet_chksum_pseudo(&tcp_pkt
->tcp_port_src
, &g_param
->ip_addr_dst
, &g_param
->ip_addr_src
, (ntohs(tcp_pkt
->ip
.len
)-20)) == 0) {// check TCP checksum
133 if (tcp_pkt
->tcp_flags
& ACK
) {
135 ackno
= ntoha(tcp_pkt
->tcp_ack_num
);
136 if (ackno
== next_seqnum
) {
137 // packet is aknowledged
138 if (ntoha(tcp_pkt
->tcp_seq_num
) == ack_num
-1)
139 tcp_send_ack(); // keep alive ack
141 int len
= ntohs(tcp_pkt
->ip
.len
) - 20 - (tcp_pkt
->tcp_hdrlen
>> 2);
143 ack_num
= ntoha(tcp_pkt
->tcp_seq_num
) + len
+ (tcp_pkt
->tcp_flags
& SYN
? 1 : 0);
144 if ((len
> 0) || (tcp_pkt
->tcp_flags
& SYN
)) {
145 // do input buffering
146 if (tcp_pkt
->tcp_flags
== (ACK
|PSH
))
151 iSignalSema(tcp_mutex
);
162 //-------------------------------------------------------------------------
163 void tcp_send(void *buf
, int size
, int hdata_flag
)
166 tcpip_pkt_t
*tcp_sndpkt
= (tcpip_pkt_t
*)tcp_sndbuf
;
170 // select a port and increment it for retries
171 tcp_sndpkt
->tcp_port_src
= IP_PORT(tcp_port_src
);
175 CpuSuspendIntr(&oldstate
);
178 CpuResumeIntr(oldstate
);
180 tcp_output(buf
, size
, hdata_flag
);
184 //while (QueryIntrContext())
185 // DelayThread(10000);
187 CpuSuspendIntr(&oldstate
);
190 if (tcp_reply_flag
== 0) { // It was a timeout ?
191 CpuResumeIntr(oldstate
);
192 goto send
; // yes, retry...
195 mips_memcpy(tcp_rcvbuf
, p_rcptbuf
, rcptbuf_size
);
196 CpuResumeIntr(oldstate
);
199 //-------------------------------------------------------------------------
200 void tcp_connect(void)
202 iop_sys_clock_t sysclock
;
208 GetSystemTime(&sysclock
);
209 seq_num
= sysclock
.lo
& 0xffff;
213 *((u16
*)&options
[0]) = 0x0402;
214 *((u16
*)&options
[2]) = htons(TCP_MSS
);
217 tcp_send(options
, sizeof(options
), 1);
224 //-------------------------------------------------------------------------
225 void tcp_send_ack(void)
228 tcp_output("\0", 0, 0);