summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NOTES52
-rw-r--r--ToDo6
-rw-r--r--cli.c9
-rw-r--r--dma.c24
-rw-r--r--dma.h1
-rw-r--r--dma/nwl_dma.h2
-rw-r--r--dma/nwl_engine.c21
-rw-r--r--dma/nwl_irq.c16
-rw-r--r--irq.c4
-rw-r--r--pcilib.h11
10 files changed, 116 insertions, 30 deletions
diff --git a/NOTES b/NOTES
index 47b2d51..eacf43c 100644
--- a/NOTES
+++ b/NOTES
@@ -187,3 +187,55 @@ Register/DMA Configuration
a) Writting/Reading register values
b) Wait until <register1>=<value> on <register2>=<value> report error
c) ... ?
+
+IRQ Handling
+============
+ IRQ types: DMA IRQ, Event IRQ, other types
+ IRQ hardware source: To allow purely user-space implementation, as general
+ rule, only a single (standard) source should be used.
+ IRQ source: The dma/event engines, however, may detail this hardware source
+ and produce real IRQ source basing on the values of registers. For example,
+ for DMA IRQs the source may present engine number and for Event IRQs the
+ source may present event type.
+
+ Only types can be enabled or disabled. The sources are enabled/disabled
+ by enabling/disabling correspondent DMA engines or Event types. The expected
+ workflow is following:
+ * We enabling IRQs in user-space (normally setting some registers). Normally,
+ just an Event IRQs, the DMA if necessary will be managed by DMA engine itself.
+ * We waiting for standard IRQ from hardware (driver)
+ * In the user space, we are checking registers to find out the real source
+ of IRQ (driver reports us just hardware source), generating appropriate
+ events, and acknowledge IRQ. This is dependent on implementation and should
+ be managed inside event API.
+
+ I.e. the driver implements just two methods pcilib_wait_irq(hw_source),
+ pcilib_clear_irq(hw_source). Only a few hardware IRQ sources are defined.
+ In most cirstumances, the IRQ_SOURCE_DEFAULT is used.
+
+ The DMA engine may provide 3 additional methods, to enable, disable,
+ and acknowledge IRQ.
+
+ ... To be decided in details upon the need...
+
+Updating Firmware
+=================
+ - JTag should be connected to left USB connector on the board
+ - The computer should be tourned off and on before programming
+ - The application is called 'impact'
+ Cancel initial proposals
+ Left click on USB connection
+ Select "Boundary Scan" and double click
+ Click "Initiate Chain" on right element (left click)
+ Say yes, Select bit file, Cancel
+ Click "Assign new CF file" on right element (left click
+ Select the bit file
+ Select xv6vlx240t
+ Program
+ - Firmwares are in
+ v.2: /home/uros/Repo/UFO2_last_good_version_UFO2.bit
+ v.3: /home/uros/Repo/UFO3
+ Step5 - best working revision
+ Step6 - last revision
+
+ \ No newline at end of file
diff --git a/ToDo b/ToDo
index 328eb41..4370807 100644
--- a/ToDo
+++ b/ToDo
@@ -7,15 +7,15 @@ High Priority (we would need it for IPE Camera)
=============
1. Serialize access to the registers across applications
2. Protect kmem_entries in the driver using spinlock
- 3. Use bus-addresses instead of physcial addresses for DMA
- 4. CMake build system
+ 3. CMake build system
Normal Priority (it would make just few things a bit easier)
===============
1. Implement software registers (stored in kernel-memory)
2. Support FIFO reads/writes from/to registers
3. Provide OR and AND operations on registers in cli
- 4. Support writting a data from binary file in cli
+ 4. Support writting a data from a binary file in cli
+ 5. Use bus-addresses instead of physcial addresses for DMA
Low Priority (only as generalization for other projects)
============
diff --git a/cli.c b/cli.c
index 22dbed8..c5df898 100644
--- a/cli.c
+++ b/cli.c
@@ -1077,6 +1077,11 @@ int ListKMEM(pcilib_t *handle, const char *device) {
}
closedir(dir);
+ if ((n_uses == 1)&&(uses[0].count == 0)) {
+ printf("No kernel memory is allocated\n");
+ return 0;
+ }
+
printf("Use Type Count Total Size REF Mode \n");
printf("--------------------------------------------------------------------------------\n");
for (useid = 0; useid < n_uses; useid++) {
@@ -1144,7 +1149,7 @@ int FreeKMEM(pcilib_t *handle, const char *device, const char *use, int force) {
return 0;
}
-int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_source_t irq_source, pcilib_timeout_t timeout) {
+int WaitIRQ(pcilib_t *handle, pcilib_model_description_t *model_info, pcilib_irq_hw_source_t irq_source, pcilib_timeout_t timeout) {
int err;
size_t count;
@@ -1186,7 +1191,7 @@ int main(int argc, char **argv) {
const char *event = NULL;
const char *dma_channel = NULL;
const char *use = NULL;
- pcilib_irq_source_t irq_source;
+ pcilib_irq_hw_source_t irq_source;
pcilib_dma_direction_t dma_direction = PCILIB_DMA_BIDIRECTIONAL;
pcilib_dma_engine_addr_t dma = PCILIB_DMA_ENGINE_ADDR_INVALID;
diff --git a/dma.c b/dma.c
index 7ae56f7..1bab0f9 100644
--- a/dma.c
+++ b/dma.c
@@ -114,7 +114,6 @@ int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flag
}
if (!ctx->model_info.dma_api->enable_irq) {
- //pcilib_error("The IRQs are not supported by configured DMA engine");
return 0;
}
@@ -136,13 +135,34 @@ int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags) {
}
if (!ctx->model_info.dma_api->disable_irq) {
- //pcilib_error("The IRQs are not supported by configured DMA engine");
return 0;
}
return ctx->model_info.dma_api->disable_irq(ctx->dma_ctx, flags);
}
+int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) {
+ int err;
+
+ const pcilib_dma_info_t *info = pcilib_get_dma_info(ctx);
+ if (!info) {
+ pcilib_error("DMA is not supported by the device");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (!ctx->model_info.dma_api) {
+ pcilib_error("DMA Engine is not configured in the current model");
+ return PCILIB_ERROR_NOTAVAILABLE;
+ }
+
+ if (!ctx->model_info.dma_api->acknowledge_irq) {
+ return 0;
+ }
+
+ return ctx->model_info.dma_api->acknowledge_irq(ctx->dma_ctx, irq_type, irq_source);
+}
+
+
typedef struct {
size_t size;
diff --git a/dma.h b/dma.h
index 0260872..b18ee56 100644
--- a/dma.h
+++ b/dma.h
@@ -13,6 +13,7 @@ struct pcilib_dma_api_description_s {
int (*enable_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags);
int (*disable_irq)(pcilib_dma_context_t *ctx, pcilib_dma_flags_t flags);
+ int (*acknowledge_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source);
int (*start_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
int (*stop_dma)(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h
index bdb3df0..d5068e2 100644
--- a/dma/nwl_dma.h
+++ b/dma/nwl_dma.h
@@ -11,6 +11,7 @@ void dma_nwl_free(pcilib_dma_context_t *vctx);
int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags);
int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags);
+int dma_nwl_acknowledge_irq(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source);
int dma_nwl_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
int dma_nwl_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
@@ -26,6 +27,7 @@ pcilib_dma_api_description_t nwl_dma_api = {
dma_nwl_free,
dma_nwl_enable_irq,
dma_nwl_disable_irq,
+ dma_nwl_acknowledge_irq,
dma_nwl_start,
dma_nwl_stop,
dma_nwl_write_fragment,
diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c
index 669dbbd..277ad23 100644
--- a/dma/nwl_engine.c
+++ b/dma/nwl_engine.c
@@ -77,12 +77,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
if (info->reused) {
info->preserve = 1;
- // Acknowledge asserted engine interrupts
- nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
- if (val & DMA_ENG_INT_ACTIVE_MASK) {
- val |= DMA_ENG_ALLINT_MASK;
- nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
- }
+ dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
#ifdef NWL_GENERATE_DMA_IRQ
dma_nwl_enable_engine_irq(ctx, dma);
@@ -131,11 +126,7 @@ int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
return PCILIB_ERROR_TIMEOUT;
}
- // Acknowledge asserted engine interrupts
- if (val & DMA_ENG_INT_ACTIVE_MASK) {
- val |= DMA_ENG_ALLINT_MASK;
- nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
- }
+ dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD);
@@ -206,12 +197,8 @@ int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
}
}
-
- // Acknowledge asserted engine interrupts
- if (val & DMA_ENG_INT_ACTIVE_MASK) {
- val |= DMA_ENG_ALLINT_MASK;
- nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
- }
+
+ dma_nwl_acknowledge_irq(ctx, PCILIB_DMA_IRQ, dma);
if (info->preserve) {
flags = PCILIB_KMEM_FLAG_REUSE;
diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c
index 86f1845..ae4aacc 100644
--- a/dma/nwl_irq.c
+++ b/dma/nwl_irq.c
@@ -100,6 +100,20 @@ int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
return 0;
}
+int dma_nwl_acknowledge_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source) {
+ uint32_t val;
+
+ nwl_dma_t *ctx = (nwl_dma_t*)vctx;
+ pcilib_nwl_engine_description_t *info = ctx->engines + irq_source;
+ if (irq_type != PCILIB_DMA_IRQ) return PCILIB_ERROR_NOTSUPPORTED;
+ if (irq_source >= ctx->n_engines) return PCILIB_ERROR_NOTAVAILABLE;
-// ACK
+ nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+ if (val & DMA_ENG_INT_ACTIVE_MASK) {
+ val |= DMA_ENG_ALLINT_MASK;
+ nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+ }
+
+ return 0;
+}
diff --git a/irq.c b/irq.c
index 6b2164c..3d387bb 100644
--- a/irq.c
+++ b/irq.c
@@ -17,7 +17,7 @@
#include "tools.h"
#include "error.h"
-int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, pcilib_timeout_t timeout, size_t *count) {
+int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source, pcilib_timeout_t timeout, size_t *count) {
int err;
interrupt_wait_t arg = { 0 };
@@ -40,7 +40,7 @@ int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, pcilib_timeout_t
return 0;
}
-int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_source_t source) {
+int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source) {
int err;
err = ioctl(ctx->handle, PCIDRIVER_IOC_CLEAR_IOQ, source);
diff --git a/pcilib.h b/pcilib.h
index 07f558a..e1cd7dc 100644
--- a/pcilib.h
+++ b/pcilib.h
@@ -16,7 +16,8 @@ typedef void pcilib_dma_context_t;
typedef struct pcilib_dma_api_description_s pcilib_dma_api_description_t;
typedef struct pcilib_event_api_description_s pcilib_event_api_description_t;
typedef struct pcilib_protocol_description_s pcilib_protocol_description_t;
-typedef unsigned int pcilib_irq_source_t;
+typedef unsigned int pcilib_irq_hw_source_t;
+typedef uint32_t pcilib_irq_source_t;
typedef uint8_t pcilib_bar_t; /**< Type holding the PCI Bar number */
typedef uint8_t pcilib_register_t; /**< Type holding the register ID within the Bank */
@@ -99,6 +100,7 @@ typedef enum {
#define PCILIB_TIMEOUT_INFINITE ((pcilib_timeout_t)-1)
#define PCILIB_TIMEOUT_IMMEDIATE 0
#define PCILIB_TIMEOUT_TRIGGER 0
+#define PCILIB_IRQ_SOURCE_DEFAULT 0
typedef int (*pcilib_dma_callback_t)(void *ctx, pcilib_dma_flags_t flags, size_t bufsize, void *buf);
typedef int (*pcilib_event_callback_t)(pcilib_event_t event, pcilib_event_id_t event_id, void *user);
@@ -204,11 +206,14 @@ void pcilib_close(pcilib_t *ctx);
int pcilib_start_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
int pcilib_stop_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags);
+
+ // Interrupt API is preliminary and can be significantly changed in future
int pcilib_enable_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags);
+int pcilib_acknowledge_irq(pcilib_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source);
int pcilib_disable_irq(pcilib_t *ctx, pcilib_dma_flags_t flags);
-int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_source_t source);
-int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_source_t source, pcilib_timeout_t timeout, size_t *count);
+int pcilib_wait_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source, pcilib_timeout_t timeout, size_t *count);
+int pcilib_clear_irq(pcilib_t *ctx, pcilib_irq_hw_source_t source);
void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar);
void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data);