/ driver-bitfury16.c
driver-bitfury16.c
   1  #include "config.h"
   2  
   3  #include "math.h"
   4  #include "miner.h"
   5  
   6  #include "bf16-communication.h"
   7  #include "bf16-ctrldevice.h"
   8  #include "bf16-mspcontrol.h"
   9  #include "bf16-spidevice.h"
  10  #include "bf16-uartdevice.h"
  11  #include "driver-bitfury16.h"
  12  
  13  #ifdef FILELOG
  14  #define LOGFILE                 "/var/log/cgminer.log"
  15  #endif
  16  
  17  #define DISABLE_SEND_CMD_ERROR
  18  
  19  #define POWER_WAIT_INTERVAL     100000
  20  #define RENONCE_SEND            5
  21  #define RENONCE_STAGE2_LIMIT    80
  22  #define RENONCE_STAGE3_LIMIT    60
  23  #define RENONCE_QUEUE_LEN       100
  24  
  25  #define RENONCE_COUNT           29
  26  
  27  /* chip nonce queue len */
  28  #define NONCE_CHIP_QUEUE_LEN    7
  29  #define RENONCE_CHIP_QUEUE_LEN  40
  30  
  31  #define WORK_TIMEOUT            2.0
  32  
  33  /* statistics intervals */
  34  #define AVG_TIME_DELTA          5.0
  35  #define AVG_TIME_INTERVAL       5.0
  36  
  37  /* power chain alarm interval */
  38  #define ICHAIN_ALARM_INTERVAL   60
  39  #define U_LOSS                  0.2
  40  
  41  /* power chain reenable timeout */
  42  #define CHAIN_REENABLE_INTERVAL 10
  43  #define CHAIN_WORK_INTERVAL     1200
  44  
  45  /* disable chip if no good nonces received during CHIP_FAILING_INTERVAL */
  46  #define RENONCE_CHIP_FAILING_INTERVAL   15.0
  47  #define CHIP_FAILING_INTERVAL           30.0
  48  #define CHIP_RECOVERY_INTERVAL          5.0
  49  
  50  /* chip is considered to be failed after CHIP_ERROR_FAIL_LIMIT recovery attempts */
  51  #define CHIP_ERROR_FAIL_LIMIT           10
  52  /* this value should be less than CHIP_ERROR_FAIL_LIMIT */
  53  #define RENONCE_CHIP_ERROR_FAIL_LIMIT   8
  54  #define CHIP_ERROR_LIMIT                5
  55  
  56  #define CHIP_TASK_STATUS_INTERVAL       7000
  57  #define CHIP_TASK_SWITCH_INTERVAL       5000000
  58  
  59  #define CHIP_RESTART_LIMIT              120
  60  
  61  /* alarm intervals */
  62  #define LED_GREEN_INTERVAL      1000000
  63  #define LED_RED_INTERVAL        1000000
  64  #define LED_RED_NET_INTERVAL    500000
  65  #define BUZZER_INTERVAL         1000000
  66  
  67  /* threads delay */
  68  #define CHIPWORKER_DELAY        1000000
  69  #define NONCEWORKER_DELAY       30000
  70  #define RENONCEWORKER_DELAY     30000
  71  #define HWMONITOR_DELAY         1000000
  72  #define STATISTICS_DELAY        400000
  73  #define ALARM_DELAY             500000
  74  
  75  /* hold 3 works for each chip */
  76  #define WORK_QUEUE_LEN          3 * CHIPS_NUM
  77  
  78  /* set clock to all chips and exit */
  79  bool opt_bf16_set_clock                 = false;
  80  
  81  /* enable board mining statistics output */
  82  bool opt_bf16_stats_enabled             = false;
  83  
  84  /* disable automatic power management */
  85  bool opt_bf16_power_management_disabled = false;
  86  
  87  /* renonce configuration */
  88  int opt_bf16_renonce                    = RENONCE_ONE_CHIP;
  89  
  90  /* chip clock value */
  91  char* opt_bf16_clock    = NULL;
  92  uint8_t bf16_chip_clock = 0x32;
  93  
  94  /* renonce chip clock value */
  95  char* opt_bf16_renonce_clock    = NULL;
  96  uint8_t bf16_renonce_chip_clock = 0x2d;
  97  
  98  /* fan speed */
  99  int opt_bf16_fan_speed = -1;
 100  
 101  /* target temp */
 102  int opt_bf16_target_temp = -1;
 103  
 104  /* alarm temp */
 105  int opt_bf16_alarm_temp = -1;
 106  
 107  /* test chip communication */
 108  char* opt_bf16_test_chip = NULL;
 109  
 110  /* number of bits to fixate */
 111  static uint32_t mask_bits = 10;
 112  
 113  /* default chip mask */
 114  static uint32_t mask = 0x00000000;
 115  
 116  /* initial pid state */
 117  static bf_pid_t pid = {
 118  	.i_state = 0,
 119  	.i_max   = 300,
 120  	.i_min   = -10,
 121  };
 122  
 123  #ifdef MINER_X5
 124  bool opt_bf16_manual_pid_enabled = false;
 125  bool manual_pid_enabled          = false;
 126  
 127  static bf_bcm250_map_t bcm250_map[CHIPBOARD_NUM][BCM250_NUM] = {
 128  	{
 129  		{
 130  			.channel_path    = { BF250_LOCAL, BF250_NONE },
 131  			.first_good_chip = 0,
 132  			.last_good_chip  = BF16_NUM,
 133  			.chips_num       = BF16_NUM
 134  		},
 135  		{
 136  			.channel_path    = { BF250_CHAN1, BF250_LOCAL },
 137  			.first_good_chip = 7,
 138  			.last_good_chip  = BF16_NUM,
 139  			.chips_num       = 4
 140  		},
 141  		{
 142  			.channel_path    = { BF250_CHAN2, BF250_LOCAL },
 143  			.first_good_chip = 0,
 144  			.last_good_chip  = BF16_NUM,
 145  			.chips_num       = BF16_NUM
 146  		}
 147  	},
 148  	{
 149  		{
 150  			.channel_path    = { BF250_LOCAL, BF250_NONE },
 151  			.first_good_chip = 0,
 152  			.last_good_chip  = BF16_NUM,
 153  			.chips_num       = BF16_NUM
 154  		},
 155  		{
 156  			.channel_path    = { BF250_CHAN1, BF250_LOCAL },
 157  			.first_good_chip = 7,
 158  			.last_good_chip  = BF16_NUM,
 159  			.chips_num       = 4
 160  		},
 161  		{
 162  			.channel_path    = { BF250_CHAN2, BF250_LOCAL },
 163  			.first_good_chip = 0,
 164  			.last_good_chip  = BF16_NUM,
 165  			.chips_num       = BF16_NUM
 166  		}
 167  	}
 168  };
 169  #endif
 170  
 171  #ifdef MINER_X6
 172  bool opt_bf16_manual_pid_disabled = false;
 173  bool manual_pid_enabled           = false;
 174  
 175  static bf_bcm250_map_t bcm250_map[CHIPBOARD_NUM][BCM250_NUM] = {
 176  	{
 177  		{
 178  			.channel_path    = { BF250_LOCAL, BF250_NONE, BF250_NONE, BF250_NONE },
 179  			.first_good_chip = 0,
 180  			.last_good_chip  = BF16_NUM,
 181  			.chips_num       = BF16_NUM
 182  		},
 183  		{
 184  			.channel_path    = { BF250_CHAN1, BF250_LOCAL, BF250_NONE, BF250_NONE },
 185  			.first_good_chip = 0,
 186  			.last_good_chip  = BF16_NUM,
 187  			.chips_num       = BF16_NUM
 188  		},
 189  		{
 190  			.channel_path    = { BF250_CHAN2, BF250_LOCAL, BF250_NONE, BF250_NONE },
 191  			.first_good_chip = 0,
 192  			.last_good_chip  = 4,
 193  			.chips_num       = 4
 194  		},
 195  		{
 196  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_LOCAL, BF250_NONE },
 197  			.first_good_chip = 0,
 198  			.last_good_chip  = BF16_NUM,
 199  			.chips_num       = BF16_NUM
 200  		},
 201  		{
 202  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_CHAN1, BF250_LOCAL },
 203  			.first_good_chip = 0,
 204  			.last_good_chip  = BF16_NUM,
 205  			.chips_num       = BF16_NUM
 206  		},
 207  		{
 208  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_CHAN2, BF250_LOCAL },
 209  			.first_good_chip = 0,
 210  			.last_good_chip  = 4,
 211  			.chips_num       = 4
 212  		}
 213  	},
 214  	{
 215  		{
 216  			.channel_path    = { BF250_LOCAL, BF250_NONE, BF250_NONE, BF250_NONE },
 217  			.first_good_chip = 0,
 218  			.last_good_chip  = BF16_NUM,
 219  			.chips_num       = BF16_NUM
 220  		},
 221  		{
 222  			.channel_path    = { BF250_CHAN1, BF250_LOCAL, BF250_NONE, BF250_NONE },
 223  			.first_good_chip = 0,
 224  			.last_good_chip  = BF16_NUM,
 225  			.chips_num       = BF16_NUM
 226  		},
 227  		{
 228  			.channel_path    = { BF250_CHAN2, BF250_LOCAL, BF250_NONE, BF250_NONE },
 229  			.first_good_chip = 0,
 230  			.last_good_chip  = 4,
 231  			.chips_num       = 4
 232  		},
 233  		{
 234  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_LOCAL, BF250_NONE },
 235  			.first_good_chip = 0,
 236  			.last_good_chip  = BF16_NUM,
 237  			.chips_num       = BF16_NUM
 238  		},
 239  		{
 240  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_CHAN1, BF250_LOCAL },
 241  			.first_good_chip = 0,
 242  			.last_good_chip  = BF16_NUM,
 243  			.chips_num       = BF16_NUM
 244  		},
 245  		{
 246  			.channel_path    = { BF250_CHAN2, BF250_CHAN2, BF250_CHAN2, BF250_LOCAL },
 247  			.first_good_chip = 0,
 248  			.last_good_chip  = 4,
 249  			.chips_num       = 4
 250  		}
 251  	}
 252  };
 253  #endif
 254  
 255  /* each array element contains chip address assosiated to corresponting chipboard *
 256   * e.g. first array element - renonce chip address for the first chipboard and so *
 257   * on */
 258  static bf_chip_address_t renonce_chip_address[CHIPBOARD_NUM] = {
 259  	{
 260  		.board_id  = 0,
 261  		.bcm250_id = 0,
 262  		.chip_id   = 0
 263  	},
 264  	{
 265  		.board_id  = 1,
 266  		.bcm250_id = 0,
 267  		.chip_id   = 0
 268  	}
 269  };
 270  
 271  #ifdef FILELOG
 272  static int filelog(struct bitfury16_info *info, const char* format, ...)
 273  {
 274  	char fmt[1024];
 275  	char datetime[64];
 276  	struct timeval tv = {0, 0};
 277  	struct tm *tm;
 278  
 279  	if (info->logfile == NULL)
 280  		return -1;
 281  
 282  	gettimeofday(&tv, NULL);
 283  
 284  	const time_t tmp_time = tv.tv_sec;
 285  	int ms = (int)(tv.tv_usec / 1000);
 286  	tm = localtime(&tmp_time);
 287  
 288  	snprintf(datetime, sizeof(datetime), " [%d-%02d-%02d %02d:%02d:%02d.%03d] ",
 289  		tm->tm_year + 1900,
 290  		tm->tm_mon + 1,
 291  		tm->tm_mday,
 292  		tm->tm_hour,
 293  		tm->tm_min,
 294  		tm->tm_sec, ms);
 295  
 296  	memset(fmt, 0, sizeof(fmt));
 297  	sprintf(fmt, "%s%s\n", datetime, format);
 298  
 299  	va_list args;
 300  	va_start(args, format);
 301  
 302  	mutex_lock(&info->logfile_mutex);
 303  	vfprintf(info->logfile, fmt, args);
 304  	fflush(info->logfile);
 305  	mutex_unlock(&info->logfile_mutex);
 306  
 307  	va_end(args);
 308  
 309  	return 0;
 310  }
 311  #endif
 312  
 313  static double timediff(struct timeval time1, struct timeval time2)
 314  {
 315  	double time1_val = 1000000 * time1.tv_sec + time1.tv_usec;
 316  	double time2_val = 1000000 * time2.tv_sec + time2.tv_usec;
 317  
 318  	return (double)(time2_val - time1_val) / 1000000.0;
 319  }
 320  
 321  static uint32_t timediff_us(struct timeval time1, struct timeval time2)
 322  {
 323  	uint32_t time1_val = 1000000 * time1.tv_sec + time1.tv_usec;
 324  	uint32_t time2_val = 1000000 * time2.tv_sec + time2.tv_usec;
 325  
 326  	return (time2_val - time1_val);
 327  }
 328  
 329  static void get_average(float* average, float delta, float time_diff, float interval)
 330  {
 331  	float ftotal, fprop;
 332  
 333  	fprop = 1.0 - 1 / (exp((float)time_diff/(float)interval));
 334  	ftotal = 1.0 + fprop;
 335  	*average += (delta / time_diff * fprop);
 336  	*average /= ftotal;
 337  }
 338  
 339  static uint8_t renonce_chip(bf_chip_address_t chip_address)
 340  {
 341  	uint8_t board_id = chip_address.board_id;
 342  
 343  	if ((renonce_chip_address[board_id].bcm250_id == chip_address.bcm250_id) &&
 344  	    (renonce_chip_address[board_id].chip_id   == chip_address.chip_id))
 345  		return 1;
 346  
 347  	return 0;
 348  }
 349  
 350  static void get_next_chip_address(struct bitfury16_info *info, bf_chip_address_t* chip_address)
 351  {
 352  	uint8_t board_id  = chip_address->board_id;
 353  	uint8_t bcm250_id = chip_address->bcm250_id;
 354  	uint8_t chip_id   = chip_address->chip_id;
 355  
 356  	uint8_t last_good_chip = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip - 1;
 357  	if (last_good_chip == chip_id) {
 358  #ifdef MINER_X5
 359  		bcm250_id = (bcm250_id + 1) % BCM250_NUM;
 360  		chip_id = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
 361  #endif
 362  
 363  #ifdef MINER_X6
 364  		if (opt_bf16_power_management_disabled == false) {
 365  			bcm250_id = (bcm250_id + 1) % BCM250_NUM;
 366  
 367  			/* do not set bcm250_id to disabled chain */
 368  			/* second power chain disabled */
 369  			if ((info->chipboard[board_id].p_chain2_enabled == 0) &&
 370  				(info->chipboard[board_id].power2_disabled == true) &&
 371  				(bcm250_id >= BCM250_NUM / 2) && (bcm250_id < BCM250_NUM)) {
 372  				bcm250_id = 0;
 373  			}
 374  
 375  			chip_id = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
 376  		} else {
 377  			chip_id = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
 378  		}
 379  #endif
 380  	} else
 381  		chip_id++;
 382  
 383  	chip_address->bcm250_id = bcm250_id;
 384  	chip_address->chip_id   = chip_id;
 385  }
 386  
 387  static int8_t change_renonce_chip_address(struct cgpu_info *bitfury, bf_chip_address_t chip_address)
 388  {
 389  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
 390  
 391  	uint8_t board_id  = chip_address.board_id;
 392  	uint8_t bcm250_id = chip_address.bcm250_id;
 393  	uint8_t chip_id   = chip_address.chip_id;
 394  
 395  	bf_chip_address_t new_chip_address = { board_id, bcm250_id, chip_id };
 396  
 397  	bool found = false;
 398  	uint8_t chip_count = 0;
 399  	while (true) {
 400  		get_next_chip_address(info, &new_chip_address);
 401  		chip_count++;
 402  
 403  		uint8_t new_board_id  = new_chip_address.board_id;
 404  		uint8_t new_bcm250_id = new_chip_address.bcm250_id;
 405  		uint8_t new_chip_id   = new_chip_address.chip_id;
 406  
 407  		/* enabled chip found */
 408  		if (info->chipboard[new_board_id].bcm250[new_bcm250_id].chips[new_chip_id].status != DISABLED) {
 409  			found = true;
 410  			break;
 411  		}
 412  
 413  		/* we have run full loop chipboard */
 414  #ifdef MINER_X5
 415  		if (chip_count == info->chipboard[board_id].chips_num)
 416  			break;
 417  #endif
 418  
 419  #ifdef MINER_X6
 420  		if (opt_bf16_power_management_disabled == false) {
 421  			if ((info->chipboard[board_id].p_chain2_enabled == 0) &&
 422  				(info->chipboard[board_id].power2_disabled == true)) {
 423  				if (chip_count == info->chipboard[board_id].chips_num / 2)
 424  					break;
 425  			} else {
 426  				if (chip_count == info->chipboard[board_id].chips_num)
 427  					break;
 428  			}
 429  		} else {
 430  			if (chip_count == info->chipboard[board_id].chips_num)
 431  				break;
 432  		}
 433  #endif
 434  	}
 435  
 436  	if ((found == true) &&
 437  		(memcmp(&new_chip_address, &renonce_chip_address[board_id], sizeof(bf_chip_address_t)) != 0)) {
 438  		board_id  = new_chip_address.board_id;
 439  		bcm250_id = new_chip_address.bcm250_id;
 440  		chip_id   = new_chip_address.chip_id;
 441  
 442  		renonce_chip_address[board_id].bcm250_id = bcm250_id;
 443  		renonce_chip_address[board_id].chip_id   = chip_id;
 444  
 445  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
 446  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
 447  		gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
 448  
 449  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count = 0;
 450  
 451  		applog(LOG_NOTICE, "%s: changed renonce chip address to: [%d:%d:%2d]",
 452  				bitfury->drv->name,
 453  				board_id, bcm250_id, chip_id);
 454  
 455  #ifdef FILELOG
 456  		filelog(info, "%s: changed renonce chip address to: [%d:%d:%2d]",
 457  				bitfury->drv->name,
 458  				board_id, bcm250_id, chip_id);
 459  #endif
 460  
 461  		return 0;
 462  	} else {
 463  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = DISABLED;
 464  
 465  		applog(LOG_NOTICE, "%s: failed to find working renonce chip. disabling...",
 466  				bitfury->drv->name);
 467  
 468  #ifdef FILELOG
 469  		filelog(info, "%s: failed to find working renonce chip. disabling...",
 470  				bitfury->drv->name);
 471  #endif
 472  
 473  		return -1;
 474  	}
 475  }
 476  
 477  static void increase_good_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 478  {
 479  	uint8_t board_id  = chip_address.board_id;
 480  	uint8_t bcm250_id = chip_address.bcm250_id;
 481  	uint8_t chip_id   = chip_address.chip_id;
 482  
 483  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_good_dx++;
 484  	info->chipboard[board_id].bcm250[bcm250_id].nonces_good_dx++;
 485  	info->chipboard[board_id].nonces_good_dx++;
 486  	info->nonces_good_dx++;
 487  }
 488  
 489  static void increase_bad_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 490  {
 491  	uint8_t board_id  = chip_address.board_id;
 492  	uint8_t bcm250_id = chip_address.bcm250_id;
 493  	uint8_t chip_id   = chip_address.chip_id;
 494  
 495  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_bad_dx++;
 496  	info->chipboard[board_id].bcm250[bcm250_id].nonces_bad_dx++;
 497  	info->chipboard[board_id].nonces_bad_dx++;
 498  	info->nonces_bad_dx++;
 499  }
 500  
 501  static void increase_re_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 502  {
 503  	uint8_t board_id  = chip_address.board_id;
 504  	uint8_t bcm250_id = chip_address.bcm250_id;
 505  	uint8_t chip_id   = chip_address.chip_id;
 506  
 507  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_dx++;
 508  	info->chipboard[board_id].bcm250[bcm250_id].nonces_re_dx++;
 509  	info->chipboard[board_id].nonces_re_dx++;
 510  	info->nonces_re_dx++;
 511  }
 512  
 513  static void increase_re_good_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 514  {
 515  	uint8_t board_id  = chip_address.board_id;
 516  	uint8_t bcm250_id = chip_address.bcm250_id;
 517  	uint8_t chip_id   = chip_address.chip_id;
 518  
 519  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_good_dx++;
 520  
 521  	if (renonce_chip(chip_address) == 0) {
 522  		info->chipboard[board_id].bcm250[bcm250_id].nonces_re_good_dx++;
 523  		info->chipboard[board_id].nonces_re_good_dx++;
 524  		info->nonces_re_good_dx++;
 525  	}
 526  }
 527  
 528  static void increase_re_bad_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 529  {
 530  	uint8_t board_id  = chip_address.board_id;
 531  	uint8_t bcm250_id = chip_address.bcm250_id;
 532  	uint8_t chip_id   = chip_address.chip_id;
 533  
 534  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_bad_dx++;
 535  
 536  	if (renonce_chip(chip_address) == 0) {
 537  		info->chipboard[board_id].bcm250[bcm250_id].nonces_re_bad_dx++;
 538  		info->chipboard[board_id].nonces_re_bad_dx++;
 539  		info->nonces_re_bad_dx++;
 540  	}
 541  }
 542  
 543  static void increase_total_nonces(struct bitfury16_info *info, bf_chip_address_t chip_address)
 544  {
 545  	uint8_t board_id  = chip_address.board_id;
 546  	uint8_t bcm250_id = chip_address.bcm250_id;
 547  	uint8_t chip_id   = chip_address.chip_id;
 548  
 549  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_dx++;
 550  
 551  	if ((renonce_chip(chip_address) == 0) ||
 552  		(opt_bf16_renonce == RENONCE_DISABLED)) {
 553  		info->chipboard[board_id].bcm250[bcm250_id].nonces_dx++;
 554  		info->chipboard[board_id].nonces_dx++;
 555  		info->nonces_dx++;
 556  	}
 557  }
 558  
 559  static void increase_task_switch(struct bitfury16_info *info, bf_chip_address_t chip_address)
 560  {
 561  	uint8_t board_id  = chip_address.board_id;
 562  	uint8_t bcm250_id = chip_address.bcm250_id;
 563  	uint8_t chip_id   = chip_address.chip_id;
 564  
 565  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch_dx++;
 566  	info->chipboard[board_id].bcm250[bcm250_id].task_switch_dx++;
 567  	info->chipboard[board_id].task_switch_dx++;
 568  	info->task_switch_dx++;
 569  }
 570  
 571  static void increase_errors(struct bitfury16_info *info, bf_chip_address_t chip_address)
 572  {
 573  	uint8_t board_id  = chip_address.board_id;
 574  	uint8_t bcm250_id = chip_address.bcm250_id;
 575  	uint8_t chip_id   = chip_address.chip_id;
 576  
 577  	/* update timing interval */
 578  	time_t curr_time = time(NULL);
 579  	if (curr_time - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time <= 1)
 580  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate++;
 581  	else
 582  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate = 0;
 583  
 584  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
 585  
 586  	info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors++;
 587  
 588  	if ((renonce_chip(chip_address) == 0) ||
 589  	    (opt_bf16_renonce == RENONCE_DISABLED))
 590  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = UNINITIALIZED;
 591  
 592  	/* mark chip as FAILING if error rate too high*/
 593  	if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate >= CHIP_ERROR_LIMIT) {
 594  #ifdef FILELOG
 595  		filelog(info, "BF16: chip [%d:%d:%2d] error rate too high: [%d], "
 596  				"marked as failing, recovery_count: [%d]",
 597  				board_id, bcm250_id, chip_id,
 598  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate,
 599  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count);
 600  #endif
 601  
 602  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = FAILING;
 603  		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate = 0;
 604  	}
 605  }
 606  
 607  static uint8_t* init_channel_path(uint8_t board_id, uint8_t btc250_num, uint8_t* channel_depth, uint8_t channel_length)
 608  {
 609  	uint8_t i, j;
 610  	uint8_t* channel_path = cgcalloc(channel_length, sizeof(uint8_t));
 611  
 612  	for (i = 0, j = 0; i < CHANNEL_DEPTH; i++) {
 613  		if (bcm250_map[board_id][btc250_num].channel_path[i] != BF250_NONE)
 614  			(*channel_depth)++;
 615  
 616  		int8_t shift = 8*(j + 1) - 3*(i + 1);
 617  		if (shift < 0) {
 618  			channel_path[j]     |= bcm250_map[board_id][btc250_num].channel_path[i] >> abs(shift);
 619  			channel_path[j + 1] |= bcm250_map[board_id][btc250_num].channel_path[i] << (8 - abs(shift));
 620  			j++;
 621  		} else
 622  			channel_path[j] |= bcm250_map[board_id][btc250_num].channel_path[i] << shift;
 623  	}
 624  
 625  	return channel_path;
 626  }
 627  
 628  static int8_t parse_chip_address(struct cgpu_info *bitfury, char* address, bf_chip_address_t* chip_address)
 629  {
 630  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
 631  
 632  	int8_t board_id  = 0;
 633  	int8_t bcm250_id = 0;
 634  	int8_t chip_id   = 0;
 635  
 636  	char buff[16];
 637  
 638  	if (address == NULL)
 639  		return -1;
 640  
 641  	/* board_id */
 642  	char* start = strchr(address, '[');
 643  	char* end   = strchr(address, ':');
 644  	if ((start == NULL) || (end == NULL))
 645  		return -1;
 646  	uint8_t len = end - start;
 647  
 648  	memset(buff, 0, sizeof(buff));
 649  	cg_memcpy(buff, start + 1, len);
 650  	board_id = atoi(buff);
 651  
 652  	/* bcm250_id */
 653  	start = end;
 654  	end = strchr(start + 1, ':');
 655  	if (end == NULL)
 656  		return -1;
 657  	len = end - start;
 658  
 659  	memset(buff, 0, sizeof(buff));
 660  	cg_memcpy(buff, start + 1, len);
 661  	bcm250_id = atoi(buff);
 662  
 663  	/* chip_id */
 664  	start = end;
 665  	end = strchr(start + 1, ']');
 666  	if (end == NULL)
 667  		return -1;
 668  	len = end - start;
 669  
 670  	memset(buff, 0, sizeof(buff));
 671  	cg_memcpy(buff, start + 1, len);
 672  	chip_id = atoi(buff);
 673  
 674  	if ((board_id < 0) || (board_id >= CHIPBOARD_NUM)) {
 675  		applog(LOG_ERR, "%s: invalid board_id %d: [0 - %d] specified",
 676  				bitfury->drv->name,
 677  				board_id, CHIPBOARD_NUM);
 678  		return -1;
 679  	}
 680  
 681  	if ((bcm250_id < 0) || (bcm250_id >= BCM250_NUM)) {
 682  		applog(LOG_ERR, "%s: invalid bcm250_id %d: [0 - %d] specified",
 683  				bitfury->drv->name,
 684  				bcm250_id, BCM250_NUM);
 685  		return -1;
 686  	}
 687  
 688  
 689  	uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
 690  	uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
 691  
 692  	if ((chip_id >= first_good_chip) && (chip_id < last_good_chip)) {
 693  		chip_address->board_id  = board_id;
 694  		chip_address->bcm250_id = bcm250_id;
 695  		chip_address->chip_id   = chip_id;
 696  	} else {
 697  		applog(LOG_ERR, "%s: invalid chip_id %d: [%d - %d] specified",
 698  				bitfury->drv->name,
 699  				chip_id, first_good_chip, last_good_chip);
 700  		return -1;
 701  	}
 702  
 703  	applog(LOG_NOTICE, "%s: parsed chip address: [%d:%d:%2d]",
 704  			bitfury->drv->name,
 705  			chip_address->board_id,
 706  			chip_address->bcm250_id,
 707  			chip_address->chip_id);
 708  
 709  	return 0;
 710  }
 711  
 712  static void update_bcm250_map(struct cgpu_info *bitfury, uint8_t board_id)
 713  {
 714  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
 715  
 716  #ifdef MINER_X5
 717  	info->chipboard[board_id].board_type = CHIPBOARD_X5;
 718  
 719  	switch (info->chipboard[board_id].board_ver) {
 720  		/* 23 chip board version */
 721  		case 5:
 722  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 723  
 724  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 2;
 725  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 2;
 726  
 727  			bcm250_map[board_id][1].first_good_chip = 6;
 728  			bcm250_map[board_id][1].chips_num       = 5;
 729  
 730  			bcm250_map[board_id][2].last_good_chip  = BF16_NUM - 2;
 731  			bcm250_map[board_id][2].chips_num       = BF16_NUM - 2;
 732  			break;
 733  
 734  		/* 24 chip board version */
 735  		case 7:
 736  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 737  
 738  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 2;
 739  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 2;
 740  
 741  			bcm250_map[board_id][1].first_good_chip = 6;
 742  			bcm250_map[board_id][1].chips_num       = 5;
 743  
 744  			bcm250_map[board_id][2].last_good_chip  = BF16_NUM - 1;
 745  			bcm250_map[board_id][2].chips_num       = BF16_NUM - 1;
 746  			break;
 747  
 748  		/* 25 chip board version */
 749  		case 9:
 750  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 751  
 752  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 1;
 753  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 1;
 754  
 755  			bcm250_map[board_id][1].first_good_chip = 6;
 756  			bcm250_map[board_id][1].chips_num       = 5;
 757  
 758  			bcm250_map[board_id][2].last_good_chip  = BF16_NUM - 1;
 759  			bcm250_map[board_id][2].chips_num       = BF16_NUM - 1;
 760  			break;
 761  
 762  		/* 26 chip board version */
 763  		case 11:
 764  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 765  
 766  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 1;
 767  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 1;
 768  
 769  			bcm250_map[board_id][1].first_good_chip = 6;
 770  			bcm250_map[board_id][1].chips_num       = 5;
 771  			break;
 772  
 773  		/* 27 chip board version */
 774  		case 13:
 775  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 776  
 777  			bcm250_map[board_id][1].first_good_chip = 6;
 778  			bcm250_map[board_id][1].chips_num       = 5;
 779  			break;
 780  
 781  		/* 26 chip board version - default */
 782  		case 1:
 783  		case 2:
 784  			info->chipboard[board_id].board_rev    = CHIPBOARD_REV1;
 785  		default:
 786  			break;
 787  	}
 788  #endif
 789  
 790  #ifdef MINER_X6
 791  	info->chipboard[board_id].board_type = CHIPBOARD_X6;
 792  
 793  	switch (info->chipboard[board_id].board_ver) {
 794  		/* 46 chip board version */
 795  		case 4:
 796  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 797  
 798  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 2;
 799  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 2;
 800  
 801  			bcm250_map[board_id][1].first_good_chip = 1;
 802  			bcm250_map[board_id][1].last_good_chip  = BF16_NUM - 1;
 803  			bcm250_map[board_id][1].chips_num       = BF16_NUM - 2;
 804  
 805  			bcm250_map[board_id][2].last_good_chip  = 5;
 806  			bcm250_map[board_id][2].chips_num       = 5;
 807  
 808  			bcm250_map[board_id][3].last_good_chip  = BF16_NUM - 2;
 809  			bcm250_map[board_id][3].chips_num       = BF16_NUM - 2;
 810  
 811  			bcm250_map[board_id][4].first_good_chip = 1;
 812  			bcm250_map[board_id][4].last_good_chip  = BF16_NUM - 1;
 813  			bcm250_map[board_id][4].chips_num       = BF16_NUM - 1;
 814  
 815  			bcm250_map[board_id][5].last_good_chip  = 5;
 816  			bcm250_map[board_id][5].chips_num       = 5;
 817  			break;
 818  
 819  		/* 48 chip board version */
 820  		case 6:
 821  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 822  
 823  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 1;
 824  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 1;
 825  
 826  			bcm250_map[board_id][1].first_good_chip = 1;
 827  			bcm250_map[board_id][1].last_good_chip  = BF16_NUM - 1;
 828  			bcm250_map[board_id][1].chips_num       = BF16_NUM - 2;
 829  
 830  			bcm250_map[board_id][2].last_good_chip  = 5;
 831  			bcm250_map[board_id][2].chips_num       = 5;
 832  
 833  			bcm250_map[board_id][3].last_good_chip  = BF16_NUM - 1;
 834  			bcm250_map[board_id][3].chips_num       = BF16_NUM - 1;
 835  
 836  			bcm250_map[board_id][4].first_good_chip = 1;
 837  			bcm250_map[board_id][4].last_good_chip  = BF16_NUM - 1;
 838  			bcm250_map[board_id][4].chips_num       = BF16_NUM - 1;
 839  
 840  			bcm250_map[board_id][5].last_good_chip  = 5;
 841  			bcm250_map[board_id][5].chips_num       = 5;
 842  			break;
 843  
 844  		/* 50 chip board version */
 845  		case 8:
 846  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 847  
 848  			bcm250_map[board_id][0].last_good_chip  = BF16_NUM - 1;
 849  			bcm250_map[board_id][0].chips_num       = BF16_NUM - 1;
 850  
 851  			bcm250_map[board_id][1].last_good_chip  = BF16_NUM - 1;
 852  			bcm250_map[board_id][1].chips_num       = BF16_NUM - 1;
 853  
 854  			bcm250_map[board_id][2].last_good_chip  = 5;
 855  			bcm250_map[board_id][2].chips_num       = 5;
 856  
 857  			bcm250_map[board_id][3].last_good_chip  = BF16_NUM - 1;
 858  			bcm250_map[board_id][3].chips_num       = BF16_NUM - 1;
 859  
 860  			bcm250_map[board_id][4].last_good_chip  = BF16_NUM - 1;
 861  			bcm250_map[board_id][4].chips_num       = BF16_NUM - 1;
 862  
 863  			bcm250_map[board_id][5].last_good_chip  = 5;
 864  			bcm250_map[board_id][5].chips_num       = 5;
 865  			break;
 866  
 867  		/* 52 chip board version */
 868  		case 10:
 869  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 870  
 871  			bcm250_map[board_id][1].last_good_chip  = BF16_NUM - 1;
 872  			bcm250_map[board_id][1].chips_num       = BF16_NUM - 1;
 873  
 874  			bcm250_map[board_id][2].last_good_chip  = 5;
 875  			bcm250_map[board_id][2].chips_num       = 5;
 876  
 877  			bcm250_map[board_id][4].last_good_chip  = BF16_NUM - 1;
 878  			bcm250_map[board_id][4].chips_num       = BF16_NUM - 1;
 879  
 880  			bcm250_map[board_id][5].last_good_chip  = 5;
 881  			bcm250_map[board_id][5].chips_num       = 5;
 882  			break;
 883  
 884  		/* 54 chip board version */
 885  		case 12:
 886  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV2;
 887  
 888  			bcm250_map[board_id][2].last_good_chip  = 5;
 889  			bcm250_map[board_id][2].chips_num       = 5;
 890  
 891  			bcm250_map[board_id][5].last_good_chip  = 5;
 892  			bcm250_map[board_id][5].chips_num       = 5;
 893  			break;
 894  
 895  		/* 46 chip board version */
 896  		case 14:;
 897  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV3;
 898  
 899  			uint8_t bcm250_channel_path[3][CHANNEL_DEPTH] = {
 900  				{ BF250_CHAN1, BF250_CHAN1, BF250_LOCAL, BF250_NONE  },
 901  				{ BF250_CHAN1, BF250_CHAN1, BF250_CHAN1, BF250_LOCAL },
 902  				{ BF250_CHAN1, BF250_CHAN1, BF250_CHAN2, BF250_LOCAL },
 903  			};
 904  
 905  			bcm250_map[board_id][0].first_good_chip = 0;
 906  			bcm250_map[board_id][0].last_good_chip  = 1;
 907  			bcm250_map[board_id][0].chips_num       = 1;
 908  
 909  			bcm250_map[board_id][2].first_good_chip = 0;
 910  			bcm250_map[board_id][2].last_good_chip  = BF16_NUM;
 911  			bcm250_map[board_id][2].chips_num       = BF16_NUM;
 912  
 913  			bcm250_map[board_id][3].first_good_chip = 0;
 914  			bcm250_map[board_id][3].last_good_chip  = 1;
 915  			bcm250_map[board_id][3].chips_num       = 1;
 916  			cg_memcpy(bcm250_map[board_id][3].channel_path, bcm250_channel_path[0], sizeof(bcm250_map[board_id][3].channel_path));
 917  
 918  			cg_memcpy(bcm250_map[board_id][4].channel_path, bcm250_channel_path[1], sizeof(bcm250_map[board_id][4].channel_path));
 919  
 920  			bcm250_map[board_id][5].first_good_chip = 0;
 921  			bcm250_map[board_id][5].last_good_chip  = BF16_NUM;
 922  			bcm250_map[board_id][5].chips_num       = BF16_NUM;
 923  			cg_memcpy(bcm250_map[board_id][5].channel_path, bcm250_channel_path[2], sizeof(bcm250_map[board_id][5].channel_path));
 924  			break;
 925  
 926  		/* 52 chip board version - default */
 927  		case 3:
 928  			info->chipboard[board_id].board_rev     = CHIPBOARD_REV1;
 929  		default:
 930  			break;
 931  	}
 932  #endif
 933  }
 934  
 935  static void reinit_x5(struct bitfury16_info *info, bool chip_reinit)
 936  {
 937  	uint8_t board_id, bcm250_id, chip_id;
 938  
 939  	/* reinit board chips */
 940  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
 941  		for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
 942  			uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
 943  			uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
 944  
 945  			for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
 946  				if (chip_reinit == true) {
 947  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count  = 0;
 948  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate      = 0;
 949  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
 950  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
 951  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = time(NULL);
 952  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
 953  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, NULL);
 954  				} else {
 955  					if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count < CHIP_ERROR_FAIL_LIMIT)
 956  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = UNINITIALIZED;
 957  				}
 958  
 959  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
 960  				gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
 961  				gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, NULL);
 962  			}
 963  		}
 964  	}
 965  
 966  	/* send reset to all boards */
 967  	spi_emit_reset(SPI_CHANNEL1);
 968  	spi_emit_reset(SPI_CHANNEL2);
 969  }
 970  
 971  static void init_x5(struct cgpu_info *bitfury)
 972  {
 973  	uint8_t board_id, bcm250_id, chip_id;
 974  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
 975  
 976  	info->chipboard = cgcalloc(CHIPBOARD_NUM, sizeof(bf_chipboard_t));
 977  
 978  	/* channel size in bytes */
 979  	info->channel_length = (CHANNEL_DEPTH * 3) / 8 + 1;
 980  	info->ialarm_count = 1;
 981  
 982  	info->work_list       = workd_list_init();
 983  	info->stale_work_list = workd_list_init();
 984  
 985  	info->noncework_list  = noncework_list_init();
 986  
 987  	if (opt_bf16_renonce != RENONCE_DISABLED) {
 988  		info->renoncework_list  = renoncework_list_init();
 989  		info->renonce_id        = 1;
 990  		info->renonce_list      = renonce_list_init();
 991  	}
 992  
 993  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
 994  		/* detect board */
 995  		char buff[256];
 996  		memset(buff, 0, sizeof(buff));
 997  
 998  		device_ctrl_txrx(board_id + 1, 0, F_BDET, buff);
 999  		parse_board_detect(bitfury, board_id, buff);
1000  
1001  		if (info->chipboard[board_id].detected == true) {
1002  			applog(LOG_NOTICE, "%s: BOARD%d detected", bitfury->drv->name, board_id + 1);
1003  
1004  			info->chipboard[board_id].bcm250 = cgcalloc(BCM250_NUM, sizeof(bf_bcm250_t));
1005  			cmd_buffer_init(&info->chipboard[board_id].cmd_buffer);
1006  
1007  			get_board_info(bitfury, board_id);
1008  			update_bcm250_map(bitfury, board_id);
1009  
1010  			info->chipboard_num++;
1011  			info->chipboard[board_id].bcm250_num = BCM250_NUM;
1012  
1013  			cg_memcpy(&info->chipboard[board_id].pid, &pid, sizeof(bf_pid_t));
1014  
1015  			uint8_t chips_num = 0;
1016  			for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
1017  				info->chipboard[board_id].bcm250[bcm250_id].channel_path    = init_channel_path(board_id, bcm250_id,
1018  						&info->chipboard[board_id].bcm250[bcm250_id].channel_depth, info->channel_length);
1019  				info->chipboard[board_id].bcm250[bcm250_id].first_good_chip = bcm250_map[board_id][bcm250_id].first_good_chip;
1020  				info->chipboard[board_id].bcm250[bcm250_id].last_good_chip  = bcm250_map[board_id][bcm250_id].last_good_chip;
1021  				info->chipboard[board_id].bcm250[bcm250_id].chips_num       = bcm250_map[board_id][bcm250_id].chips_num;
1022  				chips_num += bcm250_map[board_id][bcm250_id].chips_num;
1023  
1024  				uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1025  				uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1026  
1027  				for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
1028  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
1029  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
1030  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonce_list      = nonce_list_init();
1031  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
1032  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, NULL);
1033  				}
1034  			}
1035  
1036  			info->chipboard[board_id].chips_num  = chips_num;
1037  			info->chips_num += info->chipboard[board_id].chips_num;
1038  		} else
1039  			applog(LOG_NOTICE, "%s: BOARD%d not found", bitfury->drv->name, board_id + 1);
1040  
1041  		applog(LOG_INFO, "%s: initialized board X5.%d", bitfury->drv->name, board_id);
1042  	}
1043  
1044  	applog(LOG_INFO, "%s: initialized X5", bitfury->drv->name);
1045  }
1046  
1047  static void deinit_x5(struct cgpu_info *bitfury)
1048  {
1049  	uint8_t board_id, bcm250_id, chip_id;
1050  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1051  
1052  	workd_list_deinit(info->work_list,       bitfury);
1053  	workd_list_deinit(info->stale_work_list, bitfury);
1054  
1055  	noncework_list_deinit(info->noncework_list);
1056  
1057  	if (opt_bf16_renonce != RENONCE_DISABLED) {
1058  		renoncework_list_deinit(info->renoncework_list);
1059  		info->renonce_id = 1;
1060  		renonce_list_deinit(info->renonce_list);
1061  	}
1062  
1063  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1064  		for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
1065  			free(info->chipboard[board_id].bcm250[bcm250_id].channel_path);
1066  
1067  			uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1068  			uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1069  
1070  			for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++)
1071  				nonce_list_deinit(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonce_list);
1072  		}
1073  		free(info->chipboard[board_id].bcm250);
1074  
1075  		cmd_buffer_deinit(&info->chipboard[board_id].cmd_buffer);
1076  	}
1077  
1078  	free(info->chipboard);
1079  }
1080  
1081  static void bitfury16_set_clock(struct cgpu_info *bitfury) 
1082  {
1083  	uint8_t board_id, bcm250_id, chip_id;
1084  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
1085  
1086  	/* send reset to all boards */
1087  	spi_emit_reset(SPI_CHANNEL1);
1088  	spi_emit_reset(SPI_CHANNEL2);
1089  
1090  	/* board loop */
1091  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1092  		applog(LOG_NOTICE, "%s: CHIPBOARD [%d]:", bitfury->drv->name, board_id);
1093  		/* concentrator loop */
1094  		for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
1095  			applog(LOG_NOTICE, "%s: BCM250 [%d]:", bitfury->drv->name, bcm250_id);
1096  
1097  			spi_emit_reset(board_id + 1);
1098  
1099  			/* build channel */
1100  			create_channel(board_id + 1, info->chipboard[board_id].bcm250[bcm250_id].channel_path, info->channel_length);
1101  
1102  			uint8_t channel_depth   = info->chipboard[board_id].bcm250[bcm250_id].channel_depth;
1103  			uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1104  			uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1105  
1106  			uint8_t result;
1107  			bool fail;
1108  			/* chips loop */
1109  			for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
1110  				fail = false;
1111  				bf_chip_address_t chip_address = { board_id, bcm250_id, chip_id };
1112  
1113  				result = send_toggle(board_id + 1, channel_depth, chip_address);
1114  				if (result != 0)
1115  					fail = true;
1116  
1117  				result = set_clock(board_id + 1, channel_depth, chip_address, bf16_chip_clock);
1118  				if ((result != 0) && (fail != true))
1119  					fail = true;
1120  
1121  				if (fail == false)
1122  					applog(LOG_NOTICE, "%s: CHIP [%2d]: OK", bitfury->drv->name, chip_id);
1123  				else
1124  					applog(LOG_NOTICE, "%s: CHIP [%2d]: FAIL", bitfury->drv->name, chip_id);
1125  			}
1126  
1127  			/* destroy channel */
1128  			destroy_channel(board_id + 1, info->chipboard[board_id].bcm250[bcm250_id].channel_depth);
1129  		}
1130  	}
1131  
1132  	deinit_x5(bitfury);
1133  }
1134  
1135  static void bitfury16_test_chip(struct cgpu_info *bitfury, bf_chip_address_t chip_address) 
1136  {
1137  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
1138  
1139  	uint8_t board_id  = chip_address.board_id;
1140  	uint8_t bcm250_id = chip_address.bcm250_id;
1141  	uint8_t chip_id   = chip_address.chip_id;
1142  
1143  	/* send reset to board */
1144  	spi_emit_reset(board_id + 1);
1145  
1146  	/* build channel */
1147  	create_channel(board_id + 1, info->chipboard[board_id].bcm250[bcm250_id].channel_path, info->channel_length);
1148  
1149  	uint8_t channel_depth   = info->chipboard[board_id].bcm250[bcm250_id].channel_depth;
1150  
1151  	uint8_t result;
1152  	bool fail = false;
1153  
1154  	result = send_toggle(board_id + 1, channel_depth, chip_address);
1155  	if (result != 0)
1156  		fail = true;
1157  
1158  	result = set_clock(board_id + 1, channel_depth, chip_address, bf16_chip_clock);
1159  	if ((result != 0) && (fail != true))
1160  		fail = true;
1161  
1162  	if (fail == false)
1163  		applog(LOG_NOTICE, "%s: CHIP [%2d]: OK", bitfury->drv->name, chip_id);
1164  	else
1165  		applog(LOG_NOTICE, "%s: CHIP [%2d]: FAIL", bitfury->drv->name, chip_id);
1166  
1167  	/* destroy channel */
1168  	destroy_channel(board_id + 1, info->chipboard[board_id].bcm250[bcm250_id].channel_depth);
1169  
1170  	deinit_x5(bitfury);
1171  }
1172  
1173  static void bitfury16_identify(__maybe_unused struct cgpu_info *bitfury)
1174  {
1175  }
1176  
1177  static void set_fan_speed(struct cgpu_info *bitfury)
1178  {
1179  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
1180  	uint8_t board_id;
1181  
1182  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1183  		if (info->chipboard[board_id].detected == true) {
1184  			if (opt_bf16_fan_speed == -1) {
1185  				if (device_uart_transfer(board_id + 1, "F") < 0)
1186  					quit(1, "%s: %s() failed to set BOARD%d fan speed",
1187  							bitfury->drv->name, __func__, board_id + 1);
1188  
1189  				applog(LOG_INFO, "%s: set BOARD%d fan speed to auto mode",
1190  						bitfury->drv->name, board_id + 1);
1191  			} else {
1192  				char uart_cmd[8];
1193  				sprintf(uart_cmd, "F:%d", opt_bf16_fan_speed);
1194  
1195  				if (device_uart_transfer(board_id + 1, uart_cmd) < 0)
1196  					quit(1, "%s: %s() failed to set BOARD%d fan speed",
1197  							bitfury->drv->name, __func__, board_id + 1);
1198  
1199  				applog(LOG_INFO, "%s: set BOARD%d fan speed to [%d]",
1200  						bitfury->drv->name, board_id + 1, opt_bf16_fan_speed);
1201  			}
1202  		}
1203  	}
1204  }
1205  
1206  static void bitfury16_detect(bool hotplug)
1207  {
1208  	struct cgpu_info *bitfury = NULL;
1209  	struct bitfury16_info *info = NULL;
1210  	uint8_t board_id, bcm250_id, chip_id;
1211  
1212  	if (hotplug)
1213  		return;
1214  
1215  	bitfury = cgmalloc(sizeof(struct cgpu_info));
1216  	if (unlikely(!bitfury))
1217  		quit(1, "%s: %s() failed to malloc bitfury",
1218  				bitfury->drv->name, __func__);
1219  
1220  	bitfury->drv = &bitfury16_drv;
1221  	bitfury->deven = DEV_ENABLED;
1222  	bitfury->threads = 1;
1223  
1224  	info = cgmalloc(sizeof(struct bitfury16_info));
1225  	if (unlikely(!info))
1226  		quit(1, "%s: %s() failed to malloc info",
1227  				bitfury->drv->name, __func__);
1228  
1229  	bitfury->device_data = info;
1230  
1231  	/* manual PID option */
1232  #ifdef MINER_X5
1233  	manual_pid_enabled = opt_bf16_manual_pid_enabled;
1234  #endif
1235  
1236  #ifdef MINER_X6
1237  	manual_pid_enabled = !opt_bf16_manual_pid_disabled;
1238  #endif
1239  
1240  	/* renonce chip address and renonce chip clock */
1241  	if (opt_bf16_renonce != RENONCE_DISABLED) {
1242  		if (opt_bf16_renonce_clock != NULL)
1243  			bf16_renonce_chip_clock = strtol(opt_bf16_renonce_clock, NULL, 16);
1244  	} else
1245  		/* default chip clock if renonce is disabled */
1246  		bf16_chip_clock = 0x2d;
1247  
1248  	/* general chip clock */
1249  	if (opt_bf16_clock != NULL)
1250  		bf16_chip_clock = strtol(opt_bf16_clock, NULL, 16);
1251  	else if ((opt_bf16_set_clock == true) || (opt_bf16_test_chip != NULL))
1252  		/* default chip clock if set_clock option is set */
1253  		bf16_chip_clock = 0x20;
1254  
1255  	/* open devices */
1256  	if (open_spi_device(SPI_CHANNEL1) < 0)
1257  		quit(1, "%s: %s() failed to open [%s] device",
1258  				bitfury->drv->name, __func__, spi0_device_name);
1259  
1260  	applog(LOG_INFO, "%s: opened [%s] device", bitfury->drv->name, spi0_device_name);
1261  
1262  	if (open_spi_device(SPI_CHANNEL2) < 0)
1263  		quit(1, "%s: %s() failed to open [%s] device",
1264  				bitfury->drv->name, __func__, spi1_device_name);
1265  
1266  	applog(LOG_INFO, "%s: opened [%s] device", bitfury->drv->name, spi1_device_name);
1267  
1268  	if (open_ctrl_device() < 0)
1269  		quit(1, "%s: %s() failed to open [%s] device",
1270  				bitfury->drv->name, __func__, ctrl_device_name);
1271  
1272  	applog(LOG_INFO, "%s: opened [%s] device", bitfury->drv->name, ctrl_device_name);
1273  
1274  	if (open_uart_device(UART_CHANNEL1) < 0)
1275  		quit(1, "%s: %s() failed to open [%s] device",
1276  				bitfury->drv->name, __func__, uart1_device_name);
1277  
1278  	applog(LOG_INFO, "%s: opened [%s] device", bitfury->drv->name, uart1_device_name);
1279  
1280  	if (open_uart_device(UART_CHANNEL2) < 0)
1281  		quit(1, "%s: %s() failed to open [%s] device",
1282  				bitfury->drv->name, __func__, uart2_device_name);
1283  
1284  	applog(LOG_INFO, "%s: opened [%s] device", bitfury->drv->name, uart2_device_name);
1285  
1286  	init_x5(bitfury);
1287  
1288  	/* send reset to boards */
1289  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1290  		if (info->chipboard[board_id].detected == true) {
1291  			device_ctrl_transfer(board_id + 1, 1, F_BRST);
1292  			cgsleep_us(POWER_WAIT_INTERVAL);
1293  			device_ctrl_transfer(board_id + 1, 0, F_BRST);
1294  			cgsleep_us(POWER_WAIT_INTERVAL);
1295  
1296  			applog(LOG_INFO, "%s: sent reset to BOARD%d",
1297  					bitfury->drv->name, board_id + 1);
1298  		}
1299  	}
1300  
1301  	/* check if board power is present */
1302  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1303  		/* read hw sensor data */
1304  		char buff[256];
1305  
1306  		if (info->chipboard[board_id].detected == true) {
1307  			memset(buff, 0, sizeof(buff));
1308  			if (device_uart_txrx(board_id + 1, "S", buff) < 0)
1309  				quit(1, "%s: %s() failed to get BOARD%d status",
1310  					bitfury->drv->name, __func__, board_id + 1);
1311  
1312  			if (parse_hwstats(info, board_id, buff) < 0)
1313  				applog(LOG_ERR, "%s: failed to parse hw stats",
1314  						bitfury->drv->name);
1315  
1316  			/* disable board if power voltage is incorrect */
1317  			if ((info->chipboard[board_id].u_board < 10.0) ||
1318  			    (info->chipboard[board_id].u_board > 15.0)) {
1319  
1320  				/* concentrator loop */
1321  				for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
1322  					uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1323  					uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1324  
1325  					/* chips loop */
1326  					for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++)
1327  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = DISABLED;
1328  				}
1329  	
1330  				applog(LOG_ERR, "%s: incorrect U board detected [%.1f] on BOARD%d, "
1331  						"disabling board...",
1332  						bitfury->drv->name,
1333  						info->chipboard[board_id].u_board,
1334  						board_id + 1);
1335  			} else {
1336  				info->chipboard[board_id].active = true;
1337  				info->active_chipboard_num++;
1338  			}
1339  		}
1340  	}
1341  
1342  	/* enable power chain */
1343  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1344  		if (enable_power_chain(bitfury, board_id, 0) < 0)
1345  			info->chipboard[board_id].detected = false;
1346  		else {
1347  #ifdef MINER_X5
1348  			info->chipboard[board_id].power_enable_time   = time(NULL);
1349  			info->chipboard[board_id].power_disable_count = 1;
1350  #endif
1351  
1352  #ifdef MINER_X6
1353  			info->chipboard[board_id].power1_enable_time   = time(NULL);
1354  			info->chipboard[board_id].power2_enable_time   = time(NULL);
1355  			info->chipboard[board_id].power1_disable_count = 1;
1356  			info->chipboard[board_id].power2_disable_count = 1;
1357  #endif
1358  		}
1359  	}
1360  
1361  	/* wait for power chain to enable */
1362  	cgsleep_us(POWER_WAIT_INTERVAL);
1363  
1364  	if (opt_bf16_set_clock == true) {
1365  		applog(LOG_INFO, "%s: setting clock [%02x] to all chips",
1366  				bitfury->drv->name, bf16_chip_clock);
1367  
1368  		bitfury16_set_clock(bitfury);
1369  
1370  		quit(0, "Done.");
1371  	}
1372  
1373  	if (opt_bf16_test_chip != NULL) {
1374  		bf_chip_address_t chip_address = { 0, 0, 0 };
1375  
1376  		if (parse_chip_address(bitfury, opt_bf16_test_chip, &chip_address) < 0) {
1377  			quit(1, "%s: %s() error parsing chip address...",
1378  					bitfury->drv->name, __func__);
1379  		}
1380  
1381  		applog(LOG_INFO, "%s: testing communicaton with chip [%d:%d:%2d]",
1382  				bitfury->drv->name,
1383  				chip_address.board_id,
1384  				chip_address.bcm250_id,
1385  				chip_address.chip_id);
1386  
1387  		bitfury16_test_chip(bitfury, chip_address);
1388  
1389  		quit(0, "Done.");
1390  	}
1391  
1392  	/* fan speed */
1393  	if ((opt_bf16_fan_speed != -1) &&
1394  	    (manual_pid_enabled == true)) {
1395  		manual_pid_enabled = false;
1396  	}
1397  
1398  	set_fan_speed(bitfury);
1399  
1400  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1401  		if (info->chipboard[board_id].detected == true) {
1402  			/* target temp */
1403  			if (opt_bf16_target_temp == -1) {
1404  				if (device_uart_transfer(board_id + 1, "T") < 0)
1405  					quit(1, "%s: %s() failed to set BOARD%d target temp",
1406  							bitfury->drv->name, __func__, board_id + 1);
1407  
1408  				applog(LOG_INFO, "%s: set BOARD%d target temp to default value",
1409  						bitfury->drv->name, board_id + 1);
1410  			} else {
1411  				char uart_cmd[8];
1412  				sprintf(uart_cmd, "T:%d", opt_bf16_target_temp);
1413  
1414  				if (device_uart_transfer(board_id + 1, uart_cmd) < 0)
1415  					quit(1, "%s: %s() failed to set BOARD%d target temp",
1416  							bitfury->drv->name, __func__, board_id + 1);
1417  
1418  				applog(LOG_INFO, "%s: set BOARD%d target temp to [%d]",
1419  						bitfury->drv->name, board_id + 1, opt_bf16_target_temp);
1420  			}
1421  
1422  			/* alarm temp */
1423  			if (opt_bf16_alarm_temp == -1) {
1424  				if (device_uart_transfer(board_id + 1, "C") < 0)
1425  					quit(1, "%s: %s() failed to set BOARD%d alarm temp",
1426  							bitfury->drv->name, __func__, board_id + 1);
1427  
1428  				applog(LOG_INFO, "%s: set BOARD%d alarm temp to default value",
1429  						bitfury->drv->name, board_id + 1);
1430  			} else {
1431  				char uart_cmd[8];
1432  				sprintf(uart_cmd, "C:%d", opt_bf16_alarm_temp);
1433  
1434  				if (device_uart_transfer(board_id + 1, uart_cmd) < 0)
1435  					quit(1, "%s: %s() failed to set BOARD%d alarm temp",
1436  							bitfury->drv->name, __func__, board_id + 1);
1437  
1438  				applog(LOG_INFO, "%s: set BOARD%d alarm temp to [%d]",
1439  						bitfury->drv->name, board_id + 1, opt_bf16_alarm_temp);
1440  			}
1441  		}
1442  	}
1443  
1444  	/* count number of renonce chips */
1445  	if (opt_bf16_renonce != RENONCE_DISABLED) {
1446  		info->renonce_chips = opt_bf16_renonce;
1447  
1448  		uint8_t renonce_chips = 0;
1449  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1450  			if ((info->chipboard[board_id].detected == true) &&
1451  			    (info->chipboard[board_id].active   == true)) {
1452  				if (opt_bf16_renonce == RENONCE_ONE_CHIP) {
1453  					if (renonce_chips != info->renonce_chips)
1454  						renonce_chips++;
1455  					else {
1456  						renonce_chip_address[board_id].board_id  = -1;
1457  						renonce_chip_address[board_id].bcm250_id = -1;
1458  						renonce_chip_address[board_id].chip_id   = -1;
1459  					}
1460  				} else
1461  					renonce_chips++;
1462  			} else {
1463  				renonce_chip_address[board_id].board_id  = -1;
1464  				renonce_chip_address[board_id].bcm250_id = -1;
1465  				renonce_chip_address[board_id].chip_id   = -1;
1466  			}
1467  		}
1468  
1469  		if (renonce_chips != info->renonce_chips) {
1470  			applog(LOG_ERR, "%s: expected to find [%d] renonce chips, but found only [%d]",
1471  					bitfury->drv->name, opt_bf16_renonce, renonce_chips);
1472  
1473  			info->renonce_chips = renonce_chips;
1474  		}
1475  	} else {
1476  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1477  			renonce_chip_address[board_id].board_id  = -1;
1478  			renonce_chip_address[board_id].bcm250_id = -1;
1479  			renonce_chip_address[board_id].chip_id   = -1;
1480  		}
1481  	}
1482  
1483  	/* correct renonce chip address */
1484  	if (opt_bf16_renonce != RENONCE_DISABLED) {
1485  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
1486  			if ((info->chipboard[board_id].detected == true) &&
1487  			    (info->chipboard[board_id].active   == true) &&
1488  			    (renonce_chip_address[board_id].board_id != -1)) {
1489  				bcm250_id = renonce_chip_address[board_id].bcm250_id;
1490  
1491  				uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1492  				uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1493  
1494  				if (renonce_chip_address[board_id].chip_id >= last_good_chip)
1495  					renonce_chip_address[board_id].chip_id = last_good_chip - 1;
1496  				else if (renonce_chip_address[board_id].chip_id < first_good_chip)
1497  					renonce_chip_address[board_id].chip_id = first_good_chip;
1498  			}
1499  		}
1500  	}
1501  
1502  #ifdef FILELOG
1503  	info->logfile = fopen(LOGFILE, "a");
1504  	if (info->logfile == NULL)
1505  		applog(LOG_ERR, "%s: failed to open logfile [%s]: %s",
1506  				bitfury->drv->name, LOGFILE, strerror(errno));
1507  	else
1508  		mutex_init(&info->logfile_mutex);
1509  #endif
1510  
1511  	/* exit if no boards present */
1512  	if ((info->chipboard_num == 0) ||
1513  		(info->active_chipboard_num == 0)) {
1514  		deinit_x5(bitfury);
1515  
1516  		/* close devices */
1517  		close_spi_device(SPI_CHANNEL1);
1518  		close_spi_device(SPI_CHANNEL2);
1519  		close_ctrl_device();
1520  		close_uart_device(UART_CHANNEL1);
1521  		close_uart_device(UART_CHANNEL2);
1522  
1523  #ifdef FILELOG
1524  		fclose(info->logfile);
1525  #endif
1526  
1527  		applog(LOG_ERR, "%s: no boards present. exiting...",
1528  				bitfury->drv->name);
1529  
1530  		free(info);
1531  		free(bitfury);
1532  
1533  		return;
1534  	}
1535  
1536  	mutex_init(&info->nonces_good_lock);
1537  
1538  	if (!add_cgpu(bitfury))
1539  		quit(1, "%s: %s() failed to add_cgpu",
1540  				bitfury->drv->name, __func__);
1541  
1542  	info->initialised = true;
1543  
1544  	applog(LOG_INFO, "%s: chip driver initialized", bitfury->drv->name);
1545  #ifdef FILELOG
1546  	filelog(info, "%s: cgminer started", bitfury->drv->name);
1547  #endif
1548  }
1549  
1550  static uint8_t chip_task_update(struct cgpu_info *bitfury, bf_chip_address_t chip_address)
1551  {
1552  	uint8_t i;
1553  	int8_t ret = 0;
1554  	bf_works_t work;
1555  	time_t curr_time_t;
1556  	struct timeval curr_time;
1557  
1558  	uint8_t board_id  = chip_address.board_id;
1559  	uint8_t bcm250_id = chip_address.bcm250_id;
1560  	uint8_t chip_id   = chip_address.chip_id;
1561  
1562  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1563  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
1564  
1565  	if (cmd_buffer->status != EMPTY)
1566  		return -1;
1567  
1568  	switch (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status) {
1569  
1570  	/* fill chip buffer with toggle task */
1571  	case UNINITIALIZED:
1572  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare toggle_cmd",
1573  				bitfury->drv->name,
1574  				board_id, bcm250_id, chip_id);
1575  
1576  		uint8_t toggle[4] = { 0xa5, 0x00, 0x00, 0x02 };
1577  
1578  		ret = cmd_buffer_push(cmd_buffer,
1579  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1580  				work, 0, CHIP_CMD_TOGGLE, 3, toggle);
1581  
1582  		if (ret < 0)
1583  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare toggle_cmd",
1584  					bitfury->drv->name,
1585  					board_id, bcm250_id, chip_id);
1586  		break;
1587  
1588  	/* fill chip buffer with set clock task */
1589  	case TOGGLE_SET:
1590  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare set_clock_cmd",
1591  				bitfury->drv->name,
1592  				board_id, bcm250_id, chip_id);
1593  
1594  		uint8_t clock_buf[4];
1595  		memset(clock_buf, 0, sizeof(clock_buf));
1596  
1597  		/* init renonce chip with lower clock */
1598  		if ((renonce_chip(chip_address) == 1) &&
1599  			(opt_bf16_renonce != RENONCE_DISABLED)) {
1600  			gen_clock_data(bf16_renonce_chip_clock, 1, clock_buf);
1601  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].clock = bf16_renonce_chip_clock;
1602  		} else {
1603  			gen_clock_data(bf16_chip_clock, 1, clock_buf);
1604  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].clock = bf16_chip_clock;
1605  		}
1606  
1607  		ret = cmd_buffer_push(cmd_buffer,
1608  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1609  				work, 0, CHIP_CMD_SET_CLOCK, 3, clock_buf);
1610  
1611  		if (ret < 0)
1612  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare set_clock_cmd",
1613  					bitfury->drv->name,
1614  					board_id, bcm250_id, chip_id);
1615  		break;
1616  
1617  	/* fill chip buffer with chip mask */
1618  	case CLOCK_SET:
1619  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare set_mask_cmd",
1620  				bitfury->drv->name,
1621  				board_id, bcm250_id, chip_id);
1622  
1623  		uint8_t noncemask[4];
1624  		memset(noncemask, 0, sizeof(noncemask));
1625  
1626  		for (i = 0; i < 4; i++)
1627  			noncemask[i] = (mask >> (8*(4 - i - 1))) & 0xff;
1628  
1629  		ret = cmd_buffer_push(cmd_buffer,
1630  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1631  				work, 0, CHIP_CMD_SET_MASK, 3, noncemask);
1632  
1633  		if (ret < 0)
1634  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare set_mask_cmd",
1635  					bitfury->drv->name,
1636  					board_id, bcm250_id, chip_id);
1637  		break;
1638  
1639  	/* fill chip buffer with new task */
1640  	case MASK_SET:
1641  		if ((renonce_chip(chip_address) == 0) ||
1642  			(opt_bf16_renonce == RENONCE_DISABLED)) {
1643  			applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare send_task_cmd",
1644  					bitfury->drv->name,
1645  					board_id, bcm250_id, chip_id);
1646  
1647  			L_LOCK(info->work_list);
1648  			L_LOCK(info->stale_work_list);
1649  			if (info->work_list->count > 0) {
1650  				memset(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.task, 0,
1651  						sizeof(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.task));
1652  
1653  				bf_data_t* wdata = info->work_list->head;
1654  
1655  				workd_list_push(info->stale_work_list, WORKD(wdata));
1656  				workd_list_remove(info->work_list, &info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork);
1657  
1658  				gen_task_data(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.payload.midstate,
1659  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.payload.m7,
1660  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.payload.ntime,
1661  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.payload.nbits, mask,
1662  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.task);
1663  
1664  				ret = cmd_buffer_push(cmd_buffer,
1665  						info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1666  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork, 0,
1667  						CHIP_CMD_TASK_WRITE, 79,
1668  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork.task);
1669  
1670  				if (ret < 0)
1671  					applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare send_task_cmd",
1672  							bitfury->drv->name,
1673  							board_id, bcm250_id, chip_id);
1674  			}
1675  #if 0
1676  			else
1677  				applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare send_task_cmd: no works available",
1678  						bitfury->drv->name,
1679  						board_id, bcm250_id, chip_id);
1680  #endif
1681  			L_UNLOCK(info->stale_work_list);
1682  			L_UNLOCK(info->work_list);
1683  		}
1684  
1685  		break;
1686  
1687  	/* fill chip buffer with check status task */
1688  	case TASK_SENT:
1689  		gettimeofday(&curr_time, NULL);
1690  
1691  		if (((renonce_chip(chip_address) == 0) ||
1692  			(opt_bf16_renonce == RENONCE_DISABLED)) &&
1693  			(timediff_us(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, curr_time) > CHIP_TASK_STATUS_INTERVAL)) {
1694  			applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare task_status_cmd",
1695  					bitfury->drv->name,
1696  					board_id, bcm250_id, chip_id);
1697  
1698  			ret = cmd_buffer_push(cmd_buffer,
1699  					info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1700  					work, 0, CHIP_CMD_TASK_STATUS, 0, NULL);
1701  
1702  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time.tv_sec  = curr_time.tv_sec;
1703  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time.tv_usec = curr_time.tv_usec;
1704  
1705  			if (ret < 0)
1706  				applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare task_status_cmd",
1707  						bitfury->drv->name,
1708  						board_id, bcm250_id, chip_id);
1709  		}
1710  		break;
1711  
1712  	/* fill chip buffer with read nonces task */
1713  	case TASK_SWITCHED:
1714  		if ((renonce_chip(chip_address) == 0) ||
1715  			(opt_bf16_renonce == RENONCE_DISABLED)) {
1716  			applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], prepare read_nonce_cmd",
1717  					bitfury->drv->name,
1718  					board_id, bcm250_id, chip_id);
1719  
1720  			ret = cmd_buffer_push(cmd_buffer,
1721  					info->chipboard[board_id].bcm250[bcm250_id].channel_depth, chip_address, chip_address,
1722  					work, 0, CHIP_CMD_READ_NONCE, 0, NULL);
1723  
1724  			if (ret < 0)
1725  				applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d], error prepare read_nonce_cmd",
1726  						bitfury->drv->name,
1727  						board_id, bcm250_id, chip_id);
1728  		}
1729  
1730  		break;
1731  
1732  	/* mark chip as UNINITIALIZED and start all over again */
1733  	case FAILING:
1734  		curr_time_t = time(NULL);
1735  		time_t time_diff = curr_time_t - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time;
1736  
1737  		if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count < CHIP_ERROR_FAIL_LIMIT) {
1738  			if (time_diff >= info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count * CHIP_RECOVERY_INTERVAL) {
1739  
1740  				/* change renonce chip address if RENONCE_CHIP_ERROR_FAIL_LIMIT reached */
1741  				if ((renonce_chip(chip_address) == 1) &&
1742  					(opt_bf16_renonce != RENONCE_DISABLED)) {
1743  					if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count == RENONCE_CHIP_ERROR_FAIL_LIMIT) {
1744  						applog(LOG_ERR, "%s: chipworker_thr: renonce chip [%d:%d:%2d] failed. trying to switch to another one...",
1745  								bitfury->drv->name,
1746  								chip_address.board_id,
1747  								chip_address.bcm250_id,
1748  								chip_address.chip_id);
1749  
1750  						if (change_renonce_chip_address(bitfury, chip_address) == 0) {
1751  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
1752  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = curr_time_t;
1753  							gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
1754  						}
1755  					} else {
1756  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
1757  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = curr_time_t;
1758  						gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
1759  
1760  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count++;
1761  					}
1762  				} else {
1763  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = UNINITIALIZED;
1764  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = curr_time_t;
1765  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_time, NULL);
1766  					gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, NULL);
1767  
1768  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count++;
1769  
1770  #ifdef FILELOG
1771  					filelog(info, "BF16: chip [%d:%d:%2d] recovered time_diff: [%d], "
1772  							"recovery_count: [%d], error_rate: [%d]",
1773  							board_id, bcm250_id, chip_id,
1774  							time_diff,
1775  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
1776  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
1777  #endif
1778  				}
1779  			}
1780  		}
1781  		/* mark chip as DISABLED and never communicate to it again */
1782  		else if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status != DISABLED) {
1783  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = DISABLED;
1784  
1785  #ifdef FILELOG
1786  			filelog(info, "BF16: disabling chip [%d:%d:%2d] recovery_count: [%d], error_rate: [%d]",
1787  					board_id, bcm250_id, chip_id,
1788  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
1789  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
1790  #endif
1791  		}
1792  		break;
1793  
1794  	case DISABLED:
1795  	default:
1796  		break;
1797  	}
1798  
1799  	return ret;
1800  }
1801  
1802  static uint8_t renonce_task_update_loop(struct cgpu_info *bitfury, uint8_t board_id,
1803  		bf_renonce_stage_t stage, uint8_t renonce_count)
1804  {
1805  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1806  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
1807  
1808  	uint8_t bcm250_id = renonce_chip_address[board_id].bcm250_id;
1809  	uint8_t chip_id   = renonce_chip_address[board_id].chip_id;
1810  
1811  	uint8_t nonces = 0;
1812  
1813  	if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING) {
1814  		L_LOCK(info->renonce_list);
1815  		bf_data_t* rdata = info->renonce_list->head;
1816  		while ((rdata != NULL) && (nonces < renonce_count)) {
1817  			uint8_t ret = 1;
1818  
1819  			if ((RENONCE(rdata)->sent == false) &&
1820  				(RENONCE(rdata)->stage == stage)) {
1821  				/* generate work mask */
1822  				uint32_t nonce_mask = gen_mask(RENONCE(rdata)->nonce, mask_bits);
1823  				nonce_mask = ntohl(nonce_mask);
1824  
1825  				switch (RENONCE(rdata)->stage) {
1826  					case RENONCE_STAGE0:
1827  					case RENONCE_STAGE2:
1828  						/* generate chip work with new mask */
1829  						cg_memcpy(RENONCE(rdata)->owork.task + 19*4,
1830  								&nonce_mask, sizeof(nonce_mask));
1831  
1832  						/* send task and read nonces at the same time */
1833  						ret = cmd_buffer_push(cmd_buffer,
1834  								info->chipboard[board_id].bcm250[bcm250_id].channel_depth,
1835  								renonce_chip_address[board_id], RENONCE(rdata)->src_address,
1836  								RENONCE(rdata)->owork, RENONCE(rdata)->id,
1837  								(CHIP_CMD_TASK_WRITE | CHIP_CMD_TASK_SWITCH | CHIP_CMD_READ_NONCE), 79,
1838  								RENONCE(rdata)->owork.task);
1839  						break;
1840  					case RENONCE_STAGE1:
1841  					case RENONCE_STAGE3:
1842  						/* generate chip work with new mask */
1843  						cg_memcpy(RENONCE(rdata)->cwork.task + 19*4,
1844  								&nonce_mask, sizeof(nonce_mask));
1845  
1846  						/* send task and read nonces at the same time */
1847  						ret = cmd_buffer_push(cmd_buffer,
1848  								info->chipboard[board_id].bcm250[bcm250_id].channel_depth,
1849  								renonce_chip_address[board_id], RENONCE(rdata)->src_address,
1850  								RENONCE(rdata)->cwork, RENONCE(rdata)->id,
1851  								(CHIP_CMD_TASK_WRITE | CHIP_CMD_TASK_SWITCH | CHIP_CMD_READ_NONCE), 79,
1852  								RENONCE(rdata)->cwork.task);
1853  						break;
1854  					case RENONCE_STAGE_FINISHED:
1855  					default:
1856  						break;
1857  				}
1858  			}
1859  
1860  			if (ret == 0) {
1861  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = TASK_SWITCHED;
1862  				RENONCE(rdata)->sent     = true;
1863  				RENONCE(rdata)->received = false;
1864  				nonces++;
1865  			}
1866  
1867  			rdata = rdata->next;
1868  		}
1869  		L_UNLOCK(info->renonce_list);
1870  	}
1871  
1872  	return nonces;
1873  }
1874  
1875  static void renonce_task_update(struct cgpu_info *bitfury, uint8_t board_id, uint8_t renonce_count)
1876  {
1877  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1878  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
1879  
1880  	bf_works_t work;
1881  	uint8_t i;
1882  
1883  	uint8_t bcm250_id = renonce_chip_address[board_id].bcm250_id;
1884  	uint8_t chip_id   = renonce_chip_address[board_id].chip_id;
1885  
1886  	cmd_buffer_push_create_channel(cmd_buffer,
1887  			info->chipboard[board_id].bcm250[bcm250_id].channel_path,
1888  			info->channel_length);
1889  
1890  	if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING) {
1891  		uint8_t toggle[4] = { 0xa5, 0x00, 0x00, 0x02 };
1892  
1893  		cmd_buffer_push(cmd_buffer,
1894  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth,
1895  				renonce_chip_address[board_id], renonce_chip_address[board_id],
1896  				work, 0, CHIP_CMD_TOGGLE, 3, toggle);
1897  
1898  		uint8_t clock_buf[4];
1899  		memset(clock_buf, 0, sizeof(clock_buf));
1900  		gen_clock_data(bf16_renonce_chip_clock, 1, clock_buf);
1901  
1902  		cmd_buffer_push(cmd_buffer,
1903  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth,
1904  				renonce_chip_address[board_id], renonce_chip_address[board_id],
1905  				work, 0, CHIP_CMD_SET_CLOCK, 3, clock_buf);
1906  
1907  		uint8_t noncemask[4];
1908  		memset(noncemask, 0, sizeof(noncemask));
1909  
1910  		for (i = 0; i < 4; i++)
1911  			noncemask[i] = (mask >> (8*(4 - i - 1))) & 0xff;
1912  
1913  		cmd_buffer_push(cmd_buffer,
1914  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth,
1915  				renonce_chip_address[board_id], renonce_chip_address[board_id],
1916  				work, 0, CHIP_CMD_SET_MASK, 3, noncemask);
1917  
1918  		bf_renonce_stage_t stage = RENONCE_STAGE0;
1919  		while ((renonce_count > 0) && (stage != RENONCE_STAGE_FINISHED)) {
1920  			renonce_count -= renonce_task_update_loop(bitfury, board_id, stage++, renonce_count);
1921  		}
1922  	}
1923  
1924  	cmd_buffer_push_destroy_channel(cmd_buffer,
1925  			info->chipboard[board_id].
1926  			bcm250[renonce_chip_address[board_id].bcm250_id].channel_depth);
1927  }
1928  
1929  static void fill_cmd_buffer_loop(struct cgpu_info *bitfury, uint8_t board_id, bool do_renonce, uint16_t renonce_count)
1930  {
1931  	uint8_t bcm250_id, chip_id;
1932  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1933  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
1934  
1935  	/* concentrator loop */
1936  	for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
1937  		uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
1938  		uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
1939  
1940  		cmd_buffer_push_create_channel(cmd_buffer,
1941  				info->chipboard[board_id].bcm250[bcm250_id].channel_path,
1942  				info->channel_length);
1943  
1944  		/* chips loop */
1945  		for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
1946  			bf_chip_address_t chip_address = { board_id, bcm250_id, chip_id };
1947  			chip_task_update(bitfury, chip_address);
1948  		}
1949  
1950  		cmd_buffer_push_destroy_channel(cmd_buffer,
1951  				info->chipboard[board_id].bcm250[bcm250_id].channel_depth);
1952  	}
1953  
1954  	if (do_renonce == true) {
1955  		uint8_t count = (cmd_buffer->free_bytes - (2 + 11 + 11 + 11 + 8)) / 136;
1956  		if (count < renonce_count) {
1957  			if (count > 0)
1958  				renonce_task_update(bitfury, board_id, count);
1959  		} else if (renonce_count > 0)
1960  			renonce_task_update(bitfury, board_id, renonce_count);
1961  	}
1962  
1963  	cmd_buffer->status = TX_READY;
1964  }
1965  
1966  static void fill_cmd_buffer(struct cgpu_info *bitfury, uint8_t board_id)
1967  {
1968  	static uint8_t do_renonce[CHIPBOARD_NUM];
1969  	uint16_t renonce_count = 0;
1970  
1971  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
1972  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
1973  
1974  	if (cmd_buffer->status == EMPTY) {
1975  		if ((opt_bf16_renonce == RENONCE_DISABLED) ||
1976  			(renonce_chip_address[board_id].board_id == -1)) {
1977  
1978  			fill_cmd_buffer_loop(bitfury, board_id, false, 0);
1979  		} else {
1980  			L_LOCK(info->renonce_list);
1981  			bf_data_t* rdata = info->renonce_list->head;
1982  			while (rdata != NULL) {
1983  				if (RENONCE(rdata)->sent == false)
1984  					renonce_count++;
1985  				rdata = rdata->next;
1986  			}
1987  			L_UNLOCK(info->renonce_list);
1988  
1989  			if (do_renonce[board_id] < RENONCE_SEND) {
1990  				fill_cmd_buffer_loop(bitfury, board_id, true, renonce_count);
1991  
1992  				do_renonce[board_id]++;
1993  			} else {
1994  				if (renonce_count >= RENONCE_COUNT) {
1995  					renonce_task_update(bitfury, board_id, RENONCE_COUNT);
1996  
1997  					do_renonce[board_id] = 0;
1998  					cmd_buffer->status = TX_READY;
1999  				} else {
2000  					fill_cmd_buffer_loop(bitfury, board_id, true, renonce_count);
2001  
2002  					do_renonce[board_id]++;
2003  				}
2004  			}
2005  		}
2006  	}
2007  }
2008  
2009  static uint8_t update_chip_status(struct cgpu_info *bitfury, bf_cmd_status_t cmd_status)
2010  {
2011  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2012  	uint8_t board_id  = cmd_status.chip_address.board_id;
2013  	uint8_t bcm250_id = cmd_status.chip_address.bcm250_id;
2014  	uint8_t chip_id   = cmd_status.chip_address.chip_id;
2015  
2016  	switch (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status) {
2017  
2018  	case UNINITIALIZED:
2019  	case TOGGLE_SET:
2020  	case CLOCK_SET:
2021  	case MASK_SET:
2022  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], send_cmd [%s]",
2023  				bitfury->drv->name,
2024  				board_id, bcm250_id, chip_id,
2025  				get_cmd_description(cmd_status.cmd_code));
2026  
2027  		/* update chip status */
2028  		if (cmd_status.checksum_error == false)
2029  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status++;
2030  
2031  		else {
2032  #ifndef DISABLE_SEND_CMD_ERROR
2033  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d]: error send_cmd [%s]. "
2034  					"checksum: expected: [%02x]; received: [%02x]",
2035  					bitfury->drv->name,
2036  					board_id, bcm250_id, chip_id,
2037  					get_cmd_description(cmd_status.cmd_code),
2038  					cmd_status.checksum_expected,
2039  					cmd_status.checksum_received);
2040  #endif
2041  
2042  			/* increase error counters */
2043  			increase_errors(info, cmd_status.chip_address);
2044  		}
2045  		break;
2046  
2047  	case TASK_SENT:
2048  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], send_cmd [%s]",
2049  				bitfury->drv->name,
2050  				board_id, bcm250_id, chip_id,
2051  			 	get_cmd_description(cmd_status.cmd_code));
2052  
2053  		/* read task status from chip*/
2054  		if (cmd_status.checksum_error == false) {
2055  			uint8_t new_buff = ((cmd_status.status & 0x0f) == 0x0f) ? 1 : 0;
2056  
2057  			/* status cmd counter */
2058  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_dx++;
2059  			info->chipboard[board_id].bcm250[bcm250_id].status_cmd_dx++;
2060  			info->chipboard[board_id].status_cmd_dx++;
2061  			info->status_cmd_dx++;
2062  
2063  			/* check if chip task has switched */
2064  			if (new_buff != info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].curr_buff) {
2065  				gettimeofday(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, NULL);
2066  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].curr_buff = new_buff;
2067  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status++;
2068  
2069  				/* task switch counter */
2070  				increase_task_switch(info, cmd_status.chip_address);
2071  
2072  			} else {
2073  				/* task not switched  */
2074  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none_dx++;
2075  				info->chipboard[board_id].bcm250[bcm250_id].status_cmd_none_dx++;
2076  				info->chipboard[board_id].status_cmd_none_dx++;
2077  				info->status_cmd_none_dx++;
2078  
2079  				/* check if chip hang */
2080  				struct timeval curr_time;
2081  				gettimeofday(&curr_time, NULL);
2082  
2083  				if ((timediff_us(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].switch_time, curr_time) > CHIP_TASK_SWITCH_INTERVAL) &&
2084  					(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2085  					increase_errors(info, cmd_status.chip_address);
2086  
2087  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2088  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = time(NULL);
2089  
2090  					applog(LOG_ERR, "%s: nonceworker_thr: chip [%d:%d:%2d], "
2091  							"failed: no task switch during last [%.3f] seconds",
2092  							bitfury->drv->name,
2093  							board_id, bcm250_id, chip_id, CHIP_TASK_SWITCH_INTERVAL / 1000000.0);
2094  
2095  #ifdef FILELOG
2096  					filelog(info, "BF16: no task switch for chip [%d:%d:%2d], "
2097  							"error count: [%d], recovery_count: [%d], error_rate: [%d]",
2098  							board_id, bcm250_id, chip_id,
2099  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2100  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2101  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2102  #endif
2103  				}
2104  			}
2105  		} else {
2106  #ifndef DISABLE_SEND_CMD_ERROR
2107  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d]: error send_cmd [%s]. "
2108  					"checksum: expected: [%02x]; received: [%02x]",
2109  					bitfury->drv->name,
2110  					board_id, bcm250_id, chip_id,
2111  					get_cmd_description(cmd_status.cmd_code),
2112  					cmd_status.checksum_expected,
2113  					cmd_status.checksum_received);
2114  #endif
2115  
2116  			/* increase error counters */
2117  			increase_errors(info, cmd_status.chip_address);
2118  		}
2119  		break;
2120  
2121  	case TASK_SWITCHED:
2122  		applog(LOG_DEBUG, "%s: chipworker_thr: chip [%d:%d:%2d], send_cmd [%s]",
2123  				bitfury->drv->name,
2124  				board_id, bcm250_id, chip_id,
2125  			 	get_cmd_description(cmd_status.cmd_code));
2126  
2127  		if (cmd_status.checksum_error == false) {
2128  			if ((renonce_chip(cmd_status.chip_address) == 1) &&
2129  				(opt_bf16_renonce != RENONCE_DISABLED)) {
2130  
2131  				/* task switch counter */
2132  				if (cmd_status.cmd_code & CHIP_CMD_READ_NONCE)
2133  					increase_task_switch(info, cmd_status.chip_address);
2134  			} else if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING) {
2135  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_processed++;
2136  
2137  				if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_processed >= CHIP_RESTART_LIMIT) {
2138  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = UNINITIALIZED;
2139  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_processed = 0;
2140  				} else
2141  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status = MASK_SET;
2142  			}
2143  
2144  			return 1;
2145  		} else {
2146  #ifndef DISABLE_SEND_CMD_ERROR
2147  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d]: error send_cmd [%s]. "
2148  					"checksum: expected: [%02x]; received: [%02x]",
2149  					bitfury->drv->name,
2150  					board_id, bcm250_id, chip_id,
2151  					get_cmd_description(cmd_status.cmd_code),
2152  					cmd_status.checksum_expected,
2153  					cmd_status.checksum_received);
2154  #endif
2155  
2156  			/* increase error counters */
2157  			increase_errors(info, cmd_status.chip_address);
2158  		}
2159  
2160  		break;
2161  
2162  	case FAILING:
2163  	case DISABLED:
2164  	default:
2165  		break;
2166  	}
2167  
2168  	return 0;
2169  }
2170  
2171  static uint8_t process_nonces(struct cgpu_info *bitfury, bf_cmd_status_t cmd_status, uint32_t* nonces)
2172  {
2173  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2174  
2175  	uint8_t i;
2176  	uint32_t found_nonces[12];
2177  
2178  	uint8_t board_id  = cmd_status.chip_address.board_id;
2179  	uint8_t bcm250_id = cmd_status.chip_address.bcm250_id;
2180  	uint8_t chip_id   = cmd_status.chip_address.chip_id;
2181  
2182  	if ((cmd_status.checksum_error == false) &&
2183  	    (cmd_status.nonce_checksum_error == false)) {
2184  		cg_memcpy(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].rx, nonces, sizeof(found_nonces));
2185  
2186  		uint8_t found = find_nonces(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].rx,
2187  									info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].rx_prev,
2188  									found_nonces);
2189  
2190  		/* check if chip is still mining */
2191  		if (found == 0) {
2192  			time_t curr_time = time(NULL);
2193  			time_t time_diff = curr_time - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time;
2194  
2195  			if ((renonce_chip(cmd_status.chip_address) == 1) &&
2196  				(opt_bf16_renonce != RENONCE_DISABLED)) {
2197  				if ((time_diff >= RENONCE_CHIP_FAILING_INTERVAL) &&
2198  					(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2199  					increase_errors(info, cmd_status.chip_address);
2200  
2201  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2202  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
2203  
2204  					applog(LOG_ERR, "%s: nonceworker_thr: renonce chip [%d:%d:%2d] "
2205  							"failed: no good nonces during last [%.1f] seconds",
2206  							bitfury->drv->name,
2207  							board_id, bcm250_id, chip_id, RENONCE_CHIP_FAILING_INTERVAL);
2208  
2209  #ifdef FILELOG
2210  					filelog(info, "BF16: no good nonces from renonce chip [%d:%d:%2d], "
2211  							"error count: [%d] recovery_count: [%d], error_rate: [%d]",
2212  							board_id, bcm250_id, chip_id,
2213  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2214  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2215  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2216  #endif
2217  				}
2218  			} else {
2219  				if ((time_diff >= CHIP_FAILING_INTERVAL) &&
2220  					(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2221  					increase_errors(info, cmd_status.chip_address);
2222  
2223  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2224  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
2225  
2226  					applog(LOG_ERR, "%s: nonceworker_thr: chip [%d:%d:%2d], "
2227  							"failed: no good nonces during last [%.1f] seconds",
2228  							bitfury->drv->name,
2229  							board_id, bcm250_id, chip_id, CHIP_FAILING_INTERVAL);
2230  
2231  #ifdef FILELOG
2232  					filelog(info, "BF16: no good nonces from chip [%d:%d:%2d], "
2233  							"error count: [%d], recovery_count: [%d], error_rate: [%d]",
2234  							board_id, bcm250_id, chip_id,
2235  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2236  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2237  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2238  #endif
2239  				}
2240  			}
2241  		}
2242  
2243  		/* increase stage if no nonces received */
2244  		if ((renonce_chip(cmd_status.chip_address) == 1) &&
2245  			(opt_bf16_renonce != RENONCE_DISABLED)) {
2246  			L_LOCK(info->renonce_list);
2247  			bf_data_t* rdata = info->renonce_list->head;
2248  			while (rdata != NULL) {
2249  				if (RENONCE(rdata)->id == cmd_status.id) {
2250  					if (found == 0) {
2251  						RENONCE(rdata)->stage++;
2252  						RENONCE(rdata)->sent = false;
2253  
2254  						/* clear renonces list if we are running too slow */
2255  						if ((RENONCE(rdata)->stage >= RENONCE_STAGE2) &&
2256  							(info->renonce_list->count > RENONCE_STAGE2_LIMIT)) {
2257  							info->unmatched++;
2258  							increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2259  							bf_data_t* rndata = rdata->next;
2260  							renonce_list_remove(info->renonce_list, rdata);
2261  							rdata = rndata;
2262  							continue;
2263  						}
2264  
2265  						if ((RENONCE(rdata)->stage >= RENONCE_STAGE3) &&
2266  							(info->renonce_list->count > RENONCE_STAGE3_LIMIT)) {
2267  							info->unmatched++;
2268  							increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2269  							bf_data_t* rndata = rdata->next;
2270  							renonce_list_remove(info->renonce_list, rdata);
2271  							rdata = rndata;
2272  							continue;
2273  						}
2274  
2275  						/* remove expired renonce */
2276  						if (RENONCE(rdata)->stage == RENONCE_STAGE_FINISHED) {
2277  							info->unmatched++;
2278  							increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2279  							bf_data_t* rndata = rdata->next;
2280  							renonce_list_remove(info->renonce_list, rdata);
2281  							rdata = rndata;
2282  							continue;
2283  						}
2284  					}
2285  
2286  					RENONCE(rdata)->received = true;
2287  					break;
2288  				}
2289  				rdata = rdata->next;
2290  			}
2291  			L_UNLOCK(info->renonce_list);
2292  		}
2293  
2294  		bf_list_t* nonce_list = info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonce_list;
2295  		for (i = 0; i < found; i++) {
2296  			L_LOCK(nonce_list);
2297  			int8_t res = nonce_list_push(nonce_list, found_nonces[i]);
2298  			L_UNLOCK(nonce_list);
2299  			if (res < 0)
2300  				continue;
2301  
2302  			increase_total_nonces(info, cmd_status.chip_address);
2303  
2304  			/* check if nonce has errors and add it to renonce list */
2305  			if ((opt_bf16_renonce != RENONCE_DISABLED) &&
2306  				(renonce_chip(cmd_status.chip_address) == 0) &&
2307  				(found_nonces[i] & 0xfff00000) == 0xaaa00000) {
2308  				increase_re_nonces(info, cmd_status.src_address);
2309  
2310  				L_LOCK(info->renonce_list);
2311  				if (info->renonce_list->count < RENONCE_QUEUE_LEN) {
2312  					renonce_list_push(info->renonce_list,
2313  							info->renonce_id++,
2314  							found_nonces[i],
2315  					   		cmd_status.chip_address,
2316  					   		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork,
2317  				   		info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].owork); 
2318  				} else
2319  					increase_re_bad_nonces(info, cmd_status.chip_address);
2320  				L_UNLOCK(info->renonce_list);
2321  
2322  				applog(LOG_DEBUG, "%s: chipworker_thr: pushing renonce task: nonce: [%08x]",
2323  						bitfury->drv->name,
2324  						found_nonces[i]);
2325  				continue;
2326  			}
2327  
2328  			/* add nonces to noncework list */
2329  			if ((renonce_chip(cmd_status.chip_address) == 1) &&
2330  				(opt_bf16_renonce != RENONCE_DISABLED)) {
2331  				L_LOCK(info->renoncework_list);
2332  				renoncework_list_push(info->renoncework_list, cmd_status.chip_address, found_nonces[i]);
2333  				L_UNLOCK(info->renoncework_list);
2334  			} else {
2335  				L_LOCK(info->noncework_list);
2336  				noncework_list_push(info->noncework_list,
2337  						cmd_status.chip_address, cmd_status.src_address,
2338  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork,
2339  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].owork,
2340  						found_nonces[i]);
2341  				L_UNLOCK(info->noncework_list);
2342  			}
2343  
2344  			applog(LOG_DEBUG, "%s: chipworker_thr: pushing nonce task: nonce: [%08x]",
2345  					bitfury->drv->name,
2346  					found_nonces[i]);
2347  		}
2348  
2349  		/* rotate works and buffers */
2350  		cg_memcpy(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].rx_prev,
2351  			   info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].rx, sizeof(found_nonces));
2352  
2353  		cg_memcpy(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].owork,
2354  				&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].cwork, sizeof(bf_works_t));
2355  
2356  		/* remove old nonces from nonce list */
2357  		L_LOCK(nonce_list);
2358  		if ((renonce_chip(cmd_status.chip_address) == 1) &&
2359  			(opt_bf16_renonce != RENONCE_DISABLED)) {
2360  			while (nonce_list->count > RENONCE_CHIP_QUEUE_LEN)
2361  				nonce_list_pop(nonce_list);
2362  		} else {
2363  			while (nonce_list->count > NONCE_CHIP_QUEUE_LEN)
2364  				nonce_list_pop(nonce_list);
2365  		}
2366  		L_UNLOCK(nonce_list);
2367  	} else {
2368  		if (cmd_status.checksum_error != 0) {
2369  #ifndef DISABLE_SEND_CMD_ERROR
2370  			applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d]: error send_cmd [%s]. "
2371  					"checksum: expected: [%02x]; received: [%02x]",
2372  					bitfury->drv->name,
2373  					board_id, bcm250_id, chip_id,
2374  					get_cmd_description(cmd_status.cmd_code),
2375  					cmd_status.checksum_expected,
2376  					cmd_status.checksum_received);
2377  #endif
2378  
2379  			/* increase error counters */
2380  			increase_errors(info, cmd_status.chip_address);
2381  		}
2382  
2383  		if (cmd_status.nonce_checksum_error != 0) {
2384  			if ((renonce_chip(cmd_status.chip_address) == 0) ||
2385  				(opt_bf16_renonce == RENONCE_DISABLED)) {
2386  				applog(LOG_ERR, "%s: chipworker_thr: chip [%d:%d:%2d]: error receiving data. "
2387  						"nonce checksum: expected: [%02x]; received: [%02x]",
2388  						bitfury->drv->name,
2389  						board_id, bcm250_id, chip_id,
2390  						cmd_status.checksum_expected,
2391  						cmd_status.checksum_received);
2392  
2393  				/* increase error counters */
2394  				increase_errors(info, cmd_status.chip_address);
2395  			}
2396  		}
2397  	}
2398  
2399  	return 0;
2400  }
2401  
2402  /* routine sending-receiving data to chipboard */
2403  static void process_cmd_buffer(struct cgpu_info *bitfury, uint8_t board_id)
2404  {
2405  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2406  	uint8_t i;
2407  	bf_cmd_status_t cmd_status;
2408  	bf_cmd_buffer_t* cmd_buffer = &info->chipboard[board_id].cmd_buffer;
2409  
2410  	if (cmd_buffer->status == EXECUTED) {
2411  		/* process extracted data */
2412  		uint16_t cmd_number = cmd_buffer->cmd_list->count;
2413  		for (i = 0; i < cmd_number; i++) {
2414  			uint32_t nonces[12];
2415  
2416  			cmd_buffer_pop(cmd_buffer, &cmd_status, nonces);
2417  			if ((cmd_status.cmd_code == CHIP_CMD_CREATE_CHANNEL) ||
2418  				(cmd_status.cmd_code == CHIP_CMD_TASK_SWITCH))
2419  				continue;
2420  
2421  			uint8_t task_switch = update_chip_status(bitfury, cmd_status);
2422  
2423  			/* analyze nonces */
2424  			if ((cmd_status.cmd_code & CHIP_CMD_READ_NONCE) &&
2425  			    (task_switch == 1)) {
2426  				process_nonces(bitfury, cmd_status, nonces);
2427  			}
2428  		}
2429  
2430  		cmd_buffer_clear(cmd_buffer);
2431  	}
2432  }
2433  
2434  static void *bitfury_chipworker(void *userdata)
2435  {
2436  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
2437  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2438  	uint8_t board_id;
2439  
2440  	applog(LOG_INFO, "%s: started chipworker thread", bitfury->drv->name);
2441  
2442  	while (bitfury->shutdown == false) {
2443  		if (info->initialised) {
2444  			break;
2445  		}
2446  		cgsleep_us(30);
2447  	}
2448  
2449  	/* send reset sequence to boards */
2450  	spi_emit_reset(SPI_CHANNEL1);
2451  	spi_emit_reset(SPI_CHANNEL2);
2452  
2453  	while (bitfury->shutdown == false) {
2454  		if ((info->a_temp == false) &&
2455  			(info->a_ichain == false)) {
2456  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
2457  				if (info->chipboard[board_id].detected == true) {
2458  					/* prepare send buffer */
2459  					struct timeval start_time, stop_time;
2460  					gettimeofday(&start_time, NULL);
2461  
2462  					if (info->chipboard[board_id].cmd_buffer.status == EMPTY)
2463  						fill_cmd_buffer(bitfury, board_id);
2464  
2465  					gettimeofday(&stop_time, NULL);
2466  
2467  #if 0
2468  					applog(LOG_ERR, "%s: chipworker_thr: board %d buffer prepare: time elapsed: [%.6f]",
2469  							bitfury->drv->name, board_id, timediff(start_time, stop_time));
2470  #endif
2471  
2472  					gettimeofday(&start_time, NULL);
2473  
2474  					/* send buffer to chipboard */
2475  					if (info->chipboard[board_id].cmd_buffer.status == TX_READY) {
2476  						spi_emit_reset(board_id + 1);
2477  
2478  						cmd_buffer_exec(board_id + 1, &info->chipboard[board_id].cmd_buffer);
2479  						info->chipboard[board_id].bytes_transmitted_dx += info->chipboard[board_id].cmd_buffer.tx_offset;
2480  						info->chipboard[board_id].bytes_transmitted    += info->chipboard[board_id].cmd_buffer.tx_offset;
2481  					}
2482  
2483  					gettimeofday(&stop_time, NULL);
2484  
2485  #if 0
2486  					applog(LOG_ERR, "%s: chipworker_thr: board %d TX/RX time: [%.6f]",
2487  							bitfury->drv->name, board_id, timediff(start_time, stop_time));
2488  #endif
2489  
2490  					gettimeofday(&start_time, NULL);
2491  
2492  					/* analyze received data */
2493  					if (info->chipboard[board_id].cmd_buffer.status == EXECUTED) {
2494  						process_cmd_buffer(bitfury, board_id);
2495  					}
2496  
2497  					gettimeofday(&stop_time, NULL);
2498  
2499  #if 0
2500  					applog(LOG_ERR, "%s: chipworker_thr: board %d buffer processing: time elapsed: [%.6f]",
2501  							bitfury->drv->name, board_id, timediff(start_time, stop_time));
2502  #endif
2503  				}
2504  			}
2505  		} else
2506  			cgsleep_us(CHIPWORKER_DELAY);
2507  	}
2508  
2509  	applog(LOG_INFO, "%s: chipworker_thr: exiting...", bitfury->drv->name);
2510  	return NULL;
2511  }
2512  
2513  static int16_t cleanup_older(struct cgpu_info *bitfury)
2514  {
2515  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2516  	time_t curr_time = time(NULL);
2517  	uint16_t released = 0;
2518  
2519  	/* clear stale work list */
2520  	L_LOCK(info->stale_work_list);
2521  	bf_data_t* wdata = info->stale_work_list->head;
2522  	while (wdata != NULL) {
2523  		if (curr_time - WORKD(wdata)->generated >= WORK_TIMEOUT) {
2524  			workd_list_pop(info->stale_work_list, bitfury);
2525  			released++;
2526  		} else
2527  			break;
2528  		wdata = info->stale_work_list->head;
2529  	}
2530  	L_UNLOCK(info->stale_work_list);
2531  
2532  	applog(LOG_INFO, "%s: released %d works", bitfury->drv->name, released);
2533  	return released;
2534  }
2535  
2536  static void *bitfury_nonceworker(void *userdata)
2537  {
2538  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
2539  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2540  
2541  	applog(LOG_INFO, "%s: started nonceworker thread", bitfury->drv->name);
2542  
2543  	while (bitfury->shutdown == false) {
2544  		if (info->initialised) {
2545  			break;
2546  		}
2547  		cgsleep_us(30);
2548  	}
2549  
2550  	applog(LOG_INFO, "%s: nonceworker loop started", bitfury->drv->name);
2551  
2552  	while (bitfury->shutdown == false) {
2553  		struct timeval start_time, stop_time;
2554  		gettimeofday(&start_time, NULL);
2555  
2556  		uint32_t nonce_cnt = 0;
2557  
2558  		/* general nonces processing */
2559  		L_LOCK(info->noncework_list);
2560  		bf_data_t* nwdata = info->noncework_list->head;
2561  		while (nwdata != NULL) {
2562  			uint8_t board_id  = NONCEWORK(nwdata)->chip_address.board_id;
2563  			uint8_t bcm250_id = NONCEWORK(nwdata)->chip_address.bcm250_id;
2564  			uint8_t chip_id   = NONCEWORK(nwdata)->chip_address.chip_id;
2565  
2566  			nonce_cnt++;
2567  
2568  			/* general chip results processing */
2569  			if (test_nonce(&NONCEWORK(nwdata)->owork.work, NONCEWORK(nwdata)->nonce)) {
2570  				applog(LOG_DEBUG, "%s: nonceworker_thr: chip [%d:%d:%2d], valid nonce [%08x]",
2571  						bitfury->drv->name,
2572  						board_id, bcm250_id, chip_id, NONCEWORK(nwdata)->nonce);
2573  
2574  				submit_tested_work(info->thr, &NONCEWORK(nwdata)->owork.work);
2575  
2576  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
2577  
2578  				if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count > 0) {
2579  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count = 0;
2580  
2581  #ifdef FILELOG
2582  					filelog(info, "BF16: good nonce for chip [%d:%d:%2d] "
2583  							"setting recovery_count to [0], error_rate: [%d]",
2584  							board_id, bcm250_id, chip_id,
2585  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2586  #endif
2587  				}
2588  
2589  				increase_good_nonces(info, NONCEWORK(nwdata)->chip_address);
2590  
2591  				mutex_lock(&info->nonces_good_lock);
2592  				info->nonces_good_cg++;
2593  				mutex_unlock(&info->nonces_good_lock);
2594  			} else if (test_nonce(&NONCEWORK(nwdata)->cwork.work, NONCEWORK(nwdata)->nonce)) {
2595  				applog(LOG_DEBUG, "%s: nonceworker_thr: chip [%d:%d:%2d], valid nonce [%08x]",
2596  						bitfury->drv->name,
2597  						board_id, bcm250_id, chip_id, NONCEWORK(nwdata)->nonce);
2598  
2599  				submit_tested_work(info->thr, &NONCEWORK(nwdata)->cwork.work);
2600  
2601  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
2602  
2603  				if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count > 0) {
2604  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count = 0;
2605  
2606  #ifdef FILELOG
2607  					filelog(info, "BF16: good nonce for chip [%d:%d:%2d] "
2608  							"setting recovery_count to 0, error_rate: [%d]",
2609  							board_id, bcm250_id, chip_id,
2610  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2611  #endif
2612  				}
2613  
2614  				increase_good_nonces(info, NONCEWORK(nwdata)->chip_address);
2615  
2616  				mutex_lock(&info->nonces_good_lock);
2617  				info->nonces_good_cg++;
2618  				mutex_unlock(&info->nonces_good_lock);
2619  			} else {
2620  				time_t curr_time = time(NULL);
2621  				time_t time_diff = curr_time - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time;
2622  
2623  				if ((time_diff >= CHIP_FAILING_INTERVAL) &&
2624  					(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2625  					increase_errors(info, NONCEWORK(nwdata)->chip_address);
2626  
2627  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2628  					info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
2629  
2630  					applog(LOG_ERR, "%s: nonceworker_thr: chip [%d:%d:%2d], "
2631  							"failed: no good nonces during last [%.1f] seconds",
2632  							bitfury->drv->name,
2633  							board_id, bcm250_id, chip_id, CHIP_FAILING_INTERVAL);
2634  
2635  #ifdef FILELOG
2636  					filelog(info, "BF16: no good nonces from chip [%d:%d:%2d], "
2637  							"error count: [%d], recovery_count: [%d], error_rate: [%d]",
2638  							board_id, bcm250_id, chip_id,
2639  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2640  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2641  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2642  #endif
2643  				}
2644  
2645  				if (opt_bf16_renonce != RENONCE_DISABLED) {
2646  					/* add failed nonce to renonce list */
2647  					increase_bad_nonces(info, NONCEWORK(nwdata)->chip_address);
2648  
2649  					L_LOCK(info->renonce_list);
2650  					if (info->renonce_list->count < RENONCE_QUEUE_LEN) {
2651  						renonce_list_push(info->renonce_list,
2652  								info->renonce_id++,
2653  								NONCEWORK(nwdata)->nonce,
2654  								NONCEWORK(nwdata)->chip_address,
2655  								NONCEWORK(nwdata)->cwork,
2656  								NONCEWORK(nwdata)->owork);
2657  					} else
2658  						increase_re_bad_nonces(info, NONCEWORK(nwdata)->chip_address);
2659  					L_UNLOCK(info->renonce_list);
2660  
2661  					applog(LOG_DEBUG, "%s: nonceworker_thr: pushing renonce task: nonce: [%08x]",
2662  							bitfury->drv->name,
2663  							NONCEWORK(nwdata)->nonce);
2664  				} else
2665  					increase_bad_nonces(info, NONCEWORK(nwdata)->chip_address);
2666  			}
2667  
2668  			/* remove nonce from list */
2669  			noncework_list_pop(info->noncework_list);
2670  			nwdata = info->noncework_list->head;
2671  		}
2672  		L_UNLOCK(info->noncework_list);
2673  
2674  		/* cleanup older works */
2675  		cleanup_older(bitfury);
2676  
2677  		gettimeofday(&stop_time, NULL);
2678  
2679  #if 0
2680  		applog(LOG_DEBUG, "%s: nonceworker_thr: nonces processed [%d]: time elapsed: [%.6f]",
2681  				bitfury->drv->name,
2682  				nonce_cnt, timediff(start_time, stop_time));
2683  #endif
2684  
2685  		cgsleep_us(NONCEWORKER_DELAY);
2686  	}
2687  
2688  	applog(LOG_INFO, "%s: nonceworker_thr: exiting...", bitfury->drv->name);
2689  	return NULL;
2690  }
2691  
2692  static bool test_renonce(struct cgpu_info *bitfury, bf_data_t* rdata, bf_data_t* rnwdata, bool owork)
2693  {
2694  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2695  
2696  	uint8_t board_id  = RENONCEWORK(rnwdata)->src_address.board_id;
2697  	uint8_t bcm250_id = renonce_chip_address[board_id].bcm250_id;
2698  	uint8_t chip_id   = renonce_chip_address[board_id].chip_id;
2699  
2700  	if (owork == true) {
2701  		if (test_nonce(&RENONCE(rdata)->owork.work, RENONCEWORK(rnwdata)->nonce)) {
2702  			applog(LOG_DEBUG, "%s: renonceworker_thr: restored renonce: nonce: [%08x]",
2703  					bitfury->drv->name,
2704  					RENONCEWORK(rnwdata)->nonce);
2705  
2706  			submit_tested_work(info->thr, &RENONCE(rdata)->owork.work);
2707  
2708  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
2709  
2710  			if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count > 0) {
2711  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count = 0;
2712  
2713  #ifdef FILELOG
2714  				filelog(info, "BF16: good nonce for renonce chip [%d:%d:%2d] "
2715  						"setting recovery_count to 0, error_rate: [%d]",
2716  						board_id, bcm250_id, chip_id,
2717  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2718  #endif
2719  			}
2720  
2721  			increase_re_good_nonces(info, RENONCE(rdata)->src_address);
2722  			increase_re_good_nonces(info, renonce_chip_address[board_id]);
2723  
2724  			mutex_lock(&info->nonces_good_lock);
2725  			info->nonces_good_cg++;
2726  			mutex_unlock(&info->nonces_good_lock);
2727  
2728  			RENONCE(rdata)->match = true;
2729  		} else {
2730  			time_t curr_time = time(NULL);
2731  			time_t time_diff = curr_time - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time;
2732  
2733  			if ((time_diff >= RENONCE_CHIP_FAILING_INTERVAL) &&
2734  				(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2735  				increase_errors(info, renonce_chip_address[board_id]);
2736  
2737  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2738  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
2739  
2740  				applog(LOG_ERR, "%s: nonceworker_thr: renonce chip [%d:%d:%2d] "
2741  						"failed: no good nonces during last [%.1f] seconds",
2742  						bitfury->drv->name,
2743  						board_id, bcm250_id, chip_id, RENONCE_CHIP_FAILING_INTERVAL);
2744  
2745  #ifdef FILELOG
2746  				filelog(info, "BF16: no good nonces from renonce chip [%d:%d:%2d], "
2747  						"error count: [%d] recovery_count: [%d], error_rate: [%d]",
2748  						board_id, bcm250_id, chip_id,
2749  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2750  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2751  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2752  #endif
2753  			}
2754  		}
2755  	} else {
2756  		if (test_nonce(&RENONCE(rdata)->cwork.work, RENONCEWORK(rnwdata)->nonce)) {
2757  			applog(LOG_DEBUG, "%s: renonceworker_thr: restored renonce: nonce: [%08x]",
2758  					bitfury->drv->name,
2759  					RENONCEWORK(rnwdata)->nonce);
2760  
2761  			submit_tested_work(info->thr, &RENONCE(rdata)->cwork.work);
2762  
2763  			info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time = time(NULL);
2764  
2765  			if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count > 0) {
2766  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count = 0;
2767  
2768  #ifdef FILELOG
2769  				filelog(info, "BF16: good nonce for renonce chip [%d:%d:%2d] "
2770  						"setting recovery_count to 0, error_rate: [%d]",
2771  						board_id, bcm250_id, chip_id,
2772  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2773  #endif
2774  			}
2775  
2776  			increase_re_good_nonces(info, RENONCE(rdata)->src_address);
2777  			increase_re_good_nonces(info, renonce_chip_address[board_id]);
2778  
2779  			mutex_lock(&info->nonces_good_lock);
2780  			info->nonces_good_cg++;
2781  			mutex_unlock(&info->nonces_good_lock);
2782  
2783  			RENONCE(rdata)->match = true;
2784  		} else {
2785  			time_t curr_time = time(NULL);
2786  			time_t time_diff = curr_time - info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_nonce_time;
2787  
2788  			if ((time_diff >= RENONCE_CHIP_FAILING_INTERVAL) &&
2789  				(info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING)) {
2790  				increase_errors(info, renonce_chip_address[board_id]);
2791  
2792  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status          = FAILING;
2793  				info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].last_error_time = curr_time;
2794  
2795  				applog(LOG_ERR, "%s: nonceworker_thr: renonce chip [%d:%d:%2d] "
2796  						"failed: no good nonces during last [%.1f] seconds",
2797  						bitfury->drv->name,
2798  						board_id, bcm250_id, chip_id, RENONCE_CHIP_FAILING_INTERVAL);
2799  
2800  #ifdef FILELOG
2801  				filelog(info, "BF16: no good nonces from renonce chip [%d:%d:%2d], "
2802  						"error count: [%d] recovery_count: [%d], error_rate: [%d]",
2803  						board_id, bcm250_id, chip_id,
2804  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].errors,
2805  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].recovery_count,
2806  						info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].error_rate);
2807  #endif
2808  			}
2809  		}
2810  	}
2811  
2812  	return RENONCE(rdata)->match;
2813  }
2814  
2815  static void *bitfury_renonceworker(void *userdata)
2816  {
2817  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
2818  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
2819  	bf_list_t* id_list = nonce_list_init();
2820  
2821  	applog(LOG_INFO, "%s: started renonceworker thread", bitfury->drv->name);
2822  
2823  	while (bitfury->shutdown == false) {
2824  		if (info->initialised) {
2825  			break;
2826  		}
2827  		cgsleep_us(30);
2828  	}
2829  
2830  	applog(LOG_INFO, "%s: renonceworker loop started", bitfury->drv->name);
2831  
2832  	while (bitfury->shutdown == false) {
2833  		struct timeval start_time, stop_time;
2834  		gettimeofday(&start_time, NULL);
2835  
2836  		uint32_t nonce_cnt = 0;
2837  
2838  		/* renonce chip results processing */
2839  		L_LOCK(info->renoncework_list);
2840  		bf_data_t* rnwdata = info->renoncework_list->head;
2841  		while (rnwdata != NULL) {
2842  			nonce_cnt++;
2843  
2844  			/* find nonce by id */
2845  			L_LOCK(info->renonce_list);
2846  			bf_data_t* rdata = info->renonce_list->head;
2847  			while (rdata != NULL) {
2848  				if (match_nonce(RENONCEWORK(rnwdata)->nonce, RENONCE(rdata)->nonce, mask_bits)) {
2849  					if (RENONCE(rdata)->match == false) {
2850  						switch (RENONCE(rdata)->stage) {
2851  							case RENONCE_STAGE0:
2852  								if (test_renonce(bitfury, rdata, rnwdata, true) == true)
2853  									info->stage0_match++;
2854  								else
2855  									info->stage0_mismatch++;
2856  								break;
2857  							case RENONCE_STAGE1:
2858  							case RENONCE_STAGE2:
2859  							case RENONCE_STAGE3:
2860  								/* test old work first */
2861  								if (test_renonce(bitfury, rdata, rnwdata, true) == true) {
2862  									if (RENONCE(rdata)->stage == RENONCE_STAGE1)
2863  										info->stage1_mismatch++;
2864  
2865  									if (RENONCE(rdata)->stage == RENONCE_STAGE2)
2866  										info->stage2_match++;
2867  
2868  									if (RENONCE(rdata)->stage == RENONCE_STAGE3)
2869  										info->stage3_mismatch++;
2870  								} else {
2871  									if (test_renonce(bitfury, rdata, rnwdata, false) == true) {
2872  										if (RENONCE(rdata)->stage == RENONCE_STAGE1)
2873  											info->stage1_match++;
2874  
2875  										if (RENONCE(rdata)->stage == RENONCE_STAGE2)
2876  											info->stage2_mismatch++;
2877  
2878  										if (RENONCE(rdata)->stage == RENONCE_STAGE3)
2879  											info->stage3_match++;
2880  									}
2881  								}
2882  								break;
2883  							default:
2884  								applog(LOG_ERR, "%s: renonceworker_thr: invalid renonce stage arrived: [%d]",
2885  										bitfury->drv->name,
2886  										RENONCE(rdata)->stage);
2887  						}
2888  					}
2889  					nonce_list_push(id_list, RENONCE(rdata)->id);
2890  
2891  					if (RENONCE(rdata)->match == true)
2892  						break;
2893  				}
2894  
2895  				rdata = rdata->next;
2896  			}
2897  			L_UNLOCK(info->renonce_list);
2898  
2899  			/* remove nonce from list */
2900  			renoncework_list_pop(info->renoncework_list);
2901  			rnwdata = info->renoncework_list->head;
2902  		}
2903  		L_UNLOCK(info->renoncework_list);
2904  
2905  		L_LOCK(info->renonce_list);
2906  		bf_data_t* rdata = info->renonce_list->head;
2907  		while (rdata != NULL) {
2908  			if (RENONCE(rdata)->match == true) {
2909  				bf_data_t* rndata = rdata->next;
2910  				renonce_list_remove(info->renonce_list, rdata);
2911  				rdata = rndata;
2912  				continue;
2913  			}
2914  
2915  			/* update stage */
2916  			bf_data_t* ndata = id_list->head;
2917  			while (ndata != NULL) {
2918  				if (NONCE(ndata)->nonce == RENONCE(rdata)->id) {
2919  					RENONCE(rdata)->stage++;
2920  					RENONCE(rdata)->sent     = false;
2921  					RENONCE(rdata)->received = false;
2922  					break;
2923  				}
2924  				ndata = ndata->next;
2925  			}
2926  
2927  			/* update tasks with wrong or dup nonces recieved */
2928  			if ((RENONCE(rdata)->stage != RENONCE_STAGE_FINISHED) &&
2929  				(RENONCE(rdata)->received == true)) {
2930  				RENONCE(rdata)->stage++;
2931  				RENONCE(rdata)->sent     = false;
2932  				RENONCE(rdata)->received = false;
2933  			}
2934  
2935  			/* clear renonces list if we are running too slow */
2936  			if ((RENONCE(rdata)->stage >= RENONCE_STAGE2) &&
2937  				(info->renonce_list->count > RENONCE_STAGE2_LIMIT)) {
2938  				info->unmatched++;
2939  				increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2940  				bf_data_t* rndata = rdata->next;
2941  				renonce_list_remove(info->renonce_list, rdata);
2942  				rdata = rndata;
2943  				continue;
2944  			}
2945  
2946  			if ((RENONCE(rdata)->stage >= RENONCE_STAGE3) &&
2947  				(info->renonce_list->count > RENONCE_STAGE3_LIMIT)) {
2948  				info->unmatched++;
2949  				increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2950  				bf_data_t* rndata = rdata->next;
2951  				renonce_list_remove(info->renonce_list, rdata);
2952  				rdata = rndata;
2953  				continue;
2954  			}
2955  
2956  			if ((RENONCE(rdata)->stage == RENONCE_STAGE_FINISHED) &&
2957  				(RENONCE(rdata)->sent == false)) {
2958  				info->unmatched++;
2959  				increase_re_bad_nonces(info, RENONCE(rdata)->src_address);
2960  				bf_data_t* rndata = rdata->next;
2961  				renonce_list_remove(info->renonce_list, rdata);
2962  				rdata = rndata;
2963  				continue;
2964  			}
2965  
2966  			rdata = rdata->next;
2967  		}
2968  		L_UNLOCK(info->renonce_list);
2969  
2970  		/* clear id list */
2971  		bf_data_t* ndata = id_list->head;
2972  		while (ndata != NULL) {
2973  			nonce_list_pop(id_list);
2974  			ndata = id_list->head;
2975  		}
2976  
2977  		gettimeofday(&stop_time, NULL);
2978  
2979  #if 0
2980  		applog(LOG_DEBUG, "%s: renonceworker_thr: nonces processed [%d]: time elapsed: [%.6f]",
2981  				bitfury->drv->name,
2982  				nonce_cnt, timediff(start_time, stop_time));
2983  #endif
2984  
2985  		cgsleep_us(RENONCEWORKER_DELAY);
2986  	}
2987  
2988  	applog(LOG_INFO, "%s: renonceworker_thr: exiting...", bitfury->drv->name);
2989  	return NULL;
2990  }
2991  
2992  int16_t update_pid(bf_pid_t *pid, int16_t error)
2993  {
2994  	int16_t pTerm, iTerm;
2995  
2996  	pTerm = 2 * error;
2997  
2998  	pid->i_state += error;
2999  	if(pid->i_state > pid->i_max)
3000  		pid->i_state = pid->i_max; 
3001  	else if(pid->i_state < pid->i_min)
3002  		pid->i_state = pid->i_min;  
3003  
3004  	iTerm = pid->i_state;
3005  
3006  	return (pTerm + iTerm);
3007  }
3008  
3009  static void *bitfury_hwmonitor(void *userdata)
3010  {
3011  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
3012  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
3013  
3014  	uint8_t board_id, bcm250_id, chip_id;
3015  	time_t curr_time;
3016  
3017  	applog(LOG_INFO, "%s: started hwmonitor thread", bitfury->drv->name);
3018  
3019  	while (bitfury->shutdown == false) {
3020  		if (info->initialised) {
3021  			break;
3022  		}
3023  		cgsleep_us(30);
3024  	}
3025  
3026  	applog(LOG_INFO, "%s: hwmonitor loop started", bitfury->drv->name);
3027  
3028  	while (bitfury->shutdown == false) {
3029  		float max_temp = 0.0;
3030  		float t_alarm = 100.0;
3031  
3032  		bool a_temp = false;
3033  		bool a_ichain = false;
3034  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3035  			/* read hw sensor data */
3036  			char buff[256];
3037  
3038  			if (info->chipboard[board_id].detected == true) {
3039  				memset(buff, 0, sizeof(buff));
3040  				if (device_uart_txrx(board_id + 1, "S", buff) < 0)
3041  					quit(1, "%s: %s() failed to get BOARD%d status",
3042  						bitfury->drv->name, __func__, board_id + 1);
3043  
3044  				if (parse_hwstats(info, board_id, buff) < 0)
3045  					applog(LOG_ERR, "%s: failed to parse hw stats",
3046  							bitfury->drv->name);
3047  
3048  				info->chipboard[board_id].p_chain1 = info->chipboard[board_id].u_chain1 * info->chipboard[board_id].i_chain1;
3049  				info->chipboard[board_id].p_chain2 = info->chipboard[board_id].u_chain2 * info->chipboard[board_id].i_chain2;
3050  
3051  				/* fan power calculation */
3052  				if (info->chipboard[board_id].rpm != 0) {
3053  					if (info->chipboard[board_id].fan_speed > 40)
3054  						info->chipboard[board_id].p_fan = (0.1 + 0.0236 * (info->chipboard[board_id].fan_speed - 40)) *
3055  							(info->chipboard[board_id].u_board + U_LOSS);
3056  					else
3057  						info->chipboard[board_id].p_fan = 1.23;
3058  				} else {
3059  					info->chipboard[board_id].p_fan = 0.0;
3060  				}
3061  
3062  				/* board power calculation */
3063  #ifdef MINER_X5
3064  				float i_board = info->chipboard[board_id].i_chain1;
3065  #endif
3066  
3067  #ifdef MINER_X6
3068  				float i_board = info->chipboard[board_id].i_chain1 + info->chipboard[board_id].i_chain2;
3069  #endif
3070  				info->chipboard[board_id].p_board = ((info->chipboard[board_id].u_board + U_LOSS) * i_board + 2.0 +
3071  						info->chipboard[board_id].p_fan);
3072  
3073  				if (info->chipboard[board_id].a_temp == 1)
3074  					a_temp = true;
3075  
3076  				if ((info->chipboard[board_id].a_ichain1 == 1) ||
3077  					(info->chipboard[board_id].a_ichain2 == 1))
3078  					a_ichain = true;
3079  
3080  				if (max_temp < info->chipboard[board_id].temp)
3081  					max_temp = info->chipboard[board_id].temp;
3082  
3083  				if (t_alarm > info->chipboard[board_id].t_alarm)
3084  					t_alarm = info->chipboard[board_id].t_alarm;
3085  			}
3086  		}
3087   
3088  		/* enable temp alarm */
3089  		if ((a_temp == true) && (info->a_temp == false)) {
3090  			applog(LOG_ERR, "%s: temperature alarm enabled: [%5.1f]!!!",
3091  					bitfury->drv->name, max_temp);
3092  
3093  			/* enable fans to full speed*/
3094  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3095  				if (info->chipboard[board_id].detected == true) {
3096  					if (device_uart_transfer(board_id + 1, "F:100") < 0)
3097  						quit(1, "%s: %s() failed to set BOARD%d fan speed",
3098  								bitfury->drv->name, __func__, board_id + 1);
3099  
3100  					applog(LOG_INFO, "%s: set BOARD%d fan speed to max speed",
3101  							bitfury->drv->name, board_id + 1);
3102  				}
3103  			}
3104  		}
3105  
3106  		/* temp alarm recovery */
3107  		if ((a_temp == false) && (info->a_temp == true)) {
3108  			applog(LOG_ERR, "%s: temperature alarm recovery: [%5.1f]",
3109  					bitfury->drv->name, max_temp);
3110  
3111  			/* restore fans speed */
3112  			set_fan_speed(bitfury);
3113  
3114  			reinit_x5(info, false);
3115  		}
3116  
3117  		/* enable power chain alarm */
3118  		if ((a_ichain == true) && (info->a_ichain == false)) {
3119  			applog(LOG_ERR, "%s: power chain alarm enabled!!!",
3120  					bitfury->drv->name);
3121  			info->ialarm_start = time(NULL);
3122  		}
3123  
3124  		/* power chain alarm recovery */
3125  		if ((a_ichain == false) && (info->a_ichain == true)) {
3126  			if (info->ialarm_count > 1) {
3127  				applog(LOG_ERR, "%s: power chain alarm recovery",
3128  						bitfury->drv->name);
3129  
3130  				info->ialarm_count  = 1;
3131  				info->ialarm_buzzer = false;
3132  				info->ialarm_start  = time(NULL);
3133  
3134  				reinit_x5(info, false);
3135  			}
3136  		}
3137  
3138  		info->a_temp   = a_temp;
3139  		info->a_ichain = a_ichain;
3140  
3141  		if (info->a_temp == true)
3142  			applog(LOG_ERR, "%s: ALARM: board temp: [%5.1f] alarm temp: [%5.1f]",
3143  					bitfury->drv->name, max_temp, t_alarm);
3144  
3145  		if (info->a_ichain == true) {
3146  			curr_time = time(NULL);
3147  
3148  			if (curr_time - info->ialarm_start >= info->ialarm_count * ICHAIN_ALARM_INTERVAL) {
3149  				info->ialarm_count *= 2;
3150  				info->ialarm_start = curr_time;
3151  
3152  				/* enable power chain */
3153  				for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3154  					enable_power_chain(bitfury, board_id, 0);
3155  #ifdef MINER_X5
3156  					info->chipboard[board_id].power_enable_time = curr_time;
3157  #endif
3158  #ifdef MINER_X6
3159  					info->chipboard[board_id].power1_enable_time = curr_time;
3160  					info->chipboard[board_id].power2_enable_time = curr_time;
3161  #endif
3162  				}
3163  			}
3164  		} else if (opt_bf16_power_management_disabled == false) {
3165  			if (info->a_net == true) {
3166  				/* disable power chain if no internet available */
3167  				for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3168  					if (info->chipboard[board_id].detected == true) {
3169  #ifdef MINER_X5
3170  						if (info->chipboard[board_id].p_chain1_enabled == 1) {
3171  #endif
3172  #ifdef MINER_X6
3173  						if ((info->chipboard[board_id].p_chain1_enabled == 1) ||
3174  							(info->chipboard[board_id].p_chain2_enabled == 1)) {
3175  #endif
3176  							disable_power_chain(bitfury, board_id, 0);
3177  						}
3178  					}
3179  				}
3180  			} else {
3181  				/* enable power chain - internet recovery */
3182  				bool recovery = false;
3183  				for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3184  					if (info->chipboard[board_id].detected == true) {
3185  #ifdef MINER_X5
3186  						if ((info->chipboard[board_id].p_chain1_enabled == 0) &&
3187  							(info->chipboard[board_id].power_disabled == false)) {
3188  							enable_power_chain(bitfury, board_id, 0);
3189  							info->chipboard[board_id].power_enable_time = time(NULL);
3190  
3191  							/* wait for power chain to enable */
3192  							cgsleep_us(POWER_WAIT_INTERVAL);
3193  
3194  							reinit_x5(info, false);
3195  						}
3196  #endif
3197  
3198  #ifdef MINER_X6
3199  						if ((info->chipboard[board_id].p_chain1_enabled == 0) &&
3200  							(info->chipboard[board_id].power1_disabled == false)){
3201  							enable_power_chain(bitfury, board_id, 1);
3202  							info->chipboard[board_id].power1_enable_time = time(NULL);
3203  							recovery = true;
3204  						}
3205  
3206  						if ((info->chipboard[board_id].p_chain2_enabled == 0) &&
3207  							(info->chipboard[board_id].power2_disabled == false)) {
3208  							enable_power_chain(bitfury, board_id, 2);
3209  							info->chipboard[board_id].power2_enable_time = time(NULL);
3210  							recovery = true;
3211  						}
3212  #endif
3213  					}
3214  				}
3215  
3216  				/* reinit chips on alarm recovery */
3217  				if (recovery == true) {
3218  					/* wait for power chain to enable */
3219  					cgsleep_us(POWER_WAIT_INTERVAL);
3220  
3221  					reinit_x5(info, false);
3222  				}
3223  			}
3224  		}
3225  
3226  		/* board temperature regulation */
3227  		char uart_cmd[8];
3228  		if (manual_pid_enabled == false) {
3229  			sprintf(uart_cmd, "N:%d", (int)max_temp);
3230  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3231  				if (info->chipboard[board_id].detected == true) {
3232  					if (device_uart_transfer(board_id + 1, uart_cmd) < 0)
3233  						quit(1, "%s: %s() failed to set BOARD%d next temp",
3234  								bitfury->drv->name, __func__, board_id + 1);
3235  
3236  					applog(LOG_INFO, "%s: set BOARD%d next temp to [%5.1f]",
3237  							bitfury->drv->name, board_id + 1, max_temp);
3238  				}
3239  			}
3240  		} else {
3241  			uint8_t max_fan_speed = 0;
3242  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3243  				if (info->chipboard[board_id].detected == true) {
3244  					uint16_t pid_temp = 10 * info->chipboard[board_id].temp;
3245  					if (10 * max_temp > pid_temp)
3246  						pid_temp = 10 * max_temp;
3247  
3248  					int16_t fan_speed = update_pid(&info->chipboard[board_id].pid,
3249  							(pid_temp - 10 * info->chipboard[board_id].target_temp) / 10);
3250  
3251  					if (fan_speed > 100)
3252  						fan_speed = 100;
3253  					else if (fan_speed < 0)
3254  						fan_speed = 0;
3255  
3256  					if (max_fan_speed < fan_speed)
3257  						max_fan_speed = fan_speed;
3258  				}
3259  			}
3260  
3261  			sprintf(uart_cmd, "F:%d", max_fan_speed);
3262  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3263  				if (info->chipboard[board_id].detected == true) {
3264  					if (device_uart_transfer(board_id + 1, uart_cmd) < 0)
3265  						quit(1, "%s: %s() failed to set BOARD%d fan speed",
3266  								bitfury->drv->name, __func__, board_id + 1);
3267  
3268  					applog(LOG_INFO, "%s: set BOARD%d fan speed to [%d]",
3269  							bitfury->drv->name, board_id + 1, max_fan_speed);
3270  				}
3271  			}
3272  		}
3273  
3274  		/* board power management */
3275  		if (opt_bf16_power_management_disabled == false) {
3276  			curr_time = time(NULL);
3277  
3278  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3279  				if (info->chipboard[board_id].detected == true) {
3280  #ifdef MINER_X5
3281  					uint8_t disabled_chips = 0;
3282  					uint8_t total_chips  = 0;
3283  #endif
3284  
3285  #ifdef MINER_X6
3286  					uint8_t disabled_chips_chain1 = 0;
3287  					uint8_t total_chips_chain1  = 0;
3288  					uint8_t disabled_chips_chain2 = 0;
3289  					uint8_t total_chips_chain2  = 0;
3290  #endif
3291  					for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
3292  						uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
3293  						uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
3294  
3295  						/* chips loop */
3296  						for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
3297  #ifdef MINER_X5
3298  							total_chips++;
3299  
3300  							if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status == DISABLED)
3301  								disabled_chips++;
3302  #endif
3303  
3304  #ifdef MINER_X6
3305  							if (bcm250_id < BCM250_NUM / 2) {
3306  								total_chips_chain1++;
3307  
3308  								if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status == DISABLED)
3309  									disabled_chips_chain1++;
3310  							}
3311  
3312  							if ((bcm250_id >= BCM250_NUM / 2) && (bcm250_id < BCM250_NUM)) {
3313  								total_chips_chain2++;
3314  
3315  								if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status == DISABLED)
3316  									disabled_chips_chain2++;
3317  							}
3318  #endif
3319  						}
3320  					}
3321  
3322  #ifdef MINER_X5
3323  					/* disable chain power if all chips failed */
3324  					if ((total_chips == disabled_chips) &&
3325  						(info->chipboard[board_id].p_chain1_enabled == 1)) {
3326  						disable_power_chain(bitfury, board_id, 0);
3327  
3328  						/* increase disable counter until we reach long enough work time */
3329  						time_t work_interval = curr_time - info->chipboard[board_id].power_enable_time;
3330  						if (work_interval < CHAIN_WORK_INTERVAL)
3331  							info->chipboard[board_id].power_disable_count *= 2;
3332  
3333  						info->chipboard[board_id].power_disabled     = true;
3334  						info->chipboard[board_id].power_disable_time = curr_time;
3335  						info->chipboard[board_id].chips_disabled     = info->chipboard[board_id].chips_num;
3336  					}
3337  
3338  					/* enable disabled chain */
3339  					if ((info->chipboard[board_id].p_chain1_enabled == 0) &&
3340  					    (info->chipboard[board_id].power_disabled == true) &&
3341  					    (curr_time - info->chipboard[board_id].power_disable_time >= info->chipboard[board_id].power_disable_count * CHAIN_REENABLE_INTERVAL)) {
3342  						time_t disable_interval = curr_time - info->chipboard[board_id].power_disable_time;
3343  						info->chipboard[board_id].power_disable_time = curr_time;
3344  						info->chipboard[board_id].chips_disabled     = 0;
3345  
3346  						enable_power_chain(bitfury, board_id, 0);
3347  						info->chipboard[board_id].power_enable_time = curr_time;
3348  						info->chipboard[board_id].power_disabled    = false;
3349  
3350  						/* wait for power chain to enable */
3351  						cgsleep_us(POWER_WAIT_INTERVAL);
3352  
3353  						reinit_x5(info, true);
3354  						applog(LOG_NOTICE, "%s: reenabled power on BOARD%d: time interval [%d]",
3355  								bitfury->drv->name,
3356  								board_id + 1, (int)disable_interval);
3357  #ifdef FILELOG
3358  						filelog(info, "%s: reenabled power on BOARD%d: time interval [%d]",
3359  								bitfury->drv->name,
3360  								board_id + 1, (int)disable_interval);
3361  #endif
3362  					}
3363  #endif
3364  
3365  #ifdef MINER_X6
3366  					/* disable power on chain 1 only if chips on both chains failed
3367  					 * as chain 2 data channel depends on chain 1                    */
3368  					if ((total_chips_chain1 == disabled_chips_chain1) &&
3369  						(info->chipboard[board_id].p_chain1_enabled == 1) &&
3370  						(info->chipboard[board_id].power2_disabled == true)) {
3371  						disable_power_chain(bitfury, board_id, 0);
3372  
3373  						/* increase disable counter until we reach long enough work time */
3374  						time_t work_interval = curr_time - info->chipboard[board_id].power1_enable_time;
3375  						if (work_interval < CHAIN_WORK_INTERVAL)
3376  							info->chipboard[board_id].power1_disable_count *= 2;
3377  
3378  						info->chipboard[board_id].power1_disabled     = true;
3379  						info->chipboard[board_id].power2_disabled     = true;
3380  						info->chipboard[board_id].power1_disable_time = curr_time;
3381  						info->chipboard[board_id].power2_disable_time = curr_time;
3382  						info->chipboard[board_id].chips_disabled      = info->chipboard[board_id].chips_num;
3383  					} else
3384  					if ((total_chips_chain2 == disabled_chips_chain2) &&
3385  						(info->chipboard[board_id].p_chain2_enabled == 1)) {
3386  						disable_power_chain(bitfury, board_id, 2);
3387  						
3388  						/* increase disable counter until we reach long enough work time */
3389  						time_t work_interval = curr_time - info->chipboard[board_id].power2_enable_time;
3390  						if (work_interval < CHAIN_WORK_INTERVAL)
3391  							info->chipboard[board_id].power2_disable_count *= 2;
3392  
3393  						info->chipboard[board_id].power2_disabled     = true;
3394  						info->chipboard[board_id].power2_disable_time = curr_time;
3395  						info->chipboard[board_id].chips_disabled      = info->chipboard[board_id].chips_num / 2;
3396  					}
3397  
3398  					/* HW FIX: try to reenable disabled chain */
3399  					if ((info->chipboard[board_id].p_chain1_enabled == 0) &&
3400  					    (info->chipboard[board_id].power1_disabled == true) &&
3401  					    (curr_time - info->chipboard[board_id].power1_disable_time >= info->chipboard[board_id].power1_disable_count * CHAIN_REENABLE_INTERVAL)) {
3402  						time_t disable_interval = curr_time - info->chipboard[board_id].power1_disable_time;
3403  						info->chipboard[board_id].power1_disable_time = curr_time;
3404  						info->chipboard[board_id].power2_disable_time = curr_time;
3405  						info->chipboard[board_id].chips_disabled      = 0;
3406  
3407  						enable_power_chain(bitfury, board_id, 0);
3408  						info->chipboard[board_id].power1_enable_time = curr_time;
3409  						info->chipboard[board_id].power2_enable_time = curr_time;
3410  						info->chipboard[board_id].power1_disabled    = false;
3411  						info->chipboard[board_id].power2_disabled    = false;
3412  
3413  						/* wait for power chain to enable */
3414  						cgsleep_us(POWER_WAIT_INTERVAL);
3415  
3416  						reinit_x5(info, true);
3417  						applog(LOG_NOTICE, "%s: reenabled power on BOARD%d: time interval [%d]",
3418  								bitfury->drv->name,
3419  								board_id + 1, (int)disable_interval);
3420  #ifdef FILELOG
3421  						filelog(info, "%s: reenabled power on BOARD%d: time interval [%d]",
3422  								bitfury->drv->name,
3423  								board_id + 1, (int)disable_interval);
3424  #endif
3425  
3426  					} else
3427  					if ((info->chipboard[board_id].p_chain2_enabled == 0) &&
3428  					    (info->chipboard[board_id].power2_disabled == true) &&
3429  					    (curr_time - info->chipboard[board_id].power2_disable_time >= info->chipboard[board_id].power2_disable_count * CHAIN_REENABLE_INTERVAL)) {
3430  						time_t disable_interval = curr_time - info->chipboard[board_id].power2_disable_time;
3431  						info->chipboard[board_id].power2_disable_time = curr_time;
3432  						info->chipboard[board_id].chips_disabled      = 0;
3433  
3434  						enable_power_chain(bitfury, board_id, 2);
3435  						info->chipboard[board_id].power2_enable_time = curr_time;
3436  						info->chipboard[board_id].power2_disabled    = false;
3437  
3438  						/* wait for power chain to enable */
3439  						cgsleep_us(POWER_WAIT_INTERVAL);
3440  
3441  						reinit_x5(info, true);
3442  						applog(LOG_NOTICE, "%s: reenabled chainboard 2 on BOARD%d: time interval [%d]",
3443  								bitfury->drv->name,
3444  								board_id + 1, (int)disable_interval);
3445  #ifdef FILELOG
3446  						filelog(info, "%s: reenabled chainboard 2 on BOARD%d: time interval [%d]",
3447  								bitfury->drv->name,
3448  								board_id + 1, (int)disable_interval);
3449  #endif
3450  					}
3451  #endif
3452  					/* switch renonce chip to next board */
3453  					if ((info->renonce_chips == 1) &&
3454  						(renonce_chip_address[board_id].board_id == board_id) &&
3455  #ifdef MINER_X5
3456  						(info->chipboard[board_id].power_disabled == true)) {
3457  #endif
3458  #ifdef MINER_X6
3459  						(info->chipboard[board_id].power1_disabled == true) &&
3460  						(info->chipboard[board_id].power2_disabled == true)) {
3461  #endif
3462  						uint8_t next_board_id  = (board_id + 1) % CHIPBOARD_NUM;
3463  						uint8_t next_bcm250_id = renonce_chip_address[board_id].bcm250_id;
3464  						uint8_t next_chip_id   = renonce_chip_address[board_id].chip_id;
3465  
3466  						/* board id should be set last */
3467  						renonce_chip_address[next_board_id].bcm250_id = next_bcm250_id;
3468  						renonce_chip_address[next_board_id].chip_id   = next_chip_id;
3469  						renonce_chip_address[next_board_id].board_id  = next_board_id;
3470  
3471  						info->chipboard[next_board_id].bcm250[next_bcm250_id].chips[next_chip_id].status = UNINITIALIZED;
3472  
3473  						applog(LOG_NOTICE, "%s: changed renonce chip address to: [%d:%d:%2d]",
3474  								bitfury->drv->name,
3475  								next_board_id, next_bcm250_id, next_chip_id);
3476  
3477  						renonce_chip_address[board_id].board_id  = -1;
3478  						renonce_chip_address[board_id].bcm250_id = -1;
3479  						renonce_chip_address[board_id].chip_id   = -1;
3480  					}
3481  				}
3482  			}
3483  		}
3484  
3485  		cgsleep_us(HWMONITOR_DELAY);
3486  	}
3487  
3488  	applog(LOG_INFO, "%s: hwmonitor_thr: exiting...", bitfury->drv->name);
3489  	return NULL;
3490  }
3491  
3492  static void *bitfury_alarm(void *userdata)
3493  {
3494  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
3495  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
3496  
3497  	struct pool *pool;
3498  	int i;
3499  	time_t curr_time_t;
3500  	struct timeval curr_time;
3501  
3502  	applog(LOG_INFO, "%s: started alarm thread", bitfury->drv->name);
3503  
3504  	/* blink lamps once */
3505  	led_red_enable(info);
3506  	led_green_enable(info);
3507  
3508  	cgsleep_ms(1000);
3509  
3510  	led_red_disable(info);
3511  	led_green_disable(info);
3512  	buzzer_disable(info);
3513  
3514  	applog(LOG_INFO, "%s: alarm loop started", bitfury->drv->name);
3515  
3516  	while (bitfury->shutdown == false) {
3517  		curr_time_t = time(NULL);
3518  		gettimeofday(&curr_time, NULL);
3519  		/* check if there are enabled pools present */
3520  		bool idle = true;
3521  		for (i = 0; i < total_pools; i++) {
3522  			pool = pools[i];
3523  			if (pool->idle == false)
3524  				idle = false;
3525  		}
3526  
3527  		if (idle == true)
3528  			info->a_net = true;
3529  		else
3530  			info->a_net = false;
3531  
3532  		/* temperature alarm processing */
3533  		if ((info->a_temp == true) && (info->a_ichain == false)) {
3534  			if (timediff_us(info->led_red_switch, curr_time) >= LED_RED_INTERVAL) {
3535  				if (info->led_red_enabled == true)
3536  					led_red_disable(info);
3537  				else
3538  					led_red_enable(info);
3539  			}
3540  
3541  			/* enable buzzer */
3542  			if (timediff_us(info->buzzer_switch, curr_time) >= BUZZER_INTERVAL) {
3543  				if (info->buzzer_enabled == true)
3544  					buzzer_disable(info);
3545  				else
3546  					buzzer_enable(info);
3547  			}
3548  		} else if ((info->a_ichain == false) && (info->a_net == false)) {
3549  			if (info->led_red_enabled == true)
3550  				led_red_disable(info);
3551  
3552  			if (info->buzzer_enabled == true)
3553  				buzzer_disable(info);
3554  		}
3555  
3556  		/* power chain alarm processing */
3557  		if ((info->a_ichain == true) && (info->a_temp == false)) {
3558  			if (timediff_us(info->led_red_switch, curr_time) >= LED_RED_INTERVAL) {
3559  				if (info->led_red_enabled == true)
3560  					led_red_disable(info);
3561  				else
3562  					led_red_enable(info);
3563  			}
3564  
3565  			if (info->ialarm_buzzer == false) {
3566  				buzzer_enable(info);
3567  				cgsleep_ms(1000);
3568  				buzzer_disable(info);
3569  
3570  				info->ialarm_buzzer = true;
3571  			}
3572  
3573  			/* enable buzzer */
3574  			if (curr_time_t - info->ialarm_start >= info->ialarm_count * ICHAIN_ALARM_INTERVAL) {
3575  				buzzer_enable(info);
3576  				cgsleep_ms(1000);
3577  				buzzer_disable(info);
3578  			}
3579  		} else if ((info->a_temp == false) && (info->a_net == false)) {
3580  			if (info->led_red_enabled == true)
3581  				led_red_disable(info);
3582  
3583  			if (info->buzzer_enabled == true)
3584  				buzzer_disable(info);
3585  		}
3586  
3587  		/* blink green lamp if there are enabled pools present and no alarms active */
3588  		if ((info->a_net == false) && (info->a_temp == false) && (info->a_ichain == false)) {
3589  			if (info->led_red_enabled == true)
3590  				led_red_disable(info);
3591  
3592  			if (timediff_us(info->led_green_switch, curr_time) >= LED_GREEN_INTERVAL) {
3593  				if (info->led_green_enabled == true)
3594  					led_green_disable(info);
3595  				else
3596  					led_green_enable(info);
3597  			}
3598  		} else {
3599  			if (info->led_green_enabled == true)
3600  				led_green_disable(info);
3601  
3602  			if ((info->a_temp == false) && (info->a_ichain == false)) {
3603  				if (timediff_us(info->led_red_switch, curr_time) >= LED_RED_NET_INTERVAL) {
3604  					if (info->led_red_enabled == true)
3605  						led_red_disable(info);
3606  					else
3607  						led_red_enable(info);
3608  				}
3609  			}
3610  		}
3611  
3612  		cgsleep_us(ALARM_DELAY);
3613  	}
3614  
3615  	led_red_disable(info);
3616  	led_green_disable(info);
3617  	buzzer_disable(info);
3618  
3619  	applog(LOG_INFO, "%s: alarm_thr: exiting...", bitfury->drv->name);
3620  	return NULL;
3621  }
3622  
3623  static void *bitfury_statistics(void *userdata)
3624  {
3625  	struct cgpu_info *bitfury = (struct cgpu_info *)userdata;
3626  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
3627  
3628  	struct timeval start_time, stop_time;
3629  	uint8_t board_id, bcm250_id, chip_id;
3630  
3631  	float u_board;
3632  	float i_total;
3633  	float p_total;
3634  	float u_chip;
3635  	float p_chip;
3636  
3637  	time_t time0 = time(NULL);
3638  	time_t time1 = time(NULL);
3639  	time_t time2;
3640  
3641  	/* statistics calculation loop */
3642  	while (bitfury->shutdown == false) {
3643  		time2 = time(NULL);
3644  		if (time2 - time1 >= AVG_TIME_DELTA) {
3645  			gettimeofday(&start_time, NULL);
3646  
3647  			u_board = 0.0;
3648  			i_total = 0.0;
3649  			p_total = 0.0;
3650  			u_chip  = 0.0;
3651  			p_chip  = 0.0;
3652  
3653  			info->chips_failed     = 0;
3654  			info->chips_disabled   = 0;
3655  
3656  			for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
3657  				if (info->chipboard[board_id].detected == true) {
3658  					info->chipboard[board_id].chips_failed = 0;
3659  					info->chips_disabled += info->chipboard[board_id].chips_disabled;
3660  
3661  					/* concentrator loop */
3662  					for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
3663  						uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
3664  						uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
3665  
3666  						info->chipboard[board_id].bcm250[bcm250_id].chips_failed = 0;
3667  
3668  						/* chips loop */
3669  						for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++) {
3670  
3671  							if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status >= FAILING) {
3672  								info->chipboard[board_id].bcm250[bcm250_id].chips_failed++;
3673  								info->chipboard[board_id].chips_failed++;
3674  								info->chips_failed++;
3675  							}
3676  
3677  							if (opt_bf16_stats_enabled) {
3678  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch,
3679  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch_dx,
3680  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3681  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd,
3682  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_dx,
3683  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3684  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none,
3685  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none_dx,
3686  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3687  
3688  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces,
3689  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_dx,
3690  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3691  
3692  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate,
3693  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_dx,
3694  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3695  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_good,
3696  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_good_dx,
3697  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3698  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_diff,
3699  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_diff_dx,
3700  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3701  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_bad,
3702  										   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_bad_dx,
3703  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3704  
3705  								if (opt_bf16_renonce != RENONCE_DISABLED) {
3706  									get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_re,
3707  											   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_dx,
3708  											   (float)(time2 - time1), AVG_TIME_INTERVAL);
3709  									get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_re_good,
3710  											   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_good_dx,
3711  											   (float)(time2 - time1), AVG_TIME_INTERVAL);
3712  									get_average(&info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_re_bad,
3713  											   (float)info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_bad_dx,
3714  											   (float)(time2 - time1), AVG_TIME_INTERVAL);
3715  								}
3716  							}
3717  
3718  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch_dx     = 0;
3719  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_dx      = 0;
3720  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none_dx = 0;
3721  
3722  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_dx      = 0;
3723  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_good_dx = 0;
3724  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_diff_dx = 0;
3725  							info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_bad_dx  = 0;
3726  
3727  							if (opt_bf16_renonce != RENONCE_DISABLED) {
3728  								info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_dx      = 0;
3729  								info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_good_dx = 0;
3730  								info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces_re_bad_dx  = 0;
3731  							}
3732  
3733  							if (opt_bf16_stats_enabled) {
3734  								if (opt_bf16_renonce != RENONCE_DISABLED)
3735  									applog(LOG_NOTICE, "STATS: chp [%d:%d:%2d], tsk/s [%4.0f], "
3736  											"ncs/s [%4.0f], sts/s [%3.0f], none/s [%3.0f], hr/s [%8.3f] hr+/s [%8.3f] rhr/s [%8.3f]",
3737  											board_id, bcm250_id, chip_id,
3738  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch,
3739  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces,
3740  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd,
3741  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none,
3742  											CHIP_COEFF * info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate,
3743  											CHIP_COEFF * info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_good,
3744  											CHIP_COEFF * (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_good +
3745  											              info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_re_good));
3746  								else
3747  									applog(LOG_NOTICE, "STATS: chp [%d:%d:%2d], tsk/s [%4.0f], "
3748  											"ncs/s [%3.0f], sts/s [%3.0f], none/s [%3.0f], hr/s [%8.3f] hr+/s [%8.3f]",
3749  											board_id, bcm250_id, chip_id,
3750  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].task_switch,
3751  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].nonces,
3752  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd,
3753  											info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status_cmd_none,
3754  											CHIP_COEFF * info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate,
3755  											CHIP_COEFF * info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].hashrate_good);
3756  							}
3757  						}
3758  
3759  						if (opt_bf16_stats_enabled) {
3760  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].task_switch,
3761  									   (float)info->chipboard[board_id].bcm250[bcm250_id].task_switch_dx,
3762  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3763  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].status_cmd,
3764  									   (float)info->chipboard[board_id].bcm250[bcm250_id].status_cmd_dx,
3765  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3766  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].status_cmd_none,
3767  									   (float)info->chipboard[board_id].bcm250[bcm250_id].status_cmd_none_dx,
3768  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3769  
3770  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].nonces,
3771  									   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_dx,
3772  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3773  
3774  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate,
3775  									   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_dx,
3776  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3777  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_good,
3778  									   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_good_dx,
3779  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3780  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_diff,
3781  									   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_diff_dx,
3782  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3783  							get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_bad,
3784  									   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_bad_dx,
3785  									   (float)(time2 - time1), AVG_TIME_INTERVAL);
3786  
3787  							if (opt_bf16_renonce != RENONCE_DISABLED) {
3788  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_re,
3789  										   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_re_dx,
3790  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3791  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_re_good,
3792  										   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_re_good_dx,
3793  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3794  								get_average(&info->chipboard[board_id].bcm250[bcm250_id].hashrate_re_bad,
3795  										   (float)info->chipboard[board_id].bcm250[bcm250_id].nonces_re_bad_dx,
3796  										   (float)(time2 - time1), AVG_TIME_INTERVAL);
3797  							}
3798  						}
3799  
3800  						info->chipboard[board_id].bcm250[bcm250_id].task_switch_dx     = 0;
3801  						info->chipboard[board_id].bcm250[bcm250_id].status_cmd_dx      = 0;
3802  						info->chipboard[board_id].bcm250[bcm250_id].status_cmd_none_dx = 0;
3803  
3804  						info->chipboard[board_id].bcm250[bcm250_id].nonces_dx      = 0;
3805  						info->chipboard[board_id].bcm250[bcm250_id].nonces_good_dx = 0;
3806  						info->chipboard[board_id].bcm250[bcm250_id].nonces_diff_dx = 0;
3807  						info->chipboard[board_id].bcm250[bcm250_id].nonces_bad_dx  = 0;
3808  
3809  						if (opt_bf16_renonce != RENONCE_DISABLED) {
3810  							info->chipboard[board_id].bcm250[bcm250_id].nonces_re_dx      = 0;
3811  							info->chipboard[board_id].bcm250[bcm250_id].nonces_re_good_dx = 0;
3812  							info->chipboard[board_id].bcm250[bcm250_id].nonces_re_bad_dx  = 0;
3813  						}
3814  					}
3815  
3816  					if (opt_bf16_stats_enabled) {
3817  						get_average(&info->chipboard[board_id].task_switch,
3818  								   (float)info->chipboard[board_id].task_switch_dx,
3819  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3820  						get_average(&info->chipboard[board_id].status_cmd,
3821  								   (float)info->chipboard[board_id].status_cmd_dx,
3822  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3823  						get_average(&info->chipboard[board_id].status_cmd_none,
3824  								   (float)info->chipboard[board_id].status_cmd_none_dx,
3825  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3826  
3827  						get_average(&info->chipboard[board_id].nonces,
3828  								   (float)info->chipboard[board_id].nonces_dx,
3829  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3830  					}
3831  
3832  					get_average(&info->chipboard[board_id].hashrate,
3833  							   (float)info->chipboard[board_id].nonces_dx,
3834  							   (float)(time2 - time1), AVG_TIME_INTERVAL);
3835  					get_average(&info->chipboard[board_id].hashrate_good,
3836  							   (float)info->chipboard[board_id].nonces_good_dx,
3837  							   (float)(time2 - time1), AVG_TIME_INTERVAL);
3838  					get_average(&info->chipboard[board_id].hashrate_diff,
3839  							   (float)info->chipboard[board_id].nonces_diff_dx,
3840  							   (float)(time2 - time1), AVG_TIME_INTERVAL);
3841  					get_average(&info->chipboard[board_id].hashrate_bad,
3842  							   (float)info->chipboard[board_id].nonces_bad_dx,
3843  							   (float)(time2 - time1), AVG_TIME_INTERVAL);
3844  
3845  					info->chipboard[board_id].task_switch_dx     = 0;
3846  					info->chipboard[board_id].status_cmd_dx      = 0;
3847  					info->chipboard[board_id].status_cmd_none_dx = 0;
3848  
3849  					info->chipboard[board_id].nonces_dx         = 0;
3850  					info->chipboard[board_id].nonces_good_dx    = 0;
3851  					info->chipboard[board_id].nonces_diff_dx    = 0;
3852  					info->chipboard[board_id].nonces_bad_dx     = 0;
3853  
3854  					u_board        += (info->chipboard[board_id].u_board + U_LOSS);
3855  #ifdef MINER_X5
3856  					i_total        += (info->chipboard[board_id].i_chain1);
3857  					u_chip         += (info->chipboard[board_id].u_chain1);
3858  					p_chip         += (info->chipboard[board_id].p_chain1);
3859  #endif
3860  
3861  #ifdef MINER_X6
3862  					i_total        += (info->chipboard[board_id].i_chain1 + info->chipboard[board_id].i_chain2);
3863  					u_chip         += (info->chipboard[board_id].u_chain1 + info->chipboard[board_id].u_chain2);
3864  					p_chip         += (info->chipboard[board_id].p_chain1 + info->chipboard[board_id].p_chain2);
3865  #endif
3866  					p_total        +=  info->chipboard[board_id].p_board;
3867  
3868  					if (opt_bf16_renonce != RENONCE_DISABLED) {
3869  						get_average(&info->chipboard[board_id].hashrate_re,
3870  								   (float)info->chipboard[board_id].nonces_re_dx,
3871  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3872  						get_average(&info->chipboard[board_id].hashrate_re_good,
3873  								   (float)info->chipboard[board_id].nonces_re_good_dx,
3874  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3875  						get_average(&info->chipboard[board_id].hashrate_re_bad,
3876  								   (float)info->chipboard[board_id].nonces_re_bad_dx,
3877  								   (float)(time2 - time1), AVG_TIME_INTERVAL);
3878  
3879  						info->chipboard[board_id].nonces_re_dx      = 0;
3880  						info->chipboard[board_id].nonces_re_good_dx = 0;
3881  						info->chipboard[board_id].nonces_re_bad_dx  = 0;
3882  					}
3883  
3884  					get_average(&info->chipboard[board_id].txrx_speed,
3885  							   (float)info->chipboard[board_id].bytes_transmitted_dx,
3886  							   (float)(time2 - time1), AVG_TIME_INTERVAL);
3887  
3888  					info->chipboard[board_id].bytes_transmitted_dx = 0;
3889  
3890  					if (opt_bf16_stats_enabled) {
3891  						if (opt_bf16_renonce != RENONCE_DISABLED) {
3892  							applog(LOG_NOTICE, "STATS: board [%d] hrate: good: [%8.3f] re_good: [%8.3f] => "
3893  									"[%8.3f] toren: [%8.3f] bad: [%8.3f] total: [%8.3f]",
3894  									board_id,
3895  									CHIP_COEFF * (info->chipboard[board_id].hashrate_good),
3896  									CHIP_COEFF * (info->chipboard[board_id].hashrate_re_good),
3897  									CHIP_COEFF * (info->chipboard[board_id].hashrate_good + info->chipboard[board_id].hashrate_re_good),
3898  									CHIP_COEFF * (info->chipboard[board_id].hashrate - info->chipboard[board_id].hashrate_good),
3899  									CHIP_COEFF * (info->chipboard[board_id].hashrate_bad),
3900  									CHIP_COEFF * (info->chipboard[board_id].hashrate));
3901  						} else {
3902  							applog(LOG_NOTICE, "STATS: board [%d] hrate: good: [%8.3f] "
3903  									"bad: [%8.3f] total: [%8.3f]",
3904  									board_id,
3905  									CHIP_COEFF * (info->chipboard[board_id].hashrate_good),
3906  									CHIP_COEFF * (info->chipboard[board_id].hashrate_bad),
3907  									CHIP_COEFF * (info->chipboard[board_id].hashrate));
3908  						}
3909  
3910  #ifdef MINER_X5
3911  						applog(LOG_NOTICE, "STATS: TX/RX: [%5.3f] Mbit/s UB: [%3.1f] "
3912  								"U1: [%3.1f] I1: [%3.1f] T: [%3.1f] RPM: [%4d] FAN: [%3d]",
3913  								8.0 * info->chipboard[board_id].txrx_speed / 1000000,
3914  								info->chipboard[board_id].u_board + U_LOSS,
3915  								info->chipboard[board_id].u_chain1,
3916  								info->chipboard[board_id].i_chain1,
3917  								info->chipboard[board_id].temp,
3918  								info->chipboard[board_id].rpm,
3919  								info->chipboard[board_id].fan_speed);
3920  #endif
3921  
3922  #ifdef MINER_X6
3923  						applog(LOG_NOTICE, "STATS: TX/RX: [%5.3f] Mbit/s UB: [%3.1f] "
3924  								"U1: [%3.1f] U2: [%3.1f] I1: [%3.1f] I2: [%3.1f] T: [%3.1f] RPM: [%4d] FAN: [%3d]",
3925  								8.0 * info->chipboard[board_id].txrx_speed / 1000000,
3926  								info->chipboard[board_id].u_board + U_LOSS,
3927  								info->chipboard[board_id].u_chain1,
3928  								info->chipboard[board_id].u_chain2,
3929  								info->chipboard[board_id].i_chain1,
3930  								info->chipboard[board_id].i_chain2,
3931  								info->chipboard[board_id].temp,
3932  								info->chipboard[board_id].rpm,
3933  								info->chipboard[board_id].fan_speed);
3934  #endif
3935  
3936  						applog(LOG_NOTICE, "STATS: ver: [%d] fw: [%d] hwid: [%s]",
3937  								info->chipboard[board_id].board_ver,
3938  								info->chipboard[board_id].board_fwver,
3939  								info->chipboard[board_id].board_hwid);
3940  					}
3941  				}
3942  			}
3943  
3944  			if (opt_bf16_stats_enabled) {
3945  				get_average(&info->task_switch,
3946  						   (float)info->task_switch_dx,
3947  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3948  				get_average(&info->status_cmd,
3949  						   (float)info->status_cmd_dx,
3950  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3951  				get_average(&info->status_cmd_none,
3952  						   (float)info->status_cmd_none_dx,
3953  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3954  
3955  				get_average(&info->chipboard[board_id].nonces,
3956  						   (float)info->chipboard[board_id].nonces_dx,
3957  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3958  			}
3959  
3960  			get_average(&info->hashrate,
3961  					   (float)info->nonces_dx,
3962  					   (float)(time2 - time1), AVG_TIME_INTERVAL);
3963  			get_average(&info->hashrate_good,
3964  					   (float)info->nonces_good_dx,
3965  					   (float)(time2 - time1), AVG_TIME_INTERVAL);
3966  			get_average(&info->hashrate_diff,
3967  					   (float)info->nonces_diff_dx,
3968  					   (float)(time2 - time1), AVG_TIME_INTERVAL);
3969  			get_average(&info->hashrate_bad,
3970  					   (float)info->nonces_bad_dx,
3971  					   (float)(time2 - time1), AVG_TIME_INTERVAL);
3972  
3973  			info->task_switch_dx     = 0;
3974  			info->status_cmd_dx      = 0;
3975  			info->status_cmd_none_dx = 0;
3976  
3977  			info->nonces_dx         = 0;
3978  			info->nonces_good_dx    = 0;
3979  			info->nonces_diff_dx    = 0;
3980  			info->nonces_bad_dx     = 0;
3981  
3982  			if (opt_bf16_renonce != RENONCE_DISABLED) {
3983  				get_average(&info->hashrate_re,
3984  						   (float)info->nonces_re_dx,
3985  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3986  				get_average(&info->hashrate_re_good,
3987  						   (float)info->nonces_re_good_dx,
3988  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3989  				get_average(&info->hashrate_re_bad,
3990  						   (float)info->nonces_re_bad_dx,
3991  						   (float)(time2 - time1), AVG_TIME_INTERVAL);
3992  
3993  				info->nonces_re_dx      = 0;
3994  				info->nonces_re_good_dx = 0;
3995  				info->nonces_re_bad_dx  = 0;
3996  			}
3997  
3998  			time1 = time2;
3999  
4000  			gettimeofday(&stop_time, NULL);
4001  
4002  			uint32_t uptime = time2 - time0;
4003  			uint32_t hours  = uptime / 3600;
4004  			uint8_t minutes = (uptime - hours * 3600) / 60;
4005  			uint8_t seconds = uptime - hours * 3600 - minutes * 60;
4006  
4007  			info->u_avg   = u_board / info->active_chipboard_num;
4008  			info->i_total = i_total;
4009  			info->p_total = p_total;
4010  			info->u_chip  = u_chip;
4011  			info->p_chip  = p_chip;
4012  
4013  			if (opt_bf16_stats_enabled) {
4014  				if (opt_bf16_renonce != RENONCE_DISABLED) {
4015  					applog(LOG_NOTICE, "STATS: rencs: [%d] stale: [%d] nws: [%d] rnws: [%d] failed: [%d]",
4016  							info->renonce_list->count,
4017  							info->stale_work_list->count,
4018  							info->noncework_list->count,
4019  							info->renoncework_list->count,
4020  							info->chips_failed);
4021  
4022  					applog(LOG_NOTICE, "STATS: %4.0fGH/s osc: 0x%02x re_osc: 0x%02x "
4023  							"%3.1fV %3.1fA %4.1fW %.3fW/GH",
4024  							CHIP_COEFF * (info->hashrate_good + info->hashrate_re_good),
4025  							bf16_chip_clock,
4026  							bf16_renonce_chip_clock,
4027  							info->u_avg,
4028  							info->i_total,
4029  							info->p_total,
4030  							(info->a_net == true) ?
4031  								0.0 :
4032  								info->p_total / (CHIP_COEFF * (info->hashrate_good + info->hashrate_re_good)));
4033  
4034  					applog(LOG_NOTICE, "STATS: TOTAL: %5.1fGH/s %5.3fV %3.1fA %5.2fW "
4035  							"CHIP: %5.1fGH/s GOOD: %4.1fGH/s RENONCE: %4.1fGH/s BAD: %4.1fGH/s",
4036  							CHIP_COEFF * info->hashrate / (info->chips_num - info->renonce_chips - info->chips_failed),
4037  							info->u_chip / (info->chips_num - info->chips_disabled),
4038  							(info->a_net == true) ? 0.0 : info->p_chip / info->u_chip,
4039  							info->p_chip / (info->chips_num - info->chips_disabled),
4040  							CHIP_COEFF * (info->hashrate_good + info->hashrate_re_good) / (info->chips_num - info->renonce_chips - info->chips_failed),
4041  							CHIP_COEFF * info->hashrate_good / (info->chips_num - info->renonce_chips - info->chips_failed),
4042  							CHIP_COEFF * info->hashrate_re_good / (info->chips_num - info->renonce_chips - info->chips_failed),
4043  							CHIP_COEFF * info->hashrate_re_bad / (info->chips_num - info->renonce_chips - info->chips_failed));
4044  
4045  #if 1
4046  					applog(LOG_NOTICE, "STATS: m0: [%lu] mm0: [%lu] m1: [%lu] mm1: [%lu] m2: [%lu] mm2: [%lu] "
4047  							"m3: [%lu] mm3: [%lu] um: [%lu]",
4048  							info->stage0_match / (time2 - time0),
4049  							info->stage0_mismatch / (time2 - time0),
4050  							info->stage1_match / (time2 - time0),
4051  							info->stage1_mismatch / (time2 - time0),
4052  							info->stage2_match / (time2 - time0),
4053  							info->stage2_mismatch / (time2 - time0),
4054  							info->stage3_match / (time2 - time0),
4055  							info->stage3_mismatch / (time2 - time0),
4056  							info->unmatched / (time2 - time0));
4057  #endif
4058  				} else {
4059  					applog(LOG_NOTICE, "STATS: stale: [%d] nws: [%d]",
4060  							info->stale_work_list->count, info->noncework_list->count);
4061  
4062  					applog(LOG_NOTICE, "STATS: %4.0fGH/s osc: 0x%02x"
4063  							"%3.1fV %3.1fA %4.1fW %.3fW/GH",
4064  							CHIP_COEFF * info->hashrate_good,
4065  							bf16_chip_clock,
4066  							info->u_avg,
4067  							info->i_total,
4068  							info->p_total,
4069  							(info->a_net == true) ?
4070  								0.0 :
4071  								info->p_total / (CHIP_COEFF * info->hashrate_good));
4072  
4073  					applog(LOG_NOTICE, "STATS: TOTAL: %5.1fGH/s %5.3fV %3.1fA %5.2fW "
4074  							"CHIP: %5.1fGH/s GOOD: %4.1fGH/s BAD: %4.1fGH/s",
4075  							CHIP_COEFF * info->hashrate / (info->chips_num - info->chips_failed),
4076  							info->u_chip / (info->chips_num - info->chips_disabled),
4077  							(info->a_net == true) ? 0.0 : info->p_chip / info->u_chip,
4078  							info->p_chip / (info->chips_num - info->chips_disabled),
4079  							CHIP_COEFF * info->hashrate_good / (info->chips_num - info->chips_failed),
4080  							CHIP_COEFF * info->hashrate_good / (info->chips_num - info->chips_failed),
4081  							CHIP_COEFF * info->hashrate_bad / (info->chips_num - info->chips_failed));
4082  				}
4083  
4084  				applog(LOG_NOTICE, "STATS: uptime: [%4d:%02d:%02d] time elapsed: [%.6f] ",
4085  						hours, minutes, seconds, timediff(start_time, stop_time));
4086  			}
4087  		}
4088  
4089  		cgsleep_us(STATISTICS_DELAY);
4090  	}
4091  
4092  	applog(LOG_INFO, "%s: statistics_thr: exiting...", bitfury->drv->name);
4093  	return NULL;
4094  }
4095  
4096  static bool bitfury16_thread_prepare(struct thr_info *thr)
4097  {
4098  	struct cgpu_info *bitfury = thr->cgpu;
4099  	struct bitfury16_info *info = (struct bitfury16_info *)(bitfury->device_data);
4100  
4101  	info->thr = thr;
4102  
4103  	if (thr_info_create(&(info->chipworker_thr), NULL, bitfury_chipworker, (void *)bitfury)) {
4104  		applog(LOG_ERR, "%s: %s() chipworker thread create failed",
4105  				bitfury->drv->name, __func__);
4106  		return false;
4107  	}
4108  	pthread_detach(info->chipworker_thr.pth);
4109  
4110  	applog(LOG_INFO, "%s: thread prepare: starting chipworker thread", bitfury->drv->name);
4111  
4112  	if (thr_info_create(&(info->nonceworker_thr), NULL, bitfury_nonceworker, (void *)bitfury)) {
4113  		applog(LOG_ERR, "%s: %s() nonceworker thread create failed",
4114  				bitfury->drv->name, __func__);
4115  		return false;
4116  	}
4117  	pthread_detach(info->nonceworker_thr.pth);
4118  
4119  	applog(LOG_INFO, "%s: thread prepare: starting nonceworker thread", bitfury->drv->name);
4120  
4121  	if (opt_bf16_renonce != RENONCE_DISABLED) {
4122  		if (thr_info_create(&(info->renonceworker_thr), NULL, bitfury_renonceworker, (void *)bitfury)) {
4123  			applog(LOG_ERR, "%s: %s() renonceworker thread create failed",
4124  					bitfury->drv->name, __func__);
4125  			return false;
4126  		}
4127  		pthread_detach(info->renonceworker_thr.pth);
4128  
4129  		applog(LOG_INFO, "%s: thread prepare: starting renonceworker thread", bitfury->drv->name);
4130  	}
4131  
4132  	if (thr_info_create(&(info->hwmonitor_thr), NULL, bitfury_hwmonitor, (void *)bitfury)) {
4133  		applog(LOG_ERR, "%s: %s() hwmonitor thread create failed",
4134  				bitfury->drv->name, __func__);
4135  		return false;
4136  	}
4137  	pthread_detach(info->hwmonitor_thr.pth);
4138  
4139  	applog(LOG_INFO, "%s: thread prepare: starting hwmonitor thread", bitfury->drv->name);
4140  
4141  	if (thr_info_create(&(info->alarm_thr), NULL, bitfury_alarm, (void *)bitfury)) {
4142  		applog(LOG_ERR, "%s: %s() alarm thread create failed",
4143  				bitfury->drv->name, __func__);
4144  		return false;
4145  	}
4146  	pthread_detach(info->alarm_thr.pth);
4147  
4148  	applog(LOG_INFO, "%s: thread prepare: starting alarm thread", bitfury->drv->name);
4149  
4150  	if (thr_info_create(&(info->statistics_thr), NULL, bitfury_statistics, (void *)bitfury)) {
4151  		applog(LOG_ERR, "%s: %s() statistics thread create failed",
4152  				bitfury->drv->name, __func__);
4153  		return false;
4154  	}
4155  	pthread_detach(info->statistics_thr.pth);
4156  
4157  	applog(LOG_INFO, "%s: thread prepare: starting statistics thread", bitfury->drv->name);
4158  
4159  	return true;
4160  }
4161  
4162  static int64_t bitfury16_scanwork(struct thr_info *thr)
4163  {
4164  	struct cgpu_info *bitfury = thr->cgpu;
4165  	struct bitfury16_info *info = bitfury->device_data;
4166  	int64_t hashcount = 0;
4167  
4168  	applog(LOG_INFO, "%s: scan work", bitfury->drv->name);
4169  
4170  	mutex_lock(&info->nonces_good_lock);
4171  	if (info->nonces_good_cg) {
4172  		hashcount += 0xffffffffull * info->nonces_good_cg;
4173  		info->nonces_good_cg = 0;
4174  	}
4175  	mutex_unlock(&info->nonces_good_lock);
4176  
4177  	return hashcount;
4178  }
4179  
4180  static void prepare_work(struct cgpu_info *bitfury, struct work *work, bool rolled)
4181  {
4182  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
4183  
4184  	bf_workd_t* wdata = cgmalloc(sizeof(bf_workd_t));
4185  
4186  	wdata->work = work;
4187  	wdata->rolled = rolled;
4188  	wdata->generated = time(NULL);
4189  
4190  	/* generate task payload */
4191  	cg_memcpy(wdata->payload.midstate, work->midstate, 32);
4192  	wdata->payload.m7 = *(uint32_t *)(work->data + 64);
4193  	wdata->payload.ntime = *(uint32_t *)(work->data + 68);
4194  	wdata->payload.nbits = *(uint32_t *)(work->data + 72);
4195  
4196  	workd_list_push(info->work_list, wdata);
4197  }
4198  
4199  static bool bitfury16_queue_full(struct cgpu_info *bitfury)
4200  {
4201  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
4202  	struct work *work, *usework;
4203  	uint16_t need = 0;
4204  	uint16_t generated = 0;
4205  	uint16_t roll, roll_limit;
4206  	bool rolled;
4207  
4208  	if (info->initialised == false) {
4209  		cgsleep_us(30);
4210  		return true;
4211  	}
4212  
4213  	L_LOCK(info->work_list);
4214  	uint16_t work_count = info->work_list->count;
4215  	L_UNLOCK(info->work_list);
4216  	if (work_count < WORK_QUEUE_LEN)
4217  		need = WORK_QUEUE_LEN - work_count;
4218  	else
4219  		return true;
4220  
4221  	/* Ensure we do enough rolling to reduce CPU
4222  	   but dont roll too much to have them end up stale */
4223  	work = get_queued(bitfury);
4224  	if (work) {
4225  		roll_limit = work->drv_rolllimit;
4226  		roll = 0;
4227  
4228  		L_LOCK(info->work_list);
4229  		do {
4230  			if (roll == 0) {
4231  				usework = work;
4232  				rolled = false;
4233  			} else {
4234  				usework = copy_work_noffset(work, roll);
4235  				rolled = true;
4236  			}
4237  
4238  			prepare_work(bitfury, usework, rolled);
4239  			generated++;
4240  		} while ((--need > 0) && (++roll <= roll_limit));
4241  		L_UNLOCK(info->work_list);
4242  
4243  		applog(LOG_INFO, "%s: queue full: generated %d works", bitfury->drv->name, generated);
4244  	} else
4245  		cgsleep_us(30);
4246  
4247  	if (need > 0)
4248  		return false;
4249  	else
4250  		return true;
4251  }
4252  
4253  static void bitfury16_flush_work(struct cgpu_info *bitfury)
4254  {
4255  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
4256  	uint16_t flushed = 0;
4257  
4258  	if (info->initialised == false)
4259  		return;
4260  
4261  	bf_works_t works;
4262  
4263  	/* flush work list */
4264  	L_LOCK(info->work_list);
4265  	L_LOCK(info->stale_work_list);
4266  	bf_data_t* wdata = info->work_list->head;
4267  	while (wdata != NULL) {
4268  		workd_list_push(info->stale_work_list, WORKD(wdata));
4269  		workd_list_remove(info->work_list, &works);
4270  
4271  		wdata = info->work_list->head;
4272  		flushed++;
4273  	}
4274  	L_UNLOCK(info->stale_work_list);
4275  	L_UNLOCK(info->work_list);
4276  
4277  	/* flush nonces list */
4278  	L_LOCK(info->noncework_list);
4279  	bf_data_t* nwdata = info->noncework_list->head;
4280  	while (nwdata != NULL) {
4281  		noncework_list_pop(info->noncework_list);
4282  		nwdata = info->noncework_list->head;
4283  	}
4284  	L_UNLOCK(info->noncework_list);
4285  
4286  	if (opt_bf16_renonce != RENONCE_DISABLED) {
4287  		/* flush renonces list */
4288  		L_LOCK(info->renonce_list);
4289  		bf_data_t* rdata = info->renonce_list->head;
4290  		while (rdata != NULL) {
4291  			renonce_list_pop(info->renonce_list);
4292  			rdata = info->renonce_list->head;
4293  		}
4294  		L_UNLOCK(info->renonce_list);
4295  
4296  		/* flush renoncework list */
4297  		L_LOCK(info->renoncework_list);
4298  		bf_data_t* rnwdata = info->renoncework_list->head;
4299  		while (rnwdata != NULL) {
4300  			renoncework_list_pop(info->renoncework_list);
4301  			rnwdata = info->renoncework_list->head;
4302  		}
4303  		L_UNLOCK(info->renoncework_list);
4304  	}
4305  
4306  	applog(LOG_INFO, "%s: flushed %d works", bitfury->drv->name, flushed);
4307  }
4308  
4309  static struct api_data *bitfury16_api_stats(struct cgpu_info *bitfury)
4310  {
4311  	uint8_t board_id, bcm250_id, chip_id;
4312  	struct bitfury16_info *info = bitfury->device_data;
4313  	char data[128];
4314  	char value[128];
4315  	struct api_data *root = NULL;
4316  
4317  	applog(LOG_INFO, "%s: API stats", bitfury->drv->name);
4318  
4319  	if (info->initialised == false)
4320  		return NULL;
4321  
4322  #ifdef MINER_X5
4323  	root = api_add_string(root, "Device name", "Bitfury X5", true);
4324  #endif
4325  #ifdef MINER_X6
4326  	root = api_add_string(root, "Device name", "Bitfury X6", true);
4327  #endif
4328  	root = api_add_uint8(root, "Boards number", &info->chipboard_num, false);
4329  	root = api_add_uint8(root, "Boards detected", &info->chipboard_num, false);
4330  	root = api_add_uint8(root, "Chips number", &info->chips_num, false);
4331  
4332  	/* software revision chages according to comments in CHANGELOG */
4333  	root = api_add_string(root, "hwv1", "1", true);
4334  	root = api_add_string(root, "hwv2", "2", true);
4335  	root = api_add_string(root, "hwv3", "11", true);
4336  	root = api_add_string(root, "hwv4", "0", true);
4337  	root = api_add_string(root, "hwv5", "0", true);
4338  
4339  	/* U avg */
4340  	sprintf(value, "%.1f", info->u_avg);
4341  	root = api_add_string(root, "U avg", value, true);
4342  
4343  	/* I total */
4344  	sprintf(value, "%.1f", info->i_total);
4345  	root = api_add_string(root, "I total", value, true);
4346  
4347  	/* P total */
4348  	sprintf(value, "%.1f", info->p_total);
4349  	root = api_add_string(root, "P total", value, true);
4350  
4351  	if (opt_bf16_renonce != RENONCE_DISABLED) {
4352  		/* Efficiency */
4353  		sprintf(value, "%.3f",
4354  				(info->a_net == true) ?
4355  					0.0 :
4356  					info->p_total / (CHIP_COEFF * (info->hashrate_good + info->hashrate_re_good)));
4357  		root = api_add_string(root, "Efficiency", value, true);
4358  
4359  		/* Chip GHS total avg */
4360  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate / (info->chips_num - info->renonce_chips - info->chips_failed));
4361  		root = api_add_string(root, "Chip GHS total avg", value, true);
4362  
4363  		/* Chip GHS avg */
4364  		sprintf(value, "%.1f", CHIP_COEFF * (info->hashrate_good + info->hashrate_re_good) / (info->chips_num - info->renonce_chips - info->chips_failed));
4365  		root = api_add_string(root, "Chip GHS avg", value, true);
4366  
4367  		/* Chip GHS good avg */
4368  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_good / (info->chips_num - info->renonce_chips - info->chips_failed));
4369  		root = api_add_string(root, "Chip GHS good avg", value, true);
4370  
4371  		/* Chip GHS re avg */
4372  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_re_good / (info->chips_num - info->renonce_chips - info->chips_failed));
4373  		root = api_add_string(root, "Chip GHS re avg", value, true);
4374  
4375  		/* Chip GHS bad avg */
4376  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_re_bad / (info->chips_num - info->renonce_chips - info->chips_failed));
4377  		root = api_add_string(root, "Chip GHS bad avg", value, true);
4378  	} else {
4379  		/* Efficiency */
4380  		sprintf(value, "%.3f",
4381  				(info->a_net == true) ?
4382  					0.0 :
4383  					info->p_total / (CHIP_COEFF * info->hashrate_good));
4384  		root = api_add_string(root, "Efficiency", value, true);
4385  
4386  		/* Chip GHS total avg */
4387  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate / (info->chips_num - info->chips_failed));
4388  		root = api_add_string(root, "Chip GHS total avg", value, true);
4389  
4390  		/* Chip GHS avg */
4391  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_good / (info->chips_num - info->chips_failed));
4392  		root = api_add_string(root, "Chip GHS avg", value, true);
4393  
4394  		/* Chip GHS good avg */
4395  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_good / (info->chips_num - info->chips_failed));
4396  		root = api_add_string(root, "Chip GHS good avg", value, true);
4397  
4398  		/* Chip GHS re avg */
4399  		sprintf(value, "%.1f", 0.0);
4400  		root = api_add_string(root, "Chip GHS re avg", value, true);
4401  
4402  		/* Chip GHS bad avg */
4403  		sprintf(value, "%.1f", CHIP_COEFF * info->hashrate_bad / (info->chips_num - info->chips_failed));
4404  		root = api_add_string(root, "Chip GHS bad avg", value, true);
4405  	}
4406  
4407  	/* U Chip avg */
4408  	sprintf(value, "%.3f", info->u_chip / (info->chips_num - info->chips_disabled));
4409  	root = api_add_string(root, "U Chip avg", value, true);
4410  
4411  	/* I Chip avg */
4412  	sprintf(value, "%.1f", (info->a_net == true) ? 0.0 : info->p_chip / info->u_chip);
4413  	root = api_add_string(root, "I Chip avg", value, true);
4414  
4415  	/* P Chip avg */
4416  	sprintf(value, "%.2f", info->p_chip / (info->chips_num - info->chips_disabled));
4417  	root = api_add_string(root, "P Chip avg", value, true);
4418  
4419  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
4420  		/* board status */
4421  		sprintf(data, "Board%d detected", board_id);
4422  		if (info->chipboard[board_id].detected == true)
4423  			root = api_add_string(root, data, "1", true);
4424  		else
4425  			root = api_add_string(root, data, "0", true);
4426  
4427  		/* number of concentratord on board */
4428  		sprintf(data, "Board%d BTC250", board_id);
4429  		root = api_add_uint8(root, data, &info->chipboard[board_id].bcm250_num, false);
4430  
4431  		/* number of chips on board */
4432  		sprintf(data, "Board%d BTC16", board_id);
4433  		root = api_add_uint8(root, data, &info->chipboard[board_id].chips_num, false);
4434  
4435  		/* number of good chips on board */
4436  		sprintf(data, "Board%d BTC16 good", board_id);
4437  		uint8_t chips_good = info->chipboard[board_id].chips_num - info->chipboard[board_id].chips_failed;
4438  		root = api_add_uint8(root, data, &chips_good, true);
4439  
4440  		sprintf(data, "Board%d Clock", board_id);
4441  		if (info->chipboard[board_id].detected == true)
4442  			sprintf(value, "%d (0x%02x)", bf16_chip_clock, bf16_chip_clock);
4443  		else
4444  			sprintf(value, "%d (0x%02x)", 0, 0);
4445  
4446  		root = api_add_string(root, data, value, true);
4447  
4448  		sprintf(data, "Board%d GHS av", board_id);
4449  		if (opt_bf16_renonce != RENONCE_DISABLED) {
4450  			sprintf(value, "%.2f",
4451  					CHIP_COEFF * (info->chipboard[board_id].hashrate_good + info->chipboard[board_id].hashrate_re_good));
4452  		} else {
4453  			sprintf(value, "%.2f", CHIP_COEFF * (info->chipboard[board_id].hashrate_good));
4454  		}
4455  		root = api_add_string(root, data, value, true);
4456  
4457  		/* number of chips per concentrator */
4458  		uint8_t i = 0;
4459  		memset(value, 0, sizeof(value));
4460  
4461  		for (bcm250_id = 0; bcm250_id < BCM250_NUM; bcm250_id++) {
4462  			sprintf(data, "Board%d BTC250_%d BTC16", board_id, bcm250_id);
4463  			root = api_add_uint8(root, data, &info->chipboard[board_id].bcm250[bcm250_id].chips_num, false);
4464  
4465  			uint8_t first_good_chip = info->chipboard[board_id].bcm250[bcm250_id].first_good_chip;
4466  			uint8_t last_good_chip  = info->chipboard[board_id].bcm250[bcm250_id].last_good_chip;
4467  
4468  			/* chips loop */
4469  			for (chip_id = first_good_chip; chip_id < last_good_chip; chip_id++, i++) {
4470  				bf_chip_address_t chip_address;
4471  				chip_address.board_id  = board_id;
4472  				chip_address.bcm250_id = bcm250_id;
4473  				chip_address.chip_id   = chip_id;
4474  
4475  				if (info->chipboard[board_id].bcm250[bcm250_id].chips[chip_id].status < FAILING) {
4476  					if ((opt_bf16_renonce != RENONCE_DISABLED) &&
4477  						(renonce_chip(chip_address) == 1))
4478  						value[i] = 'O';
4479  					else
4480  						value[i] = 'o';
4481  				} else {
4482  					if ((opt_bf16_renonce != RENONCE_DISABLED) &&
4483  						(renonce_chip(chip_address) == 1))
4484  						value[i] = 'X';
4485  					else
4486  						value[i] = 'x';
4487  				}
4488  			}
4489  
4490  			if (bcm250_id != BCM250_NUM - 1)
4491  				value[i++] = ' ';
4492  		}
4493  
4494  		sprintf(data, "Board%d BF16 Status", board_id);
4495  		root = api_add_string(root, data, value, true);
4496  
4497  		/* MSP version data */
4498  		/* board version */
4499  		sprintf(data, "Board%d Ver", board_id);
4500  		root = api_add_uint32(root, data, &info->chipboard[board_id].board_ver, false);
4501  
4502  		/* board firmware version */
4503  		sprintf(data, "Board%d FW", board_id);
4504  		root = api_add_uint32(root, data, &info->chipboard[board_id].board_fwver, false);
4505  
4506  		/* board hardware id */
4507  		sprintf(data, "Board%d HWID", board_id);
4508  		root = api_add_string(root, data, info->chipboard[board_id].board_hwid, true);
4509  
4510  		/* MSP hw data */
4511  		/* T */
4512  		sprintf(data, "Board%d T", board_id);
4513  		sprintf(value, "%.1f", info->chipboard[board_id].temp);
4514  		root = api_add_string(root, data, value, true);
4515  
4516  		/* UB */
4517  		sprintf(data, "Board%d UB", board_id);
4518  		sprintf(value, "%.1f", info->chipboard[board_id].u_board);
4519  		root = api_add_string(root, data, value, true);
4520  
4521  		/* P1 */
4522  		sprintf(data, "Board%d P1", board_id);
4523  		root = api_add_uint8(root, data, &info->chipboard[board_id].p_chain1_enabled, false);
4524  
4525  		/* P2 */
4526  		sprintf(data, "Board%d P2", board_id);
4527  		root = api_add_uint8(root, data, &info->chipboard[board_id].p_chain2_enabled, false);
4528  
4529  		/* U1 */
4530  		sprintf(data, "Board%d U1", board_id);
4531  		sprintf(value, "%.1f", info->chipboard[board_id].u_chain1);
4532  		root = api_add_string(root, data, value, true);
4533  
4534  		/* U2 */
4535  		sprintf(data, "Board%d U2", board_id);
4536  		sprintf(value, "%.1f", info->chipboard[board_id].u_chain2);
4537  		root = api_add_string(root, data, value, true);
4538  
4539  		/* I1 */
4540  		sprintf(data, "Board%d I1", board_id);
4541  		sprintf(value, "%.1f", info->chipboard[board_id].i_chain1);
4542  		root = api_add_string(root, data, value, true);
4543  
4544  		/* I2 */
4545  		sprintf(data, "Board%d I2", board_id);
4546  		sprintf(value, "%.1f", info->chipboard[board_id].i_chain2);
4547  		root = api_add_string(root, data, value, true);
4548  
4549  		/* RPM */
4550  		sprintf(data, "Board%d PRM", board_id);
4551  		root = api_add_uint32(root, data, &info->chipboard[board_id].rpm, true);
4552  
4553  		/* A */
4554  		sprintf(data, "Board%d T_Alarm", board_id);
4555  		root = api_add_uint8(root, data, &info->chipboard[board_id].a_temp, true);
4556  
4557  		sprintf(data, "Board%d I1_Alarm", board_id);
4558  		root = api_add_uint8(root, data, &info->chipboard[board_id].a_ichain1, true);
4559  
4560  		sprintf(data, "Board%d I2_Alarm", board_id);
4561  		root = api_add_uint8(root, data, &info->chipboard[board_id].a_ichain2, true);
4562  
4563  		/* F */
4564  		sprintf(data, "Board%d F", board_id);
4565  		root = api_add_uint8(root, data, &info->chipboard[board_id].fan_speed, false);
4566  
4567  		/* AI */
4568  		sprintf(data, "Board%d AI", board_id);
4569  		sprintf(value, "%.1f", info->chipboard[board_id].i_alarm);
4570  		root = api_add_string(root, data, value, true);
4571  
4572  		/* AT */
4573  		sprintf(data, "Board%d AT", board_id);
4574  		sprintf(value, "%.0f", info->chipboard[board_id].t_alarm);
4575  		root = api_add_string(root, data, value, true);
4576  
4577  		/* AG */
4578  		sprintf(data, "Board%d AG", board_id);
4579  		sprintf(value, "%.0f", info->chipboard[board_id].t_gisteresis);
4580  		root = api_add_string(root, data, value, true);
4581  
4582  		/* FM */
4583  		sprintf(data, "Board%d FM", board_id);
4584  #ifdef MINER_X5
4585  		sprintf(value, "%c", info->chipboard[board_id].fan_mode);
4586  #endif
4587  
4588  #ifdef MINER_X6
4589  		if (manual_pid_enabled == true)
4590  			sprintf(value, "A");
4591  		else
4592  			sprintf(value, "%c", info->chipboard[board_id].fan_mode);
4593  #endif
4594  		root = api_add_string(root, data, value, true);
4595  
4596  		/* TT */
4597  		sprintf(data, "Board%d TT", board_id);
4598  		sprintf(value, "%.0f", info->chipboard[board_id].target_temp);
4599  		root = api_add_string(root, data, value, true);
4600  	}
4601  
4602  	return root;
4603  }
4604  
4605  static void bitfury16_shutdown(struct thr_info *thr)
4606  {
4607  	struct cgpu_info *bitfury = thr->cgpu;
4608  	struct bitfury16_info *info = (struct bitfury16_info *)bitfury->device_data;
4609  	uint8_t board_id;
4610  
4611  	bitfury->shutdown = true;
4612  
4613  	cgsleep_ms(300);
4614  
4615  	/* flush next board temp to default value */
4616  	if (manual_pid_enabled == false) {
4617  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
4618  			if (info->chipboard[board_id].detected == true) {
4619  				if (device_uart_transfer(board_id + 1, "N") < 0)
4620  					quit(1, "%s: %s() failed to set BOARD%d next temp",
4621  							bitfury->drv->name, __func__, board_id + 1);
4622  
4623  				applog(LOG_INFO, "%s: set BOARD%d next temp to default value",
4624  						bitfury->drv->name, board_id + 1);
4625  			}
4626  		}
4627  	} else {
4628  		for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
4629  			if (info->chipboard[board_id].detected == true) {
4630  				if (device_uart_transfer(board_id + 1, "F") < 0)
4631  					quit(1, "%s: %s() failed to set BOARD%d fan speed to auto mode",
4632  							bitfury->drv->name, __func__, board_id + 1);
4633  
4634  				applog(LOG_INFO, "%s: set BOARD%d fan speed to auto mode",
4635  						bitfury->drv->name, board_id + 1);
4636  			}
4637  		}
4638  	}
4639  
4640  	/* disable power chain */
4641  	for (board_id = 0; board_id < CHIPBOARD_NUM; board_id++) {
4642  		disable_power_chain(bitfury, board_id, 0);
4643  	}	
4644  
4645  	mutex_destroy(&info->nonces_good_lock);
4646  
4647  	/* close devices */
4648  	close_spi_device(SPI_CHANNEL1);
4649  	close_spi_device(SPI_CHANNEL2);
4650  	close_ctrl_device();
4651  	close_uart_device(UART_CHANNEL1);
4652  	close_uart_device(UART_CHANNEL2);
4653  
4654  #ifdef FILELOG
4655  	filelog(info, "%s: cgminer stopped", bitfury->drv->name);
4656  	fclose(info->logfile);
4657  	mutex_destroy(&info->logfile_mutex);
4658  #endif
4659  
4660  	applog(LOG_INFO, "%s: driver shutdown", bitfury->drv->name);
4661  }
4662  
4663  /* Currently hardcoded to BF1 devices */
4664  struct device_drv bitfury16_drv = {
4665  	.drv_id = DRIVER_bitfury16,
4666  	.dname = "bitfury16",
4667  	.name = "BF16",
4668  	.drv_detect = bitfury16_detect,
4669  	.get_api_stats = bitfury16_api_stats,
4670  	.identify_device = bitfury16_identify,
4671  	.thread_prepare = bitfury16_thread_prepare,
4672  	.hash_work = hash_queued_work,
4673  	.scanwork = bitfury16_scanwork,
4674  	.queue_full = bitfury16_queue_full,
4675  	.flush_work = bitfury16_flush_work,
4676  	.thread_shutdown = bitfury16_shutdown
4677  };