Browse Source

New IPEDMA versioning

Suren A. Chilingaryan 8 years ago
parent
commit
92b9df25f5
3 changed files with 75 additions and 74 deletions
  1. 56 62
      dma/ipe.c
  2. 6 5
      dma/ipe.h
  3. 13 7
      dma/ipe_private.h

+ 56 - 62
dma/ipe.c

@@ -27,7 +27,7 @@
 
 pcilib_dma_context_t *dma_ipe_init(pcilib_t *pcilib, const char *model, const void *arg) {
     int err = 0;
-    pcilib_register_value_t value;
+    pcilib_register_value_t version_value;
 
 //    const pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
 
@@ -51,50 +51,51 @@ pcilib_dma_context_t *dma_ipe_init(pcilib_t *pcilib, const char *model, const vo
 	ctx->base_addr[2] = (void*)pcilib_resolve_bank_address_by_id(pcilib, 0, dma_bankc);
 
 
+	RD(IPEDMA_REG_VERSION, version_value);
+	ctx->version = IPEDMA_VERSION(version_value);
+	
 	if ((model)&&(!strcasecmp(model, "ipecamera"))) {
-	    ctx->version = 2;
+	    ctx->gen = 2;
 	} else {
-	    RD(IPEDMA_REG_VERSION, value);
-
-	    if (value >= 0xa7) {
-		ctx->version = 3;
+            if (IPEDMA_GENERATION(version_value) > 2) {
+		ctx->gen = 3;
 	    } else {
-		ctx->version = 2;
+		ctx->gen = 2;
 	    }
 
 	    err = pcilib_add_registers(pcilib, PCILIB_MODEL_MODIFICATON_FLAGS_DEFAULT, 0, ipe_dma_app_registers, NULL);
 	}
-	
-	if (ctx->version >= 3) {
-	    ctx->reg_last_read = IPEDMA_REG3_LAST_READ;
 
+        if (ctx->gen > 2) {
+            ctx->mode64 = 1;
+            ctx->addr64 = 1;
+#ifdef IPEDMA_STREAMING_MODE
+	    if (IPEDMA_STREAMING(version_value)) ctx->streaming = 1;
+#endif /* IPEDMA_STREAMING_MODE */
+
+	    ctx->reg_last_read = IPEDMA_REG3_LAST_READ;
 	    if (!err) 
 		err = pcilib_add_registers(pcilib, PCILIB_MODEL_MODIFICATON_FLAGS_DEFAULT, 0, ipe_dma_v3_registers, NULL);
-	} else {
+        } else {
+#ifdef IPEDMA_ENFORCE_64BIT_MODE
+	    // According to Lorenzo, some gen2 boards have problems with 64-bit addressing. Therefore, we only enable it for gen3 boards unless enforced
+	    ctx->mode64 = 1;
+#endif /* IPEDMA_ENFORCE_64BIT_MODE */
+            ctx->addr64 = 0;
+            ctx->streaming = 0;
+
 	    ctx->reg_last_read = IPEDMA_REG2_LAST_READ;
-	    
 	    if (!err)
 	        err = pcilib_add_registers(pcilib, PCILIB_MODEL_MODIFICATON_FLAGS_DEFAULT, 0, ipe_dma_v2_registers, NULL);
-	}
-	
+        }
+
+        pcilib_info("IPEDMA gen%lu version %lu (64-bit mode: %u, 64-bit addressing: %u, streaming: %u)", ctx->gen, ctx->version, ctx->mode64, ctx->addr64, ctx->streaming);
+
 	if (err) {
 	    free(ctx);
 	    pcilib_error("Error (%i) registering firmware-dependent IPEDMA registers", err);
 	    return NULL;
 	}
-
-	RD(IPEDMA_REG_PCIE_GEN, value);
-
-#ifdef IPEDMA_ENFORCE_64BIT_MODE
-	ctx->mode64 = 1;
-#else /* IPEDMA_ENFORCE_64BIT_MODE */
-	    // According to Lorenzo, some gen2 boards have problems with 64-bit addressing. Therefore, we only enable it for gen3 boards unless enforced
-	if ((value&IPEDMA_MASK_PCIE_GEN) > 2) ctx->mode64 = 1;
-#endif /* IPEDMA_ENFORCE_64BIT_MODE */
-
-#ifdef IPEDMA_STREAMING_MODE
-	if (value&IPEDMA_MASK_STREAMING_MODE) ctx->streaming = 1;
-#endif /* IPEDMA_STREAMING_MODE */
     }
 
     return (pcilib_dma_context_t*)ctx;
@@ -122,7 +123,7 @@ static void dma_ipe_disable(ipe_dma_t *ctx) {
     usleep(IPEDMA_RESET_DELAY);
 
         // Reseting configured DMA pages
-    if (ctx->version < 3) {
+    if (ctx->gen < 3) {
 	WR(IPEDMA_REG2_PAGE_COUNT, 0);
     }
     usleep(IPEDMA_RESET_DELAY);
@@ -210,7 +211,7 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
 	ctx->dma_flags = 0;
 
 #ifdef IPEDMA_CONFIGURE_DMA_MASK
-    if (ctx->version >= 3) mask = 64;
+    if (ctx->addr64) mask = 64;
 
     err = pcilib_set_dma_mask(ctx->dmactx.pcilib, mask);
     if (err) {
@@ -276,12 +277,9 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
     }
 
     desc_va = pcilib_kmem_get_ua(ctx->dmactx.pcilib, desc);
-    if (ctx->version < 3) {
-	if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t);
-	else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t);
-    }  else {
-	last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
-    }
+    if (ctx->addr64) last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
+    else if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t);
+    else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t);
 
 	// get page size if default size was used
     if (!ctx->page_size) {
@@ -324,7 +322,7 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
 	WR(IPEDMA_REG_UPDATE_THRESHOLD, IPEDMA_DMA_PROGRESS_THRESHOLD);
 
 	    // Reseting configured DMA pages
-	if (ctx->version < 3) {
+	if (ctx->gen < 3) {
 	    WR(IPEDMA_REG2_PAGE_COUNT, 0);
 	}
 
@@ -335,17 +333,14 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
 	WR(ctx->reg_last_read, ctx->ring_size);
 #endif /* IPEDMA_BUG_LAST_READ */
 
-	if (ctx->version < 3) {
-	    WR(IPEDMA_REG2_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, desc, 0));
-	} else {
-	    WR64(IPEDMA_REG3_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, desc, 0));
-	}
-
 	    // Instructing DMA engine that writting should start from the first DMA page
