event.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #define _POSIX_C_SOURCE 199309L
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <strings.h>
  5. #include <stdlib.h>
  6. #include <stdint.h>
  7. #include <stdarg.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/mman.h>
  12. #include <arpa/inet.h>
  13. #include <errno.h>
  14. #include <assert.h>
  15. #include "pci.h"
  16. #include "tools.h"
  17. #include "error.h"
  18. pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) {
  19. int i;
  20. pcilib_register_bank_t res;
  21. unsigned long addr;
  22. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  23. pcilib_event_description_t *events = model_info->events;
  24. for (i = 0; events[i].name; i++) {
  25. if (!strcasecmp(events[i].name, event)) return (1<<i);
  26. }
  27. return (pcilib_event_t)-1;
  28. }
  29. int pcilib_reset(pcilib_t *ctx) {
  30. pcilib_event_api_description_t *api;
  31. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  32. api = model_info->event_api;
  33. if (!api) {
  34. pcilib_error("Event API is not supported by the selected model");
  35. return PCILIB_ERROR_NOTSUPPORTED;
  36. }
  37. if (api->reset)
  38. return api->reset(ctx->event_ctx);
  39. return 0;
  40. }
  41. int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user) {
  42. pcilib_event_api_description_t *api;
  43. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  44. api = model_info->event_api;
  45. if (!api) {
  46. pcilib_error("Event API is not supported by the selected model");
  47. return PCILIB_ERROR_NOTSUPPORTED;
  48. }
  49. if (api->start)
  50. return api->start(ctx->event_ctx, event_mask, callback, user);
  51. return 0;
  52. }
  53. int pcilib_stop(pcilib_t *ctx) {
  54. pcilib_event_api_description_t *api;
  55. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  56. api = model_info->event_api;
  57. if (!api) {
  58. pcilib_error("Event API is not supported by the selected model");
  59. return PCILIB_ERROR_NOTSUPPORTED;
  60. }
  61. if (api->stop)
  62. return api->stop(ctx->event_ctx);
  63. return 0;
  64. }
  65. pcilib_event_id_t pcilib_get_next_event(pcilib_t *ctx, pcilib_event_t event_mask, const struct timespec *timeout) {
  66. pcilib_event_api_description_t *api;
  67. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  68. api = model_info->event_api;
  69. if (!api) {
  70. pcilib_error("Event API is not supported by the selected model");
  71. return PCILIB_ERROR_NOTSUPPORTED;
  72. }
  73. if (api->next_event)
  74. return api->next_event(ctx->event_ctx, event_mask, timeout);
  75. pcilib_error("Event enumeration is not suppored by API");
  76. return PCILIB_EVENT_ID_INVALID;
  77. }
  78. int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
  79. pcilib_event_api_description_t *api;
  80. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  81. api = model_info->event_api;
  82. if (!api) {
  83. pcilib_error("Event API is not supported by the selected model");
  84. return PCILIB_ERROR_NOTSUPPORTED;
  85. }
  86. if (api->trigger)
  87. return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data);
  88. pcilib_error("Self triggering is not supported by the selected model");
  89. return PCILIB_ERROR_NOTSUPPORTED;
  90. }
  91. void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) {
  92. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  93. pcilib_event_api_description_t *api = model_info->event_api;
  94. if (!api) {
  95. pcilib_error("Event API is not supported by the selected model");
  96. return NULL;
  97. }
  98. if (api->get_data)
  99. return api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, size);
  100. return NULL;
  101. }
  102. void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) {
  103. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  104. pcilib_event_api_description_t *api = model_info->event_api;
  105. if (!api) {
  106. pcilib_error("Event API is not supported by the selected model");
  107. return NULL;
  108. }
  109. if (api->get_data)
  110. return api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, size);
  111. return NULL;
  112. }
  113. int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id) {
  114. pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
  115. pcilib_event_api_description_t *api = model_info->event_api;
  116. if (!api) {
  117. pcilib_error("Event API is not supported by the selected model");
  118. return PCILIB_ERROR_NOTSUPPORTED;
  119. }
  120. if (api->return_data)
  121. return api->return_data(ctx->event_ctx, event_id);
  122. return 0;
  123. }
  124. typedef struct {
  125. pcilib_t *ctx;
  126. size_t *size;
  127. void **data;
  128. } pcilib_grab_callback_user_data_t;
  129. static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) {
  130. int err;
  131. void *data;
  132. size_t size;
  133. int allocated = 0;
  134. pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser;
  135. data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size);
  136. if (!data) {
  137. pcilib_error("Error getting event data");
  138. return PCILIB_ERROR_FAILED;
  139. }
  140. if (*(user->data)) {
  141. if ((user->size)&&(*(user->size) < size)) {
  142. pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size);
  143. return PCILIB_ERROR_MEMORY;
  144. }
  145. *(user->size) = size;
  146. } else {
  147. *(user->data) = malloc(size);
  148. if (!*(user->data)) {
  149. pcilib_error("Memory allocation (%i bytes) for event data is failed");
  150. return PCILIB_ERROR_MEMORY;
  151. }
  152. if (*(user->size)) *(user->size) = size;
  153. allocated = 1;
  154. }
  155. memcpy(*(user->data), data, size);
  156. err = pcilib_return_data(user->ctx, event_id);
  157. if (err) {
  158. if (allocated) {
  159. free(*(user->data));
  160. *(user->data) = NULL;
  161. }
  162. pcilib_error("The event data had been overwritten before it was returned, data corruption may occur");
  163. return err;
  164. }
  165. return 0;
  166. }
  167. int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout) {
  168. int err;
  169. pcilib_grab_callback_user_data_t user = {ctx, size, data};
  170. err = pcilib_start(ctx, event_mask, pcilib_grab_callback, &user);
  171. if (!err) {
  172. if (timeout) nanosleep(timeout, NULL);
  173. else err = pcilib_trigger(ctx, event_mask, 0, NULL);
  174. }
  175. pcilib_stop(ctx);
  176. return 0;
  177. }