Deleted Added
full compact
emac.c (157873) emac.c (161196)
1/******************************************************************************
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
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 157873 2006-04-19 17:16:49Z imp $
23 *****************************************************************************/
21 *
22 * $FreeBSD: head/sys/boot/arm/at91/libat91/emac.c 161196 2006-08-10 18:11:22Z imp $
23 ******************************************************************************/
24
25#include "at91rm9200.h"
24
25#include "at91rm9200.h"
26#include "emac.h"
27#include "p_string.h"
28#include "at91rm9200_lowlevel.h"
26#include "at91rm9200_lowlevel.h"
27#include "emac.h"
29#include "lib.h"
30
28#include "lib.h"
29
31/******************************* GLOBALS *************************************/
30/* ****************************** GLOBALS *************************************/
32
31
33/*********************** PRIVATE FUNCTIONS/DATA ******************************/
32/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
34
33
35static unsigned localMACSet, serverMACSet, MAC_init;
34static unsigned localMACSet, serverMACSet;
36static unsigned char localMACAddr[6], serverMACAddr[6];
35static unsigned char localMACAddr[6], serverMACAddr[6];
37static unsigned localIPAddr, serverIPAddr;
36static unsigned localMAClow, localMAChigh;
37static unsigned localIPSet, serverIPSet;
38static unsigned char localIPAddr[4], serverIPAddr[4];
38static unsigned short serverPort, localPort;
39static int ackBlock;
39static unsigned short serverPort, localPort;
40static int ackBlock;
40
41static unsigned lastAddress, lastSize;
41static unsigned lastSize;
42static char *dlAddress;
43
44static unsigned transmitBuffer[1024 / sizeof(unsigned)];
45static unsigned tftpSendPacket[256 / sizeof(unsigned)];
46
47receive_descriptor_t *p_rxBD;
48
49
50/*
51 * .KB_C_FN_DEFINITION_START
52 * unsigned short IP_checksum(unsigned short *p, int len)
53 * This private function calculates the IP checksum for various headers.
54 * .KB_C_FN_DEFINITION_END
55 */
56static unsigned short
42static char *dlAddress;
43
44static unsigned transmitBuffer[1024 / sizeof(unsigned)];
45static unsigned tftpSendPacket[256 / sizeof(unsigned)];
46
47receive_descriptor_t *p_rxBD;
48
49
50/*
51 * .KB_C_FN_DEFINITION_START
52 * unsigned short IP_checksum(unsigned short *p, int len)
53 * This private function calculates the IP checksum for various headers.
54 * .KB_C_FN_DEFINITION_END
55 */
56static unsigned short
57IP_checksum(void *cp, int len)
57IP_checksum(unsigned short *p, int len)
58{
59 unsigned i, t;
58{
59 unsigned i, t;
60 unsigned short *p = (unsigned short *)cp;
61
62 len &= ~1;
60
61 len &= ~1;
62
63 for (i=0,t=0; i<len; i+=2, ++p)
64 t += SWAP16(*p);
63 for (i=0,t=0; i<len; i+=2, ++p)
64 t += SWAP16(*p);
65
65 t = (t & 0xffff) + (t >> 16);
66 t = (t & 0xffff) + (t >> 16);
66 return (~t);
67 return (~t);
67}
68
69
70/*
71 * .KB_C_FN_DEFINITION_START
72 * void GetServerAddress(void)
73 * This private function sends an ARP request to determine the server MAC.
74 * .KB_C_FN_DEFINITION_END
75 */
76static void
77GetServerAddress(void)
78{
79 arp_header_t *p_ARP;
80
81 p_ARP = (arp_header_t*)transmitBuffer;
68}
69
70
71/*
72 * .KB_C_FN_DEFINITION_START
73 * void GetServerAddress(void)
74 * This private function sends an ARP request to determine the server MAC.
75 * .KB_C_FN_DEFINITION_END
76 */
77static void
78GetServerAddress(void)
79{
80 arp_header_t *p_ARP;
81
82 p_ARP = (arp_header_t*)transmitBuffer;
83
82 p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
84 p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
85
83 p_memcpy((char*)p_ARP->src_mac, (char*)localMACAddr, 6);
84
85 p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
86 p_ARP->hard_type = SWAP16(1);
87 p_ARP->prot_type = SWAP16(PROTOCOL_IP);
88 p_ARP->hard_size = 6;
89 p_ARP->prot_size = 4;
90 p_ARP->operation = SWAP16(ARP_REQUEST);
91
92 p_memcpy((char*)p_ARP->sender_mac, (char*)localMACAddr, 6);
86 p_memcpy((char*)p_ARP->src_mac, (char*)localMACAddr, 6);
87
88 p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
89 p_ARP->hard_type = SWAP16(1);
90 p_ARP->prot_type = SWAP16(PROTOCOL_IP);
91 p_ARP->hard_size = 6;
92 p_ARP->prot_size = 4;
93 p_ARP->operation = SWAP16(ARP_REQUEST);
94
95 p_memcpy((char*)p_ARP->sender_mac, (char*)localMACAddr, 6);
96
93 p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4);
97 p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4);
98
94 p_memset((char*)p_ARP->target_mac, 0, 6);
99 p_memset((char*)p_ARP->target_mac, 0, 6);
100
95 p_memcpy((char*)p_ARP->target_ip, (char*)serverIPAddr, 4);
96
97 // wait until transmit is available
98 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
99
100 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
101 *AT91C_EMAC_TAR = (unsigned)transmitBuffer;
102 *AT91C_EMAC_TCR = 0x40;

