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