⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ether.c

📁 mips架构的bootloader,99左右的版本 但源代码现在没人更新了
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************* * File: lib/ether.c * Purpose: common ethernet functions * Author: Phil Bunce (pjb@carmel.com) * Revision History: *	980615	Created from sonic.c *	981127	Moved the GETRXREC swapPkt here from drivers. *//* This module contains all of the chip-independent code needed to * PMON/IMON with an Ethernet download facility.  The code is rather  * primitive, it only understands UDP and ARP messages, and is only * able to send two types of packet (UDP REPLY and ARP REPLY). The * ether_xxx functions are performed by either sonic.c or am79970.c. */#include <defines.h>#ifdef ETHERNET/*#define VERBOSE   	/* be verbose */#include <mon.h>#include <termio.h>#include <ether.h>#ifdef CHECKS_ON#include <assert.h>#else#define assert(x)#endif#define swap32(n) ( \	((((Ulong)(n))>>24)&0x000000ff) | \	((((Ulong)(n))>>8)&0x0000ff00) |  \	((((Ulong)(n))<<8)&0x00ff0000) |  \	((((Ulong)(n))<<24)&0xff000000)   \	)#define swap16(n) ( \	((((Ushort)(n))>>8)&0x00ff) | \	((((Ushort)(n))<<8)&0xff00)   \	)#define ether_driver(a,b,c)	(*ether_driver_ptr)(a,b,c)/* This is how you call the chip-dependent code. ether_driver_ptr * should have been initialized by your cpu-dependent module (eg. c4101.c), * to point to the appropriate driver (eg. sonic_driver). */vpFunc *ether_driver_ptr;static Ushort last_udp_seqno;static char *last_dest_addr;static Ushort tx_ip_id;static char *rx_byte_ptr;static int rx_byte_cnt;static int dotcnt;static RXREC *rx_desc;static char *dest_addr;static Uchar EnetAddr[6]; /* the MAC address */static filbuf();char *getMsg();#ifdef VERBOSEstatic printIp();static printUdp();static printArp();#endifextern int re_ether;extern int vflag;/**************************************************************  ether_open(etheraddr)*	Just like the standard open() except that it opens the*	Ethernet controller.*	'etheraddr' is a string containing the MAC address in the*	form aa:bb:cc:dd:ee:ff.*/ether_open(etheraddr)char *etheraddr;{char tmp[30],*p;int i,n;if (etheraddr == 0 || ether_driver_ptr == 0) return(-1);rx_byte_cnt = 0;rx_desc = 0;/* convert the mac address string into an array of 6 bytes */strcpy(tmp,etheraddr);for (i=0,p=strtok(tmp,":");p;p=strtok(0,":"),i++) {	sscanf(p,"%x",&n);	EnetAddr[i] = n; 	}if (!ether_driver(ETHER_INIT,EnetAddr,0)) return(-1);flush_cache(DCACHE);return(ETHERFD);}/**************************************************************  ether_close()*	Just like the standard close() except that it closes the*	Ethernet controller.*/ether_close(){char *rxptr;int len;if (rx_desc) {	rxptr = (char *)ether_driver(ETHER_GETRBA,rx_desc,&len);	sendAck(rxptr,len);	ether_driver(ETHER_RXDONE,rx_desc,0);	}}/**************************************************************  ether_read(fd,ptr,size)*	Just like the standard read() except that it reads from the*	Ethernet controller.*/ether_read(fd,ptr,size)int fd,size;char *ptr;{int i,c;for (i=0;i<size;) {	c = ((rx_byte_cnt--)?*rx_byte_ptr++:filbuf(0));	ptr[i++] = c;	if (c == '\n') break;	}return(i);}/**************************************************************  ether_bcopy()*	supports "load -B", binary mode transfers*/ether_bcopy(){for (;;) {	filbuf(1);	bcopy(rx_byte_ptr,dest_addr,rx_byte_cnt);	dest_addr += rx_byte_cnt;	}}/**************************************************************  filbuf(no_rtn)*	Called when the buffer runs out of bytes.*	It gets a packet of data and transfers it to the*	buffer.*/static filbuf(no_rtn)int no_rtn;{RXREC *q;struct ether_header *e;char *rxptr;int len;if (rx_desc) {	rxptr = (char *)ether_driver(ETHER_GETRBA,rx_desc,&len);	sendAck(rxptr,len);	ether_driver(ETHER_RXDONE,rx_desc,0);	}while (1) {	while (!ether_driver(ETHER_RXRDY,0,0)) {		dotcnt--;		if (dotcnt <= 0) {			scandevs();			dotcnt = 100000;			}		}	if (!(q=(RXREC *)ether_driver(ETHER_GETRXREC,0,0))) continue;	e = (struct ether_header *)ether_driver(ETHER_GETRBA,q,&len);#ifndef MIPSEB	if (!swapPkt(phy2k1(e))) {		ether_driver(ETHER_RXDONE,(void *)q,0);		continue;		}#endif#ifdef VERBOSE	if (vflag) printPkt(e);#endif	if (e->ether_type == ETHERTYPE_ARP) {		arpRequest(e);		ether_driver(ETHER_RXDONE,q,0);		continue;		}	rx_byte_ptr = getMsg(e,len,&rx_byte_cnt);	if (rx_byte_ptr) break;	ether_driver(ETHER_RXDONE,q,0);	}assert(rx_byte_cnt != 0);rx_desc = q;if (no_rtn) return(0);rx_byte_cnt--;return(*rx_byte_ptr++);}/**************************************************************  sendAck(re,len)*	send an ACK back to the host*/sendAck(re,len)struct ether_header *re;Ushort len;{int i,n;Ushort *sp;Ulong t;struct ether_header *te;struct ip *ti,*ri;struct udphdr *tu,*ru;if (vflag) {	printf("sendAck(%08x,%d)\n",re,len);	printMem((char *)re,len);	}assert(re != 0);n = 64;te = (struct ether_header *) ether_driver(ETHER_GETTBA,0,&n);te->ether_shost = re->ether_dhost;te->ether_dhost = re->ether_shost;te->ether_type = re->ether_type;ti = (struct ip *) (te+1);ri = (struct ip *) (re+1);ti->ip_vhl = ri->ip_vhl;ti->ip_tos = ri->ip_tos;ti->ip_len = sizeof(struct ip)+sizeof(struct udphdr);ti->ip_id = tx_ip_id++;ti->ip_off = 0;ti->ip_ttl = UDP_TTL;ti->ip_p = IP_UDP;bcopy(&(ri->ip_dst.s_addr),&(ti->ip_src.s_addr),sizeof(struct in_addr));bcopy(&(ri->ip_src.s_addr),&(ti->ip_dst.s_addr),sizeof(struct in_addr));tu = (struct udphdr *) (ti+1);ru = (struct udphdr *) (ri+1);tu->uh_sport = ru->uh_sport;tu->uh_dport = ru->uh_sport;tu->uh_ulen = 12;tu->uh_sum = 0; /* haven't figured this out, try zero */tu->uh_type = UDP_ACK;tu->uh_seqno = 0;if (ru->uh_type == UDP_DATA) tu->uh_seqno = ru->uh_seqno;#ifndef MIPSEBunswapPkt(te);#endif/* compute csum of ip hdr -> t */ti->ip_sum = 0;sp = (Ushort *) ti;for (i=0,t=0;i<(sizeof(struct ip)/sizeof(Ushort));i++,sp++) t += *sp;t = (t&0xffff)+(t>>16);ti->ip_sum = ~t;if (vflag) printMem((char *)te,64);#ifdef VERBOSEif (vflag) printPkt(te,64);#endifif (re_ether) swap32n(te,64);ether_driver(ETHER_TBARDY,0,0);}/**************************************************************  char *getMsg(e,size,cnt)*	Interprets the packet. *	Is only able to understand UDP packets of type UDP_OPEN *	and UDP_DATA.*/char *getMsg(e,size,cnt)struct ether_header *e;Ushort size;int *cnt;{struct ip *i;struct udphdr *u;int minlen;*cnt = 0;assert(e != 0);minlen = sizeof(struct ether_header)+sizeof(struct ip)+sizeof(struct udphdr);assert(size >= minlen);i = (struct ip *)(e+1);if (pingRequest(e)) return(0);if (i->ip_p != IP_UDP) return(0);u = (struct udphdr *)(i+1);switch (u->uh_type) {	case UDP_OPEN : #ifndef MIPSEB		u->uh_seqno = swap16(u->uh_seqno);#endif		sscanf(&(u->uh_seqno),"%x",&dest_addr);		last_udp_seqno = 0;		tx_ip_id = i->ip_id;		sendAck(e,size);		return(0);	case UDP_DATA :		if (u->uh_seqno > last_udp_seqno) {			last_dest_addr = dest_addr;			last_udp_seqno = u->uh_seqno;			}		else {			/* retry packet */			dest_addr = last_dest_addr;			}		*cnt = u->uh_ulen-sizeof(struct udphdr);		return((char *)(u+1));	}return(0);}/**************************************************************  pingRequest(e)*/pingRequest(e)struct ether_header *e;{struct ether_header *te;struct ip *i,*ti;struct icmp *m,*tm;Ushort *sp;Ulong t;int n,len;if (e->ether_type != ETHERTYPE_IP) return(0);i = (struct ip *)(e+1);if (i->ip_p != IP_ICMP) return(0);m = (struct icmp *)(i+1);if (m->icmp_type != ICMP_ECHO) return(0);/* This is a ping request */len = i->ip_len+sizeof(struct ether_header);te = (struct ether_header *) ether_driver(ETHER_GETTBA,0,&len);te->ether_dhost = e->ether_shost;bcopy(EnetAddr,&(te->ether_shost),6);te->ether_type = e->ether_type;/* build ip header */ti = (struct ip *) (te+1);ti->ip_vhl = i->ip_vhl;ti->ip_tos = i->ip_tos;ti->ip_len = i->ip_len;ti->ip_id = i->ip_id;ti->ip_off = i->ip_off;ti->ip_ttl = i->ip_ttl;ti->ip_p = i->ip_p; /* proto */bcopy(&(i->ip_dst.s_addr),&(ti->ip_src.s_addr),sizeof(struct in_addr));bcopy(&(i->ip_src.s_addr),&(ti->ip_dst.s_addr),sizeof(struct in_addr));/* build icmp header */tm = (struct icmp *) (ti+1);tm->icmp_type = ICMP_ECHOREPLY;tm->icmp_code = m->icmp_code;tm->icmp_cksum = 0;tm->icmp_id = m->icmp_id;tm->icmp_seq = m->icmp_seq;bcopy(m->icmp_data,tm->icmp_data,i->ip_len-sizeof(struct ip));/* this is a hack. The real checksum calc appears to be 16-bit addstarting at icmp_type and continuing for 62 bytes. Then add 4. Write

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -