emac.c revision 161196
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 161196 2006-08-10 18:11:22Z 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
34static unsigned localMACSet, serverMACSet;
35static unsigned char localMACAddr[6], serverMACAddr[6];
36static unsigned localMAClow, localMAChigh;
37static unsigned localIPSet, serverIPSet;
38static unsigned char localIPAddr[4], serverIPAddr[4];
39static unsigned short	serverPort, localPort;
40static int	ackBlock;
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
57IP_checksum(unsigned short *p, int len)
58{
59	unsigned	i, t;
60
61	len &= ~1;
62
63	for (i=0,t=0; i<len; i+=2, ++p)
64		t += SWAP16(*p);
65
66	t = (t & 0xffff) + (t >> 16);
67	return (~t);
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
84	p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
85
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
97	p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4);
98
99	p_memset((char*)p_ARP->target_mac, 0, 6);
100
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;
109}
110
111
112/*
113 * .KB_C_FN_DEFINITION_START
114 * void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
115 *  This private function initializes and send a TFTP packet.
116 * .KB_C_FN_DEFINITION_END
117 */
118static void
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
128	p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6);
129
130	macHdr->proto_mac = SWAP16(PROTOCOL_IP);
131
132	ipHdr = (ip_header_t*)&macHdr->packet_length;
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
145	p_memcpy((char*)ipHdr->ip_dst, (char*)serverIPAddr, 4);
146
147	ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)ipHdr, 20));
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
158	t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (16 + tftpLength));
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);
167
168	while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
169
170  	*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
171	*AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
172	*AT91C_EMAC_TCR = 42 + tftpLength;
173}
174
175
176/*
177 * .KB_C_FN_DEFINITION_START
178 * void TFTP_RequestFile(char *filename)
179 *  This private function sends a RRQ packet to the server.
180 * .KB_C_FN_DEFINITION_END
181 */
182static void
183TFTP_RequestFile(char *filename)
184{
185	tftp_header_t	tftpHeader;
186	char		*cPtr, *ePtr, *mPtr;
187	unsigned	length;
188
189	tftpHeader.opcode = TFTP_RRQ_OPCODE;
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;
198
199	Send_TFTP_Packet((char*)&tftpHeader, length);
200}
201
202
203/*
204 * .KB_C_FN_DEFINITION_START
205 * void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
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
214	if (block_num == (ackBlock + 1)) {
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);
221	}
222	tftpHeader.opcode = TFTP_ACK_OPCODE;
223	tftpHeader.block_num = SWAP16(ackBlock);
224	Send_TFTP_Packet((char*)&tftpHeader, 4);
225	if (len < 512) {
226		ackBlock = -2;
227		printf("tftp: %u byte\r\n", lastSize);
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 */
239static int
240CheckForNewPacket(ip_header_t *pHeader)
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)
259		return (0);
260
261	process = i;
262
263	pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
264	pData      = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
265
266	switch (*pFrameType) {
267
268	case SWAP16(PROTOCOL_ARP):
269		p_ARP = (arp_header_t*)pData;
270		if (p_ARP->operation == SWAP16(ARP_REPLY)) {
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			}
281		} else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
282			// ARP REPLY operation
283			p_ARP->operation =  SWAP16(ARP_REPLY);
284
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			}
294
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			}
300
301			if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
302
303		  	*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
304			*AT91C_EMAC_TAR = (unsigned)pData;
305 			*AT91C_EMAC_TCR = 0x40;
306		}
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));
311
312		if (pIpHeader->ip_p == PROTOCOL_UDP) {
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
322			if (tftpHdr->opcode != TFTP_DATA_OPCODE)
323				break;
324
325			if (ackBlock == -1) {
326				if (tftpHdr->block_num != SWAP16(1))
327					break;
328				serverPort = udpHdr->src_port;
329				ackBlock = 0;
330			}
331
332			if (serverPort != udpHdr->src_port)
333				break;
334
335			TFTP_ACK_Data(tftpHdr->data,
336			    SWAP16(tftpHdr->block_num),
337			    SWAP16(udpHdr->udp_len) - 12);
338		}
339	}
340	p_rxBD[process].address &= ~0x01;
341	return (1);
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
350 */
351static unsigned short
352AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
353{
354	unsigned value = 0x60020000 | (addr << 18);
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;
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
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{
392	unsigned short stat2;
393	unsigned update;
394#ifdef BOOT_TSC
395	unsigned sec;
396	int i;
397#endif
398#ifdef BOOT_KB9202
399	stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
400	if (!(stat2 & MII_STS2_LINK))
401		return ;
402	update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
403	if (stat2 & MII_STS2_100TX)
404		update |= AT91C_EMAC_SPD;
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;
417		}
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");
433		update |= AT91C_EMAC_FD;
434	}
435	printf("\r\n");
436#endif
437	pEmac->EMAC_CFG = update;
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
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
464	if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
465		MII_GetLinkSpeed(pEmac);
466
467	pEmac->EMAC_RBQP = (unsigned) p_rxBD;
468	pEmac->EMAC_RSR  |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
469	pEmac->EMAC_CTL  = AT91C_EMAC_TE | AT91C_EMAC_RE;
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
486SetMACAddress(unsigned char mac[6])
487{
488	AT91PS_PMC	pPMC = AT91C_BASE_PMC;
489	AT91PS_EMAC	pEmac = AT91C_BASE_EMAC;
490
491	/* enable the peripheral clock before using EMAC */
492	pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
493
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];
497	localMACSet = 1;
498
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;
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;
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;
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;
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;
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{
586	ip_header_t 	IpHeader;
587	unsigned	thisSeconds;
588	int		timeout;
589
590	if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
591		return ;
592
593	AT91F_EmacEntry();
594	GetServerAddress();
595	dlAddress = (char*)address;
596	lastSize = 0;
597	timeout = 10;
598	thisSeconds = GetSeconds() + 1;
599	serverPort = SWAP16(69);
600	++localPort;
601	ackBlock = -1;
602
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) {
610			--timeout;
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			}
622		}
623	}
624	if (timeout == 0)
625		printf("TFTP TIMEOUT!\r\n");
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;
643	localPort = SWAP16(0x8002);
644	lastSize = 0;
645}
646