Browse Source

CMR allow sending flash and clock commands

nfactor-troky
Kano 11 years ago
parent
commit
39ac69c14c
  1. 162
      driver-icarus.c

162
driver-icarus.c

@ -180,6 +180,7 @@ static const char *MODE_VALUE_STR = "value";
static const char *MODE_UNKNOWN_STR = "unknown"; static const char *MODE_UNKNOWN_STR = "unknown";
struct ICARUS_INFO { struct ICARUS_INFO {
enum sub_ident ident;
int intinfo; int intinfo;
// time to calculate the golden_ob // time to calculate the golden_ob
@ -217,16 +218,44 @@ struct ICARUS_INFO {
int work_division; int work_division;
int fpga_count; int fpga_count;
uint32_t nonce_mask; uint32_t nonce_mask;
uint8_t cmr2_speed;
bool speed_next_work;
bool flash_next_work;
}; };
#define ICARUS_MIDSTATE_SIZE 32 #define ICARUS_MIDSTATE_SIZE 32
#define ICARUS_UNUSED_SIZE 20 #define ICARUS_UNUSED_SIZE 16
#define ICARUS_WORK_SIZE 12 #define ICARUS_WORK_SIZE 12
#define ICARUS_WORK_DATA_OFFSET 64 #define ICARUS_WORK_DATA_OFFSET 64
#define ICARUS_CMR2_SPEED_FACTOR 2.5
#define ICARUS_CMR2_SPEED_MIN_INT 100
#define ICARUS_CMR2_SPEED_DEF_INT 180
#define ICARUS_CMR2_SPEED_MAX_INT 220
#define CMR2_INT_TO_SPEED(_speed) ((uint8_t)((float)_speed / ICARUS_CMR2_SPEED_FACTOR))
#define ICARUS_CMR2_SPEED_MIN CMR2_INT_TO_SPEED(ICARUS_CMR2_SPEED_MIN_INT)
#define ICARUS_CMR2_SPEED_DEF CMR2_INT_TO_SPEED(ICARUS_CMR2_SPEED_DEF_INT)
#define ICARUS_CMR2_SPEED_MAX CMR2_INT_TO_SPEED(ICARUS_CMR2_SPEED_MAX_INT)
#define ICARUS_CMR2_SPEED_INC 1
#define ICARUS_CMR2_SPEED_DEC -1
#define ICARUS_CMR2_SPEED_FAIL -10
#define ICARUS_CMR2_PREFIX ((uint8_t)0xB7)
#define ICARUS_CMR2_CMD_SPEED ((uint8_t)0)
#define ICARUS_CMR2_CMD_FLASH ((uint8_t)1)
#define ICARUS_CMR2_DATA_FLASH_OFF ((uint8_t)0)
#define ICARUS_CMR2_DATA_FLASH_ON ((uint8_t)1)
#define ICARUS_CMR2_CHECK ((uint8_t)0x6D)
struct ICARUS_WORK { struct ICARUS_WORK {
uint8_t midstate[ICARUS_MIDSTATE_SIZE]; uint8_t midstate[ICARUS_MIDSTATE_SIZE];
// These 4 bytes are for CMR2 bitstreams that handle MHz adjustment
uint8_t check;
uint8_t data;
uint8_t cmd;
uint8_t prefix;
uint8_t unused[ICARUS_UNUSED_SIZE]; uint8_t unused[ICARUS_UNUSED_SIZE];
uint8_t work[ICARUS_WORK_SIZE]; uint8_t work[ICARUS_WORK_SIZE];
}; };
@ -574,8 +603,6 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
break; break;
case IDENT_CMR2: case IDENT_CMR2:
info->Hs = CAIRNSMORE2_HASH_TIME; info->Hs = CAIRNSMORE2_HASH_TIME;
if (info->fpga_count == 2)
info->Hs *= 2;
break; break;
default: default:
quit(1, "Icarus get_options() called with invalid %s ident=%d", quit(1, "Icarus get_options() called with invalid %s ident=%d",
@ -821,7 +848,6 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
int baud, uninitialised_var(work_division), uninitialised_var(fpga_count); int baud, uninitialised_var(work_division), uninitialised_var(fpga_count);
struct cgpu_info *icarus; struct cgpu_info *icarus;
int ret, err, amount, tries, i; int ret, err, amount, tries, i;
enum sub_ident ident;
bool ok; bool ok;
bool cmr2_ok[CAIRNSMORE2_INTS]; bool cmr2_ok[CAIRNSMORE2_INTS];
int cmr2_count; int cmr2_count;
@ -845,8 +871,8 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
quit(1, "Failed to malloc ICARUS_INFO"); quit(1, "Failed to malloc ICARUS_INFO");
icarus->device_data = (void *)info; icarus->device_data = (void *)info;
ident = usb_ident(icarus); info->ident = usb_ident(icarus);
switch (ident) { switch (info->ident) {
case IDENT_ICA: case IDENT_ICA:
case IDENT_BLT: case IDENT_BLT:
case IDENT_LLT: case IDENT_LLT:
@ -867,7 +893,7 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
break; break;
default: default:
quit(1, "%s icarus_detect_one() invalid %s ident=%d", quit(1, "%s icarus_detect_one() invalid %s ident=%d",
icarus->drv->dname, icarus->drv->dname, ident); icarus->drv->dname, icarus->drv->dname, info->ident);
} }
// For CMR2 test each USB Interface // For CMR2 test each USB Interface
@ -894,7 +920,7 @@ cmr2_retry:
if (strncmp(nonce_hex, golden_nonce, 8) == 0) if (strncmp(nonce_hex, golden_nonce, 8) == 0)
ok = true; ok = true;
else { else {
if (tries < 0 && ident != IDENT_CMR2) { if (tries < 0 && info->ident != IDENT_CMR2) {
applog(LOG_ERR, applog(LOG_ERR,
"Icarus Detect: " "Icarus Detect: "
"Test failed at %s: get %s, should: %s", "Test failed at %s: get %s, should: %s",
@ -905,7 +931,7 @@ cmr2_retry:
} }
if (!ok) { if (!ok) {
if (ident != IDENT_CMR2) if (info->ident != IDENT_CMR2)
goto unshin; goto unshin;
if (info->intinfo < CAIRNSMORE2_INTS-1) { if (info->intinfo < CAIRNSMORE2_INTS-1) {
@ -913,7 +939,7 @@ cmr2_retry:
goto cmr2_retry; goto cmr2_retry;
} }
} else { } else {
if (ident == IDENT_CMR2) { if (info->ident == IDENT_CMR2) {
applog(LOG_DEBUG, applog(LOG_DEBUG,
"Icarus Detect: " "Icarus Detect: "
"Test succeeded at %s i%d: got %s", "Test succeeded at %s i%d: got %s",
@ -928,7 +954,7 @@ cmr2_retry:
} }
} }
if (ident == IDENT_CMR2) { if (info->ident == IDENT_CMR2) {
if (cmr2_count == 0) { if (cmr2_count == 0) {
applog(LOG_ERR, applog(LOG_ERR,
"Icarus Detect: Test failed at %s: for all %d CMR2 Interfaces", "Icarus Detect: Test failed at %s: for all %d CMR2 Interfaces",
@ -958,13 +984,16 @@ cmr2_retry:
applog(LOG_INFO, "%s%d: Found at %s", applog(LOG_INFO, "%s%d: Found at %s",
icarus->drv->name, icarus->device_id, icarus->device_path); icarus->drv->name, icarus->device_id, icarus->device_path);
if (ident == IDENT_CMR2) { if (info->ident == IDENT_CMR2) {
applog(LOG_INFO, "%s%d: with %d Interface%s", applog(LOG_INFO, "%s%d: with %d Interface%s",
icarus->drv->name, icarus->device_id, icarus->drv->name, icarus->device_id,
cmr2_count, cmr2_count > 1 ? "s" : ""); cmr2_count, cmr2_count > 1 ? "s" : "");
if (cmr2_count < 3) // Assume 1 or 2 are running FPGA pairs
if (cmr2_count < 3) {
work_division = fpga_count = 2; work_division = fpga_count = 2;
info->Hs /= 2;
}
} }
applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d", applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d",
@ -980,7 +1009,7 @@ cmr2_retry:
set_timing_mode(this_option_offset, icarus); set_timing_mode(this_option_offset, icarus);
if (ident == IDENT_CMR2) { if (info->ident == IDENT_CMR2) {
int i; int i;
for (i = info->intinfo + 1; i < icarus->usbdev->found->intinfo_count; i++) { for (i = info->intinfo + 1; i < icarus->usbdev->found->intinfo_count; i++) {
struct cgpu_info *cgtmp; struct cgpu_info *cgtmp;
@ -1048,6 +1077,45 @@ static bool icarus_prepare(__maybe_unused struct thr_info *thr)
return true; return true;
} }
static void cmr2_command(struct cgpu_info *icarus, uint8_t cmd, uint8_t data)
{
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(icarus->device_data);
struct ICARUS_WORK workdata;
int amount;
memset((void *)(&workdata), 0, sizeof(workdata));
workdata.prefix = ICARUS_CMR2_PREFIX;
workdata.cmd = cmd;
workdata.data = data;
workdata.check = workdata.data ^ workdata.cmd ^ workdata.prefix ^ ICARUS_CMR2_CHECK;
usb_write_ii(icarus, info->intinfo, (char *)(&workdata), sizeof(workdata), &amount, C_SENDWORK);
}
static void cmr2_commands(struct cgpu_info *icarus)
{
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(icarus->device_data);
if (info->speed_next_work) {
info->speed_next_work = false;
cmr2_command(icarus, ICARUS_CMR2_CMD_SPEED, info->cmr2_speed);
return;
}
if (info->flash_next_work) {
info->flash_next_work = false;
cmr2_command(icarus, ICARUS_CMR2_CMD_FLASH, ICARUS_CMR2_DATA_FLASH_ON);
cgsleep_ms(250);
cmr2_command(icarus, ICARUS_CMR2_CMD_FLASH, ICARUS_CMR2_DATA_FLASH_OFF);
cgsleep_ms(250);
cmr2_command(icarus, ICARUS_CMR2_CMD_FLASH, ICARUS_CMR2_DATA_FLASH_ON);
cgsleep_ms(250);
cmr2_command(icarus, ICARUS_CMR2_CMD_FLASH, ICARUS_CMR2_DATA_FLASH_OFF);
return;
}
}
static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
__maybe_unused int64_t max_nonce) __maybe_unused int64_t max_nonce)
{ {
@ -1086,6 +1154,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
rev((void *)(&(workdata.midstate)), ICARUS_MIDSTATE_SIZE); rev((void *)(&(workdata.midstate)), ICARUS_MIDSTATE_SIZE);
rev((void *)(&(workdata.work)), ICARUS_WORK_SIZE); rev((void *)(&(workdata.work)), ICARUS_WORK_SIZE);
if (info->speed_next_work || info->flash_next_work)
cmr2_commands(icarus);
// We only want results for the work we are about to send // We only want results for the work we are about to send
usb_buffer_clear(icarus); usb_buffer_clear(icarus);
@ -1306,17 +1377,80 @@ static struct api_data *icarus_api_stats(struct cgpu_info *cgpu)
return root; return root;
} }
static void icarus_statline_before(char *buf, size_t bufsiz, struct cgpu_info *cgpu)
{
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(cgpu->device_data);
if (info->ident == IDENT_CMR2 && info->cmr2_speed > 0)
tailsprintf(buf, bufsiz, "%5.1fMhz", (float)(info->cmr2_speed) * ICARUS_CMR2_SPEED_FACTOR);
else
tailsprintf(buf, bufsiz, " ");
tailsprintf(buf, bufsiz, " | ");
}
static void icarus_shutdown(__maybe_unused struct thr_info *thr) static void icarus_shutdown(__maybe_unused struct thr_info *thr)
{ {
// TODO: ? // TODO: ?
} }
static void icarus_identify(struct cgpu_info *cgpu)
{
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(cgpu->device_data);
if (info->ident == IDENT_CMR2)
info->flash_next_work = true;
}
static char *icarus_set(struct cgpu_info *cgpu, char *option, char *setting, char *replybuf)
{
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(cgpu->device_data);
int val;
if (info->ident != IDENT_CMR2) {
strcpy(replybuf, "no set options available");
return replybuf;
}
if (strcasecmp(option, "help") == 0) {
sprintf(replybuf, "clock: range %d-%d",
ICARUS_CMR2_SPEED_MIN_INT, ICARUS_CMR2_SPEED_MAX_INT);
return replybuf;
}
if (strcasecmp(option, "clock") == 0) {
if (!setting || !*setting) {
sprintf(replybuf, "missing clock setting");
return replybuf;
}
val = atoi(setting);
if (val < ICARUS_CMR2_SPEED_MIN_INT || val > ICARUS_CMR2_SPEED_MAX_INT) {
sprintf(replybuf, "invalid clock: '%s' valid range %d-%d",
setting,
ICARUS_CMR2_SPEED_MIN_INT,
ICARUS_CMR2_SPEED_MAX_INT);
}
info->cmr2_speed = CMR2_INT_TO_SPEED(val);
info->speed_next_work = true;
return NULL;
}
sprintf(replybuf, "Unknown option: %s", option);
return replybuf;
}
struct device_drv icarus_drv = { struct device_drv icarus_drv = {
.drv_id = DRIVER_icarus, .drv_id = DRIVER_icarus,
.dname = "Icarus", .dname = "Icarus",
.name = "ICA", .name = "ICA",
.drv_detect = icarus_detect, .drv_detect = icarus_detect,
.get_api_stats = icarus_api_stats, .get_api_stats = icarus_api_stats,
.get_statline_before = icarus_statline_before,
.set_device = icarus_set,
.identify_device = icarus_identify,
.thread_prepare = icarus_prepare, .thread_prepare = icarus_prepare,
.scanhash = icarus_scanhash, .scanhash = icarus_scanhash,
.thread_shutdown = icarus_shutdown, .thread_shutdown = icarus_shutdown,

Loading…
Cancel
Save