-	if (ctx->version < 3)
-	    *(uint32_t*)last_written_addr_ptr = 0;
-	else
+	if (ctx->addr64) {
+	    WR64(IPEDMA_REG3_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, desc, 0));
 	    *(uint64_t*)last_written_addr_ptr = 0;
+	} else {
+	    WR(IPEDMA_REG2_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, desc, 0));
+	    *(uint32_t*)last_written_addr_ptr = 0;
+	}
 	
 	    // In ring buffer mode, the hardware taking care to preserve an empty buffer to help distinguish between
 	    // completely empty and completely full cases. In streaming mode, it is our responsibility to track this
@@ -355,15 +350,15 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
 	
 	for (i = 0; i < num_pages; i++) {
 	    uintptr_t bus_addr_check, bus_addr = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, pages, i);
-	    if (ctx->version < 3) {
-		WR(IPEDMA_REG2_PAGE_ADDR, bus_addr);
-	    } else {
+	    if (ctx->addr64) {
 		WR64(IPEDMA_REG3_PAGE_ADDR, bus_addr);
+	    } else {
+		WR(IPEDMA_REG2_PAGE_ADDR, bus_addr);
 	    }
 
 	    if (bus_addr%4096) printf("Bad address %lu: %lx\n", i, bus_addr);
 
-	    if (ctx->version < 3) {
+	    if ((!ctx->addr64)&&(!ctx->streaming)) {
 	        RD(IPEDMA_REG2_PAGE_ADDR, bus_addr_check);
 		if (bus_addr_check != bus_addr) {
 		    pcilib_error("Written (%x) and read (%x) bus addresses does not match\n", bus_addr, bus_addr_check);
@@ -449,13 +444,13 @@ int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcil
 
     if (!status) return -1;
 
-    if (ctx->version < 3) {
+    if (ctx->addr64) {
+	last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
+	last_written_addr = *(uint64_t*)last_written_addr_ptr;
+    } else {
 	if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t);
 	else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t);
 	last_written_addr = *(uint32_t*)last_written_addr_ptr;
-    } else {
-	last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
-	last_written_addr = *(uint64_t*)last_written_addr_ptr;
     }
 
     pcilib_debug(DMA, "Current DMA status      - last read: %4u, last_read_addr: %4u (0x%x), last_written: %4lu (0x%lx)", ctx->last_read, 
@@ -563,18 +558,17 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
 
     desc_va = (void*)pcilib_kmem_get_ua(ctx->dmactx.pcilib, ctx->desc);
 
-    if (ctx->version < 3) {
+    if (ctx->addr64) {
+	last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
+	empty_detected_ptr = desc_va + sizeof(uint32_t);
+//	empty_detected_ptr = &empty_detected_dummy;
+    } else {
 	if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t);
 	else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t);
 	empty_detected_ptr = NULL; // Not properly supported
 //	empty_detected_ptr = last_written_addr_ptr - 2;
-    } else {
-	last_written_addr_ptr = desc_va + 2 * sizeof(uint32_t);
-	empty_detected_ptr = desc_va + sizeof(uint32_t);
-//	empty_detected_ptr = &empty_detected_dummy;
     }
 
-
     switch (sched_getscheduler(0)) {
      case SCHED_FIFO:
      case SCHED_RR:
@@ -666,10 +660,10 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
 	    else last_free = ctx->ring_size - 1;
 
 	    uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, last_free);
-	    if (ctx->version < 3) {
-		WR(IPEDMA_REG2_PAGE_ADDR, buf_ba);
-	    } else {
+	    if (ctx->addr64) {
 		WR64(IPEDMA_REG3_PAGE_ADDR, buf_ba);
+	    } else {
+		WR(IPEDMA_REG2_PAGE_ADDR, buf_ba);
 	    }
 # ifdef IPEDMA_STREAMING_CHECKS
 	    pcilib_register_value_t streaming_status;

+ 6 - 5
dma/ipe.h

@@ -44,7 +44,7 @@ static const pcilib_dma_engine_description_t ipe_dma_engines[] = {
 
 static const pcilib_register_bank_description_t ipe_dma_banks[] = {
     { PCILIB_REGISTER_BANK_DMA, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, 0, 0, 32, 0x0200, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"},
-    { PCILIB_REGISTER_BANK_DMA1, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, 0x9000, 0x9000, 32, 0x0100, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma9000", "Additional DMA Registers"},
+    { PCILIB_REGISTER_BANK_DMA1, PCILIB_REGISTER_PROTOCOL_DEFAULT, PCILIB_BAR0, 0x9000, 0x9000, 32, 0x0100, PCILIB_LITTLE_ENDIAN, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma9000", "DMA Application Registers"},
     { PCILIB_REGISTER_BANK_DMACONF, PCILIB_REGISTER_PROTOCOL_SOFTWARE, PCILIB_BAR_NOBAR, 0, 0, 32, 0x1000, PCILIB_HOST_ENDIAN, PCILIB_HOST_ENDIAN, "0x%lx", "dmaconf", "DMA Configuration"},
     { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
 };
@@ -71,9 +71,10 @@ static const pcilib_register_description_t ipe_dma_registers[] = {
     {0x000C, 	24, 	8, 	0, 	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_up_addr",  			"Upper address for 64 bit memory addressing"},
     {0x0010, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_count",  		"Write DMA TLP Count"},
     {0x0014, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_pattern",  		"DMA generator data pattern"},
-    {0x0018, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_mode_flags",		"DMA operation mode"},
-    {0x0018, 	0, 	4, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "pcie_gen",  			"PCIe version 2/3 depending on the used XILINX core"},
-    {0x0018, 	4, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "streaming_dma", 			"Streaming mode (enabled/disabled)"},
+    {0x0018, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_firmware_mode",		"DMA operation mode"},
+    {0x0018, 	0, 	4, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_firmware_gen",  		"Generation of DMA engine (2/3 depending on the used XILINX core and PCIe generation)"},
+    {0x0018, 	4, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_firmware_streaming",		"Streaming mode (enabled/disabled)"},
+    {0x0018, 	16, 	16, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_firmware_version", 		"Version of DMA firmware"},
     {0x0028, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_perf",			"MWR Performance"},
     {0x003C, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "cfg_lnk_width",		"Negotiated and max width of PCIe Link"},
     {0x003C, 	0, 	6, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_cap_max_lnk_width", 		"Max link width"},
@@ -101,7 +102,7 @@ static const pcilib_register_description_t ipe_dma_app_registers[] = {
     {0x0000,	8,	1,	0,	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA1, "fix_cntgen",			"Enable fixed pattern mode of dummy generator"},
     {0x0004,	0,	32,	0,	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA1, "cntgen_pattern",		"Pattern for fixed pattern dummy generator"},
     {0x0008,	0,	32,	0,	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA1, "update_word0",		"Content of first 32-bit word in the progress register"},
-    {0x0020,	0,	32,	0,	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA1, "dma_firmware",		"Version of DMA firmware"},
+    {0x0030,	0,	32,	0,	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA1, "dma_app_version",		"Version of DMA application"},
     {0,		0,	0,	0,	0x00000000,	0,                                           0,                        0, NULL, 			NULL}
 };
 

+ 13 - 7
dma/ipe_private.h

@@ -28,13 +28,16 @@
 #define REG(bank, addr) ((bank<<IPEDMA_REG_BANK_SHIFT)|addr)
 #define CONFREG(addr) REG(2, addr)
 
-#define IPEDMA_REG_VERSION		REG(1, 0x20)
+#define IPEDMA_REG_VERSION		0x18
+#define IPEDMA_REG_APPVERSION		REG(1, 0x20)
+#define IPEDMA_GENERATION(ver)          (ver&0xF)
+#define IPEDMA_STREAMING(ver)           ((ver>>4)&0x1)
+#define IPEDMA_VERSION(ver)             ((ver>>16)&0xFFFF)
 
 #define IPEDMA_REG_RESET		0x00
 #define IPEDMA_REG_CONTROL		0x04
 #define IPEDMA_REG_TLP_SIZE		0x0C
 #define IPEDMA_REG_TLP_COUNT		0x10
-#define IPEDMA_REG_PCIE_GEN		0x18
 #define IPEDMA_REG_UPDATE_THRESHOLD	0x60
 #define IPEDMA_REG_STREAMING_STATUS	0x68
 
@@ -54,8 +57,8 @@
 #define IPEDMA_FLAG_NOSYNC		0x01		/**< Do not call kernel space for page synchronization */
 #define IPEDMA_FLAG_NOSLEEP		0x02		/**< Do not sleep in the loop while waiting for the data */
 
-#define IPEDMA_MASK_PCIE_GEN		0xF
-#define IPEDMA_MASK_STREAMING_MODE	0x10
+//#define IPEDMA_MASK_PCIE_GEN		0xF
+//#define IPEDMA_MASK_STREAMING_MODE	0x10
 
 #define IPEDMA_RESET_DELAY		10000		/**< Sleep between accessing DMA control and reset registers */
 #define IPEDMA_ADD_PAGE_DELAY		1000		/**< Delay between submitting successive DMA pages into IPEDMA_REG_PAGE_ADDR register */
@@ -84,13 +87,16 @@ struct ipe_dma_s {
     pcilib_irq_type_t irq_preserve;	/**< indicates that IRQs should not be disabled during clean-up */
     int irq_started;			/**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */    
 
-    uint32_t version;			/**< hardware version */
+    uint32_t gen;                       /**< hardware generation, currently corresponds to PCIe generation 2/3 */
+    uint32_t version;			/**< hardware revision */
+    int mode64;				/**< indicates 64-bit operation mode (for gen2, gen3 always operates in 64-bit mode) */
+    int addr64;                         /**< indicates that 64-bit addressing mode is used (gen3 only) */
+    int streaming;			/**< indicates if DMA is operating in streaming or ring-buffer mode (gen3 only) */
+
     int started;			/**< indicates that DMA buffers are initialized and reading is allowed */
     int writting;			/**< indicates that we are in middle of writting packet */
     int reused;				/**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */
     int preserve;			/**< indicates that DMA should not be stopped during clean-up */
-    int mode64;				/**< indicates 64-bit operation mode */
-    int streaming;			/**< indicates if DMA is operating in streaming or ring-buffer mode */
 
     uint32_t dma_flags;			/**< Various operation flags, see IPEDMA_FLAG_* */
     size_t dma_timeout;			/**< DMA timeout,IPEDMA_DMA_TIMEOUT is used by default */