--- 10 unchanged lines hidden (view full) ---

113Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
114{
115 transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
116 ip_header_t *ipHdr;
117 udp_header_t *udpHdr;
118 unsigned t_checksum;
119
120 p_memcpy((char*)macHdr->dest_mac, (char*)serverMACAddr, 6);
101 p_memcpy((char*)p_ARP->target_ip, (char*)serverIPAddr, 4);
102
103 // wait until transmit is available
104 while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
105
106 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
107 *AT91C_EMAC_TAR = (unsigned)transmitBuffer;
108 *AT91C_EMAC_TCR = 0x40;

--- 10 unchanged lines hidden (view full) ---

119Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
120{
121 transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
122 ip_header_t *ipHdr;
123 udp_header_t *udpHdr;
124 unsigned t_checksum;
125
126 p_memcpy((char*)macHdr->dest_mac, (char*)serverMACAddr, 6);
127
121 p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6);
122
123 macHdr->proto_mac = SWAP16(PROTOCOL_IP);
124
128 p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6);
129
130 macHdr->proto_mac = SWAP16(PROTOCOL_IP);
131
125 ipHdr = &macHdr->iphdr;
132 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
136 p_memcpy((char*)ipHdr->ip_src, (char*)localIPAddr, 4);
133
134 ipHdr->ip_v_hl = 0x45;
135 ipHdr->ip_tos = 0;
136 ipHdr->ip_len = SWAP16(28 + tftpLength);
137 ipHdr->ip_id = 0;
138 ipHdr->ip_off = SWAP16(0x4000);
139 ipHdr->ip_ttl = 64;
140 ipHdr->ip_p = PROTOCOL_UDP;
141 ipHdr->ip_sum = 0;
142
143 p_memcpy((char*)ipHdr->ip_src, (char*)localIPAddr, 4);
144
137 p_memcpy((char*)ipHdr->ip_dst, (char*)serverIPAddr, 4);
138
145 p_memcpy((char*)ipHdr->ip_dst, (char*)serverIPAddr, 4);
146
139 ipHdr->ip_sum = SWAP16(IP_checksum(ipHdr, 20));
147 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);
149
148
149 udpHdr = (udp_header_t*)(ipHdr + 1);
150
151 udpHdr->src_port = localPort;
152 udpHdr->dst_port = serverPort;
153 udpHdr->udp_len = SWAP16(8 + tftpLength);
154 udpHdr->udp_cksum = 0;
155
156 p_memcpy((char*)udpHdr+8, tftpData, tftpLength);
157
150 t_checksum = IP_checksum((char *)ipHdr + 12, (16 + tftpLength));
158 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);

--- 14 unchanged lines hidden (view full) ---

