#include #include #include #include "sys/alt_stdio.h" #include "sys/alt_irq.h" #include // Function Prototypes void rx_ethernet_isr (void *context); // Global Variables unsigned int text_length; // Create a transmit frame unsigned char tx_frame[2048] = { 0x00,0x00, // for 32-bit alignment 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // destination address (broadcast) 0x01,0x60,0x6E,0x11,0x02,0x0F, // source address 0x00,0x2E, // length or type of the payload data '\0' // payload data (ended with termination character) }; //ethernet header struct etheader { unsigned char preamble[2]; unsigned char MACdestination[6]; unsigned char MACsource[6]; unsigned char proto[2]; }; //ip header struct ipheader { unsigned char iph_type; unsigned char iph_dscp; unsigned short int iph_len; unsigned short int iph_ident; unsigned char iph_flag; unsigned char iph_offset; unsigned char iph_ttl; unsigned char iph_protocol; unsigned short int iph_chksum; unsigned char iph_sourceip[4]; unsigned char iph_destip[4]; }; //UDP header's structure struct udpheader { unsigned short int port[2]; unsigned short int udph_len; unsigned short int udph_chksum; }; //crc32 body struct crc32body { unsigned int crc_chksum; unsigned char end; }; //Comput ipcheck sum and crc32: unsigned int crc32c(unsigned char *message, unsigned int last) { int i, j; unsigned int byte, crc, mask; static unsigned int table[256]; /* Set up the table, if necessary. */ if (table[1] == 0) { for (byte = 0; byte <= 255; byte++) { crc = byte; for (j = 7; j >= 0; j--) { // Do eight times. mask = -(crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } table[byte] = crc; } } /* Through with table setup, now calculate the CRC. */ i = 0; crc = 0xFFFFFFFF; while ((byte = message[i]) != 0) { crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF]; i = i + 1; } return ~crc; } unsigned short csum(unsigned short *buf, int nwords, int mwords) { // unsigned short *sht_buf = (buf + mwords ); unsigned long sum; for(sum=0; nwords>0; nwords--) sum += *sht_buf++; sum = (sum >> 16) + (sum &0xffff); sum += (sum >> 16); return (unsigned short)(~sum); } unsigned short int htons(unsigned short int x) { #if BYTE_ORDER == LITTLE_ENDIAN u_char *s = (u_char *) &x; return (unsigned short int)(s[0] << 8 | s[1]); #else return x; #endif } // Create a receive frame unsigned char rx_frame[1024] = { 0 }; // Create sgdma transmit and receive devices alt_sgdma_dev * sgdma_tx_dev; alt_sgdma_dev * sgdma_rx_dev; // Allocate descriptors in the descriptor_memory (onchip memory) alt_sgdma_descriptor tx_descriptor __attribute__ (( section ( ".descriptor_memory" ))); alt_sgdma_descriptor tx_descriptor_end __attribute__ (( section ( ".descriptor_memory" ))); alt_sgdma_descriptor rx_descriptor __attribute__ (( section ( ".descriptor_memory" ))); alt_sgdma_descriptor rx_descriptor_end __attribute__ (( section ( ".descriptor_memory" ))); /******************************************************************************** * This program demonstrates use of the Ethernet in the DE2-115 board. * * It performs the following: * 1. Records input text and transmits the text via Ethernet after Enter is * pressed * 2. Displays text received via Ethernet frame on the JTAG UART ********************************************************************************/ int main(void) { // Open the sgdma transmit device sgdma_tx_dev = alt_avalon_sgdma_open ("/dev/sgdma_tx"); if (sgdma_tx_dev == NULL) { alt_printf ("Error: could not open scatter-gather dma transmit device\n"); return -1; } else alt_printf ("Opened scatter-gather dma transmit device\n"); // Open the sgdma receive device sgdma_rx_dev = alt_avalon_sgdma_open ("/dev/sgdma_rx"); if (sgdma_rx_dev == NULL) { alt_printf ("Error: could not open scatter-gather dma receive device\n"); return -1; } else alt_printf ("Opened scatter-gather dma receive device\n"); // Set interrupts for the sgdma receive device alt_avalon_sgdma_register_callback( sgdma_rx_dev, (alt_avalon_sgdma_callback) rx_ethernet_isr, 0x00000014, NULL ); // Create sgdma receive descriptor alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 ); // Set up non-blocking transfer of sgdma receive descriptor alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor ); // Triple-speed Ethernet MegaCore base address volatile int * tse = (int *) 0x00102000; // Initialize the MAC address *(tse + 3) = 0x116E6001; *(tse + 4) = 0x00000F02; // Specify the addresses of the PHY devices to be accessed through MDIO interface *(tse + 0x0F) = 0x10; *(tse + 0x10) = 0x11; // Write to register 20 of the PHY chip for Ethernet port 0 to set up line loopback *(tse + 0x94) = 0x4000; // Write to register 16 of the PHY chip for Ethernet port 1 to enable automatic crossover for all modes *(tse + 0xB0) = *(tse + 0xB0) | 0x0060; // Write to register 20 of the PHY chip for Ethernet port 2 to set up delay for input/output clk *(tse + 0xB4) = *(tse + 0xB4) | 0x0082; // Software reset the second PHY chip and wait *(tse + 0xA0) = *(tse + 0xA0) | 0x8000; while ( *(tse + 0xA0) & 0x8000 ) ; // Enable read and write transfers, gigabit Ethernet operation, and CRC forwarding *(tse + 2) = *(tse + 2) | 0x0000004B; alt_printf( "send> " ); text_length = 0; while (1) { // frame buffer unsigned char rx_frame[1024]; // size of frame unsigned int Tx_UDPpayloadlength = 1600; unsigned int header_size = sizeof(struct etheader) + sizeof(struct ipheader) + sizeof(struct udpheader); unsigned int total_size = sizeof(struct etheader)+Tx_UDPpayloadlength+ sizeof(struct ipheader)+sizeof(struct udpheader) + 0x0004; //insert data unsigned char buffer[20] = {0x0A, 0x0B, 0x0C}; int i=0; for (i=0;i<=20;i++) tx_frame[header_size+i] = buffer[i]; // structure the frame unsigned char MAC_des[6] = {0x44,0x8A,0x5B,0x43,0x34,0xAC};// laptop unsigned char MAC_src[6] = {0x01,0x60,0x6E,0x11,0x02,0x0F}; unsigned char IP_des[4] = {192,168,0,2}; unsigned char IP_src[4] = {192,168,0,44}; struct etheader *eth = (struct etheader * ) tx_frame; struct ipheader *ip = (struct ipheader *) (tx_frame + sizeof(struct etheader) ); struct udpheader *udp = (struct udpheader *) (tx_frame + sizeof(struct etheader)+ sizeof(struct ipheader)); struct crc32body *crc_32b = (struct crc32body *) (tx_frame + sizeof(struct etheader)+ sizeof(struct ipheader)+sizeof(struct udpheader) + Tx_UDPpayloadlength); // Fabricate the ethernet header or we can use the int lp=0; for (lp=0; lp < 2; lp++) // Ethernet preamble eth->preamble[lp] = 0x00; for (lp=0; lp < 6; lp++) // Ethernet preamble { eth->MACsource[lp] = MAC_src[lp]; eth->MACdestination[lp] = MAC_des[lp]; if (lp < 4) { ip->iph_sourceip[lp] = IP_src[lp]; ip->iph_destip[lp] = IP_des[lp]; } } eth->proto[0]=0x08; eth->proto[1]=0x00; // Fabricate the IP and UDP header ip->iph_type = 0x45; ip->iph_dscp = 0x00; ip->iph_len = htons(Tx_UDPpayloadlength + sizeof(struct ipheader) + sizeof(struct udpheader)); ip->iph_ident = 0x0000; ip->iph_offset = 0x00; ip->iph_flag = 0x00; ip->iph_ttl = 0x80; // time to live ip->iph_protocol = 0x11; // UDP = 17 udp->port[0]=htons(1024);//0x04; udp->port[1]=0x00; udp->port[1]=htons(1024);//=0x04; udp->port[3]=0x00; //udp->port[1]=htons(1024); udp->udph_len=htons(sizeof(struct udpheader)+Tx_UDPpayloadlength); udp->udph_chksum=0x0000; ip->iph_chksum=csum((unsigned short *)tx_frame, sizeof(struct ipheader) + sizeof(struct udpheader), sizeof(struct etheader) ); crc_32b->crc_chksum =crc32c(tx_frame, total_size-0x0005); crc_32b->end = '\0'; // Create transmit sgdma descriptor alt_avalon_sgdma_construct_mem_to_stream_desc( &tx_descriptor, &tx_descriptor_end, (alt_u32 *)tx_frame, total_size, 0, 1, 1, 0 ); // Set up non-blocking transfer of sgdma transmit descriptor alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor ); // Wait until transmit descriptor transfer is complete while (alt_avalon_sgdma_check_descriptor_status(&tx_descriptor) != 0) ; } return 0; } /**************************************************************************************** * Subroutine to read incoming Ethernet frames ****************************************************************************************/ void rx_ethernet_isr (void *context) { int i; // Wait until receive descriptor transfer is complete while (alt_avalon_sgdma_check_descriptor_status(&rx_descriptor) != 0) ; // Clear input line before writing for (i = 0; i < (6 + text_length); i++) { alt_printf( "%c", 0x08 ); // 0x08 --> backspace } // Output received text alt_printf( "receive> %s\n", rx_frame + 16 ); // Reprint current input line after the output alt_printf( "send> %s", tx_frame + 16 ); // Create new receive sgdma descriptor alt_avalon_sgdma_construct_stream_to_mem_desc( &rx_descriptor, &rx_descriptor_end, (alt_u32 *)rx_frame, 0, 0 ); // Set up non-blocking transfer of sgdma receive descriptor alt_avalon_sgdma_do_async_transfer( sgdma_rx_dev, &rx_descriptor ); }