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

📄 networkstack.c

📁 WWVB receiver using AVR.
💻 C
📖 第 1 页 / 共 2 页
字号:
		net_pings++;#endif	}}static void net_handleudp(uint8_t hlen) {	/* UDP: IP Header +	 *  0 -  1:  srcport	 *  2 -  3:  dstport	 *  4 -  5:  length including header (>= 8)	 *  6 -  7:  checksum	 *  8 -  X:  data */	if ((net_packet[hlen+2] == 0) && (net_packet[hlen+3] == 123)) {		/* This goes to the NTP port */		struct tickdata td;		uint16_t cs;		uint32_t tstmp;		uint8_t dcfv = dcfvalid;		gettickdata(&td);		if (dcftime[dcfv].timestamp == 0) {			/* Oups, we have no signal yet - do not reply,			 * since we have no idea what day or time it is			 * without receiving the signal */			return;		}		if ((net_packet[hlen] == 0) && (net_packet[hlen+1] == 0)) {			/* No sourceport - so we don't know where to send a reply */			return;		}		if ((net_packet[hlen+8] & 0x07) > 0x06) {			/* We cannot handle mode 6 (control messages) */		}		swapdestandsrceth();		swapdestandsrcip();		net_packet[hlen+2] = net_packet[hlen];		net_packet[hlen+3] = net_packet[hlen+1];		net_packet[hlen] = 0; net_packet[hlen+1] = 123;		net_packet[hlen+4] = 0; net_packet[hlen+5] = 56;		net_packet[hlen+8] = 0x1c; /* Flags: No Leap, V3, Server */		net_packet[hlen+9] = 1; /* Stratum */		if ((net_packet[hlen+10] < 4) || (net_packet[hlen+10] > 10)) {			net_packet[hlen+10] = 6; /* Poll Interval (64 sec) */		}		net_packet[hlen+11] = 0xee; /* Precision (Yes, this is a lie) */		memset(&net_packet[hlen+12], 0, 8); /* 8 bytes of 0 */		net_packet[hlen+14] = 0x04; /* These must not be 0 though, */		net_packet[hlen+18] = 0x04; /* so we fill in dummys */		net_packet[hlen+20] = 'D';		net_packet[hlen+21] = 'C';		net_packet[hlen+22] = 'F';		net_packet[hlen+23] = 0;		tstmp = dcftime[dcfv].timestamp + 2208988800UL; /* Yes, this WILL overflow in 2036 */		if (dcftime[dcfv].issummertime) { /* Summertime: -3600 */			tstmp -= 3600UL;		}		/* Reference Timestamp */		net_packet[hlen+24] = (uint8_t)(tstmp >> 24);		net_packet[hlen+25] = (uint8_t)(tstmp >> 16);		net_packet[hlen+26] = (uint8_t)(tstmp >>  8);		net_packet[hlen+27] = (uint8_t)(tstmp      );		memset(&net_packet[hlen+28], 0, 4);		/* Originate Timestamp */		memcpy(&net_packet[hlen+32], &net_packet[hlen+48], 8);		/* Receive and Transmit Timestamp */		tstmp += ((uint16_t)(td.seconds - dcftime[dcfv].ticksecs));		net_packet[hlen+40] = net_packet[hlen+48] = (uint8_t)(tstmp >> 24);		net_packet[hlen+41] = net_packet[hlen+49] = (uint8_t)(tstmp >> 16);		net_packet[hlen+42] = net_packet[hlen+50] = (uint8_t)(tstmp >>  8);		net_packet[hlen+43] = net_packet[hlen+51] = (uint8_t)(tstmp      );		/* Set fraction in hlen+44 and hlen+52 */		tstmp = td.ticks;		tstmp = (tstmp << 16) / TICKSPERSECOND;		tstmp <<= 16;		net_packet[hlen+44] = net_packet[hlen+52] = (uint8_t)(tstmp >> 24);		net_packet[hlen+45] = net_packet[hlen+53] = (uint8_t)(tstmp >> 16);		net_packet[hlen+46] = net_packet[hlen+54] = (uint8_t)(tstmp >>  8);		net_packet[hlen+47] = net_packet[hlen+55] = (uint8_t)(tstmp      );		/* IP header checksum */		net_packet[24] = net_packet[25] = 0;		cs = net_calcipchecksum(&net_packet[14], (hlen - 14));		net_packet[24] = cs & 0xff;		net_packet[25] = cs >> 8;		/* UDP checksum */		net_packet[hlen+6] = net_packet[hlen+7] = 0;		/* We have to add the "pseudo header" - what a piece of		 * crap... */		memcpy(&net_packet[hlen+56], &net_packet[26], 8);		net_packet[hlen+64] = 0; net_packet[hlen+65] = 56;		net_packet[hlen+66] = 0; net_packet[hlen+67] = 17;		cs = net_calcipchecksum(&net_packet[hlen], 68);		net_packet[hlen+6] = cs & 0xff;		net_packet[hlen+7] = cs >> 8;		net_sendpacket(net_packet, hlen + 56);		led_statusleds |= led_status_netntp;#ifdef NETWORKSTATS		net_ntpqs++;#endif	} else if ((net_packet[hlen+2] == 0x7a) && (net_packet[hlen+3] == 0x69)) {		/* Port 31337 can be used to send commands (with password) */		/* Nothing fancy here, structure of the packet is simple:		 * byte  8 - 16  password (8 characters + terminating \0)		 * byte 17       command:		 *                1 == display text		 * byte 18 - X   additional data for commands		 * for command  1: byte 18 - 24  text to display.		 */		if (memcmp(&net_packet[hlen+8], net_rconpass, 8)) {			/* Password incorrect */			return;		}		led_statusleds |= led_status_netrcon;		switch (net_packet[hlen+17]) {		case 1: /* Command "Display Text" */			memcpy(&led_dispoverride[0], &net_packet[hlen+18], 7);			if ((net_packet[hlen+25] <= 0) || (net_packet[hlen+25] > 60)) {				led_dispovcnt = 30; /* 5 seconds */			} else {				led_dispovcnt = net_packet[hlen+25];			}			break;		case 2: /* Command "Set Display Brightness" */			led_brightness = net_packet[hlen+18];			break;#ifdef CLOCKFACEMODULE		case 3: /* Command "Set Clockface Brightness" */			clockface_brightness = net_packet[hlen+18];			break;#endif /* CLOCKFACEMODULE */		};#ifdef NETWORKSTATS		net_rcons++;#endif /* def NETWORKSTATS */#ifndef NET_NODPORTUNREACH	} else {		uint16_t i;		/* Send back ICMP Port unreachable, unless packet is too		 * large. */		if (net_recvdbytes > 200) {			return;		}		for (i = (net_recvdbytes-5); i >= 14; i--) {			net_packet[i+hlen+8-14] = net_packet[i];		}		net_recvdbytes += (hlen + 8);		net_recvdbytes -= (14 + 4);		/* And alter the header */		swapdestandsrceth();		swapdestandsrcip();		net_packet[23] = 1; /* We're now an ICMP packet */		net_packet[22] = 0x40; /* With a lot of TTL */		net_packet[17] += hlen + 8 - 14; /* And a new length */		net_packet[24] = net_packet[25] = 0;		i = net_calcipchecksum(&net_packet[14], hlen-14);		net_packet[24] = i & 0xff;		net_packet[25] = i >> 8;		/* Now fill in the first 8 bytes after header */		net_packet[hlen  ] = 0x03; /* "Unreachable" */		net_packet[hlen+1] = 0x03; /* Type "Port" -> Port Unreach */		memset(&net_packet[hlen+2], 0, 6);		i = net_calcipchecksum(&net_packet[hlen], (net_recvdbytes - hlen));		net_packet[hlen+2] = i & 0xff;		net_packet[hlen+3] = i >> 8;		net_sendpacket(net_packet, net_recvdbytes);#endif /* ndef NET_NODPORTUNREACH */	}}/* The name "HANDLEtcp" might be a bit misleading, because all this * actually does is to send back a TCP Reset */#ifndef NET_NOTCPRESETvoid net_handletcp(uint8_t hlen) {	uint16_t i;	i = *((uint16_t *)(&net_packet[hlen]));	*((uint16_t *)(&net_packet[hlen])) = *((uint16_t *)(&net_packet[hlen+2]));	*((uint16_t *)(&net_packet[hlen+2])) = i;	for (i=0; i<4; i++) {		net_packet[hlen+i+8] = net_packet[hlen+i+4];		net_packet[hlen+i+4] = 0;	}	net_packet[hlen+12] = 0x50;	net_packet[hlen+13] = 0x14;	memset(&net_packet[hlen+14], 0, 6);	/* checksum @ 16+17 */	/* add the "pseudo header" for checksum calculation */	memcpy(&net_packet[hlen+20], &net_packet[26], 8);	net_packet[hlen+28] = 0; net_packet[hlen+29] = 20; /* tcp length */	net_packet[hlen+30] = 0; net_packet[hlen+31] = 6; /* prot. number */	i = net_calcipchecksum(&net_packet[hlen], 32);	net_packet[hlen+16] = i & 0xff;	net_packet[hlen+17] = i >> 8;	swapdestandsrceth();	swapdestandsrcip();	net_packet[24] = net_packet[25] = 0;	i = net_calcipchecksum(&net_packet[14], (hlen - 14));	net_packet[24] = i & 0xff;	net_packet[25] = i >> 8;	net_sendpacket(net_packet, hlen+20);}#endif /* ndef NET_NOTCPRESET */void net_handleip(void) {	uint8_t hlen; /* Header length (Points to start of actual data) */	if (memcmp(&net_packet[30], net_ip, 4)) {		/* Not for us */		return;	}	if ((net_packet[14] & 0xf0) != 0x40) {		/* Not IPv_4_ */		return;	}	hlen = ((net_packet[14] & 0x0f) << 2) + 14;	if (((net_packet[20] & 0xBF) != 0x00) || (net_packet[21] != 0x00)) {		/* We cannot handle fragmentation. */		return;	}	/* That should be enough sanity checks for now */	if (net_packet[23] == 1) { /* Protocol ICMP */		net_handleicmp(hlen);	} else if (net_packet[23] == 17) { /* Protocol UDP */		net_handleudp(hlen);#ifndef NET_NOTCPRESET	} else if (net_packet[23] == 6) { /* Protocol TCP */		net_handletcp(hlen);#endif /* ndef NET_NOTCPRESET */	}}void net_handlereceivedpacket(void) {	/* For reference: Structure of a Ethernet Packet:	 * Destination		Byte  0 -  5	 * Source		Byte  6 - 11	 * Length/Type		Byte 12 - 13	 * Data			at least 46 Bytes */	if ((net_recvdbytes >= 64) && ((net_packet[6] & NET_MCASTBIT) == 0)) {		/* Packets shorter than 64 bytes are nonsense, and		 * Sanity check, so that we don't reply to		 * multi-/broadcast-addresses and create a flood */		if ((memcmp(net_packet, net_mac, 6) == 0)		 || ((net_packet[0] == 0xff) && (net_packet[1] == 0xff)		  && (net_packet[2] == 0xff) && (net_packet[3] == 0xff)		  && (net_packet[4] == 0xff) && (net_packet[5] == 0xff))) {			/* Addressed to our unicast address or			 * Addressed to broadcast */			/* check if it's ARP (type 0x0806)			 * or IP (type 0x0800) */			if ((net_packet[12] == 0x08) /* Protocol ARP */			 && (net_packet[13] == 0x06)) {				net_handlearp();			} else if ((net_packet[12] == 0x08) /* Protocol IP */				&& (net_packet[13] == 0x00)) {				net_handleip();			}		}	}}static void readmacfromeeprom(void) {	uint8_t i;	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_STOP | CMDR_NODMA);	/* select byte wide transfers */	writene2kreg(NEDCR, DCR_BYTEDMA | DCR_FIFO8 | DCR_NOLPBK);	writene2kreg(NERBCR0, 0);	writene2kreg(NERBCR1, 0);	writene2kreg(NEIMR, 0); /* no IRQs */	writene2kreg(NEISR, 0xff); /* ACK any irqs */	writene2kreg(NERCR, RCR_MONITOR); /* receive off */	writene2kreg(NETCR, TCR_INTLPBK); /* transmit off */	writene2kreg(NERBCR0, 32); /* Intend to read 32 Bytes */	writene2kreg(NERBCR1, 0);	writene2kreg(NERSAR0, 0); /* low byte of start address (0x0000) */	writene2kreg(NERSAR1, 0); /* high byte of start address */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_DMAREAD);	/* for some reason, 2 reads are required, otherwise you get duplicate	 * values. the comments in the linux driver talk about values being	 * "doubled up", but i don't know why. whatever - it works this way	 * and i don't have time to investigate :) */	for (i = 0; i < 6; i++) {		readne2kreg(NERDMA);		net_mac[i] = readne2kreg(NERDMA);	}	/* end (abort) the DMA transfer */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);}void net_init(void) {	uint8_t i;	/* my step 0a: force a hardware reset on the card */	isareset();	/* my step 0b: read mac address from the card's onboard eeprom */	readmacfromeeprom();	/* step 1: program command register for page 0	 * cheung, ns 0x21 */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_STOP | CMDR_NODMA);	/* cheung does a soft reset here... */	/* step 2: initialize data configuration register	 * cheung 0x48, ns 0x58 */	writene2kreg(NEDCR, DCR_BYTEDMA | DCR_FIFO8 | DCR_NOLPBK);	/* step 3: clear remote byte count registers	 * cheung, ns 0 */	writene2kreg(NERBCR0, 0);	writene2kreg(NERBCR1, 0);	/* step 4: initialize recieve configuration register	 * cheung: 0x0c, ns: 0, linux: 0x20 */	writene2kreg(NERCR, RCR_MONITOR); /* disable reception for now */	/* step 5: place the NIC in loopback mode (hey - don't i also have to set	 * a bit in DCR in order to go into loopback mode? hmm...) */	writene2kreg(NETCR, TCR_INTLPBK);	/* step 5 and a half: initialize the transmit buffer start page */	writene2kreg(NETPSR, TXSTART);	/* step 6: initialize receive buffer ring (256 byte blocks) 	 * cheung: start=0x40, stop=0x76 (or 0x7c?)	 * ns: start=0x26, stop=0x40	 * linux: 0x26/0x40 or 0x46/0x80 (NE1SM or NESM) */	writene2kreg(NEPSTA, RXSTART);	writene2kreg(NEBNRY, RXSTART);	writene2kreg(NEPSTO, RXSTOP);	/* step 7: clear interrupt status register	 * cheung: performs this step earlier (after step #3) */	writene2kreg(NEISR, 0xff);	/* step 8: initialize the interrupt mask register	 * cheung: 0 (out of order - after #7)	 * ns: 0x0b */	writene2kreg(NEIMR, 0); /* no interrupts, please */	/* step 9a: go to register page 1 */	writene2kreg(NECMDR, CMDR_PAGE1 | CMDR_STOP | CMDR_NODMA);	/* step 9b: initialize hardware address	 * (what?! shouldn't this already be set from EEPROM?) */	for (i=0; i<6; i++) {		writene2kreg(NEPAR0 + i, net_mac[i]);	}	/* step 9c: initialize multicast address (i don't care about multicast) */	/* ... not implemented ... */	/* step 9d: initialize CURRent pointer */	writene2kreg(NECURR, RXSTART + 1);	/* step 10: put NIC in START mode */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);	/* step 11: initialize transmit control register (disable loopback mode) */	writene2kreg(NETCR, TCR_NOLPBK);	/* should i re-set DCR here to cancel loopback? */	/* my step 12: initialize recieve configuration register so that we	 * can  get packets */	writene2kreg(NERCR, RCR_BCAST);	/* cheung reads the mac address from eeprom here. seems too late to me! */	/* FIXME? Enable ISA IRQs? the IRQ line is connected to PD4 */}

⌨️ 快捷键说明

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