diff options
Diffstat (limited to 'dma/ipe.c')
-rw-r--r-- | dma/ipe.c | 118 |
1 files changed, 56 insertions, 62 deletions
@@ -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; |