driver-dummy.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright 2013 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <ctype.h>
  11. #include <stdbool.h>
  12. #include <stddef.h>
  13. #include <stdint.h>
  14. #ifndef WIN32
  15. #include <unistd.h>
  16. #else
  17. #include <io.h>
  18. #endif
  19. #include "deviceapi.h"
  20. #include "fpgautils.h"
  21. #include "logging.h"
  22. #include "miner.h"
  23. struct device_drv dummy_drv;
  24. static
  25. bool dummy_send_command(const int fd, const uint8_t cmd, const void * const data, const size_t datasz)
  26. {
  27. if (1 != write(fd, &cmd, 1))
  28. return false;
  29. if (datasz)
  30. if (write(fd, data, datasz) != datasz)
  31. return false;
  32. return true;
  33. }
  34. static
  35. int dummy_recv_reply(const int fd, void * const bufp, const uint8_t cmd)
  36. {
  37. uint8_t chk, len;
  38. uint8_t * const buf = bufp;
  39. if (1 != read(fd, &chk, 1) || (cmd && chk != cmd))
  40. return -1;
  41. if (1 != read(fd, &len, 1))
  42. return -1;
  43. buf[0] = chk;
  44. if (len)
  45. if (len != read(fd, &buf[1], len))
  46. return -1;
  47. if (1 != read(fd, &chk, 1) || chk != '\x0a')
  48. return -1;
  49. return len;
  50. }
  51. static
  52. int dummy_do_command(const int fd, void * const buf, const uint8_t cmd, const void * const data, const size_t datasz)
  53. {
  54. if (!dummy_send_command(fd, cmd, data, datasz))
  55. return -1;
  56. return dummy_recv_reply(fd, buf, tolower(cmd));
  57. }
  58. static
  59. bool dummy_detect_one(const char * const devpath)
  60. {
  61. uint8_t buf[0x100];
  62. int n;
  63. const int fd = serial_open(devpath, 38400, 1, true);
  64. if (fd == -1)
  65. return false;
  66. buf[0] = '\0';
  67. n = dummy_do_command(fd, buf, 'V', NULL, 0);
  68. if (buf[1] != 'M' || buf[2] != 'P')
  69. {
  70. serial_close(fd);
  71. return false;
  72. }
  73. n = dummy_do_command(fd, buf, 'R', NULL, 0);
  74. n = dummy_do_command(fd, buf, 'I', NULL, 0);
  75. serial_close(fd);
  76. if (serial_claim_v(devpath, &dummy_drv))
  77. return false;
  78. struct cgpu_info *cgpu = malloc(sizeof(*cgpu));
  79. *cgpu = (struct cgpu_info){
  80. .drv = &dummy_drv,
  81. .device_path = strdup(devpath),
  82. .device_fd = -1,
  83. .threads = 1,
  84. .procs = buf[1],
  85. };
  86. add_cgpu(cgpu);
  87. return true;
  88. }
  89. static int dummy_detect_auto()
  90. {
  91. return serial_autodetect(dummy_detect_one, "Dummy BFGMiner Device");
  92. }
  93. static void dummy_detect()
  94. {
  95. serial_detect_auto(&dummy_drv, dummy_detect_one, dummy_detect_auto);
  96. }
  97. static bool dummy_init(struct thr_info * const thr)
  98. {
  99. struct cgpu_info * const cgpu = thr->cgpu;
  100. int fd = serial_open(cgpu->device_path, 38400, 1, true);
  101. if (unlikely(-1 == fd))
  102. {
  103. applog(LOG_ERR, "%"PRIpreprv": Failed to open %s",
  104. cgpu->proc_repr, cgpu->device_path);
  105. return false;
  106. }
  107. cgpu->device_fd = fd;
  108. applog(LOG_INFO, "%"PRIpreprv": Opened %s", cgpu->proc_repr, cgpu->device_path);
  109. return true;
  110. }
  111. static
  112. bool dummy_queue_append(struct thr_info * const thr, struct work * const work)
  113. {
  114. struct cgpu_info * const cgpu = thr->cgpu;
  115. const int fd = cgpu->device_fd;
  116. uint8_t buf[0x100];
  117. if (thr->queue_full)
  118. return false;
  119. memcpy(&buf[ 0], work->midstate , 0x20);
  120. memcpy(&buf[0x20], &work->data[64], 0x0c);
  121. dummy_do_command(fd, buf, 'Q', buf, 0x2c);
  122. if (thr->work)
  123. {
  124. dummy_send_command(fd, 'W', &buf[2], 1);
  125. thr->queue_full = true;
  126. }
  127. else
  128. dummy_send_command(fd, 'J', &buf[2], 1);
  129. return true;
  130. }
  131. static
  132. void dummy_queue_flush(struct thr_info * const thr)
  133. {
  134. // TODO
  135. }
  136. static
  137. void dummy_poll(struct thr_info * const thr)
  138. {
  139. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  140. const int fd = cgpu->device_fd;
  141. struct thr_info *mythr;
  142. uint8_t buf[0x100];
  143. int n, i, engineid;
  144. uint32_t nonce;
  145. n = dummy_recv_reply(fd, buf, 0);
  146. if (n == -1)
  147. goto out;
  148. if (buf[0] == 'j')
  149. goto out;
  150. if (buf[1] & 0x80)
  151. {
  152. engineid = buf[1] & 0x7f;
  153. proc = cgpu;
  154. for (i = 0; i < engineid; ++i)
  155. proc = proc->next_proc;
  156. mythr = proc->thr[0];
  157. nonce = buf[2] | (buf[3] << 8) | (buf[4] << 16) | (buf[5] << 24);
  158. submit_nonce(mythr, thr->work, nonce);
  159. goto out;
  160. }
  161. thr->queue_full = false;
  162. out:
  163. timer_set_delay_from_now(&thr->tv_poll, 10000);
  164. }
  165. struct device_drv dummy_drv = {
  166. .dname = "dummy",
  167. .name = "EMP",
  168. .drv_detect = dummy_detect,
  169. .thread_init = dummy_init,
  170. .minerloop = minerloop_queue,
  171. .queue_append = dummy_queue_append,
  172. .queue_flush = dummy_queue_flush,
  173. .poll = dummy_poll,
  174. };