sps_map.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. /**
  13. * Connection mapping table managment for SPS device driver.
  14. */
  15. #include <linux/types.h> /* u32 */
  16. #include <linux/kernel.h> /* pr_info() */
  17. #include <linux/memory.h> /* memset */
  18. #include "spsi.h"
  19. /* Module state */
  20. struct sps_map_state {
  21. const struct sps_map *maps;
  22. u32 num_maps;
  23. u32 options;
  24. };
  25. static struct sps_map_state sps_maps;
  26. /**
  27. * Initialize connection mapping module
  28. *
  29. */
  30. int sps_map_init(const struct sps_map *map_props, u32 options)
  31. {
  32. const struct sps_map *maps;
  33. /* Are there any connection mappings? */
  34. memset(&sps_maps, 0, sizeof(sps_maps));
  35. if (map_props == NULL)
  36. return 0;
  37. /* Init the module state */
  38. sps_maps.maps = map_props;
  39. sps_maps.options = options;
  40. for (maps = sps_maps.maps;; maps++, sps_maps.num_maps++)
  41. if (maps->src.periph_class == SPS_CLASS_INVALID &&
  42. maps->src.periph_phy_addr == SPS_ADDR_INVALID)
  43. break;
  44. SPS_DBG("sps: %d mappings", sps_maps.num_maps);
  45. return 0;
  46. }
  47. /**
  48. * De-initialize connection mapping module
  49. *
  50. */
  51. void sps_map_de_init(void)
  52. {
  53. memset(&sps_maps, 0, sizeof(sps_maps));
  54. }
  55. /**
  56. * Find matching connection mapping
  57. *
  58. */
  59. int sps_map_find(struct sps_connect *connect)
  60. {
  61. const struct sps_map *map;
  62. u32 i;
  63. void *desc;
  64. void *data;
  65. /* Are there any connection mappings? */
  66. if (sps_maps.num_maps == 0)
  67. return SPS_ERROR;
  68. /* Search the mapping table for a match to the specified connection */
  69. for (i = sps_maps.num_maps, map = sps_maps.maps;
  70. i > 0; i--, map++)
  71. if (map->src.periph_class == (u32) connect->source &&
  72. map->dest.periph_class == (u32) connect->destination
  73. && map->config == (u32) connect->config)
  74. break;
  75. if (i == 0)
  76. return SPS_ERROR;
  77. /*
  78. * Before modifying client parameter struct, perform all
  79. * operations that might fail
  80. */
  81. desc = spsi_get_mem_ptr(map->desc_base);
  82. if (desc == NULL) {
  83. SPS_ERR("sps:Cannot get virt addr for I/O buffer: %pa\n",
  84. &map->desc_base);
  85. return SPS_ERROR;
  86. }
  87. if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
  88. data = spsi_get_mem_ptr(map->data_base);
  89. if (data == NULL) {
  90. SPS_ERR("sps:Can't get virt addr for I/O buffer: %pa",
  91. &map->data_base);
  92. return SPS_ERROR;
  93. }
  94. } else {
  95. data = NULL;
  96. }
  97. /* Copy mapping values to client parameter struct */
  98. if (connect->source != SPS_DEV_HANDLE_MEM)
  99. connect->src_pipe_index = map->src.pipe_index;
  100. if (connect->destination != SPS_DEV_HANDLE_MEM)
  101. connect->dest_pipe_index = map->dest.pipe_index;
  102. if (connect->mode == SPS_MODE_SRC)
  103. connect->event_thresh = map->src.event_thresh;
  104. else
  105. connect->event_thresh = map->dest.event_thresh;
  106. connect->desc.size = map->desc_size;
  107. connect->desc.phys_base = map->desc_base;
  108. connect->desc.base = desc;
  109. if (map->data_size > 0 && map->data_base != SPS_ADDR_INVALID) {
  110. connect->data.size = map->data_size;
  111. connect->data.phys_base = map->data_base;
  112. connect->data.base = data;
  113. }
  114. return 0;
  115. }