int tftp_download(char *filename, ulong msec_max, int cnt_max, ulong addr)
{
...
TftpRRQTimeoutMSecs = msec_max; //100
TftpRRQTimeoutCountMax = cnt_max; //0
setenv("netretry", "no");
load_addr = addr; //下载到内存的地址
copy_filename(BootFile, filename, sizeof(BootFile));
size = NetLoop(TFTP);
if(size < 0)
return ERROR;
else
flush_cache(addr,size);
...
}
int NetLoop(proto_t protocol)
{
...
switch (protocol)
{
case TFTP:
TftpStart();
break;
case DHCP:
BootpTry = 0;
NetOurIP = 0;
DhcpRequest();
break;
case BOOTP:
BootpTry = 0;
NetOurIP = 0;
BootpRequest ();
break;
case RARP:
RarpTry = 0;
NetOurIP = 0;
RarpRequest ();
break;
case PING:
PingStart();
break;
case NFS:
NfsStart();
break;
case CDP:
CDPStart();
break;
case NETCONS:
NcStart();
break;
case SNTP:
SntpStart();
break;
case DNS:
DnsStart();
break;
}
...
}
void TftpStart (void)
{
...
//设置参数
NetSetTimeout (TftpTimeoutMSecs * CFG_HZ, TftpTimeout);
NetSetHandler (TftpHandler);
...
//发送
TftpSend ();
...
}
static void TftpSend (void)
{
...
//容错
//开始组包
pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
//针对各种状态组包
switch (TftpState)
{
case STATE_RRQ:
xp = pkt;
s = (ushort *)pkt;
if(TftpState == STATE_WRQ)
*s++ = htons(TFTP_WRQ);
else
*s++ = htons(TFTP_RRQ);
pkt = (uchar *)s;
strcpy ((char *)pkt, tftp_filename);
pkt += strlen(tftp_filename) + 1;
strcpy ((char *)pkt, "octet");
pkt += 5 /*strlen("octet")*/ + 1;
strcpy ((char *)pkt, "timeout");
pkt += 7 /*strlen("timeout")*/ + 1;
sprintf((char *)pkt, "%lu", TftpTimeoutMSecs / 1000);
pkt += strlen((char *)pkt) + 1;
memcpy((char *)pkt, "tsize 000 ", 8);
pkt += 8;
if(TftpState == STATE_WRQ)
pkt += sprintf((char *)pkt,"blksize%c%d%c", 0,TftpBlkSizeOption,0);
else
pkt += sprintf((char *)pkt,"blksize%c%d%c", 0,TftpBlkSizeOption,0);
if (!ProhibitMcast && (Bitmap=malloc(Mapsize)) && eth_get_dev()->mcast)
{
free(Bitmap);
Bitmap=NULL;
pkt += sprintf((char *)pkt,"multicast%c%c",0,0);
}
len = pkt - xp;
break;
case STATE_WRQ:
...
case STATE_OACK:
...
case STATE_DATA:
...
case STATE_TOO_LARGE:
...
case STATE_BAD_MAGIC:
...
case STATE_ACK:
...
}
//发送
NetSendUDPPacket(NetServerEther, TftpServerIP, TftpServerPort, TftpOurPort, len);
}
int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
{
//容错:目标IP
//容错:ether 发ARP
if (memcmp(ether, NetEtherNullAddr, 6) == 0)
{
NetArpWaitPacketIP = dest;
NetArpWaitPacketMAC = ether;
pkt = NetArpWaitTxPacket;
pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP);
NetSetIP (pkt, dest, dport, sport, len);
memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
NetArpWaitTry = 1;
NetArpWaitTimerStart = get_timer(0);
ArpRequest();
return 1;
}
//容错:time 发ARP
if (times == 10000)
{
times = 0;
NetArpWaitPacketIP = dest;
NetArpWaitPacketMAC = ether;
pkt = NetArpWaitTxPacket;
pkt += NetSetEther(pkt, NetArpWaitPacketMAC, PROT_IP);
NetSetIP(pkt, dest, dport, sport, len);
memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len);
NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len;
NetArpWaitTry = 1;
NetArpWaitTimerStart = get_timer(0);
ArpRequest();
}
//组包发送
times++;
pkt = (uchar *)NetTxPacket;
pkt += NetSetEther (pkt, ether, PROT_IP);
NetSetIP (pkt, dest, dport, sport, len);
(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);
...
}
至此,(void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len);开始转向各个网卡驱动的发送函数。