//************************************************************************************** //************************************************************************************** #include "stdio.h" #include "stdlib.h" #include "altera_avalon_sgdma.h" #include "altera_avalon_sgdma_regs.h" #include "alt_types.h" #include "sys/alt_cache.h" #include "io.h" #include "altera_avalon_sgdma_descriptor.h" #define MDIO_PAGE_ADD 0x200 #define EXT_PHY_SPECIFIC_CONTROL_REG MDIO_PAGE_ADD + (0x14 << 2) //Reg 20 #define PHY_SPECIFIC_STATUS_REG MDIO_PAGE_ADD + (0x11 << 2) //Reg 17 #define LINK_STATUS_REG MDIO_PAGE_ADD + (0xA << 2) //Reg 10 #define NUMBER_OF_BUFFERS 1 /* each direction so double this for the total */ #define MINIMUM_BUFFER_LENGTH 100 #define MAXIMUM_BUFFER_LENGTH 100 /* set this to the same value as the min for a fixed size, also don't exceed 65535 */ //define a array for receive frame to compare with frame that is receive from netwrork. unsigned char rx_frame[20] = { 0x00,0x00, // for 32-bit alignment 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // destination address (broadcast) 0x00,0x1C,0xC0,0xD4,0xcd,0x46, // source address 0x08,0x00, // length or type of the payload data 0x45, // Version 0x00, // Diffrentiated service field 0x00,0x24, // total length //upto this field all the host application frame field is same after this field identification field which is vary on frame by frame. }; // Create test data rx alt_u32 buffer_counter, contents_counter, temp_length; alt_u32 *receive_ptr; alt_u8 *receive_ptr_copy; // will use these to fill up the rx buffers //validate data alt_u32 buffer_counter_rx, contents_counter_rx; alt_u32 *receive_ptr_rx; alt_u8 temp_receive; int match_count = 0; int done; /* These will gate the data checking near the end of main */ volatile alt_u8 tx_done = 0; volatile alt_u8 rx_done = 0; void transmit_callback_function(void * context) { tx_done++; /* main will be polling for this value being 1 */ } void receive_callback_function(void * context) { rx_done++; /* main will be polling for this value being 1 */ } int main() { //*********************************************************************// // // // TSE_MAC_Configuration // // // //*********************************************************************// unsigned int phy_status,i; unsigned char tse_1000b; tse_1000b = 0x00; IOWR_32DIRECT(TSE_MAC_BASE, 0x03C, 0x12); //Assign PHY Address IOWR_32DIRECT(TSE_MAC_BASE,0x200,((IORD_32DIRECT(TSE_MAC_BASE,0x200)) & 0xBFFF)); //Clear AutoLoopBack IOWR_32DIRECT(TSE_MAC_BASE,0x200,((IORD_32DIRECT(TSE_MAC_BASE,0x200)) | 0x1000)); //Enable Auto negotiation IOWR_32DIRECT(TSE_MAC_BASE,0x200,((IORD_32DIRECT(TSE_MAC_BASE,0x200)) | 0x0200)); //Restart Auto Negotiation i=0; while((IORD_32DIRECT(TSE_MAC_BASE,0x204) & 0x0024) != 0x0024)//Wait for Auto negotiation complete and LINK UP { if(i++ > 10000000) break; } phy_status = IORD_32DIRECT(TSE_MAC_BASE,0x204); //Check For Auto negotiation process if(phy_status & 0x00000020) printf("Auto-Negotiation is complete\n"); else printf("Auto-Negotiation is NOT complete\n"); //Check For Remote Fault if(phy_status & 0x00000010) printf("Remote fault is detected\n"); //Check For Link Status if(phy_status & 0x00000004) printf("LINK is UP\n"); else printf("LINK is DOWN\n"); //phy_status = IORD_32DIRECT(TSE_MAC_BASE,0x200); phy_status = IORD_32DIRECT(TSE_MAC_BASE,PHY_SPECIFIC_STATUS_REG); if((phy_status & 0xC000) == 0x8000) { printf("1000Mbps mode set\n"); tse_1000b = 0x01; } if((phy_status & 0xC000) == 0x4000) { printf("100Mbps mode set\n"); tse_1000b = 0x00; } #if 1 // User Configuration alt_u16 dat = IORD_32DIRECT(TSE_MAC_BASE, 0x26c);//IORD(&pmac->mdio1.reg1b, 0); dat &= 0xfff0; printf("MARVELL : Mode changed to RGMII/Modified MII to Copper mode\n"); IOWR_32DIRECT(TSE_MAC_BASE, 0x26c, dat | 0xb);//IOWR(&pmac->mdio1.reg1b, 0, dat | 0xb); printf("MARVELL : Enable RGMII Timing Control\n"); dat = IORD_32DIRECT(TSE_MAC_BASE, EXT_PHY_SPECIFIC_CONTROL_REG);//IORD(&pmac->mdio1.reg14, 0); dat &= ~0x82; dat |= 0x82; IOWR_32DIRECT(TSE_MAC_BASE, EXT_PHY_SPECIFIC_CONTROL_REG, dat );//IOWR(&pmac->mdio1.reg14, 0, dat); printf("MARVELL : PHY reset\n"); dat = IORD_32DIRECT(TSE_MAC_BASE, 0x200);//IORD(&pmac->mdio1.CONTROL, 0); IOWR_32DIRECT(TSE_MAC_BASE, 0x200, dat | 0x8000);//Reset the PHY #endif while((IORD_32DIRECT(TSE_MAC_BASE,0x204) & 0x8000) == 0x8000); //Wait for reset complete i=0; while((IORD_32DIRECT(TSE_MAC_BASE,0x204) & 0x0024) != 0x0024)//Wait for Auto negotiation complete and LINK UP { if(i++ > 10000000) break; } //Check For Auto negotiation process if((IORD_32DIRECT(TSE_MAC_BASE,0x204)) & 0x00000020) printf("Auto-Negotiation is complete\n"); else printf("Auto-Negotiation is NOT complete\n"); //Check For Link Status i=0; while((IORD_32DIRECT(TSE_MAC_BASE,0x244) & 0x0400) != 0x0400)//Wait for LINK UP { if(i++ > 10000000) break; } if((IORD_32DIRECT(TSE_MAC_BASE,0x244)) & 0x0400) printf("LINK is UP\n"); else printf("LINK is DOWN\n"); printf("PHY_REG0 = %x\n",IORD_32DIRECT(TSE_MAC_BASE,0x200)); //READ PHY Reg0 printf("PHY_STATUS = %x\n",IORD_32DIRECT(TSE_MAC_BASE,0x204));//READ PHY Reg1 IOWR_32DIRECT(TSE_MAC_BASE, 0x008, 0x00002003); //Reset MAC while(( IORD_32DIRECT(TSE_MAC_BASE, 0x008) & 0x00002003) != 0x00000000)//Wait till reset completes IOWR_32DIRECT(TSE_MAC_BASE, 0x00C, 0xffed0700); //MAC ID 0 IOWR_32DIRECT(TSE_MAC_BASE, 0x010, 0x00004f68); //MAC ID 1 IOWR_32DIRECT(TSE_MAC_BASE, 0x014, 0x0000003D); //Frame Length IOWR_32DIRECT(TSE_MAC_BASE, 0x018, 0x0000FFFF); //PAUSE QUANTA IOWR_32DIRECT(TSE_MAC_BASE, 0x01C, 0x000007F0); //RX Section Empty IOWR_32DIRECT(TSE_MAC_BASE, 0x020, 0x00000000); //RX Section Full IOWR_32DIRECT(TSE_MAC_BASE, 0x024, 0x000007F0); //TX Section Empty IOWR_32DIRECT(TSE_MAC_BASE, 0x028, 0x00000000); //TX Section Full IOWR_32DIRECT(TSE_MAC_BASE, 0x02C, 0x00000008); //RX Almost Empty IOWR_32DIRECT(TSE_MAC_BASE, 0x030, 0x00000008); //RX Almost Full IOWR_32DIRECT(TSE_MAC_BASE, 0x034, 0x00000008); //TX Almost Empty IOWR_32DIRECT(TSE_MAC_BASE, 0x038, 0x00000003); //TX Almost Full IOWR_32DIRECT(TSE_MAC_BASE, 0x03C, 0x12 ); //Assign PHY Address IOWR_32DIRECT(TSE_MAC_BASE, 0x05C, 0x00000000); //TX Inter Packet Gap IOWR_32DIRECT(TSE_MAC_BASE, 0x0E8, 0x00000000); //tx_cmd_stat Reg if(tse_1000b) IOWR_32DIRECT(TSE_MAC_BASE, 0x008, 0x0400004b); //TSE_COMMAND_CONFIG else IOWR_32DIRECT(TSE_MAC_BASE, 0x008, 0x04000043); //TSE_COMMAND_CONFIG // printf("TSE_COMMAND_CONFIG = %x\n",IORD_32DIRECT(TSE_MAC_BASE,0x008)); //Mac ID of the device printf("0x18-aMacID0: %x\n", IORD_32DIRECT(TSE_MAC_BASE, 0x060)); printf("0x19-aMacID1: %x\n", IORD_32DIRECT(TSE_MAC_BASE, 0x064)); //*********************************************************************// // // //**********************TSE MAC Configuration End**********************// // // //*********************************************************************// //*********************************************************************// // // // Scatter-Gather DMA Configuration // // // //*********************************************************************// /* Open a SG-DMA for MM-->ST and ST-->MM (two SG-DMAs are present) */ alt_sgdma_dev * receive_DMA = alt_avalon_sgdma_open("/dev/sgdma_st_to_mm"); /* Needs one allocated descriptor at the end to mark the tail of the list. * Copies are made so that they can be put back on the heap when we are done. * The copies are a superset of the other pointers so by freeing them at the * end we'll be freeing transmit_descriptors and receive_descriptors as well. */ // alt_u32 return_code,success_code; int frame_num = 0; do { printf("\n frame_num %d\n",frame_num); alt_sgdma_descriptor *receive_descriptors, *receive_descriptors_copy; if(receive_DMA == NULL) { printf("Could not open the receive SG-DMA\n"); return 1; } /////////////////////////////////////////////////////////////////////////////////////////////// // Descriptor allocation start // /////////////////////////////////////////////////////////////////////////////////////////////// /**************************************************************/ /************************************************************** * Allocating Rx_descriptor table space from main memory. * * Pointers are passed by reference since they will be * * modified by this function. * ************************************************************/ //Allocate some big buffers to hold all descriptors which will slide until //the first 32 byte boundary is found alt_u32 * temp_ptr_rx; /************************************************************** * Allocation of the receive descriptors * * - First allocate a large buffer to the temporary pointer * * - Second check for sucessful memory allocation * * - Third put this memory location into the pointer copy * * to be freed before the program exits * * - Forth slide the tempory pointer until it lies on a 32 * * byte boundary (descriptor master is 256 bits wide) * ************************************************************/ temp_ptr_rx = malloc((NUMBER_OF_BUFFERS + 2) * ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE); if(temp_ptr_rx == NULL) { printf("Failed to allocate memory for the receive descriptors\n"); return 1; } receive_descriptors_copy = (alt_sgdma_descriptor *)temp_ptr_rx; while((((alt_u32)temp_ptr_rx) % ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE) != 0) { temp_ptr_rx++; // slide the pointer until 32 byte boundary is found } receive_descriptors = (alt_sgdma_descriptor *)temp_ptr_rx;// copy starting address //Clear out the null descriptor owned by hardware bit. These locations //came from the heap so we don't know what state the bytes are in (owned bit could be high). receive_descriptors[NUMBER_OF_BUFFERS].control = 1; /////////////////////////////////////////////////////////////////////////////////////////////// // Descriptor allocation over // /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// // Create test data start // /////////////////////////////////////////////////////////////////////////////////////////////// //Initialization of the buffer memories and the receive descriptors for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) { //Generate a random buffer length between within MINIMUM_BUFFER_LENGTH and MAXIMUM_BUFFER_LENGTH */ if(MINIMUM_BUFFER_LENGTH == MAXIMUM_BUFFER_LENGTH) // if you don't want a random length set these equal { temp_length = MINIMUM_BUFFER_LENGTH; } else { if(MINIMUM_BUFFER_LENGTH > MAXIMUM_BUFFER_LENGTH) { printf("\nPlease set the maximum buffer length to be larger than the minimum buffer length\n"); return 1; } temp_length = (rand() % (MAXIMUM_BUFFER_LENGTH - MINIMUM_BUFFER_LENGTH)) + MINIMUM_BUFFER_LENGTH; } receive_ptr = (alt_u32 *)malloc(temp_length); // since the same contents will be received the length is the same printf("\n************ receive_ptr : %x\n",receive_ptr); if(receive_ptr == NULL) { printf("Allocating a receive buffer region failed\n"); return 1; } // This will create a descriptor that is capable of transmitting data from an Avalon-ST FIFO to an Avalon-MM buffer // When the transfer completes the SGDMA will write the actual_bytes transfer into the descriptor field as well as set "OWNNED_BY_HW" to 0. // So if you want to reuse those descriptors you might be able to just flip the owned by hardware back to 1. alt_avalon_sgdma_construct_stream_to_mem_desc(&receive_descriptors[buffer_counter], // descriptor &receive_descriptors[buffer_counter+1], // next descriptor receive_ptr, // write buffer location 0x00,//(alt_u16)temp_length, // length of the buffer 0); // writes are not to a fixed location } alt_dcache_flush_all(); // make sure all the transmit buffers and cleared receive buffers go out to main memory /////////////////////////////////////////////////////////////////////////////////////////////// // Create test data over // /////////////////////////////////////////////////////////////////////////////////////////////// /************************************************************** * Register the ISRs that will get called when each (full) * * transfer completes * ************************************************************/ alt_avalon_sgdma_register_callback( receive_DMA, &receive_callback_function, (ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK), NULL ); printf("Starting up the SGDMA Receive engines\n"); if(alt_avalon_sgdma_do_async_transfer(receive_DMA, &receive_descriptors[0]) != 0) { printf("Writing the head of the receive descriptor list to the DMA failed\n"); return 1; } /************************************************************** * Blocking until the SGDMA interrupts fire * ************************************************************/ while(rx_done == 0) {} printf("The receive SGDMA has completed with rx_done :%01d\n",rx_done); /************************************************************** * Verify the returned data and free up the data buffers * ************************************************************/ for(buffer_counter_rx = 0; buffer_counter_rx < NUMBER_OF_BUFFERS; buffer_counter_rx++) { receive_ptr_rx = receive_descriptors[buffer_counter_rx].write_addr; /* loop through each buffer to check the contents on each byte */ for(contents_counter_rx = 0; contents_counter_rx < 20; contents_counter_rx++) { temp_receive = IORD_8DIRECT((alt_u32)receive_ptr_rx, contents_counter_rx); printf("temp_receive %01d : %01x\n",contents_counter_rx,temp_receive); if(temp_receive == rx_frame[contents_counter_rx]) { match_count = match_count + 1; } } /* Done with these, time to clean up after ourselves. */ printf("***********match_count %d\n",match_count); // free(receive_ptr_rx); } if(match_count == 20) { done = 1; } else { done = 0; } if(done == 0) { //Make sure SGDMA controller is not busy from a former command */ //In short we check ready busy flag over here. while((IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_ST_TO_MM_BASE) & ALTERA_AVALON_SGDMA_STATUS_BUSY_MSK)){} IOWR_ALTERA_AVALON_SGDMA_STATUS(SGDMA_ST_TO_MM_BASE, 0xff);////clear status register (look at documentation of sgdma status reg) IOWR_32DIRECT(TSE_MAC_BASE, 0x008, IORD_32DIRECT(TSE_MAC_BASE,0x008) | 0x80000000);//TSE_COMMAND_CONFIG ;Clear statistic counters printf("Its time to check another frame \n"); /* Reset RX-side SGDMA */ IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_ST_TO_MM_BASE, ALTERA_AVALON_SGDMA_CONTROL_SOFTWARERESET_MSK); IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_ST_TO_MM_BASE, 0x0); match_count = 0; rx_done = 0; free(receive_descriptors); free(receive_descriptors_copy); free(receive_ptr); free(receive_ptr_rx); frame_num++; } else { // IOWR_32DIRECT(SGDMA_ST_TO_MM_BASE,0x04,(IORD_32DIRECT(SGDMA_ST_TO_MM_BASE,0x4) | 0x00000000));//clear the park bit printf("You catch the correct frame\n"); } } while(done == 0); printf("Exiting...%c", 4); // 4 will terminate the console return 0; } //************************************************************************************** //**************************************************************************************