/ driver-klondike.c
driver-klondike.c
   1  /*
   2   * Copyright 2013 Andrew Smith
   3   * Copyright 2013 Con Kolivas
   4   * Copyright 2013 Chris Savery
   5   *
   6   * This program is free software; you can redistribute it and/or modify it
   7   * under the terms of the GNU General Public License as published by the Free
   8   * Software Foundation; either version 3 of the License, or (at your option)
   9   * any later version.  See COPYING for more details.
  10   */
  11  
  12  #include <float.h>
  13  #include <limits.h>
  14  #include <pthread.h>
  15  #include <stdint.h>
  16  #include <stdio.h>
  17  #include <strings.h>
  18  #include <sys/time.h>
  19  #include <unistd.h>
  20  #include <math.h>
  21  
  22  #include "config.h"
  23  
  24  #include "compat.h"
  25  #include "miner.h"
  26  #include "usbutils.h"
  27  
  28  #define K1 "K1"
  29  #define K16 "K16"
  30  #define K64 "K64"
  31  
  32  static const char *msg_detect_send = "DSend";
  33  static const char *msg_detect_reply = "DReply";
  34  static const char *msg_send = "Send";
  35  static const char *msg_reply = "Reply";
  36  
  37  #define KLN_CMD_ABORT	'A'
  38  #define KLN_CMD_CONFIG	'C'
  39  #define KLN_CMD_ENABLE	'E'
  40  #define KLN_CMD_IDENT	'I'
  41  #define KLN_CMD_NONCE	'='
  42  #define KLN_CMD_STATUS	'S'
  43  #define KLN_CMD_WORK	'W'
  44  
  45  #define KLN_CMD_ENABLE_OFF	'0'
  46  #define KLN_CMD_ENABLE_ON	'1'
  47  
  48  #define MIDSTATE_BYTES 32
  49  #define MERKLE_OFFSET 64
  50  #define MERKLE_BYTES 12
  51  
  52  #define REPLY_SIZE		15	// adequate for all types of replies
  53  #define MAX_KLINES		1024	// unhandled reply limit
  54  #define REPLY_WAIT_TIME		100 	// poll interval for a cmd waiting it's reply
  55  #define CMD_REPLY_RETRIES	8	// how many retries for cmds
  56  #define MAX_WORK_COUNT		4	// for now, must be binary multiple and match firmware
  57  #define TACH_FACTOR		87890	// fan rpm divisor
  58  
  59  #define KLN_KILLWORK_TEMP	53.5
  60  #define KLN_COOLED_DOWN		45.5
  61  
  62  /*
  63   *  Work older than 5s will already be completed
  64   *  FYI it must not be possible to complete 256 work
  65   *  items this quickly on a single device -
  66   *  thus limited to 219.9GH/s per device
  67   */
  68  #define OLD_WORK_MS ((int)(5 * 1000))
  69  
  70  /*
  71   * How many incorrect slave counts to ignore in a row
  72   * 2 means it allows random grabage returned twice
  73   * Until slaves are implemented, this should never occur
  74   * so allowing 2 in a row should ignore random errros
  75   */
  76  #define KLN_ISS_IGNORE 2
  77  
  78  /*
  79   * If the queue status hasn't been updated for this long then do it now
  80   * 5GH/s = 859ms per full nonce range
  81   */
  82  #define LATE_UPDATE_MS ((int)(2.5 * 1000))
  83  
  84  // If 5 late updates in a row, try to reset the device
  85  #define LATE_UPDATE_LIMIT	5
  86  
  87  // If the reset fails sleep for 1s
  88  #define LATE_UPDATE_SLEEP_MS 1000
  89  
  90  // However give up after 8s
  91  #define LATE_UPDATE_NODEV_MS ((int)(8.0 * 1000))
  92  
  93  struct device_drv klondike_drv;
  94  
  95  typedef struct klondike_header {
  96  	uint8_t cmd;
  97  	uint8_t dev;
  98  	uint8_t buf[REPLY_SIZE-2];
  99  } HEADER;
 100  
 101  #define K_2(_bytes) ((int)(_bytes[0]) + \
 102  			((int)(_bytes[1]) << 8))
 103  
 104  #define K_4(_bytes) ((uint64_t)(_bytes[0]) + \
 105  			((uint64_t)(_bytes[1]) << 8) + \
 106  			((uint64_t)(_bytes[2]) << 16) + \
 107  			((uint64_t)(_bytes[3]) << 24))
 108  
 109  #define K_SERIAL(_serial) K_4(_serial)
 110  #define K_HASHCOUNT(_hashcount) K_2(_hashcount)
 111  #define K_MAXCOUNT(_maxcount) K_2(_maxcount)
 112  #define K_NONCE(_nonce) K_4(_nonce)
 113  #define K_HASHCLOCK(_hashclock) K_2(_hashclock)
 114  
 115  #define SET_HASHCLOCK(_hashclock, _value) do { \
 116  						(_hashclock)[0] = (uint8_t)((_value) & 0xff); \
 117  						(_hashclock)[1] = (uint8_t)(((_value) >> 8) & 0xff); \
 118  					  } while(0)
 119  
 120  #define KSENDHD(_add) (sizeof(uint8_t) + sizeof(uint8_t) + _add)
 121  
 122  typedef struct klondike_id {
 123  	uint8_t cmd;
 124  	uint8_t dev;
 125  	uint8_t version;
 126  	uint8_t product[7];
 127  	uint8_t serial[4];
 128  } IDENTITY;
 129  
 130  typedef struct klondike_status {
 131  	uint8_t cmd;
 132  	uint8_t dev;
 133  	uint8_t state;
 134  	uint8_t chipcount;
 135  	uint8_t slavecount;
 136  	uint8_t workqc;
 137  	uint8_t workid;
 138  	uint8_t temp;
 139  	uint8_t fanspeed;
 140  	uint8_t errorcount;
 141  	uint8_t hashcount[2];
 142  	uint8_t maxcount[2];
 143  	uint8_t noise;
 144  } WORKSTATUS;
 145  
 146  typedef struct _worktask {
 147  	uint8_t cmd;
 148  	uint8_t dev;
 149  	uint8_t workid;
 150  	uint8_t midstate[32];
 151  	uint8_t merkle[12];
 152  } WORKTASK;
 153  
 154  typedef struct _workresult {
 155  	uint8_t cmd;
 156  	uint8_t dev;
 157  	uint8_t workid;
 158  	uint8_t nonce[4];
 159  } WORKRESULT;
 160  
 161  typedef struct klondike_cfg {
 162  	uint8_t cmd;
 163  	uint8_t dev;
 164  	uint8_t hashclock[2];
 165  	uint8_t temptarget;
 166  	uint8_t tempcritical;
 167  	uint8_t fantarget;
 168  	uint8_t pad2;
 169  } WORKCFG;
 170  
 171  typedef struct kline {
 172  	union {
 173  		HEADER hd;
 174  		IDENTITY id;
 175  		WORKSTATUS ws;
 176  		WORKTASK wt;
 177  		WORKRESULT wr;
 178  		WORKCFG cfg;
 179  	};
 180  } KLINE;
 181  
 182  #define zero_kline(_kline) memset((void *)(_kline), 0, sizeof(KLINE));
 183  
 184  typedef struct device_info {
 185  	uint32_t noncecount;
 186  	uint32_t nextworkid;
 187  	uint16_t lasthashcount;
 188  	uint64_t totalhashcount;
 189  	uint32_t rangesize;
 190  	uint32_t *chipstats;
 191  } DEVINFO;
 192  
 193  typedef struct klist {
 194  	struct klist *prev;
 195  	struct klist *next;
 196  	KLINE kline;
 197  	struct timeval tv_when;
 198  	int block_seq;
 199  	bool ready;
 200  	bool working;
 201  } KLIST;
 202  
 203  typedef struct jobque {
 204  	int workqc;
 205  	struct timeval last_update;
 206  	bool overheat;
 207  	bool flushed;
 208  	int late_update_count;
 209  	int late_update_sequential;
 210  } JOBQUE;
 211  
 212  struct klondike_info {
 213  	pthread_rwlock_t stat_lock;
 214  	struct thr_info replies_thr;
 215  	cglock_t klist_lock;
 216  	KLIST *used;
 217  	KLIST *free;
 218  	int kline_count;
 219  	int used_count;
 220  	int block_seq;
 221  	KLIST *status;
 222  	DEVINFO *devinfo;
 223  	KLIST *cfg;
 224  	JOBQUE *jobque;
 225  	int noncecount;
 226  	uint64_t hashcount;
 227  	uint64_t errorcount;
 228  	uint64_t noisecount;
 229  	int incorrect_slave_sequential;
 230  
 231  	// us Delay from USB reply to being processed
 232  	double delay_count;
 233  	double delay_total;
 234  	double delay_min;
 235  	double delay_max;
 236  
 237  	struct timeval tv_last_nonce_received;
 238  
 239  	// Time from recieving one nonce to the next
 240  	double nonce_count;
 241  	double nonce_total;
 242  	double nonce_min;
 243  	double nonce_max;
 244  
 245  	int wque_size;
 246  	int wque_cleared;
 247  
 248  	bool initialised;
 249  };
 250  
 251  static KLIST *new_klist_set(struct cgpu_info *klncgpu)
 252  {
 253  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 254  	KLIST *klist = NULL;
 255  	int i;
 256  
 257  	klist = calloc(MAX_KLINES, sizeof(*klist));
 258  	if (!klist)
 259  		quit(1, "Failed to calloc klist - when old count=%d", klninfo->kline_count);
 260  
 261  	klninfo->kline_count += MAX_KLINES;
 262  
 263  	klist[0].prev = NULL;
 264  	klist[0].next = &(klist[1]);
 265  	for (i = 1; i < MAX_KLINES-1; i++) {
 266  		klist[i].prev = &klist[i-1];
 267  		klist[i].next = &klist[i+1];
 268  	}
 269  	klist[MAX_KLINES-1].prev = &(klist[MAX_KLINES-2]);
 270  	klist[MAX_KLINES-1].next = NULL;
 271  
 272  	return klist;
 273  }
 274  
 275  static KLIST *allocate_kitem(struct cgpu_info *klncgpu)
 276  {
 277  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 278  	KLIST *kitem = NULL;
 279  	int ran_out = 0;
 280  	char errbuf[1024];
 281  
 282  	cg_wlock(&klninfo->klist_lock);
 283  
 284  	if (klninfo->free == NULL) {
 285  		ran_out = klninfo->kline_count;
 286  		klninfo->free = new_klist_set(klncgpu);
 287  		snprintf(errbuf, sizeof(errbuf),
 288  				 "%s%i: KLINE count exceeded %d, now %d",
 289  				 klncgpu->drv->name, klncgpu->device_id,
 290  				 ran_out, klninfo->kline_count);
 291  	}
 292  
 293  	kitem = klninfo->free;
 294  
 295  	klninfo->free = klninfo->free->next;
 296  	if (klninfo->free)
 297  		klninfo->free->prev = NULL;
 298  
 299  	kitem->next = klninfo->used;
 300  	kitem->prev = NULL;
 301  	if (kitem->next)
 302  		kitem->next->prev = kitem;
 303  	klninfo->used = kitem;
 304  
 305  	kitem->ready = false;
 306  	kitem->working = false;
 307  
 308  	memset((void *)&(kitem->kline), 0, sizeof(kitem->kline));
 309  
 310  	klninfo->used_count++;
 311  
 312  	cg_wunlock(&klninfo->klist_lock);
 313  
 314  	if (ran_out > 0)
 315  		applog(LOG_WARNING, "%s", errbuf);
 316  
 317  	return kitem;
 318  }
 319  
 320  static KLIST *release_kitem(struct cgpu_info *klncgpu, KLIST *kitem)
 321  {
 322  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 323  
 324  	cg_wlock(&klninfo->klist_lock);
 325  
 326  	if (kitem == klninfo->used)
 327  		klninfo->used = kitem->next;
 328  
 329  	if (kitem->next)
 330  		kitem->next->prev = kitem->prev;
 331  	if (kitem->prev)
 332  		kitem->prev->next = kitem->next;
 333  
 334  	kitem->next = klninfo->free;
 335  	if (klninfo->free)
 336  		klninfo->free->prev = kitem;
 337  
 338  	kitem->prev = NULL;
 339  
 340  	klninfo->free = kitem;
 341  
 342  	klninfo->used_count--;
 343  
 344  	cg_wunlock(&klninfo->klist_lock);
 345  
 346  	return NULL;
 347  }
 348  
 349  static double cvtKlnToC(uint8_t temp)
 350  {
 351  	double Rt, stein, celsius;
 352  
 353  	if (temp == 0)
 354  		return 0.0;
 355  
 356  	Rt = 1000.0 * 255.0 / (double)temp - 1000.0;
 357  
 358  	stein = log(Rt / 2200.0) / 3987.0;
 359  
 360  	stein += 1.0 / (double)(25.0 + 273.15);
 361  
 362  	celsius = (1.0 / stein) - 273.15;
 363  
 364  	// For display of bad data
 365  	if (celsius < 0.0)
 366  		celsius = 0.0;
 367  	if (celsius > 200.0)
 368  		celsius = 200.0;
 369  
 370  	return celsius;
 371  }
 372  
 373  static int cvtCToKln(double deg)
 374  {
 375  	double Rt, stein, temp;
 376  
 377  	if (deg < 0.0)
 378  		deg = 0.0;
 379  
 380  	stein = 1.0 / (deg + 273.15);
 381  
 382  	stein -= 1.0 / (double)(25.0 + 273.15);
 383  
 384  	Rt = exp(stein * 3987.0) * 2200.0;
 385  
 386  	if (Rt == -1000.0)
 387  		Rt++;
 388  
 389  	temp = 1000.0 * 256.0 / (Rt + 1000.0);
 390  
 391  	if (temp > 255)
 392  		temp = 255;
 393  	if (temp < 0)
 394  		temp = 0;
 395  
 396  	return (int)temp;
 397  }
 398  
 399  // Change this to LOG_WARNING if you wish to always see the replies
 400  #define READ_DEBUG LOG_DEBUG
 401  
 402  static void display_kline(struct cgpu_info *klncgpu, KLINE *kline, const char *msg)
 403  {
 404  	char *hexdata;
 405  
 406  	switch (kline->hd.cmd) {
 407  		case KLN_CMD_NONCE:
 408  			applog(READ_DEBUG,
 409  				"%s%i:%d %s work [%c] dev=%d workid=%d"
 410  				" nonce=0x%08x",
 411  				klncgpu->drv->name, klncgpu->device_id,
 412  				(int)(kline->wr.dev), msg, kline->wr.cmd,
 413  				(int)(kline->wr.dev),
 414  				(int)(kline->wr.workid),
 415  				(unsigned int)K_NONCE(kline->wr.nonce) - 0xC0);
 416  			break;
 417  		case KLN_CMD_STATUS:
 418  		case KLN_CMD_WORK:
 419  		case KLN_CMD_ENABLE:
 420  		case KLN_CMD_ABORT:
 421  			applog(READ_DEBUG,
 422  				"%s%i:%d %s status [%c] dev=%d chips=%d"
 423  				" slaves=%d workcq=%d workid=%d temp=%d fan=%d"
 424  				" errors=%d hashes=%d max=%d noise=%d",
 425  				klncgpu->drv->name, klncgpu->device_id,
 426  				(int)(kline->ws.dev), msg, kline->ws.cmd,
 427  				(int)(kline->ws.dev),
 428  				(int)(kline->ws.chipcount),
 429  				(int)(kline->ws.slavecount),
 430  				(int)(kline->ws.workqc),
 431  				(int)(kline->ws.workid),
 432  				(int)(kline->ws.temp),
 433  				(int)(kline->ws.fanspeed),
 434  				(int)(kline->ws.errorcount),
 435  				K_HASHCOUNT(kline->ws.hashcount),
 436  				K_MAXCOUNT(kline->ws.maxcount),
 437  				(int)(kline->ws.noise));
 438  			break;
 439  		case KLN_CMD_CONFIG:
 440  			applog(READ_DEBUG,
 441  				"%s%i:%d %s config [%c] dev=%d clock=%d"
 442  				" temptarget=%d tempcrit=%d fan=%d",
 443  				klncgpu->drv->name, klncgpu->device_id,
 444  				(int)(kline->cfg.dev), msg, kline->cfg.cmd,
 445  				(int)(kline->cfg.dev),
 446  				K_HASHCLOCK(kline->cfg.hashclock),
 447  				(int)(kline->cfg.temptarget),
 448  				(int)(kline->cfg.tempcritical),
 449  				(int)(kline->cfg.fantarget));
 450  			break;
 451  		case KLN_CMD_IDENT:
 452  			applog(READ_DEBUG,
 453  				"%s%i:%d %s info [%c] version=0x%02x prod=%.7s"
 454  				" serial=0x%08x",
 455  				klncgpu->drv->name, klncgpu->device_id,
 456  				(int)(kline->hd.dev), msg, kline->hd.cmd,
 457  				(int)(kline->id.version),
 458  				kline->id.product,
 459  				(unsigned int)K_SERIAL(kline->id.serial));
 460  			break;
 461  		default:
 462  			hexdata = bin2hex((unsigned char *)&(kline->hd.dev), REPLY_SIZE - 1);
 463  			applog(LOG_ERR,
 464  				"%s%i:%d %s [%c:%s] unknown and ignored",
 465  				klncgpu->drv->name, klncgpu->device_id,
 466  				(int)(kline->hd.dev), msg, kline->hd.cmd,
 467  				hexdata);
 468  			free(hexdata);
 469  			break;
 470  	}
 471  }
 472  
 473  static void display_send_kline(struct cgpu_info *klncgpu, KLINE *kline, const char *msg)
 474  {
 475  	char *hexdata;
 476  
 477  	switch (kline->hd.cmd) {
 478  		case KLN_CMD_WORK:
 479  			applog(READ_DEBUG,
 480  				"%s%i:%d %s work [%c] dev=%d workid=0x%02x ...",
 481  				klncgpu->drv->name, klncgpu->device_id,
 482  				(int)(kline->wt.dev), msg, kline->ws.cmd,
 483  				(int)(kline->wt.dev),
 484  				(int)(kline->wt.workid));
 485  			break;
 486  		case KLN_CMD_CONFIG:
 487  			applog(READ_DEBUG,
 488  				"%s%i:%d %s config [%c] dev=%d clock=%d"
 489  				" temptarget=%d tempcrit=%d fan=%d",
 490  				klncgpu->drv->name, klncgpu->device_id,
 491  				(int)(kline->cfg.dev), msg, kline->cfg.cmd,
 492  				(int)(kline->cfg.dev),
 493  				K_HASHCLOCK(kline->cfg.hashclock),
 494  				(int)(kline->cfg.temptarget),
 495  				(int)(kline->cfg.tempcritical),
 496  				(int)(kline->cfg.fantarget));
 497  			break;
 498  		case KLN_CMD_IDENT:
 499  		case KLN_CMD_STATUS:
 500  		case KLN_CMD_ABORT:
 501  			applog(READ_DEBUG,
 502  				"%s%i:%d %s cmd [%c]",
 503  				klncgpu->drv->name, klncgpu->device_id,
 504  				(int)(kline->hd.dev), msg, kline->hd.cmd);
 505  			break;
 506  		case KLN_CMD_ENABLE:
 507  			applog(READ_DEBUG,
 508  				"%s%i:%d %s enable [%c] enable=%c",
 509  				klncgpu->drv->name, klncgpu->device_id,
 510  				(int)(kline->hd.dev), msg, kline->hd.cmd,
 511  				(char)(kline->hd.buf[0]));
 512  			break;
 513  		case KLN_CMD_NONCE:
 514  		default:
 515  			hexdata = bin2hex((unsigned char *)&(kline->hd.dev), REPLY_SIZE - 1);
 516  			applog(LOG_ERR,
 517  				"%s%i:%d %s [%c:%s] unknown/unexpected and ignored",
 518  				klncgpu->drv->name, klncgpu->device_id,
 519  				(int)(kline->hd.dev), msg, kline->hd.cmd,
 520  				hexdata);
 521  			free(hexdata);
 522  			break;
 523  	}
 524  }
 525  
 526  static bool SendCmd(struct cgpu_info *klncgpu, KLINE *kline, int datalen)
 527  {
 528  	int err, amt, writ;
 529  
 530  	if (klncgpu->usbinfo.nodev)
 531  		return false;
 532  
 533  	display_send_kline(klncgpu, kline, msg_send);
 534  	writ = KSENDHD(datalen);
 535  	err = usb_write(klncgpu, (char *)kline, writ, &amt, C_REQUESTRESULTS);
 536  	if (err < 0 || amt != writ) {
 537  		applog(LOG_ERR, "%s%i:%d Cmd:%c Dev:%d, write failed (%d:%d:%d)",
 538  				klncgpu->drv->name, klncgpu->device_id,
 539  				(int)(kline->hd.dev),
 540  				kline->hd.cmd, (int)(kline->hd.dev),
 541  				writ, amt, err);
 542  		return false;
 543  	}
 544  
 545  	return true;
 546  }
 547  
 548  static KLIST *GetReply(struct cgpu_info *klncgpu, uint8_t cmd, uint8_t dev)
 549  {
 550  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 551  	KLIST *kitem;
 552  	int retries = CMD_REPLY_RETRIES;
 553  
 554  	while (retries-- > 0 && klncgpu->shutdown == false) {
 555  		cgsleep_ms(REPLY_WAIT_TIME);
 556  		cg_rlock(&klninfo->klist_lock);
 557  		kitem = klninfo->used;
 558  		while (kitem) {
 559  			if (kitem->kline.hd.cmd == cmd &&
 560  			    kitem->kline.hd.dev == dev &&
 561  			    kitem->ready == true && kitem->working == false) {
 562  				kitem->working = true;
 563  				cg_runlock(&klninfo->klist_lock);
 564  				return kitem;
 565  			}
 566  			kitem = kitem->next;
 567  		}
 568  		cg_runlock(&klninfo->klist_lock);
 569  	}
 570  	return NULL;
 571  }
 572  
 573  static KLIST *SendCmdGetReply(struct cgpu_info *klncgpu, KLINE *kline, int datalen)
 574  {
 575  	if (!SendCmd(klncgpu, kline, datalen))
 576  		return NULL;
 577  
 578  	return GetReply(klncgpu, kline->hd.cmd, kline->hd.dev);
 579  }
 580  
 581  static bool klondike_get_stats(struct cgpu_info *klncgpu)
 582  {
 583  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 584  	KLIST *kitem;
 585  	KLINE kline;
 586  	int slaves, dev;
 587  
 588  	if (klncgpu->usbinfo.nodev || klninfo->status == NULL)
 589  		return false;
 590  
 591  	applog(LOG_DEBUG, "%s%i: getting status",
 592  			klncgpu->drv->name, klncgpu->device_id);
 593  
 594  	rd_lock(&(klninfo->stat_lock));
 595  	slaves = klninfo->status[0].kline.ws.slavecount;
 596  	rd_unlock(&(klninfo->stat_lock));
 597  
 598  	// loop thru devices and get status for each
 599  	for (dev = 0; dev <= slaves; dev++) {
 600  		zero_kline(&kline);
 601  		kline.hd.cmd = KLN_CMD_STATUS;
 602  		kline.hd.dev = dev;
 603  		kitem = SendCmdGetReply(klncgpu, &kline, 0);
 604  		if (kitem != NULL) {
 605  			wr_lock(&(klninfo->stat_lock));
 606  			memcpy((void *)(&(klninfo->status[dev])),
 607  				(void *)kitem,
 608  				sizeof(klninfo->status[dev]));
 609  			wr_unlock(&(klninfo->stat_lock));
 610  			kitem = release_kitem(klncgpu, kitem);
 611  		} else {
 612  			applog(LOG_ERR, "%s%i:%d failed to update stats",
 613  					klncgpu->drv->name, klncgpu->device_id, dev);
 614  		}
 615  	}
 616  	return true;
 617  }
 618  
 619  // TODO: this only enables the master (no slaves)
 620  static bool kln_enable(struct cgpu_info *klncgpu)
 621  {
 622  	KLIST *kitem;
 623  	KLINE kline;
 624  	int tries = 2;
 625  	bool ok = false;
 626  
 627  	zero_kline(&kline);
 628  	kline.hd.cmd = KLN_CMD_ENABLE;
 629  	kline.hd.dev = 0;
 630  	kline.hd.buf[0] = KLN_CMD_ENABLE_ON;
 631  	
 632  	while (tries-- > 0) {
 633  		kitem = SendCmdGetReply(klncgpu, &kline, 1);
 634  		if (kitem) {
 635  			kitem = release_kitem(klncgpu, kitem);
 636  			ok = true;
 637  			break;
 638  		}
 639  		cgsleep_ms(50);
 640  	}
 641  
 642  	if (ok)
 643  		cgsleep_ms(50);
 644  
 645  	return ok;
 646  }
 647  
 648  static void kln_disable(struct cgpu_info *klncgpu, int dev, bool all)
 649  {
 650  	KLINE kline;
 651  	int i;
 652  
 653  	zero_kline(&kline);
 654  	kline.hd.cmd = KLN_CMD_ENABLE;
 655  	kline.hd.buf[0] = KLN_CMD_ENABLE_OFF;
 656  	for (i = (all ? 0 : dev); i <= dev; i++) {
 657  		kline.hd.dev = i;
 658  		SendCmd(klncgpu, &kline, KSENDHD(1));
 659  	}
 660  }
 661  
 662  static bool klondike_init(struct cgpu_info *klncgpu)
 663  {
 664  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 665  	KLIST *kitem;
 666  	KLINE kline;
 667  	int slaves, dev;
 668  
 669  	klninfo->initialised = false;
 670  
 671  	zero_kline(&kline);
 672  	kline.hd.cmd = KLN_CMD_STATUS;
 673  	kline.hd.dev = 0;
 674  	kitem = SendCmdGetReply(klncgpu, &kline, 0);
 675  	if (kitem == NULL)
 676  		return false;
 677  
 678  	slaves = kitem->kline.ws.slavecount;
 679  	if (klninfo->status == NULL) {
 680  		applog(LOG_DEBUG, "%s%i: initializing data",
 681  				klncgpu->drv->name, klncgpu->device_id);
 682  
 683  		// alloc space for status, devinfo, cfg and jobque for master and slaves
 684  		klninfo->status = calloc(slaves+1, sizeof(*(klninfo->status)));
 685  		if (unlikely(!klninfo->status))
 686  			quit(1, "Failed to calloc status array in klondke_get_stats");
 687  		klninfo->devinfo = calloc(slaves+1, sizeof(*(klninfo->devinfo)));
 688  		if (unlikely(!klninfo->devinfo))
 689  			quit(1, "Failed to calloc devinfo array in klondke_get_stats");
 690  		klninfo->cfg = calloc(slaves+1, sizeof(*(klninfo->cfg)));
 691  		if (unlikely(!klninfo->cfg))
 692  			quit(1, "Failed to calloc cfg array in klondke_get_stats");
 693  		klninfo->jobque = calloc(slaves+1, sizeof(*(klninfo->jobque)));
 694  		if (unlikely(!klninfo->jobque))
 695  			quit(1, "Failed to calloc jobque array in klondke_get_stats");
 696  	}
 697  
 698  	memcpy((void *)(&(klninfo->status[0])), (void *)kitem, sizeof(klninfo->status[0]));
 699  	kitem = release_kitem(klncgpu, kitem);
 700  
 701  	// zero init triggers read back only
 702  	zero_kline(&kline);
 703  	kline.cfg.cmd = KLN_CMD_CONFIG;
 704  
 705  	int size = 2;
 706  
 707  	// boundaries are checked by device, with valid values returned
 708  	if (opt_klondike_options != NULL) {
 709  		int hashclock;
 710  		double temptarget;
 711  
 712  		sscanf(opt_klondike_options, "%d:%lf", &hashclock, &temptarget);
 713  		SET_HASHCLOCK(kline.cfg.hashclock, hashclock);
 714  		kline.cfg.temptarget = cvtCToKln(temptarget);
 715  		kline.cfg.tempcritical = 0; // hard code for old firmware
 716  		kline.cfg.fantarget = 0xff; // hard code for old firmware
 717  		size = sizeof(kline.cfg) - 2;
 718  	}
 719  
 720  	for (dev = 0; dev <= slaves; dev++) {
 721  		kline.cfg.dev = dev;
 722  		kitem = SendCmdGetReply(klncgpu, &kline, size);
 723  		if (kitem != NULL) {
 724  			memcpy((void *)&(klninfo->cfg[dev]), kitem, sizeof(klninfo->cfg[dev]));
 725  			applog(LOG_WARNING, "%s%i:%d config (%d: Clk: %d, T:%.0lf, C:%.0lf, F:%d)",
 726  				klncgpu->drv->name, klncgpu->device_id, dev,
 727  				dev, K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock),
 728  				cvtKlnToC(klninfo->cfg[dev].kline.cfg.temptarget),
 729  				cvtKlnToC(klninfo->cfg[dev].kline.cfg.tempcritical),
 730  				(int)100*klninfo->cfg[dev].kline.cfg.fantarget/256);
 731  			kitem = release_kitem(klncgpu, kitem);
 732  		}
 733  	}
 734  	klondike_get_stats(klncgpu);
 735  	klninfo->initialised = true;
 736  	for (dev = 0; dev <= slaves; dev++) {
 737  		klninfo->devinfo[dev].rangesize = ((uint64_t)1<<32) / klninfo->status[dev].kline.ws.chipcount;
 738  		klninfo->devinfo[dev].chipstats = calloc(klninfo->status[dev].kline.ws.chipcount*2 , sizeof(uint32_t));
 739  	}
 740  
 741  	bool ok = kln_enable(klncgpu);
 742  
 743  	if (!ok)
 744  		applog(LOG_ERR, "%s%i: failed to enable", klncgpu->drv->name, klncgpu->device_id);
 745  
 746  	return ok;
 747  }
 748  
 749  static void control_init(struct cgpu_info *klncgpu)
 750  {
 751  	int err, interface;
 752  
 753  	if (klncgpu->usbinfo.nodev)
 754  		return;
 755  
 756  	interface = usb_interface(klncgpu);
 757  
 758  	err = usb_transfer(klncgpu, 0, 9, 1, interface, C_RESET);
 759  
 760  	applog(LOG_DEBUG, "%s%i: reset got err %d",
 761  			  klncgpu->drv->name, klncgpu->device_id, err);
 762  }
 763  
 764  static struct cgpu_info *klondike_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
 765  {
 766  	struct cgpu_info *klncgpu = usb_alloc_cgpu(&klondike_drv, 1);
 767  	struct klondike_info *klninfo = NULL;
 768  	KLINE kline;
 769  
 770  	if (unlikely(!klncgpu))
 771  		quit(1, "Failed to calloc klncgpu in klondike_detect_one");
 772  
 773  	klninfo = calloc(1, sizeof(*klninfo));
 774  	if (unlikely(!klninfo))
 775  		quit(1, "Failed to calloc klninfo in klondke_detect_one");
 776  	klncgpu->device_data = (void *)klninfo;
 777  
 778  	klninfo->free = new_klist_set(klncgpu);
 779  
 780  	if (usb_init(klncgpu, dev, found)) {
 781  		int sent, recd, err;
 782  		KLIST kitem;
 783  		int attempts = 0;
 784  
 785  		control_init(klncgpu);
 786  
 787  		while (attempts++ < 3) {
 788  			kline.hd.cmd = KLN_CMD_IDENT;
 789  			kline.hd.dev = 0;
 790  			display_send_kline(klncgpu, &kline, msg_detect_send);
 791  			err = usb_write(klncgpu, (char *)&(kline.hd), 2, &sent, C_REQUESTRESULTS);
 792  			if (err < 0 || sent != 2) {
 793  				applog(LOG_ERR, "%s (%s) detect write failed (%d:%d)",
 794  						klncgpu->drv->dname,
 795  						klncgpu->device_path,
 796  						sent, err);
 797  			}
 798  			cgsleep_ms(REPLY_WAIT_TIME*10);
 799  			err = usb_read(klncgpu, (char *)&(kitem.kline), REPLY_SIZE, &recd, C_GETRESULTS);
 800  			if (err < 0) {
 801  				applog(LOG_ERR, "%s (%s) detect read failed (%d:%d)",
 802  						klncgpu->drv->dname,
 803  						klncgpu->device_path,
 804  						recd, err);
 805  			} else if (recd < 1) {
 806  				applog(LOG_ERR, "%s (%s) detect empty reply (%d)",
 807  						klncgpu->drv->dname,
 808  						klncgpu->device_path,
 809  						recd);
 810  			} else if (kitem.kline.hd.cmd == KLN_CMD_IDENT && kitem.kline.hd.dev == 0) {
 811  				display_kline(klncgpu, &kitem.kline, msg_detect_reply);
 812  				applog(LOG_DEBUG, "%s (%s) detect successful (%d attempt%s)",
 813  						  klncgpu->drv->dname,
 814  						  klncgpu->device_path,
 815  						  attempts, attempts == 1 ? "" : "s");
 816  				if (!add_cgpu(klncgpu))
 817  					break;
 818  				update_usb_stats(klncgpu);
 819  				applog(LOG_DEBUG, "Klondike cgpu added");
 820  				rwlock_init(&klninfo->stat_lock);
 821  				cglock_init(&klninfo->klist_lock);
 822  				return klncgpu;
 823  			}
 824  		}
 825  		usb_uninit(klncgpu);
 826  	}
 827  	free(klninfo->free);
 828  	free(klninfo);
 829  	free(klncgpu);
 830  	return NULL;
 831  }
 832  
 833  static void klondike_detect(bool __maybe_unused hotplug)
 834  {
 835  	usb_detect(&klondike_drv, klondike_detect_one);
 836  }
 837  
 838  static void klondike_identify(__maybe_unused struct cgpu_info *klncgpu)
 839  {
 840  /*
 841  	KLINE kline;
 842  
 843  	zero_kline(&kline);
 844  	kline.hd.cmd = KLN_CMD_IDENT;
 845  	kline.hd.dev = 0;
 846  	SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
 847  */
 848  }
 849  
 850  static void klondike_check_nonce(struct cgpu_info *klncgpu, KLIST *kitem)
 851  {
 852  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 853  	struct work *work, *look, *tmp;
 854  	KLINE *kline = &(kitem->kline);
 855  	struct timeval tv_now;
 856  	double us_diff;
 857  	uint32_t nonce = K_NONCE(kline->wr.nonce) - 0xC0;
 858  
 859  	applog(LOG_DEBUG, "%s%i:%d FOUND NONCE (%02x:%08x)",
 860  			  klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev),
 861  			  kline->wr.workid, (unsigned int)nonce);
 862  
 863  	work = NULL;
 864  	cgtime(&tv_now);
 865  	rd_lock(&(klncgpu->qlock));
 866  	HASH_ITER(hh, klncgpu->queued_work, look, tmp) {
 867  		if (ms_tdiff(&tv_now, &(look->tv_stamp)) < OLD_WORK_MS &&
 868  		    (look->subid == (kline->wr.dev*256 + kline->wr.workid))) {
 869  			work = look;
 870  			break;
 871  		}
 872  	}
 873  	rd_unlock(&(klncgpu->qlock));
 874  
 875  	if (work) {
 876  		wr_lock(&(klninfo->stat_lock));
 877  		klninfo->devinfo[kline->wr.dev].noncecount++;
 878  		klninfo->noncecount++;
 879  		wr_unlock(&(klninfo->stat_lock));
 880  
 881  		applog(LOG_DEBUG, "%s%i:%d SUBMIT NONCE (%02x:%08x)",
 882  				  klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev),
 883  				  kline->wr.workid, (unsigned int)nonce);
 884  
 885  		cgtime(&tv_now);
 886  		bool ok = submit_nonce(klncgpu->thr[0], work, nonce);
 887  
 888  		applog(LOG_DEBUG, "%s%i:%d chip stats %d, %08x, %d, %d",
 889  				  klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev),
 890  				  kline->wr.dev, (unsigned int)nonce,
 891  				  klninfo->devinfo[kline->wr.dev].rangesize,
 892  				  klninfo->status[kline->wr.dev].kline.ws.chipcount);
 893  
 894  		klninfo->devinfo[kline->wr.dev].chipstats[(nonce / klninfo->devinfo[kline->wr.dev].rangesize) + (ok ? 0 : klninfo->status[kline->wr.dev].kline.ws.chipcount)]++;
 895  
 896  		us_diff = us_tdiff(&tv_now, &(kitem->tv_when));
 897  		if (klninfo->delay_count == 0) {
 898  			klninfo->delay_min = us_diff;
 899  			klninfo->delay_max = us_diff;
 900  		} else {
 901  			if (klninfo->delay_min > us_diff)
 902  				klninfo->delay_min = us_diff;
 903  			if (klninfo->delay_max < us_diff)
 904  				klninfo->delay_max = us_diff;
 905  		}
 906  		klninfo->delay_count++;
 907  		klninfo->delay_total += us_diff;
 908  
 909  		if (klninfo->nonce_count > 0) {
 910  			us_diff = us_tdiff(&(kitem->tv_when), &(klninfo->tv_last_nonce_received));
 911  			if (klninfo->nonce_count == 1) {
 912  				klninfo->nonce_min = us_diff;
 913  				klninfo->nonce_max = us_diff;
 914  			} else {
 915  				if (klninfo->nonce_min > us_diff)
 916  					klninfo->nonce_min = us_diff;
 917  				if (klninfo->nonce_max < us_diff)
 918  					klninfo->nonce_max = us_diff;
 919  			}
 920  			klninfo->nonce_total += us_diff;
 921  		}
 922  		klninfo->nonce_count++;
 923  
 924  		memcpy(&(klninfo->tv_last_nonce_received), &(kitem->tv_when),
 925  			sizeof(klninfo->tv_last_nonce_received));
 926  
 927  		return;
 928  	}
 929  
 930  	applog(LOG_ERR, "%s%i:%d unknown work (%02x:%08x) - ignored",
 931  			klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev),
 932  			kline->wr.workid, (unsigned int)nonce);
 933  
 934  	//inc_hw_errors(klncgpu->thr[0]);
 935  }
 936  
 937  // thread to keep looking for replies
 938  static void *klondike_get_replies(void *userdata)
 939  {
 940  	struct cgpu_info *klncgpu = (struct cgpu_info *)userdata;
 941  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
 942  	KLIST *kitem = NULL;
 943  	char *hexdata;
 944  	int err, recd, slaves, dev, isc;
 945  	bool overheat, sent;
 946  
 947  	applog(LOG_DEBUG, "%s%i: listening for replies",
 948  			  klncgpu->drv->name, klncgpu->device_id);
 949  
 950  	while (klncgpu->shutdown == false) {
 951  		if (klncgpu->usbinfo.nodev)
 952  			return NULL;
 953  
 954  		if (kitem == NULL)
 955  			kitem = allocate_kitem(klncgpu);
 956  		else
 957  			memset((void *)&(kitem->kline), 0, sizeof(kitem->kline));
 958  
 959  		err = usb_read(klncgpu, (char *)&(kitem->kline), REPLY_SIZE, &recd, C_GETRESULTS);
 960  		if (err || recd != REPLY_SIZE) {
 961  			if (err != -7)
 962  				applog(LOG_ERR, "%s%i: reply err=%d amt=%d",
 963  						klncgpu->drv->name, klncgpu->device_id,
 964  						err, recd);
 965  		}
 966  		if (!err && recd == REPLY_SIZE) {
 967  			cgtime(&(kitem->tv_when));
 968  			rd_lock(&(klninfo->stat_lock));
 969  			kitem->block_seq = klninfo->block_seq;
 970  			rd_unlock(&(klninfo->stat_lock));
 971  			if (opt_log_level <= READ_DEBUG) {
 972  				hexdata = bin2hex((unsigned char *)&(kitem->kline.hd.dev), recd-1);
 973  				applog(READ_DEBUG, "%s%i:%d reply [%c:%s]",
 974  						klncgpu->drv->name, klncgpu->device_id,
 975  						(int)(kitem->kline.hd.dev),
 976  						kitem->kline.hd.cmd, hexdata);
 977  				free(hexdata);
 978  			}
 979  
 980  			// We can't check this until it's initialised
 981  			if (klninfo->initialised) {
 982  				rd_lock(&(klninfo->stat_lock));
 983  				slaves = klninfo->status[0].kline.ws.slavecount;
 984  				rd_unlock(&(klninfo->stat_lock));
 985  
 986  				if (kitem->kline.hd.dev > slaves) {
 987  					applog(LOG_ERR, "%s%i: reply [%c] has invalid dev=%d (max=%d) using 0",
 988  							klncgpu->drv->name, klncgpu->device_id,
 989  							(char)(kitem->kline.hd.cmd),
 990  							(int)(kitem->kline.hd.dev),
 991  							slaves);
 992  					/* TODO: this is rather problematic if there are slaves
 993  					 * however without slaves - it should always be zero */
 994  					kitem->kline.hd.dev = 0;
 995  				} else {
 996  					wr_lock(&(klninfo->stat_lock));
 997  					klninfo->jobque[kitem->kline.hd.dev].late_update_sequential = 0;
 998  					wr_unlock(&(klninfo->stat_lock));
 999  				}
1000  			}
1001  
1002  			switch (kitem->kline.hd.cmd) {
1003  				case KLN_CMD_NONCE:
1004  					klondike_check_nonce(klncgpu, kitem);
1005  					display_kline(klncgpu, &kitem->kline, msg_reply);
1006  					break;
1007  				case KLN_CMD_WORK:
1008  					// We can't do/check this until it's initialised
1009  					if (klninfo->initialised) {
1010  						dev = kitem->kline.ws.dev;
1011  						if (kitem->kline.ws.workqc == 0) {
1012  							bool idle = false;
1013  							rd_lock(&(klninfo->stat_lock));
1014  							if (klninfo->jobque[dev].flushed == false)
1015  								idle = true;
1016  							slaves = klninfo->status[0].kline.ws.slavecount;
1017  							rd_unlock(&(klninfo->stat_lock));
1018  							if (idle)
1019  								applog(LOG_WARNING, "%s%i:%d went idle before work was sent",
1020  										    klncgpu->drv->name,
1021  										    klncgpu->device_id,
1022  										    dev);
1023  						}
1024  						wr_lock(&(klninfo->stat_lock));
1025  						klninfo->jobque[dev].flushed = false;
1026  						wr_unlock(&(klninfo->stat_lock));
1027  					}
1028  				case KLN_CMD_STATUS:
1029  				case KLN_CMD_ABORT:
1030  					// We can't do/check this until it's initialised
1031  					if (klninfo->initialised) {
1032  						isc = 0;
1033  						dev = kitem->kline.ws.dev;
1034  						wr_lock(&(klninfo->stat_lock));
1035  						klninfo->jobque[dev].workqc = (int)(kitem->kline.ws.workqc);
1036  						cgtime(&(klninfo->jobque[dev].last_update));
1037  						slaves = klninfo->status[0].kline.ws.slavecount;
1038  						overheat = klninfo->jobque[dev].overheat;
1039  						if (dev == 0) {
1040  							if (kitem->kline.ws.slavecount != slaves)
1041  								isc = ++klninfo->incorrect_slave_sequential;
1042  							else
1043  								isc = klninfo->incorrect_slave_sequential = 0;
1044  						}
1045  						wr_unlock(&(klninfo->stat_lock));
1046  
1047  						if (isc) {
1048  							applog(LOG_ERR, "%s%i:%d reply [%c] has a diff"
1049  									" # of slaves=%d (curr=%d)%s",
1050  									klncgpu->drv->name,
1051  									klncgpu->device_id,
1052  									dev,
1053  									(char)(kitem->kline.ws.cmd),
1054  									(int)(kitem->kline.ws.slavecount),
1055  									slaves,
1056  									isc <= KLN_ISS_IGNORE ? "" :
1057  									 " disabling device");
1058  							if (isc > KLN_ISS_IGNORE)
1059  								usb_nodev(klncgpu);
1060  							break;
1061  						}
1062  
1063  						if (!overheat) {
1064  							double temp = cvtKlnToC(kitem->kline.ws.temp);
1065  							if (temp >= KLN_KILLWORK_TEMP) {
1066  								KLINE kline;
1067  
1068  								wr_lock(&(klninfo->stat_lock));
1069  								klninfo->jobque[dev].overheat = true;
1070  								wr_unlock(&(klninfo->stat_lock));
1071  
1072  								applog(LOG_WARNING, "%s%i:%d Critical overheat (%.0fC)",
1073  										    klncgpu->drv->name,
1074  										    klncgpu->device_id,
1075  										    dev, temp);
1076  
1077  								zero_kline(&kline);
1078  								kline.hd.cmd = KLN_CMD_ABORT;
1079  								kline.hd.dev = dev;
1080  								sent = SendCmd(klncgpu, &kline, KSENDHD(0));
1081  								kln_disable(klncgpu, dev, false);
1082  								if (!sent) {
1083  									applog(LOG_ERR, "%s%i:%d overheat failed to"
1084  											" abort work - disabling device",
1085  											klncgpu->drv->name,
1086  											klncgpu->device_id,
1087  											dev);
1088  									usb_nodev(klncgpu);
1089  								}
1090  							}
1091  						}
1092  					}
1093  				case KLN_CMD_ENABLE:
1094  					wr_lock(&(klninfo->stat_lock));
1095  					klninfo->errorcount += kitem->kline.ws.errorcount;
1096  					klninfo->noisecount += kitem->kline.ws.noise;
1097  					wr_unlock(&(klninfo->stat_lock));
1098  					display_kline(klncgpu, &kitem->kline, msg_reply);
1099  					kitem->ready = true;
1100  					kitem = NULL;
1101  					break;
1102  				case KLN_CMD_CONFIG:
1103  					display_kline(klncgpu, &kitem->kline, msg_reply);
1104  					kitem->ready = true;
1105  					kitem = NULL;
1106  					break;
1107  				case KLN_CMD_IDENT:
1108  					display_kline(klncgpu, &kitem->kline, msg_reply);
1109  					kitem->ready = true;
1110  					kitem = NULL;
1111  					break;
1112  				default:
1113  					display_kline(klncgpu, &kitem->kline, msg_reply);
1114  					break;
1115  			}
1116  		}
1117  	}
1118  	return NULL;
1119  }
1120  
1121  static void klondike_flush_work(struct cgpu_info *klncgpu)
1122  {
1123  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1124  	KLIST *kitem;
1125  	KLINE kline;
1126  	int slaves, dev;
1127  
1128  	if (klninfo->initialised) {
1129  		wr_lock(&(klninfo->stat_lock));
1130  		klninfo->block_seq++;
1131  		slaves = klninfo->status[0].kline.ws.slavecount;
1132  		wr_unlock(&(klninfo->stat_lock));
1133  
1134  		applog(LOG_DEBUG, "%s%i: flushing work",
1135  				  klncgpu->drv->name, klncgpu->device_id);
1136  		zero_kline(&kline);
1137  		kline.hd.cmd = KLN_CMD_ABORT;
1138  		for (dev = 0; dev <= slaves; dev++) {
1139  			kline.hd.dev = dev;
1140  			kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
1141  			if (kitem != NULL) {
1142  				wr_lock(&(klninfo->stat_lock));
1143  				memcpy((void *)&(klninfo->status[dev]),
1144  					kitem,
1145  					sizeof(klninfo->status[dev]));
1146  				klninfo->jobque[dev].flushed = true;
1147  				wr_unlock(&(klninfo->stat_lock));
1148  				kitem = release_kitem(klncgpu, kitem);
1149  			}
1150  		}
1151  	}
1152  }
1153  
1154  static bool klondike_thread_prepare(struct thr_info *thr)
1155  {
1156  	struct cgpu_info *klncgpu = thr->cgpu;
1157  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1158  
1159  	if (thr_info_create(&(klninfo->replies_thr), NULL, klondike_get_replies, (void *)klncgpu)) {
1160  		applog(LOG_ERR, "%s%i: thread create failed", klncgpu->drv->name, klncgpu->device_id);
1161  		return false;
1162  	}
1163  	pthread_detach(klninfo->replies_thr.pth);
1164  
1165  	// let the listening get started
1166  	cgsleep_ms(100);
1167  
1168  	return klondike_init(klncgpu);
1169  }
1170  
1171  static bool klondike_thread_init(struct thr_info *thr)
1172  {
1173  	struct cgpu_info *klncgpu = thr->cgpu;
1174  
1175  	if (klncgpu->usbinfo.nodev)
1176  		return false;
1177  
1178  	klondike_flush_work(klncgpu);
1179  
1180  	return true;
1181  }
1182  
1183  static void klondike_shutdown(struct thr_info *thr)
1184  {
1185  	struct cgpu_info *klncgpu = thr->cgpu;
1186  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1187  
1188  	applog(LOG_DEBUG, "%s%i: shutting down work",
1189  			  klncgpu->drv->name, klncgpu->device_id);
1190  
1191  	kln_disable(klncgpu, klninfo->status[0].kline.ws.slavecount, true);
1192  
1193  	klncgpu->shutdown = true;
1194  }
1195  
1196  static void klondike_thread_enable(struct thr_info *thr)
1197  {
1198  	struct cgpu_info *klncgpu = thr->cgpu;
1199  
1200  	if (klncgpu->usbinfo.nodev)
1201  		return;
1202  
1203  /*
1204  	KLINE kline;
1205  
1206  	zero_kline(&kline);
1207  	kline.hd.cmd = KLN_CMD_ENABLE;
1208  	kline.hd.dev = dev;
1209  	kline.hd.buf[0] = KLN_CMD_ENABLE_OFF;
1210  	kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(1));
1211  */
1212  
1213  }
1214  
1215  static bool klondike_send_work(struct cgpu_info *klncgpu, int dev, struct work *work)
1216  {
1217  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1218  	struct work *look, *tmp;
1219  	KLINE kline;
1220  	struct timeval tv_old;
1221  	int wque_size, wque_cleared;
1222  
1223  	if (klncgpu->usbinfo.nodev)
1224  		return false;
1225  
1226  	zero_kline(&kline);
1227  	kline.wt.cmd = KLN_CMD_WORK;
1228  	kline.wt.dev = dev;
1229  	memcpy(kline.wt.midstate, work->midstate, MIDSTATE_BYTES);
1230  	memcpy(kline.wt.merkle, work->data + MERKLE_OFFSET, MERKLE_BYTES);
1231  	kline.wt.workid = (uint8_t)(klninfo->devinfo[dev].nextworkid++ & 0xFF);
1232  	work->subid = dev*256 + kline.wt.workid;
1233  	cgtime(&work->tv_stamp);
1234  
1235  	if (opt_log_level <= LOG_DEBUG) {
1236  		char *hexdata = bin2hex((void *)&kline.wt, sizeof(kline.wt));
1237  		applog(LOG_DEBUG, "WORKDATA: %s", hexdata);
1238  		free(hexdata);
1239  	}
1240  
1241  	applog(LOG_DEBUG, "%s%i:%d sending work (%d:%02x)",
1242  			  klncgpu->drv->name, klncgpu->device_id, dev,
1243  			  dev, kline.wt.workid);
1244  	KLIST *kitem = SendCmdGetReply(klncgpu, &kline, sizeof(kline.wt));
1245  	if (kitem != NULL) {
1246  		wr_lock(&(klninfo->stat_lock));
1247  		memcpy((void *)&(klninfo->status[dev]), kitem, sizeof(klninfo->status[dev]));
1248  		wr_unlock(&(klninfo->stat_lock));
1249  		kitem = release_kitem(klncgpu, kitem);
1250  
1251  		// remove old work
1252  		wque_size = 0;
1253  		wque_cleared = 0;
1254  		cgtime(&tv_old);
1255  		wr_lock(&klncgpu->qlock);
1256  		HASH_ITER(hh, klncgpu->queued_work, look, tmp) {
1257  			if (ms_tdiff(&tv_old, &(look->tv_stamp)) > OLD_WORK_MS) {
1258  				__work_completed(klncgpu, look);
1259  				free_work(look);
1260  				wque_cleared++;
1261  			} else
1262  				wque_size++;
1263  		}
1264  		wr_unlock(&klncgpu->qlock);
1265  
1266  		wr_lock(&(klninfo->stat_lock));
1267  		klninfo->wque_size = wque_size;
1268  		klninfo->wque_cleared = wque_cleared;
1269  		wr_unlock(&(klninfo->stat_lock));
1270  		return true;
1271  	}
1272  	return false;
1273  }
1274  
1275  static bool klondike_queue_full(struct cgpu_info *klncgpu)
1276  {
1277  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1278  	struct work *work = NULL;
1279  	int dev, queued, slaves, seq, howlong;
1280  	struct timeval now;
1281  	bool nowork;
1282  
1283  	if (klncgpu->shutdown == true)
1284  		return true;
1285  
1286  	cgtime(&now);
1287  	rd_lock(&(klninfo->stat_lock));
1288  	slaves = klninfo->status[0].kline.ws.slavecount;
1289  	for (dev = 0; dev <= slaves; dev++)
1290  		if (ms_tdiff(&now, &(klninfo->jobque[dev].last_update)) > LATE_UPDATE_MS) {
1291  			klninfo->jobque[dev].late_update_count++;
1292  			seq = ++klninfo->jobque[dev].late_update_sequential;
1293  			rd_unlock(&(klninfo->stat_lock));
1294  			if (seq < LATE_UPDATE_LIMIT) {
1295  				applog(LOG_DEBUG, "%s%i:%d late update",
1296  						klncgpu->drv->name, klncgpu->device_id, dev);
1297  				klondike_get_stats(klncgpu);
1298  				goto que;
1299  			} else {
1300  				applog(LOG_WARNING, "%s%i:%d late update (%d) reached - attempting reset",
1301  						    klncgpu->drv->name, klncgpu->device_id,
1302  						    dev, LATE_UPDATE_LIMIT);
1303  				control_init(klncgpu);
1304  				kln_enable(klncgpu);
1305  				klondike_get_stats(klncgpu);
1306  				rd_lock(&(klninfo->stat_lock));
1307  				howlong = ms_tdiff(&now, &(klninfo->jobque[dev].last_update));
1308  				if (howlong > LATE_UPDATE_MS) {
1309  					rd_unlock(&(klninfo->stat_lock));
1310  					if (howlong > LATE_UPDATE_NODEV_MS) {
1311  						applog(LOG_ERR, "%s%i:%d reset failed - dropping device",
1312  								klncgpu->drv->name, klncgpu->device_id, dev);
1313  						usb_nodev(klncgpu);
1314  					} else
1315  						cgsleep_ms(LATE_UPDATE_SLEEP_MS);
1316  
1317  					return true;
1318  				}
1319  				break;
1320  			}
1321  		}
1322  	rd_unlock(&(klninfo->stat_lock));
1323  
1324  que:
1325  
1326  	nowork = true;
1327  	for (queued = 0; queued < MAX_WORK_COUNT-1; queued++)
1328  		for (dev = 0; dev <= slaves; dev++) {
1329  tryagain:
1330  			rd_lock(&(klninfo->stat_lock));
1331  			if (klninfo->jobque[dev].overheat) {
1332  				double temp = cvtKlnToC(klninfo->status[0].kline.ws.temp);
1333  				if ((queued == MAX_WORK_COUNT-2) &&
1334  				    ms_tdiff(&now, &(klninfo->jobque[dev].last_update)) > (LATE_UPDATE_MS/2)) {
1335  					rd_unlock(&(klninfo->stat_lock));
1336  					klondike_get_stats(klncgpu);
1337  					goto tryagain;
1338  				}
1339  				if (temp <= KLN_COOLED_DOWN) {
1340  					klninfo->jobque[dev].overheat = false;
1341  					rd_unlock(&(klninfo->stat_lock));
1342  					applog(LOG_WARNING, "%s%i:%d Overheat recovered (%.0fC)",
1343  							    klncgpu->drv->name, klncgpu->device_id,
1344  							    dev, temp);
1345  					kln_enable(klncgpu);
1346  					goto tryagain;
1347  				} else {
1348  					rd_unlock(&(klninfo->stat_lock));
1349  					continue;
1350  				}
1351  			}
1352  
1353  			if (klninfo->jobque[dev].workqc <= queued) {
1354  				rd_unlock(&(klninfo->stat_lock));
1355  				if (!work)
1356  					work = get_queued(klncgpu);
1357  				if (unlikely(!work))
1358  					return false;
1359  				nowork = false;
1360  				if (klondike_send_work(klncgpu, dev, work))
1361  					return false;
1362  			} else
1363  				rd_unlock(&(klninfo->stat_lock));
1364  		}
1365  
1366  	if (nowork)
1367  		cgsleep_ms(10); // avoid a hard loop in case we have nothing to do
1368  
1369  	return true;
1370  }
1371  
1372  static int64_t klondike_scanwork(struct thr_info *thr)
1373  {
1374  	struct cgpu_info *klncgpu = thr->cgpu;
1375  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1376  	int64_t newhashcount = 0;
1377  	int dev, slaves;
1378  
1379  	if (klncgpu->usbinfo.nodev)
1380  		return -1;
1381  
1382  	restart_wait(thr, 200);
1383  	if (klninfo->status != NULL) {
1384  		rd_lock(&(klninfo->stat_lock));
1385  		slaves = klninfo->status[0].kline.ws.slavecount;
1386  		for (dev = 0; dev <= slaves; dev++) {
1387  			uint64_t newhashdev = 0, hashcount;
1388  			int maxcount;
1389  
1390  			hashcount = K_HASHCOUNT(klninfo->status[dev].kline.ws.hashcount);
1391  			maxcount = K_MAXCOUNT(klninfo->status[dev].kline.ws.maxcount);
1392  			// todo: chg this to check workid for wrapped instead
1393  			if (klninfo->devinfo[dev].lasthashcount > hashcount)
1394  				newhashdev += maxcount; // hash counter wrapped
1395  			newhashdev += hashcount - klninfo->devinfo[dev].lasthashcount;
1396  			klninfo->devinfo[dev].lasthashcount = hashcount;
1397  			if (maxcount != 0)
1398  				klninfo->hashcount += (newhashdev << 32) / maxcount;
1399  		}
1400  		newhashcount += 0xffffffffull * (uint64_t)klninfo->noncecount;
1401  		klninfo->noncecount = 0;
1402  		rd_unlock(&(klninfo->stat_lock));
1403  	}
1404  
1405  	return newhashcount;
1406  }
1407  
1408  
1409  static void get_klondike_statline_before(char *buf, size_t siz, struct cgpu_info *klncgpu)
1410  {
1411  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1412  	uint8_t temp = 0xFF;
1413  	uint16_t fan = 0;
1414  	uint16_t clock = 0;
1415  	int dev, slaves;
1416  
1417  	if (klninfo->status == NULL) {
1418  		blank_get_statline_before(buf, siz, klncgpu);
1419  		return;
1420  	}
1421  
1422  	rd_lock(&(klninfo->stat_lock));
1423  	slaves = klninfo->status[0].kline.ws.slavecount;
1424  	for (dev = 0; dev <= slaves; dev++) {
1425  		if (klninfo->status[dev].kline.ws.temp < temp)
1426  			temp = klninfo->status[dev].kline.ws.temp;
1427  		fan += klninfo->cfg[dev].kline.cfg.fantarget;
1428  		clock += (uint16_t)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock);
1429  	}
1430  	rd_unlock(&(klninfo->stat_lock));
1431  	fan /= slaves + 1;
1432  	//fan *= 100/255; // <-- You can't do this because int 100 / int 255 == 0
1433          fan = 100 * fan / 255;
1434  	if (fan > 100)
1435  		fan = 100;
1436  	clock /= slaves + 1;
1437  	if (clock > 999) // error - so truncate it
1438  		clock = 999;
1439  
1440  	tailsprintf(buf, siz, "%3dMHz %3d%% %.1fC", (int)clock, (int)fan, cvtKlnToC(temp));
1441  }
1442  
1443  static struct api_data *klondike_api_stats(struct cgpu_info *klncgpu)
1444  {
1445  	struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
1446  	struct api_data *root = NULL;
1447  	char buf[32];
1448  	int dev, slaves;
1449  
1450  	if (klninfo->status == NULL)
1451  		return NULL;
1452  
1453  	rd_lock(&(klninfo->stat_lock));
1454  	slaves = klninfo->status[0].kline.ws.slavecount;
1455  	for (dev = 0; dev <= slaves; dev++) {
1456  
1457  		float fTemp = cvtKlnToC(klninfo->status[dev].kline.ws.temp);
1458  		sprintf(buf, "Temp %d", dev);
1459  		root = api_add_temp(root, buf, &fTemp, true);
1460  
1461  		double dClk = (double)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock);
1462  		sprintf(buf, "Clock %d", dev);
1463  		root = api_add_freq(root, buf, &dClk, true);
1464  
1465  		unsigned int iFan = (unsigned int)100 * klninfo->cfg[dev].kline.cfg.fantarget / 255;
1466  		sprintf(buf, "Fan Percent %d", dev);
1467  		root = api_add_int(root, buf, (int *)(&iFan), true);
1468  
1469  		iFan = 0;
1470  		if (klninfo->status[dev].kline.ws.fanspeed > 0)
1471  			iFan = (unsigned int)TACH_FACTOR / klninfo->status[dev].kline.ws.fanspeed;
1472  		sprintf(buf, "Fan RPM %d", dev);
1473  		root = api_add_int(root, buf, (int *)(&iFan), true);
1474  
1475  		if (klninfo->devinfo[dev].chipstats != NULL) {
1476  			char data[2048];
1477  			char one[32];
1478  			int n;
1479  
1480  			sprintf(buf, "Nonces / Chip %d", dev);
1481  			data[0] = '\0';
1482  			for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) {
1483  				snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n]);
1484  				strcat(data, one);
1485  			}
1486  			root = api_add_string(root, buf, data, true);
1487  
1488  			sprintf(buf, "Errors / Chip %d", dev);
1489  			data[0] = '\0';
1490  			for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) {
1491  				snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n + klninfo->status[dev].kline.ws.chipcount]);
1492  				strcat(data, one);
1493  			}
1494  			root = api_add_string(root, buf, data, true);
1495  		}
1496  	}
1497  
1498  	root = api_add_uint64(root, "Hash Count", &(klninfo->hashcount), true);
1499  	root = api_add_uint64(root, "Error Count", &(klninfo->errorcount), true);
1500  	root = api_add_uint64(root, "Noise Count", &(klninfo->noisecount), true);
1501  
1502  	root = api_add_int(root, "KLine Limit", &(klninfo->kline_count), true);
1503  	root = api_add_int(root, "KLine Used", &(klninfo->used_count), true);
1504  
1505  	root = api_add_elapsed(root, "KQue Delay Count", &(klninfo->delay_count), true);
1506  	root = api_add_elapsed(root, "KQue Delay Total", &(klninfo->delay_total), true);
1507  	root = api_add_elapsed(root, "KQue Delay Min", &(klninfo->delay_min), true);
1508  	root = api_add_elapsed(root, "KQue Delay Max", &(klninfo->delay_max), true);
1509  	double avg;
1510  	if (klninfo->delay_count == 0)
1511  		avg = 0;
1512  	else
1513  		avg = klninfo->delay_total / klninfo->delay_count;
1514  	root = api_add_diff(root, "KQue Delay Avg", &avg, true);
1515  
1516  	root = api_add_elapsed(root, "KQue Nonce Count", &(klninfo->nonce_count), true);
1517  	root = api_add_elapsed(root, "KQue Nonce Total", &(klninfo->nonce_total), true);
1518  	root = api_add_elapsed(root, "KQue Nonce Min", &(klninfo->nonce_min), true);
1519  	root = api_add_elapsed(root, "KQue Nonce Max", &(klninfo->nonce_max), true);
1520  	if (klninfo->nonce_count == 0)
1521  		avg = 0;
1522  	else
1523  		avg = klninfo->nonce_total / klninfo->nonce_count;
1524  	root = api_add_diff(root, "KQue Nonce Avg", &avg, true);
1525  
1526  	root = api_add_int(root, "WQue Size", &(klninfo->wque_size), true);
1527  	root = api_add_int(root, "WQue Cleared", &(klninfo->wque_cleared), true);
1528  
1529  	rd_unlock(&(klninfo->stat_lock));
1530  
1531  	return root;
1532  }
1533  
1534  struct device_drv klondike_drv = {
1535  	.drv_id = DRIVER_klondike,
1536  	.dname = "Klondike",
1537  	.name = "KLN",
1538  	.drv_detect = klondike_detect,
1539  	.get_api_stats = klondike_api_stats,
1540  	.get_statline_before = get_klondike_statline_before,
1541  	.get_stats = klondike_get_stats,
1542  	.identify_device = klondike_identify,
1543  	.thread_prepare = klondike_thread_prepare,
1544  	.thread_init = klondike_thread_init,
1545  	.hash_work = hash_queued_work,
1546  	.scanwork = klondike_scanwork,
1547  	.queue_full = klondike_queue_full,
1548  	.flush_work = klondike_flush_work,
1549  	.thread_shutdown = klondike_shutdown,
1550  	.thread_enable = klondike_thread_enable
1551  };