driver-titan.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * Copyright 2014 Vitalii Demianets
  3. * Copyright 2014 KnCMiner
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 3 of the License, or (at your option)
  8. * any later version. See COPYING for more details.
  9. */
  10. #include <fcntl.h>
  11. #include <sys/ioctl.h>
  12. #include <linux/spi/spidev.h>
  13. #include "deviceapi.h"
  14. #include "logging.h"
  15. #include "lowl-spi.h"
  16. #include "miner.h"
  17. #include "util.h"
  18. #include "titan-asic.h"
  19. #define KNC_TITAN_DEFAULT_FREQUENCY 600
  20. #define KNC_TITAN_HWERR_DISABLE_SECS 10
  21. #define KNC_TITAN_SPI_SPEED 3000000
  22. #define KNC_TITAN_SPI_DELAY 0
  23. #define KNC_TITAN_SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  24. #define KNC_TITAN_SPI_BITS 8
  25. BFG_REGISTER_DRIVER(knc_titan_drv)
  26. static const struct bfg_set_device_definition knc_titan_set_device_funcs[];
  27. struct knc_titan_core {
  28. int asicno;
  29. int dieno; /* inside asic */
  30. int coreno; /* inside die */
  31. struct knc_titan_die *die;
  32. struct cgpu_info *proc;
  33. int hwerr_in_row;
  34. int hwerr_disable_time;
  35. struct timeval enable_at;
  36. struct timeval first_hwerr;
  37. };
  38. struct knc_titan_die {
  39. int asicno;
  40. int dieno; /* inside asic */
  41. int cores;
  42. struct cgpu_info *first_proc;
  43. int freq;
  44. };
  45. struct knc_titan_info {
  46. struct spi_port *spi;
  47. struct cgpu_info *cgpu;
  48. int cores;
  49. struct knc_titan_die dies[KNC_TITAN_MAX_ASICS][KNC_TITAN_DIES_PER_ASIC];
  50. };
  51. static bool knc_titan_spi_open(const char *repr, struct spi_port * const spi)
  52. {
  53. const char * const spipath = "/dev/spidev0.1";
  54. const int fd = open(spipath, O_RDWR);
  55. const uint8_t lsbfirst = 0;
  56. if (0 > fd)
  57. return false;
  58. if (ioctl(fd, SPI_IOC_WR_MODE , &spi->mode )) goto fail;
  59. if (ioctl(fd, SPI_IOC_WR_LSB_FIRST , &lsbfirst )) goto fail;
  60. if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi->bits )) goto fail;
  61. if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ , &spi->speed)) goto fail;
  62. spi->fd = fd;
  63. return true;
  64. fail:
  65. close(fd);
  66. spi->fd = -1;
  67. applog(LOG_WARNING, "%s: Failed to open %s", repr, spipath);
  68. return false;
  69. }
  70. #define knc_titan_spi_txrx linux_spi_txrx
  71. static bool knc_titan_detect_one(const char *devpath)
  72. {
  73. static struct cgpu_info *prev_cgpu = NULL;
  74. struct cgpu_info *cgpu;
  75. struct spi_port *spi;
  76. struct knc_titan_info *knc;
  77. int cores = 0, asic, die;
  78. struct titan_info_response resp;
  79. char repr[6];
  80. cgpu = malloc(sizeof(*cgpu));
  81. if (unlikely(!cgpu))
  82. quit(1, "Failed to alloc cgpu_info");
  83. if (!prev_cgpu) {
  84. spi = calloc(1, sizeof(*spi));
  85. if (unlikely(!spi))
  86. quit(1, "Failed to alloc spi_port");
  87. /* Be careful, read lowl-spi.h comments for warnings */
  88. memset(spi, 0, sizeof(*spi));
  89. spi->txrx = knc_titan_spi_txrx;
  90. spi->cgpu = cgpu;
  91. spi->repr = knc_titan_drv.dname;
  92. spi->logprio = LOG_ERR;
  93. spi->speed = KNC_TITAN_SPI_SPEED;
  94. spi->delay = KNC_TITAN_SPI_DELAY;
  95. spi->mode = KNC_TITAN_SPI_MODE;
  96. spi->bits = KNC_TITAN_SPI_BITS;
  97. if (!knc_titan_spi_open(knc_titan_drv.name, spi)) {
  98. free(cgpu);
  99. return false;
  100. }
  101. knc = calloc(1, sizeof(*knc));
  102. if (unlikely(!knc))
  103. quit(1, "Failed to alloc knc_titan_info");
  104. knc->spi = spi;
  105. knc->cgpu = cgpu;
  106. } else {
  107. knc = prev_cgpu->device_data;
  108. spi = knc->spi;
  109. }
  110. snprintf(repr, sizeof(repr), "%s %s", knc_titan_drv.name, devpath);
  111. asic = atoi(devpath);
  112. for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
  113. if (!knc_titan_spi_get_info(repr, spi, &resp, die, KNC_TITAN_CORES_PER_DIE))
  114. continue;
  115. if (0 < resp.cores) {
  116. knc->dies[asic][die] = (struct knc_titan_die) {
  117. .asicno = asic,
  118. .dieno = die,
  119. .cores = resp.cores,
  120. .first_proc = cgpu,
  121. .freq = KNC_TITAN_DEFAULT_FREQUENCY,
  122. };
  123. cores += resp.cores;
  124. } else {
  125. knc->dies[asic][die] = (struct knc_titan_die) {
  126. .asicno = -INT_MAX,
  127. .dieno = -INT_MAX,
  128. .cores = 0,
  129. .first_proc = NULL,
  130. };
  131. }
  132. }
  133. if (0 == cores) {
  134. free(cgpu);
  135. if (!prev_cgpu) {
  136. free(knc);
  137. close(spi->fd);
  138. free(spi);
  139. }
  140. return false;
  141. }
  142. applog(LOG_NOTICE, "%s: Found ASIC with %d cores", repr, cores);
  143. *cgpu = (struct cgpu_info) {
  144. .drv = &knc_titan_drv,
  145. .device_path = strdup(devpath),
  146. .set_device_funcs = knc_titan_set_device_funcs,
  147. .deven = DEV_ENABLED,
  148. .procs = cores,
  149. .threads = prev_cgpu ? 0 : 1,
  150. .device_data = knc,
  151. };
  152. const bool rv = add_cgpu_slave(cgpu, prev_cgpu);
  153. prev_cgpu = cgpu;
  154. return rv;
  155. }
  156. static int knc_titan_detect_auto(void)
  157. {
  158. const int first = 0, last = KNC_TITAN_MAX_ASICS - 1;
  159. char devpath[256];
  160. int found = 0, i;
  161. for (i = first; i <= last; ++i)
  162. {
  163. sprintf(devpath, "%d", i);
  164. if (knc_titan_detect_one(devpath))
  165. ++found;
  166. }
  167. return found;
  168. }
  169. static void knc_titan_detect(void)
  170. {
  171. generic_detect(&knc_titan_drv, knc_titan_detect_one, knc_titan_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  172. }
  173. static bool knc_titan_init(struct thr_info * const thr)
  174. {
  175. const int max_cores = KNC_TITAN_CORES_PER_ASIC;
  176. struct thr_info *mythr;
  177. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  178. struct knc_titan_core *knccore;
  179. struct knc_titan_info *knc;
  180. int i, asic, die, core_base;
  181. int total_cores = 0;
  182. for (proc = cgpu; proc; ) {
  183. if (proc->device != proc) {
  184. applog(LOG_WARNING, "%"PRIpreprv": Extra processor?", proc->proc_repr);
  185. proc = proc->next_proc;
  186. continue;
  187. }
  188. asic = atoi(proc->device_path);
  189. knc = proc->device_data;
  190. die = 0;
  191. core_base = 0;
  192. for (i = 0; i < max_cores; ++i) {
  193. while (i >= (core_base + knc->dies[asic][die].cores)) {
  194. core_base += knc->dies[asic][die].cores;
  195. if (++die >= KNC_TITAN_DIES_PER_ASIC)
  196. break;
  197. }
  198. if (die >= KNC_TITAN_DIES_PER_ASIC)
  199. break;
  200. mythr = proc->thr[0];
  201. mythr->cgpu_data = knccore = malloc(sizeof(*knccore));
  202. if (unlikely(!knccore))
  203. quit(1, "Failed to alloc knc_titan_core");
  204. *knccore = (struct knc_titan_core) {
  205. .asicno = asic,
  206. .dieno = die,
  207. .coreno = i - core_base,
  208. .die = &(knc->dies[asic][die]),
  209. .proc = proc,
  210. .hwerr_in_row = 0,
  211. .hwerr_disable_time = KNC_TITAN_HWERR_DISABLE_SECS,
  212. };
  213. timer_set_now(&knccore->enable_at);
  214. proc->device_data = knc;
  215. ++total_cores;
  216. applog(LOG_DEBUG, "%s Allocated core %d:%d:%d", proc->device->dev_repr, asic, die, (i - core_base));
  217. proc = proc->next_proc;
  218. if ((!proc) || proc->device == proc)
  219. break;
  220. }
  221. knc->cores = total_cores;
  222. }
  223. cgpu_set_defaults(cgpu);
  224. if (0 >= total_cores)
  225. return false;
  226. /* Init nonce ranges for cores */
  227. double nonce_step = 4294967296.0 / total_cores;
  228. double nonce_f = 0.0;
  229. struct titan_setup_core_params setup_params = {
  230. .bad_address_mask = {0, 0},
  231. .bad_address_match = {0x3FF, 0x3FF},
  232. .difficulty = 0xC,
  233. .thread_enable = 0xFF,
  234. .thread_base_address = {0, 1, 2, 3, 4, 5, 6, 7},
  235. .lookup_gap_mask = {0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7},
  236. .N_mask = {0, 0, 0, 0, 0, 0, 0, 0},
  237. .N_shift = {0, 0, 0, 0, 0, 0, 0, 0},
  238. .nonce_bottom = 0,
  239. .nonce_top = 0xFFFFFFFF,
  240. };
  241. for (proc = cgpu; proc; proc = proc->next_proc) {
  242. nonce_f += nonce_step;
  243. setup_params.nonce_bottom = setup_params.nonce_top + 1;
  244. if (NULL != proc->next_proc)
  245. setup_params.nonce_top = nonce_f;
  246. else
  247. setup_params.nonce_top = 0xFFFFFFFF;
  248. knc = proc->device_data;
  249. mythr = proc->thr[0];
  250. knccore = mythr->cgpu_data;
  251. applog(LOG_DEBUG, "%s Setup core %d:%d:%d, nonces 0x%08X - 0x%08X", proc->device->dev_repr, knccore->asicno, knccore->dieno, knccore->coreno, setup_params.nonce_bottom, setup_params.nonce_top);
  252. knc_titan_setup_core(proc->device->dev_repr, knc->spi, &setup_params, knccore->dieno, knccore->coreno);
  253. }
  254. return true;
  255. }
  256. static int64_t knc_titan_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
  257. {
  258. return 0;
  259. }
  260. /*
  261. * specify settings / options via RPC or command line
  262. */
  263. /* support for --set-device
  264. * must be set before probing the device
  265. */
  266. static void knc_titan_set_clock_freq(struct cgpu_info * const device, int const val)
  267. {
  268. }
  269. static const char *knc_titan_set_clock(struct cgpu_info * const device, const char * const option, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const success)
  270. {
  271. knc_titan_set_clock_freq(device, atoi(setting));
  272. return NULL;
  273. }
  274. static const struct bfg_set_device_definition knc_titan_set_device_funcs[] = {
  275. { "clock", knc_titan_set_clock, NULL },
  276. { NULL },
  277. };
  278. /*
  279. * specify settings / options via TUI
  280. */
  281. #ifdef HAVE_CURSES
  282. static void knc_titan_tui_wlogprint_choices(struct cgpu_info * const proc)
  283. {
  284. wlogprint("[C]lock speed ");
  285. }
  286. static const char *knc_titan_tui_handle_choice(struct cgpu_info * const proc, const int input)
  287. {
  288. static char buf[0x100]; /* Static for replies */
  289. switch (input)
  290. {
  291. case 'c': case 'C':
  292. {
  293. sprintf(buf, "Set clock speed");
  294. char * const setting = curses_input(buf);
  295. knc_titan_set_clock_freq(proc->device, atoi(setting));
  296. return "Clock speed changed\n";
  297. }
  298. }
  299. return NULL;
  300. }
  301. static void knc_titan_wlogprint_status(struct cgpu_info * const proc)
  302. {
  303. wlogprint("Clock speed: N/A\n");
  304. }
  305. #endif
  306. struct device_drv knc_titan_drv =
  307. {
  308. /* metadata */
  309. .dname = "titan",
  310. .name = "KNC",
  311. .supported_algos = POW_SCRYPT,
  312. .drv_detect = knc_titan_detect,
  313. .thread_init = knc_titan_init,
  314. /* specify mining type - scanhash */
  315. .minerloop = minerloop_scanhash,
  316. /* scanhash mining hooks */
  317. .scanhash = knc_titan_scanhash,
  318. /* TUI support - e.g. setting clock via UI */
  319. #ifdef HAVE_CURSES
  320. .proc_wlogprint_status = knc_titan_wlogprint_status,
  321. .proc_tui_wlogprint_choices = knc_titan_tui_wlogprint_choices,
  322. .proc_tui_handle_choice = knc_titan_tui_handle_choice,
  323. #endif
  324. };