nwl.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #define _PCILIB_DMA_NWL_C
  2. #define _BSD_SOURCE
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <sys/time.h>
  8. #include "pci.h"
  9. #include "pcilib.h"
  10. #include "error.h"
  11. #include "tools.h"
  12. #include "nwl_private.h"
  13. #include "nwl_defines.h"
  14. int dma_nwl_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
  15. int err;
  16. nwl_dma_t *ctx = (nwl_dma_t*)vctx;
  17. if (!ctx->started) {
  18. // global initialization, should we do anything?
  19. ctx->started = 1;
  20. }
  21. if (dma == PCILIB_DMA_ENGINE_INVALID) return 0;
  22. else if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK;
  23. if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->engines[dma].preserve = 1;
  24. err = dma_nwl_start_engine(ctx, dma);
  25. return err;
  26. }
  27. int dma_nwl_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
  28. int err;
  29. int preserving = 0;
  30. nwl_dma_t *ctx = (nwl_dma_t*)vctx;
  31. if (!ctx->started) return 0;
  32. // stop everything
  33. if (dma == PCILIB_DMA_ENGINE_INVALID) {
  34. for (dma = 0; dma < ctx->n_engines; dma++) {
  35. if (flags&PCILIB_DMA_FLAG_PERSISTENT) {
  36. ctx->engines[dma].preserve = 0;
  37. }
  38. if (ctx->engines[dma].preserve) preserving = 1;
  39. err = dma_nwl_stop_engine(ctx, dma);
  40. if (err) return err;
  41. }
  42. // global cleanup, should we do anything?
  43. if (!preserving) {
  44. ctx->started = 0;
  45. }
  46. return 0;
  47. }
  48. if (dma > ctx->n_engines) return PCILIB_ERROR_INVALID_BANK;
  49. // ignorign previous setting if flag specified
  50. if (flags&PCILIB_DMA_FLAG_PERSISTENT) {
  51. ctx->engines[dma].preserve = 0;
  52. }
  53. return dma_nwl_stop_engine(ctx, dma);
  54. }
  55. pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib, pcilib_dma_modification_t type, void *arg) {
  56. int i;
  57. int err;
  58. pcilib_dma_engine_t n_engines;
  59. pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
  60. nwl_dma_t *ctx = malloc(sizeof(nwl_dma_t));
  61. if (ctx) {
  62. memset(ctx, 0, sizeof(nwl_dma_t));
  63. ctx->pcilib = pcilib;
  64. ctx->type = type;
  65. if (type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
  66. ctx->dmactx.ignore_eop = 1;
  67. }
  68. pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
  69. if (dma_bank == PCILIB_REGISTER_BANK_INVALID) {
  70. free(ctx);
  71. pcilib_error("DMA Register Bank could not be found");
  72. return NULL;
  73. }
  74. ctx->dma_bank = model_info->banks + dma_bank;
  75. ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr);
  76. for (i = 0, n_engines = 0; i < 2 * PCILIB_MAX_DMA_ENGINES; i++) {
  77. char *addr = ctx->base_addr + DMA_OFFSET + i * DMA_ENGINE_PER_SIZE;
  78. memset(ctx->engines + n_engines, 0, sizeof(pcilib_nwl_engine_description_t));
  79. err = dma_nwl_read_engine_config(ctx, ctx->engines + n_engines, addr);
  80. if (err) continue;
  81. pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines));
  82. ++n_engines;
  83. }
  84. pcilib_set_dma_engine_description(pcilib, n_engines, NULL);
  85. ctx->n_engines = n_engines;
  86. err = nwl_add_registers(ctx);
  87. if (err) {
  88. free(ctx);
  89. pcilib_error("Failed to add DMA registers");
  90. return NULL;
  91. }
  92. }
  93. return (pcilib_dma_context_t*)ctx;
  94. }
  95. void dma_nwl_free(pcilib_dma_context_t *vctx) {
  96. nwl_dma_t *ctx = (nwl_dma_t*)vctx;
  97. if (ctx) {
  98. if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx);
  99. dma_nwl_free_irq(ctx);
  100. dma_nwl_stop(vctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT);
  101. free(ctx);
  102. }
  103. }