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

📄 networkstack.c

📁 WWVB receiver using AVR.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: networkstack.c,v 1.45 2005/10/30 21:06:14 simimeie Exp $ * Basic Network Stack. Handles ARP / IP. * * I need to give some credits here: * Most of the code here is basically a port of Dave Clausen's assembler * code, at the time of writing this available under the GPL from * http://www.dclausen.net/projects/avr_ethernet/index.html * There is a lot of code in C out on the internet for using a NE2000 from * an AVR, but his assembler code was way better commented, documented and * easier to understand than anything I could find in C. */  #define BV _BV#include <avr/io.h>#include <avr/delay.h>#include <string.h>#include "networkstack.h"#include "ledmodule.h"#include "debugconsole.h"#include "dcf77.h"#include "timers.h"#include "clockface.h"#ifdef NET_NOUSELESSCRAP#define NET_NOTCPRESET#define NET_NODPORTUNREACH#endif/* Network Configuration. This gets read from EEPROM, set it in eepromdata.h */uint8_t net_ip[4];#if 0uint8_t net_mask[4];uint8_t net_gate[4];#endifuint8_t net_mac[6];uint8_t net_rconpass[9];uint8_t net_packet[1518];uint16_t net_recvdbytes;#ifdef NETWORKSTATSuint32_t net_rxbytes; /* Received Bytes */uint32_t net_txbytes; /* Transmitted Bytes */uint32_t net_pings; /* ICMP Pings */uint32_t net_ntpqs; /* NTP Queries */uint32_t net_rcons; /* Remote Control Commands */#endif/* On our board, address pin 15 on the atmel goes to address pin 9 of the ISA * bus. * So every access to a memory address above 0x8000 goes to the ISA bus, and * accesses I/O Port (0x200 + (address % 0x200)) there. * So if your NE2000 is on I/O 0x300, set this to 0x8100 or 0x8300 * or 0x8500 or ... */#define NE2KBASE	0x8300/* Register Offsets */#define NECMDR	0x00	/* Command Register (page *)*/#define NEPSTA	0x01	/* Page Start Register (page 0 = w, page 2 = r) */#define NEPAR0	0x01	/* Physical Address Register Byte 0 (page 1 = rw) */#define NEPSTO	0x02	/* Page Stop Register (page 0 = w, page 2 = r) */#define NEBNRY	0x03	/* Boundary Register (page 0 = rw) */#define NETPSR	0x04	/* Transmit Page Start Register (page 0 = w) */#define NETBCR0	0x05	/* Transmit Byte Count Register 0 (page 0 = w) */#define NETBCR1	0x06	/* Transmit Byte Count Register 1 (page 0 = w) */#define NEISR	0x07	/* Interrupt Status Register */#define NECURR	0x07	/* Current Page Register (page 1 = rw) */#define NERSAR0	0x08	/* Remote Start Address Register 0 (page 0 = w) */#define NERSAR1	0x09	/* Remote Start Address Register 1 (page 0 = w) */#define NERBCR0	0x0A	/* Remote Byte Count Register 0 (page 0 = w) */#define NERBCR1	0x0B	/* Remote Byte Count Register 1 (page 0 = w) */#define NERCR	0x0C	/* Receive Control Register */#define NETCR	0x0D	/* Transmission Control Register */#define NEDCR	0x0E	/* Data Control Register */#define NEIMR	0x0F	/* Interrupt Mask Register */#define NERDMA	0x10	/* Remote DMA */#define NERESET	0x1f	/* Well guess, what does the "reset" register do? *//* Bit defines *//* For the command register */#define CMDR_STOP	0x01	/* Stop (Reset) NIC */#define CMDR_START	0x02	/* Start NIC */#define CMDR_TRANSMIT	0x04	/* Must be 1 to transmit packet */#define CMDR_DMAREAD	0x08	/* remote DMA read */#define CMDR_DMAWRITE	0x10	/* remote DMA write */#define CMDR_NODMA	0x20	/* abort/complete remote DMA */#define CMDR_PAGE0	0x00	/* select register page 0 */#define CMDR_PAGE1	0x40	/* select register page 1 */#define CMDR_PAGE2	0x80	/* select register page 2 *//* For the Receive Control Register */#define RCR_BCAST	0x04#define RCR_MCAST	0x08#define RCR_PROMISCUOUS	0x10#define RCR_MONITOR	0x20/* For the Data Control Register */#define DCR_BYTEDMA	0x00#define DCR_WORDDMA	0x01#define DCR_NOLPBK	0x08#define DCR_FIFO2	0x00#define DCR_FIFO4	0x20#define DCR_FIFO8	0x40#define DCR_FIFO12	0x60/* For the Transmission Control Register */#define TCR_NOLPBK	0x00#define TCR_INTLPBK	0x02#define TCR_EXTLPBK	0x04#define TCR_EXTLPBK2	0x06/* Address defines * These defines should be correct for most ne2k compatibles. * It seems they usually have RAM available between 0x4000 and 0x8000. * These values are page numbers, with a page being 256 (0x100 bytes). */#define RXSTART	0x46	/* Start of RX buffers */#define RXSTOP	0x5f	/* End of RX buffers */#define TXSTART	0x40	/* Start of TX buffers */static void isareset(void) {	uint16_t i;	/* PortD Pin 4 is ISA RESET */	DDRD |= BV(PD4);	PORTD |= BV(PD4);	for (i=0; i<20000; i++) {		_delay_loop_1(250);	}	PORTD &= (uint8_t)~BV(PD4);	for (i=0; i<20000; i++) {		_delay_loop_1(250);	}}static void writene2kreg(uint8_t nr, uint8_t val) {	*((volatile uint8_t *)(NE2KBASE + nr)) = val;}static uint8_t readne2kreg(uint8_t nr) {	return *((volatile uint8_t *)(NE2KBASE + nr));}void net_sendpacket(uint8_t * packet, uint16_t len) {	uint16_t i;	if (len < 0x40) { len = 0x40; }	i = 0;	/* If there is still a packet in transmission, wait until it's done! */	while ((i < 50000) && (readne2kreg(NECMDR) & CMDR_TRANSMIT)) {		i++;	}	/* Abort any currently running "DMA" operations */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);	writene2kreg(NERBCR0, len & 0xff);	writene2kreg(NERBCR1, len >> 8);	writene2kreg(NERSAR0, 0x00);	writene2kreg(NERSAR1, TXSTART);	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_DMAWRITE);	for (i = 0; i < len; i++) {		writene2kreg(NERDMA, packet[i]);	}	/* Wait for something here? */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);	writene2kreg(NETBCR0, len & 0xff);	writene2kreg(NETBCR1, len >> 8);	writene2kreg(NETPSR, TXSTART);	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_TRANSMIT);	led_statusleds |= led_status_nettx;#ifdef NETWORKSTATS	net_txbytes += len;#endif}uint16_t net_receivepacket(void) {	uint8_t curr, bnry;	net_recvdbytes = 0;	/* goto register page 1 */	writene2kreg(NECMDR, CMDR_PAGE1 | CMDR_START | CMDR_NODMA);	/* read the CURRent pointer */	curr = readne2kreg(NECURR);	/* goto register page 0 */	writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);	/* read the boundary pointer */	bnry = readne2kreg(NEBNRY) + 1;	if (bnry > RXSTOP - 1) { bnry = RXSTART; }	if (bnry != curr) { /* data available - read it */		uint16_t i;#if 0		debugconsole_printtext("P:");		debugconsole_printhex8(curr);		debugconsole_printtext(",");		debugconsole_printhex8(bnry);		debugconsole_printtext("->");#endif		/* i don't know how many bytes i intend to read, so just set		 * this to the maximum */		writene2kreg(NERBCR0, 0xff);		writene2kreg(NERBCR1, 0xff);		writene2kreg(NERSAR0, 0); /* low byte of start address (0) */		writene2kreg(NERSAR1, bnry); /* high byte of start address (BNRY) */		/* begin the dma read */		writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_DMAREAD);		readne2kreg(NERDMA); /* Status flags, throw away */		bnry = readne2kreg(NERDMA) - 1; /* next-pointer */		if (bnry < RXSTART) { bnry = RXSTOP - 1; }		net_recvdbytes = readne2kreg(NERDMA); /* receive byte count low */		net_recvdbytes |= (((uint16_t)readne2kreg(NERDMA)) << 8); /* receive byte count high */#if 0		debugconsole_printhex8(bnry);		debugconsole_printtext(" ");		debugconsole_printhex8(net_recvdbytes >> 8);		debugconsole_printhex8(net_recvdbytes & 0xff);		debugconsole_printtext("\r\n");#endif		if (net_recvdbytes > 1518) { net_recvdbytes = 1518; }		for (i = 0; i < net_recvdbytes; i++) {			net_packet[i] = readne2kreg(NERDMA);#if 0			debugconsole_printhex8(net_packet[i]);			if ((i % 20) == 0) {				debugconsole_printtext("\r\n");			}#endif		}		/* debugconsole_printtext("\r\n"); */		writene2kreg(NECMDR, CMDR_PAGE0 | CMDR_START | CMDR_NODMA);		/* write updated bnry pointer */		writene2kreg(NEBNRY, bnry);		led_statusleds |= led_status_netrx;#ifdef NETWORKSTATS		net_rxbytes += net_recvdbytes;#endif	}	return net_recvdbytes;}static void swapdestandsrceth(void) {	uint8_t c;	for (c = 0; c < 6; c++) {		/* set dst to src, and src to our mac */		net_packet[c] = net_packet[c+6];		net_packet[c+6] = net_mac[c];	}}static void swapdestandsrcarp(void) {	uint8_t c;		for (c = 0; c < 4; c++) {		net_packet[c+38] = net_packet[c+28];		net_packet[c+28] = net_ip[c];	}	for (c = 0; c < 6; c++) {		net_packet[c+32] = net_packet[c+22];		net_packet[c+22] = net_mac[c];	}}static void swapdestandsrcip(void) {	uint8_t c;		for (c = 0; c < 4; c++) {		net_packet[c+30] = net_packet[c+26];		net_packet[c+26] = net_ip[c];	}}void net_handlearp(void) {	/* 14 - 15  hardware type	 * 16 - 17  protocol	 * 18       hardware address size	 * 19       protocol address size	 * 20 - 21  type (0x0001 = request, 0x0002 = reply)	 * 22 - 27  sender hw address	 * 28 - 31  sender ip address	 * 32 - 37  target hw address	 * 38 - 41  target ip address	 */	if ((net_packet[14] == 0x00) /* Hardware type */	 && (net_packet[15] == 0x01)	 && (net_packet[16] == 0x08) /* Protocol */	 && (net_packet[17] == 0x00)	 && (net_packet[18] == 0x06) /* Hardware size */	 && (net_packet[19] == 0x04) /* Protocol size */	 && (net_packet[20] == 0x00) /* ARP Request */	 && (net_packet[21] == 0x01)	   ) {		if (memcmp(&net_packet[38], net_ip, 4)) {			/* Not for us */			return;		}		/* OK this is a request for our IP. Send a reply. */		/* We just rewrite the existing packet */		/* It's now an ARP REPLY, not a request */		net_packet[21] = 0x02;		swapdestandsrceth();		swapdestandsrcarp();		net_sendpacket(net_packet, 0x40);	}}uint16_t net_calcipchecksum(uint8_t * packet, uint8_t end) {	uint32_t tmp = 0;	uint16_t * pp;	uint8_t i;		pp = (uint16_t *)packet;	for (i = end; i > 1; i-=2) {		tmp += *pp;		pp++;	}	if (i > 0) {		tmp += (*pp & 0xff00);	}	while ((tmp >> 16) > 0) {		tmp = (tmp >> 16) + (tmp & 0xffffUL);	}	/* No idea why it works with the byte order swapped?	 * anyways, you will have to swap the byte order of the result! */	return (uint16_t)~tmp;}static void net_handleicmp(uint8_t hlen) {	/* ICMP: IP Header + type (1 byte) + code (1 byte) + checksum (2 bytes) 	 *                 + parameters (0-4 bytes) + data	 *       type  8 code 0:  echo request	 *       type  0 code 0:  echo reply	 *       type 11 code 0:  TTL exceeded	 */	if ((net_packet[hlen] == 8) && (net_packet[hlen+1] == 0)) {		/* We have an echo request - send it back almost unmodified? */		uint16_t cs;		if (net_packet[16] > 1) {			/* We don't do more than 511 bytes */			return;		}		net_packet[hlen] = 0;		swapdestandsrceth();		swapdestandsrcip();		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;		net_packet[hlen+2] = net_packet[hlen+3] = 0;		cs = net_calcipchecksum(&net_packet[hlen], (net_recvdbytes - hlen - 4));		net_packet[hlen+2] = cs & 0xff;		net_packet[hlen+3] = cs >> 8;		net_sendpacket(net_packet, net_recvdbytes - 4);		led_statusleds |= led_status_netping;#ifdef NETWORKSTATS

⌨️ 快捷键说明

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