Deleted Added
full compact
emac.c (161370) emac.c (163533)
1/*******************************************************************************
2 *
3 * Filename: emac.c
4 *
5 * Instantiation of routines for MAC/ethernet functions supporting tftp.
6 *
7 * Revision information:
8 *
9 * 28AUG2004 kb_admin initial creation
10 * 08JAN2005 kb_admin added tftp download
11 * also adapted from external sources
12 *
13 * BEGIN_KBDD_BLOCK
14 * No warranty, expressed or implied, is included with this software. It is
15 * provided "AS IS" and no warranty of any kind including statutory or aspects
16 * relating to merchantability or fitness for any purpose is provided. All
17 * intellectual property rights of others is maintained with the respective
18 * owners. This software is not copyrighted and is intended for reference
19 * only.
20 * END_BLOCK
21 *
1/*******************************************************************************
2 *
3 * Filename: emac.c
4 *
5 * Instantiation of routines for MAC/ethernet functions supporting tftp.
6 *
7 * Revision information:
8 *
9 * 28AUG2004 kb_admin initial creation
10 * 08JAN2005 kb_admin added tftp download
11 * also adapted from external sources
12 *
13 * BEGIN_KBDD_BLOCK
14 * No warranty, expressed or implied, is included with this software. It is
15 * provided "AS IS" and no warranty of any kind including statutory or aspects
16 * relating to merchantability or fitness for any purpose is provided. All
17 * intellectual property rights of others is maintained with the respective
18 * owners. This software is not copyrighted and is intended for reference
19 * only.
20 * END_BLOCK
21 *
22 * $FreeBSD: head/sys/boot/arm/at91/libat91/emac.c 161370 2006-08-16 23:39:58Z imp $
22 * $FreeBSD: head/sys/boot/arm/at91/libat91/emac.c 163533 2006-10-20 09:12:05Z imp $
23 ******************************************************************************/
24
25#include "at91rm9200.h"
26#include "at91rm9200_lowlevel.h"
27#include "emac.h"
28#include "lib.h"
29
30/* ****************************** GLOBALS *************************************/
31
32/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
33
23 ******************************************************************************/
24
25#include "at91rm9200.h"
26#include "at91rm9200_lowlevel.h"
27#include "emac.h"
28#include "lib.h"
29
30/* ****************************** GLOBALS *************************************/
31
32/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
33
34static char serverMACAddr[6];
34static receive_descriptor_t *p_rxBD;
35static unsigned short localPort;
36static unsigned short serverPort;
37static unsigned serverMACSet;
38static unsigned localIPSet, serverIPSet;
39static unsigned lastSize;
40static unsigned char serverMACAddr[6];
35static unsigned char localIPAddr[4], serverIPAddr[4];
36static int ackBlock;
37static char *dlAddress;
38
39static unsigned transmitBuffer[1024 / sizeof(unsigned)];
40static unsigned tftpSendPacket[256 / sizeof(unsigned)];
41
42/*
43 * .KB_C_FN_DEFINITION_START
44 * unsigned short IP_checksum(unsigned short *p, int len)
45 * This private function calculates the IP checksum for various headers.
46 * .KB_C_FN_DEFINITION_END
47 */
48static unsigned short
49IP_checksum(unsigned short *p, int len)
50{
51 unsigned i, t;
52
53 len &= ~1;
54
55 for (i=0,t=0; i<len; i+=2, ++p)
56 t += SWAP16(*p);
57
58 t = (t & 0xffff) + (t >> 16);
59 return (~t);
60}
61
62
63/*
64 * .KB_C_FN_DEFINITION_START
65 * void GetServerAddress(void)
66 * This private function sends an ARP request to determine the server MAC.
67 * .KB_C_FN_DEFINITION_END
68 */
69static void
70GetServerAddress(void)
71{
72 arp_header_t *p_ARP;
73
74 p_ARP = (arp_header_t*)transmitBuffer;
75
76 p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
77
41static unsigned char localIPAddr[4], serverIPAddr[4];
42static int ackBlock;
43static char *dlAddress;
44
45static unsigned transmitBuffer[1024 / sizeof(unsigned)];
46static unsigned tftpSendPacket[256 / sizeof(unsigned)];
47
48/*
49 * .KB_C_FN_DEFINITION_START
50 * unsigned short IP_checksum(unsigned short *p, int len)
51 * This private function calculates the IP checksum for various headers.
52 * .KB_C_FN_DEFINITION_END
53 */
54static unsigned short
55IP_checksum(unsigned short *p, int len)
56{
57 unsigned i, t;
58
59 len &= ~1;
60
61 for (i=0,t=0; i<len; i+=2, ++p)
62 t += SWAP16(*p);
63
64 t = (t & 0xffff) + (t >> 16);
65 return (~t);
66}
67
68
69/*
70 * .KB_C_FN_DEFINITION_START
71 * void GetServerAddress(void)
72 * This private function sends an ARP request to determine the server MAC.
73 * .KB_C_FN_DEFINITION_END
74 */
75static void
76GetServerAddress(void)
77{
78 arp_header_t *p_ARP;
79
80 p_ARP = (arp_header_t*)transmitBuffer;
81
82 p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
83
78 p_memcpy((char*)p_ARP->src_mac, (char*)localMACAddr, 6);
84 memcpy(p_ARP->src_mac, localMACAddr, 6);
79
80 p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
81 p_ARP->hard_type = SWAP16(1);
82 p_ARP->prot_type = SWAP16(PROTOCOL_IP);
83 p_ARP->hard_size = 6;
84 p_ARP->prot_size = 4;
85 p_ARP->operation = SWAP16(ARP_REQUEST);
86
85
86 p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
87 p_ARP->hard_type = SWAP16(1);
88 p_ARP->prot_type = SWAP16(PROTOCOL_IP);
89 p_ARP->hard_size = 6;
90 p_ARP->prot_size = 4;
91 p_ARP->operation = SWAP16(ARP_REQUEST);
92
87 p_memcpy((char*)p_ARP->sender_mac, (char*)localMACAddr, 6);
88
89 p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4);
90
93 memcpy(p_ARP->sender_mac, localMACAddr, 6);
94 memcpy(p_ARP->sender_ip, localIPAddr, 4);
91 p_memset((char*)p_ARP->target_mac, 0, 6);
95 p_memset((char*)p_ARP->target_mac, 0, 6);
96 memcpy(p_ARP->target_ip, serverIPAddr, 4);
92
97
93 p_memcpy((char*)p_ARP->target_ip, (char*)serverIPAddr, 4);
94
95 // wait until transmit is available
96 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
97
98 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
99 *AT91C_EMAC_TAR = (unsigned)transmitBuffer;
100 *AT91C_EMAC_TCR = 0x40;
101}
102
103
104/*
105 * .KB_C_FN_DEFINITION_START
106 * void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
107 * This private function initializes and send a TFTP packet.
108 * .KB_C_FN_DEFINITION_END
109 */
110static void
111Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
112{
113 transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
114 ip_header_t *ipHdr;
115 udp_header_t *udpHdr;
116 unsigned t_checksum;
117
98 // wait until transmit is available
99 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
100
101 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
102 *AT91C_EMAC_TAR = (unsigned)transmitBuffer;
103 *AT91C_EMAC_TCR = 0x40;
104}
105
106
107/*
108 * .KB_C_FN_DEFINITION_START
109 * void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
110 * This private function initializes and send a TFTP packet.
111 * .KB_C_FN_DEFINITION_END
112 */
113static void
114Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
115{
116 transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
117 ip_header_t *ipHdr;
118 udp_header_t *udpHdr;
119 unsigned t_checksum;
120
118 p_memcpy((char*)macHdr->dest_mac, (char*)serverMACAddr, 6);
119
120 p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6);
121
121 memcpy(macHdr->dest_mac, serverMACAddr, 6);
122 memcpy(macHdr->src_mac, localMACAddr, 6);
122 macHdr->proto_mac = SWAP16(PROTOCOL_IP);
123
124 ipHdr = (ip_header_t*)&macHdr->packet_length;
125
126 ipHdr->ip_v_hl = 0x45;
127 ipHdr->ip_tos = 0;
128 ipHdr->ip_len = SWAP16(28 + tftpLength);
129 ipHdr->ip_id = 0;
130 ipHdr->ip_off = SWAP16(0x4000);
131 ipHdr->ip_ttl = 64;
132 ipHdr->ip_p = PROTOCOL_UDP;
133 ipHdr->ip_sum = 0;
134
123 macHdr->proto_mac = SWAP16(PROTOCOL_IP);
124
125 ipHdr = (ip_header_t*)&macHdr->packet_length;
126
127 ipHdr->ip_v_hl = 0x45;
128 ipHdr->ip_tos = 0;
129 ipHdr->ip_len = SWAP16(28 + tftpLength);
130 ipHdr->ip_id = 0;
131 ipHdr->ip_off = SWAP16(0x4000);
132 ipHdr->ip_ttl = 64;
133 ipHdr->ip_p = PROTOCOL_UDP;
134 ipHdr->ip_sum = 0;
135
135 p_memcpy((char*)ipHdr->ip_src, (char*)localIPAddr, 4);
136 memcpy(ipHdr->ip_src, localIPAddr, 4);
137 memcpy(ipHdr->ip_dst, serverIPAddr, 4);
136
138
137 p_memcpy((char*)ipHdr->ip_dst, (char*)serverIPAddr, 4);
138
139 ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)ipHdr, 20));
140
141 udpHdr = (udp_header_t*)(ipHdr + 1);
142
143 udpHdr->src_port = localPort;
144 udpHdr->dst_port = serverPort;
145 udpHdr->udp_len = SWAP16(8 + tftpLength);
146 udpHdr->udp_cksum = 0;
147
139 ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)ipHdr, 20));
140
141 udpHdr = (udp_header_t*)(ipHdr + 1);
142
143 udpHdr->src_port = localPort;
144 udpHdr->dst_port = serverPort;
145 udpHdr->udp_len = SWAP16(8 + tftpLength);
146 udpHdr->udp_cksum = 0;
147
148 p_memcpy((char*)udpHdr+8, tftpData, tftpLength);
148 memcpy((char *)udpHdr+8, tftpData, tftpLength);
149
150 t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (16 + tftpLength));
151
152 t_checksum = (~t_checksum) & 0xFFFF;
153 t_checksum += 25 + tftpLength;
154
155 t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
156 t_checksum = (~t_checksum) & 0xFFFF;
157
158 udpHdr->udp_cksum = SWAP16(t_checksum);
159
160 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
161
162 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
163 *AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
164 *AT91C_EMAC_TCR = 42 + tftpLength;
165}
166
167
168/*
169 * .KB_C_FN_DEFINITION_START
170 * void TFTP_RequestFile(char *filename)
171 * This private function sends a RRQ packet to the server.
172 * .KB_C_FN_DEFINITION_END
173 */
174static void
175TFTP_RequestFile(char *filename)
176{
177 tftp_header_t tftpHeader;
178 char *cPtr, *ePtr, *mPtr;
179 unsigned length;
180
181 tftpHeader.opcode = TFTP_RRQ_OPCODE;
182
183 cPtr = (char*)&(tftpHeader.block_num);
184
149
150 t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (16 + tftpLength));
151
152 t_checksum = (~t_checksum) & 0xFFFF;
153 t_checksum += 25 + tftpLength;
154
155 t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
156 t_checksum = (~t_checksum) & 0xFFFF;
157
158 udpHdr->udp_cksum = SWAP16(t_checksum);
159
160 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
161
162 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
163 *AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
164 *AT91C_EMAC_TCR = 42 + tftpLength;
165}
166
167
168/*
169 * .KB_C_FN_DEFINITION_START
170 * void TFTP_RequestFile(char *filename)
171 * This private function sends a RRQ packet to the server.
172 * .KB_C_FN_DEFINITION_END
173 */
174static void
175TFTP_RequestFile(char *filename)
176{
177 tftp_header_t tftpHeader;
178 char *cPtr, *ePtr, *mPtr;
179 unsigned length;
180
181 tftpHeader.opcode = TFTP_RRQ_OPCODE;
182
183 cPtr = (char*)&(tftpHeader.block_num);
184
185 ePtr = p_strcpy(cPtr, filename);
186 mPtr = p_strcpy(ePtr, "octet");
185 ePtr = strcpy(cPtr, filename);
186 mPtr = strcpy(ePtr, "octet");
187
188 length = mPtr - cPtr;
189 length += 2;
190
191 Send_TFTP_Packet((char*)&tftpHeader, length);
192}
193
194
195/*
196 * .KB_C_FN_DEFINITION_START
197 * void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
198 * This private function sends an ACK packet to the server.
199 * .KB_C_FN_DEFINITION_END
200 */
201static void
202TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
203{
204 tftp_header_t tftpHeader;
205
206 if (block_num == (ackBlock + 1)) {
207 ++ackBlock;
187
188 length = mPtr - cPtr;
189 length += 2;
190
191 Send_TFTP_Packet((char*)&tftpHeader, length);
192}
193
194
195/*
196 * .KB_C_FN_DEFINITION_START
197 * void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
198 * This private function sends an ACK packet to the server.
199 * .KB_C_FN_DEFINITION_END
200 */
201static void
202TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
203{
204 tftp_header_t tftpHeader;
205
206 if (block_num == (ackBlock + 1)) {
207 ++ackBlock;
208 p_memcpy(dlAddress, data, len);
208 memcpy(dlAddress, data, len);
209 dlAddress += len;
210 lastSize += len;
211 if (ackBlock % 128 == 0)
212 printf("tftp: %u kB\r", lastSize / 1024);
213 }
214 tftpHeader.opcode = TFTP_ACK_OPCODE;
215 tftpHeader.block_num = SWAP16(ackBlock);
216 Send_TFTP_Packet((char*)&tftpHeader, 4);
217 if (len < 512) {
218 ackBlock = -2;
209 dlAddress += len;
210 lastSize += len;
211 if (ackBlock % 128 == 0)
212 printf("tftp: %u kB\r", lastSize / 1024);
213 }
214 tftpHeader.opcode = TFTP_ACK_OPCODE;
215 tftpHeader.block_num = SWAP16(ackBlock);
216 Send_TFTP_Packet((char*)&tftpHeader, 4);
217 if (len < 512) {
218 ackBlock = -2;
219 printf("tftp: %u byte\r\n", lastSize);
219 printf("tftp: %u byte\n", lastSize);
220 }
221}
222
223
224/*
225 * .KB_C_FN_DEFINITION_START
226 * void CheckForNewPacket(ip_header_t *pHeader)
227 * This private function polls for received ethernet packets and handles
228 * any here.
229 * .KB_C_FN_DEFINITION_END
230 */
231static int
232CheckForNewPacket(ip_header_t *pHeader)
233{
234 unsigned short *pFrameType;
235 unsigned i;
236 char *pData;
237 ip_header_t *pIpHeader;
238 arp_header_t *p_ARP;
239 int process = 0;
240
241 process = 0;
242 for (i = 0; i < MAX_RX_PACKETS; ++i) {
243 if(p_rxBD[i].address & 0x1) {
244 process = 1;
245 (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
246 break;
247 }
248 }
249
250 if (!process)
251 return (0);
220 }
221}
222
223
224/*
225 * .KB_C_FN_DEFINITION_START
226 * void CheckForNewPacket(ip_header_t *pHeader)
227 * This private function polls for received ethernet packets and handles
228 * any here.
229 * .KB_C_FN_DEFINITION_END
230 */
231static int
232CheckForNewPacket(ip_header_t *pHeader)
233{
234 unsigned short *pFrameType;
235 unsigned i;
236 char *pData;
237 ip_header_t *pIpHeader;
238 arp_header_t *p_ARP;
239 int process = 0;
240
241 process = 0;
242 for (i = 0; i < MAX_RX_PACKETS; ++i) {
243 if(p_rxBD[i].address & 0x1) {
244 process = 1;
245 (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
246 break;
247 }
248 }
249
250 if (!process)
251 return (0);
252
253 process = i;
254
255 pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
256 pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
257
258 switch (*pFrameType) {
259
260 case SWAP16(PROTOCOL_ARP):
261 p_ARP = (arp_header_t*)pData;
262 if (p_ARP->operation == SWAP16(ARP_REPLY)) {
263 // check if new server info is available
264 if ((!serverMACSet) &&
265 (!(p_memcmp((char*)p_ARP->sender_ip,
266 (char*)serverIPAddr, 4)))) {
267
268 serverMACSet = 1;
252 process = i;
253
254 pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
255 pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
256
257 switch (*pFrameType) {
258
259 case SWAP16(PROTOCOL_ARP):
260 p_ARP = (arp_header_t*)pData;
261 if (p_ARP->operation == SWAP16(ARP_REPLY)) {
262 // check if new server info is available
263 if ((!serverMACSet) &&
264 (!(p_memcmp((char*)p_ARP->sender_ip,
265 (char*)serverIPAddr, 4)))) {
266
267 serverMACSet = 1;
269
270 p_memcpy((char*)serverMACAddr,
271 (char*)p_ARP->sender_mac, 6);
268 memcpy(serverMACAddr, p_ARP->sender_mac, 6);
272 }
273 } else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
274 // ARP REPLY operation
275 p_ARP->operation = SWAP16(ARP_REPLY);
276
277 // Fill the dest address and src address
278 for (i = 0; i <6; i++) {
279 // swap ethernet dest address and ethernet src address
280 pData[i] = pData[i+6];
281 pData[i+6] = localMACAddr[i];
282 // swap sender ethernet address and target ethernet address
283 pData[i+22] = localMACAddr[i];
284 pData[i+32] = pData[i+6];
285 }
286
287 // swap sender IP address and target IP address
288 for (i = 0; i<4; i++) {
289 pData[i+38] = pData[i+28];
290 pData[i+28] = localIPAddr[i];
291 }
292
293 if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
294
295 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
296 *AT91C_EMAC_TAR = (unsigned)pData;
297 *AT91C_EMAC_TCR = 0x40;
298 }
299 break;
300 case SWAP16(PROTOCOL_IP):
301 pIpHeader = (ip_header_t*)(pData + 14);
269 }
270 } else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
271 // ARP REPLY operation
272 p_ARP->operation = SWAP16(ARP_REPLY);
273
274 // Fill the dest address and src address
275 for (i = 0; i <6; i++) {
276 // swap ethernet dest address and ethernet src address
277 pData[i] = pData[i+6];
278 pData[i+6] = localMACAddr[i];
279 // swap sender ethernet address and target ethernet address
280 pData[i+22] = localMACAddr[i];
281 pData[i+32] = pData[i+6];
282 }
283
284 // swap sender IP address and target IP address
285 for (i = 0; i<4; i++) {
286 pData[i+38] = pData[i+28];
287 pData[i+28] = localIPAddr[i];
288 }
289
290 if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
291
292 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
293 *AT91C_EMAC_TAR = (unsigned)pData;
294 *AT91C_EMAC_TCR = 0x40;
295 }
296 break;
297 case SWAP16(PROTOCOL_IP):
298 pIpHeader = (ip_header_t*)(pData + 14);
302 p_memcpy((char*)pHeader, (char*)pIpHeader,sizeof(ip_header_t));
299 memcpy(pHeader, pIpHeader, sizeof(ip_header_t));
303
304 if (pIpHeader->ip_p == PROTOCOL_UDP) {
305 udp_header_t *udpHdr;
306 tftp_header_t *tftpHdr;
307
308 udpHdr = (udp_header_t*)((char*)pIpHeader+20);
309 tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
310
311 if (udpHdr->dst_port != localPort)
312 break;
313
314 if (tftpHdr->opcode != TFTP_DATA_OPCODE)
315 break;
316
317 if (ackBlock == -1) {
318 if (tftpHdr->block_num != SWAP16(1))
319 break;
320 serverPort = udpHdr->src_port;
321 ackBlock = 0;
322 }
323
324 if (serverPort != udpHdr->src_port)
325 break;
326
327 TFTP_ACK_Data(tftpHdr->data,
328 SWAP16(tftpHdr->block_num),
329 SWAP16(udpHdr->udp_len) - 12);
330 }
331 }
332 p_rxBD[process].address &= ~0x01;
333 return (1);
334}
335
336
337/*
338 * .KB_C_FN_DEFINITION_START
339 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
340 * This private function reads the PHY device.
341 * .KB_C_FN_DEFINITION_END
342 */
343static unsigned short
344AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
345{
346 unsigned value = 0x60020000 | (addr << 18);
347
348 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
349 pEmac->EMAC_MAN = value;
350 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
351 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
352 return (pEmac->EMAC_MAN & 0x0000ffff);
353}
354
355/*
356 * .KB_C_FN_DEFINITION_START
357 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
358 * This private function reads the PHY device.
359 * .KB_C_FN_DEFINITION_END
360 */
361#ifdef BOOT_TSC
362static unsigned short
363AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
364{
365 unsigned value = 0x50020000 | (addr << 18) | s;
366
367 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
368 pEmac->EMAC_MAN = value;
369 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
370 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
371 return (pEmac->EMAC_MAN & 0x0000ffff);
372}
373#endif
374
375/*
376 * .KB_C_FN_DEFINITION_START
377 * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
378 * This private function determines the link speed set by the PHY.
379 * .KB_C_FN_DEFINITION_END
380 */
381static void
382MII_GetLinkSpeed(AT91PS_EMAC pEmac)
383{
384 unsigned short stat2;
385 unsigned update;
386#ifdef BOOT_TSC
387 unsigned sec;
388 int i;
389#endif
390#ifdef BOOT_KB9202
391 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
392 if (!(stat2 & MII_STS2_LINK))
393 return ;
394 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
395 if (stat2 & MII_STS2_100TX)
396 update |= AT91C_EMAC_SPD;
397 if (stat2 & MII_STS2_FDX)
398 update |= AT91C_EMAC_FD;
399#endif
400#ifdef BOOT_TSC
401 while (1) {
402 for (i = 0; i < 10; i++) {
403 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
404 if (stat2 & MII_STS_LINK_STAT)
405 break;
406 printf(".");
407 sec = GetSeconds();
408 while (GetSeconds() <= sec) continue;
409 }
410 if (stat2 & MII_STS_LINK_STAT)
411 break;
412 printf("Resetting MII...");
413 AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
414 while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
415 }
416 printf("emac: link");
417 stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
418 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
419 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
420 printf(" 100TX");
421 update |= AT91C_EMAC_SPD;
422 }
423 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
424 printf(" FDX");
425 update |= AT91C_EMAC_FD;
426 }
300
301 if (pIpHeader->ip_p == PROTOCOL_UDP) {
302 udp_header_t *udpHdr;
303 tftp_header_t *tftpHdr;
304
305 udpHdr = (udp_header_t*)((char*)pIpHeader+20);
306 tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
307
308 if (udpHdr->dst_port != localPort)
309 break;
310
311 if (tftpHdr->opcode != TFTP_DATA_OPCODE)
312 break;
313
314 if (ackBlock == -1) {
315 if (tftpHdr->block_num != SWAP16(1))
316 break;
317 serverPort = udpHdr->src_port;
318 ackBlock = 0;
319 }
320
321 if (serverPort != udpHdr->src_port)
322 break;
323
324 TFTP_ACK_Data(tftpHdr->data,
325 SWAP16(tftpHdr->block_num),
326 SWAP16(udpHdr->udp_len) - 12);
327 }
328 }
329 p_rxBD[process].address &= ~0x01;
330 return (1);
331}
332
333
334/*
335 * .KB_C_FN_DEFINITION_START
336 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
337 * This private function reads the PHY device.
338 * .KB_C_FN_DEFINITION_END
339 */
340static unsigned short
341AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
342{
343 unsigned value = 0x60020000 | (addr << 18);
344
345 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
346 pEmac->EMAC_MAN = value;
347 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
348 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
349 return (pEmac->EMAC_MAN & 0x0000ffff);
350}
351
352/*
353 * .KB_C_FN_DEFINITION_START
354 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
355 * This private function reads the PHY device.
356 * .KB_C_FN_DEFINITION_END
357 */
358#ifdef BOOT_TSC
359static unsigned short
360AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
361{
362 unsigned value = 0x50020000 | (addr << 18) | s;
363
364 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
365 pEmac->EMAC_MAN = value;
366 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
367 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
368 return (pEmac->EMAC_MAN & 0x0000ffff);
369}
370#endif
371
372/*
373 * .KB_C_FN_DEFINITION_START
374 * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
375 * This private function determines the link speed set by the PHY.
376 * .KB_C_FN_DEFINITION_END
377 */
378static void
379MII_GetLinkSpeed(AT91PS_EMAC pEmac)
380{
381 unsigned short stat2;
382 unsigned update;
383#ifdef BOOT_TSC
384 unsigned sec;
385 int i;
386#endif
387#ifdef BOOT_KB9202
388 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
389 if (!(stat2 & MII_STS2_LINK))
390 return ;
391 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
392 if (stat2 & MII_STS2_100TX)
393 update |= AT91C_EMAC_SPD;
394 if (stat2 & MII_STS2_FDX)
395 update |= AT91C_EMAC_FD;
396#endif
397#ifdef BOOT_TSC
398 while (1) {
399 for (i = 0; i < 10; i++) {
400 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
401 if (stat2 & MII_STS_LINK_STAT)
402 break;
403 printf(".");
404 sec = GetSeconds();
405 while (GetSeconds() <= sec) continue;
406 }
407 if (stat2 & MII_STS_LINK_STAT)
408 break;
409 printf("Resetting MII...");
410 AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
411 while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
412 }
413 printf("emac: link");
414 stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
415 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
416 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
417 printf(" 100TX");
418 update |= AT91C_EMAC_SPD;
419 }
420 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
421 printf(" FDX");
422 update |= AT91C_EMAC_FD;
423 }
427 printf("\r\n");
424 printf("\n");
428#endif
429 pEmac->EMAC_CFG = update;
430}
431
432
433/*
434 * .KB_C_FN_DEFINITION_START
435 * void AT91F_EmacEntry(void)
436 * This private function initializes the EMAC on the chip.
437 * .KB_C_FN_DEFINITION_END
438 */
439static void
440AT91F_EmacEntry(void)
441{
442 unsigned i;
443 char *pRxPacket = (char*)RX_DATA_START;
444 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
445
425#endif
426 pEmac->EMAC_CFG = update;
427}
428
429
430/*
431 * .KB_C_FN_DEFINITION_START
432 * void AT91F_EmacEntry(void)
433 * This private function initializes the EMAC on the chip.
434 * .KB_C_FN_DEFINITION_END
435 */
436static void
437AT91F_EmacEntry(void)
438{
439 unsigned i;
440 char *pRxPacket = (char*)RX_DATA_START;
441 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
442
443 p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
444 localPort = SWAP16(0x8002);
445
446 for (i = 0; i < MAX_RX_PACKETS; ++i) {
447
448 p_rxBD[i].address = (unsigned)pRxPacket;
449 p_rxBD[i].size = 0;
450 pRxPacket += RX_PACKET_SIZE;
451 }
452
453 // Set the WRAP bit at the end of the list descriptor
454 p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
455
456 if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
457 MII_GetLinkSpeed(pEmac);
458
459 pEmac->EMAC_RBQP = (unsigned) p_rxBD;
460 pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
461 pEmac->EMAC_CTL = AT91C_EMAC_TE | AT91C_EMAC_RE;
462
463 pEmac->EMAC_TAR = (unsigned)transmitBuffer;
464}
465
466
467/* ************************** GLOBAL FUNCTIONS ********************************/
468
469/*
470 * .KB_C_FN_DEFINITION_START
471 * void SetServerIPAddress(unsigned address)
472 * This global function sets the IP of the TFTP download server.
473 * .KB_C_FN_DEFINITION_END
474 */
475void
476SetServerIPAddress(unsigned address)
477{
478 // force update in case the IP has changed
479 serverMACSet = 0;
480
481 serverIPAddr[0] = (address >> 24) & 0xFF;
482 serverIPAddr[1] = (address >> 16) & 0xFF;
483 serverIPAddr[2] = (address >> 8) & 0xFF;
484 serverIPAddr[3] = (address >> 0) & 0xFF;
485
486 serverIPSet = 1;
487}
488
489
490/*
491 * .KB_C_FN_DEFINITION_START
492 * void SetLocalIPAddress(unsigned address)
493 * This global function sets the IP of this module.
494 * .KB_C_FN_DEFINITION_END
495 */
496void
497SetLocalIPAddress(unsigned address)
498{
499 // force update in case the IP has changed
500 serverMACSet = 0;
501
502 localIPAddr[0] = (address >> 24) & 0xFF;
503 localIPAddr[1] = (address >> 16) & 0xFF;
504 localIPAddr[2] = (address >> 8) & 0xFF;
505 localIPAddr[3] = (address >> 0) & 0xFF;
506
507 localIPSet = 1;
508}
509
510
511/*
512 * .KB_C_FN_DEFINITION_START
513 * void TFTP_Download(unsigned address, char *filename)
514 * This global function initiates and processes a tftp download request.
515 * The server IP, local IP, local MAC must be set before this function is
516 * executed.
517 * .KB_C_FN_DEFINITION_END
518 */
519void
520TFTP_Download(unsigned address, char *filename)
521{
522 ip_header_t IpHeader;
523 unsigned thisSeconds;
524 int timeout;
525
526 if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
527 return ;
528
529 AT91F_EmacEntry();
530 GetServerAddress();
531 dlAddress = (char*)address;
532 lastSize = 0;
533 timeout = 10;
534 thisSeconds = GetSeconds() + 1;
535 serverPort = SWAP16(69);
536 ++localPort;
537 ackBlock = -1;
538
539 while (timeout) {
540 if (CheckForNewPacket(&IpHeader)) {
541 if (ackBlock == -2)
542 break;
543 timeout = 10;
544 thisSeconds = GetSeconds() + 1;
545 } else if (GetSeconds() > thisSeconds) {
546 --timeout;
547 thisSeconds = GetSeconds() + 1;
548 if (!serverMACSet)
549 GetServerAddress();
550 else if (ackBlock == -1)
551 TFTP_RequestFile(filename);
552 else {
553 // Be sure to send a NAK, which is done by
554 // ACKing the last block we got.
555 TFTP_ACK_Data(0, ackBlock, 512);
446 for (i = 0; i < MAX_RX_PACKETS; ++i) {
447
448 p_rxBD[i].address = (unsigned)pRxPacket;
449 p_rxBD[i].size = 0;
450 pRxPacket += RX_PACKET_SIZE;
451 }
452
453 // Set the WRAP bit at the end of the list descriptor
454 p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
455
456 if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
457 MII_GetLinkSpeed(pEmac);
458
459 pEmac->EMAC_RBQP = (unsigned) p_rxBD;
460 pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
461 pEmac->EMAC_CTL = AT91C_EMAC_TE | AT91C_EMAC_RE;
462
463 pEmac->EMAC_TAR = (unsigned)transmitBuffer;
464}
465
466
467/* ************************** GLOBAL FUNCTIONS ********************************/
468
469/*
470 * .KB_C_FN_DEFINITION_START
471 * void SetServerIPAddress(unsigned address)
472 * This global function sets the IP of the TFTP download server.
473 * .KB_C_FN_DEFINITION_END
474 */
475void
476SetServerIPAddress(unsigned address)
477{
478 // force update in case the IP has changed
479 serverMACSet = 0;
480
481 serverIPAddr[0] = (address >> 24) & 0xFF;
482 serverIPAddr[1] = (address >> 16) & 0xFF;
483 serverIPAddr[2] = (address >> 8) & 0xFF;
484 serverIPAddr[3] = (address >> 0) & 0xFF;
485
486 serverIPSet = 1;
487}
488
489
490/*
491 * .KB_C_FN_DEFINITION_START
492 * void SetLocalIPAddress(unsigned address)
493 * This global function sets the IP of this module.
494 * .KB_C_FN_DEFINITION_END
495 */
496void
497SetLocalIPAddress(unsigned address)
498{
499 // force update in case the IP has changed
500 serverMACSet = 0;
501
502 localIPAddr[0] = (address >> 24) & 0xFF;
503 localIPAddr[1] = (address >> 16) & 0xFF;
504 localIPAddr[2] = (address >> 8) & 0xFF;
505 localIPAddr[3] = (address >> 0) & 0xFF;
506
507 localIPSet = 1;
508}
509
510
511/*
512 * .KB_C_FN_DEFINITION_START
513 * void TFTP_Download(unsigned address, char *filename)
514 * This global function initiates and processes a tftp download request.
515 * The server IP, local IP, local MAC must be set before this function is
516 * executed.
517 * .KB_C_FN_DEFINITION_END
518 */
519void
520TFTP_Download(unsigned address, char *filename)
521{
522 ip_header_t IpHeader;
523 unsigned thisSeconds;
524 int timeout;
525
526 if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
527 return ;
528
529 AT91F_EmacEntry();
530 GetServerAddress();
531 dlAddress = (char*)address;
532 lastSize = 0;
533 timeout = 10;
534 thisSeconds = GetSeconds() + 1;
535 serverPort = SWAP16(69);
536 ++localPort;
537 ackBlock = -1;
538
539 while (timeout) {
540 if (CheckForNewPacket(&IpHeader)) {
541 if (ackBlock == -2)
542 break;
543 timeout = 10;
544 thisSeconds = GetSeconds() + 1;
545 } else if (GetSeconds() > thisSeconds) {
546 --timeout;
547 thisSeconds = GetSeconds() + 1;
548 if (!serverMACSet)
549 GetServerAddress();
550 else if (ackBlock == -1)
551 TFTP_RequestFile(filename);
552 else {
553 // Be sure to send a NAK, which is done by
554 // ACKing the last block we got.
555 TFTP_ACK_Data(0, ackBlock, 512);
556 printf("\nNAK %u\r\n", ackBlock);
556 printf("\nNAK %u\n", ackBlock);
557 }
558 }
559 }
560 if (timeout == 0)
557 }
558 }
559 }
560 if (timeout == 0)
561 printf("TFTP TIMEOUT!\r\n");
561 printf("TFTP TIMEOUT!\n");
562}
562}