driver-cointerra.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  1. /*
  2. * Copyright 2013-2014 Con Kolivas
  3. * Copyright 2014 Luke Dashjr
  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 "config.h"
  11. #include <string.h>
  12. #include "miner.h"
  13. #include "deviceapi.h"
  14. #include "driver-cointerra.h"
  15. #include "lowlevel.h"
  16. #include "lowl-usb.h"
  17. #include <math.h>
  18. static const unsigned cointerra_desired_roll = 60;
  19. static const unsigned long cointerra_latest_result_usecs = (10 * 1000000);
  20. static const unsigned cointerra_max_nonce_diff = 0x20;
  21. #define COINTERRA_USB_TIMEOUT 500
  22. #define COINTERRA_PACKET_SIZE 0x40
  23. #define COINTERRA_START_SEQ 0x5a,0x5a
  24. #define COINTERRA_MSG_SIZE (COINTERRA_PACKET_SIZE - sizeof(cointerra_startseq))
  25. #define COINTERRA_MSGBODY_SIZE (COINTERRA_MSG_SIZE - 1)
  26. BFG_REGISTER_DRIVER(cointerra_drv)
  27. static const struct bfg_set_device_definition cointerra_set_device_funcs[];
  28. enum cointerra_msg_type_out {
  29. CMTO_RESET = 1,
  30. CMTO_WORK = 2,
  31. CMTO_REQUEST = 4,
  32. CMTO_HWERR = 5,
  33. CMTO_LEDCTL = 6,
  34. CMTO_HASHRATE = 7,
  35. CMTO_GET_INFO = 0x21,
  36. };
  37. static const uint8_t cointerra_startseq[] = {COINTERRA_START_SEQ};
  38. static const char *cointerra_hdr = "ZZ";
  39. static void cta_gen_message(char *msg, char type)
  40. {
  41. memset(msg, 0, CTA_MSG_SIZE);
  42. memcpy(msg, cointerra_hdr, 2);
  43. msg[CTA_MSG_TYPE] = type;
  44. }
  45. /* Find the number of leading zero bits in diff */
  46. static uint8_t diff_to_bits(double diff)
  47. {
  48. uint64_t diff64;
  49. uint8_t i;
  50. diff *= (double)2147483648.0;
  51. if (diff > 0x8000000000000000ULL)
  52. diff = 0x8000000000000000ULL;
  53. /* Convert it to an integer */
  54. diff64 = diff;
  55. for (i = 0; diff64; i++, diff64 >>= 1);
  56. return i;
  57. }
  58. static double bits_to_diff(uint8_t bits)
  59. {
  60. double ret = 1.0;
  61. if (likely(bits > 32))
  62. ret *= 1ull << (bits - 32);
  63. else if (unlikely(bits < 32))
  64. ret /= 1ull << (32 - bits);
  65. return ret;
  66. }
  67. static bool cta_reset_init(char *buf)
  68. {
  69. return ((buf[CTA_MSG_TYPE] == CTA_RECV_RDONE) && ((buf[CTA_RESET_TYPE]&0x3) == CTA_RESET_INIT));
  70. }
  71. static char *mystrstr(char *haystack, int size, const char *needle)
  72. {
  73. int loop = 0;
  74. while (loop < (size-1)) {
  75. if ((haystack[loop] == needle[0])&&
  76. (haystack[loop+1] == needle[1]))
  77. return &haystack[loop];
  78. loop++;
  79. }
  80. return NULL;
  81. }
  82. static
  83. bool cta_open(struct lowl_usb_endpoint * const ep, const char * const repr, struct cointerra_info * const devstate)
  84. {
  85. int amount, offset = 0;
  86. char buf[CTA_MSG_SIZE];
  87. cgtimer_t ts_start;
  88. bool ret = false;
  89. applog(LOG_INFO, "CTA_OPEN");
  90. cta_gen_message(buf, CTA_SEND_RESET);
  91. // set the initial difficulty
  92. buf[CTA_RESET_TYPE] = CTA_RESET_INIT | CTA_RESET_DIFF;
  93. buf[CTA_RESET_DIFF] = diff_to_bits(CTA_INIT_DIFF);
  94. buf[CTA_RESET_LOAD] = devstate->set_load ?: 255;
  95. buf[CTA_RESET_PSLOAD] = 0;
  96. amount = usb_write(ep, buf, CTA_MSG_SIZE);
  97. if (amount != CTA_MSG_SIZE) {
  98. applog(LOG_INFO, "Write error %s, wrote %d of %d",
  99. bfg_strerror(errno, BST_ERRNO),
  100. amount, CTA_MSG_SIZE);
  101. return ret;
  102. }
  103. cgtimer_time(&ts_start);
  104. /* Read from the device for up to 2 seconds discarding any data that
  105. * doesn't match a reset complete acknowledgement. */
  106. while (42) {
  107. cgtimer_t ts_now, ts_diff;
  108. char *msg;
  109. cgtimer_time(&ts_now);
  110. cgtimer_sub(&ts_now, &ts_start, &ts_diff);
  111. if (cgtimer_to_ms(&ts_diff) > 2000) {
  112. applog(LOG_DEBUG, "%s: Timed out waiting for response to reset init", repr);
  113. break;
  114. }
  115. amount = usb_read(ep, buf + offset, CTA_MSG_SIZE - offset);
  116. if (amount != (CTA_MSG_SIZE - offset) && amount != 0) {
  117. applog(LOG_INFO, "%s: Read error %s, read %d",
  118. repr, bfg_strerror(errno, BST_ERRNO), amount);
  119. break;
  120. }
  121. if (!amount)
  122. continue;
  123. msg = mystrstr(buf, amount, cointerra_hdr);
  124. if (!msg) {
  125. /* Keep the last byte in case it's the first byte of
  126. * the 2 byte header. */
  127. offset = 1;
  128. memmove(buf, buf + amount - 1, offset);
  129. continue;
  130. }
  131. if (msg > buf) {
  132. /* length of message = offset for next usb_read after moving */
  133. offset = CTA_MSG_SIZE - (msg - buf);
  134. memmove(buf, msg, offset);
  135. continue;
  136. }
  137. /* We have a full sized message starting with the header now */
  138. if (cta_reset_init(buf)) {
  139. /* We can't store any other data returned with this
  140. * reset since we have not allocated any memory for
  141. * a cointerra_info structure yet. */
  142. applog(LOG_INFO, "%s: Successful reset init received", repr);
  143. ret = true;
  144. break;
  145. }
  146. }
  147. return ret;
  148. }
  149. static
  150. bool cointerra_open(const struct lowlevel_device_info * const info, const char * const repr, struct libusb_device_handle ** const usbh_p, struct lowl_usb_endpoint ** const ep_p, struct cointerra_info * const devstate)
  151. {
  152. int e;
  153. if (libusb_open(info->lowl_data, usbh_p))
  154. applogr(false, LOG_DEBUG, "%s: USB open failed on %s",
  155. cointerra_drv.dname, info->devid);
  156. if ( (e = libusb_set_configuration(*usbh_p, 1)) )
  157. return_via_applog(fail, , LOG_ERR, "%s: Failed to %s on %s: %s", repr, "set configuration 1", info->devid, bfg_strerror(e, BST_LIBUSB));
  158. if ( (e = libusb_claim_interface(*usbh_p, 0)) )
  159. return_via_applog(fail, , LOG_ERR, "%s: Failed to %s on %s: %s", repr, "claim interface 0", info->devid, bfg_strerror(e, BST_LIBUSB));
  160. *ep_p = usb_open_ep_pair(*usbh_p, LIBUSB_ENDPOINT_IN | 1, 64, LIBUSB_ENDPOINT_OUT | 1, 64);
  161. if (!*ep_p)
  162. {
  163. applog(LOG_DEBUG, "%s: Endpoint open failed on %s",
  164. cointerra_drv.dname, info->devid);
  165. fail:
  166. libusb_close(*usbh_p);
  167. *usbh_p = NULL;
  168. return false;
  169. }
  170. if (!cta_open(*ep_p, repr, devstate))
  171. {
  172. usb_close_ep(*ep_p);
  173. *ep_p = NULL;
  174. goto fail;
  175. }
  176. return true;
  177. }
  178. static void cta_clear_work(struct cgpu_info *cgpu)
  179. {
  180. struct work *work, *tmp;
  181. wr_lock(&cgpu->qlock);
  182. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  183. __work_completed(cgpu, work);
  184. free_work(work);
  185. }
  186. wr_unlock(&cgpu->qlock);
  187. }
  188. static void cta_close(struct cgpu_info *cointerra)
  189. {
  190. struct cointerra_info *info = cointerra->device_data;
  191. if (info->ep)
  192. {
  193. /* Open does the same reset init followed by response as is required to
  194. * close the device. */
  195. if (!cta_open(info->ep, cointerra->dev_repr, info)) {
  196. applog(LOG_INFO, "%s %d: Reset on close failed", cointerra->drv->name,
  197. cointerra->device_id);
  198. }
  199. }
  200. mutex_destroy(&info->lock);
  201. mutex_destroy(&info->sendlock);
  202. /* Don't free info here to avoid trying to access dereferenced members
  203. * once a device is unplugged. */
  204. cta_clear_work(cointerra);
  205. }
  206. static void cta_parse_info(struct cgpu_info *, struct cointerra_info *, char *);
  207. static void msg_from_hu16(char *, int, uint16_t);
  208. static
  209. bool cointerra_wait_for_info(struct cointerra_info * const ctainfo, struct lowl_usb_endpoint * const ep)
  210. {
  211. char buf[CTA_MSG_SIZE];
  212. int amount;
  213. cta_gen_message(buf, CTA_SEND_REQUEST);
  214. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_INFO);
  215. msg_from_hu16(buf, CTA_REQ_INTERVAL, 0);
  216. amount = usb_write(ep, buf, CTA_MSG_SIZE);
  217. if (amount != CTA_MSG_SIZE)
  218. return false;
  219. do {
  220. amount = usb_read(ep, buf, CTA_MSG_SIZE);
  221. if (amount != CTA_MSG_SIZE)
  222. applogr(false, LOG_ERR, "%s: Read error %s, read %d",
  223. __func__, bfg_strerror(errno, BST_ERRNO), amount);
  224. if (memcmp(buf, cointerra_hdr, 2))
  225. applogr(false, LOG_ERR, "%s: Packet header mismatch", __func__);
  226. } while (buf[CTA_MSG_TYPE] != CTA_RECV_INFO);
  227. cta_parse_info(NULL, ctainfo, buf);
  228. return true;
  229. }
  230. static
  231. bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
  232. {
  233. struct cointerra_info ctainfo = { .set_load = 0, };
  234. struct libusb_device_handle *usbh;
  235. struct lowl_usb_endpoint *ep;
  236. bool b;
  237. if (info->lowl != &lowl_usb)
  238. {
  239. bfg_probe_result_flags = BPR_WRONG_DEVTYPE;
  240. return false;
  241. }
  242. if (!cointerra_open(info, cointerra_drv.dname, &usbh, &ep, &ctainfo))
  243. return false;
  244. mutex_init(&ctainfo.lock);
  245. b = cointerra_wait_for_info(&ctainfo, ep);
  246. mutex_destroy(&ctainfo.lock);
  247. usb_close_ep(ep);
  248. libusb_close(usbh);
  249. if (!b)
  250. return false;
  251. applog(LOG_DEBUG, "%s: Found %lu cores on %s",
  252. __func__, (unsigned long)ctainfo.cores, info->devid);
  253. libusb_device * const usbdev = info->lowl_data;
  254. if (bfg_claim_libusb(&cointerra_drv, true, usbdev))
  255. return false;
  256. struct cgpu_info * const dev = malloc(sizeof(*dev));
  257. *dev = (struct cgpu_info){
  258. .drv = &cointerra_drv,
  259. .set_device_funcs = cointerra_set_device_funcs,
  260. .procs = ctainfo.cores,
  261. .device_data = lowlevel_ref(info),
  262. .threads = 1,
  263. .device_path = strdup(info->devid),
  264. .dev_manufacturer = maybe_strdup(info->manufacturer),
  265. .dev_product = maybe_strdup(info->product),
  266. .dev_serial = maybe_strdup(info->serial),
  267. .deven = DEV_ENABLED,
  268. };
  269. const bool rv = add_cgpu(dev);
  270. applog(LOG_INFO, "%s: Successfully set up %s",
  271. cointerra_drv.dname, dev->dev_repr);
  272. return rv;
  273. }
  274. static
  275. void cointerra_set_queue_full(struct cgpu_info * const dev, const bool nv)
  276. {
  277. if (dev->thr[0]->queue_full == nv)
  278. return;
  279. for_each_managed_proc(proc, dev)
  280. proc->thr[0]->queue_full = nv;
  281. }
  282. static
  283. bool cointerra_lowl_match(const struct lowlevel_device_info * const info)
  284. {
  285. return lowlevel_match_lowlproduct(info, &lowl_usb, "GoldStrike");
  286. }
  287. /* This function will remove a work item from the hashtable if it matches the
  288. * id in work->subid and return a pointer to the work but it will not free the
  289. * work. It may return NULL if it cannot find matching work. */
  290. static struct work *take_work_by_id(struct cgpu_info *cgpu, uint16_t id)
  291. {
  292. struct work *work, *tmp, *ret = NULL;
  293. wr_lock(&cgpu->qlock);
  294. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  295. if (work->subid == id) {
  296. ret = work;
  297. break;
  298. }
  299. }
  300. if (ret)
  301. __work_completed(cgpu, ret);
  302. wr_unlock(&cgpu->qlock);
  303. return ret;
  304. }
  305. /* This function will look up a work item in the hashtable if it matches the
  306. * id in work->subid and return a cloned work item if it matches. It may return
  307. * NULL if it cannot find matching work. */
  308. static struct work *clone_work_by_id(struct cgpu_info *cgpu, uint16_t id)
  309. {
  310. struct work *work, *tmp, *ret = NULL;
  311. rd_lock(&cgpu->qlock);
  312. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  313. if (work->subid == id) {
  314. ret = work;
  315. break;
  316. }
  317. }
  318. if (ret)
  319. ret = copy_work(ret);
  320. rd_unlock(&cgpu->qlock);
  321. return ret;
  322. }
  323. static bool cta_send_msg(struct cgpu_info *cointerra, char *buf);
  324. static uint16_t hu16_from_msg(char *buf, int msg)
  325. {
  326. return le16toh(*(uint16_t *)&buf[msg]);
  327. }
  328. static uint32_t hu32_from_msg(char *buf, int msg)
  329. {
  330. return le32toh(*(uint32_t *)&buf[msg]);
  331. }
  332. static uint64_t hu64_from_msg(char *buf, int msg)
  333. {
  334. return le64toh(*(uint64_t *)&buf[msg]);
  335. }
  336. static uint8_t u8_from_msg(char *buf, int msg)
  337. {
  338. return *(uint8_t *)&buf[msg];
  339. }
  340. static void msg_from_hu16(char *buf, int msg, uint16_t val)
  341. {
  342. *(uint16_t *)&buf[msg] = htole16(val);
  343. }
  344. static void cta_parse_reqwork(struct cgpu_info *cointerra, struct cointerra_info *info,
  345. char *buf)
  346. {
  347. uint16_t retwork;
  348. retwork = hu16_from_msg(buf, CTA_REQWORK_REQUESTS);
  349. applog(LOG_DEBUG, "%s %d: Request work message for %u items received",
  350. cointerra->drv->name, cointerra->device_id, retwork);
  351. mutex_lock(&info->lock);
  352. info->requested = retwork;
  353. cointerra_set_queue_full(cointerra, !retwork);
  354. mutex_unlock(&info->lock);
  355. }
  356. static void cta_parse_recvmatch(struct thr_info *thr, struct cgpu_info *cointerra,
  357. struct cointerra_info *info, char *buf)
  358. {
  359. struct cgpu_info *corecgpu;
  360. struct thr_info *corethr;
  361. uint32_t timestamp_offset, mcu_tag;
  362. uint16_t retwork;
  363. struct work *work;
  364. uint8_t asic, core, pipe, coreno;
  365. int pipeno, bitchar, bitbit;
  366. /* No endian switch needs doing here since it's sent and returned as
  367. * the same 4 bytes */
  368. retwork = *(uint16_t *)(&buf[CTA_DRIVER_TAG]);
  369. mcu_tag = hu32_from_msg(buf, CTA_MCU_TAG);
  370. const uint8_t wdiffbits = u8_from_msg(buf, CTA_WORK_DIFFBITS);
  371. const uint32_t nonce = hu32_from_msg(buf, CTA_MATCH_NONCE);
  372. asic = u8_from_msg(buf, CTA_MCU_ASIC);
  373. core = u8_from_msg(buf, CTA_MCU_CORE);
  374. pipe = u8_from_msg(buf, CTA_MCU_PIPE);
  375. pipeno = asic * 512 + core * 128 + pipe;
  376. // For some reason, pipe numbers skip 0x?f
  377. const int bfg_pipeno = ((pipe >> 4) * 0xf) + (pipe & 0xf);
  378. const unsigned procno = (asic * 480) + (core * 120) + bfg_pipeno;
  379. corecgpu = device_proc_by_id(cointerra, procno) ?: cointerra;
  380. corethr = corecgpu->thr[0];
  381. applog(LOG_DEBUG, "%s %d: Match message for id 0x%04x MCU id 0x%08x received",
  382. cointerra->drv->name, cointerra->device_id, retwork, mcu_tag);
  383. work = clone_work_by_id(cointerra, retwork);
  384. if (likely(work)) {
  385. unsigned char rhash[32];
  386. char outhash[16];
  387. double wdiff;
  388. uint64_t hashes;
  389. bool ret;
  390. timestamp_offset = hu32_from_msg(buf, CTA_MATCH_NOFFSET);
  391. if (timestamp_offset) {
  392. struct work *base_work = work;
  393. work = copy_work_noffset(base_work, timestamp_offset);
  394. free_work(base_work);
  395. }
  396. /* Test against the difficulty we asked for along with the work */
  397. wdiff = bits_to_diff(wdiffbits);
  398. hashes = (uint64_t)wdiff * 0x100000000ull;
  399. ret = true; // TODO: test_nonce_diff(work, nonce, wdiff);
  400. if (opt_debug) {
  401. /* Debugging, remove me */
  402. swab256(rhash, work->hash);
  403. bin2hex(outhash, rhash, 8);
  404. applog(LOG_DEBUG, "submit work %s 0x%04x 0x%08x %d 0x%08x",
  405. outhash, retwork, mcu_tag, timestamp_offset, nonce);
  406. }
  407. hashes_done2(corethr, hashes, NULL);
  408. if (likely(ret)) {
  409. coreno = asic * 4 + core;
  410. if (unlikely(asic > 1 || core > 3 || pipe > 127 || pipeno > 1023)) {
  411. applog(LOG_WARNING, "%s %d: MCU invalid pipe asic %d core %d pipe %d",
  412. cointerra->drv->name, cointerra->device_id, asic, core, pipe);
  413. coreno = 0;
  414. } else {
  415. info->last_pipe_nonce[pipeno] = time(NULL);
  416. bitchar = pipeno / 8;
  417. bitbit = pipeno % 8;
  418. info->pipe_bitmap[bitchar] |= 0x80 >> bitbit;
  419. }
  420. applog(LOG_DEBUG, "%"PRIpreprv": Submitting tested work job_id %s work_id %u",
  421. corecgpu->proc_repr, work->job_id, work->subid);
  422. ret = submit_nonce(corethr, work, nonce);
  423. mutex_lock(&info->lock);
  424. info->share_hashes += hashes;
  425. info->tot_core_hashes[coreno] += hashes;
  426. info->hashes += nonce;
  427. mutex_unlock(&info->lock);
  428. } else {
  429. char sendbuf[CTA_MSG_SIZE];
  430. applog(LOG_DEBUG, "%s %d: Notify bad match work",
  431. cointerra->drv->name, cointerra->device_id);
  432. if (opt_debug) {
  433. unsigned char midstate[32], wdata[12];
  434. char hexmidstate[68], hexwdata[28];
  435. uint16_t wid;
  436. memcpy(&wid, &info->work_id, 2);
  437. flip32(midstate, work->midstate);
  438. bin2hex(hexmidstate, midstate, 32);
  439. flip12(wdata, &work->data[64]);
  440. bin2hex(hexwdata, wdata, 12);
  441. applog(LOG_DEBUG, "False match sent: work id %u midstate %s blkhdr %s",
  442. wid, hexmidstate, hexwdata);
  443. applog(LOG_DEBUG, "False match reports: work id 0x%04x MCU id 0x%08x work diff %.1f",
  444. retwork, mcu_tag, wdiff);
  445. applog(LOG_DEBUG, "False match tested: nonce 0x%08x noffset %d %s",
  446. nonce, timestamp_offset, outhash);
  447. }
  448. /* Tell the device we got a false match */
  449. cta_gen_message(sendbuf, CTA_SEND_FMATCH);
  450. memcpy(sendbuf + 3, buf, CTA_MSG_SIZE - 3);
  451. cta_send_msg(cointerra, sendbuf);
  452. }
  453. free_work(work);
  454. } else {
  455. applog(LOG_INFO, "%s %d: Matching work id 0x%X %d not found", cointerra->drv->name,
  456. cointerra->device_id, retwork, __LINE__);
  457. inc_hw_errors3(corethr, NULL, &nonce, bits_to_diff(wdiffbits));
  458. mutex_lock(&info->lock);
  459. info->no_matching_work++;
  460. mutex_unlock(&info->lock);
  461. }
  462. }
  463. static void cta_parse_wdone(struct thr_info *thr, struct cgpu_info *cointerra,
  464. struct cointerra_info *info, char *buf)
  465. {
  466. uint16_t retwork = *(uint16_t *)(&buf[CTA_DRIVER_TAG]);
  467. struct work *work = take_work_by_id(cointerra, retwork);
  468. uint64_t hashes;
  469. if (likely(work))
  470. free_work(work);
  471. else {
  472. applog(LOG_INFO, "%s %d: Done work not found id 0x%X %d",
  473. cointerra->drv->name, cointerra->device_id, retwork, __LINE__);
  474. inc_hw_errors_only(thr);
  475. }
  476. /* Removing hashes from work done message */
  477. hashes = hu64_from_msg(buf, CTA_WDONE_NONCES);
  478. if (unlikely(hashes > (61 * 0x100000000ull))) {
  479. applog(LOG_INFO, "%s Invalid hash returned %"PRIu64"x %"PRIu64"x %"PRIu64"X",
  480. __func__, info->hashes, hashes, hashes);
  481. hashes = 0;
  482. }
  483. mutex_lock(&info->lock);
  484. info->hashes += hashes;
  485. mutex_unlock(&info->lock);
  486. }
  487. static void u16array_from_msg(uint16_t *u16, int entries, int var, char *buf)
  488. {
  489. int i, j;
  490. for (i = 0, j = 0; i < entries; i++, j += sizeof(uint16_t))
  491. u16[i] = hu16_from_msg(buf, var + j);
  492. }
  493. static void cta_parse_statread(struct cgpu_info *cointerra, struct cointerra_info *info,
  494. char *buf)
  495. {
  496. int i;
  497. mutex_lock(&info->lock);
  498. u16array_from_msg(info->coretemp, CTA_CORES, CTA_STAT_CORETEMPS, buf);
  499. info->ambtemp_low = hu16_from_msg(buf, CTA_STAT_AMBTEMP_LOW);
  500. info->ambtemp_avg = hu16_from_msg(buf, CTA_STAT_AMBTEMP_AVG);
  501. info->ambtemp_high = hu16_from_msg(buf, CTA_STAT_AMBTEMP_HIGH);
  502. u16array_from_msg(info->pump_tachs, CTA_PUMPS, CTA_STAT_PUMP_TACHS, buf);
  503. u16array_from_msg(info->fan_tachs, CTA_FANS, CTA_STAT_FAN_TACHS, buf);
  504. u16array_from_msg(info->corevolts, CTA_CORES, CTA_STAT_CORE_VOLTS, buf);
  505. info->volts33 = hu16_from_msg(buf, CTA_STAT_VOLTS33);
  506. info->volts12 = hu16_from_msg(buf, CTA_STAT_VOLTS12);
  507. info->inactive = hu16_from_msg(buf, CTA_STAT_INACTIVE);
  508. info->active = hu16_from_msg(buf, CTA_STAT_ACTIVE);
  509. mutex_unlock(&info->lock);
  510. struct cgpu_info *proc = cointerra;
  511. for (i = 0; i < CTA_CORES; i++) {
  512. float temp = info->coretemp[i] / 100.;
  513. for (int j = 0; j < 120; (++j), (proc = proc->next_proc))
  514. proc->temp = temp;
  515. }
  516. }
  517. static void u8array_from_msg(uint8_t *u8, int entries, int var, char *buf)
  518. {
  519. int i;
  520. for (i = 0; i < entries; i++)
  521. u8[i] = u8_from_msg(buf, var + i);
  522. }
  523. static void cta_parse_statset(struct cointerra_info *info, char *buf)
  524. {
  525. mutex_lock(&info->lock);
  526. u8array_from_msg(info->coreperf, CTA_CORES, CTA_STAT_PERFMODE, buf);
  527. u8array_from_msg(info->fanspeed, CTA_FANS, CTA_STAT_FANSPEEDS, buf);
  528. info->dies_active = u8_from_msg(buf, CTA_STAT_DIES_ACTIVE);
  529. u8array_from_msg(info->pipes_enabled, CTA_CORES, CTA_STAT_PIPES_ENABLED, buf);
  530. u16array_from_msg(info->corefreqs, CTA_CORES, CTA_STAT_CORE_FREQS, buf);
  531. info->uptime = hu32_from_msg(buf,CTA_STAT_UPTIME);
  532. mutex_unlock(&info->lock);
  533. }
  534. static void cta_parse_info(struct cgpu_info *cointerra, struct cointerra_info *info,
  535. char *buf)
  536. {
  537. mutex_lock(&info->lock);
  538. info->hwrev = hu64_from_msg(buf, CTA_INFO_HWREV);
  539. info->serial = hu32_from_msg(buf, CTA_INFO_SERNO);
  540. info->asics = u8_from_msg(buf, CTA_INFO_NUMASICS);
  541. info->dies = u8_from_msg(buf, CTA_INFO_NUMDIES);
  542. info->cores = hu16_from_msg(buf, CTA_INFO_NUMCORES);
  543. info->board_number = u8_from_msg(buf, CTA_INFO_BOARDNUMBER);
  544. info->fwrev[0] = u8_from_msg(buf, CTA_INFO_FWREV_MAJ);
  545. info->fwrev[1] = u8_from_msg(buf, CTA_INFO_FWREV_MIN);
  546. info->fwrev[2] = u8_from_msg(buf, CTA_INFO_FWREV_MIC);
  547. info->fw_year = hu16_from_msg(buf, CTA_INFO_FWDATE_YEAR);
  548. info->fw_month = u8_from_msg(buf, CTA_INFO_FWDATE_MONTH);
  549. info->fw_day = u8_from_msg(buf, CTA_INFO_FWDATE_DAY);
  550. info->init_diffbits = u8_from_msg(buf, CTA_INFO_INITDIFFBITS);
  551. info->min_diffbits = u8_from_msg(buf, CTA_INFO_MINDIFFBITS);
  552. info->max_diffbits = u8_from_msg(buf, CTA_INFO_MAXDIFFBITS);
  553. mutex_unlock(&info->lock);
  554. #if 0
  555. if (!cointerra->unique_id) {
  556. uint32_t b32 = htobe32(info->serial);
  557. cointerra->unique_id = malloc((4 * 2) + 1);
  558. bin2hex(cointerra->unique_id, &b32, 4);
  559. }
  560. #endif
  561. }
  562. static void cta_parse_rdone(struct cgpu_info *cointerra, struct cointerra_info *info,
  563. char *buf)
  564. {
  565. uint8_t reset_type, diffbits;
  566. uint64_t wdone;
  567. reset_type = buf[CTA_RESET_TYPE];
  568. diffbits = buf[CTA_RESET_DIFF];
  569. wdone = hu64_from_msg(buf, CTA_WDONE_NONCES);
  570. applog(LOG_INFO, "%s %d: Reset done type %u message %u diffbits %"PRIu64" done received",
  571. cointerra->drv->name, cointerra->device_id, reset_type, diffbits, wdone);
  572. if (wdone) {
  573. applog(LOG_INFO, "%s %d: Reset done type %u message %u diffbits %"PRIu64" done received",
  574. cointerra->drv->name, cointerra->device_id, reset_type, diffbits, wdone);
  575. mutex_lock(&info->lock);
  576. info->hashes += wdone;
  577. mutex_unlock(&info->lock);
  578. }
  579. /* Note that the cgsem that is posted here must not be waited on while
  580. * holding the info->lock to not get into a livelock since this
  581. * function also grabs the lock first and it's always best to not sleep
  582. * while holding a lock. */
  583. if (reset_type == CTA_RESET_NEW) {
  584. cta_clear_work(cointerra);
  585. /* Tell reset sender that the reset is complete
  586. * and it may resume. */
  587. notifier_wake(info->reset_notifier);
  588. }
  589. }
  590. static void cta_zero_stats(struct cgpu_info *cointerra);
  591. static void cta_parse_debug(struct cointerra_info *info, char *buf)
  592. {
  593. mutex_lock(&info->lock);
  594. info->tot_underruns = hu16_from_msg(buf, CTA_STAT_UNDERRUNS);
  595. u16array_from_msg(info->tot_hw_errors, CTA_CORES, CTA_STAT_HW_ERRORS, buf);
  596. info->tot_hashes = hu64_from_msg(buf, CTA_STAT_HASHES);
  597. info->tot_flushed_hashes = hu64_from_msg(buf, CTA_STAT_FLUSHED_HASHES);
  598. info->autovoltage = u8_from_msg(buf, CTA_STAT_AUTOVOLTAGE);
  599. info->current_ps_percent = u8_from_msg(buf, CTA_STAT_POWER_PERCENT);
  600. info->power_used = hu16_from_msg(buf,CTA_STAT_POWER_USED);
  601. info->power_voltage = hu16_from_msg(buf,CTA_STAT_VOLTAGE);
  602. info->ipower_used = hu16_from_msg(buf,CTA_STAT_IPOWER_USED);
  603. info->ipower_voltage = hu16_from_msg(buf,CTA_STAT_IVOLTAGE);
  604. info->power_temps[0] = hu16_from_msg(buf,CTA_STAT_PS_TEMP1);
  605. info->power_temps[1] = hu16_from_msg(buf,CTA_STAT_PS_TEMP2);
  606. mutex_unlock(&info->lock);
  607. #if 0
  608. /* Autovoltage is positive only once at startup and eventually drops
  609. * to zero. After that time we reset the stats since they're unreliable
  610. * till then. */
  611. if (unlikely(!info->autovoltage_complete && !info->autovoltage)) {
  612. struct cgpu_info *cointerra = info->thr->cgpu;
  613. info->autovoltage_complete = true;
  614. cgtime(&cointerra->dev_start_tv);
  615. cta_zero_stats(cointerra);
  616. cointerra->total_mhashes = 0;
  617. cointerra->accepted = 0;
  618. cointerra->rejected = 0;
  619. cointerra->hw_errors = 0;
  620. cointerra->utility = 0.0;
  621. cointerra->last_share_pool_time = 0;
  622. cointerra->diff1 = 0;
  623. cointerra->diff_accepted = 0;
  624. cointerra->diff_rejected = 0;
  625. cointerra->last_share_diff = 0;
  626. }
  627. #endif
  628. }
  629. static void cta_parse_msg(struct thr_info *thr, struct cgpu_info *cointerra,
  630. struct cointerra_info *info, char *buf)
  631. {
  632. switch (buf[CTA_MSG_TYPE]) {
  633. default:
  634. case CTA_RECV_UNUSED:
  635. applog(LOG_INFO, "%s %d: Unidentified message type %u",
  636. cointerra->drv->name, cointerra->device_id, buf[CTA_MSG_TYPE]);
  637. break;
  638. case CTA_RECV_REQWORK:
  639. cta_parse_reqwork(cointerra, info, buf);
  640. break;
  641. case CTA_RECV_MATCH:
  642. cta_parse_recvmatch(thr, cointerra, info, buf);
  643. break;
  644. case CTA_RECV_WDONE:
  645. applog(LOG_DEBUG, "%s %d: Work done message received",
  646. cointerra->drv->name, cointerra->device_id);
  647. cta_parse_wdone(thr, cointerra, info, buf);
  648. break;
  649. case CTA_RECV_STATREAD:
  650. applog(LOG_DEBUG, "%s %d: Status readings message received",
  651. cointerra->drv->name, cointerra->device_id);
  652. cta_parse_statread(cointerra, info, buf);
  653. break;
  654. case CTA_RECV_STATSET:
  655. applog(LOG_DEBUG, "%s %d: Status settings message received",
  656. cointerra->drv->name, cointerra->device_id);
  657. cta_parse_statset(info, buf);
  658. break;
  659. case CTA_RECV_INFO:
  660. applog(LOG_DEBUG, "%s %d: Info message received",
  661. cointerra->drv->name, cointerra->device_id);
  662. cta_parse_info(cointerra, info, buf);
  663. break;
  664. case CTA_RECV_MSG:
  665. applog(LOG_NOTICE, "%s: Devlog: %.*s", cointerra->dev_repr, (int)COINTERRA_MSGBODY_SIZE, &buf[CTA_MSG_RECVD]);
  666. break;
  667. case CTA_RECV_RDONE:
  668. cta_parse_rdone(cointerra, info, buf);
  669. break;
  670. case CTA_RECV_STATDEBUG:
  671. cta_parse_debug(info, buf);
  672. break;
  673. }
  674. }
  675. static
  676. void cta_recv_thread(void *arg)
  677. {
  678. struct thr_info *thr = (struct thr_info *)arg;
  679. struct cgpu_info *cointerra = thr->cgpu;
  680. struct cointerra_info *info = cointerra->device_data;
  681. int offset = 0;
  682. while (likely(!cointerra->shutdown)) {
  683. char buf[CTA_READBUF_SIZE];
  684. int amount;
  685. if (unlikely(0))
  686. {
  687. applog(LOG_DEBUG, "%s %d: Device disappeared, disabling recv thread",
  688. cointerra->drv->name, cointerra->device_id);
  689. break;
  690. }
  691. amount = usb_read(info->ep, buf + offset, CTA_MSG_SIZE);
  692. if (amount != CTA_MSG_SIZE && amount != 0) {
  693. applog(LOG_ERR, "%s: Read error %s, read %d",
  694. cointerra->dev_repr, bfg_strerror(errno, BST_ERRNO), amount);
  695. break;
  696. }
  697. offset += amount;
  698. while (offset >= CTA_MSG_SIZE) {
  699. char *msg = mystrstr(buf, offset, cointerra_hdr);
  700. int begin;
  701. if (unlikely(!msg)) {
  702. applog(LOG_WARNING, "%s %d: No message header found, discarding buffer",
  703. cointerra->drv->name, cointerra->device_id);
  704. inc_hw_errors_only(thr);
  705. /* Save the last byte in case it's the fist
  706. * byte of a header. */
  707. begin = CTA_MSG_SIZE - 1;
  708. offset -= begin;
  709. memmove(buf, buf + begin, offset);
  710. continue;
  711. }
  712. if (unlikely(msg != buf)) {
  713. begin = msg - buf;
  714. applog(LOG_WARNING, "%s %d: Reads out of sync, discarding %d bytes",
  715. cointerra->drv->name, cointerra->device_id, begin);
  716. inc_hw_errors_only(thr);
  717. offset -= begin;
  718. memmove(buf, msg, offset);
  719. if (offset < CTA_MSG_SIZE)
  720. break;
  721. }
  722. /* We have enough buffer for a full message, parse now */
  723. cta_parse_msg(thr, cointerra, info, msg);
  724. offset -= CTA_MSG_SIZE;
  725. if (offset > 0)
  726. memmove(buf, buf + CTA_MSG_SIZE, offset);
  727. }
  728. break;
  729. }
  730. }
  731. static
  732. bool cointerra_write_msg(struct lowl_usb_endpoint * const ep, const char * const repr, const uint8_t msgtype, const void * const msgbody)
  733. {
  734. uint8_t buf[COINTERRA_PACKET_SIZE], *p;
  735. memcpy(buf, cointerra_startseq, sizeof(cointerra_startseq));
  736. p = &buf[sizeof(cointerra_startseq)];
  737. pk_u8(p, 0, msgtype);
  738. memcpy(&p[1], msgbody, COINTERRA_MSGBODY_SIZE);
  739. if (usb_write(ep, buf, sizeof(buf)) != sizeof(buf))
  740. return false;
  741. return true;
  742. }
  743. static bool cta_send_msg(struct cgpu_info *cointerra, char *buf)
  744. {
  745. struct cointerra_info *info = cointerra->device_data;
  746. int amount;
  747. /* Serialise usb writes to prevent overlap in case multiple threads
  748. * send messages */
  749. mutex_lock(&info->sendlock);
  750. amount = usb_write(info->ep, buf, CTA_MSG_SIZE);
  751. mutex_unlock(&info->sendlock);
  752. if (unlikely(amount != CTA_MSG_SIZE)) {
  753. applog(LOG_ERR, "%s: Write error %s, wrote %d of %d",
  754. cointerra->dev_repr, bfg_strerror(errno, BST_ERRNO), amount, CTA_MSG_SIZE);
  755. return false;
  756. }
  757. return true;
  758. }
  759. static bool cta_prepare(struct thr_info *thr)
  760. {
  761. struct cgpu_info *cointerra = thr->cgpu;
  762. struct lowlevel_device_info * const llinfo = cointerra->device_data;
  763. struct cointerra_info *info = calloc(sizeof(struct cointerra_info), 1);
  764. char buf[CTA_MSG_SIZE];
  765. sleep(1);
  766. if (unlikely(!info))
  767. quit(1, "Failed to calloc info in cta_detect_one");
  768. for_each_managed_proc(proc, cointerra)
  769. proc->device_data = info;
  770. /* Nominally set a requested value when starting, preempting the need
  771. * for a req-work message. */
  772. info->requested = CTA_MAX_QUEUE;
  773. cointerra_set_queue_full(cointerra, false);
  774. cgpu_set_defaults(cointerra);
  775. bool open_rv = cointerra_open(llinfo, cointerra->dev_repr, &info->usbh, &info->ep, info);
  776. lowlevel_devinfo_free(llinfo);
  777. if (!open_rv)
  778. return false;
  779. info->thr = thr;
  780. mutex_init(&info->lock);
  781. mutex_init(&info->sendlock);
  782. notifier_init(info->reset_notifier);
  783. /* Request a single status setting message */
  784. cta_gen_message(buf, CTA_SEND_REQUEST);
  785. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_STATSET);
  786. msg_from_hu16(buf, CTA_REQ_INTERVAL, 0);
  787. if (!cta_send_msg(cointerra, buf))
  788. return false;
  789. /* Request status debug messages every 60 seconds */
  790. cta_gen_message(buf, CTA_SEND_REQUEST);
  791. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_STATDEBUG);
  792. msg_from_hu16(buf, CTA_REQ_INTERVAL, 6000);
  793. if (!cta_send_msg(cointerra, buf))
  794. return false;
  795. cgtime(&info->core_hash_start);
  796. usb_ep_set_timeouts_ms(info->ep, COINTERRA_USB_TIMEOUT, COINTERRA_USB_TIMEOUT);
  797. timer_set_now(&thr->tv_poll);
  798. return true;
  799. }
  800. static void cta_send_reset(struct cgpu_info *cointerra, struct cointerra_info *info,
  801. uint8_t reset_type, uint8_t diffbits);
  802. static void cta_flush_work(struct cgpu_info *cointerra);
  803. static
  804. bool cointerra_queue_append(struct thr_info * const thr, struct work * const work)
  805. {
  806. struct cgpu_info * const dev = thr->cgpu->device;
  807. // struct thr_info * const master_thr = dev->thr[0];
  808. struct cointerra_info * const devstate = dev->device_data;
  809. struct timeval tv_now, tv_latest;
  810. uint8_t buf[COINTERRA_MSGBODY_SIZE] = {0};
  811. uint16_t ntimeroll, zerobits;
  812. if (unlikely(!devstate->requested))
  813. {
  814. applog(LOG_DEBUG, "%s: Attempt to queue work while none requested; rejecting", dev->dev_repr);
  815. cointerra_set_queue_full(dev, true);
  816. return false;
  817. }
  818. timer_set_now(&tv_now);
  819. timer_set_delay(&tv_latest, &tv_now, cointerra_latest_result_usecs);
  820. ntimeroll = max(0, work_ntime_range(work, &tv_now, &tv_latest, cointerra_desired_roll));
  821. if (unlikely(!devstate->work_id))
  822. ++devstate->work_id;
  823. work->device_id = devstate->work_id;
  824. pk_u16be(buf, 0, work->device_id);
  825. work->subid = htobe16(work->device_id);
  826. swap32yes(&buf[ 6], work->midstate , 0x20 / 4);
  827. swap32yes(&buf[0x26], &work->data[0x40], 0xc / 4);
  828. pk_u16le(buf, 50, ntimeroll);
  829. // Use the real share difficulty up to cointerra_max_nonce_diff
  830. if (work->work_difficulty >= cointerra_max_nonce_diff)
  831. work->nonce_diff = cointerra_max_nonce_diff;
  832. else
  833. work->nonce_diff = work->work_difficulty;
  834. zerobits = log2(floor(work->nonce_diff));
  835. work->nonce_diff = pow(2, zerobits);
  836. zerobits += 0x20;
  837. pk_u16le(buf, 52, zerobits);
  838. if (!cointerra_write_msg(devstate->ep, cointerra_drv.dname, CMTO_WORK, buf))
  839. return false;
  840. // HASH_ADD_INT(master_thr->work, device_id, work);
  841. {
  842. ++dev->queued_count;
  843. timer_set_now(&work->tv_work_start);
  844. HASH_ADD_INT(dev->queued_work, id, work);
  845. }
  846. ++devstate->work_id;
  847. if (!--devstate->requested)
  848. {
  849. applog(LOG_DEBUG, "%s: Sent all requested works, queue full", dev->dev_repr);
  850. cointerra_set_queue_full(dev, true);
  851. }
  852. return true;
  853. }
  854. static
  855. void cointerra_queue_flush(struct thr_info * const thr)
  856. {
  857. }
  858. static void cta_send_reset(struct cgpu_info *cointerra, struct cointerra_info *info,
  859. uint8_t reset_type, uint8_t diffbits)
  860. {
  861. char buf[CTA_MSG_SIZE];
  862. int ret, retries = 0;
  863. /* Clear any accumulated messages in case we've gotten out of sync. */
  864. notifier_reset(info->reset_notifier);
  865. resend:
  866. cta_gen_message(buf, CTA_SEND_RESET);
  867. buf[CTA_RESET_TYPE] = reset_type;
  868. buf[CTA_RESET_LOAD] = info->set_load ?: 255;
  869. buf[CTA_RESET_PSLOAD] = 0;
  870. applog(LOG_INFO, "%s %d: Sending Reset type %u with diffbits %u", cointerra->drv->name,
  871. cointerra->device_id, reset_type, diffbits);
  872. cta_send_msg(cointerra, buf);
  873. /* Wait for read thread to parse a reset message and signal us we may
  874. * return to submitting other messages. Use a timeout in case we have
  875. * a problem and the reset done message never returns. */
  876. if (reset_type == CTA_RESET_NEW) {
  877. ret = notifier_wait_us(info->reset_notifier, CTA_RESET_TIMEOUT * 1000);
  878. if (ret) {
  879. if (++retries < 3) {
  880. applog(LOG_INFO, "%s %d: Timed out waiting for reset done msg, retrying",
  881. cointerra->drv->name, cointerra->device_id);
  882. goto resend;
  883. }
  884. applog(LOG_WARNING, "%s %d: Timed out waiting for reset done msg",
  885. cointerra->drv->name, cointerra->device_id);
  886. }
  887. /* Good place to flush any work we have */
  888. flush_queue(cointerra);
  889. }
  890. }
  891. static void cta_update_work(struct cgpu_info *);
  892. static void cta_flush_work(struct cgpu_info *cointerra)
  893. {
  894. struct cointerra_info *info = cointerra->device_data;
  895. if (1)
  896. cta_update_work(cointerra);
  897. else
  898. {
  899. applog(LOG_INFO, "%s %d: cta_flush_work %d", cointerra->drv->name, cointerra->device_id,
  900. __LINE__);
  901. cta_send_reset(cointerra, info, CTA_RESET_NEW, 0);
  902. }
  903. info->thr->work_restart = false;
  904. }
  905. static void cta_update_work(struct cgpu_info *cointerra)
  906. {
  907. struct cointerra_info *info = cointerra->device_data;
  908. applog(LOG_INFO, "%s %d: Update work", cointerra->drv->name, cointerra->device_id);
  909. cta_send_reset(cointerra, info, CTA_RESET_UPDATE, 0);
  910. }
  911. static void cta_zero_corehashes(struct cointerra_info *info)
  912. {
  913. int i;
  914. for (i = 0; i < CTA_CORES; i++)
  915. info->tot_core_hashes[i] = 0;
  916. cgtime(&info->core_hash_start);
  917. }
  918. /* Send per core hashrate calculations at regular intervals ~every 5 minutes */
  919. static void cta_send_corehashes(struct cgpu_info *cointerra, struct cointerra_info *info,
  920. double corehash_time)
  921. {
  922. uint16_t core_ghs[CTA_CORES];
  923. double k[CTA_CORES];
  924. char buf[CTA_MSG_SIZE];
  925. int i, offset;
  926. for (i = 0; i < CTA_CORES; i++) {
  927. k[i] = (double)info->tot_core_hashes[i] / ((double)32 * (double)0x100000000ull);
  928. k[i] = sqrt(k[i]) + 1;
  929. k[i] *= k[i];
  930. k[i] = k[i] * 32 * ((double)0x100000000ull / (double)1000000000) / corehash_time;
  931. core_ghs[i] = k[i];
  932. }
  933. cta_gen_message(buf, CTA_SEND_COREHASHRATE);
  934. offset = CTA_CORE_HASHRATES;
  935. for (i = 0; i < CTA_CORES; i++) {
  936. msg_from_hu16(buf, offset, core_ghs[i]);
  937. offset += 2; // uint16_t
  938. }
  939. cta_send_msg(cointerra, buf);
  940. }
  941. static void cta_scanwork(struct thr_info *thr)
  942. {
  943. struct cgpu_info *cointerra = thr->cgpu;
  944. struct cointerra_info *info = cointerra->device_data;
  945. double corehash_time;
  946. struct timeval now;
  947. cgtime(&now);
  948. if (unlikely(thr->work_restart)) {
  949. applog(LOG_INFO, "%s %d: Flush work line %d",
  950. cointerra->drv->name, cointerra->device_id,__LINE__);
  951. cta_flush_work(cointerra);
  952. } else {
  953. time_t now_t;
  954. int i;
  955. /* Discard work that was started more than 5 minutes ago as
  956. * a safety precaution backup in case the hardware failed to
  957. * return a work done message for some work items. */
  958. age_queued_work(cointerra, 300.0);
  959. /* Each core should be 1.7MH so at max diff of 32 should
  960. * average a share every ~80 seconds.Use this opportunity to
  961. * unset the bits in any pipes that have not returned a valid
  962. * nonce for over 30 full nonce ranges or 2400s. */
  963. now_t = time(NULL);
  964. for (i = 0; i < 1024; i++) {
  965. if (unlikely(now_t > info->last_pipe_nonce[i] + 2400)) {
  966. int bitchar = i / 8, bitbit = i % 8;
  967. info->pipe_bitmap[bitchar] &= ~(0x80 >> bitbit);
  968. }
  969. }
  970. /* Sleep for up to 0.5 seconds, waking if we need work or
  971. * have received a restart message. */
  972. cta_recv_thread(thr);
  973. if (thr->work_restart) {
  974. applog(LOG_INFO, "%s %d: Flush work line %d",
  975. cointerra->drv->name, cointerra->device_id,__LINE__);
  976. cta_flush_work(cointerra);
  977. }
  978. }
  979. corehash_time = tdiff(&now, &info->core_hash_start);
  980. if (corehash_time > 300) {
  981. cta_send_corehashes(cointerra, info, corehash_time);
  982. cta_zero_corehashes(info);
  983. }
  984. mutex_lock(&info->lock);
  985. info->tot_share_hashes += info->share_hashes;
  986. info->tot_calc_hashes += info->hashes;
  987. info->hashes = info->share_hashes = 0;
  988. mutex_unlock(&info->lock);
  989. }
  990. static void cta_shutdown(struct thr_info *thr)
  991. {
  992. struct cgpu_info *cointerra = thr->cgpu;
  993. cta_close(cointerra);
  994. }
  995. static void cta_zero_stats(struct cgpu_info *cointerra)
  996. {
  997. struct cointerra_info *info = cointerra->device_data;
  998. info->tot_calc_hashes = 0;
  999. info->tot_reset_hashes = info->tot_hashes;
  1000. info->tot_share_hashes = 0;
  1001. cta_zero_corehashes(info);
  1002. }
  1003. static int bits_set(char v)
  1004. {
  1005. int c;
  1006. for (c = 0; v; c++)
  1007. v &= v - 1;
  1008. return c;
  1009. }
  1010. static struct api_data *cta_api_stats(struct cgpu_info *cgpu)
  1011. {
  1012. struct api_data *root = NULL;
  1013. struct cointerra_info *info = cgpu->device_data;
  1014. double dev_runtime = cgpu_runtime(cgpu);
  1015. int i, asic, core, coreno = 0;
  1016. struct timeval now;
  1017. char bitmaphex[36];
  1018. uint64_t ghs, val;
  1019. char buf[64];
  1020. asic = cgpu->proc_id / 480;
  1021. int coreabs = cgpu->proc_id / 120;
  1022. core = coreabs % 4;
  1023. /* Info data */
  1024. root = api_add_uint16(root, "HW Revision", &info->hwrev, false);
  1025. root = api_add_uint32(root, "Serial", &info->serial, false);
  1026. root = api_add_uint8(root, "Asics", &info->asics, false);
  1027. root = api_add_uint8(root, "Dies", &info->dies, false);
  1028. root = api_add_uint16(root, "Cores", &info->cores, false);
  1029. root = api_add_uint8(root, "Board number", &info->board_number, false);
  1030. sprintf(buf, "%u.%u.%u", info->fwrev[0], info->fwrev[1], info->fwrev[2]);
  1031. root = api_add_string(root, "FW Revision", buf, true);
  1032. sprintf(buf, "%04u-%02u-%02u", info->fw_year, info->fw_month, info->fw_day);
  1033. root = api_add_string(root, "FW Date", buf, true);
  1034. root = api_add_uint8(root, "Init diffbits", &info->init_diffbits, false);
  1035. root = api_add_uint8(root, "Min diffbits", &info->min_diffbits, false);
  1036. root = api_add_uint8(root, "Max diffbits", &info->max_diffbits, false);
  1037. /* Status readings */
  1038. {
  1039. i = coreabs;
  1040. sprintf(buf, "CoreTemp%d", i);
  1041. root = api_add_int16(root, buf, &info->coretemp[i], false);
  1042. }
  1043. root = api_add_int16(root, "Ambient Low", &info->ambtemp_low, false);
  1044. root = api_add_int16(root, "Ambient Avg", &info->ambtemp_avg, false);
  1045. root = api_add_int16(root, "Ambient High", &info->ambtemp_high, false);
  1046. for (i = 0; i < CTA_PUMPS; i++) {
  1047. sprintf(buf, "PumpRPM%d", i);
  1048. root = api_add_uint16(root, buf, &info->pump_tachs[i], false);
  1049. }
  1050. for (i = 0; i < CTA_FANS; i++) {
  1051. sprintf(buf, "FanRPM%d", i);
  1052. root = api_add_uint16(root, buf, &info->fan_tachs[i], false);
  1053. }
  1054. {
  1055. i = coreabs;
  1056. sprintf(buf, "CoreFreqs%d", i);
  1057. root = api_add_uint16(root, buf, &info->corefreqs[i], false);
  1058. }
  1059. {
  1060. i = coreabs;
  1061. sprintf(buf, "CoreVolts%d", i);
  1062. root = api_add_uint16(root, buf, &info->corevolts[i], false);
  1063. }
  1064. root = api_add_uint16(root, "Volts3.3", &info->volts33, false);
  1065. root = api_add_uint16(root, "Volts12", &info->volts12, false);
  1066. root = api_add_uint16(root, "Inactive", &info->inactive, false);
  1067. root = api_add_uint16(root, "Active", &info->active, false);
  1068. /* Status settings */
  1069. {
  1070. i = coreabs;
  1071. sprintf(buf, "CorePerfMode%d", i);
  1072. root = api_add_uint8(root, buf, &info->coreperf[i], false);
  1073. }
  1074. for (i = 0; i < CTA_FANS; i++) {
  1075. sprintf(buf, "FanSpeed%d", i);
  1076. root = api_add_uint8(root, buf, &info->fanspeed[i], false);
  1077. }
  1078. root = api_add_uint8(root, "DiesActive", &info->dies_active, false);
  1079. {
  1080. i = coreabs;
  1081. sprintf(buf, "PipesEnabled%d", i);
  1082. root = api_add_uint8(root, buf, &info->pipes_enabled[i], false);
  1083. }
  1084. /* Status debug */
  1085. root = api_add_int(root, "Underruns", &info->tot_underruns, false);
  1086. {
  1087. i = coreabs;
  1088. sprintf(buf, "HWErrors%d", i);
  1089. root = api_add_uint16(root, buf, &info->tot_hw_errors[i], false);
  1090. }
  1091. ghs = info->tot_calc_hashes / dev_runtime;
  1092. root = api_add_uint64(root, "Calc hashrate", &ghs, true);
  1093. ghs = (info->tot_hashes - info->tot_reset_hashes) / dev_runtime;
  1094. root = api_add_uint64(root, "Hashrate", &ghs, true);
  1095. ghs = info->tot_share_hashes / dev_runtime;
  1096. root = api_add_uint64(root, "Share hashrate", &ghs, true);
  1097. root = api_add_uint64(root, "Total calc hashes", &info->tot_calc_hashes, false);
  1098. ghs = info->tot_hashes - info->tot_reset_hashes;
  1099. root = api_add_uint64(root, "Total hashes", &ghs, true);
  1100. root = api_add_uint64(root, "Total raw hashes", &info->tot_hashes, false);
  1101. root = api_add_uint64(root, "Total share hashes", &info->tot_share_hashes, false);
  1102. root = api_add_uint64(root, "Total flushed hashes", &info->tot_flushed_hashes, false);
  1103. val = cgpu->diff_accepted * 0x100000000ull;
  1104. root = api_add_uint64(root, "Accepted hashes", &val, true);
  1105. ghs = val / dev_runtime;
  1106. root = api_add_uint64(root, "Accepted hashrate", &ghs, true);
  1107. val = cgpu->diff_rejected * 0x100000000ull;
  1108. root = api_add_uint64(root, "Rejected hashes", &val, true);
  1109. ghs = val / dev_runtime;
  1110. root = api_add_uint64(root, "Rejected hashrate", &ghs, true);
  1111. cgtime(&now);
  1112. dev_runtime = tdiff(&now, &info->core_hash_start);
  1113. if (dev_runtime < 1)
  1114. dev_runtime = 1;
  1115. {
  1116. i = coreabs;
  1117. sprintf(buf, "Core%d hashrate", i);
  1118. ghs = info->tot_core_hashes[i] / dev_runtime;
  1119. root = api_add_uint64(root, buf, &ghs, true);
  1120. }
  1121. root = api_add_uint32(root, "Uptime",&info->uptime,false);
  1122. {
  1123. char bitmapcount[40], asiccore[12];
  1124. int count = 0;
  1125. sprintf(asiccore, "Asic%dCore%d", asic, core);
  1126. bin2hex(bitmaphex, &info->pipe_bitmap[coreno], 16);
  1127. for (i = coreno; i < coreno + 16; i++)
  1128. count += bits_set(info->pipe_bitmap[i]);
  1129. snprintf(bitmapcount, 40, "%d:%s", count, bitmaphex);
  1130. root = api_add_string(root, asiccore, bitmapcount, true);
  1131. coreno += 16;
  1132. }
  1133. root = api_add_uint8(root, "AV", &info->autovoltage, false);
  1134. root = api_add_uint8(root, "Power Supply Percent", &info->current_ps_percent, false);
  1135. root = api_add_uint16(root, "Power Used", &info->power_used, false);
  1136. root = api_add_uint16(root, "IOUT", &info->power_used, false);
  1137. root = api_add_uint16(root, "VOUT", &info->power_voltage, false);
  1138. root = api_add_uint16(root, "IIN", &info->ipower_used, false);
  1139. root = api_add_uint16(root, "VIN", &info->ipower_voltage, false);
  1140. root = api_add_uint16(root, "PSTemp1", &info->power_temps[0], false);
  1141. root = api_add_uint16(root, "PSTemp2", &info->power_temps[1], false);
  1142. return root;
  1143. }
  1144. static
  1145. const char *cointerra_set_load(struct cgpu_info *proc, const char *optname, const char *newvalue, char *replybuf, enum bfg_set_device_replytype *out_success)
  1146. {
  1147. struct cointerra_info * const devstate = proc->device_data;
  1148. const int nv = atoi(newvalue);
  1149. if (nv <= 0 || nv > 0xff)
  1150. return "Invalid power stepping value";
  1151. devstate->set_load = nv;
  1152. return NULL;
  1153. }
  1154. static const struct bfg_set_device_definition cointerra_set_device_funcs[] = {
  1155. {"load", cointerra_set_load, "power stepping (1-255)"},
  1156. {NULL},
  1157. };
  1158. struct device_drv cointerra_drv = {
  1159. .dname = "cointerra",
  1160. .name = "CTA",
  1161. .lowl_match = cointerra_lowl_match,
  1162. .lowl_probe = cointerra_lowl_probe,
  1163. .thread_init = cta_prepare,
  1164. .minerloop = minerloop_queue,
  1165. .queue_append = cointerra_queue_append,
  1166. .queue_flush = cointerra_queue_flush,
  1167. // TODO .update_work = cta_update_work,
  1168. .poll = cta_scanwork,
  1169. .get_api_stats = cta_api_stats,
  1170. .thread_shutdown = cta_shutdown,
  1171. .zero_stats = cta_zero_stats,
  1172. };