From 1aafef50177b850efda576259cb78d2df7d03259 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Jun 2011 04:28:59 +0200 Subject: A bit of DMA infrastructure --- cli.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- driver/base.h | 2 +- driver/ioctl.c | 4 ++-- driver/pciDriver.h | 4 ++-- pci.c | 40 +++++++++++++++++++++++++++++----------- pci.h | 13 +++++++++---- pcilib.h | 35 ++++++++++++++++++++++++++++++++++- 7 files changed, 126 insertions(+), 24 deletions(-) diff --git a/cli.c b/cli.c index 73449ee..4a5aafc 100644 --- a/cli.c +++ b/cli.c @@ -167,8 +167,10 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { int i; pcilib_register_bank_description_t *banks; pcilib_register_description_t *registers; + pcilib_event_description_t *events; - const pci_board_info *board_info = pcilib_get_board_info(handle); + const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); + const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle); for (i = 0; i < PCILIB_MAX_BANKS; i++) { if (board_info->bar_length[i] > 0) { @@ -188,6 +190,36 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } } printf("\n"); + + if ((dma_info)&&(dma_info->engines)) { + printf("DMA Engines: \n"); + for (i = 0; dma_info->engines[i]; i++) { + pcilib_dma_engine_description_t *engine = dma_info->engines[i]; + printf(" DMA %2d ", engine->addr); + switch (engine->direction) { + case PCILIB_DMA_FROM_DEVICE: + printf("C2S"); + break; + case PCILIB_DMA_TO_DEVICE: + printf("S2C"); + break; + case PCILIB_DMA_BIDIRECTIONAL: + printf("BI "); + break; + } + printf(" - Type: "); + switch (engine->type) { + case PCILIB_DMA_TYPE_BLOCK: + printf("Block"); + break; + case PCILIB_DMA_TYPE_PACKET: + printf("Packet"); + break; + } + + printf(", Size: %08lx", engine->max_bytes); + } + } if ((bank)&&(bank != (char*)-1)) banks = NULL; else banks = pcilib_model[model].banks; @@ -239,10 +271,24 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } printf("\n"); } + + if (bank == (char*)-1) events = NULL; + else events = pcilib_model[model].events; + + if (events) { + printf("Events: \n"); + for (i = 0; events[i].name; i++) { + printf(" %s", events[i].name); + if ((events[i].description)&&(events[i].description[0])) { + printf(": %s", events[i].description); + } + } + printf("\n"); + } } void Info(pcilib_t *handle, pcilib_model_t model) { - const pci_board_info *board_info = pcilib_get_board_info(handle); + const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); printf("Vendor: %x, Device: %x, Interrupt Pin: %i, Interrupt Line: %i\n", board_info->vendor_id, board_info->device_id, board_info->interrupt_pin, board_info->interrupt_line); List(handle, model, (char*)-1); @@ -257,7 +303,7 @@ int Benchmark(pcilib_t *handle, pcilib_bar_t bar) { unsigned long time; unsigned int size, max_size; - const pci_board_info *board_info = pcilib_get_board_info(handle); + const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); if (bar < 0) { unsigned long maxlength = 0; diff --git a/driver/base.h b/driver/base.h index 743eee5..84f0aad 100644 --- a/driver/base.h +++ b/driver/base.h @@ -53,7 +53,7 @@ static const __devinitdata struct pci_device_id pcidriver_ids[] = { /* prototypes for internal driver functions */ int pcidriver_pci_read( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd ); int pcidriver_pci_write( pcidriver_privdata_t *privdata, pci_cfg_cmd *pci_cmd ); -int pcidriver_pci_info( pcidriver_privdata_t *privdata, pci_board_info *pci_info ); +int pcidriver_pci_info( pcidriver_privdata_t *privdata, pcilib_board_info_t *pci_info ); int pcidriver_mmap_pci( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap , int bar ); int pcidriver_mmap_kmem( pcidriver_privdata_t *privdata, struct vm_area_struct *vmap ); diff --git a/driver/ioctl.c b/driver/ioctl.c index 6240d31..dacf94a 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -143,7 +143,7 @@ static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg) { int ret; int bar; - READ_FROM_USER(pci_board_info, pci_info); + READ_FROM_USER(pcilib_board_info_t, pci_info); pci_info.vendor_id = privdata->pdev->vendor; pci_info.device_id = privdata->pdev->device; @@ -163,7 +163,7 @@ static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg) pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar); } - WRITE_TO_USER(pci_board_info, pci_info); + WRITE_TO_USER(pcilib_board_info_t, pci_info); return 0; } diff --git a/driver/pciDriver.h b/driver/pciDriver.h index 083b0b2..98c1301 100644 --- a/driver/pciDriver.h +++ b/driver/pciDriver.h @@ -152,7 +152,7 @@ typedef struct { unsigned long bar_start[6]; unsigned long bar_length[6]; unsigned long bar_flags[6]; -} pci_board_info; +} pcilib_board_info_t; /* ioctl interface */ @@ -182,7 +182,7 @@ typedef struct { /* And now, the methods to access the PCI configuration area */ #define PCIDRIVER_IOC_PCI_CFG_RD _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 10, pci_cfg_cmd * ) #define PCIDRIVER_IOC_PCI_CFG_WR _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 11, pci_cfg_cmd * ) -#define PCIDRIVER_IOC_PCI_INFO _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 12, pci_board_info * ) +#define PCIDRIVER_IOC_PCI_INFO _IOWR( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 12, pcilib_board_info_t * ) /* Clear interrupt queues */ #define PCIDRIVER_IOC_CLEAR_IOQ _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 13 ) diff --git a/pci.c b/pci.c index 6221ddf..f40b9ed 100644 --- a/pci.c +++ b/pci.c @@ -31,7 +31,8 @@ struct pcilib_s { int handle; uintptr_t page_mask; - pci_board_info board_info; + pcilib_board_info_t board_info; + pcilib_dma_info_t dma_info; pcilib_model_t model; char *bar_space[PCILIB_MAX_BANKS]; @@ -45,7 +46,10 @@ struct pcilib_s { // char *data_space; // size_t data_size; - void *event_ctx; + + pcilib_dma_context_t *dma_ctx; + + pcilib_event_context_t *event_ctx; #ifdef PCILIB_FILE_IO int file_io_handle; @@ -96,7 +100,7 @@ pcilib_t *pcilib_open(const char *device, pcilib_model_t model) { return ctx; } -const pci_board_info *pcilib_get_board_info(pcilib_t *ctx) { +const pcilib_board_info_t *pcilib_get_board_info(pcilib_t *ctx) { int ret; if (ctx->page_mask == (uintptr_t)-1) { @@ -112,6 +116,18 @@ const pci_board_info *pcilib_get_board_info(pcilib_t *ctx) { return &ctx->board_info; } +const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx) { + if (!ctx->dma_ctx) { + pcilib_model_t model = pcilib_get_model(ctx); + pcilib_dma_api_description_t *api = pcilib_model[model].dma_api; + if ((api)&&(api->init)) ctx->dma_ctx = api->init(ctx); + + if (!ctx->dma_ctx) return NULL; + } + + return &ctx->dma_info; +} + pcilib_context_t *pcilib_get_implementation_context(pcilib_t *ctx) { return ctx->event_ctx; } @@ -123,7 +139,7 @@ pcilib_model_t pcilib_get_model(pcilib_t *ctx) { //return PCILIB_MODEL_PCI; - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return PCILIB_MODEL_PCI; if ((board_info->vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info->device_id == PCIE_IPECAMERA_DEVICE_ID)) @@ -138,7 +154,7 @@ pcilib_model_t pcilib_get_model(pcilib_t *ctx) { static pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) { pcilib_bar_t i; - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return PCILIB_BAR_INVALID; for (i = 0; i < PCILIB_MAX_BANKS; i++) { @@ -149,7 +165,7 @@ static pcilib_bar_t pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size } static int pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size) { - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return PCILIB_ERROR_NOTFOUND; if (*bar == PCILIB_BAR_DETECT) { @@ -179,7 +195,7 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { void *res; int ret; - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return NULL; if (ctx->bar_space[bar]) return ctx->bar_space[bar]; @@ -212,7 +228,7 @@ void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) { } void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) { - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return; if (ctx->bar_space[bar]) return; @@ -396,7 +412,7 @@ static int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) { pcilib_bar_t i; if (!ctx->data_bar_mapped) { - const pci_board_info *board_info = pcilib_get_board_info(ctx); + const pcilib_board_info_t *board_info = pcilib_get_board_info(ctx); if (!board_info) return PCILIB_ERROR_FAILED; err = pcilib_map_register_space(ctx); @@ -511,9 +527,11 @@ void pcilib_close(pcilib_t *ctx) { if (ctx) { pcilib_model_t model = pcilib_get_model(ctx); - pcilib_event_api_description_t *api = pcilib_model[model].event_api; + pcilib_event_api_description_t *eapi = pcilib_model[model].event_api; + pcilib_dma_api_description_t *dapi = pcilib_model[model].dma_api; - if ((api)&&(api->free)) api->free(ctx->event_ctx); + if ((eapi)&&(eapi->free)) eapi->free(ctx->event_ctx); + if ((dapi)&&(dapi->free)) dapi->free(ctx->dma_ctx); for (i = 0; i < PCILIB_MAX_BANKS; i++) { if (ctx->bar_space[i]) { diff --git a/pci.h b/pci.h index e3e5c9a..0a7a55e 100644 --- a/pci.h +++ b/pci.h @@ -5,19 +5,24 @@ #include "driver/pciDriver.h" + +typedef void pcilib_event_context_t; +typedef void pcilib_dma_context_t; + #include "pcilib.h" -const pci_board_info *pcilib_get_board_info(pcilib_t *ctx); +const pcilib_board_info_t *pcilib_get_board_info(pcilib_t *ctx); +const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx); #ifdef _PCILIB_PCI_C # include "ipecamera/model.h" # include "default.h" pcilib_model_description_t pcilib_model[3] = { - { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL }, - { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL }, - { 4, PCILIB_BIG_ENDIAN, ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, ipecamera_events, &ipecamera_image_api } + { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL, NULL }, + { 4, PCILIB_HOST_ENDIAN, NULL, NULL, NULL, NULL, NULL }, + { 4, PCILIB_BIG_ENDIAN, ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, ipecamera_events, NULL, &ipecamera_image_api } }; pcilib_protocol_description_t pcilib_protocol[3] = { diff --git a/pcilib.h b/pcilib.h index 1df65f6..6d52714 100644 --- a/pcilib.h +++ b/pcilib.h @@ -27,6 +27,9 @@ typedef uint8_t pcilib_register_bank_addr_t; /**< Type holding the register bank typedef uint8_t pcilib_register_size_t; /**< Type holding the size in bits of the register */ typedef uint32_t pcilib_register_value_t; /**< Type holding the register value */ typedef uint64_t pcilib_event_id_t; +typedef uint8_t pcilib_dma_addr_t; +typedef uint8_t pcilib_dma_t; + typedef uint32_t pcilib_event_t; @@ -128,9 +131,38 @@ typedef struct { int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); } pcilib_protocol_description_t; +typedef enum { + PCILIB_DMA_FROM_DEVICE = 1, + PCILIB_DMA_TO_DEVICE = 2, + PCILIB_DMA_BIDIRECTIONAL = 3 +} pcilib_dma_direction_t; + +typedef enum { + PCILIB_DMA_TYPE_BLOCK, + PCILIB_DMA_TYPE_PACKET +} pcilib_dma_type_t; + +typedef struct { + pcilib_dma_addr_t addr; + pcilib_dma_type_t type; + pcilib_dma_direction_t direction; + size_t max_bytes; +} pcilib_dma_engine_description_t; + +typedef struct { + pcilib_dma_engine_description_t **engines; +} pcilib_dma_info_t; typedef int (*pcilib_callback_t)(pcilib_event_t event, pcilib_event_id_t event_id, void *user); +typedef struct { + pcilib_dma_context_t *(*init)(pcilib_t *ctx); + void (*free)(pcilib_dma_context_t *ctx); + +// int (*read)(pcilib_dma_context_t *ctx, pcilib_event_t event_mask, pcilib_callback_t callback, void *user); +// int (*write)(pcilib_dma_context_t *ctx); +} pcilib_dma_api_description_t; + typedef struct { pcilib_context_t *(*init)(pcilib_t *ctx); void (*free)(pcilib_context_t *ctx); @@ -154,7 +186,8 @@ typedef struct { pcilib_register_bank_description_t *banks; pcilib_register_range_t *ranges; pcilib_event_description_t *events; - + + pcilib_dma_api_description_t *dma_api; pcilib_event_api_description_t *event_api; } pcilib_model_description_t; -- cgit v1.2.3