diff options
| author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-18 16:42:51 +0200 | 
|---|---|---|
| committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-18 16:42:51 +0200 | 
| commit | 9e424252a35879f121e7ea4531a9ab3dda56d595 (patch) | |
| tree | 2cf3dfeceb67eee989a6cc4b20f639baf68748f8 | |
| parent | e9904116a5b39e47744fb39cc5aad574c8bee03f (diff) | |
| download | ipecamera-9e424252a35879f121e7ea4531a9ab3dda56d595.tar.gz ipecamera-9e424252a35879f121e7ea4531a9ab3dda56d595.tar.bz2 ipecamera-9e424252a35879f121e7ea4531a9ab3dda56d595.tar.xz ipecamera-9e424252a35879f121e7ea4531a9ab3dda56d595.zip | |
IRQ acknowledgement support in the engine API
| -rw-r--r-- | NOTES | 52 | ||||
| -rw-r--r-- | ToDo | 6 | ||||
| -rw-r--r-- | cli.c | 9 | ||||
| -rw-r--r-- | dma.c | 24 | ||||
| -rw-r--r-- | dma.h | 1 | ||||
| -rw-r--r-- | dma/nwl_dma.h | 2 | ||||
| -rw-r--r-- | dma/nwl_engine.c | 21 | ||||
| -rw-r--r-- | dma/nwl_irq.c | 16 | ||||
| -rw-r--r-- | irq.c | 4 | ||||
| -rw-r--r-- | pcilib.h | 11 | 
10 files changed, 116 insertions, 30 deletions
| @@ -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 @@ -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)  ============ @@ -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; @@ -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; @@ -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; +} @@ -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); @@ -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); | 
