1/******************************************************************************* 2 * 3 * Filename: emac.c 4 * 5 * Instantiation of routines for MAC/ethernet functions supporting tftp. 6 * 7 * Revision information: 8 * --- 5 unchanged lines hidden (view full) --- 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 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 |
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]; |
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/* --- 27 unchanged lines hidden (view full) --- 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 |
84 memcpy(p_ARP->src_mac, localMACAddr, 6); |
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 |
93 memcpy(p_ARP->sender_mac, localMACAddr, 6); 94 memcpy(p_ARP->sender_ip, localIPAddr, 4); |
95 p_memset((char*)p_ARP->target_mac, 0, 6); |
96 memcpy(p_ARP->target_ip, serverIPAddr, 4); |
97 |
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 --- 7 unchanged lines hidden (view full) --- 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 |
121 memcpy(macHdr->dest_mac, serverMACAddr, 6); 122 memcpy(macHdr->src_mac, localMACAddr, 6); |
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 |
136 memcpy(ipHdr->ip_src, localIPAddr, 4); 137 memcpy(ipHdr->ip_dst, 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 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; --- 20 unchanged lines hidden (view full) --- 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 = 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 --- 5 unchanged lines hidden (view full) --- 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 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\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 --- 16 unchanged lines hidden (view full) --- 244 process = 1; 245 (*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR); 246 break; 247 } 248 } 249 250 if (!process) 251 return (0); |
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; |
268 memcpy(serverMACAddr, p_ARP->sender_mac, 6); |
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 --- 14 unchanged lines hidden (view full) --- 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); |
299 memcpy(pHeader, pIpHeader, sizeof(ip_header_t)); |
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 --- 108 unchanged lines hidden (view full) --- 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 } |
424 printf("\n"); |
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 --- 94 unchanged lines hidden (view full) --- 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\n", ackBlock); |
557 } 558 } 559 } 560 if (timeout == 0) |
561 printf("TFTP TIMEOUT!\n"); |
562} |