1161196Simp/*******************************************************************************
2157873Simp *
3157873Simp * Filename: emac.c
4157873Simp *
5157873Simp * Instantiation of routines for MAC/ethernet functions supporting tftp.
6157873Simp *
7157873Simp * Revision information:
8157873Simp *
9157873Simp * 28AUG2004	kb_admin	initial creation
10157873Simp * 08JAN2005	kb_admin	added tftp download
11157873Simp *					also adapted from external sources
12157873Simp *
13157873Simp * BEGIN_KBDD_BLOCK
14157873Simp * No warranty, expressed or implied, is included with this software.  It is
15157873Simp * provided "AS IS" and no warranty of any kind including statutory or aspects
16157873Simp * relating to merchantability or fitness for any purpose is provided.  All
17157873Simp * intellectual property rights of others is maintained with the respective
18157873Simp * owners.  This software is not copyrighted and is intended for reference
19157873Simp * only.
20157873Simp * END_BLOCK
21161196Simp *
22157873Simp * $FreeBSD$
23161196Simp ******************************************************************************/
24157873Simp
25157873Simp#include "at91rm9200.h"
26161196Simp#include "at91rm9200_lowlevel.h"
27157873Simp#include "emac.h"
28157873Simp#include "lib.h"
29157873Simp
30161196Simp/* ****************************** GLOBALS *************************************/
31157873Simp
32161196Simp/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
33157873Simp
34163533Simpstatic receive_descriptor_t *p_rxBD;
35163533Simpstatic unsigned short localPort;
36163533Simpstatic unsigned short serverPort;
37163533Simpstatic unsigned serverMACSet;
38163533Simpstatic unsigned localIPSet, serverIPSet;
39163533Simpstatic unsigned	lastSize;
40163533Simpstatic unsigned char serverMACAddr[6];
41161196Simpstatic unsigned char localIPAddr[4], serverIPAddr[4];
42157873Simpstatic int	ackBlock;
43157873Simpstatic char *dlAddress;
44157873Simp
45157873Simpstatic unsigned transmitBuffer[1024 / sizeof(unsigned)];
46157873Simpstatic unsigned tftpSendPacket[256 / sizeof(unsigned)];
47157873Simp
48157873Simp/*
49157873Simp * .KB_C_FN_DEFINITION_START
50157873Simp * unsigned short IP_checksum(unsigned short *p, int len)
51157873Simp *  This private function calculates the IP checksum for various headers.
52157873Simp * .KB_C_FN_DEFINITION_END
53157873Simp */
54157873Simpstatic unsigned short
55161196SimpIP_checksum(unsigned short *p, int len)
56157873Simp{
57157873Simp	unsigned	i, t;
58157873Simp
59157873Simp	len &= ~1;
60161196Simp
61157873Simp	for (i=0,t=0; i<len; i+=2, ++p)
62157873Simp		t += SWAP16(*p);
63161196Simp
64157873Simp	t = (t & 0xffff) + (t >> 16);
65161196Simp	return (~t);
66157873Simp}
67157873Simp
68157873Simp
69157873Simp/*
70157873Simp * .KB_C_FN_DEFINITION_START
71157873Simp * void GetServerAddress(void)
72157873Simp *  This private function sends an ARP request to determine the server MAC.
73157873Simp * .KB_C_FN_DEFINITION_END
74157873Simp */
75157873Simpstatic void
76157873SimpGetServerAddress(void)
77157873Simp{
78157873Simp	arp_header_t	*p_ARP;
79157873Simp
80157873Simp	p_ARP = (arp_header_t*)transmitBuffer;
81161196Simp
82157873Simp	p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
83161196Simp
84163533Simp	memcpy(p_ARP->src_mac, localMACAddr, 6);
85157873Simp
86157873Simp	p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
87157873Simp	p_ARP->hard_type  = SWAP16(1);
88157873Simp	p_ARP->prot_type  = SWAP16(PROTOCOL_IP);
89157873Simp	p_ARP->hard_size  = 6;
90157873Simp	p_ARP->prot_size  = 4;
91157873Simp	p_ARP->operation  = SWAP16(ARP_REQUEST);
92157873Simp
93163533Simp	memcpy(p_ARP->sender_mac, localMACAddr, 6);
94163533Simp	memcpy(p_ARP->sender_ip, localIPAddr, 4);
95157873Simp	p_memset((char*)p_ARP->target_mac, 0, 6);
96163533Simp	memcpy(p_ARP->target_ip, serverIPAddr, 4);
97161196Simp
98157873Simp	// wait until transmit is available
99157873Simp	while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
100157873Simp
101157873Simp  	*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
102157873Simp	*AT91C_EMAC_TAR = (unsigned)transmitBuffer;
103157873Simp	*AT91C_EMAC_TCR = 0x40;
104157873Simp}
105157873Simp
106157873Simp
107157873Simp/*
108157873Simp * .KB_C_FN_DEFINITION_START
109157873Simp * void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
110157873Simp *  This private function initializes and send a TFTP packet.
111157873Simp * .KB_C_FN_DEFINITION_END
112157873Simp */
113157873Simpstatic void
114157873SimpSend_TFTP_Packet(char *tftpData, unsigned tftpLength)
115157873Simp{
116157873Simp	transmit_header_t	*macHdr = (transmit_header_t*)tftpSendPacket;
117157873Simp	ip_header_t		*ipHdr;
118157873Simp	udp_header_t		*udpHdr;
119157873Simp	unsigned		t_checksum;
120157873Simp
121163533Simp	memcpy(macHdr->dest_mac, serverMACAddr, 6);
122163533Simp	memcpy(macHdr->src_mac, localMACAddr, 6);
123157873Simp	macHdr->proto_mac = SWAP16(PROTOCOL_IP);
124157873Simp
125161196Simp	ipHdr = (ip_header_t*)&macHdr->packet_length;
126157873Simp
127157873Simp	ipHdr->ip_v_hl = 0x45;
128157873Simp	ipHdr->ip_tos = 0;
129157873Simp	ipHdr->ip_len = SWAP16(28 + tftpLength);
130157873Simp	ipHdr->ip_id = 0;
131157873Simp	ipHdr->ip_off = SWAP16(0x4000);
132157873Simp	ipHdr->ip_ttl = 64;
133157873Simp	ipHdr->ip_p = PROTOCOL_UDP;
134157873Simp	ipHdr->ip_sum = 0;
135157873Simp
136163533Simp	memcpy(ipHdr->ip_src, localIPAddr, 4);
137163533Simp	memcpy(ipHdr->ip_dst, serverIPAddr, 4);
138161196Simp
139161196Simp	ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)ipHdr, 20));
140157873Simp
141157873Simp	udpHdr = (udp_header_t*)(ipHdr + 1);
142157873Simp
143157873Simp	udpHdr->src_port  = localPort;
144157873Simp	udpHdr->dst_port  = serverPort;
145157873Simp	udpHdr->udp_len   = SWAP16(8 + tftpLength);
146157873Simp	udpHdr->udp_cksum = 0;
147157873Simp
148163533Simp	memcpy((char *)udpHdr+8, tftpData, tftpLength);
149157873Simp
150161196Simp	t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (16 + tftpLength));
151157873Simp
152157873Simp	t_checksum = (~t_checksum) & 0xFFFF;
153157873Simp	t_checksum += 25 + tftpLength;
154157873Simp
155157873Simp	t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
156157873Simp	t_checksum = (~t_checksum) & 0xFFFF;
157157873Simp
158157873Simp	udpHdr->udp_cksum = SWAP16(t_checksum);
159157873Simp
160157873Simp	while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) ;
161157873Simp
162157873Simp  	*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
163157873Simp	*AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
164157873Simp	*AT91C_EMAC_TCR = 42 + tftpLength;
165157873Simp}
166157873Simp
167157873Simp
168157873Simp/*
169157873Simp * .KB_C_FN_DEFINITION_START
170157873Simp * void TFTP_RequestFile(char *filename)
171157873Simp *  This private function sends a RRQ packet to the server.
172157873Simp * .KB_C_FN_DEFINITION_END
173157873Simp */
174157873Simpstatic void
175157873SimpTFTP_RequestFile(char *filename)
176157873Simp{
177157873Simp	tftp_header_t	tftpHeader;
178157873Simp	char		*cPtr, *ePtr, *mPtr;
179157873Simp	unsigned	length;
180157873Simp
181161196Simp	tftpHeader.opcode = TFTP_RRQ_OPCODE;
182157873Simp
183157873Simp	cPtr = (char*)&(tftpHeader.block_num);
184157873Simp
185163533Simp	ePtr = strcpy(cPtr, filename);
186163533Simp	mPtr = strcpy(ePtr, "octet");
187157873Simp
188157873Simp	length = mPtr - cPtr;
189157873Simp	length += 2;
190157873Simp
191157873Simp	Send_TFTP_Packet((char*)&tftpHeader, length);
192157873Simp}
193157873Simp
194157873Simp
195157873Simp/*
196157873Simp * .KB_C_FN_DEFINITION_START
197157873Simp * void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
198157873Simp *  This private function sends an ACK packet to the server.
199157873Simp * .KB_C_FN_DEFINITION_END
200157873Simp */
201157873Simpstatic void
202172991ScognetTFTP_ACK_Data(unsigned char *data, unsigned short block_num, unsigned short len)
203157873Simp{
204157873Simp	tftp_header_t	tftpHeader;
205157873Simp
206161196Simp	if (block_num == (ackBlock + 1)) {
207157873Simp		++ackBlock;
208163533Simp		memcpy(dlAddress, data, len);
209157873Simp		dlAddress += len;
210157873Simp		lastSize += len;
211161196Simp		if (ackBlock % 128 == 0)
212161196Simp			printf("tftp: %u kB\r", lastSize / 1024);
213157873Simp	}
214161196Simp	tftpHeader.opcode = TFTP_ACK_OPCODE;
215161196Simp	tftpHeader.block_num = SWAP16(ackBlock);
216157873Simp	Send_TFTP_Packet((char*)&tftpHeader, 4);
217161196Simp	if (len < 512) {
218157873Simp		ackBlock = -2;
219163533Simp		printf("tftp: %u byte\n", lastSize);
220161196Simp	}
221157873Simp}
222157873Simp
223157873Simp
224157873Simp/*
225157873Simp * .KB_C_FN_DEFINITION_START
226157873Simp * void CheckForNewPacket(ip_header_t *pHeader)
227157873Simp *  This private function polls for received ethernet packets and handles
228157873Simp * any here.
229157873Simp * .KB_C_FN_DEFINITION_END
230157873Simp */
231161196Simpstatic int
232161196SimpCheckForNewPacket(ip_header_t *pHeader)
233157873Simp{
234157873Simp	unsigned short	*pFrameType;
235157873Simp	unsigned	i;
236157873Simp	char		*pData;
237157873Simp	ip_header_t	*pIpHeader;
238157873Simp	arp_header_t	*p_ARP;
239157873Simp	int		process = 0;
240157873Simp
241157873Simp	process = 0;
242157873Simp	for (i = 0; i < MAX_RX_PACKETS; ++i) {
243157873Simp		if(p_rxBD[i].address & 0x1) {
244157873Simp			process = 1;
245157873Simp			(*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
246157873Simp			break;
247157873Simp		}
248157873Simp	}
249157873Simp
250157873Simp	if (!process)
251161196Simp		return (0);
252157873Simp	process = i;
253157873Simp
254161196Simp	pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
255157873Simp	pData      = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
256157873Simp
257161196Simp	switch (*pFrameType) {
258157873Simp
259161196Simp	case SWAP16(PROTOCOL_ARP):
260157873Simp		p_ARP = (arp_header_t*)pData;
261161196Simp		if (p_ARP->operation == SWAP16(ARP_REPLY)) {
262157873Simp			// check if new server info is available
263157873Simp			if ((!serverMACSet) &&
264157873Simp				(!(p_memcmp((char*)p_ARP->sender_ip,
265157873Simp					(char*)serverIPAddr, 4)))) {
266157873Simp
267157873Simp				serverMACSet = 1;
268163533Simp				memcpy(serverMACAddr, p_ARP->sender_mac, 6);
269157873Simp			}
270161196Simp		} else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
271157873Simp			// ARP REPLY operation
272157873Simp			p_ARP->operation =  SWAP16(ARP_REPLY);
273157873Simp
274161196Simp			// Fill the dest address and src address
275161196Simp			for (i = 0; i <6; i++) {
276161196Simp				// swap ethernet dest address and ethernet src address
277161196Simp				pData[i] = pData[i+6];
278161196Simp				pData[i+6] = localMACAddr[i];
279161196Simp				// swap sender ethernet address and target ethernet address
280161196Simp				pData[i+22] = localMACAddr[i];
281161196Simp				pData[i+32] = pData[i+6];
282161196Simp			}
283157873Simp
284161196Simp			// swap sender IP address and target IP address
285161196Simp			for (i = 0; i<4; i++) {
286161196Simp				pData[i+38] = pData[i+28];
287161196Simp				pData[i+28] = localIPAddr[i];
288161196Simp			}
289157873Simp
290161196Simp			if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
291161196Simp
292157873Simp		  	*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
293157873Simp			*AT91C_EMAC_TAR = (unsigned)pData;
294157873Simp 			*AT91C_EMAC_TCR = 0x40;
295157873Simp		}
296161196Simp		break;
297161196Simp	case SWAP16(PROTOCOL_IP):
298161196Simp		pIpHeader = (ip_header_t*)(pData + 14);
299163533Simp		memcpy(pHeader, pIpHeader, sizeof(ip_header_t));
300157873Simp
301161196Simp		if (pIpHeader->ip_p == PROTOCOL_UDP) {
302157873Simp			udp_header_t	*udpHdr;
303157873Simp			tftp_header_t	*tftpHdr;
304157873Simp
305157873Simp			udpHdr = (udp_header_t*)((char*)pIpHeader+20);
306157873Simp			tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
307157873Simp
308157873Simp			if (udpHdr->dst_port != localPort)
309157873Simp				break;
310157873Simp
311161196Simp			if (tftpHdr->opcode != TFTP_DATA_OPCODE)
312157873Simp				break;
313157873Simp
314157873Simp			if (ackBlock == -1) {
315157873Simp				if (tftpHdr->block_num != SWAP16(1))
316161196Simp					break;
317161196Simp				serverPort = udpHdr->src_port;
318161196Simp				ackBlock = 0;
319161196Simp			}
320157873Simp
321157873Simp			if (serverPort != udpHdr->src_port)
322157873Simp				break;
323157873Simp
324157873Simp			TFTP_ACK_Data(tftpHdr->data,
325161196Simp			    SWAP16(tftpHdr->block_num),
326161196Simp			    SWAP16(udpHdr->udp_len) - 12);
327157873Simp		}
328157873Simp	}
329157873Simp	p_rxBD[process].address &= ~0x01;
330161196Simp	return (1);
331157873Simp}
332157873Simp
333157873Simp
334157873Simp/*
335157873Simp * .KB_C_FN_DEFINITION_START
336157873Simp * unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
337157873Simp *  This private function reads the PHY device.
338157873Simp * .KB_C_FN_DEFINITION_END
339157873Simp */
340165401Simp#ifndef BOOT_BWCT
341157873Simpstatic unsigned short
342157873SimpAT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
343157873Simp{
344157873Simp	unsigned value = 0x60020000 | (addr << 18);
345157873Simp
346157873Simp	pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
347157873Simp	pEmac->EMAC_MAN = value;
348157873Simp  	while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
349157873Simp	pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
350157873Simp	return (pEmac->EMAC_MAN & 0x0000ffff);
351157873Simp}
352165401Simp#endif
353157873Simp
354161196Simp/*
355161196Simp * .KB_C_FN_DEFINITION_START
356165401Simp * unsigned short AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
357165401Simp *  This private function writes the PHY device.
358161196Simp * .KB_C_FN_DEFINITION_END
359161196Simp */
360161196Simp#ifdef BOOT_TSC
361161196Simpstatic unsigned short
362161196SimpAT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
363161196Simp{
364161196Simp	unsigned value = 0x50020000 | (addr << 18) | s;
365157873Simp
366161196Simp	pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
367161196Simp	pEmac->EMAC_MAN = value;
368161196Simp  	while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
369161196Simp	pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
370161196Simp	return (pEmac->EMAC_MAN & 0x0000ffff);
371161196Simp}
372161196Simp#endif
373161196Simp
374157873Simp/*
375157873Simp * .KB_C_FN_DEFINITION_START
376157873Simp * void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
377157873Simp *  This private function determines the link speed set by the PHY.
378157873Simp * .KB_C_FN_DEFINITION_END
379157873Simp */
380157873Simpstatic void
381157873SimpMII_GetLinkSpeed(AT91PS_EMAC pEmac)
382157873Simp{
383171426Simp#if defined(BOOT_TSC) || defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
384161196Simp	unsigned short stat2;
385165401Simp#endif
386161196Simp	unsigned update;
387161196Simp#ifdef BOOT_TSC
388161196Simp	unsigned sec;
389161196Simp	int i;
390161196Simp#endif
391165401Simp#ifdef BOOT_BWCT
392165401Simp	/* hardcoded link speed since we connect a switch via MII */
393165401Simp	update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
394165401Simp	update |= AT91C_EMAC_SPD;
395165401Simp	update |= AT91C_EMAC_FD;
396165401Simp#endif
397171426Simp#if defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
398157873Simp	stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
399161196Simp	if (!(stat2 & MII_STS2_LINK))
400157873Simp		return ;
401161196Simp	update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
402161196Simp	if (stat2 & MII_STS2_100TX)
403157873Simp		update |= AT91C_EMAC_SPD;
404161196Simp	if (stat2 & MII_STS2_FDX)
405161196Simp		update |= AT91C_EMAC_FD;
406161196Simp#endif
407161196Simp#ifdef BOOT_TSC
408161196Simp	while (1) {
409161196Simp		for (i = 0; i < 10; i++) {
410161196Simp			stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
411161196Simp			if (stat2 & MII_STS_LINK_STAT)
412161196Simp				break;
413161196Simp			printf(".");
414161196Simp			sec = GetSeconds();
415168013Simp			while (GetSeconds() == sec)
416168013Simp			    continue;
417157873Simp		}
418161196Simp		if (stat2 & MII_STS_LINK_STAT)
419161196Simp			break;
420161196Simp		printf("Resetting MII...");
421161196Simp		AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
422161196Simp		while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
423161196Simp	}
424161196Simp	printf("emac: link");
425161196Simp	stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
426161196Simp	update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
427161196Simp	if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
428161196Simp		printf(" 100TX");
429161196Simp		update |= AT91C_EMAC_SPD;
430161196Simp	}
431161196Simp	if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
432161196Simp		printf(" FDX");
433157873Simp		update |= AT91C_EMAC_FD;
434157873Simp	}
435163533Simp	printf("\n");
436161196Simp#endif
437161196Simp	pEmac->EMAC_CFG = update;
438157873Simp}
439157873Simp
440157873Simp
441157873Simp/*
442157873Simp * .KB_C_FN_DEFINITION_START
443157873Simp * void AT91F_EmacEntry(void)
444157873Simp *  This private function initializes the EMAC on the chip.
445157873Simp * .KB_C_FN_DEFINITION_END
446157873Simp */
447157873Simpstatic void
448157873SimpAT91F_EmacEntry(void)
449157873Simp{
450157873Simp	unsigned	i;
451157873Simp	char		*pRxPacket = (char*)RX_DATA_START;
452157873Simp	AT91PS_EMAC	pEmac = AT91C_BASE_EMAC;
453157873Simp
454163533Simp	p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
455163533Simp	localPort = SWAP16(0x8002);
456163533Simp
457157873Simp	for (i = 0; i < MAX_RX_PACKETS; ++i) {
458161196Simp
459157873Simp		p_rxBD[i].address = (unsigned)pRxPacket;
460157873Simp		p_rxBD[i].size = 0;
461157873Simp		pRxPacket += RX_PACKET_SIZE;
462157873Simp	}
463157873Simp
464157873Simp	// Set the WRAP bit at the end of the list descriptor
465157873Simp	p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
466157873Simp
467161196Simp	if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
468157873Simp		MII_GetLinkSpeed(pEmac);
469157873Simp
470157873Simp	pEmac->EMAC_RBQP = (unsigned) p_rxBD;
471157873Simp	pEmac->EMAC_RSR  |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
472161196Simp	pEmac->EMAC_CTL  = AT91C_EMAC_TE | AT91C_EMAC_RE;
473157873Simp
474157873Simp	pEmac->EMAC_TAR = (unsigned)transmitBuffer;
475157873Simp}
476157873Simp
477157873Simp
478157873Simp/* ************************** GLOBAL FUNCTIONS ********************************/
479157873Simp
480157873Simp/*
481157873Simp * .KB_C_FN_DEFINITION_START
482157873Simp * void SetServerIPAddress(unsigned address)
483157873Simp *  This global function sets the IP of the TFTP download server.
484157873Simp * .KB_C_FN_DEFINITION_END
485157873Simp */
486157873Simpvoid
487157873SimpSetServerIPAddress(unsigned address)
488157873Simp{
489157873Simp	// force update in case the IP has changed
490157873Simp	serverMACSet = 0;
491161196Simp
492161196Simp	serverIPAddr[0] = (address >> 24) & 0xFF;
493161196Simp	serverIPAddr[1] = (address >> 16) & 0xFF;
494161196Simp	serverIPAddr[2] = (address >>  8) & 0xFF;
495161196Simp	serverIPAddr[3] = (address >>  0) & 0xFF;
496161196Simp
497161196Simp	serverIPSet = 1;
498157873Simp}
499157873Simp
500157873Simp
501157873Simp/*
502157873Simp * .KB_C_FN_DEFINITION_START
503157873Simp * void SetLocalIPAddress(unsigned address)
504157873Simp *  This global function sets the IP of this module.
505157873Simp * .KB_C_FN_DEFINITION_END
506157873Simp */
507157873Simpvoid
508157873SimpSetLocalIPAddress(unsigned address)
509157873Simp{
510157873Simp	// force update in case the IP has changed
511157873Simp	serverMACSet = 0;
512161196Simp
513161196Simp	localIPAddr[0] = (address >> 24) & 0xFF;
514161196Simp	localIPAddr[1] = (address >> 16) & 0xFF;
515161196Simp	localIPAddr[2] = (address >>  8) & 0xFF;
516161196Simp	localIPAddr[3] = (address >>  0) & 0xFF;
517161196Simp
518161196Simp	localIPSet = 1;
519157873Simp}
520157873Simp
521157873Simp
522157873Simp/*
523157873Simp * .KB_C_FN_DEFINITION_START
524157873Simp * void TFTP_Download(unsigned address, char *filename)
525157873Simp *  This global function initiates and processes a tftp download request.
526157873Simp * The server IP, local IP, local MAC must be set before this function is
527157873Simp * executed.
528157873Simp * .KB_C_FN_DEFINITION_END
529157873Simp */
530157873Simpvoid
531157873SimpTFTP_Download(unsigned address, char *filename)
532157873Simp{
533161196Simp	ip_header_t 	IpHeader;
534161196Simp	unsigned	thisSeconds;
535161196Simp	int		timeout;
536157873Simp
537161196Simp	if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
538157873Simp		return ;
539157873Simp
540157873Simp	AT91F_EmacEntry();
541157873Simp	GetServerAddress();
542157873Simp	dlAddress = (char*)address;
543157873Simp	lastSize = 0;
544157873Simp	timeout = 10;
545168013Simp	thisSeconds = (GetSeconds() + 2) % 32;
546157873Simp	serverPort = SWAP16(69);
547161196Simp	++localPort;
548157873Simp	ackBlock = -1;
549157873Simp
550161196Simp	while (timeout) {
551161196Simp		if (CheckForNewPacket(&IpHeader)) {
552161196Simp			if (ackBlock == -2)
553161196Simp				break;
554161196Simp			timeout = 10;
555168013Simp			thisSeconds = (GetSeconds() + 2) % 32;
556168013Simp		} else if (GetSeconds() == thisSeconds) {
557157873Simp			--timeout;
558168013Simp			thisSeconds = (GetSeconds() + 2) % 32;
559161196Simp			if (!serverMACSet)
560161196Simp				GetServerAddress();
561161196Simp			else if (ackBlock == -1)
562161196Simp				TFTP_RequestFile(filename);
563161196Simp			else {
564161196Simp				// Be sure to send a NAK, which is done by
565161196Simp				// ACKing the last block we got.
566161196Simp				TFTP_ACK_Data(0, ackBlock, 512);
567163533Simp				printf("\nNAK %u\n", ackBlock);
568161196Simp			}
569157873Simp		}
570157873Simp	}
571161196Simp	if (timeout == 0)
572163533Simp		printf("TFTP TIMEOUT!\n");
573157873Simp}
574