diff --git a/enc28j60.cpp b/enc28j60.cpp index 03c4ef7..2aa7072 100644 --- a/enc28j60.cpp +++ b/enc28j60.cpp @@ -114,6 +114,15 @@ void nicReboot(void) enc28j60Reboot(); } +uint16_t nicGetChecksum(uint8_t* packet, uint16_t len) +{ +#ifdef ENC28J60_CHECKSUM_ENABLED + enc28j60getChecksum(packet, len); +#else + return 0x0000; +#endif +} + void enc28j60Reboot(void) { #ifndef ENC28J60_HARD_RESET_DISABLED @@ -215,6 +224,68 @@ void enc28j60ReadBuffer(uint16_t len, uint8_t* data) sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS); } + +uint16_t enc28j60getChecksum(uint8_t* packet, uint16_t len) +//void enc28j60PacketSend(uint16_t len, uint8_t* packet) +{ + // Errata workaround #10 Transmit Logic + if (enc28j60Read(EIR) & EIR_TXERIF) + { + enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); + enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF); + } + + // Set the write pointer to start of transmit buffer area + enc28j60Write(EWRPTL, TXSTART_INIT); + enc28j60Write(EWRPTH, TXSTART_INIT>>8); + + // Set the TXND pointer to correspond to the packet size given + enc28j60Write(ETXNDL, (TXSTART_INIT+len)); + enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8); + + // write per-packet control byte + enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); + + // copy the packet into the transmit buffer + enc28j60WriteBuffer(len, packet); + + // return the calculated checksum + return enc28j60doHardwareChecksum(len); +} + +uint16_t enc28j60doHardwareChecksum(uint16_t len) +{ + // Set EDMASTL to the beggining of the used memory + enc28j60Write(EDMASTL, TXSTART_INIT); + enc28j60Write(EDMASTH, TXSTART_INIT>>8); + + // Set EDMAND to the end of the memory used + enc28j60Write(EDMANDL, (TXSTART_INIT+len)); + enc28j60Write(EDMANDH, (TXSTART_INIT+len)>>8); + + // Set EDMADST to the beggining of the DMA buffer + enc28j60Write(EDMADSTL, TXSTART_INIT); + enc28j60Write(EDMADSTH, TXSTART_INIT>>8); + + // Enable DMA copy mode + enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // Wait for the DMA copy to complete + while(!(enc28j60Read(EIR) & EIR_DMAIF)); + + // Start the checksum calculation + enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_CSUMEN); + enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // Wait for the checksum calculation to complete + while(!(enc28j60Read(ECON1) & ~ECON1_DMAST && enc28j60Read(EIR) & EIR_DMAIF)); + + // Read back and return the calculated checksum + return (uint16_t)(enc28j60Read(EDMACSL) | (uint16_t)enc28j60Read(EDMACSH)<<8); +} + void enc28j60WriteBuffer(uint16_t len, uint8_t* data) { // assert CS diff --git a/enc28j60.h b/enc28j60.h index a8e980d..4115889 100644 --- a/enc28j60.h +++ b/enc28j60.h @@ -301,6 +301,9 @@ uint16_t enc28j60PhyRead(uint8_t address); //! write a PHY register void enc28j60PhyWrite(uint8_t address, uint16_t data); +uint16_t enc28j60doHardwareChecksum(uint16_t len); +uint16_t enc28j60getChecksum(uint8_t* packet, uint16_t len); + //! initialize the ethernet interface for transmit/receive /// \return -1 if there was a problem initializing the NIC, otherwise the value is undefined char enc28j60Init(void); diff --git a/enc28j60conf.h b/enc28j60conf.h index ca91c5b..f2c01ff 100644 --- a/enc28j60conf.h +++ b/enc28j60conf.h @@ -67,6 +67,9 @@ #define ENC28J60_PACKET_FILTER_ENABLED /* Unimplemented */ #define ENC28J60_LAMPS_MODE 0x3476 /* Default (with Errata #9 correction) applied if this is undefied */ + +#define ENC28J60_CHECKSUM_ENABLED + /** * Lamps reference * 0x3D56 # Default full duplex: LEDA: Display link status and transmit/receive activity LEDB: Display duplex status diff --git a/icmp.cpp b/icmp.cpp index dfee688..e95fc6d 100644 --- a/icmp.cpp +++ b/icmp.cpp @@ -26,6 +26,10 @@ #include "HardwareSerial.h" #endif +#ifdef NET_CHECKSUM_DEBUG +#include "enc28j60.h" +#endif + // functions void icmpInit(void) { @@ -48,36 +52,27 @@ void icmpIpIn(icmpip_hdr* packet) void icmpEchoRequest(icmpip_hdr* packet) { - uint32_t tempIp, tempId; + uint32_t tempIp; + uint16_t tempId; // change type to reply packet->icmp.type = ICMP_TYPE_ECHOREPLY; // recalculate checksum packet->icmp.icmpchksum = 0x0000; - packet->icmp.icmpchksum = ipChecksum((netIpHeader*)&packet->icmp, htons(packet->ip.len)-sizeof(netIpHeader)); + packet->icmp.icmpchksum = nicGetChecksum((uint8_t*)&packet->icmp, htons(packet->ip.len)-IP_HEADER_LEN); -#ifdef NET_CHECKSUM_DEBUG - SPrintln(" "); - SPrint("ICMP Checksum: 0x"); - Serial.print((uint16_t)htons(packet->icmp.icmpchksum), HEX); - SPrint(" 0x"); - Serial.println((uint16_t)HTONS(packet->icmp.icmpchksum), HEX); -#endif + #ifdef NET_CHECKSUM_DEBUG + SPrintln(" "); + SPrint("Hardware Checksum: 0x"); + Serial.println((uint16_t)HTONS(packet->icmp.icmpchksum), HEX); + #endif // return to sender tempIp = packet->ip.destipaddr; packet->ip.destipaddr = packet->ip.srcipaddr; packet->ip.srcipaddr = tempIp; - // Set the proper transaction id - - tempId = packet->ip.ipid; - packet->ip.ipid = tempId; - - tempId = packet->icmp.id; - packet->icmp.id = tempId; - // add ethernet routing arpIpOut((struct netEthIpHeader*)(((u08*)packet)-ETH_HEADER_LEN), 0); @@ -88,7 +83,7 @@ void icmpEchoRequest(icmpip_hdr* packet) #endif // send it (packet->ip.len+ETH_HEADER_LEN - nicSend(htons(packet->ip.len)+ETH_HEADER_LEN, (((u08*)packet)-ETH_HEADER_LEN)); + nicSend(htons(packet->ip.len)+ETH_HEADER_LEN, (((uint8_t*)packet)-ETH_HEADER_LEN)); } #ifdef ICMP_DEBUG_PRINT diff --git a/icmp.h b/icmp.h index 75d6250..d7c4a4a 100644 --- a/icmp.h +++ b/icmp.h @@ -31,7 +31,7 @@ #include "net.h" -#define ICMP_DEBUG_PRINT +// #define ICMP_DEBUG_PRINT //! Initialize ICMP protocol library. void icmpInit(void); diff --git a/main.pde b/main.pde index 8d2f0dc..57ba84c 100644 --- a/main.pde +++ b/main.pde @@ -5,7 +5,6 @@ **/ #include "main.h" - /** * Network support **/ @@ -21,6 +20,8 @@ #include "ip.h" #include "icmp.h" +#define PrintIP(ip) netPrintIPAddr(ip); SPrintln(" ") + struct netEthAddr myEthAddress; // prototypes @@ -112,10 +113,12 @@ void serviceLocal(void) sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS); break; */ -#if defined(NET_DEBUG) || defined(NIC_DEBUG) +#if defined(ARP_DEBUG_PRINT) case 'a' : arpPrintTable(); break; +#endif +#if defined(NET_DEBUG) || defined(NIC_DEBUG) case 'd': nicRegDump(); break; @@ -144,11 +147,13 @@ void serviceLocal(void) case 'c': SPrintln("IP Configs"); SPrint("IP:"); - Serial.println(ipGetConfig()->ip); + PrintIP(ipGetConfig()->ip); SPrint("Gateway:"); - Serial.println(ipGetConfig()->gateway); + PrintIP(ipGetConfig()->gateway); SPrint("Netmask:"); - Serial.println(ipGetConfig()->netmask); + PrintIP(ipGetConfig()->netmask); + //SPrint("MAC:"); + //netPrintEthAddr(netEthAddr); break; /* case 'x': diff --git a/net.cpp b/net.cpp index b89c659..56745ea 100644 --- a/net.cpp +++ b/net.cpp @@ -30,12 +30,17 @@ uint32_t htonl(uint32_t val) return (htons(val>>16) | (uint32_t)htons(val&0x0000FFFF)<<16); } -static uint16_t generateChecksum(uint16_t sum, netIpHeader *data, uint16_t len) +uint16_t generateChecksum(uint16_t sum, netIpHeader *data, uint16_t len) { uint16_t t; uint32_t *dataptr; uint32_t *last_byte; + +#ifdef NET_CHECKSUM_DEBUG + SPrint("Length for chksum func: "); + Serial.println((long int)len, HEX); +#endif dataptr = (uint32_t *) data; last_byte = (uint32_t *) data + len - 1; diff --git a/net.h b/net.h index 5c2ab35..e5f8abf 100644 --- a/net.h +++ b/net.h @@ -29,7 +29,7 @@ // #define NET_DEBUG 7 -//#define NET_CHECKSUM_DEBUG +// #define NET_CHECKSUM_DEBUG #include "avrlibdefs.h" #include "avrlibtypes.h" @@ -198,7 +198,7 @@ uint16_t ipChecksum(netIpHeader *data, uint16_t len); //! Calculate IP Header checksum from data. uint16_t netChecksum(netIpHeader *data, uint16_t len); -static uint16_t generateChecksum(uint16_t sum, netIpHeader *data, uint16_t len); +uint16_t generateChecksum(uint16_t sum, netIpHeader *data, uint16_t len); //! Print Ethernet address in XX:XX:XX:XX:XX:XX format. void netPrintEthAddr(struct netEthAddr* ethaddr); diff --git a/netstack.h b/netstack.h index 09530c8..1ed6601 100644 --- a/netstack.h +++ b/netstack.h @@ -44,7 +44,7 @@ #include "ip.h" #include "nic.h" -// #define NETSTACK_DEBUG +//#define NETSTACK_DEBUG /// NET_BUFFERSIZE is the common receive/process/transmit buffer. /// - You may override the default NET_BUFFERSIZE by defining an alternate value in global.h. diff --git a/nic.h b/nic.h index 842f349..923327e 100644 --- a/nic.h +++ b/nic.h @@ -27,6 +27,7 @@ #ifndef NIC_H #define NIC_H +#include "net.h" // #define NIC_DEBUG #include @@ -81,5 +82,8 @@ void nicSoftReset(void); //! PHY Chip reboot void nicReboot(void); +//! PHY Chip hardware checksum, if available +uint16_t nicGetChecksum(uint8_t* packet, uint16_t len); + #endif //@}