driver-knc.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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 <stdbool.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #ifdef HAVE_LINUX_I2C_DEV_USER_H
  18. #include <linux/i2c-dev-user.h>
  19. #else
  20. #include <linux/i2c-dev.h>
  21. #endif
  22. #include <linux/spi/spidev.h>
  23. #include <uthash.h>
  24. #include "deviceapi.h"
  25. #include "logging.h"
  26. #include "miner.h"
  27. #include "spidevc.h"
  28. #define KNC_POLL_INTERVAL_US 10000
  29. #define KNC_SPI_SPEED 3000000
  30. #define KNC_SPI_DELAY 0
  31. #define KNC_SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  32. #define KNC_SPI_BITS 8
  33. static const char * const i2cpath = "/dev/i2c-2";
  34. enum knc_request_cmd {
  35. KNC_REQ_SUBMIT_WORK = 2,
  36. KNC_REQ_FLUSH_QUEUE = 3,
  37. };
  38. enum knc_reply_type {
  39. KNC_REPLY_NONCE_FOUND = 1,
  40. KNC_REPLY_WORK_DONE = 2,
  41. };
  42. struct device_drv knc_drv;
  43. struct knc_device {
  44. int i2c;
  45. struct spi_port *spi;
  46. struct work *workqueue;
  47. int workqueue_size;
  48. int workqueue_max;
  49. struct work *devicework;
  50. };
  51. static
  52. bool knc_detect_one(const char *devpath)
  53. {
  54. static struct cgpu_info *prev_cgpu = NULL;
  55. struct cgpu_info *cgpu;
  56. int i;
  57. const int fd = open(i2cpath, O_RDWR);
  58. char *leftover = NULL;
  59. const int i2cslave = strtol(devpath, &leftover, 0);
  60. uint8_t buf[0x20];
  61. if (leftover && leftover[0])
  62. return false;
  63. if (unlikely(fd == -1))
  64. {
  65. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  66. return false;
  67. }
  68. if (ioctl(fd, I2C_SLAVE, i2cslave))
  69. {
  70. close(fd);
  71. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  72. __func__, i2cslave);
  73. return false;
  74. }
  75. i = i2c_smbus_read_i2c_block_data(fd, 0, 0x20, buf);
  76. close(fd);
  77. if (-1 == i)
  78. {
  79. applog(LOG_DEBUG, "%s: 0x%x: Failed to read i2c block data",
  80. __func__, i2cslave);
  81. return false;
  82. }
  83. for (i = 0; ; ++i)
  84. {
  85. if (buf[i] == 3)
  86. break;
  87. if (i == 0x1f)
  88. return false;
  89. }
  90. cgpu = malloc(sizeof(*cgpu));
  91. *cgpu = (struct cgpu_info){
  92. .drv = &knc_drv,
  93. .device_path = strdup(devpath),
  94. .deven = DEV_ENABLED,
  95. .procs = 192,
  96. .threads = prev_cgpu ? 0 : 1,
  97. };
  98. const bool rv = add_cgpu_slave(cgpu, prev_cgpu);
  99. prev_cgpu = cgpu;
  100. return rv;
  101. }
  102. static int knc_detect_auto(void)
  103. {
  104. const int first = 0x20, last = 0x26;
  105. char devpath[4];
  106. int found = 0, i;
  107. for (i = first; i <= last; ++i)
  108. {
  109. sprintf(devpath, "%d", i);
  110. if (knc_detect_one(devpath))
  111. ++found;
  112. }
  113. return found;
  114. }
  115. static void knc_detect(void)
  116. {
  117. generic_detect(&knc_drv, knc_detect_one, knc_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  118. }
  119. static
  120. bool knc_spi_open(const char *repr, struct spi_port * const spi)
  121. {
  122. const char * const spipath = "/dev/spidev1.0";
  123. const int fd = open(spipath, O_RDWR);
  124. const uint8_t lsbfirst = 0;
  125. if (fd == -1)
  126. return false;
  127. if (ioctl(fd, SPI_IOC_WR_MODE , &spi->mode )) goto fail;
  128. if (ioctl(fd, SPI_IOC_WR_LSB_FIRST , &lsbfirst )) goto fail;
  129. if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi->bits )) goto fail;
  130. if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ , &spi->speed)) goto fail;
  131. spi->fd = fd;
  132. return true;
  133. fail:
  134. close(fd);
  135. spi->fd = -1;
  136. applog(LOG_WARNING, "%s: Failed to open %s", repr, spipath);
  137. return false;
  138. }
  139. static
  140. bool knc_spi_txrx(struct spi_port * const spi)
  141. {
  142. const void * const wrbuf = spi_gettxbuf(spi);
  143. void * const rdbuf = spi_getrxbuf(spi);
  144. const size_t bufsz = spi_getbufsz(spi);
  145. const int fd = spi->fd;
  146. struct spi_ioc_transfer xf = {
  147. .tx_buf = (uintptr_t) wrbuf,
  148. .rx_buf = (uintptr_t) rdbuf,
  149. .len = bufsz,
  150. .delay_usecs = spi->delay,
  151. .speed_hz = spi->speed,
  152. .bits_per_word = spi->bits,
  153. };
  154. return (ioctl(fd, SPI_IOC_MESSAGE(1), &xf) > 0);
  155. }
  156. static
  157. bool knc_init(struct thr_info * const thr)
  158. {
  159. const int max_cores = 192;
  160. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  161. struct knc_device *knc;
  162. struct spi_port *spi;
  163. const int i2c = open(i2cpath, O_RDWR);
  164. int i2cslave, i, j;
  165. uint8_t buf[0x20];
  166. if (unlikely(i2c == -1))
  167. {
  168. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  169. return false;
  170. }
  171. for (proc = cgpu; proc; )
  172. {
  173. if (proc->device != proc)
  174. {
  175. applog(LOG_WARNING, "%"PRIpreprv": Extra processor?", proc->proc_repr);
  176. continue;
  177. }
  178. i2cslave = atoi(proc->device_path);
  179. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  180. {
  181. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  182. __func__, i2cslave);
  183. return false;
  184. }
  185. for (i = 0; i < max_cores; i += 0x20)
  186. {
  187. i2c_smbus_read_i2c_block_data(i2c, i, 0x20, buf);
  188. for (j = 0; j < 0x20; ++j)
  189. {
  190. if (buf[j] != 3)
  191. proc->deven = DEV_DISABLED;
  192. proc = proc->next_proc;
  193. if ((!proc) || proc->device == proc)
  194. goto nomorecores;
  195. }
  196. }
  197. nomorecores: ;
  198. }
  199. cgpu->device_data = knc = malloc(sizeof(*knc));
  200. spi = malloc(sizeof(*spi));
  201. *knc = (struct knc_device){
  202. .i2c = i2c,
  203. .spi = spi,
  204. .workqueue_max = 1,
  205. };
  206. *spi = (struct spi_port){
  207. .txrx = knc_spi_txrx,
  208. .cgpu = cgpu,
  209. .repr = knc_drv.dname,
  210. .logprio = LOG_ERR,
  211. .speed = KNC_SPI_SPEED,
  212. .delay = KNC_SPI_DELAY,
  213. .mode = KNC_SPI_MODE,
  214. .bits = KNC_SPI_BITS,
  215. };
  216. if (!knc_spi_open(cgpu->dev_repr, spi))
  217. return false;
  218. timer_set_now(&thr->tv_poll);
  219. return true;
  220. }
  221. static
  222. void knc_remove_local_queue(struct knc_device * const knc, struct work * const work)
  223. {
  224. DL_DELETE(knc->workqueue, work);
  225. free_work(work);
  226. --knc->workqueue_size;
  227. }
  228. static
  229. void knc_prune_local_queue(struct thr_info *thr)
  230. {
  231. struct cgpu_info * const cgpu = thr->cgpu;
  232. struct knc_device * const knc = cgpu->device_data;
  233. struct work *work, *tmp;
  234. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  235. {
  236. if (stale_work(work, false))
  237. knc_remove_local_queue(knc, work);
  238. }
  239. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  240. }
  241. static
  242. bool knc_queue_append(struct thr_info * const thr, struct work * const work)
  243. {
  244. struct cgpu_info * const cgpu = thr->cgpu;
  245. struct knc_device * const knc = cgpu->device_data;
  246. if (knc->workqueue_size >= knc->workqueue_max)
  247. {
  248. knc_prune_local_queue(thr);
  249. if (thr->queue_full)
  250. return false;
  251. }
  252. DL_APPEND(knc->workqueue, work);
  253. ++knc->workqueue_size;
  254. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  255. if (thr->queue_full)
  256. knc_prune_local_queue(thr);
  257. return true;
  258. }
  259. static
  260. void knc_queue_flush(struct thr_info * const thr)
  261. {
  262. struct cgpu_info * const cgpu = thr->cgpu;
  263. struct knc_device * const knc = cgpu->device_data;
  264. struct work *work, *tmp;
  265. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  266. {
  267. knc_remove_local_queue(knc, work);
  268. }
  269. thr->queue_full = false;
  270. }
  271. static inline
  272. uint16_t get_u16be(const void * const p)
  273. {
  274. const uint8_t * const b = p;
  275. return (((uint16_t)b[0]) << 8) | b[1];
  276. }
  277. static inline
  278. uint16_t get_u32be(const void * const p)
  279. {
  280. const uint8_t * const b = p;
  281. return (((uint32_t)b[0]) << 0x18)
  282. | (((uint32_t)b[1]) << 0x10)
  283. | (((uint32_t)b[2]) << 8)
  284. | b[3];
  285. }
  286. static
  287. void knc_poll(struct thr_info * const thr)
  288. {
  289. struct thr_info *mythr;
  290. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  291. struct knc_device * const knc = cgpu->device_data;
  292. struct spi_port * const spi = knc->spi;
  293. struct work *work, *tmp;
  294. uint8_t buf[0x30], *rxbuf;
  295. int works_sent = 0, asicno, i;
  296. uint16_t workaccept;
  297. uint32_t nonce, coreno;
  298. size_t spi_req_sz = 0x1000;
  299. unsigned long delay_usecs = KNC_POLL_INTERVAL_US;
  300. knc_prune_local_queue(thr);
  301. spi_clear_buf(spi);
  302. DL_FOREACH(knc->workqueue, work)
  303. {
  304. buf[0] = KNC_REQ_SUBMIT_WORK << 4;
  305. buf[1] = 0;
  306. buf[2] = work->id >> 8;
  307. buf[3] = work->id & 0xff;
  308. memcpy(&buf[4], work->midstate, 0x20);
  309. memcpy(&buf[0x24], &work->data[64], 0xc);
  310. spi_emit_buf(spi, buf, sizeof(buf));
  311. ++works_sent;
  312. }
  313. spi_emit_nop(spi, spi_req_sz - spi_getbufsz(spi));
  314. spi_txrx(spi);
  315. rxbuf = spi_getrxbuf(spi);
  316. if (rxbuf[3] & 1)
  317. applog(LOG_DEBUG, "%s: Receive buffer overflow reported", knc_drv.dname);
  318. workaccept = get_u16be(&rxbuf[6]);
  319. applog(LOG_DEBUG, "%s: %lu/%d jobs accepted to queue (max=%d)",
  320. knc_drv.dname, (unsigned long)workaccept, works_sent, knc->workqueue_max);
  321. if (workaccept)
  322. {
  323. if (workaccept >= knc->workqueue_max)
  324. {
  325. knc->workqueue_max = workaccept;
  326. delay_usecs = 0;
  327. }
  328. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  329. {
  330. DL_DELETE(knc->workqueue, work);
  331. HASH_ADD_INT(knc->devicework, id, work);
  332. if (!--workaccept)
  333. break;
  334. }
  335. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  336. }
  337. while (true)
  338. {
  339. rxbuf += 0xc;
  340. spi_req_sz -= 0xc;
  341. if (spi_req_sz < 0xc)
  342. break;
  343. const int rtype = rxbuf[0] >> 6;
  344. if (rtype && opt_debug)
  345. {
  346. char x[(0xc * 2) + 1];
  347. bin2hex(x, rxbuf, 0xc);
  348. applog(LOG_DEBUG, "%s: RECV: %s", knc_drv.dname, x);
  349. }
  350. if (rtype != KNC_REPLY_NONCE_FOUND && rtype != KNC_REPLY_WORK_DONE)
  351. continue;
  352. asicno = (rxbuf[0] & 0x38) >> 3;
  353. coreno = get_u32be(&rxbuf[8]);
  354. proc = cgpu;
  355. for (i = 0; i < asicno; )
  356. {
  357. proc = proc->next_proc;
  358. if (proc == proc->device)
  359. ++i;
  360. }
  361. for (i = 0; i < coreno; ++i)
  362. proc = proc->next_proc;
  363. mythr = proc->thr[0];
  364. i = get_u16be(&rxbuf[2]);
  365. HASH_FIND_INT(knc->devicework, &i, work);
  366. if (!work)
  367. {
  368. const char * const msgtype = (rtype == KNC_REPLY_NONCE_FOUND) ? "nonce found" : "work done";
  369. applog(LOG_WARNING, "%"PRIpreprv": Got %s message about unknown work 0x%04x",
  370. proc->proc_repr, msgtype, i);
  371. continue;
  372. }
  373. switch (rtype)
  374. {
  375. case KNC_REPLY_NONCE_FOUND:
  376. nonce = get_u32be(&rxbuf[4]);
  377. submit_nonce(mythr, work, nonce);
  378. break;
  379. case KNC_REPLY_WORK_DONE:
  380. HASH_DEL(knc->devicework, work);
  381. free_work(work);
  382. hashes_done2(mythr, 0x100000000, NULL);
  383. break;
  384. }
  385. }
  386. timer_set_delay_from_now(&thr->tv_poll, delay_usecs);
  387. }
  388. struct device_drv knc_drv = {
  389. .dname = "knc",
  390. .name = "KNC",
  391. .drv_detect = knc_detect,
  392. .thread_init = knc_init,
  393. .minerloop = minerloop_queue,
  394. .queue_append = knc_queue_append,
  395. .queue_flush = knc_queue_flush,
  396. .poll = knc_poll,
  397. };