static void gc3355_set_core_freq(struct cgpu_info *gridseed) { GRIDSEED_INFO *info = (GRIDSEED_INFO*)(gridseed->device_data); gc3355_write_data(gridseed, info->freq_cmd, sizeof(info->freq_cmd)); cgsleep_ms(GRIDSEED_COMMAND_DELAY); applog(LOG_NOTICE, "Set GC3355 core frequency to %d MHz", info->freq); }
static void gc3355_enable_btc_cores(struct cgpu_info *gridseed, GRIDSEED_INFO *info) { unsigned char cmd[24], c1, c2; uint16_t mask; int i; mask = 0x00; for(i=0; i<info->btcore; i++) mask = mask << 1 | 0x01; if (mask == 0) return; c1 = mask & 0x00ff; c2 = mask >> 8; memset(cmd, 0, sizeof(cmd)); memcpy(cmd, "\x55\xAA\xEF\x02", 4); for(i=4; i<24; i++) { cmd[i] = ((i%2)==0) ? c1 : c2; gc3355_write_data(gridseed, cmd, sizeof(cmd)); cgsleep_ms(GRIDSEED_COMMAND_DELAY); } return; }
static bool gc3355_write_register(struct cgpu_info *gridseed, uint32_t reg_addr, uint32_t reg_value) { GRIDSEED_INFO *info = (GRIDSEED_INFO*)(gridseed->device_data); char cmd[16] = "\x55\xaa\xc0\x02"; uint32_t reg_len = 4; unsigned char buf[4]; if (info->fw_version != 0x01140113) { applog(LOG_ERR, "Can't write registers; incompatible firmware %08X on %i", info->fw_version, gridseed->device_id); return false; } *(uint32_t *)(cmd + 4) = htole32(reg_addr); *(uint32_t *)(cmd + 8) = htole32(reg_value); *(uint32_t *)(cmd + 12) = htole32(reg_len); if (gc3355_write_data(gridseed, cmd, sizeof(cmd)) != 0) { applog(LOG_DEBUG, "Failed to write data to %i", gridseed->device_id); return false; } cgsleep_ms(GRIDSEED_COMMAND_DELAY); if (gc3355_get_data(gridseed, buf, 4)) { applog(LOG_DEBUG, "No response from %i", gridseed->device_id); return false; } return true; }
static bool gridseed_send_task(struct cgpu_info *gridseed, struct work *work) { unsigned char cmd[156]; memcpy(cmd, "\x55\xaa\x1f\x00", 4); memcpy(cmd+4, work->target, 32); memcpy(cmd+36, work->midstate, 32); memcpy(cmd+68, work->data, 80); memcpy(cmd+148, "\xff\xff\xff\xff", 4); // nonce_max memcpy(cmd+152, "\x12\x34\x56\x78", 4); // taskid return (gc3355_write_data(gridseed, cmd, sizeof(cmd)) == 0); }
static void gc3355_send_cmds_bin(struct cgpu_info *gridseed, const char *cmds[], int size) { int i; for(i=0; ; i++) { if (cmds[i] == NULL) break; gc3355_write_data(gridseed, (char *)cmds[i], size); cgsleep_ms(GRIDSEED_COMMAND_DELAY); } return; }
static void gc3355_send_cmds(struct cgpu_info *gridseed, const char *cmds[]) { unsigned char ob[512]; int i; for(i=0; ; i++) { if (cmds[i] == NULL) break; hex2bin(ob, cmds[i], sizeof(ob)); gc3355_write_data(gridseed, ob, strlen(cmds[i])/2); cgsleep_ms(GRIDSEED_COMMAND_DELAY); } }
static bool gridseed_send_query_cmd(struct cgpu_info *gridseed, GRIDSEED_INFO *info) { unsigned char *cmd = "\x55\xaa\xc0\x00\xa0\xa0\xa0\xa0\x00\x00\x00\x00\x01\x00\x00\x00"; cgtimer_t ts_now, ts_res; bool ret = false; cgtimer_time(&ts_now); mutex_lock(&info->qlock); if (!info->query_qlen) { cgtimer_sub(&ts_now, &info->query_ts, &ts_res); #ifndef WIN32 if (ts_res.tv_sec > 0) { #else if (ts_res.QuadPart > 10000000) { #endif if (gc3355_write_data(gridseed, cmd, 16) == 0) { info->query_qlen = true; ret = true; } } } mutex_unlock(&info->qlock); return ret; } static bool gridseed_send_task(struct cgpu_info *gridseed, GRIDSEED_INFO *info, struct work *work) { unsigned char cmd[52]; memcpy(cmd, "\x55\xaa\x0f\x01", 4); memcpy(cmd+4, work->midstate, 32); memcpy(cmd+36, work->data+64, 12); memcpy(cmd+48, &(work->id), 4); return (gc3355_write_data(gridseed, cmd, sizeof(cmd)) == 0); }
/* * check if we have LTC task. timeout 1ms */ static void gridseed_recv_ltc(struct cgpu_info *gridseed, GRIDSEED_INFO *info) { fd_set rdfs; struct timeval tv; unsigned char buf[156]; int sock; int n; sock = info->sockltc; if (sock <= 0) return; re_read: tv.tv_sec = 0; tv.tv_usec = 10000; FD_ZERO(&rdfs); FD_SET(sock, &rdfs); if (select(sock+1, &rdfs, NULL, NULL, &tv) <= 0) return; n = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL); if (n != sizeof(buf)) goto re_read; mutex_lock(&info->qlock); if (buf[0] == 0x55 || buf[1] == 0xaa) { if (buf[2] == 0x1f) { gc3355_send_cmds(gridseed, str_ltc_reset); gc3355_write_data(gridseed, buf, sizeof(buf)); } else if (buf[2] == 0x55) { // ping command unsigned char nonce[12]; memcpy(nonce, "\x55\xaa\x55\xaa\x11\x22\x33\x44\x55\x66\x77\x88", 12); gridseed_send_ltc_nonce(gridseed, info, nonce, sizeof(nonce)); } } mutex_unlock(&info->qlock); goto re_read; }
static bool gridseed_detect_one(libusb_device *dev, struct usb_find_devices *found) { struct cgpu_info *gridseed; GRIDSEED_INFO *info; int err, wrote, def_freq_inx; unsigned char rbuf[GRIDSEED_READ_SIZE]; #if 0 const char detect_cmd[] = "55aa0f01" "4a548fe471fa3a9a1371144556c3f64d" "2500b4826008fe4bbf7698c94eba7946" "ce22a72f4f6726141a0b3287eeeeeeee"; unsigned char detect_data[52]; #else const char detect_cmd[] = "55aac000909090900000000001000000"; unsigned char detect_data[16]; #endif gridseed = usb_alloc_cgpu(&gridseed_drv, GRIDSEED_MINER_THREADS); if (!usb_init(gridseed, dev, found)) goto shin; libusb_reset_device(gridseed->usbdev->handle); info = (GRIDSEED_INFO*)calloc(sizeof(GRIDSEED_INFO), 1); if (unlikely(!info)) quit(1, "Failed to calloc gridseed_info data"); gridseed->device_data = (void *)info; info->baud = GRIDSEED_DEFAULT_BAUD; info->freq = GRIDSEED_DEFAULT_FREQUENCY; def_freq_inx = gc3355_find_freq_index(GRIDSEED_DEFAULT_FREQUENCY); memcpy(info->freq_cmd, bin_frequency[def_freq_inx], 8); info->chips = GRIDSEED_DEFAULT_CHIPS; info->voltage = 0; info->per_chip_stats = 0; info->serial = strdup(gridseed->usbdev->serial_string); memset(info->nonce_count, 0, sizeof(info->nonce_count)); memset(info->error_count, 0, sizeof(info->error_count)); get_options(info, opt_gridseed_options); get_freq(info, opt_gridseed_freq); get_chips(info, opt_gridseed_chips); update_usb_stats(gridseed); gridseed->usbdev->usb_type = USB_TYPE_STD; gridseed_initialise(gridseed, info); /* get MCU firmware version */ hex2bin(detect_data, detect_cmd, sizeof(detect_data)); if (gc3355_write_data(gridseed, detect_data, sizeof(detect_data))) { applog(LOG_DEBUG, "Failed to write work data to %i, err %d", gridseed->device_id, err); goto unshin; } /* waiting for return */ if (gc3355_get_data(gridseed, rbuf, GRIDSEED_READ_SIZE)) { applog(LOG_DEBUG, "No response from %i", gridseed->device_id); goto unshin; } if (memcmp(rbuf, "\x55\xaa\xc0\x00\x90\x90\x90\x90", GRIDSEED_READ_SIZE-4) != 0) { applog(LOG_DEBUG, "Bad response from %i", gridseed->device_id); goto unshin; } info->fw_version = le32toh(*(uint32_t *)(rbuf+8)); applog(LOG_NOTICE, "Device found, firmware version %08X, driver version %s", info->fw_version, gridseed_version); gc3355_init(gridseed, info); gridseed->algorithm = default_algorithm; if (!add_cgpu(gridseed)) goto unshin; return true; unshin: usb_uninit(gridseed); free(gridseed->device_data); gridseed->device_data = NULL; shin: gridseed = usb_free_cgpu(gridseed); return false; }
static struct cgpu_info *gridseed_detect_one(libusb_device *dev, struct usb_find_devices *found) { struct cgpu_info *gridseed; GRIDSEED_INFO *info; int this_option_offset; int baud, freq, chips, modules, usefifo, btcore; int err, wrote; bool configured; unsigned char rbuf[GRIDSEED_READ_SIZE]; unsigned char *p; #if 0 const char detect_cmd[] = "55aa0f01" "4a548fe471fa3a9a1371144556c3f64d" "2500b4826008fe4bbf7698c94eba7946" "ce22a72f4f6726141a0b3287eeeeeeee"; unsigned char detect_data[52]; #else const char detect_cmd[] = "55aac000909090900000000001000000"; unsigned char detect_data[16]; #endif gridseed = usb_alloc_cgpu(&gridseed_drv, GRIDSEED_MINER_THREADS); if (!usb_init(gridseed, dev, found)) goto shin; libusb_reset_device(gridseed->usbdev->handle); baud = GRIDSEED_DEFAULT_BAUD; chips = GRIDSEED_DEFAULT_CHIPS; modules = GRIDSEED_DEFAULT_MODULES; freq = gc3355_find_freq_index(GRIDSEED_DEFAULT_FREQUENCY); usefifo = GRIDSEED_DEFAULT_USEFIFO; btcore = GRIDSEED_DEFAULT_BTCORE; this_option_offset = 0; configured = get_options(this_option_offset, gridseed, opt_gridseed_options, &baud, &freq, &chips, &modules, &usefifo, &btcore); info = (GRIDSEED_INFO*)calloc(sizeof(GRIDSEED_INFO), 1); if (unlikely(!info)) quit(1, "Failed to calloc gridseed_info data"); gridseed->device_data = (void *)info; update_usb_stats(gridseed); //if (configured) { info->baud = baud; info->freq = freq; info->chips = chips; info->modules = modules; info->usefifo = usefifo; info->btcore = btcore; //} gridseed->usbdev->usb_type = USB_TYPE_STD; gridseed_initialise(gridseed, info); /* send testing work to chips */ hex2bin(detect_data, detect_cmd, sizeof(detect_data)); if (gc3355_write_data(gridseed, detect_data, sizeof(detect_data))) { applog(LOG_DEBUG, "Failed to write work data to %i, err %d", gridseed->device_id, err); goto unshin; } /* waiting for return */ if (gc3355_get_data(gridseed, rbuf, GRIDSEED_READ_SIZE)) { applog(LOG_DEBUG, "No response from %i", gridseed->device_id); goto unshin; } if (memcmp(rbuf, "\x55\xaa\xc0\x00\x90\x90\x90\x90", GRIDSEED_READ_SIZE-4) != 0) { applog(LOG_DEBUG, "Bad response from %i", gridseed->device_id); goto unshin; } p = bin2hex(rbuf+GRIDSEED_READ_SIZE-4, 4); applog(LOG_NOTICE, "Device found, firmware version 0x%s, driver version %s", p, gridseed_version); free(p); if (!add_cgpu(gridseed)) goto unshin; return gridseed; unshin: usb_uninit(gridseed); free(gridseed->device_data); gridseed->device_data = NULL; shin: gridseed = usb_free_cgpu(gridseed); return NULL; }