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
| 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 78 p_memcpy((char*)p_ARP->src_mac, (char*)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 87 p_memcpy((char*)p_ARP->sender_mac, (char*)localMACAddr, 6); 88 89 p_memcpy((char*)p_ARP->sender_ip, (char*)localIPAddr, 4); 90 91 p_memset((char*)p_ARP->target_mac, 0, 6); 92 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 118 p_memcpy((char*)macHdr->dest_mac, (char*)serverMACAddr, 6); 119 120 p_memcpy((char*)macHdr->src_mac, (char*)localMACAddr, 6); 121 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 135 p_memcpy((char*)ipHdr->ip_src, (char*)localIPAddr, 4); 136 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 148 p_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 185 ePtr = p_strcpy(cPtr, filename); 186 mPtr = p_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; 208 p_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; 219 printf("tftp: %u byte\r\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); 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; 269 270 p_memcpy((char*)serverMACAddr, 271 (char*)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); 302 p_memcpy((char*)pHeader, (char*)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 } 427 printf("\r\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 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
|