static int64_t gridseed_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) { struct cgpu_info *gridseed = thr->cgpu; GRIDSEED_INFO *info = gridseed->device_data; unsigned char buf[GRIDSEED_READ_SIZE]; int ret = 0; struct timeval old_scanhash_time = info->scanhash_time; int elapsed_ms; while (!thr->work_restart && (ret = gc3355_get_data(gridseed, buf, GRIDSEED_READ_SIZE)) == 0) { if (buf[0] == 0x55 || buf[1] == 0x20) { uint32_t nonce = le32toh(*(uint32_t *)(buf+4)); uint32_t chip = nonce / ((uint32_t)0xffffffff / info->chips); info->nonce_count[chip]++; if (!submit_nonce(thr, work, nonce)) info->error_count[chip]++; } else { applog(LOG_ERR, "Unrecognized response from %i", gridseed->device_id); return -1; } } if (ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) { applog(LOG_ERR, "No response from %i", gridseed->device_id); return -1; } cgtime(&info->scanhash_time); elapsed_ms = ms_tdiff(&info->scanhash_time, &old_scanhash_time); return GRIDSEED_HASH_SPEED * (double)elapsed_ms * (double)(info->freq * info->chips); }
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_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; }
static bool gridseed_check_new_task(struct cgpu_info *gridseed, GRIDSEED_INFO *info) { cgtimer_t ts_now, ts_res; bool ret = false; cgtimer_time(&ts_now); mutex_lock(&info->qlock); cgtimer_sub(&ts_now, &info->query_ts, &ts_res); #ifndef WIN32 if (ts_res.tv_sec > 0 || ts_res.tv_nsec > 350000000) { #else if (ts_res.QuadPart > 3500000) { #endif info->query_qlen = false; info->dev_queue_len = 1; info->needworks = 1; cgtimer_time(&info->query_ts); } mutex_unlock(&info->qlock); } /* * Thread to read response from Miner device */ static void *gridseed_get_results(void *userdata) { struct cgpu_info *gridseed = (struct cgpu_info *)userdata; GRIDSEED_INFO *info = gridseed->device_data; struct thr_info *thr = info->thr; char threadname[24]; unsigned char readbuf[GRIDSEED_READBUF_SIZE]; int offset = 0, ret; snprintf(threadname, sizeof(threadname), "GridSeed_Recv/%d", gridseed->device_id); RenameThread(threadname); applog(LOG_NOTICE, "GridSeed: recv thread running, %s", threadname); while(likely(!gridseed->shutdown)) { unsigned char buf[GRIDSEED_READ_SIZE]; if (offset >= GRIDSEED_READ_SIZE) gridseed_parse_results(gridseed, info, thr, readbuf, &offset); if (unlikely(offset + GRIDSEED_READ_SIZE >= GRIDSEED_READBUF_SIZE)) { applog(LOG_ERR, "Read buffer overflow, resetting %d", gridseed->device_id); offset = 0; } ret = gc3355_get_data(gridseed, buf, sizeof(buf)); if (ret == LIBUSB_ERROR_NO_DEVICE) gridseed->shutdown = true; if (unlikely(ret != 0)) continue; if (opt_debug) { applog(LOG_DEBUG, "GridSeed: get %d bytes", GRIDSEED_READ_SIZE); hexdump((uint8_t *)buf, GRIDSEED_READ_SIZE); } memcpy(readbuf + offset, buf, GRIDSEED_READ_SIZE); offset += GRIDSEED_READ_SIZE; } return NULL; } /* * Thread to send task and queue length query command to device */ static void *gridseed_send_command(void *userdata) { struct cgpu_info *gridseed = (struct cgpu_info *)userdata; GRIDSEED_INFO *info = gridseed->device_data; char threadname[24]; int i; snprintf(threadname, sizeof(threadname), "GridSeed_Send/%d", gridseed->device_id); RenameThread(threadname); applog(LOG_NOTICE, "GridSeed: send thread running, %s", threadname); while(likely(!gridseed->shutdown)) { cgsleep_ms(10); if (info->usefifo == 0) { /* mark the first work in queue as complete after several ms */ if (gridseed_check_new_task(gridseed, info)) continue; } else { /* send query command to device */ if (gridseed_send_query_cmd(gridseed, info)) continue; } /* send task to device */ mutex_lock(&info->qlock); for(i=0; i<info->soft_queue_len; i++) { if (info->workqueue[i] && info->workqueue[i]->devflag == false) { if (gridseed_send_task(gridseed, info, info->workqueue[i])) { info->workqueue[i]->devflag = true; break; } } } mutex_unlock(&info->qlock); /* recv LTC task and send to device */ gridseed_recv_ltc(gridseed, info); } return NULL; } /*========== functions for struct device_drv ===========*/ static void gridseed_detect(bool __maybe_unused hotplug) { usb_detect(&gridseed_drv, gridseed_detect_one); }