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}
|