173 */
174static void
175TFTP_RequestFile(char *filename)
176{
177 tftp_header_t tftpHeader;
178 char *cPtr, *ePtr, *mPtr;
179 unsigned length;
180
159
160 t_checksum = (~t_checksum) & 0xFFFF;
161 t_checksum += 25 + tftpLength;
162
163 t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
164 t_checksum = (~t_checksum) & 0xFFFF;
165
166 udpHdr->udp_cksum = SWAP16(t_checksum);

--- 14 unchanged lines hidden (view full) ---

181 */
182static void
183TFTP_RequestFile(char *filename)
184{
185 tftp_header_t tftpHeader;
186 char *cPtr, *ePtr, *mPtr;
187 unsigned length;
188
181 tftpHeader.opcode = SWAP16(TFTP_RRQ_OPCODE);
189 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");
187
188 length = mPtr - cPtr;
189 length += 2;

--- 8 unchanged lines hidden (view full) ---

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
190
191 cPtr = (char*)&(tftpHeader.block_num);
192
193 ePtr = p_strcpy(cPtr, filename);
194 mPtr = p_strcpy(ePtr, "octet");
195
196 length = mPtr - cPtr;
197 length += 2;

--- 8 unchanged lines hidden (view full) ---

206 * This private function sends an ACK packet to the server.
207 * .KB_C_FN_DEFINITION_END
208 */
209static void
210TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
211{
212 tftp_header_t tftpHeader;
213
206 if (block_num == SWAP16(ackBlock + 1)) {
214 if (block_num == (ackBlock + 1)) {
207 ++ackBlock;
208 p_memcpy(dlAddress, data, len);
209 dlAddress += len;
210 lastSize += len;
215 ++ackBlock;
216 p_memcpy(dlAddress, data, len);
217 dlAddress += len;
218 lastSize += len;
219 if (ackBlock % 128 == 0)
220 printf("tftp: %u kB\r", lastSize / 1024);
211 }
221 }
212
213 tftpHeader.opcode = SWAP16(TFTP_ACK_OPCODE);
214 tftpHeader.block_num = block_num;
222 tftpHeader.opcode = TFTP_ACK_OPCODE;
223 tftpHeader.block_num = SWAP16(ackBlock);
215 Send_TFTP_Packet((char*)&tftpHeader, 4);
224 Send_TFTP_Packet((char*)&tftpHeader, 4);
216
217 if (len < 512)
225 if (len < 512) {
218 ackBlock = -2;
226 ackBlock = -2;
227 printf("tftp: %u byte\r\n", lastSize);
228 }
219}
220
221
222/*
223 * .KB_C_FN_DEFINITION_START
224 * void CheckForNewPacket(ip_header_t *pHeader)
225 * This private function polls for received ethernet packets and handles
226 * any here.
227 * .KB_C_FN_DEFINITION_END
228 */
229}
230
231
232/*
233 * .KB_C_FN_DEFINITION_START
234 * void CheckForNewPacket(ip_header_t *pHeader)
235 * This private function polls for received ethernet packets and handles
236 * any here.
237 * .KB_C_FN_DEFINITION_END
238 */
229static void
230CheckForNewPacket(void)
239static int
240CheckForNewPacket(ip_header_t *pHeader)
231{
232 unsigned short *pFrameType;
233 unsigned i;
234 char *pData;
235 ip_header_t *pIpHeader;
236 arp_header_t *p_ARP;
237 int process = 0;
238
239 process = 0;
240 for (i = 0; i < MAX_RX_PACKETS; ++i) {
241 if(p_rxBD[i].address & 0x1) {
242 process = 1;
243 (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
244 break;
245 }
246 }
247
248 if (!process)
241{
242 unsigned short *pFrameType;
243 unsigned i;
244 char *pData;
245 ip_header_t *pIpHeader;
246 arp_header_t *p_ARP;
247 int process = 0;
248
249 process = 0;
250 for (i = 0; i < MAX_RX_PACKETS; ++i) {
251 if(p_rxBD[i].address & 0x1) {
252 process = 1;
253 (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
254 break;
255 }
256 }
257
258 if (!process)
249 return ;
259 return (0);
250
251 process = i;
252
260
261 process = i;
262
253 pFrameType = (unsigned short *) ((p_rxBD[i].address & 0xFFFFFFFC) + 12);
263 pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
254 pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
255
264 pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
265
256 switch (SWAP16(*pFrameType)) {
266 switch (*pFrameType) {
257
267
258 case PROTOCOL_ARP:
268 case SWAP16(PROTOCOL_ARP):
259 p_ARP = (arp_header_t*)pData;
269 p_ARP = (arp_header_t*)pData;
260
261 i = SWAP16(p_ARP->operation);
262 if (i == ARP_REPLY) {
263
270 if (p_ARP->operation == SWAP16(ARP_REPLY)) {
264 // check if new server info is available
265 if ((!serverMACSet) &&
266 (!(p_memcmp((char*)p_ARP->sender_ip,
267 (char*)serverIPAddr, 4)))) {
268
269 serverMACSet = 1;
270
271 p_memcpy((char*)serverMACAddr,
272 (char*)p_ARP->sender_mac, 6);
273 }
271 // check if new server info is available
272 if ((!serverMACSet) &&
273 (!(p_memcmp((char*)p_ARP->sender_ip,
274 (char*)serverIPAddr, 4)))) {
275
276 serverMACSet = 1;
277
278 p_memcpy((char*)serverMACAddr,
279 (char*)p_ARP->sender_mac, 6);
280 }
274 } else if (i == ARP_REQUEST) {
275
281 } else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
276 // ARP REPLY operation
277 p_ARP->operation = SWAP16(ARP_REPLY);
278
282 // ARP REPLY operation
283 p_ARP->operation = SWAP16(ARP_REPLY);
284
279 // Swap the src/dst MAC addr
280 p_memcpy(p_ARP->dest_mac, p_ARP->src_mac, 6);
281 p_memcpy(p_ARP->src_mac, localMACAddr, 6);
282
283 // Do IP and MAC addr at same time.
284 p_memcpy(p_ARP->target_mac, p_ARP->sender_mac, 10);
285 p_memcpy(p_ARP->sender_mac, localMACAddr, 6);
286 p_memcpy(p_ARP->sender_ip, (char *)&localIPAddr, 4);
285 // Fill the dest address and src address
286 for (i = 0; i <6; i++) {
287 // swap ethernet dest address and ethernet src address
288 pData[i] = pData[i+6];
289 pData[i+6] = localMACAddr[i];
290 // swap sender ethernet address and target ethernet address
291 pData[i+22] = localMACAddr[i];
292 pData[i+32] = pData[i+6];
293 }
287
294
288 if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
289 break;
295 // swap sender IP address and target IP address
296 for (i = 0; i<4; i++) {
297 pData[i+38] = pData[i+28];
298 pData[i+28] = localIPAddr[i];
299 }
290
300
301 if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
302
291 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
292 *AT91C_EMAC_TAR = (unsigned)pData;
293 *AT91C_EMAC_TCR = 0x40;
294 }
303 *AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
304 *AT91C_EMAC_TAR = (unsigned)pData;
305 *AT91C_EMAC_TCR = 0x40;
306 }
295 break;
307 break;
308 case SWAP16(PROTOCOL_IP):
309 pIpHeader = (ip_header_t*)(pData + 14);
310 p_memcpy((char*)pHeader, (char*)pIpHeader,sizeof(ip_header_t));
296
311
297 case PROTOCOL_IP:
298 pIpHeader = (ip_header_t*)(pData + 14);
299 switch(pIpHeader->ip_p) {
300 case PROTOCOL_UDP:
301 {
312 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
313 udp_header_t *udpHdr;
314 tftp_header_t *tftpHdr;
315
316 udpHdr = (udp_header_t*)((char*)pIpHeader+20);
317 tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
318
319 if (udpHdr->dst_port != localPort)
320 break;
321
311 if (tftpHdr->opcode != SWAP16(TFTP_DATA_OPCODE))
322 if (tftpHdr->opcode != TFTP_DATA_OPCODE)
312 break;
313
314 if (ackBlock == -1) {
315 if (tftpHdr->block_num != SWAP16(1))
323 break;
324
325 if (ackBlock == -1) {
326 if (tftpHdr->block_num != SWAP16(1))
316 break;
317 serverPort = udpHdr->src_port;
318 ackBlock = 0;
319 }
327 break;
328 serverPort = udpHdr->src_port;
329 ackBlock = 0;
330 }
320
321 if (serverPort != udpHdr->src_port)
322 break;
323
324 TFTP_ACK_Data(tftpHdr->data,
331
332 if (serverPort != udpHdr->src_port)
333 break;
334
335 TFTP_ACK_Data(tftpHdr->data,
325 tftpHdr->block_num,
326 SWAP16(udpHdr->udp_len) - 12);
336 SWAP16(tftpHdr->block_num),
337 SWAP16(udpHdr->udp_len) - 12);
327 }
338 }
328 break;
329
330 default:
331 break;
332 }
333 break;
334
335 default:
336 break;
337 }
338 p_rxBD[process].address &= ~0x01;
339 }
340 p_rxBD[process].address &= ~0x01;
341 return (1);
339}
340
341
342/*
343 * .KB_C_FN_DEFINITION_START
344 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
345 * This private function reads the PHY device.
346 * .KB_C_FN_DEFINITION_END

--- 5 unchanged lines hidden (view full) ---

352
353 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
354 pEmac->EMAC_MAN = value;
355 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
356 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
357 return (pEmac->EMAC_MAN & 0x0000ffff);
358}
359
342}
343
344
345/*
346 * .KB_C_FN_DEFINITION_START
347 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
348 * This private function reads the PHY device.
349 * .KB_C_FN_DEFINITION_END

--- 5 unchanged lines hidden (view full) ---

355
356 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
357 pEmac->EMAC_MAN = value;
358 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
359 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
360 return (pEmac->EMAC_MAN & 0x0000ffff);
361}
362
363/*
364 * .KB_C_FN_DEFINITION_START
365 * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
366 * This private function reads the PHY device.
367 * .KB_C_FN_DEFINITION_END
368 */
369#ifdef BOOT_TSC
370static unsigned short
371AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
372{
373 unsigned value = 0x50020000 | (addr << 18) | s;
360
374
375 pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
376 pEmac->EMAC_MAN = value;
377 while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
378 pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
379 return (pEmac->EMAC_MAN & 0x0000ffff);
380}
381#endif
382
361/*
362 * .KB_C_FN_DEFINITION_START
363 * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
364 * This private function determines the link speed set by the PHY.
365 * .KB_C_FN_DEFINITION_END
366 */
367static void
368MII_GetLinkSpeed(AT91PS_EMAC pEmac)
369{
383/*
384 * .KB_C_FN_DEFINITION_START
385 * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
386 * This private function determines the link speed set by the PHY.
387 * .KB_C_FN_DEFINITION_END
388 */
389static void
390MII_GetLinkSpeed(AT91PS_EMAC pEmac)
391{
370 unsigned short stat2;
371 unsigned update = 0;
372
392 unsigned short stat2;
393 unsigned update;
394#ifdef BOOT_TSC
395 unsigned sec;
396 int i;
397#endif
398#ifdef BOOT_KB9202
373 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
399 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
374
375 if (!(stat2 & 0x400)) {
400 if (!(stat2 & MII_STS2_LINK))
376 return ;
401 return ;
377
378 } else if (stat2 & 0x4000) {
379
402 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
403 if (stat2 & MII_STS2_100TX)
380 update |= AT91C_EMAC_SPD;
404 update |= AT91C_EMAC_SPD;
381
382 if (stat2 & 0x200) {
383 update |= AT91C_EMAC_FD;
405 if (stat2 & MII_STS2_FDX)
406 update |= AT91C_EMAC_FD;
407#endif
408#ifdef BOOT_TSC
409 while (1) {
410 for (i = 0; i < 10; i++) {
411 stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
412 if (stat2 & MII_STS_LINK_STAT)
413 break;
414 printf(".");
415 sec = GetSeconds();
416 while (GetSeconds() <= sec) continue;
384 }
417 }
385
386 } else if (stat2 & 0x200) {
418 if (stat2 & MII_STS_LINK_STAT)
419 break;
420 printf("Resetting MII...");
421 AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
422 while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
423 }
424 printf("emac: link");
425 stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
426 update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
427 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
428 printf(" 100TX");
429 update |= AT91C_EMAC_SPD;
430 }
431 if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
432 printf(" FDX");
387 update |= AT91C_EMAC_FD;
388 }
433 update |= AT91C_EMAC_FD;
434 }
389
390 pEmac->EMAC_CFG =
391 (pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)) | update;
435 printf("\r\n");
436#endif
437 pEmac->EMAC_CFG = update;
392}
393
394
395/*
396 * .KB_C_FN_DEFINITION_START
397 * void AT91F_EmacEntry(void)
398 * This private function initializes the EMAC on the chip.
399 * .KB_C_FN_DEFINITION_END
400 */
401static void
402AT91F_EmacEntry(void)
403{
404 unsigned i;
405 char *pRxPacket = (char*)RX_DATA_START;
406 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
407
408 for (i = 0; i < MAX_RX_PACKETS; ++i) {
438}
439
440
441/*
442 * .KB_C_FN_DEFINITION_START
443 * void AT91F_EmacEntry(void)
444 * This private function initializes the EMAC on the chip.
445 * .KB_C_FN_DEFINITION_END
446 */
447static void
448AT91F_EmacEntry(void)
449{
450 unsigned i;
451 char *pRxPacket = (char*)RX_DATA_START;
452 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
453
454 for (i = 0; i < MAX_RX_PACKETS; ++i) {
455
409 p_rxBD[i].address = (unsigned)pRxPacket;
410 p_rxBD[i].size = 0;
411 pRxPacket += RX_PACKET_SIZE;
412 }
413
414 // Set the WRAP bit at the end of the list descriptor
415 p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
416
456 p_rxBD[i].address = (unsigned)pRxPacket;
457 p_rxBD[i].size = 0;
458 pRxPacket += RX_PACKET_SIZE;
459 }
460
461 // Set the WRAP bit at the end of the list descriptor
462 p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
463
417 pEmac->EMAC_CTL = 0;
418
419 if(!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
464 if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
420 MII_GetLinkSpeed(pEmac);
421
465 MII_GetLinkSpeed(pEmac);
466
422 // the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
423 pEmac->EMAC_SA1L = ((unsigned)localMACAddr[2] << 24) |
424 ((unsigned)localMACAddr[3] << 16) | ((int)localMACAddr[4] << 8) |
425 localMACAddr[5];
426 pEmac->EMAC_SA1H = ((unsigned)localMACAddr[0] << 8) | localMACAddr[1];
427
428 pEmac->EMAC_RBQP = (unsigned) p_rxBD;
429 pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
467 pEmac->EMAC_RBQP = (unsigned) p_rxBD;
468 pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
430 pEmac->EMAC_CFG |= AT91C_EMAC_CAF;
431 pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~(AT91C_EMAC_CLK)) |
432 AT91C_EMAC_CLK_HCLK_32;
433 pEmac->EMAC_CTL |= (AT91C_EMAC_TE | AT91C_EMAC_RE);
469 pEmac->EMAC_CTL = AT91C_EMAC_TE | AT91C_EMAC_RE;
434
435 pEmac->EMAC_TAR = (unsigned)transmitBuffer;
436}
437
438
439/* ************************** GLOBAL FUNCTIONS ********************************/
440
441
442/*
443 * .KB_C_FN_DEFINITION_START
444 * void SetMACAddress(unsigned low_address, unsigned high_address)
445 * This global function sets the MAC address. low_address is the first
446 * four bytes while high_address is the last 2 bytes of the 48-bit value.
447 * .KB_C_FN_DEFINITION_END
448 */
449void
470
471 pEmac->EMAC_TAR = (unsigned)transmitBuffer;
472}
473
474
475/* ************************** GLOBAL FUNCTIONS ********************************/
476
477
478/*
479 * .KB_C_FN_DEFINITION_START
480 * void SetMACAddress(unsigned low_address, unsigned high_address)
481 * This global function sets the MAC address. low_address is the first
482 * four bytes while high_address is the last 2 bytes of the 48-bit value.
483 * .KB_C_FN_DEFINITION_END
484 */
485void
450SetMACAddress(unsigned low_address, unsigned high_address)
486SetMACAddress(unsigned char mac[6])
451{
487{
452
453 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
454 AT91PS_PMC pPMC = AT91C_BASE_PMC;
488 AT91PS_PMC pPMC = AT91C_BASE_PMC;
489 AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
455
456 /* enable the peripheral clock before using EMAC */
457 pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
458
490
491 /* enable the peripheral clock before using EMAC */
492 pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
493
459 pEmac->EMAC_SA1L = low_address;
460 pEmac->EMAC_SA1H = (high_address & 0x0000ffff);
461
462 localMACAddr[0] = (low_address >> 0) & 0xFF;
463 localMACAddr[1] = (low_address >> 8) & 0xFF;
464 localMACAddr[2] = (low_address >> 16) & 0xFF;
465 localMACAddr[3] = (low_address >> 24) & 0xFF;
466 localMACAddr[4] = (high_address >> 0) & 0xFF;
467 localMACAddr[5] = (high_address >> 8) & 0xFF;
468
494 p_memcpy(localMACAddr, mac, 6);
495 localMAClow = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
496 localMAChigh = (mac[0] << 8) | mac[1];
469 localMACSet = 1;
470
497 localMACSet = 1;
498
471 // low_address & 0x000000ff = first byte in address
472 // low_address & 0x0000ff00 = next
473 // low_address & 0x00ff0000 = next
474 // low_address & 0xff000000 = next
475 // high_address & 0x000000ff = next
476 // high_address & 0x0000ff00 = last byte in address
499 AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
500 AT91C_BASE_PIOA->PIO_ASR =
501 AT91C_PA14_ERXER | AT91C_PA12_ERX0 | AT91C_PA13_ERX1 |
502 AT91C_PA8_ETXEN | AT91C_PA16_EMDIO | AT91C_PA9_ETX0 |
503 AT91C_PA10_ETX1 | AT91C_PA11_ECRS_ECRSDV | AT91C_PA15_EMDC |
504 AT91C_PA7_ETXCK_EREFCK;
505 AT91C_BASE_PIOA->PIO_PDR =
506 AT91C_PA14_ERXER | AT91C_PA12_ERX0 | AT91C_PA13_ERX1 |
507 AT91C_PA8_ETXEN | AT91C_PA16_EMDIO | AT91C_PA9_ETX0 |
508 AT91C_PA10_ETX1 | AT91C_PA11_ECRS_ECRSDV | AT91C_PA15_EMDC |
509 AT91C_PA7_ETXCK_EREFCK;
510#ifdef BOOT_KB9202 /* Really !RMII */
511 AT91C_BASE_PIOB->PIO_BSR =
512 AT91C_PB12_ETX2 | AT91C_PB13_ETX3 | AT91C_PB14_ETXER |
513 AT91C_PB15_ERX2 | AT91C_PB16_ERX3 | AT91C_PB17_ERXDV |
514 AT91C_PB18_ECOL | AT91C_PB19_ERXCK;
515 AT91C_BASE_PIOB->PIO_PDR =
516 AT91C_PB12_ETX2 | AT91C_PB13_ETX3 | AT91C_PB14_ETXER |
517 AT91C_PB15_ERX2 | AT91C_PB16_ERX3 | AT91C_PB17_ERXDV |
518 AT91C_PB18_ECOL | AT91C_PB19_ERXCK;
519#endif
520 pEmac->EMAC_CTL = 0;
521
522 pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~(AT91C_EMAC_CLK)) |
523#ifdef BOOT_TSC
524 AT91C_EMAC_RMII |
525#endif
526 AT91C_EMAC_CLK_HCLK_32 | AT91C_EMAC_CAF;
527 // the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
528 pEmac->EMAC_SA1L = localMAClow;
529 pEmac->EMAC_SA1H = localMAChigh;
477}
478
479
480/*
481 * .KB_C_FN_DEFINITION_START
482 * void SetServerIPAddress(unsigned address)
483 * This global function sets the IP of the TFTP download server.
484 * .KB_C_FN_DEFINITION_END
485 */
486void
487SetServerIPAddress(unsigned address)
488{
489 // force update in case the IP has changed
490 serverMACSet = 0;
530}
531
532
533/*
534 * .KB_C_FN_DEFINITION_START
535 * void SetServerIPAddress(unsigned address)
536 * This global function sets the IP of the TFTP download server.
537 * .KB_C_FN_DEFINITION_END
538 */
539void
540SetServerIPAddress(unsigned address)
541{
542 // force update in case the IP has changed
543 serverMACSet = 0;
491 serverIPAddr = address;
544
545 serverIPAddr[0] = (address >> 24) & 0xFF;
546 serverIPAddr[1] = (address >> 16) & 0xFF;
547 serverIPAddr[2] = (address >> 8) & 0xFF;
548 serverIPAddr[3] = (address >> 0) & 0xFF;
549
550 serverIPSet = 1;
492}
493
494
495/*
496 * .KB_C_FN_DEFINITION_START
497 * void SetLocalIPAddress(unsigned address)
498 * This global function sets the IP of this module.
499 * .KB_C_FN_DEFINITION_END
500 */
501void
502SetLocalIPAddress(unsigned address)
503{
504 // force update in case the IP has changed
505 serverMACSet = 0;
551}
552
553
554/*
555 * .KB_C_FN_DEFINITION_START
556 * void SetLocalIPAddress(unsigned address)
557 * This global function sets the IP of this module.
558 * .KB_C_FN_DEFINITION_END
559 */
560void
561SetLocalIPAddress(unsigned address)
562{
563 // force update in case the IP has changed
564 serverMACSet = 0;
506 localIPAddr = address;
565
566 localIPAddr[0] = (address >> 24) & 0xFF;
567 localIPAddr[1] = (address >> 16) & 0xFF;
568 localIPAddr[2] = (address >> 8) & 0xFF;
569 localIPAddr[3] = (address >> 0) & 0xFF;
570
571 localIPSet = 1;
507}
508
509
510/*
511 * .KB_C_FN_DEFINITION_START
512 * void TFTP_Download(unsigned address, char *filename)
513 * This global function initiates and processes a tftp download request.
514 * The server IP, local IP, local MAC must be set before this function is
515 * executed.
516 * .KB_C_FN_DEFINITION_END
517 */
518void
519TFTP_Download(unsigned address, char *filename)
520{
572}
573
574
575/*
576 * .KB_C_FN_DEFINITION_START
577 * void TFTP_Download(unsigned address, char *filename)
578 * This global function initiates and processes a tftp download request.
579 * The server IP, local IP, local MAC must be set before this function is
580 * executed.
581 * .KB_C_FN_DEFINITION_END
582 */
583void
584TFTP_Download(unsigned address, char *filename)
585{
521 unsigned thisSeconds, running, state;
522 int timeout, tickUpdate;
586 ip_header_t IpHeader;
587 unsigned thisSeconds;
588 int timeout;
523
589
524 if (!address) {
525 // report last transfer information
526 printf("Last tftp transfer info --\r\n"
527 "address: 0x%x\r\n"
528 " size: 0x%x\r\n", lastAddress, lastSize);
590 if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
529 return ;
591 return ;
530 }
531
592
532 if ((!localMACSet) || (!localIPAddr) || (!serverIPAddr))
533 return ;
534
535 if (!MAC_init) {
536 AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
537
538 AT91C_BASE_PIOA->PIO_ASR =
539 AT91C_PA14_ERXER |
540 AT91C_PA12_ERX0 |
541 AT91C_PA13_ERX1 |
542 AT91C_PA8_ETXEN |
543 AT91C_PA16_EMDIO |
544 AT91C_PA9_ETX0 |
545 AT91C_PA10_ETX1 |
546 AT91C_PA11_ECRS_ECRSDV |
547 AT91C_PA15_EMDC |
548 AT91C_PA7_ETXCK_EREFCK;
549 AT91C_BASE_PIOA->PIO_BSR = 0;
550 AT91C_BASE_PIOA->PIO_PDR =
551 AT91C_PA14_ERXER |
552 AT91C_PA12_ERX0 |
553 AT91C_PA13_ERX1 |
554 AT91C_PA8_ETXEN |
555 AT91C_PA16_EMDIO |
556 AT91C_PA9_ETX0 |
557 AT91C_PA10_ETX1 |
558 AT91C_PA11_ECRS_ECRSDV |
559 AT91C_PA15_EMDC |
560 AT91C_PA7_ETXCK_EREFCK;
561 AT91C_BASE_PIOB->PIO_ASR = 0;
562 AT91C_BASE_PIOB->PIO_BSR =
563 AT91C_PB12_ETX2 |
564 AT91C_PB13_ETX3 |
565 AT91C_PB14_ETXER |
566 AT91C_PB15_ERX2 |
567 AT91C_PB16_ERX3 |
568 AT91C_PB17_ERXDV |
569 AT91C_PB18_ECOL |
570 AT91C_PB19_ERXCK;
571 AT91C_BASE_PIOB->PIO_PDR =
572 AT91C_PB12_ETX2 |
573 AT91C_PB13_ETX3 |
574 AT91C_PB14_ETXER |
575 AT91C_PB15_ERX2 |
576 AT91C_PB16_ERX3 |
577 AT91C_PB17_ERXDV |
578 AT91C_PB18_ECOL |
579 AT91C_PB19_ERXCK;
580 MAC_init = 1;
581 }
582
583 AT91F_EmacEntry();
593 AT91F_EmacEntry();
584
585 GetServerAddress();
594 GetServerAddress();
586 lastAddress = address;
587 dlAddress = (char*)address;
588 lastSize = 0;
595 dlAddress = (char*)address;
596 lastSize = 0;
589 running = 1;
590 state = TFTP_WAITING_SERVER_MAC;
591 timeout = 10;
597 timeout = 10;
592 thisSeconds = GetSeconds();
598 thisSeconds = GetSeconds() + 1;
593 serverPort = SWAP16(69);
599 serverPort = SWAP16(69);
594 localPort++; /* In network byte order, but who cares */
600 ++localPort;
595 ackBlock = -1;
596
601 ackBlock = -1;
602
597 while (running && timeout) {
598
599 CheckForNewPacket();
600
601 tickUpdate = 0;
602
603 if (thisSeconds != GetSeconds()) {
604 tickUpdate = 1;
603 while (timeout) {
604 if (CheckForNewPacket(&IpHeader)) {
605 if (ackBlock == -2)
606 break;
607 timeout = 10;
608 thisSeconds = GetSeconds() + 1;
609 } else if (GetSeconds() > thisSeconds) {
605 --timeout;
610 --timeout;
606 thisSeconds = GetSeconds();
611 thisSeconds = GetSeconds() + 1;
612 if (!serverMACSet)
613 GetServerAddress();
614 else if (ackBlock == -1)
615 TFTP_RequestFile(filename);
616 else {
617 // Be sure to send a NAK, which is done by
618 // ACKing the last block we got.
619 TFTP_ACK_Data(0, ackBlock, 512);
620 printf("\nNAK %u\r\n", ackBlock);
621 }
607 }
622 }
608
609 switch (state) {
610
611 case TFTP_WAITING_SERVER_MAC:
612 if (serverMACSet) {
613 state = TFTP_SEND_REQUEST;
614 break;
615 }
616
617 if (tickUpdate)
618 GetServerAddress();
619 break;
620
621 case TFTP_SEND_REQUEST:
622 // send request for file
623 if (ackBlock != -1) {
624 state = TFTP_GET_DATA;
625 break;
626 }
627
628 if (tickUpdate)
629 TFTP_RequestFile(filename);
630 break;
631
632 case TFTP_GET_DATA:
633 // receiving data
634 if (ackBlock == -2) {
635 state = TFTP_COMPLETE;
636 break;
637 }
638 break;
639
640 case TFTP_COMPLETE:
641 default:
642 running = 0;
643 break;
644 }
645 }
623 }
624 if (timeout == 0)
625 printf("TFTP TIMEOUT!\r\n");
646}
647
648
649/*
650 * .KB_C_FN_DEFINITION_START
651 * void EMAC_Init(void)
652 * This global function initializes variables used in tftp transfers.
653 * .KB_C_FN_DEFINITION_END
654 */
655void
656EMAC_Init(void)
657{
658 p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
659 localMACSet = 0;
660 serverMACSet = 0;
626}
627
628
629/*
630 * .KB_C_FN_DEFINITION_START
631 * void EMAC_Init(void)
632 * This global function initializes variables used in tftp transfers.
633 * .KB_C_FN_DEFINITION_END
634 */
635void
636EMAC_Init(void)
637{
638 p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
639 localMACSet = 0;
640 serverMACSet = 0;
641 localIPSet = 0;
642 serverIPSet = 0;
661 localPort = SWAP16(0x8002);
643 localPort = SWAP16(0x8002);
662 lastAddress = 0;
663 lastSize = 0;
644 lastSize = 0;
664 MAC_init = 0;
665}
645}