driver-cointerra.c 38 KB

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