From cbf6c71648d2edc56fae7ec60b217e5475f9cfca Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 08:54:02 +1100 Subject: [PATCH 01/47] BFL libusb driver --- driver-bitforce.c | 602 ++++++++++++++++++++++------------------------ usbutils.c | 133 ++++++++-- usbutils.h | 55 ++++- 3 files changed, 450 insertions(+), 340 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index b8a83430..62c40636 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -1,4 +1,5 @@ /* + * Copyright 2012 Andrew Smith * Copyright 2012 Luke Dashjr * Copyright 2012 Con Kolivas * @@ -19,34 +20,25 @@ #include "config.h" #ifdef WIN32 - #include - -#define dlsym (void*)GetProcAddress -#define dlclose FreeLibrary - -typedef unsigned long FT_STATUS; -typedef PVOID FT_HANDLE; -__stdcall FT_STATUS (*FT_ListDevices)(PVOID pArg1, PVOID pArg2, DWORD Flags); -__stdcall FT_STATUS (*FT_Open)(int idx, FT_HANDLE*); -__stdcall FT_STATUS (*FT_GetComPortNumber)(FT_HANDLE, LPLONG lplComPortNumber); -__stdcall FT_STATUS (*FT_Close)(FT_HANDLE); -const uint32_t FT_OPEN_BY_DESCRIPTION = 2; -const uint32_t FT_LIST_ALL = 0x20000000; -const uint32_t FT_LIST_NUMBER_ONLY = 0x80000000; -enum { - FT_OK, -}; - -// Code must deal with a timeout. Make it 1 second on windows, 0.1 on linux. -#define BFopen(devpath) serial_open(devpath, 0, 10, true) -#else /* WIN32 */ -#define BFopen(devpath) serial_open(devpath, 0, 1, true) #endif /* WIN32 */ #include "compat.h" #include "miner.h" -#include "fpgautils.h" +#include "usbutils.h" + +#define BITFORCE_IDENTIFY "ZGX" +#define BITFORCE_IDENTIFY_LEN (sizeof(BITFORCE_IDENTIFY)-1) +#define BITFORCE_FLASH "ZMX" +#define BITFORCE_FLASH_LEN (sizeof(BITFORCE_FLASH)-1) +#define BITFORCE_TEMPERATURE "ZLX" +#define BITFORCE_TEMPERATURE_LEN (sizeof(BITFORCE_TEMPERATURE)-1) +#define BITFORCE_SENDRANGE "ZPX" +#define BITFORCE_SENDRANGE_LEN (sizeof(BITFORCE_SENDRANGE)-1) +#define BITFORCE_SENDWORK "ZDX" +#define BITFORCE_SENDWORK_LEN (sizeof(BITFORCE_SENDWORK)-1) +#define BITFORCE_WORKSTATUS "ZFX" +#define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1) #define BITFORCE_SLEEP_MS 500 #define BITFORCE_TIMEOUT_S 7 @@ -62,62 +54,143 @@ enum { #define KNAME_WORK "full work" #define KNAME_RANGE "nonce range" +#define BITFORCE_BUFSIZ (0x200) + +// If initialisation fails the first time, +// sleep this amount (ms) and try again +#define REINIT_TIME_MS 6000 + +static const char *blank = ""; + struct device_api bitforce_api; -static void BFgets(char *buf, size_t bufLen, int fd) +static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) { - do { - buf[0] = '\0'; - --bufLen; - } while (likely(bufLen && read(fd, buf, 1) == 1 && (buf++)[0] != '\n')); + int err; - buf[0] = '\0'; -} + if (lock) + mutex_lock(&bitforce->device_mutex); -static ssize_t BFwrite(int fd, const void *buf, ssize_t bufLen) -{ - if ((bufLen) != write(fd, buf, bufLen)) - return 0; - else - return bufLen; + // Reset + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: reset got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set data control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, + FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setdata got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set the baud + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, + (FTDI_INDEX_BAUD & 0xff00) | bitforce->usbdev->found->interface, + C_SETBAUD); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setbaud got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set Flow Control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, + FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set Modem Control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, + FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Clear any sent data +// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, +// FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); +// if (opt_debug) +// applog(LOG_DEBUG, "%s%i: purgetx got err %d", +// bitforce->api->name, bitforce->device_id, err); + + // Clear any received data +// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, +// FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); +// if (opt_debug) +// applog(LOG_DEBUG, "%s%i: purgerx got err %d", +// bitforce->api->name, bitforce->device_id, err); + + if (lock) + mutex_unlock(&bitforce->device_mutex); } -#define BFclose(fd) close(fd) - -static bool bitforce_detect_one(const char *devpath) +static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) { - int fdDev = BFopen(devpath); - struct cgpu_info *bitforce; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + char devpath[20]; + int err, amount; char *s; - applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath); + struct cgpu_info *bitforce = NULL; + bitforce = calloc(1, sizeof(*bitforce)); + bitforce->api = &bitforce_api; + bitforce->deven = DEV_ENABLED; + bitforce->threads = 1; - if (unlikely(fdDev == -1)) { - applog(LOG_ERR, "BFL: Failed to open %s", devpath); - return false; + if (!usb_init(bitforce, dev, found)) { + applog(LOG_ERR, "%s detect: failed to initialise (incorrect device?)", bitforce->api->dname); + goto shin; } - BFwrite(fdDev, "ZGX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)"); - return 0; + int init_counter = 0; +reinit: + + bitforce_initialise(bitforce, false); + + if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { + applog(LOG_ERR, "%s detect: send identify request failed (%d:%d)", + bitforce->api->dname, amount, err); + goto unshin; } - BFclose(fdDev); - if (unlikely(!strstr(pdevbuf, "SHA256"))) { - applog(LOG_ERR, "BFL: Didn't recognise BitForce on %s", devpath); - return false; + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { + // Maybe it was still processing previous work? + if (init_counter++ < 1) { + applog(LOG_WARNING, "%s detect: 1st init failed - retrying in %dms (%d:%d)", + bitforce->api->dname, REINIT_TIME_MS, amount, err); + nmsleep(REINIT_TIME_MS); + goto reinit; + } + + if (err < 0) { + applog(LOG_ERR, "%s detect: error identify reply (%d:%d)", + bitforce->api->dname, amount, err); + } else { + applog(LOG_ERR, "%s detect: empty identify reply (%d)", + bitforce->api->dname, amount); + } + + goto unshin; + } + buf[amount] = '\0'; + + if (unlikely(!strstr(buf, "SHA256"))) { + applog(LOG_ERR, "%s detect: didn't recognise %s", + bitforce->api->dname, buf); + goto unshin; + } + + if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { + s[0] = '\0'; + bitforce->name = strdup(buf + 7); + } else { + bitforce->name = (char *)blank; } // We have a real BitForce! - bitforce = calloc(1, sizeof(*bitforce)); - bitforce->api = &bitforce_api; - bitforce->device_path = strdup(devpath); - bitforce->deven = DEV_ENABLED; - bitforce->threads = 1; + applog(LOG_DEBUG, "%s identified as: '%s'", bitforce->api->dname, bitforce->name); + /* Initially enable support for nonce range and disable it later if it * fails */ if (opt_bfl_noncerange) { @@ -129,108 +202,38 @@ static bool bitforce_detect_one(const char *devpath) bitforce->kname = KNAME_WORK; } - if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) { - s[0] = '\0'; - bitforce->name = strdup(pdevbuf + 7); - } + sprintf(devpath, "%d:%d", + (int)(bitforce->usbdev->bus_number), + (int)(bitforce->usbdev->device_address)); + + bitforce->device_path = strdup(devpath); + + if (!add_cgpu(bitforce)) + goto unshin; mutex_init(&bitforce->device_mutex); - return add_cgpu(bitforce); -} + return true; -#define LOAD_SYM(sym) do { \ - if (!(sym = dlsym(dll, #sym))) { \ - applog(LOG_DEBUG, "Failed to load " #sym ", not using FTDI bitforce autodetect"); \ - goto out; \ - } \ -} while(0) +unshin: -#ifdef WIN32 -static int bitforce_autodetect_ftdi(void) -{ - char devpath[] = "\\\\.\\COMnnnnn"; - char *devpathnum = &devpath[7]; - char **bufptrs; - char *buf; - int found = 0; - DWORD i; - - FT_STATUS ftStatus; - DWORD numDevs; - HMODULE dll = LoadLibrary("FTD2XX.DLL"); - if (!dll) { - applog(LOG_DEBUG, "FTD2XX.DLL failed to load, not using FTDI bitforce autodetect"); - return 0; - } - LOAD_SYM(FT_ListDevices); - LOAD_SYM(FT_Open); - LOAD_SYM(FT_GetComPortNumber); - LOAD_SYM(FT_Close); - - ftStatus = FT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY); - if (ftStatus != FT_OK) { - applog(LOG_DEBUG, "FTDI device count failed, not using FTDI bitforce autodetect"); - goto out; - } - applog(LOG_DEBUG, "FTDI reports %u devices", (unsigned)numDevs); - - buf = alloca(65 * numDevs); - bufptrs = alloca(sizeof(*bufptrs) * (numDevs + 1)); - - for (i = 0; i < numDevs; ++i) - bufptrs[i] = &buf[i * 65]; - bufptrs[numDevs] = NULL; - ftStatus = FT_ListDevices(bufptrs, &numDevs, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - if (ftStatus != FT_OK) { - applog(LOG_DEBUG, "FTDI device list failed, not using FTDI bitforce autodetect"); - goto out; - } - - for (i = numDevs; i > 0; ) { - --i; - bufptrs[i][64] = '\0'; - - if (!(strstr(bufptrs[i], "BitFORCE") && strstr(bufptrs[i], "SHA256"))) - continue; - - FT_HANDLE ftHandle; - if (FT_OK != FT_Open(i, &ftHandle)) - continue; - LONG lComPortNumber; - ftStatus = FT_GetComPortNumber(ftHandle, &lComPortNumber); - FT_Close(ftHandle); - if (FT_OK != ftStatus || lComPortNumber < 0) - continue; - - sprintf(devpathnum, "%d", (int)lComPortNumber); - - if (bitforce_detect_one(devpath)) - ++found; - } + usb_uninit(bitforce); -out: - dlclose(dll); - return found; -} -#else -static int bitforce_autodetect_ftdi(void) -{ - return 0; -} -#endif +shin: -static int bitforce_detect_auto(void) -{ - return (serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?: - serial_autodetect_devserial(bitforce_detect_one, "BitFORCE_SHA256") ?: - bitforce_autodetect_ftdi() ?: - 0); + free(bitforce->device_path); + + if (bitforce->name != blank) + free(bitforce->name); + + free(bitforce); + + return false; } static void bitforce_detect(void) { - serial_detect_auto(&bitforce_api, bitforce_detect_one, bitforce_detect_auto); + usb_detect(&bitforce_api, bitforce_detect_one); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) @@ -247,105 +250,17 @@ static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) static bool bitforce_thread_prepare(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = BFopen(bitforce->device_path); struct timeval now; - if (unlikely(fdDev == -1)) { - applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, bitforce->device_path); - return false; - } - - bitforce->device_fd = fdDev; - - applog(LOG_INFO, "BFL%i: Opened %s", bitforce->device_id, bitforce->device_path); gettimeofday(&now, NULL); get_datestamp(bitforce->init, &now); return true; } -static void bitforce_clear_buffer(struct cgpu_info *bitforce) -{ - int fdDev = bitforce->device_fd; - char pdevbuf[0x100]; - int count = 0; - - if (!fdDev) - return; - - applog(LOG_DEBUG, "BFL%i: Clearing read buffer", bitforce->device_id); - - mutex_lock(&bitforce->device_mutex); - do { - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - } while (pdevbuf[0] && (++count < 10)); - mutex_unlock(&bitforce->device_mutex); -} - -void bitforce_init(struct cgpu_info *bitforce) -{ - char *devpath = bitforce->device_path; - int fdDev = bitforce->device_fd, retries = 0; - char pdevbuf[0x100]; - char *s; - - applog(LOG_WARNING, "BFL%i: Re-initialising", bitforce->device_id); - - bitforce_clear_buffer(bitforce); - - mutex_lock(&bitforce->device_mutex); - if (fdDev) { - BFclose(fdDev); - sleep(5); - } - bitforce->device_fd = 0; - - fdDev = BFopen(devpath); - if (unlikely(fdDev == -1)) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, devpath); - return; - } - - do { - BFwrite(fdDev, "ZGX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - - if (unlikely(!pdevbuf[0])) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Error reading/timeout (ZGX)", bitforce->device_id); - return; - } - - if (retries++) - nmsleep(10); - } while (!strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS)); - - if (unlikely(!strstr(pdevbuf, "SHA256"))) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Didn't recognise BitForce on %s returned: %s", bitforce->device_id, devpath, pdevbuf); - return; - } - - if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) { - s[0] = '\0'; - bitforce->name = strdup(pdevbuf + 7); - } - - bitforce->device_fd = fdDev; - bitforce->sleep_ms = BITFORCE_SLEEP_MS; - - mutex_unlock(&bitforce->device_mutex); -} - static void bitforce_flash_led(struct cgpu_info *bitforce) { - int fdDev = bitforce->device_fd; - - if (!fdDev) - return; + int err, amount; /* Do not try to flash the led if we're polling for a result to * minimise the chance of interleaved results */ @@ -353,19 +268,22 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) return; /* It is not critical flashing the led so don't get stuck if we - * can't grab the mutex here */ + * can't grab the mutex now */ if (mutex_trylock(&bitforce->device_mutex)) return; - BFwrite(fdDev, "ZMX", 3); + if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { + applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } else { + /* However, this stops anything else getting a reply + * So best to delay any other access to the BFL */ + sleep(4); + } /* Once we've tried - don't do it until told to again */ bitforce->flash_led = false; - /* However, this stops anything else getting a reply - * So best to delay any other access to the BFL */ - sleep(4); - mutex_unlock(&bitforce->device_mutex); return; // nothing is returned by the BFL @@ -373,13 +291,10 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) static bool bitforce_get_temp(struct cgpu_info *bitforce) { - int fdDev = bitforce->device_fd; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int err, amount; char *s; - if (!fdDev) - return false; - /* Do not try to get the temperature if we're polling for a result to * minimise the chance of interleaved results */ if (bitforce->polling) @@ -396,18 +311,30 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if (mutex_trylock(&bitforce->device_mutex)) return false; - BFwrite(fdDev, "ZLX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - mutex_unlock(&bitforce->device_mutex); - - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL%i: Error: Get temp returned empty string/timed out", bitforce->device_id); + if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + bitforce->hw_errors++; + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETTEMPERATURE)) < 0 || amount < 1) { + mutex_unlock(&bitforce->device_mutex); + if (err < 0) { + applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } else { + applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } bitforce->hw_errors++; return false; } - if ((!strncasecmp(pdevbuf, "TEMP", 4)) && (s = strchr(pdevbuf + 4, ':'))) { + mutex_unlock(&bitforce->device_mutex); + + if ((!strncasecmp(buf, "TEMP", 4)) && (s = strchr(buf + 4, ':'))) { float temp = strtof(s + 1, NULL); /* Cope with older software that breaks and reads nonsense @@ -418,7 +345,8 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if (temp > 0) { bitforce->temp = temp; if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) { - applog(LOG_WARNING, "BFL%i: Hit thermal cutoff limit, disabling!", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!", + bitforce->api->name, bitforce->device_id); bitforce->deven = DEV_RECOVER; dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF); } @@ -427,11 +355,12 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) /* Use the temperature monitor as a kind of watchdog for when * our responses are out of sync and flush the buffer to * hopefully recover */ - applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer", + bitforce->api->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_THROTTLE); /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; - bitforce_clear_buffer(bitforce); + bitforce_initialise(bitforce, true); return false; } @@ -441,35 +370,53 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) static bool bitforce_send_work(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = bitforce->device_fd; unsigned char ob[70]; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int err, amount; char *s; + char *cmd; + int len; - if (!fdDev) - return false; re_send: + if (bitforce->nonce_range) { + cmd = BITFORCE_SENDRANGE; + len = BITFORCE_SENDRANGE_LEN; + } else { + cmd = BITFORCE_SENDWORK; + len = BITFORCE_SENDWORK_LEN; + } + mutex_lock(&bitforce->device_mutex); - if (bitforce->nonce_range) - BFwrite(fdDev, "ZPX", 3); - else - BFwrite(fdDev, "ZDX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) { + if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if (amount == 0 || !buf[0] || !strncasecmp(buf, "B", 1)) { mutex_unlock(&bitforce->device_mutex); nmsleep(WORK_CHECK_INTERVAL_MS); goto re_send; - } else if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { + } else if (unlikely(strncasecmp(buf, "OK", 2))) { mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { - applog(LOG_WARNING, "BFL%i: Does not support nonce range, disabling", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", + bitforce->api->name, bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } - applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf); + applog(LOG_ERR, "%s%i: Error: Send work reports: %s", + bitforce->api->name, bitforce->device_id, buf); return false; } @@ -479,7 +426,7 @@ re_send: if (!bitforce->nonce_range) { sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>"); work->blk.nonce = bitforce->nonces = 0xffffffff; - BFwrite(fdDev, ob, 60); + len = 60; } else { uint32_t *nonce; @@ -491,26 +438,41 @@ re_send: *nonce = htobe32(work->blk.nonce + bitforce->nonces); work->blk.nonce += bitforce->nonces + 1; sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>"); - BFwrite(fdDev, ob, 68); + len = 68; + } + + if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: send work failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; } - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); if (opt_debug) { s = bin2hex(ob + 8, 44); - applog(LOG_DEBUG, "BFL%i: block data: %s", bitforce->device_id, s); + applog(LOG_DEBUG, "%s%i: block data: %s", + bitforce->api->name, bitforce->device_id, s); free(s); } - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL%i: Error: Send block data returned empty string/timed out", bitforce->device_id); + if (amount == 0 || !buf[0]) { + applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", + bitforce->api->name, bitforce->device_id); return false; } - if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { - applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf); + if (unlikely(strncasecmp(buf, "OK", 2))) { + applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", + bitforce->api->name, bitforce->device_id, buf); return false; } @@ -521,53 +483,52 @@ re_send: static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = bitforce->device_fd; unsigned int delay_time_ms; struct timeval elapsed; struct timeval now; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int amount; char *pnoncebuf; uint32_t nonce; - if (!fdDev) - return -1; - while (1) { if (unlikely(thr->work_restart)) return 0; mutex_lock(&bitforce->device_mutex); - BFwrite(fdDev, "ZFX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); + usb_write(bitforce, BITFORCE_WORKSTATUS, BITFORCE_WORKSTATUS_LEN, &amount, C_REQUESTWORKSTATUS); + usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETWORKSTATUS); mutex_unlock(&bitforce->device_mutex); gettimeofday(&now, NULL); timersub(&now, &bitforce->work_start_tv, &elapsed); if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { - applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, + applog(LOG_ERR, "%s%i: took %dms - longer than %dms", + bitforce->api->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } - if (pdevbuf[0] && strncasecmp(pdevbuf, "B", 1)) /* BFL does not respond during throttling */ + if (amount > 0 && buf[0] && strncasecmp(buf, "B", 1)) /* BFL does not respond during throttling */ break; /* if BFL is throttling, no point checking so quickly */ - delay_time_ms = (pdevbuf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); + delay_time_ms = (buf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); nmsleep(delay_time_ms); bitforce->wait_ms += delay_time_ms; } if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { - applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, + applog(LOG_ERR, "%s%i: took %dms - longer than %dms", + bitforce->api->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); dev_error(bitforce, REASON_DEV_OVER_HEAT); - if (!pdevbuf[0]) /* Only return if we got nothing after timeout - there still may be results */ + /* Only return if we got nothing after timeout - there still may be results */ + if (amount == 0) return 0; - } else if (!strncasecmp(pdevbuf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ + } else if (!strncasecmp(buf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or @@ -584,26 +545,31 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) } if (delay_time_ms != bitforce->sleep_ms) - applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d, waited %u", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); + applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", + bitforce->api->name, bitforce->device_id, + bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT; bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5); } - applog(LOG_DEBUG, "BFL%i: waited %dms until %s", bitforce->device_id, bitforce->wait_ms, pdevbuf); - if (!strncasecmp(&pdevbuf[2], "-", 1)) + applog(LOG_DEBUG, "%s%i: waited %dms until %s", + bitforce->api->name, bitforce->device_id, + bitforce->wait_ms, buf); + if (!strncasecmp(&buf[2], "-", 1)) return bitforce->nonces; /* No valid nonce found */ - else if (!strncasecmp(pdevbuf, "I", 1)) + else if (!strncasecmp(buf, "I", 1)) return 0; /* Device idle */ - else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) { + else if (strncasecmp(buf, "NONCE-FOUND", 11)) { bitforce->hw_errors++; - applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf); - bitforce_clear_buffer(bitforce); + applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", + bitforce->api->name, bitforce->device_id, buf); + bitforce_initialise(bitforce, true); return 0; } - pnoncebuf = &pdevbuf[12]; + pnoncebuf = &buf[12]; while (1) { hex2bin((void*)&nonce, pnoncebuf, 4); @@ -612,7 +578,8 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) #endif if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { - applog(LOG_WARNING, "BFL%i: Disabling broken nonce range support", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", + bitforce->api->name, bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; @@ -628,19 +595,16 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) return bitforce->nonces; } -static void bitforce_shutdown(struct thr_info *thr) +static void bitforce_shutdown(__maybe_unused struct thr_info *thr) { - struct cgpu_info *bitforce = thr->cgpu; - - BFclose(bitforce->device_fd); - bitforce->device_fd = 0; +// struct cgpu_info *bitforce = thr->cgpu; } static void biforce_thread_enable(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; - bitforce_init(bitforce); + bitforce_initialise(bitforce, true); } static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) @@ -665,11 +629,11 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ if (ret == -1) { ret = 0; - applog(LOG_ERR, "BFL%i: Comms error", bitforce->device_id); + applog(LOG_ERR, "%s%i: Comms error", bitforce->api->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_COMMS_ERROR); bitforce->hw_errors++; /* empty read buffer */ - bitforce_clear_buffer(bitforce); + bitforce_initialise(bitforce, true); } return ret; } @@ -692,7 +656,8 @@ static bool bitforce_thread_init(struct thr_info *thr) /* Pause each new thread at least 100ms between initialising * so the devices aren't making calls all at the same time. */ wait = thr->id * MAX_START_DELAY_MS; - applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000); + applog(LOG_DEBUG, "%s%d: Delaying start by %dms", + bitforce->api->name, bitforce->device_id, wait / 1000); nmsleep(wait); return true; @@ -717,7 +682,6 @@ struct device_api bitforce_api = { .name = "BFL", .api_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, - .reinit_device = bitforce_init, .get_statline_before = get_bitforce_statline_before, .get_stats = bitforce_get_stats, .identify_device = bitforce_identify, diff --git a/usbutils.c b/usbutils.c index ad3ff270..d2298dfa 100644 --- a/usbutils.c +++ b/usbutils.c @@ -36,11 +36,20 @@ #define EPO(x) (LIBUSB_ENDPOINT_OUT | (unsigned char)(x)) #ifdef WIN32 +#define BITFORCE_TIMEOUT_MS 200 #define MODMINER_TIMEOUT_MS 200 #else +#define BITFORCE_TIMEOUT_MS 100 #define MODMINER_TIMEOUT_MS 100 #endif +#ifdef USE_BITFORCE +static struct usb_endpoints bfl_eps[] = { + { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, + { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } +}; +#endif + #ifdef USE_MODMINER static struct usb_endpoints mmq_eps[] = { { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, @@ -48,7 +57,7 @@ static struct usb_endpoints mmq_eps[] = { }; #endif -// TODO: Add support for (at least) Interrupt endpoints +// TODO: Add support for (at least) Isochronous endpoints static struct usb_find_devices find_dev[] = { /* #ifdef USE_ICARUS @@ -56,10 +65,19 @@ static struct usb_find_devices find_dev[] = { { DRV_ICARUS, "LOT", 0x0403, 0x6001, false, EPI(0), EPO(0), 1 }, { DRV_ICARUS, "CM1", 0x067b, 0x0230, false, EPI(0), EPO(0), 1 }, #endif +*/ #ifdef USE_BITFORCE - { DRV_BITFORCE, "BFL", 0x0403, 0x6014, true, EPI(1), EPO(2), 1 }, + { + .drv = DRV_BITFORCE, + .name = "BFL", + .idVendor = 0x0403, + .idProduct = 0x6014, + .config = 1, + .interface = 0, + .timeout = BITFORCE_TIMEOUT_MS, + .epcount = ARRAY_SIZE(bfl_eps), + .eps = bfl_eps }, #endif -*/ #ifdef USE_MODMINER { .drv = DRV_MODMINER, @@ -160,6 +178,18 @@ static const char *C_SENDWORK_S = "SendWork"; static const char *C_SENDWORKSTATUS_S = "SendWorkStatus"; static const char *C_REQUESTWORKSTATUS_S = "RequestWorkStatus"; static const char *C_GETWORKSTATUS_S = "GetWorkStatus"; +static const char *C_REQUESTIDENTIFY_S = "RequestIdentify"; +static const char *C_GETIDENTIFY_S = "GetIdentify"; +static const char *C_REQUESTFLASH_S = "RequestFlash"; +static const char *C_REQUESTSENDWORK_S = "RequestSendWork"; +static const char *C_REQUESTSENDWORKSTATUS_S = "RequestSendWorkStatus"; +static const char *C_RESET_S = "Reset"; +static const char *C_SETBAUD_S = "SetBaud"; +static const char *C_SETDATA_S = "SetDataCtrl"; +static const char *C_SETFLOW_S = "SetFlowCtrl"; +static const char *C_SETMODEM_S = "SetModemCtrl"; +static const char *C_PURGERX_S = "PurgeRx"; +static const char *C_PURGETX_S = "PurgeTx"; #ifdef EOL #undef EOL @@ -505,6 +535,7 @@ static void cgusb_check_init() list_lock = calloc(1, sizeof(*list_lock)); mutex_init(list_lock); + // N.B. environment LIBUSB_DEBUG also sets libusb_set_debug() if (opt_usbdump >= 0) { libusb_set_debug(NULL, opt_usbdump); usb_all(); @@ -537,6 +568,18 @@ static void cgusb_check_init() usb_commands[C_SENDWORKSTATUS] = C_SENDWORKSTATUS_S; usb_commands[C_REQUESTWORKSTATUS] = C_REQUESTWORKSTATUS_S; usb_commands[C_GETWORKSTATUS] = C_GETWORKSTATUS_S; + usb_commands[C_REQUESTIDENTIFY] = C_REQUESTIDENTIFY_S; + usb_commands[C_GETIDENTIFY] = C_GETIDENTIFY_S; + usb_commands[C_REQUESTFLASH] = C_REQUESTFLASH_S; + usb_commands[C_REQUESTSENDWORK] = C_REQUESTSENDWORK_S; + usb_commands[C_REQUESTSENDWORKSTATUS] = C_REQUESTSENDWORKSTATUS_S; + usb_commands[C_RESET] = C_RESET_S; + usb_commands[C_SETBAUD] = C_SETBAUD_S; + usb_commands[C_SETDATA] = C_SETDATA_S; + usb_commands[C_SETFLOW] = C_SETFLOW_S; + usb_commands[C_SETMODEM] = C_SETMODEM_S; + usb_commands[C_PURGERX] = C_PURGERX_S; + usb_commands[C_PURGETX] = C_PURGETX_S; } mutex_unlock(&cgusb_lock); @@ -745,9 +788,9 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find } if (libusb_kernel_driver_active(cgusb->handle, 0) == 1) { - applog(LOG_WARNING, "USB init, kernel attached ..."); + applog(LOG_DEBUG, "USB init, kernel attached ..."); if (libusb_detach_kernel_driver(cgusb->handle, 0) == 0) - applog(LOG_WARNING, "USB init, kernel detached successfully"); + applog(LOG_DEBUG, "USB init, kernel detached successfully"); else applog(LOG_WARNING, "USB init, kernel detach failed :("); } @@ -773,7 +816,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto cldame; } - if ((int)(config->bNumInterfaces) < found->interface) + if ((int)(config->bNumInterfaces) <= found->interface) goto cldame; for (i = 0; i < found->epcount; i++) @@ -1118,26 +1161,42 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev } #endif -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd) +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi) { struct cg_usb_device *usbdev = cgpu->usbdev; #if DO_USB_STATS - struct timeval tv_start, tv_finish; + struct timeval tv_start; #endif - int err, got, tot; + struct timeval read_start, tv_finish; + unsigned int initial_timeout; + double max, done; + int err, got, tot, i; bool first = true; + if (timeout == DEVTIMEOUT) + timeout = usbdev->found->timeout; + if (eol == -1) { got = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, usbdev->found->eps[ep].ep, (unsigned char *)buf, - bufsiz, &got, - timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); + bufsiz, &got, timeout); STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + if (ftdi) { + // first 2 bytes returned are an FTDI status + if (got > 2) { + got -= 2; + memmove(buf, buf+2, got+1); + } else { + got = 0; + *buf = '\0'; + } + } + *processed = got; return err; @@ -1145,31 +1204,55 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro tot = 0; err = LIBUSB_SUCCESS; + initial_timeout = timeout; + max = ((double)timeout) / 1000.0; + gettimeofday(&read_start, NULL); while (bufsiz) { got = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, usbdev->found->eps[ep].ep, (unsigned char *)buf, - 1, &got, - timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); - STATS_TIMEVAL(&tv_finish); + bufsiz, &got, timeout); + gettimeofday(&tv_finish, NULL); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, first ? SEQ0 : SEQ1); + if (ftdi) { + // first 2 bytes returned are an FTDI status + if (got > 2) { + got -= 2; + memmove(buf, buf+2, got+1); + } else { + got = 0; + *buf = '\0'; + } + } + tot += got; if (err) break; - if (eol == buf[0]) - break; + // WARNING - this will return data past EOL ('if' there is extra data) + for (i = 0; i < got; i++) + if (buf[i] == eol) + goto goteol; buf += got; bufsiz -= got; first = false; + + done = tdiff(&tv_finish, &read_start); + // N.B. this is return LIBUSB_SUCCESS with whatever size has already been read + if (unlikely(done >= max)) + break; + + timeout = initial_timeout - (done * 1000); } +goteol: + *processed = tot; return err; @@ -1198,6 +1281,24 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr return err; } +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd) +{ + struct cg_usb_device *usbdev = cgpu->usbdev; +#if DO_USB_STATS + struct timeval tv_start, tv_finish; +#endif + int err; + + STATS_TIMEVAL(&tv_start); + err = libusb_control_transfer(usbdev->handle, request_type, + bRequest, wValue, wIndex, NULL, 0, + timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); + STATS_TIMEVAL(&tv_finish); + USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + + return err; +} + void usb_cleanup() { // TODO: diff --git a/usbutils.h b/usbutils.h index 71fd9699..156e2a2d 100644 --- a/usbutils.h +++ b/usbutils.h @@ -12,6 +12,29 @@ #include +// for 0x0403/0x6014 FT232H (and possibly others?) +#define FTDI_TYPE_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT) + +#define FTDI_REQUEST_RESET ((uint8_t)0) +#define FTDI_REQUEST_MODEM ((uint8_t)1) +#define FTDI_REQUEST_FLOW ((uint8_t)2) +#define FTDI_REQUEST_BAUD ((uint8_t)3) +#define FTDI_REQUEST_DATA ((uint8_t)4) + +#define FTDI_VALUE_RESET 0 +#define FTDI_VALUE_PURGE_RX 1 +#define FTDI_VALUE_PURGE_TX 2 + +// baud with a 0 divisor is 120,000,000/10 +//#define FTDI_VALUE_BAUD (0) +//#define FTDI_INDEX_BAUD (0) +#define FTDI_VALUE_BAUD 0xc068 +#define FTDI_INDEX_BAUD 0x0200 + +#define FTDI_VALUE_DATA 0 +#define FTDI_VALUE_FLOW 0 +#define FTDI_VALUE_MODEM 0x0303 + // Use the device defined timeout #define DEVTIMEOUT 0 @@ -78,6 +101,18 @@ enum usb_cmds { C_SENDWORKSTATUS, C_REQUESTWORKSTATUS, C_GETWORKSTATUS, + C_REQUESTIDENTIFY, + C_GETIDENTIFY, + C_REQUESTFLASH, + C_REQUESTSENDWORK, + C_REQUESTSENDWORKSTATUS, + C_RESET, + C_SETBAUD, + C_SETDATA, + C_SETFLOW, + C_SETMODEM, + C_PURGERX, + C_PURGETX, C_MAX }; @@ -89,21 +124,25 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); void update_usb_stats(struct cgpu_info *cgpu); -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds); +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds, bool ftdi); int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds); +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd); void usb_cleanup(); #define usb_read(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false) + +#define usb_read_nl(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, false) #define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd) + _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false) #define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd, false) #define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd) + _usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd, false) #define usb_write(cgpu, buf, bufsiz, wrote, cmd) \ _usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd) @@ -117,4 +156,10 @@ void usb_cleanup(); #define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \ _usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) +#define usb_ftdi_read_nl(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, true) + +#define usb_transfer(cgpu, typ, req, val, idx, cmd) \ + _usb_transfer(cgpu, typ, req, val, idx, DEVTIMEOUT, cmd) + #endif From 040ec589fa4dfdecfb1ae04b94e88e1b4588ff9f Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 09:09:43 +1100 Subject: [PATCH 02/47] BFL USB build changes --- Makefile.am | 6 +++++- configure.ac | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5f846289..b7f90637 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,6 +82,10 @@ if NEED_FPGAUTILS cgminer_SOURCES += fpgautils.c fpgautils.h endif +if NEED_USBUTILS_C +cgminer_SOURCES += usbutils.c +endif + if HAS_BITFORCE cgminer_SOURCES += driver-bitforce.c endif @@ -91,7 +95,7 @@ cgminer_SOURCES += driver-icarus.c endif if HAS_MODMINER -cgminer_SOURCES += driver-modminer.c usbutils.c +cgminer_SOURCES += driver-modminer.c bitstreamsdir = $(bindir)/bitstreams dist_bitstreams_DATA = bitstreams/* endif diff --git a/configure.ac b/configure.ac index 3b51f73a..67a70bee 100644 --- a/configure.ac +++ b/configure.ac @@ -273,6 +273,7 @@ fi AM_CONDITIONAL([NEED_FPGAUTILS], [test x$icarus$bitforce$modminer$ztex != xnononono]) +AM_CONDITIONAL([NEED_USBUTILS_C], [test x$bitforce$modminer != xnono]) AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes]) AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue]) AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue]) @@ -321,7 +322,7 @@ fi AM_CONDITIONAL([HAS_YASM], [test x$has_yasm = xtrue]) -if test "x$bitforce" != xno; then +if test "x$icarus" != xno; then AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])], [libudev=$withval], [libudev=auto] @@ -343,7 +344,7 @@ AM_CONDITIONAL([HAVE_LIBUDEV], [test x$libudev != xno]) PKG_PROG_PKG_CONFIG() -if test "x$ztex$modminer" != xnono; then +if test "x$ztex$modminer$bitforce" != xnonono; then case $target in *-*-freebsd*) LIBUSB_LIBS="-lusb" @@ -508,7 +509,7 @@ else echo " Ztex.FPGAs...........: Disabled" fi -if test "x$bitforce" != xno; then +if test "x$icarus" != xno; then echo " libudev.detection....: $libudev" fi From b0996152461abe61522b4cc173f9f51bc22dfa99 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 13:04:53 +1100 Subject: [PATCH 03/47] BFL report USB device numbers for init errors and allow faster 'reinit' --- driver-bitforce.c | 70 +++++++++++++++++++++++++++-------------------- usbutils.c | 5 ++++ 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index 62c40636..57d2115c 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -58,7 +58,9 @@ // If initialisation fails the first time, // sleep this amount (ms) and try again -#define REINIT_TIME_MS 6000 +#define REINIT_TIME_MS 1000 +// But try this many times +#define REINIT_COUNT 6 static const char *blank = ""; @@ -108,18 +110,18 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) bitforce->api->name, bitforce->device_id, err); // Clear any sent data -// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, -// FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); -// if (opt_debug) -// applog(LOG_DEBUG, "%s%i: purgetx got err %d", -// bitforce->api->name, bitforce->device_id, err); + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: purgetx got err %d", + bitforce->api->name, bitforce->device_id, err); // Clear any received data -// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, -// FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); -// if (opt_debug) -// applog(LOG_DEBUG, "%s%i: purgerx got err %d", -// bitforce->api->name, bitforce->device_id, err); + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: purgerx got err %d", + bitforce->api->name, bitforce->device_id, err); if (lock) mutex_unlock(&bitforce->device_mutex); @@ -139,36 +141,49 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { - applog(LOG_ERR, "%s detect: failed to initialise (incorrect device?)", bitforce->api->dname); + applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", + bitforce->api->dname, + (int)libusb_get_bus_number(dev), + (int)libusb_get_device_address(dev)); goto shin; } - int init_counter = 0; + sprintf(devpath, "%d:%d", + (int)(bitforce->usbdev->bus_number), + (int)(bitforce->usbdev->device_address)); + + int init_count = 0; reinit: bitforce_initialise(bitforce, false); if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { - applog(LOG_ERR, "%s detect: send identify request failed (%d:%d)", - bitforce->api->dname, amount, err); + applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", + bitforce->api->dname, devpath, amount, err); goto unshin; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { // Maybe it was still processing previous work? - if (init_counter++ < 1) { - applog(LOG_WARNING, "%s detect: 1st init failed - retrying in %dms (%d:%d)", - bitforce->api->dname, REINIT_TIME_MS, amount, err); + if (++init_count <= REINIT_COUNT) { + if (init_count < 2) { + applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", + bitforce->api->dname, devpath, amount, err); + } nmsleep(REINIT_TIME_MS); goto reinit; } + if (init_count > 0) + applog(LOG_WARNING, "%s detect (%s) init failed %d times", + bitforce->api->dname, devpath, init_count); + if (err < 0) { - applog(LOG_ERR, "%s detect: error identify reply (%d:%d)", - bitforce->api->dname, amount, err); + applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", + bitforce->api->dname, devpath, amount, err); } else { - applog(LOG_ERR, "%s detect: empty identify reply (%d)", - bitforce->api->dname, amount); + applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", + bitforce->api->dname, devpath, amount); } goto unshin; @@ -176,8 +191,8 @@ reinit: buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { - applog(LOG_ERR, "%s detect: didn't recognise %s", - bitforce->api->dname, buf); + applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", + bitforce->api->dname, devpath, buf); goto unshin; } @@ -189,7 +204,8 @@ reinit: } // We have a real BitForce! - applog(LOG_DEBUG, "%s identified as: '%s'", bitforce->api->dname, bitforce->name); + applog(LOG_DEBUG, "%s (%s) identified as: '%s'", + bitforce->api->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ @@ -202,10 +218,6 @@ reinit: bitforce->kname = KNAME_WORK; } - sprintf(devpath, "%d:%d", - (int)(bitforce->usbdev->bus_number), - (int)(bitforce->usbdev->device_address)); - bitforce->device_path = strdup(devpath); if (!add_cgpu(bitforce)) diff --git a/usbutils.c b/usbutils.c index d2298dfa..4b126177 100644 --- a/usbutils.c +++ b/usbutils.c @@ -45,8 +45,13 @@ #ifdef USE_BITFORCE static struct usb_endpoints bfl_eps[] = { +#ifdef WIN32 + { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, + { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } +#else { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } +#endif }; #endif From 70b47a770d5181330826fd84b1640714da2a5793 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 13:25:19 +1100 Subject: [PATCH 04/47] BFL USB - README and FPGA-README --- FPGA-README | 25 ++++++++++++++----------- README | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/FPGA-README b/FPGA-README index a970df72..5a1e6a34 100644 --- a/FPGA-README +++ b/FPGA-README @@ -2,15 +2,8 @@ This README contains extended details about FPGA mining with cgminer -ModMinerQuad (MMQ) ------------------- - -The mining bitstream does not survive a power cycle, so cgminer will upload -it, if it needs to, before it starts mining (approx 7min 40sec) - -The red LED also flashes while it is uploading the bitstream - -- +For ModMinerQuad (MMQ) and BitForce (BFL) +----------------------------------------- When mining on windows, the driver being used will determine if mining will work. @@ -39,7 +32,17 @@ problems: --usb-dump 0 -It will only help if you have a working MMQ device attached to the computer +It will only help if you have a working MMQ or BFL device attached to the +computer + + +ModMinerQuad (MMQ) +------------------ + +The mining bitstream does not survive a power cycle, so cgminer will upload +it, if it needs to, before it starts mining (approx 7min 40sec) + +The red LED also flashes while it is uploading the bitstream - @@ -130,7 +133,7 @@ modem-manager software TODO: check that all MMQ's have the same product ID -Bitforce (BFL) +BitForce (BFL) -------------- --bfl-range Use nonce range on bitforce devices if supported diff --git a/README b/README index 8865529c..fd310154 100644 --- a/README +++ b/README @@ -220,15 +220,16 @@ SCRYPT only options: See SCRYPT-README for more information regarding litecoin mining. -FPGA mining boards(BitForce, Icarus, ModMiner, Ztex) only options: +FPGA mining boards (BitForce, Icarus, ModMiner, Ztex) only options: -cgminer will automatically find your ModMiner or Ztex FPGAs +cgminer will automatically find your ModMiner, BitForce or Ztex FPGAs +independent of the --scan-serial options specified below ---scan-serial|-S Serial port to probe for FPGA mining device +--scan-serial|-S Serial port to probe for Icarus mining device -This option is only for BitForce and/or Icarus FPGAs +This option is only for Icarus bitstream FPGAs -By default, cgminer will scan for autodetected FPGAs unless at least one +By default, cgminer will scan for autodetected Icarus unless at least one -S is specified for that driver. If you specify -S and still want cgminer to scan, you must also use "-S auto". If you want to prevent cgminer from scanning without specifying a device, you can use "-S noauto". Note that @@ -237,13 +238,14 @@ device depending on the version of udev being used. On linux is usually of the format /dev/ttyUSBn On windows is usually of the format \\.\COMn -(where n = the correct device number for the FPGA device) +(where n = the correct device number for the Icarus device) The official supplied binaries are compiled with support for all FPGAs. To force the code to only attempt detection with a specific driver, prepend the argument with the driver name followed by a colon. -For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5" -or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5" +For example, "icarus:/dev/ttyUSB0" or using the short name: "ica:/dev/ttyUSB0" +This option not longer matters since Icarus is the only serial-USB +device that uses it For other FPGA details see the FPGA-README From 03c2cabab2cca31731c4a2e1940a331d8fd7b7d7 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 23:46:03 +1100 Subject: [PATCH 05/47] BFL include all USB requirements --- miner.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/miner.h b/miner.h index f777a30d..5a6e89a1 100644 --- a/miner.h +++ b/miner.h @@ -114,7 +114,7 @@ static inline int fsync (int fd) #include "libztex.h" #endif -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) #include "usbutils.h" #endif @@ -374,13 +374,17 @@ struct cgpu_info { #ifdef USE_ZTEX struct libztex_device *device_ztex; #endif -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) struct cg_usb_device *usbdev; #endif +#ifdef USE_ICARUS int device_fd; +#endif }; -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) int usbstat; +#endif +#ifdef USE_MODMINER char fpgaid; unsigned char clock; pthread_mutex_t *modminer_mutex; From 07db1ed6874d96c08910275e6bc53ef745ab5933 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 1 Jan 2013 00:29:17 +1100 Subject: [PATCH 06/47] BFL USB api.c usbstats --- api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.c b/api.c index 659d934a..1d29dbb9 100644 --- a/api.c +++ b/api.c @@ -3120,7 +3120,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may { struct api_data *root = NULL; -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) char buf[TMPBUFSIZ]; bool io_open = false; int count = 0; @@ -3133,7 +3133,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may return; } -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) message(io_data, MSG_USBSTA, 0, NULL, isjson); From 211b0f4ea15dcd88012232cb31e537cc8b61f490 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:18:08 +1100 Subject: [PATCH 07/47] BFL USB longer timeout --- usbutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 4b126177..0d9e79aa 100644 --- a/usbutils.c +++ b/usbutils.c @@ -36,10 +36,10 @@ #define EPO(x) (LIBUSB_ENDPOINT_OUT | (unsigned char)(x)) #ifdef WIN32 -#define BITFORCE_TIMEOUT_MS 200 +#define BITFORCE_TIMEOUT_MS 500 #define MODMINER_TIMEOUT_MS 200 #else -#define BITFORCE_TIMEOUT_MS 100 +#define BITFORCE_TIMEOUT_MS 200 #define MODMINER_TIMEOUT_MS 100 #endif From 03f626e68d1a90fde0441cf39d932238bf0edab6 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:51:09 +1100 Subject: [PATCH 08/47] Remember best share per pool and return in API pools --- API-README | 9 ++++++++- api.c | 1 + cgminer.c | 2 ++ miner.h | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index b205c90b..a71b694f 100644 --- a/API-README +++ b/API-README @@ -400,7 +400,14 @@ miner.php - an example web page to access the API Feature Changelog for external applications using the API: -API V1.23 +API V1.24 + +Modified API commands: + 'pools' - add 'Best Share' + +---------- + +API V1.23 (cgminer v2.10.2) Added API commands: 'pgaset' - with: MMQ opt=clock val=160 to 230 (and a multiple of 2) diff --git a/api.c b/api.c index 659d934a..94b1d5ce 100644 --- a/api.c +++ b/api.c @@ -1993,6 +1993,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m else root = api_add_const(root, "Stratum URL", BLANK, false); root = api_add_bool(root, "Has GBT", &(pool->has_gbt), false); + root = api_add_uint64(root, "Best Share", &(pool->best_diff), true); root = print_data(root, buf, isjson, isjson && (i > 0)); io_add(io_data, buf); diff --git a/cgminer.c b/cgminer.c index 876abeda..b33bb7fa 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2349,6 +2349,8 @@ static uint64_t share_diff(const struct work *work) best_diff = ret; suffix_string(best_diff, best_share, 0); } + if (ret > work->pool->best_diff) + work->pool->best_diff = ret; mutex_unlock(&control_lock); return ret; } diff --git a/miner.h b/miner.h index df2888e9..79a4cf27 100644 --- a/miner.h +++ b/miner.h @@ -920,6 +920,7 @@ struct pool { time_t last_share_time; double last_share_diff; + uint64_t best_diff; struct cgminer_stats cgminer_stats; struct cgminer_pool_stats cgminer_pool_stats; From abaaf93c8dc8714594d9d29490a195d8ed9df377 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:52:38 +1100 Subject: [PATCH 09/47] Correct API version to match docs --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index 94b1d5ce..207dfd71 100644 --- a/api.c +++ b/api.c @@ -133,7 +133,7 @@ static const char SEPARATOR = '|'; #define SEPSTR "|" static const char GPUSEP = ','; -static const char *APIVERSION = "1.23"; +static const char *APIVERSION = "1.24"; static const char *DEAD = "Dead"; #if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) static const char *SICK = "Sick"; From 4c2f26e28062143b2a9e8793bb57903080b8fbb1 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 22:34:05 +1100 Subject: [PATCH 10/47] zero (most) API stats --- cgminer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cgminer.c b/cgminer.c index b33bb7fa..0c2d8c2c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -3935,6 +3935,10 @@ void zero_stats(void) total_diff1 = 0; memset(best_share, 0, 8); suffix_string(best_diff, best_share, 0); + found_blocks = 0; + total_diff_accepted = 0; + total_diff_rejected = 0; + total_diff_stale = 0; for (i = 0; i < total_pools; i++) { struct pool *pool = pools[i]; @@ -3946,6 +3950,13 @@ void zero_stats(void) pool->discarded_work = 0; pool->getfail_occasions = 0; pool->remotefail_occasions = 0; + pool->last_share_time = 0; + pool->diff1 = 0; + pool->diff_accepted = 0; + pool->diff_rejected = 0; + pool->diff_stale = 0; + pool->last_share_diff = 0; + pool->best_diff = 0; } mutex_lock(&hash_lock); @@ -3957,6 +3968,11 @@ void zero_stats(void) cgpu->rejected = 0; cgpu->hw_errors = 0; cgpu->utility = 0.0; + cgpu->last_share_pool_time = 0; + cgpu->diff1 = 0; + cgpu->diff_accepted = 0; + cgpu->diff_rejected = 0; + cgpu->last_share_diff = 0; } mutex_unlock(&hash_lock); } From 44ec75528219686b68ec9e50b8de8236f90f8439 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 22:43:48 +1100 Subject: [PATCH 11/47] BFL USB correct usb stats id --- driver-bitforce.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver-bitforce.c b/driver-bitforce.c index 57d2115c..4a06b597 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -223,6 +223,8 @@ reinit: if (!add_cgpu(bitforce)) goto unshin; + update_usb_stats(bitforce); + mutex_init(&bitforce->device_mutex); return true; From 1b2654e1ff02de4d92724b695c4c758d3c2aa9f4 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 4 Jan 2013 16:07:10 +1100 Subject: [PATCH 12/47] miner.php optional user/pass login restrictions --- API-README | 32 +++++++ miner.php | 246 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 233 insertions(+), 45 deletions(-) diff --git a/API-README b/API-README index a71b694f..14f8b53c 100644 --- a/API-README +++ b/API-README @@ -937,6 +937,38 @@ true --------- +Default: + $userlist = null; + +Define password checking and default access + null means there is no password checking + +$userlist is an array of 3 arrays e.g. +$userlist = array('sys' => array('boss' => 'bpass'), + 'usr' => array('user' => 'upass', 'pleb' => 'ppass'), + 'def' => array('Pools')); + +'sys' is an array of system users and passwords (full access) +'usr' is an array of user level users and passwords (readonly access) +'def' is an array of custompages that anyone not logged in can view + +Any of the 3 can be null, meaning there are none of that item + +All validated 'usr' users are given $readonly = true; access +All validated 'sys' users are given the $readonly access you defined + +If 'def' has one or more values, and allowcustompages is true, then +anyone without a password can see the list of custompage buttons given +in 'def' and will see the first one when they go to the web page, with +a login button at the top right + +From the login page, if you login with no username or password, it will +show the first 'def' custompage (if there are any) + +If you are logged in, it will show a logout button at the top right + +--------- + Default: $notify = true; diff --git a/miner.php b/miner.php index 8c393ac8..b0e80030 100644 --- a/miner.php +++ b/miner.php @@ -8,7 +8,7 @@ global $checklastshare, $poolinputs, $hidefields; global $ignorerefresh, $changerefresh, $autorefresh; global $allowcustompages, $customsummarypages; global $miner_font_family, $miner_font_size; -global $colouroverride, $placebuttons; +global $colouroverride, $placebuttons, $userlist; # # See API-README for more details of these variables and how # to configure miner.php @@ -20,6 +20,9 @@ $title = 'Mine'; # Set $readonly to false then it will check cgminer 'privileged' $readonly = false; # +# Set $userlist to null to allow anyone access or read API-README +$userlist = null; +# # Set $notify to false to NOT attempt to display the notify command # Set $notify to true to attempt to display the notify command $notify = true; @@ -212,6 +215,10 @@ $rigerror = array(); global $rownum; $rownum = 0; # +// Login +global $ses; +$ses = 'rutroh'; +# function getcss($cssname, $dom = false) { global $colourtable, $colouroverride; @@ -239,7 +246,7 @@ function getdom($domname) return getcss($domname, true); } # -function htmlhead($checkapi, $rig, $pg = null) +function htmlhead($checkapi, $rig, $pg = null, $noscript = false) { global $title, $miner_font_family, $miner_font_size; global $error, $readonly, $poolinputs, $here; @@ -285,8 +292,10 @@ td.lst { $miner_font ".getcss('td.lst')."} td.hi { $miner_font ".getcss('td.hi')."} td.lo { $miner_font ".getcss('td.lo')."} - -\n"; +} ?> -
@@ -1507,7 +1517,6 @@ function doforeach($cmd, $des, $sum, $head, $datetime) # function refreshbuttons() { - global $readonly; global $ignorerefresh, $changerefresh, $autorefresh; if ($ignorerefresh == false && $changerefresh == true) @@ -1521,7 +1530,7 @@ function refreshbuttons() # function pagebuttons($rig, $pg) { - global $readonly, $rigs; + global $readonly, $rigs, $userlist, $ses; global $allowcustompages, $customsummarypages; if ($rig === null) @@ -1557,18 +1566,33 @@ function pagebuttons($rig, $pg) } echo '"; } # @@ -2410,13 +2440,126 @@ function showcustompage($pagename) pagebuttons(null, $pagename); } # +function onlylogin() +{ + global $here; + + htmlhead(false, null, null, true); + +?> + + +No rigs defined"); + return; + } if ($ignorerefresh == false) { @@ -2425,52 +2568,65 @@ function display() $autorefresh = intval($ref); } - $rig = trim(getparam('rig', true)); - - $arg = trim(getparam('arg', true)); - $preprocess = null; - if ($arg != null and $arg != '') + if ($pagesonly !== true) { - $num = null; - if ($rig != null and $rig != '') - { - if ($rig >= 0 and $rig < count($rigs)) - $num = $rig; - } - else - if (count($rigs) == 0) - $num = 0; + $rig = trim(getparam('rig', true)); - if ($num != null) + $arg = trim(getparam('arg', true)); + $preprocess = null; + if ($arg != null and $arg != '') { - $parts = explode(':', $rigs[$num], 3); - if (count($parts) >= 2) + if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs)) { - $miner = $parts[0]; - $port = $parts[1]; + $parts = explode(':', $rigs[$rig], 3); + if (count($parts) >= 2) + { + $miner = $parts[0]; + $port = $parts[1]; - if ($readonly !== true) - $preprocess = $arg; + if ($readonly !== true) + $preprocess = $arg; + } } } } - if ($rigs == null or count($rigs) == 0) - { - otherrow(""); - return; - } - if ($allowcustompages === true) { $pg = trim(getparam('pg', true)); - if ($pg != null && $pg != '') + if ($pagesonly === true) + { + if ($pg !== null && $pg !== '') + { + if ($userlist !== null && isset($userlist['def']) + && !in_array($pg, $userlist['def'])) + $pg = null; + } + else + { + if ($userlist !== null && isset($userlist['def'])) + foreach ($userlist['def'] as $pglook) + if (isset($customsummarypages[$pglook])) + { + $pg = $pglook; + break; + } + } + } + + if ($pg !== null && $pg !== '') { showcustompage($pg); return; } } + if ($pagesonly === true) + { + onlylogin(); + return; + } + if (count($rigs) == 1) { $parts = explode(':', $rigs[0], 3); From f6bde14c3113ec85f4743584a9900b3c81b387f7 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 4 Jan 2013 17:45:54 +1100 Subject: [PATCH 13/47] miner.php user/pass fix 'usr' is readonly --- miner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner.php b/miner.php index b0e80030..9215a21e 100644 --- a/miner.php +++ b/miner.php @@ -2476,7 +2476,7 @@ function onlylogin() function checklogin() { global $allowcustompages, $customsummarypages; - global $userlist, $ses; + global $readonly, $userlist, $ses; $out = trim(getparam('logout', true)); if ($out !== null && $out !== '' && isset($_SESSION[$ses])) From 7724989d9bd59f458b0c873c09c0fff9e291f152 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 5 Jan 2013 10:40:32 +1100 Subject: [PATCH 14/47] diffexactone pool diff1 used for share value calculation is ffffffff... not 100000000... :P --- cgminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 0c2d8c2c..19ffcb98 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2576,7 +2576,7 @@ static inline struct pool *select_pool(bool lagging) return pool; } -static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0; +static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0; /* * Calculate the work share difficulty From a344deb6ac8605a57c96eb03cb7ec9b17c4575b7 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 5 Jan 2013 23:47:26 +1100 Subject: [PATCH 15/47] rename device_api -> device_drv and all related api -> drv and add a device_drv->drv enum for identifying which driver each is --- api.c | 64 ++++++++++--------------- cgminer.c | 119 +++++++++++++++++++++++----------------------- driver-bitforce.c | 87 ++++++++++++++++----------------- driver-cpu.c | 6 +-- driver-cpu.h | 2 +- driver-icarus.c | 11 +++-- driver-modminer.c | 93 ++++++++++++++++++------------------ driver-opencl.c | 38 +++++---------- driver-opencl.h | 2 +- driver-ztex.c | 10 ++-- findnonce.c | 2 +- fpgautils.c | 10 ++-- fpgautils.h | 14 +++--- miner.h | 19 ++++++-- usbutils.c | 38 +++++++-------- usbutils.h | 4 +- 16 files changed, 253 insertions(+), 266 deletions(-) diff --git a/api.c b/api.c index 3561c7ab..2e013ff4 100644 --- a/api.c +++ b/api.c @@ -599,22 +599,6 @@ struct APIGROUPS { static struct IP4ACCESS *ipaccess = NULL; static int ips = 0; -#ifdef USE_BITFORCE -extern struct device_api bitforce_api; -#endif - -#ifdef USE_ICARUS -extern struct device_api icarus_api; -#endif - -#ifdef USE_ZTEX -extern struct device_api ztex_api; -#endif - -#ifdef USE_MODMINER -extern struct device_api modminer_api; -#endif - struct io_data { size_t siz; char *ptr; @@ -1153,19 +1137,19 @@ static int numpgas() for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->api == &bitforce_api) + if (devices[i]->drv->drv == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->api == &icarus_api) + if (devices[i]->drv->drv == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->api == &ztex_api) + if (devices[i]->drv->drv == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->api == &modminer_api) + if (devices[i]->drv->drv == DRIVER_MODMINER) count++; #endif } @@ -1179,19 +1163,19 @@ static int pgadevice(int pgaid) for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->api == &bitforce_api) + if (devices[i]->drv->drv == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->api == &icarus_api) + if (devices[i]->drv->drv == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->api == &ztex_api) + if (devices[i]->drv->drv == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->api == &modminer_api) + if (devices[i]->drv->drv == DRIVER_MODMINER) count++; #endif if (count == (pgaid + 1)) @@ -1535,11 +1519,11 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom float temp = cgpu->temp; #ifdef USE_ZTEX - if (cgpu->api == &ztex_api && cgpu->device_ztex) + if (cgpu->drv->drv == DRIVER_ZTEX && cgpu->device_ztex) frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1); #endif #ifdef USE_MODMINER - if (cgpu->api == &modminer_api) + if (cgpu->drv->drv == DRIVER_MODMINER) frequency = cgpu->clock; #endif @@ -1553,7 +1537,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom status = (char *)status2str(cgpu->status); root = api_add_int(root, "PGA", &pga, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); root = api_add_string(root, "Enabled", enabled, false); root = api_add_string(root, "Status", status, false); @@ -1868,12 +1852,12 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch } struct cgpu_info *cgpu = devices[dev]; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; - if (!api->identify_device) + if (!drv->identify_device) message(io_data, MSG_PGANOID, id, NULL, isjson); else { - api->identify_device(cgpu); + drv->identify_device(cgpu); message(io_data, MSG_PGAIDENT, id, NULL, isjson); } } @@ -2753,7 +2737,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b // ALL counters (and only counters) must start the name with a '*' // Simplifies future external support for identifying new counters root = api_add_int(root, "NOTIFY", &device, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); root = api_add_time(root, "Last Well", &(cgpu->device_last_well), false); root = api_add_time(root, "Last Not Well", &(cgpu->device_last_not_well), false); @@ -2817,9 +2801,9 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m cgpu = devices[i]; root = api_add_int(root, "DEVDETAILS", &i, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); - root = api_add_string(root, "Driver", cgpu->api->dname, false); + root = api_add_string(root, "Driver", cgpu->drv->dname, false); root = api_add_const(root, "Kernel", cgpu->kname ? : BLANK, false); root = api_add_const(root, "Model", cgpu->name ? : BLANK, false); root = api_add_const(root, "Device Path", cgpu->device_path ? : BLANK, false); @@ -2923,13 +2907,13 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m for (j = 0; j < total_devices; j++) { struct cgpu_info *cgpu = devices[j]; - if (cgpu && cgpu->api) { - if (cgpu->api->get_api_stats) - extra = cgpu->api->get_api_stats(cgpu); + if (cgpu && cgpu->drv) { + if (cgpu->drv->get_api_stats) + extra = cgpu->drv->get_api_stats(cgpu); else extra = NULL; - sprintf(id, "%s%d", cgpu->api->name, cgpu->device_id); + sprintf(id, "%s%d", cgpu->drv->name, cgpu->device_id); i = itemstats(io_data, i, id, &(cgpu->cgminer_stats), NULL, extra, isjson); } } @@ -3195,16 +3179,16 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe } struct cgpu_info *cgpu = devices[dev]; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; char *set = strchr(opt, ','); if (set) *(set++) = '\0'; - if (!api->set_device) + if (!drv->set_device) message(io_data, MSG_PGANOSET, id, NULL, isjson); else { - char *ret = api->set_device(cgpu, opt, set, buf); + char *ret = drv->set_device(cgpu, opt, set, buf); if (ret) { if (strcasecmp(opt, "help") == 0) message(io_data, MSG_PGAHELP, id, ret, isjson); diff --git a/cgminer.c b/cgminer.c index 19ffcb98..adf7db45 100644 --- a/cgminer.c +++ b/cgminer.c @@ -385,7 +385,7 @@ static void sharelog(const char*disposition, const struct work*work) data = bin2hex(work->data, sizeof(work->data)); // timestamp,disposition,target,pool,dev,thr,sharehash,sharedata - rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->api->name, cgpu->device_id, thr_id, hash, data); + rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->drv->name, cgpu->device_id, thr_id, hash, data); free(target); free(hash); free(data); @@ -1875,9 +1875,9 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) suffix_string(dh64, displayed_hashes, 4); suffix_string(dr64, displayed_rolling, 4); - sprintf(buf, "%s%d ", cgpu->api->name, cgpu->device_id); - if (cgpu->api->get_statline_before) - cgpu->api->get_statline_before(buf, cgpu); + sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id); + if (cgpu->drv->get_statline_before) + cgpu->drv->get_statline_before(buf, cgpu); else tailsprintf(buf, " | "); tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m", @@ -1888,8 +1888,8 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) cgpu->rejected, cgpu->hw_errors, cgpu->utility); - if (cgpu->api->get_statline) - cgpu->api->get_statline(buf, cgpu); + if (cgpu->drv->get_statline) + cgpu->drv->get_statline(buf, cgpu); } static void text_print_status(int thr_id) @@ -1971,10 +1971,10 @@ static void curses_print_devstatus(int thr_id) cgpu->utility = cgpu->accepted / total_secs * 60; wmove(statuswin,devcursor + cgpu->cgminer_id, 0); - wprintw(statuswin, " %s %*d: ", cgpu->api->name, dev_width, cgpu->device_id); - if (cgpu->api->get_statline_before) { + wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id); + if (cgpu->drv->get_statline_before) { logline[0] = '\0'; - cgpu->api->get_statline_before(logline, cgpu); + cgpu->drv->get_statline_before(logline, cgpu); wprintw(statuswin, "%s", logline); } else @@ -2007,9 +2007,9 @@ static void curses_print_devstatus(int thr_id) hwwidth, cgpu->hw_errors, uwidth + 3, cgpu->utility); - if (cgpu->api->get_statline) { + if (cgpu->drv->get_statline) { logline[0] = '\0'; - cgpu->api->get_statline(logline, cgpu); + cgpu->drv->get_statline(logline, cgpu); wprintw(statuswin, "%s", logline); } @@ -2234,10 +2234,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, if (!QUIET) { if (total_pools > 1) applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s", - hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); else applog(LOG_NOTICE, "Accepted %s %s %d %s%s", - hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); } sharelog("accept", work); if (opt_shares && total_accepted >= opt_shares) { @@ -2302,7 +2302,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, } applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s", - hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); sharelog(disposition, work); } @@ -5238,15 +5238,15 @@ static bool hashtest(struct thr_info *thr, struct work *work) if (hash2_32[7] != 0) { applog(LOG_WARNING, "%s%d: invalid nonce - HW error", - thr->cgpu->api->name, thr->cgpu->device_id); + thr->cgpu->drv->name, thr->cgpu->device_id); mutex_lock(&stats_lock); hw_errors++; thr->cgpu->hw_errors++; mutex_unlock(&stats_lock); - if (thr->cgpu->api->hw_error) - thr->cgpu->api->hw_error(thr); + if (thr->cgpu->drv->hw_error) + thr->cgpu->drv->hw_error(thr); goto out; } @@ -5294,7 +5294,7 @@ static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64 } static void mt_disable(struct thr_info *mythr, const int thr_id, - struct device_api *api) + struct device_drv *drv) { applog(LOG_WARNING, "Thread %d being disabled", thr_id); mythr->rolling = mythr->cgpu->rolling = 0; @@ -5305,8 +5305,8 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, } while (mythr->pause); thread_reportin(mythr); applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); - if (api->thread_enable) - api->thread_enable(mythr); + if (drv->thread_enable) + drv->thread_enable(mythr); } void *miner_thread(void *userdata) @@ -5314,7 +5314,7 @@ void *miner_thread(void *userdata) struct thr_info *mythr = userdata; const int thr_id = mythr->id; struct cgpu_info *cgpu = mythr->cgpu; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats); struct cgminer_stats *pool_stats; struct timeval getwork_start; @@ -5323,7 +5323,7 @@ void *miner_thread(void *userdata) const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; struct timeval diff, sdiff, wdiff = {0, 0}; - uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff; + uint32_t max_nonce = drv->can_limit_work ? drv->can_limit_work(mythr) : 0xffffffff; int64_t hashes_done = 0; int64_t hashes; struct work *work; @@ -5337,7 +5337,7 @@ void *miner_thread(void *userdata) gettimeofday(&getwork_start, NULL); - if (api->thread_init && !api->thread_init(mythr)) { + if (drv->thread_init && !drv->thread_init(mythr)) { dev_error(cgpu, REASON_THREAD_FAIL_INIT); goto out; } @@ -5357,7 +5357,7 @@ void *miner_thread(void *userdata) gettimeofday(&tv_workstart, NULL); work->blk.nonce = 0; cgpu->max_hashes = 0; - if (api->prepare_work && !api->prepare_work(mythr, work)) { + if (drv->prepare_work && !drv->prepare_work(mythr, work)) { applog(LOG_ERR, "work prepare failed, exiting " "mining thread %d", thr_id); break; @@ -5399,16 +5399,16 @@ void *miner_thread(void *userdata) gettimeofday(&(work->tv_work_start), NULL); thread_reportin(mythr); - hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce); + hashes = drv->scanhash(mythr, work, work->blk.nonce + max_nonce); thread_reportin(mythr); gettimeofday(&getwork_start, NULL); if (unlikely(hashes == -1)) { - applog(LOG_ERR, "%s %d failure, disabling!", api->name, cgpu->device_id); + applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id); cgpu->deven = DEV_DISABLED; dev_error(cgpu, REASON_THREAD_ZERO_HASH); - mt_disable(mythr, thr_id, api); + mt_disable(mythr, thr_id, drv); } hashes_done += hashes; @@ -5429,7 +5429,7 @@ void *miner_thread(void *userdata) if (unlikely((long)sdiff.tv_sec < cycle)) { int mult; - if (likely(!api->can_limit_work || max_nonce == 0xffffffff)) + if (likely(!drv->can_limit_work || max_nonce == 0xffffffff)) continue; mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10; @@ -5438,9 +5438,9 @@ void *miner_thread(void *userdata) max_nonce = 0xffffffff; else max_nonce = (max_nonce * mult) / 0x400; - } else if (unlikely(sdiff.tv_sec > cycle) && api->can_limit_work) + } else if (unlikely(sdiff.tv_sec > cycle) && drv->can_limit_work) max_nonce = max_nonce * cycle / sdiff.tv_sec; - else if (unlikely(sdiff.tv_usec > 100000) && api->can_limit_work) + else if (unlikely(sdiff.tv_usec > 100000) && drv->can_limit_work) max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400)); timersub(&tv_end, &tv_lastupdate, &diff); @@ -5466,7 +5466,7 @@ void *miner_thread(void *userdata) } if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) - mt_disable(mythr, thr_id, api); + mt_disable(mythr, thr_id, drv); sdiff.tv_sec = sdiff.tv_usec = 0; } while (!abandon_work(work, &wdiff, cgpu->max_hashes)); @@ -5474,8 +5474,8 @@ void *miner_thread(void *userdata) } out: - if (api->thread_shutdown) - api->thread_shutdown(mythr); + if (drv->thread_shutdown) + drv->thread_shutdown(mythr); thread_reportin(mythr); applog(LOG_ERR, "Thread %d failure, exiting", thr_id); @@ -5703,8 +5703,8 @@ out: void reinit_device(struct cgpu_info *cgpu) { - if (cgpu->api->reinit_device) - cgpu->api->reinit_device(cgpu); + if (cgpu->drv->reinit_device) + cgpu->drv->reinit_device(cgpu); } static struct timeval rotate_tv; @@ -5879,12 +5879,12 @@ static void *watchdog_thread(void __maybe_unused *userdata) char dev_str[8]; int gpu; - if (cgpu->api->get_stats) - cgpu->api->get_stats(cgpu); + if (cgpu->drv->get_stats) + cgpu->drv->get_stats(cgpu); gpu = cgpu->device_id; denable = &cgpu->deven; - sprintf(dev_str, "%s%d", cgpu->api->name, gpu); + sprintf(dev_str, "%s%d", cgpu->drv->name, gpu); #ifdef HAVE_ADL if (adl_active && cgpu->has_adl) @@ -5904,7 +5904,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) continue; #ifdef WANT_CPUMINE - if (!strcmp(cgpu->api->dname, "cpu")) + if (cgpu->drv->drv != DRIVER_CPU) continue; #endif if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { @@ -6294,26 +6294,27 @@ void enable_curses(void) { /* TODO: fix need a dummy CPU device_api even if no support for CPU mining */ #ifndef WANT_CPUMINE -struct device_api cpu_api; -struct device_api cpu_api = { +struct device_drv cpu_drv; +struct device_drv cpu_drv = { + .drv = DRIVER_CPU, .name = "CPU", }; #endif #ifdef USE_BITFORCE -extern struct device_api bitforce_api; +extern struct device_drv bitforce_drv; #endif #ifdef USE_ICARUS -extern struct device_api icarus_api; +extern struct device_drv icarus_drv; #endif #ifdef USE_MODMINER -extern struct device_api modminer_api; +extern struct device_drv modminer_drv; #endif #ifdef USE_ZTEX -extern struct device_api ztex_api; +extern struct device_drv ztex_drv; #endif @@ -6328,7 +6329,7 @@ void enable_device(struct cgpu_info *cgpu) adj_width(mining_threads, &dev_width); #endif #ifdef HAVE_OPENCL - if (cgpu->api == &opencl_api) { + if (cgpu->drv->drv == DRIVER_OPENCL) { gpu_threads += cgpu->threads; } #endif @@ -6345,12 +6346,12 @@ bool add_cgpu(struct cgpu_info*cgpu) static struct _cgpu_devid_counter *devids = NULL; struct _cgpu_devid_counter *d; - HASH_FIND_STR(devids, cgpu->api->name, d); + HASH_FIND_STR(devids, cgpu->drv->name, d); if (d) cgpu->device_id = ++d->lastid; else { d = malloc(sizeof(*d)); - memcpy(d->name, cgpu->api->name, sizeof(d->name)); + memcpy(d->name, cgpu->drv->name, sizeof(d->name)); cgpu->device_id = d->lastid = 0; HASH_ADD_STR(devids, name, d); } @@ -6568,32 +6569,32 @@ int main(int argc, char *argv[]) #ifdef HAVE_OPENCL if (!opt_nogpu) - opencl_api.api_detect(); + opencl_drv.drv_detect(); gpu_threads = 0; #endif #ifdef USE_ICARUS if (!opt_scrypt) - icarus_api.api_detect(); + icarus_drv.drv_detect(); #endif #ifdef USE_BITFORCE if (!opt_scrypt) - bitforce_api.api_detect(); + bitforce_drv.drv_detect(); #endif #ifdef USE_MODMINER if (!opt_scrypt) - modminer_api.api_detect(); + modminer_drv.drv_detect(); #endif #ifdef USE_ZTEX if (!opt_scrypt) - ztex_api.api_detect(); + ztex_drv.drv_detect(); #endif #ifdef WANT_CPUMINE - cpu_api.api_detect(); + cpu_drv.drv_detect(); #endif if (devices_enabled == -1) { @@ -6601,9 +6602,9 @@ int main(int argc, char *argv[]) for (i = 0; i < total_devices; ++i) { struct cgpu_info *cgpu = devices[i]; if (cgpu->name) - applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->name, cgpu->api->dname); + applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->name, cgpu->drv->dname); else - applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->api->dname); + applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->drv->dname); } quit(0, "%d devices listed", total_devices); } @@ -6617,7 +6618,7 @@ int main(int argc, char *argv[]) enable_device(devices[i]); } else if (i < total_devices) { if (opt_removedisabled) { - if (devices[i]->api == &cpu_api) + if (devices[i]->drv->drv == DRIVER_CPU) --opt_n_threads; } else { enable_device(devices[i]); @@ -6789,7 +6790,7 @@ begin_bench: thr->q = tq_new(); if (!thr->q) - quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->api->name, cgpu->device_id, i); + quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->drv->name, cgpu->device_id, i); /* Enable threads for devices set not to mine but disable * their queue in case we wish to enable them later */ @@ -6799,7 +6800,7 @@ begin_bench: tq_push(thr->q, &ping); } - if (cgpu->api->thread_prepare && !cgpu->api->thread_prepare(thr)) + if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr)) continue; thread_reportout(thr); diff --git a/driver-bitforce.c b/driver-bitforce.c index 4a06b597..f1196322 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -64,7 +64,7 @@ static const char *blank = ""; -struct device_api bitforce_api; +struct device_drv bitforce_drv; static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) { @@ -78,14 +78,14 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); if (opt_debug) applog(LOG_DEBUG, "%s%i: reset got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set data control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); if (opt_debug) applog(LOG_DEBUG, "%s%i: setdata got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set the baud err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, @@ -93,35 +93,35 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) C_SETBAUD); if (opt_debug) applog(LOG_DEBUG, "%s%i: setbaud got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set Flow Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); if (opt_debug) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set Modem Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); if (opt_debug) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Clear any sent data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); if (opt_debug) applog(LOG_DEBUG, "%s%i: purgetx got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Clear any received data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); if (opt_debug) applog(LOG_DEBUG, "%s%i: purgerx got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); if (lock) mutex_unlock(&bitforce->device_mutex); @@ -136,13 +136,13 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); - bitforce->api = &bitforce_api; + bitforce->drv = &bitforce_drv; bitforce->deven = DEV_ENABLED; bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", - bitforce->api->dname, + bitforce->drv->dname, (int)libusb_get_bus_number(dev), (int)libusb_get_device_address(dev)); goto shin; @@ -159,7 +159,7 @@ reinit: if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); goto unshin; } @@ -168,7 +168,7 @@ reinit: if (++init_count <= REINIT_COUNT) { if (init_count < 2) { applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); } nmsleep(REINIT_TIME_MS); goto reinit; @@ -176,14 +176,14 @@ reinit: if (init_count > 0) applog(LOG_WARNING, "%s detect (%s) init failed %d times", - bitforce->api->dname, devpath, init_count); + bitforce->drv->dname, devpath, init_count); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); } else { applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", - bitforce->api->dname, devpath, amount); + bitforce->drv->dname, devpath, amount); } goto unshin; @@ -192,7 +192,7 @@ reinit: if (unlikely(!strstr(buf, "SHA256"))) { applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", - bitforce->api->dname, devpath, buf); + bitforce->drv->dname, devpath, buf); goto unshin; } @@ -205,7 +205,7 @@ reinit: // We have a real BitForce! applog(LOG_DEBUG, "%s (%s) identified as: '%s'", - bitforce->api->dname, devpath, bitforce->name); + bitforce->drv->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ @@ -247,7 +247,7 @@ shin: static void bitforce_detect(void) { - usb_detect(&bitforce_api, bitforce_detect_one); + usb_detect(&bitforce_drv, bitforce_detect_one); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) @@ -288,7 +288,7 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } else { /* However, this stops anything else getting a reply * So best to delay any other access to the BFL */ @@ -328,7 +328,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); bitforce->hw_errors++; return false; } @@ -337,10 +337,10 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) mutex_unlock(&bitforce->device_mutex); if (err < 0) { applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } else { applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } bitforce->hw_errors++; return false; @@ -360,7 +360,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) bitforce->temp = temp; if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) { applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->deven = DEV_RECOVER; dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF); } @@ -370,7 +370,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) * our responses are out of sync and flush the buffer to * hopefully recover */ applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_THROTTLE); /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; @@ -404,14 +404,14 @@ re_send: if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } @@ -423,14 +423,14 @@ re_send: mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } applog(LOG_ERR, "%s%i: Error: Send work reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); return false; } @@ -458,14 +458,14 @@ re_send: if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: send work failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } @@ -474,19 +474,19 @@ re_send: if (opt_debug) { s = bin2hex(ob + 8, 44); applog(LOG_DEBUG, "%s%i: block data: %s", - bitforce->api->name, bitforce->device_id, s); + bitforce->drv->name, bitforce->device_id, s); free(s); } if (amount == 0 || !buf[0]) { applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); return false; } if (unlikely(strncasecmp(buf, "OK", 2))) { applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); return false; } @@ -519,7 +519,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %dms - longer than %dms", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } @@ -535,7 +535,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %dms - longer than %dms", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); dev_error(bitforce, REASON_DEV_OVER_HEAT); @@ -560,7 +560,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (delay_time_ms != bitforce->sleep_ms) applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ @@ -569,7 +569,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) } applog(LOG_DEBUG, "%s%i: waited %dms until %s", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, bitforce->wait_ms, buf); if (!strncasecmp(&buf[2], "-", 1)) return bitforce->nonces; /* No valid nonce found */ @@ -578,7 +578,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) else if (strncasecmp(buf, "NONCE-FOUND", 11)) { bitforce->hw_errors++; applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); bitforce_initialise(bitforce, true); return 0; } @@ -593,7 +593,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; @@ -643,7 +643,7 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ if (ret == -1) { ret = 0; - applog(LOG_ERR, "%s%i: Comms error", bitforce->api->name, bitforce->device_id); + applog(LOG_ERR, "%s%i: Comms error", bitforce->drv->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_COMMS_ERROR); bitforce->hw_errors++; /* empty read buffer */ @@ -671,7 +671,7 @@ static bool bitforce_thread_init(struct thr_info *thr) * so the devices aren't making calls all at the same time. */ wait = thr->id * MAX_START_DELAY_MS; applog(LOG_DEBUG, "%s%d: Delaying start by %dms", - bitforce->api->name, bitforce->device_id, wait / 1000); + bitforce->drv->name, bitforce->device_id, wait / 1000); nmsleep(wait); return true; @@ -691,10 +691,11 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) return root; } -struct device_api bitforce_api = { +struct device_drv bitforce_drv = { + .drv = DRIVER_BITFORCE, .dname = "bitforce", .name = "BFL", - .api_detect = bitforce_detect, + .drv_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, .get_statline_before = get_bitforce_statline_before, .get_stats = bitforce_get_stats, diff --git a/driver-cpu.c b/driver-cpu.c index 75d9a5a4..99c5a3fa 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -758,7 +758,7 @@ static void cpu_detect() struct cgpu_info *cgpu; cgpu = &cpus[i]; - cgpu->api = &cpu_api; + cgpu->drv = &cpu_drv; cgpu->deven = DEV_ENABLED; cgpu->threads = 1; cgpu->kname = algo_names[opt_algo]; @@ -843,10 +843,10 @@ CPUSearch: return last_nonce - first_nonce + 1; } -struct device_api cpu_api = { +struct device_drv cpu_drv = { .dname = "cpu", .name = "CPU", - .api_detect = cpu_detect, + .drv_detect = cpu_detect, .reinit_device = reinit_cpu_device, .thread_prepare = cpu_thread_prepare, .can_limit_work = cpu_can_limit_work, diff --git a/driver-cpu.h b/driver-cpu.h index e4b44527..361ae5d8 100644 --- a/driver-cpu.h +++ b/driver-cpu.h @@ -53,7 +53,7 @@ enum sha256_algos { extern const char *algo_names[]; extern bool opt_usecpu; -extern struct device_api cpu_api; +extern struct device_drv cpu_drv; extern char *set_algo(const char *arg, enum sha256_algos *algo); extern void show_algo(char buf[OPT_SHOW_LEN], const enum sha256_algos *algo); diff --git a/driver-icarus.c b/driver-icarus.c index c979a681..f42e7214 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -208,7 +208,7 @@ static struct ICARUS_INFO **icarus_info; // static int option_offset = -1; -struct device_api icarus_api; +struct device_drv icarus_drv; static void rev(unsigned char *s, size_t l) { @@ -571,7 +571,7 @@ static bool icarus_detect_one(const char *devpath) /* We have a real Icarus! */ struct cgpu_info *icarus; icarus = calloc(1, sizeof(struct cgpu_info)); - icarus->api = &icarus_api; + icarus->drv = &icarus_drv; icarus->device_path = strdup(devpath); icarus->device_fd = -1; icarus->threads = 1; @@ -609,7 +609,7 @@ static bool icarus_detect_one(const char *devpath) static void icarus_detect() { - serial_detect(&icarus_api, icarus_detect_one); + serial_detect(&icarus_drv, icarus_detect_one); } static bool icarus_prepare(struct thr_info *thr) @@ -900,10 +900,11 @@ static void icarus_shutdown(struct thr_info *thr) do_icarus_close(thr); } -struct device_api icarus_api = { +struct device_drv icarus_drv = { + .drv = DRIVER_ICARUS, .dname = "icarus", .name = "ICA", - .api_detect = icarus_detect, + .drv_detect = icarus_detect, .get_api_stats = icarus_api_stats, .thread_prepare = icarus_prepare, .scanhash = icarus_scanhash, diff --git a/driver-modminer.c b/driver-modminer.c index c48a51bc..0868e85e 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -87,7 +87,7 @@ // Limit when reducing shares_to_good #define MODMINER_MIN_BACK 12 -struct device_api modminer_api; +struct device_drv modminer_drv; // 45 noops sent when detecting, in case the device was left in "start job" reading static const char NOOP[] = MODMINER_PING "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; @@ -100,15 +100,15 @@ static void do_ping(struct cgpu_info *modminer) // Don't care if it fails err = usb_write(modminer, (char *)NOOP, sizeof(NOOP)-1, &amount, C_PING); applog(LOG_DEBUG, "%s%u: flush noop got %d err %d", - modminer->api->name, modminer->fpgaid, amount, err); + modminer->drv->name, modminer->fpgaid, amount, err); // Clear any outstanding data while ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_CLEAR)) == 0 && amount > 0) applog(LOG_DEBUG, "%s%u: clear got %d", - modminer->api->name, modminer->fpgaid, amount); + modminer->drv->name, modminer->fpgaid, amount); applog(LOG_DEBUG, "%s%u: final clear got %d err %d", - modminer->api->name, modminer->fpgaid, amount, err); + modminer->drv->name, modminer->fpgaid, amount, err); } static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devices *found) @@ -121,7 +121,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic struct cgpu_info *modminer = NULL; modminer = calloc(1, sizeof(*modminer)); - modminer->api = &modminer_api; + modminer->drv = &modminer_drv; modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex))); mutex_init(modminer->modminer_mutex); modminer->fpgaid = (char)0; @@ -182,7 +182,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic for (i = 0; i < buf[0]; i++) { struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); - tmp->api = modminer->api; + tmp->drv = modminer->drv; tmp->name = devname; sprintf(devpath, "%d:%d:%d", @@ -233,7 +233,7 @@ shin: static void modminer_detect() { - usb_detect(&modminer_api, modminer_detect_one); + usb_detect(&modminer_drv, modminer_detect_one); } static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) @@ -242,13 +242,13 @@ static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) if (fread(&buf, 1, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream (%c)", - modminer->api->name, modminer->device_id, errno, c); + modminer->drv->name, modminer->device_id, errno, c); return false; } if (buf != c) { applog(LOG_ERR, "%s%u: firmware code mismatch (%c)", - modminer->api->name, modminer->device_id, c); + modminer->drv->name, modminer->device_id, c); return false; } @@ -262,7 +262,7 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz, if (fread(siz, 2, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s' len", - modminer->api->name, modminer->device_id, errno, name); + modminer->drv->name, modminer->device_id, errno, name); return false; } @@ -270,13 +270,13 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz, if (len >= bufsiz) { applog(LOG_ERR, "%s%u: Bitstream '%s' len too large (%d)", - modminer->api->name, modminer->device_id, name, len); + modminer->drv->name, modminer->device_id, name, len); return false; } if (fread(buf, len, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s'", errno, - modminer->api->name, modminer->device_id, errno, name); + modminer->drv->name, modminer->device_id, errno, name); return false; } @@ -302,7 +302,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d:%d) getting %s reply", - modminer->api->name, modminer->device_id, amount, err, msg); + modminer->drv->name, modminer->device_id, amount, err, msg); return false; } @@ -311,7 +311,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error, invalid %s reply (was %d should be 1)", - modminer->api->name, modminer->device_id, msg, buf[0]); + modminer->drv->name, modminer->device_id, msg, buf[0]); return false; } @@ -343,7 +343,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) opening bitstream file %s", - modminer->api->name, modminer->device_id, errno, bsfile); + modminer->drv->name, modminer->device_id, errno, bsfile); return false; } @@ -352,7 +352,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) reading bitstream magic", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -361,7 +361,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream has incorrect magic (%u,%u) instead of (%u,%u)", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, buf[0], buf[1], BITSTREAM_MAGIC_0, BITSTREAM_MAGIC_1); @@ -372,7 +372,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) bitstream seek failed", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -384,7 +384,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) goto undame; applog(LOG_DEBUG, "%s%u: bitstream file '%s' info:", - modminer->api->name, modminer->device_id, bsfile); + modminer->drv->name, modminer->device_id, bsfile); applog(LOG_DEBUG, " Design name: '%s'", buf); @@ -399,7 +399,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Bad usercode in bitstream file", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); goto dame; } @@ -408,7 +408,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream doesn't support user code", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); goto dame; } @@ -446,7 +446,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) reading bitstream data len", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -460,7 +460,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) *ptr = '\0'; applog(LOG_WARNING, "%s%u: Programming all FPGA on %s ... Mining will not start until complete", - modminer->api->name, modminer->device_id, devmsg); + modminer->drv->name, modminer->device_id, devmsg); buf[0] = MODMINER_PROGRAM; buf[1] = fpgaid; @@ -473,7 +473,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Program init failed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); goto dame; } @@ -492,7 +492,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream file read error %d (%d bytes left)", - modminer->api->name, modminer->device_id, errno, len); + modminer->drv->name, modminer->device_id, errno, len); goto dame; } @@ -507,7 +507,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) if (opt_debug) applog(LOG_DEBUG, "%s%u: Program timeout (%d:%d) sent %d tries %d", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, amount, err, remaining, tries); if (!get_status(modminer, "write status", C_PROGRAMSTATUS2)) @@ -517,7 +517,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Program failed (%d:%d) sent %d", - modminer->api->name, modminer->device_id, amount, err, remaining); + modminer->drv->name, modminer->device_id, amount, err, remaining); goto dame; } @@ -532,7 +532,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) if (upto >= nextmsg) { applog(LOG_WARNING, "%s%u: Programming %.1f%% (%d out of %d)", - modminer->api->name, modminer->device_id, upto*100, (totlen - len), totlen); + modminer->drv->name, modminer->device_id, upto*100, (totlen - len), totlen); nextmsg += 0.1; } @@ -542,7 +542,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) goto undame; applog(LOG_WARNING, "%s%u: Programming completed for all FPGA on %s", - modminer->api->name, modminer->device_id, devmsg); + modminer->drv->name, modminer->device_id, devmsg); // Give it a 2/3s delay after programming nmsleep(666); @@ -653,7 +653,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error writing set clock speed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return clocksetfail; } @@ -662,7 +662,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error reading set clock speed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return clockreplyfail; } @@ -670,7 +670,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_WARNING, "%s%u: Set clock speed %sto %u", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, (delta < 0) ? "down " : (delta > 0 ? "up " : ""), modminer->clock); @@ -691,7 +691,7 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error requesting USER code (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } @@ -700,14 +700,14 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error reading USER code (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } if (memcmp(buf, BISTREAM_USER_ID, 4)) { applog(LOG_ERR, "%s%u: FPGA not programmed", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); if (!modminer_fpga_upload_bitstream(modminer)) return false; @@ -717,7 +717,7 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_DEBUG, "%s%u: FPGA is already programmed :)", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); } modminer->clock = MODMINER_DEF_CLOCK; @@ -773,7 +773,7 @@ static bool modminer_start_work(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } @@ -827,14 +827,14 @@ static void check_temperature(struct thr_info *thr) if (modminer->temp < MODMINER_RECOVER_TEMP) { state->overheated = false; applog(LOG_WARNING, "%s%u: Recovered, temp less than (%.1f) now %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_RECOVER_TEMP, modminer->temp); } } else if (modminer->temp >= MODMINER_OVERHEAT_TEMP) { if (modminer->temp >= MODMINER_CUTOFF_TEMP) { applog(LOG_WARNING, "%s%u: Hit thermal cutoff limit! (%.1f) at %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_CUTOFF_TEMP, modminer->temp); modminer_delta_clock(thr, MODMINER_CLOCK_CUTOFF, true, false); @@ -842,7 +842,7 @@ static void check_temperature(struct thr_info *thr) dev_error(modminer, REASON_DEV_THERMAL_CUTOFF); } else { applog(LOG_WARNING, "%s%u: Overheat limit (%.1f) reached %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_OVERHEAT_TEMP, modminer->temp); // If it's defined to be 0 then don't call modminer_delta_clock() @@ -909,7 +909,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } applog(LOG_ERR, "%s%u: Error sending (get nonce) (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return -1; } @@ -936,7 +936,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } applog(LOG_ERR, "%s%u: Error reading (get nonce) (%d:%d)", - modminer->api->name, modminer->device_id, amount+amount2, err); + modminer->drv->name, modminer->device_id, amount+amount2, err); } if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) { @@ -975,7 +975,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) if (state->death_stage_one) { modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true); applog(LOG_ERR, "%s%u: DEATH clock down", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); // reset the death info and DISABLE it state->last_nonce.tv_sec = 0; @@ -985,7 +985,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } else { modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true); applog(LOG_ERR, "%s%u: death clock down", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); state->death_stage_one = true; } @@ -1141,10 +1141,11 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char return replybuf; } -struct device_api modminer_api = { +struct device_drv modminer_drv = { + .drv = DRIVER_MODMINER, .dname = "modminer", .name = "MMQ", - .api_detect = modminer_detect, + .drv_detect = modminer_detect, .get_statline_before = get_modminer_statline_before, .set_device = modminer_set_device, .thread_prepare = modminer_fpga_prepare, diff --git a/driver-opencl.c b/driver-opencl.c index 01e70198..966d8cd0 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -50,24 +50,24 @@ extern int gpur_thr_id; extern bool opt_noadl; extern bool have_opencl; - - extern void *miner_thread(void *userdata); extern int dev_from_id(int thr_id); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlog(const char *f, ...); extern void decay_time(double *f, double fadd); - /**********************************************/ +#ifdef HAVE_OPENCL +struct device_drv opencl_drv; +#endif + #ifdef HAVE_ADL extern float gpu_temp(int gpu); extern int gpu_fanspeed(int gpu); extern int gpu_fanpercent(int gpu); #endif - #ifdef HAVE_OPENCL char *set_vector(char *arg) { @@ -591,28 +591,20 @@ char *set_intensity(char *arg) return NULL; } -#endif - - -#ifdef HAVE_OPENCL -struct device_api opencl_api; char *print_ndevs_and_exit(int *ndevs) { opt_log_output = true; - opencl_api.api_detect(); + opencl_drv.drv_detect(); clear_adl(*ndevs); applog(LOG_INFO, "%i GPU devices max detected", *ndevs); exit(*ndevs); } #endif - struct cgpu_info gpus[MAX_GPUDEVICES]; /* Maximum number apparently possible */ struct cgpu_info *cpus; - - #ifdef HAVE_OPENCL /* In dynamic mode, only the first thread of each device will be in use. @@ -637,9 +629,6 @@ void pause_dynamic_threads(int gpu) } } - -struct device_api opencl_api; - #endif /* HAVE_OPENCL */ #if defined(HAVE_OPENCL) && defined(HAVE_CURSES) @@ -773,7 +762,7 @@ retry: for (i = 0; i < mining_threads; ++i) { thr = &thr_info[i]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(i) != selected) continue; @@ -1160,7 +1149,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1185,7 +1174,7 @@ select_cgpu: thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1222,7 +1211,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1243,8 +1232,6 @@ void *reinit_gpu(__maybe_unused void *userdata) #ifdef HAVE_OPENCL -struct device_api opencl_api; - static void opencl_detect() { int i; @@ -1263,7 +1250,7 @@ static void opencl_detect() cgpu = &gpus[i]; cgpu->deven = DEV_ENABLED; - cgpu->api = &opencl_api; + cgpu->drv = &opencl_drv; cgpu->device_id = i; cgpu->threads = opt_g_threads; cgpu->virtual_gpu = i; @@ -1570,10 +1557,11 @@ static void opencl_thread_shutdown(struct thr_info *thr) clReleaseContext(clState->context); } -struct device_api opencl_api = { +struct device_drv opencl_drv = { + .drv = DRIVER_OPENCL, .dname = "opencl", .name = "GPU", - .api_detect = opencl_detect, + .drv_detect = opencl_detect, .reinit_device = reinit_opencl_device, #ifdef HAVE_ADL .get_statline_before = get_opencl_statline_before, diff --git a/driver-opencl.h b/driver-opencl.h index c1d61822..22bd9ec2 100644 --- a/driver-opencl.h +++ b/driver-opencl.h @@ -30,6 +30,6 @@ extern void pause_dynamic_threads(int gpu); extern bool have_opencl; extern int opt_platform_id; -extern struct device_api opencl_api; +extern struct device_drv opencl_drv; #endif /* __DEVICE_GPU_H__ */ diff --git a/driver-ztex.c b/driver-ztex.c index 23aa97e4..4a61a5c5 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -30,7 +30,7 @@ #define GOLDEN_BACKLOG 5 -struct device_api ztex_api; +struct device_drv ztex_drv; // Forward declarations static void ztex_disable(struct thr_info* thr); @@ -68,7 +68,7 @@ static void ztex_detect(void) for (i = 0; i < cnt; i++) { ztex = calloc(1, sizeof(struct cgpu_info)); - ztex->api = &ztex_api; + ztex->drv = &ztex_drv; ztex->device_ztex = ztex_devices[i]->dev; ztex->threads = 1; ztex->device_ztex->fpgaNum = 0; @@ -82,7 +82,7 @@ static void ztex_detect(void) for (j = 1; j < fpgacount; j++) { ztex = calloc(1, sizeof(struct cgpu_info)); - ztex->api = &ztex_api; + ztex->drv = &ztex_drv; ztex_slave = calloc(1, sizeof(struct libztex_device)); memcpy(ztex_slave, ztex_devices[i]->dev, sizeof(struct libztex_device)); ztex->device_ztex = ztex_slave; @@ -394,10 +394,10 @@ static void ztex_disable(struct thr_info *thr) ztex_shutdown(thr); } -struct device_api ztex_api = { +struct device_drv ztex_drv = { .dname = "ztex", .name = "ZTX", - .api_detect = ztex_detect, + .drv_detect = ztex_detect, .get_statline_before = ztex_statline_before, .thread_prepare = ztex_prepare, .scanhash = ztex_scanhash, diff --git a/findnonce.c b/findnonce.c index bf39a122..fcf75f23 100644 --- a/findnonce.c +++ b/findnonce.c @@ -204,7 +204,7 @@ static void *postcalc_hash(void *userdata) * end of the res[] array */ if (unlikely(pcd->res[FOUND] & ~FOUND)) { applog(LOG_WARNING, "%s%d: invalid nonce count - HW error", - thr->cgpu->api->name, thr->cgpu->device_id); + thr->cgpu->drv->name, thr->cgpu->device_id); hw_errors++; thr->cgpu->hw_errors++; pcd->res[FOUND] &= FOUND; diff --git a/fpgautils.c b/fpgautils.c index 487395cc..307bec49 100644 --- a/fpgautils.c +++ b/fpgautils.c @@ -104,14 +104,14 @@ int serial_autodetect_devserial(__maybe_unused detectone_func_t detectone, __may #endif } -int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) +int _serial_detect(struct device_drv *drv, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) { struct string_elist *iter, *tmp; const char *dev, *colon; bool inhibitauto = false; char found = 0; - size_t namel = strlen(api->name); - size_t dnamel = strlen(api->dname); + size_t namel = strlen(drv->name); + size_t dnamel = strlen(drv->dname); list_for_each_entry_safe(iter, tmp, &scan_devices, list) { dev = iter->string; @@ -119,8 +119,8 @@ int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_ size_t idlen = colon - dev; // allow either name:device or dname:device - if ((idlen != namel || strncasecmp(dev, api->name, idlen)) - && (idlen != dnamel || strncasecmp(dev, api->dname, idlen))) + if ((idlen != namel || strncasecmp(dev, drv->name, idlen)) + && (idlen != dnamel || strncasecmp(dev, drv->dname, idlen))) continue; dev = colon + 1; diff --git a/fpgautils.h b/fpgautils.h index 18025488..b979b6c6 100644 --- a/fpgautils.h +++ b/fpgautils.h @@ -16,13 +16,13 @@ typedef bool(*detectone_func_t)(const char*); typedef int(*autoscan_func_t)(); -extern int _serial_detect(struct device_api *api, detectone_func_t, autoscan_func_t, bool force_autoscan); -#define serial_detect_fauto(api, detectone, autoscan) \ - _serial_detect(api, detectone, autoscan, true) -#define serial_detect_auto(api, detectone, autoscan) \ - _serial_detect(api, detectone, autoscan, false) -#define serial_detect(api, detectone) \ - _serial_detect(api, detectone, NULL, false) +extern int _serial_detect(struct device_drv *drv, detectone_func_t, autoscan_func_t, bool force_autoscan); +#define serial_detect_fauto(drv, detectone, autoscan) \ + _serial_detect(drv, detectone, autoscan, true) +#define serial_detect_auto(drv, detectone, autoscan) \ + _serial_detect(drv, detectone, autoscan, false) +#define serial_detect(drv, detectone) \ + _serial_detect(drv, detectone, NULL, false) extern int serial_autodetect_devserial(detectone_func_t, const char *prodname); extern int serial_autodetect_udev(detectone_func_t, const char *prodname); diff --git a/miner.h b/miner.h index d892ed03..4e888f32 100644 --- a/miner.h +++ b/miner.h @@ -196,6 +196,15 @@ static inline int fsync (int fd) #endif #endif +enum drv_driver { + DRIVER_OPENCL, + DRIVER_ICARUS, + DRIVER_BITFORCE, + DRIVER_MODMINER, + DRIVER_ZTEX, + DRIVER_CPU, +}; + enum alive { LIFE_WELL, LIFE_SICK, @@ -263,12 +272,14 @@ struct api_data; struct thr_info; struct work; -struct device_api { +struct device_drv { + enum drv_driver drv; + char *dname; char *name; - // API-global functions - void (*api_detect)(); + // DRV-global functions + void (*drv_detect)(); // Device-specific functions void (*reinit_device)(struct cgpu_info *); @@ -365,7 +376,7 @@ struct cgminer_pool_stats { struct cgpu_info { int cgminer_id; - struct device_api *api; + struct device_drv *drv; int device_id; char *name; char *device_path; diff --git a/usbutils.c b/usbutils.c index 0d9e79aa..bebd722d 100644 --- a/usbutils.c +++ b/usbutils.c @@ -99,15 +99,15 @@ static struct usb_find_devices find_dev[] = { }; #ifdef USE_BITFORCE -extern struct device_api bitforce_api; +extern struct device_drv bitforce_drv; #endif #ifdef USE_ICARUS -extern struct device_api icarus_api; +extern struct device_drv icarus_drv; #endif #ifdef USE_MODMINER -extern struct device_api modminer_api; +extern struct device_drv modminer_drv; #endif /* @@ -907,7 +907,7 @@ dame: return false; } -static bool usb_check_device(struct device_api *api, struct libusb_device *dev, struct usb_find_devices *look) +static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, struct usb_find_devices *look) { struct libusb_device_descriptor desc; int err; @@ -920,25 +920,25 @@ static bool usb_check_device(struct device_api *api, struct libusb_device *dev, if (desc.idVendor != look->idVendor || desc.idProduct != look->idProduct) { applog(LOG_DEBUG, "%s looking for %04x:%04x but found %04x:%04x instead", - api->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); + drv->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); return false; } applog(LOG_DEBUG, "%s looking for and found %04x:%04x", - api->name, look->idVendor, look->idProduct); + drv->name, look->idVendor, look->idProduct); return true; } -static struct usb_find_devices *usb_check_each(int drv, struct device_api *api, struct libusb_device *dev) +static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *drv, struct libusb_device *dev) { struct usb_find_devices *found; int i; for (i = 0; find_dev[i].drv != DRV_LAST; i++) - if (find_dev[i].drv == drv) { - if (usb_check_device(api, dev, &(find_dev[i]))) { + if (find_dev[i].drv == drvnum) { + if (usb_check_device(drv, dev, &(find_dev[i]))) { found = malloc(sizeof(*found)); memcpy(found, &(find_dev[i]), sizeof(*found)); return found; @@ -948,27 +948,27 @@ static struct usb_find_devices *usb_check_each(int drv, struct device_api *api, return NULL; } -static struct usb_find_devices *usb_check(__maybe_unused struct device_api *api, __maybe_unused struct libusb_device *dev) +static struct usb_find_devices *usb_check(__maybe_unused struct device_drv *drv, __maybe_unused struct libusb_device *dev) { #ifdef USE_BITFORCE - if (api == &bitforce_api) - return usb_check_each(DRV_BITFORCE, api, dev); + if (drv->drv == DRIVER_BITFORCE) + return usb_check_each(DRV_BITFORCE, drv, dev); #endif #ifdef USE_ICARUS - if (api == &icarus_api) - return usb_check_each(DRV_ICARUS, api, dev); + if (drv->drv == DRIVER_ICARUS) + return usb_check_each(DRV_ICARUS, drv, dev); #endif #ifdef USE_MODMINER - if (api == &modminer_api) - return usb_check_each(DRV_MODMINER, api, dev); + if (drv->drv == DRIVER_MODMINER) + return usb_check_each(DRV_MODMINER, drv, dev); #endif return NULL; } -void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)) +void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)) { libusb_device **list; ssize_t count, i; @@ -995,7 +995,7 @@ void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_devi mutex_unlock(list_lock); - found = usb_check(api, list[i]); + found = usb_check(drv, list[i]); if (!found) release_dev(list[i], true); else @@ -1106,7 +1106,7 @@ static void newstats(struct cgpu_info *cgpu) cgpu->usbstat = ++next_stat; usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); - usb_stats[next_stat-1].name = cgpu->api->name; + usb_stats[next_stat-1].name = cgpu->drv->name; usb_stats[next_stat-1].device_id = -1; usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); for (i = 1; i < C_MAX * 2; i += 2) diff --git a/usbutils.h b/usbutils.h index 156e2a2d..2ee86150 100644 --- a/usbutils.h +++ b/usbutils.h @@ -116,12 +116,12 @@ enum usb_cmds { C_MAX }; -struct device_api; +struct device_drv; struct cgpu_info; void usb_uninit(struct cgpu_info *cgpu); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); -void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); +void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); void update_usb_stats(struct cgpu_info *cgpu); int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds, bool ftdi); From a4e95cfa424084b26a900d3e31f5ec6e5152b70c Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 6 Jan 2013 01:00:18 +1100 Subject: [PATCH 16/47] device_drv missing drv for cpu and incorrect test --- cgminer.c | 2 +- driver-cpu.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index adf7db45..177f61c4 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5904,7 +5904,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) continue; #ifdef WANT_CPUMINE - if (cgpu->drv->drv != DRIVER_CPU) + if (cgpu->drv->drv == DRIVER_CPU) continue; #endif if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { diff --git a/driver-cpu.c b/driver-cpu.c index 99c5a3fa..eb46f3d8 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -844,6 +844,7 @@ CPUSearch: } struct device_drv cpu_drv = { + .drv = DRIVER_CPU, .dname = "cpu", .name = "CPU", .drv_detect = cpu_detect, From f9e04a3c5b311e2a1f54ca5729d974825b5f09ea Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 6 Jan 2013 21:00:38 +1100 Subject: [PATCH 17/47] device_drv - allow .name to be changed before add_cgpu() --- cgminer.c | 15 +++++++++++++++ driver-bitforce.c | 3 +++ driver-modminer.c | 10 +++++++++- miner.h | 5 +++++ usbutils.c | 16 ++++++++++++---- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/cgminer.c b/cgminer.c index 177f61c4..befe57e7 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6360,6 +6360,21 @@ bool add_cgpu(struct cgpu_info*cgpu) return true; } +struct device_drv *copy_drv(struct device_drv *drv) +{ + struct device_drv *copy; + char buf[100]; + + if (unlikely(!(copy = malloc(sizeof(*copy))))) { + sprintf(buf, "Failed to allocate device_drv copy of %s (%s)", + drv->name, drv->copy ? "copy" : "original"); + quit(1, buf); + } + memcpy(copy, drv, sizeof(*copy)); + copy->copy = true; + return copy; +} + int main(int argc, char *argv[]) { bool pools_active = false; diff --git a/driver-bitforce.c b/driver-bitforce.c index f1196322..0181b170 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -240,6 +240,9 @@ shin: if (bitforce->name != blank) free(bitforce->name); + if (bitforce->drv->copy) + free(bitforce->drv); + free(bitforce); return false; diff --git a/driver-modminer.c b/driver-modminer.c index 0868e85e..246947b4 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -182,7 +182,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic for (i = 0; i < buf[0]; i++) { struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); - tmp->drv = modminer->drv; + tmp->drv = copy_drv(modminer->drv); tmp->name = devname; sprintf(devpath, "%d:%d:%d", @@ -202,6 +202,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic if (!add_cgpu(tmp)) { free(tmp->device_path); + if (tmp->drv->copy) + free(tmp->drv); free(tmp); goto unshin; } @@ -211,6 +213,9 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic added = true; } + if (modminer->drv->copy) + free(modminer->drv); + free(modminer); return true; @@ -223,6 +228,9 @@ shin: if (!added) free(modminer->modminer_mutex); + if (modminer->drv->copy) + free(modminer->drv); + free(modminer); if (added) diff --git a/miner.h b/miner.h index 4e888f32..b89d072e 100644 --- a/miner.h +++ b/miner.h @@ -299,8 +299,13 @@ struct device_drv { void (*hw_error)(struct thr_info *); void (*thread_shutdown)(struct thr_info *); void (*thread_enable)(struct thr_info *); + + // Does it need to be free()d? + bool copy; }; +extern struct device_drv *copy_drv(struct device_drv*); + enum dev_enable { DEV_ENABLED, DEV_DISABLED, diff --git a/usbutils.c b/usbutils.c index bebd722d..ebfcc0b2 100644 --- a/usbutils.c +++ b/usbutils.c @@ -891,6 +891,14 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find libusb_free_config_descriptor(config); + // Allow a name change based on the idVendor+idProduct + // N.B. must be done before calling add_cgpu() + if (strcmp(cgpu->drv->name, found->name)) { + if (!cgpu->drv->copy) + cgpu->drv = copy_drv(cgpu->drv); + cgpu->drv->name = (char *)(found->name); + } + return true; cldame: @@ -919,14 +927,14 @@ static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, } if (desc.idVendor != look->idVendor || desc.idProduct != look->idProduct) { - applog(LOG_DEBUG, "%s looking for %04x:%04x but found %04x:%04x instead", - drv->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); + applog(LOG_DEBUG, "%s looking for %s %04x:%04x but found %04x:%04x instead", + drv->name, look->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); return false; } - applog(LOG_DEBUG, "%s looking for and found %04x:%04x", - drv->name, look->idVendor, look->idProduct); + applog(LOG_DEBUG, "%s looking for and found %s %04x:%04x", + drv->name, look->name, look->idVendor, look->idProduct); return true; } From bad942e59a209bc35c370bb7d34c75578bd2502e Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 8 Jan 2013 14:06:16 +1100 Subject: [PATCH 18/47] increase device status string length --- cgminer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgminer.c b/cgminer.c index befe57e7..1bc57e96 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1986,11 +1986,11 @@ static void curses_print_devstatus(int thr_id) suffix_string(dr64, displayed_rolling, 4); if (cgpu->status == LIFE_DEAD) - wprintw(statuswin, "DEAD "); + wprintw(statuswin, "DEAD "); else if (cgpu->status == LIFE_SICK) - wprintw(statuswin, "SICK "); + wprintw(statuswin, "SICK "); else if (cgpu->deven == DEV_DISABLED) - wprintw(statuswin, "OFF "); + wprintw(statuswin, "OFF "); else if (cgpu->deven == DEV_RECOVER) wprintw(statuswin, "REST "); else From bd5f20ebf57103eefb52c4e1fe0be7823623ed9a Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 8 Jan 2013 16:30:51 +1100 Subject: [PATCH 19/47] api.c pgaenable not re-enabling the device - plus related debug --- api.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/api.c b/api.c index 2e013ff4..bfd83708 100644 --- a/api.c +++ b/api.c @@ -1761,6 +1761,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char struct cgpu_info *cgpu = devices[dev]; + applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s%u", + id, dev, cgpu->drv->name, cgpu->device_id); + if (cgpu->deven != DEV_DISABLED) { message(io_data, MSG_PGALRENA, id, NULL, isjson); return; @@ -1774,10 +1777,11 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { - pga = thr_info[i].cgpu->device_id; + pga = thr_info[i].cgpu->cgminer_id; if (pga == dev) { thr = &thr_info[i]; cgpu->deven = DEV_ENABLED; + applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); } } @@ -1814,6 +1818,9 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha struct cgpu_info *cgpu = devices[dev]; + applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s%u", + id, dev, cgpu->drv->name, cgpu->device_id); + if (cgpu->deven == DEV_DISABLED) { message(io_data, MSG_PGALRDIS, id, NULL, isjson); return; @@ -2066,6 +2073,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char return; } + applog(LOG_DEBUG, "API: request to gpuenable gpuid %d %s%u", + id, gpus[id].drv->name, gpus[id].device_id); + if (gpus[id].deven != DEV_DISABLED) { message(io_data, MSG_ALRENA, id, NULL, isjson); return; @@ -2079,10 +2089,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char message(io_data, MSG_GPUMRE, id, NULL, isjson); return; } - gpus[id].deven = DEV_ENABLED; + applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); - } } @@ -2109,6 +2118,9 @@ static void gpudisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha return; } + applog(LOG_DEBUG, "API: request to gpudisable gpuid %d %s%u", + id, gpus[id].drv->name, gpus[id].device_id); + if (gpus[id].deven == DEV_DISABLED) { message(io_data, MSG_ALRDIS, id, NULL, isjson); return; From 0b3d8c89c24cefc67626e703aece84a7f59d446e Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 10 Jan 2013 11:08:12 +1100 Subject: [PATCH 20/47] API zero - zero statistics - all or bestshare - with optional on screen summary --- API-README | 15 ++++++++++++++ api.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cgminer.c | 24 +++++++++++++++------- miner.h | 3 +++ 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/API-README b/API-README index 14f8b53c..d8a5dec5 100644 --- a/API-README +++ b/API-README @@ -347,6 +347,18 @@ The list of requests - a (*) means it requires privileged access - and replies a The current options are: MMQ opt=clock val=160 to 230 (and a multiple of 2) + zero|Which,true/false (*) + none There is no reply section just the STATUS section + stating that the zero, and optional summary, was done + If Which='all', all normal cgminer and API statistics + will be zeroed other than the numbers displayed by the + usbstats and stats commands + If Which='bestshare', only the 'Best Share' values + are zeroed for each pool and the global 'Best Share' + The true/false option determines if a full summary is + shown on the cgminer display like is normally displayed + on exit. + When you enable, disable or restart a GPU or PGA, you will also get Thread messages in the cgminer status window @@ -402,6 +414,9 @@ Feature Changelog for external applications using the API: API V1.24 +Added API commands: + 'zero' + Modified API commands: 'pools' - add 'Best Share' diff --git a/api.c b/api.c index bfd83708..faad39ae 100644 --- a/api.c +++ b/api.c @@ -387,6 +387,11 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_PGASETERR 93 #endif +#define MSG_ZERMIS 94 +#define MSG_ZERINV 95 +#define MSG_ZERSUM 96 +#define MSG_ZERNOSUM 97 + enum code_severity { SEVERITY_ERR, SEVERITY_WARN, @@ -559,6 +564,10 @@ struct CODES { { SEVERITY_SUCC, MSG_PGASETOK, PARAM_BOTH, "PGA %d set OK" }, { SEVERITY_ERR, MSG_PGASETERR, PARAM_BOTH, "PGA %d set failed: %s" }, #endif + { SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, + { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, + { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, + { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, { SEVERITY_FAIL, 0, 0, NULL } }; @@ -3212,6 +3221,54 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe } #endif +static void dozero(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + if (param == NULL || *param == '\0') { + message(io_data, MSG_ZERMIS, 0, NULL, isjson); + return; + } + + char *sum = strchr(param, ','); + if (sum) + *(sum++) = '\0'; + if (!sum || !*sum) { + message(io_data, MSG_MISBOOL, 0, NULL, isjson); + return; + } + + bool all = false; + bool bs = false; + if (strcasecmp(param, "all") == 0) + all = true; + else if (strcasecmp(param, "bestshare") == 0) + bs = true; + + if (all == false && bs == false) { + message(io_data, MSG_ZERINV, 0, param, isjson); + return; + } + + *sum = tolower(*sum); + if (*sum != 't' && *sum != 'f') { + message(io_data, MSG_INVBOOL, 0, NULL, isjson); + return; + } + + bool dosum = (*sum == 't'); + if (dosum) + print_summary(); + + if (all) + zero_stats(); + if (bs) + zero_bestshare(); + + if (dosum) + message(io_data, MSG_ZERSUM, 0, all ? "All" : "BestShare", isjson); + else + message(io_data, MSG_ZERNOSUM, 0, all ? "All" : "BestShare", isjson); +} + static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group); struct CMDS { @@ -3271,6 +3328,7 @@ struct CMDS { #ifdef HAVE_AN_FPGA { "pgaset", pgaset, true }, #endif + { "zero", dozero, true }, { NULL, NULL, false } }; diff --git a/cgminer.c b/cgminer.c index 1bc57e96..c42703fb 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2732,8 +2732,6 @@ static void disable_curses(void) } #endif -static void print_summary(void); - static void __kill_work(void) { struct thr_info *thr; @@ -3915,6 +3913,20 @@ void write_config(FILE *fcfg) json_escape_free(); } +void zero_bestshare(void) +{ + int i; + + best_diff = 0; + memset(best_share, 0, 8); + suffix_string(best_diff, best_share, 0); + + for (i = 0; i < total_pools; i++) { + struct pool *pool = pools[i]; + pool->best_diff = 0; + } +} + void zero_stats(void) { int i; @@ -3931,10 +3943,7 @@ void zero_stats(void) total_go = 0; total_ro = 0; total_secs = 1.0; - best_diff = 0; total_diff1 = 0; - memset(best_share, 0, 8); - suffix_string(best_diff, best_share, 0); found_blocks = 0; total_diff_accepted = 0; total_diff_rejected = 0; @@ -3956,9 +3965,10 @@ void zero_stats(void) pool->diff_rejected = 0; pool->diff_stale = 0; pool->last_share_diff = 0; - pool->best_diff = 0; } + zero_bestshare(); + mutex_lock(&hash_lock); for (i = 0; i < total_devices; ++i) { struct cgpu_info *cgpu = devices[i]; @@ -5961,7 +5971,7 @@ static void log_print_status(struct cgpu_info *cgpu) applog(LOG_WARNING, "%s", logline); } -static void print_summary(void) +void print_summary(void) { struct timeval diff; int hours, mins, secs, i; diff --git a/miner.h b/miner.h index b89d072e..1992bd50 100644 --- a/miner.h +++ b/miner.h @@ -759,6 +759,7 @@ extern void api(int thr_id); extern struct pool *current_pool(void); extern int enabled_pools; extern bool detect_stratum(struct pool *pool, char *url); +extern void print_summary(void); extern struct pool *add_pool(void); extern void add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass); @@ -1077,6 +1078,8 @@ extern void kill_work(void); extern void switch_pools(struct pool *selected); extern void remove_pool(struct pool *pool); extern void write_config(FILE *fcfg); +extern void zero_bestshare(void); +extern void zero_stats(void); extern void default_save_file(char *filename); extern bool log_curses_only(int prio, const char *f, va_list ap); extern void clear_logwin(void); From f53549a861a65957ab748f09dca0a753e3e00ea7 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 10 Jan 2013 11:27:51 +1100 Subject: [PATCH 21/47] BFL minimise first initialisation failure delay since it is common --- driver-bitforce.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index 0181b170..75e8b160 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -58,9 +58,11 @@ // If initialisation fails the first time, // sleep this amount (ms) and try again -#define REINIT_TIME_MS 1000 -// But try this many times -#define REINIT_COUNT 6 +#define REINIT_TIME_FIRST_MS 100 +// Max ms per sleep +#define REINIT_TIME_MAX_MS 800 +// Keep trying up to this many us +#define REINIT_TIME_MAX 3000000 static const char *blank = ""; @@ -133,6 +135,8 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic char devpath[20]; int err, amount; char *s; + struct timeval init_start, init_now; + int init_sleep, init_count; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); @@ -152,7 +156,10 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic (int)(bitforce->usbdev->bus_number), (int)(bitforce->usbdev->device_address)); - int init_count = 0; + + init_count = 0; + init_sleep = REINIT_TIME_FIRST_MS; + gettimeofday(&init_start, NULL); reinit: bitforce_initialise(bitforce, false); @@ -164,19 +171,22 @@ reinit: } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { - // Maybe it was still processing previous work? - if (++init_count <= REINIT_COUNT) { - if (init_count < 2) { - applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", + init_count++; + gettimeofday(&init_now, NULL); + if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { + if (init_count == 2) { + applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", bitforce->drv->dname, devpath, amount, err); } - nmsleep(REINIT_TIME_MS); + nmsleep(init_sleep); + if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) + init_sleep *= 2; goto reinit; } if (init_count > 0) - applog(LOG_WARNING, "%s detect (%s) init failed %d times", - bitforce->drv->dname, devpath, init_count); + applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", + bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start)); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", From 4f460ca72d5573b98970364c048560a52e898b18 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 13 Jan 2013 10:28:19 +1100 Subject: [PATCH 22/47] Best Share readme --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index fd310154..21f12962 100644 --- a/README +++ b/README @@ -457,7 +457,7 @@ The block display shows: Block: 0074c5e482e34a506d2a051a... Started: [17:17:22] Best share: 2.71K This shows a short stretch of the current block, when the new block started, -and the all time best difficulty share you've submitted since starting cgminer +and the all time best difficulty share you've found since starting cgminer this time. From 34bcc1c66de4e03baf5aadb2a4c2369fa920379a Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:30:11 +1100 Subject: [PATCH 23/47] USB automatically handle losing the device and report nodev in the API --- API-README | 1 + api.c | 14 +++++++ driver-bitforce.c | 30 ++++++++++++- driver-modminer.c | 29 +++++++++---- miner.h | 1 + usbutils.c | 104 +++++++++++++++++++++++++++++++++++++++++----- usbutils.h | 6 ++- 7 files changed, 165 insertions(+), 20 deletions(-) diff --git a/API-README b/API-README index d8a5dec5..5fd2dda4 100644 --- a/API-README +++ b/API-README @@ -419,6 +419,7 @@ Added API commands: Modified API commands: 'pools' - add 'Best Share' + 'devs' and 'pga' - add 'No Device' for PGAs if MMQ or BFL compiled ---------- diff --git a/api.c b/api.c index faad39ae..c3158758 100644 --- a/api.c +++ b/api.c @@ -391,6 +391,7 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_ZERINV 95 #define MSG_ZERSUM 96 #define MSG_ZERNOSUM 97 +#define MSG_USBNODEV 98 enum code_severity { SEVERITY_ERR, @@ -568,6 +569,9 @@ struct CODES { { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + { SEVERITY_ERR, MSG_USBNODEV, PARAM_PGA, "PGA%d has no device" }, +#endif { SEVERITY_FAIL, 0, 0, NULL } }; @@ -1570,6 +1574,9 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + root = api_add_bool(root, "No Device", &(cgpu->nodev), false); +#endif root = print_data(root, buf, isjson, precom); io_add(io_data, buf); @@ -1785,6 +1792,13 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } #endif +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + if (cgpu->nodev) { + message(io_data, MSG_USBNODEV, id, NULL, isjson); + return; + } +#endif + for (i = 0; i < mining_threads; i++) { pga = thr_info[i].cgpu->cgminer_id; if (pga == dev) { diff --git a/driver-bitforce.c b/driver-bitforce.c index 75e8b160..a529042b 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * Copyright 2012 Luke Dashjr * Copyright 2012 Con Kolivas * @@ -82,6 +82,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: reset got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set data control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); @@ -89,6 +92,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setdata got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set the baud err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, (FTDI_INDEX_BAUD & 0xff00) | bitforce->usbdev->found->interface, @@ -97,6 +103,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setbaud got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set Flow Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); @@ -104,6 +113,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set Modem Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); @@ -111,6 +123,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Clear any sent data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); @@ -118,6 +133,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgetx got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Clear any received data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); @@ -125,6 +143,8 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgerx got err %d", bitforce->drv->name, bitforce->device_id, err); +failed: + if (lock) mutex_unlock(&bitforce->device_mutex); } @@ -322,6 +342,10 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) int err, amount; char *s; + // Device is gone + if (bitforce->nodev) + return false; + /* Do not try to get the temperature if we're polling for a result to * minimise the chance of interleaved results */ if (bitforce->polling) @@ -640,6 +664,10 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ bool send_ret; int64_t ret; + // Device is gone + if (bitforce->nodev) + return -1; + send_ret = bitforce_send_work(thr, work); if (!restart_wait(bitforce->sleep_ms)) diff --git a/driver-modminer.c b/driver-modminer.c index 246947b4..5c165760 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * Copyright 2012 Luke Dashjr * * This program is free software; you can redistribute it and/or modify it @@ -607,6 +607,7 @@ static bool modminer_fpga_prepare(struct thr_info *thr) * * N.B. clock must always be a multiple of 2 */ +static const char *clocknodev = "clock failed - no device"; static const char *clockoldwork = "clock already changed for this work"; static const char *clocktoolow = "clock too low"; static const char *clocktoohi = "clock too high"; @@ -620,6 +621,10 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te unsigned char cmd[6], buf[1]; int err, amount; + // Device is gone + if (modminer->nodev) + return clocknodev; + // Only do once if multiple shares per work or multiple reasons if (!state->new_work && !force) return clockoldwork; @@ -775,9 +780,6 @@ static bool modminer_start_work(struct thr_info *thr) mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, (char *)(state->next_work_cmd), 46, &amount, C_SENDWORK)) < 0 || amount != 46) { -// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared -// - need to delete it and rescan for it? (after a delay?) -// but check all (4) disappeared mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", @@ -807,6 +809,10 @@ static void check_temperature(struct thr_info *thr) int tbytes, tamount; int amount; + // Device is gone + if (modminer->nodev) + return; + if (state->one_byte_temp) { cmd[0] = MODMINER_TEMP1; tbytes = 1; @@ -891,6 +897,10 @@ static uint64_t modminer_process_results(struct thr_info *thr) double timeout; int temploop; + // Device is gone + if (modminer->nodev) + return -1; + // If we are overheated it will just keep checking for results // since we can't stop the work // The next work will not start until the temp drops @@ -904,9 +914,6 @@ static uint64_t modminer_process_results(struct thr_info *thr) while (1) { mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, cmd, 2, &amount, C_REQUESTWORKSTATUS)) < 0 || amount != 2) { -// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared -// - need to delete it and rescan for it? (after a delay?) -// but check all (4) disappeared mutex_unlock(modminer->modminer_mutex); // timeoutloop never resets so the timeouts can't @@ -1053,6 +1060,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ bool startwork; struct timeval tv1, tv2; + // Device is gone + if (thr->cgpu->nodev) + return -1; + // Don't start new work if overheated if (state->overheated == true) { gettimeofday(&tv1, NULL); @@ -1062,6 +1073,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ while (state->overheated == true) { check_temperature(thr); + // Device is gone + if (thr->cgpu->nodev) + return -1; + if (state->overheated == true) { gettimeofday(&tv2, NULL); diff --git a/miner.h b/miner.h index 1992bd50..a7b6fa15 100644 --- a/miner.h +++ b/miner.h @@ -399,6 +399,7 @@ struct cgpu_info { }; #if defined(USE_MODMINER) || defined(USE_BITFORCE) int usbstat; + bool nodev; #endif #ifdef USE_MODMINER char fpgaid; diff --git a/usbutils.c b/usbutils.c index ebfcc0b2..273d8528 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -16,6 +16,10 @@ #include "miner.h" #include "usbutils.h" +#define NODEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \ + (err) == LIBUSB_ERROR_PIPE || \ + (err) == LIBUSB_ERROR_OTHER) + #ifdef USE_ICARUS #define DRV_ICARUS 1 #endif @@ -161,6 +165,7 @@ static int next_stat = 0; static const char **usb_commands; +static const char *C_REJECTED_S = "RejectedNoDevice"; static const char *C_PING_S = "Ping"; static const char *C_CLEAR_S = "Clear"; static const char *C_REQUESTVERSION_S = "RequestVersion"; @@ -551,6 +556,7 @@ static void cgusb_check_init() // use constants so the stat generation is very quick // and the association between number and name can't // be missalined easily + usb_commands[C_REJECTED] = C_REJECTED_S; usb_commands[C_PING] = C_PING_S; usb_commands[C_CLEAR] = C_CLEAR_S; usb_commands[C_REQUESTVERSION] = C_REQUESTVERSION_S; @@ -673,8 +679,7 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) if (lock) mutex_lock(list_lock); - usb_tmp = usb_head; - if (usb_tmp) + if ((usb_tmp = usb_head)) do { if (bus_number == usb_tmp->bus_number && device_address == usb_tmp->device_address) { @@ -698,6 +703,8 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) if (usb_tmp->next == usb_tmp) { usb_head = NULL; } else { + if (usb_head == usb_tmp) + usb_head = usb_tmp->next; usb_tmp->next->prev = usb_tmp->prev; usb_tmp->prev->next = usb_tmp->next; } @@ -719,13 +726,6 @@ static void release_dev(libusb_device *dev, bool lock) release(bus_number, device_address, lock); } -#if 0 -static void release_cgusb(struct cg_usb_device *cgusb, bool lock) -{ - release(cgusb->bus_number, cgusb->device_address, lock); -} -#endif - static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) { if (cgusb->serial_string && cgusb->serial_string != BLANK) @@ -739,6 +739,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) free(cgusb->descriptor); + free(cgusb->found); + free(cgusb); return NULL; @@ -751,6 +753,31 @@ void usb_uninit(struct cgpu_info *cgpu) cgpu->usbdev = free_cgusb(cgpu->usbdev); } +void release_cgpu(struct cgpu_info *cgpu) +{ + struct cg_usb_device *cgusb = cgpu->usbdev; + uint8_t bus_number; + uint8_t device_address; + int i; + + cgpu->nodev = true; + + // Any devices sharing the same USB device should be marked also + // Currently only MMQ shares a USB device + for (i = 0; i < total_devices; i++) + if (devices[i] != cgpu && devices[i]->usbdev == cgusb) { + devices[i]->nodev = true; + devices[i]->usbdev = NULL; + } + + bus_number = cgusb->bus_number; + device_address = cgusb->device_address; + + usb_uninit(cgpu); + + release(bus_number, device_address, true); +} + bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) { struct cg_usb_device *cgusb = NULL; @@ -1172,6 +1199,19 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev memcpy(&(details->item[item].last), tv_start, sizeof(tv_start)); details->item[item].count++; } + +static void rejected_inc(struct cgpu_info *cgpu) +{ + struct cg_usb_stats_details *details; + int item = CMD_ERROR; + + if (cgpu->usbstat < 1) + newstats(cgpu); + + details = &(usb_stats[cgpu->usbstat - 1].details[C_REJECTED * 2 + 0]); + + details->item[item].count++; +} #endif int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi) @@ -1186,6 +1226,15 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro int err, got, tot, i; bool first = true; + if (cgpu->nodev) { + *buf = '\0'; + *processed = 0; +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + if (timeout == DEVTIMEOUT) timeout = usbdev->found->timeout; @@ -1212,6 +1261,11 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro *processed = got; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1268,6 +1322,11 @@ goteol: *processed = tot; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1279,6 +1338,14 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr #endif int err, sent; + if (cgpu->nodev) { + *processed = 0; +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + sent = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, @@ -1291,6 +1358,11 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr *processed = sent; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1302,6 +1374,13 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest #endif int err; + if (cgpu->nodev) { +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + STATS_TIMEVAL(&tv_start); err = libusb_control_transfer(usbdev->handle, request_type, bRequest, wValue, wIndex, NULL, 0, @@ -1309,6 +1388,11 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } diff --git a/usbutils.h b/usbutils.h index 2ee86150..7912be52 100644 --- a/usbutils.h +++ b/usbutils.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -79,7 +79,8 @@ struct cg_usb_device { }; enum usb_cmds { - C_PING = 0, + C_REJECTED = 0, + C_PING, C_CLEAR, C_REQUESTVERSION, C_GETVERSION, @@ -120,6 +121,7 @@ struct device_drv; struct cgpu_info; void usb_uninit(struct cgpu_info *cgpu); +void release_cgpu(struct cgpu_info *cgpu); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); From 24525edbefffd944d07d289beaf1f0534cbfc10d Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:40:02 +1100 Subject: [PATCH 24/47] api.c update copyright year --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index c3158758..ce598683 100644 --- a/api.c +++ b/api.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 Andrew Smith + * Copyright 2011-2013 Andrew Smith * Copyright 2011-2012 Con Kolivas * * This program is free software; you can redistribute it and/or modify it From ea807cf0c7ee5c8bd9b315f395847d0176d741fc Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:44:31 +1100 Subject: [PATCH 25/47] USB BFL transfer is only 64 bytes in a USB1.1 socket --- usbutils.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 273d8528..d9427067 100644 --- a/usbutils.c +++ b/usbutils.c @@ -48,14 +48,10 @@ #endif #ifdef USE_BITFORCE +// N.B. transfer size is 512 with USB2.0, but only 64 with USB1.1 static struct usb_endpoints bfl_eps[] = { -#ifdef WIN32 { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } -#else - { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, - { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } -#endif }; #endif From a52522af3727cad95c5818c1d137c80e403dc121 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 21:01:25 +1100 Subject: [PATCH 26/47] MMQ it's a bitstream --- driver-modminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-modminer.c b/driver-modminer.c index 5c165760..abb2d7fc 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -255,7 +255,7 @@ static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) } if (buf != c) { - applog(LOG_ERR, "%s%u: firmware code mismatch (%c)", + applog(LOG_ERR, "%s%u: bitstream code mismatch (%c)", modminer->drv->name, modminer->device_id, c); return false; } From 92abe36f1207533e29d42d1eba6306663ce9b6b1 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 21:12:50 +1100 Subject: [PATCH 27/47] MMQ include USB devpath in detection error messages --- driver-modminer.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/driver-modminer.c b/driver-modminer.c index abb2d7fc..24a952a4 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -126,37 +126,52 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic mutex_init(modminer->modminer_mutex); modminer->fpgaid = (char)0; - if (!usb_init(modminer, dev, found)) + if (!usb_init(modminer, dev, found)) { + applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", + modminer->drv->dname, + (int)libusb_get_bus_number(dev), + (int)libusb_get_device_address(dev)); goto shin; + } + + sprintf(devpath, "%d:%d", + (int)(modminer->usbdev->bus_number), + (int)(modminer->usbdev->device_address)); do_ping(modminer); if ((err = usb_write(modminer, MODMINER_GET_VERSION, 1, &amount, C_REQUESTVERSION)) < 0 || amount != 1) { - applog(LOG_ERR, "ModMiner detect: send version request failed (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) send version request failed (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) { if (err < 0) - applog(LOG_ERR, "ModMiner detect: no version reply (%d)", err); + applog(LOG_ERR, "%s detect (%s) no version reply (%d)", + modminer->drv->dname, devpath, err); else - applog(LOG_ERR, "ModMiner detect: empty version reply (%d)", amount); + applog(LOG_ERR, "%s detect (%s) empty version reply (%d)", + modminer->drv->dname, devpath, amount); - applog(LOG_DEBUG, "ModMiner detect: check the firmware"); + applog(LOG_DEBUG, "%s detect (%s) check the firmware", + modminer->drv->dname, devpath); goto unshin; } buf[amount] = '\0'; devname = strdup(buf); - applog(LOG_DEBUG, "ModMiner identified as: %s", devname); + applog(LOG_DEBUG, "%s (%s) identified as: %s", modminer->drv->dname, devpath, devname); if ((err = usb_write(modminer, MODMINER_FPGA_COUNT, 1, &amount, C_REQUESTFPGACOUNT) < 0 || amount != 1)) { - applog(LOG_ERR, "ModMiner detect: FPGA count request failed (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) FPGA count request failed (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_read(modminer, buf, 1, &amount, C_GETFPGACOUNT)) < 0 || amount != 1) { - applog(LOG_ERR, "ModMiner detect: no FPGA count reply (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) no FPGA count reply (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } @@ -164,16 +179,19 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic // can detect with modminer->cgusb->serial ? if (buf[0] == 0) { - applog(LOG_ERR, "ModMiner detect: zero FPGA count from %s", devname); + applog(LOG_ERR, "%s detect (%s) zero FPGA count from %s", + modminer->drv->dname, devpath, devname); goto unshin; } if (buf[0] < 1 || buf[0] > 4) { - applog(LOG_ERR, "ModMiner detect: invalid FPGA count (%u) from %s", buf[0], devname); + applog(LOG_ERR, "%s detect (%s) invalid FPGA count (%u) from %s", + modminer->drv->dname, devpath, buf[0], devname); goto unshin; } - applog(LOG_DEBUG, "ModMiner %s has %u FPGAs", devname, buf[0]); + applog(LOG_DEBUG, "%s (%s) %s has %u FPGAs", + modminer->drv->dname, devpath, devname, buf[0]); modminer->name = devname; From c1eae36f7bf2299fb49b1eeeba49345e5dc7a46a Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 15 Jan 2013 01:13:00 +1100 Subject: [PATCH 28/47] API stats - include pool network bytes + in miner.php --- api.c | 2 ++ miner.h | 2 ++ miner.php | 16 +++++++++++----- util.c | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/api.c b/api.c index ce598683..fe593a76 100644 --- a/api.c +++ b/api.c @@ -2915,6 +2915,8 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st root = api_add_uint64(root, "Bytes Sent", &(pool_stats->bytes_sent), false); root = api_add_uint64(root, "Times Recv", &(pool_stats->times_received), false); root = api_add_uint64(root, "Bytes Recv", &(pool_stats->bytes_received), false); + root = api_add_uint64(root, "Net Bytes Sent", &(pool_stats->net_bytes_sent), false); + root = api_add_uint64(root, "Net Bytes Recv", &(pool_stats->net_bytes_received), false); } if (extra) diff --git a/miner.h b/miner.h index a7b6fa15..f9e616d0 100644 --- a/miner.h +++ b/miner.h @@ -375,8 +375,10 @@ struct cgminer_pool_stats { uint32_t max_diff_count; uint64_t times_sent; uint64_t bytes_sent; + uint64_t net_bytes_sent; uint64_t times_received; uint64_t bytes_received; + uint64_t net_bytes_received; }; struct cgpu_info { diff --git a/miner.php b/miner.php index 9215a21e..717e26aa 100644 --- a/miner.php +++ b/miner.php @@ -116,16 +116,17 @@ $poolspage = array( 'POOL.Difficulty Rejected=Diff Rej', 'POOL.Has Stratum=Stratum', 'POOL.Stratum Active=StrAct', 'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent', - 'STATS.Bytes Sent=BSent', 'STATS.Times Recv=TRecv', - 'STATS.Bytes Recv=BRecv')); + 'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent', + 'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv', + 'STATS.Net Bytes Recv=NRecv')); # $poolssum = array( 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'Rejected', 'Utility', 'Hardware Errors', 'Work Utility'), 'POOL+STATS' => array('POOL.Difficulty Accepted', 'POOL.Difficulty Rejected', - 'STATS.Times Sent', 'STATS.Bytes Sent', - 'STATS.Times Recv', 'STATS.Bytes Recv')); + 'STATS.Times Sent', 'STATS.Bytes Sent', 'STATS.Net Bytes Sent', + 'STATS.Times Recv', 'STATS.Bytes Recv', 'STATS.Net Bytes Recv')); # $poolsext = array( 'POOL+STATS' => array( @@ -133,7 +134,8 @@ $poolsext = array( 'group' => array('POOL.URL', 'POOL.Has Stratum', 'POOL.Stratum Active', 'POOL.Has GBT'), 'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum', 'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum', - 'STATS.Times Recv' => 'sum', 'STATS.Bytes Recv' => 'sum'), + 'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum', + 'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum'), 'having' => array(array('STATS.Bytes Recv', '>', 0))) ); @@ -850,12 +852,16 @@ function fmt($section, $name, $value, $when, $alldata) case 'total.Diff1 Work': case 'STATS.Times Sent': case 'STATS.Bytes Sent': + case 'STATS.Net Bytes Sent': case 'STATS.Times Recv': case 'STATS.Bytes Recv': + case 'STATS.Net Bytes Recv': case 'total.Times Sent': case 'total.Bytes Sent': + case 'total.Net Bytes Sent': case 'total.Times Recv': case 'total.Bytes Recv': + case 'total.Net Bytes Recv': $parts = explode('.', $value, 2); if (count($parts) == 1) $dec = ''; diff --git a/util.c b/util.c index e628af45..9283955c 100644 --- a/util.c +++ b/util.c @@ -261,6 +261,30 @@ static void set_nettime(void) wr_unlock(&netacc_lock); } +static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type, + __maybe_unused unsigned char *data, size_t size, + void *userdata) +{ + struct pool *pool = (struct pool *)userdata; + + switch(type) { + case CURLINFO_HEADER_IN: + case CURLINFO_DATA_IN: + case CURLINFO_SSL_DATA_IN: + pool->cgminer_pool_stats.net_bytes_received += size; + break; + case CURLINFO_HEADER_OUT: + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_OUT: + pool->cgminer_pool_stats.net_bytes_sent += size; + break; + case CURLINFO_TEXT: + default: + break; + } + return 0; +} + json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req, bool probe, bool longpoll, int *rolltime, @@ -287,10 +311,11 @@ json_t *json_rpc_call(CURL *curl, const char *url, probing = !pool->probed; curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); -#if 0 /* Disable curl debugging since it spews to stderr */ - if (opt_protocol) - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); -#endif + // CURLOPT_VERBOSE won't write to stderr if we use CURLOPT_DEBUGFUNCTION + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)pool); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_ENCODING, ""); @@ -912,6 +937,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len) pool->cgminer_pool_stats.times_sent++; pool->cgminer_pool_stats.bytes_sent += ssent; + pool->cgminer_pool_stats.net_bytes_sent += ssent; return true; } @@ -1041,6 +1067,7 @@ char *recv_line(struct pool *pool) pool->cgminer_pool_stats.times_received++; pool->cgminer_pool_stats.bytes_received += len; + pool->cgminer_pool_stats.net_bytes_received += len; out: if (!sret) clear_sock(pool); From baf3aca88c5196029caa200aa504c96adfba2690 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 17 Jan 2013 19:21:40 +1100 Subject: [PATCH 29/47] usbutils.c release_cgpu() sets nodev --- usbutils.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/usbutils.c b/usbutils.c index d9427067..30be2884 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1257,10 +1257,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro *processed = got; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1318,10 +1316,8 @@ goteol: *processed = tot; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1354,10 +1350,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr *processed = sent; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1384,10 +1378,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } From 9447610091feb5a679d72ae7bae89a776917186e Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 17 Jan 2013 19:55:08 +1100 Subject: [PATCH 30/47] ICA use drv->name --- driver-icarus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-icarus.c b/driver-icarus.c index f42e7214..1faab2b6 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -668,7 +668,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, icarus = thr->cgpu; if (icarus->device_fd == -1) if (!icarus_prepare(thr)) { - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); // fail the device if the reopen attempt fails @@ -688,7 +688,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, ret = icarus_write(fd, ob_bin, sizeof(ob_bin)); if (ret) { do_icarus_close(thr); - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); return 0; /* This should never happen */ } @@ -708,7 +708,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, ret = icarus_gets(nonce_bin, fd, &tv_finish, thr, info->read_count); if (ret == ICA_GETS_ERROR) { do_icarus_close(thr); - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); return 0; } From 383a21bebf871e22a7152129313aa52cbf307d79 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 18 Jan 2013 20:33:23 +1100 Subject: [PATCH 31/47] miner.php trim trailing zeros on some of the STATS numbers --- miner.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/miner.php b/miner.php index 717e26aa..396121b6 100644 --- a/miner.php +++ b/miner.php @@ -590,6 +590,14 @@ function classlastshare($when, $alldata, $warnclass, $errorclass) return ''; } # +function endzero($num) +{ + $rep = preg_replace('/0*$/', '', $num); + if ($rep === '') + $rep = '0'; + return $rep; +} +# function fmt($section, $name, $value, $when, $alldata) { global $dfmt, $rownum; @@ -869,6 +877,23 @@ function fmt($section, $name, $value, $when, $alldata) $dec = '.'.$parts[1]; $ret = number_format((float)$parts[0]).$dec; break; + case 'STATS.Hs': + case 'STATS.W': + case 'STATS.history_time': + case 'STATS.Pool Wait': + case 'STATS.Pool Max': + case 'STATS.Pool Min': + case 'STATS.Pool Av': + case 'STATS.Min Diff': + case 'STATS.Max Diff': + case 'STATS.Work Diff': + $parts = explode('.', $value, 2); + if (count($parts) == 1) + $dec = ''; + else + $dec = '.'.endzero($parts[1]); + $ret = number_format((float)$parts[0]).$dec; + break; case 'GPU.Status': case 'PGA.Status': case 'DEVS.Status': From 3f4d9fc5d61784e6a7df3d1d11f1511fe36c3ce3 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 19 Jan 2013 00:24:26 +1100 Subject: [PATCH 32/47] BFL use #defined strings for work replies --- driver-bitforce.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index a529042b..fbc98723 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -40,6 +40,16 @@ #define BITFORCE_WORKSTATUS "ZFX" #define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1) +// Either of Nonce or No-nonce start with: +#define BITFORCE_EITHER "N" +#define BITFORCE_EITHER_LEN 1 +#define BITFORCE_NONCE "NONCE-FOUND" +#define BITFORCE_NONCE_LEN (sizeof(BITFORCE_NONCE)-1) +#define BITFORCE_NO_NONCE "NO-NONCE" +#define BITFORCE_NO_NONCE_MATCH 3 +#define BITFORCE_IDLE "IDLE" +#define BITFORCE_IDLE_MATCH 1 + #define BITFORCE_SLEEP_MS 500 #define BITFORCE_TIMEOUT_S 7 #define BITFORCE_TIMEOUT_MS (BITFORCE_TIMEOUT_S * 1000) @@ -579,7 +589,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) /* Only return if we got nothing after timeout - there still may be results */ if (amount == 0) return 0; - } else if (!strncasecmp(buf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ + } else if (!strncasecmp(buf, BITFORCE_EITHER, BITFORCE_EITHER_LEN)) { /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or @@ -608,11 +618,11 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) applog(LOG_DEBUG, "%s%i: waited %dms until %s", bitforce->drv->name, bitforce->device_id, bitforce->wait_ms, buf); - if (!strncasecmp(&buf[2], "-", 1)) + if (!strncasecmp(buf, BITFORCE_NO_NONCE, BITFORCE_NO_NONCE_MATCH)) return bitforce->nonces; /* No valid nonce found */ - else if (!strncasecmp(buf, "I", 1)) + else if (!strncasecmp(buf, BITFORCE_IDLE, BITFORCE_IDLE_MATCH)) return 0; /* Device idle */ - else if (strncasecmp(buf, "NONCE-FOUND", 11)) { + else if (strncasecmp(buf, BITFORCE_NONCE, BITFORCE_NONCE_LEN)) { bitforce->hw_errors++; applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", bitforce->drv->name, bitforce->device_id, buf); From 8f4340bfeb1348f1369fdd1962f9267383052e31 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 21 Jan 2013 21:30:21 +1100 Subject: [PATCH 33/47] BFL allow a 2nd init attempt if the 1st reply is unknown --- driver-bitforce.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index fbc98723..f97bcda5 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -167,6 +167,7 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic char *s; struct timeval init_start, init_now; int init_sleep, init_count; + bool ident_first; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); @@ -187,13 +188,14 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic (int)(bitforce->usbdev->device_address)); + // Allow 2 complete attempts if the 1st time returns an unrecognised reply + ident_first = true; +retry: init_count = 0; init_sleep = REINIT_TIME_FIRST_MS; gettimeofday(&init_start, NULL); reinit: - bitforce_initialise(bitforce, false); - if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", bitforce->drv->dname, devpath, amount, err); @@ -231,7 +233,13 @@ reinit: buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { - applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", + if (ident_first) { + applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", + bitforce->drv->dname, devpath, buf); + ident_first = false; + goto retry; + } + applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", bitforce->drv->dname, devpath, buf); goto unshin; } From 7fbc3770b471b956d40cb78e8b7e365b54de9cf1 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 22 Jan 2013 21:46:21 +1100 Subject: [PATCH 34/47] USB move usbdev info that needs to stay around into usbinfo --- api.c | 4 ++-- driver-bitforce.c | 24 +++++++++++----------- driver-modminer.c | 24 +++++++++++----------- miner.h | 3 +-- usbutils.c | 51 ++++++++++++++++++++++++----------------------- usbutils.h | 11 ++++++++-- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/api.c b/api.c index fe593a76..a2470b0d 100644 --- a/api.c +++ b/api.c @@ -1575,7 +1575,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); #if defined(USE_MODMINER) || defined(USE_BITFORCE) - root = api_add_bool(root, "No Device", &(cgpu->nodev), false); + root = api_add_bool(root, "No Device", &(cgpu->usbinfo.nodev), false); #endif root = print_data(root, buf, isjson, precom); @@ -1793,7 +1793,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif #if defined(USE_MODMINER) || defined(USE_BITFORCE) - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { message(io_data, MSG_USBNODEV, id, NULL, isjson); return; } diff --git a/driver-bitforce.c b/driver-bitforce.c index f97bcda5..be22c7b6 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -92,7 +92,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: reset got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set data control @@ -102,7 +102,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setdata got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set the baud @@ -113,7 +113,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setbaud got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set Flow Control @@ -123,7 +123,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set Modem Control @@ -133,7 +133,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Clear any sent data @@ -143,7 +143,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgetx got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Clear any received data @@ -178,14 +178,14 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", bitforce->drv->dname, - (int)libusb_get_bus_number(dev), - (int)libusb_get_device_address(dev)); + (int)(bitforce->usbinfo.bus_number), + (int)(bitforce->usbinfo.device_address)); goto shin; } sprintf(devpath, "%d:%d", - (int)(bitforce->usbdev->bus_number), - (int)(bitforce->usbdev->device_address)); + (int)(bitforce->usbinfo.bus_number), + (int)(bitforce->usbinfo.device_address)); // Allow 2 complete attempts if the 1st time returns an unrecognised reply @@ -361,7 +361,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) char *s; // Device is gone - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) return false; /* Do not try to get the temperature if we're polling for a result to @@ -683,7 +683,7 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ int64_t ret; // Device is gone - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) return -1; send_ret = bitforce_send_work(thr, work); diff --git a/driver-modminer.c b/driver-modminer.c index 24a952a4..eb54d914 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -129,14 +129,14 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic if (!usb_init(modminer, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", modminer->drv->dname, - (int)libusb_get_bus_number(dev), - (int)libusb_get_device_address(dev)); + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address)); goto shin; } sprintf(devpath, "%d:%d", - (int)(modminer->usbdev->bus_number), - (int)(modminer->usbdev->device_address)); + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address)); do_ping(modminer); @@ -204,15 +204,15 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic tmp->name = devname; sprintf(devpath, "%d:%d:%d", - (int)(modminer->usbdev->bus_number), - (int)(modminer->usbdev->device_address), + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address), i); tmp->device_path = strdup(devpath); tmp->usbdev = modminer->usbdev; // Only the first copy gets the already used stats if (!added) - tmp->usbstat = modminer->usbstat; + tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; tmp->fpgaid = (char)i; tmp->modminer_mutex = modminer->modminer_mutex; tmp->deven = DEV_ENABLED; @@ -640,7 +640,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te int err, amount; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return clocknodev; // Only do once if multiple shares per work or multiple reasons @@ -828,7 +828,7 @@ static void check_temperature(struct thr_info *thr) int amount; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return; if (state->one_byte_temp) { @@ -916,7 +916,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) int temploop; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return -1; // If we are overheated it will just keep checking for results @@ -1079,7 +1079,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ struct timeval tv1, tv2; // Device is gone - if (thr->cgpu->nodev) + if (thr->cgpu->usbinfo.nodev) return -1; // Don't start new work if overheated @@ -1092,7 +1092,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ check_temperature(thr); // Device is gone - if (thr->cgpu->nodev) + if (thr->cgpu->usbinfo.nodev) return -1; if (state->overheated == true) { diff --git a/miner.h b/miner.h index f9e616d0..2a74bdc0 100644 --- a/miner.h +++ b/miner.h @@ -400,8 +400,7 @@ struct cgpu_info { #endif }; #if defined(USE_MODMINER) || defined(USE_BITFORCE) - int usbstat; - bool nodev; + struct cg_usb_info usbinfo; #endif #ifdef USE_MODMINER char fpgaid; diff --git a/usbutils.c b/usbutils.c index 30be2884..9c55ca49 100644 --- a/usbutils.c +++ b/usbutils.c @@ -641,7 +641,7 @@ static void add_used(libusb_device *dev, bool lock) mutex_unlock(list_lock); sprintf(buf, "add_used() duplicate bus_number %d device_address %d", - bus_number, device_address); + (int)bus_number, (int)device_address); quit(1, buf); } @@ -692,7 +692,7 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) mutex_unlock(list_lock); sprintf(buf, "release() unknown: bus_number %d device_address %d", - bus_number, device_address); + (int)bus_number, (int)device_address); quit(1, buf); } @@ -752,26 +752,26 @@ void usb_uninit(struct cgpu_info *cgpu) void release_cgpu(struct cgpu_info *cgpu) { struct cg_usb_device *cgusb = cgpu->usbdev; - uint8_t bus_number; - uint8_t device_address; int i; - cgpu->nodev = true; + cgpu->usbinfo.nodev = true; + cgpu->usbinfo.nodev_count++; + gettimeofday(&(cgpu->usbinfo.last_nodev), NULL); // Any devices sharing the same USB device should be marked also // Currently only MMQ shares a USB device for (i = 0; i < total_devices; i++) if (devices[i] != cgpu && devices[i]->usbdev == cgusb) { - devices[i]->nodev = true; + devices[i]->usbinfo.nodev = true; + devices[i]->usbinfo.nodev_count++; + memcpy(&(devices[i]->usbinfo.last_nodev), + &(cgpu->usbinfo.last_nodev), sizeof(struct timeval)); devices[i]->usbdev = NULL; } - bus_number = cgusb->bus_number; - device_address = cgusb->device_address; - usb_uninit(cgpu); - release(bus_number, device_address, true); + release(cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address, true); } bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) @@ -783,12 +783,12 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find unsigned char strbuf[STRBUFLEN+1]; int err, i, j, k; + cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); + cgpu->usbinfo.device_address = libusb_get_device_address(dev); + cgusb = calloc(1, sizeof(*cgusb)); cgusb->found = found; - cgusb->bus_number = libusb_get_bus_number(dev); - cgusb->device_address = libusb_get_device_address(dev); - cgusb->descriptor = calloc(1, sizeof(*(cgusb->descriptor))); err = libusb_get_device_descriptor(dev, cgusb->descriptor); @@ -828,7 +828,8 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find switch(err) { case LIBUSB_ERROR_BUSY: applog(LOG_WARNING, "USB init, %s device %d:%d in use", - found->name, cgusb->bus_number, cgusb->device_address); + found->name, (int)(cgpu->usbinfo.bus_number), + (int)(cgpu->usbinfo.device_address)); break; default: applog(LOG_DEBUG, "USB init, failed to set config to %d, err %d", @@ -908,7 +909,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find // cgusb->fwVersion <- for temp1/temp2 decision? or serial? (driver-modminer.c) // cgusb->interfaceVersion - applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgusb->bus_number), (int)(cgusb->device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); + applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); cgpu->usbdev = cgusb; @@ -1134,7 +1135,7 @@ static void newstats(struct cgpu_info *cgpu) { int i; - cgpu->usbstat = ++next_stat; + cgpu->usbinfo.usbstat = ++next_stat; usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); usb_stats[next_stat-1].name = cgpu->drv->name; @@ -1148,11 +1149,11 @@ static void newstats(struct cgpu_info *cgpu) void update_usb_stats(__maybe_unused struct cgpu_info *cgpu) { #if DO_USB_STATS - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); // we don't know the device_id until after add_cgpu() - usb_stats[cgpu->usbstat - 1].device_id = cgpu->device_id; + usb_stats[cgpu->usbinfo.usbstat - 1].device_id = cgpu->device_id; #endif } @@ -1163,10 +1164,10 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev double diff; int item; - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); - details = &(usb_stats[cgpu->usbstat - 1].details[cmd * 2 + seq]); + details = &(usb_stats[cgpu->usbinfo.usbstat - 1].details[cmd * 2 + seq]); diff = tdiff(tv_finish, tv_start); @@ -1201,10 +1202,10 @@ static void rejected_inc(struct cgpu_info *cgpu) struct cg_usb_stats_details *details; int item = CMD_ERROR; - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); - details = &(usb_stats[cgpu->usbstat - 1].details[C_REJECTED * 2 + 0]); + details = &(usb_stats[cgpu->usbinfo.usbstat - 1].details[C_REJECTED * 2 + 0]); details->item[item].count++; } @@ -1222,7 +1223,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro int err, got, tot, i; bool first = true; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { *buf = '\0'; *processed = 0; #if DO_USB_STATS @@ -1330,7 +1331,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr #endif int err, sent; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { *processed = 0; #if DO_USB_STATS rejected_inc(cgpu); @@ -1364,7 +1365,7 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest #endif int err; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { #if DO_USB_STATS rejected_inc(cgpu); #endif diff --git a/usbutils.h b/usbutils.h index 7912be52..d63122f8 100644 --- a/usbutils.h +++ b/usbutils.h @@ -67,8 +67,6 @@ struct cg_usb_device { libusb_device_handle *handle; pthread_mutex_t *mutex; struct libusb_device_descriptor *descriptor; - uint8_t bus_number; - uint8_t device_address; uint16_t usbver; int speed; char *prod_string; @@ -78,6 +76,15 @@ struct cg_usb_device { unsigned char interfaceVersion; // ?? }; +struct cg_usb_info { + uint8_t bus_number; + uint8_t device_address; + int usbstat; + bool nodev; + int nodev_count; + struct timeval last_nodev; +}; + enum usb_cmds { C_REJECTED = 0, C_PING, From d05779191541b4502aaba0ada5ca7bfa24f5733f Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 22 Jan 2013 21:58:33 +1100 Subject: [PATCH 35/47] Capitalise driver long names used in applog messages --- driver-bitforce.c | 2 +- driver-icarus.c | 2 +- driver-modminer.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index be22c7b6..69da9a5e 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -752,7 +752,7 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) struct device_drv bitforce_drv = { .drv = DRIVER_BITFORCE, - .dname = "bitforce", + .dname = "BitForce", .name = "BFL", .drv_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, diff --git a/driver-icarus.c b/driver-icarus.c index 1faab2b6..49300319 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -902,7 +902,7 @@ static void icarus_shutdown(struct thr_info *thr) struct device_drv icarus_drv = { .drv = DRIVER_ICARUS, - .dname = "icarus", + .dname = "Icarus", .name = "ICA", .drv_detect = icarus_detect, .get_api_stats = icarus_api_stats, diff --git a/driver-modminer.c b/driver-modminer.c index eb54d914..2c850b84 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -1184,7 +1184,7 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char struct device_drv modminer_drv = { .drv = DRIVER_MODMINER, - .dname = "modminer", + .dname = "ModMiner", .name = "MMQ", .drv_detect = modminer_detect, .get_statline_before = get_modminer_statline_before, From a59b0c0355912bfce47ae5cff1500e342b810133 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 12:42:33 +1100 Subject: [PATCH 36/47] usbutils.c use correct config from found (not 0) --- usbutils.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 9c55ca49..422962f4 100644 --- a/usbutils.c +++ b/usbutils.c @@ -815,19 +815,26 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto dame; } - if (libusb_kernel_driver_active(cgusb->handle, 0) == 1) { + if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { applog(LOG_DEBUG, "USB init, kernel attached ..."); - if (libusb_detach_kernel_driver(cgusb->handle, 0) == 0) + err = libusb_detach_kernel_driver(cgusb->handle, found->config); + if (err == 0) applog(LOG_DEBUG, "USB init, kernel detached successfully"); - else - applog(LOG_WARNING, "USB init, kernel detach failed :("); + else { + applog(LOG_WARNING, + "USB init, kernel detach failed, err %s - %s device %d:%d in use?", + err, found->name, + (int)(cgpu->usbinfo.bus_number), + (int)(cgpu->usbinfo.device_address)); + goto cldame; + } } err = libusb_set_configuration(cgusb->handle, found->config); if (err) { switch(err) { case LIBUSB_ERROR_BUSY: - applog(LOG_WARNING, "USB init, %s device %d:%d in use", + applog(LOG_WARNING, "USB init, set config - %s device %d:%d in use", found->name, (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address)); break; From 59c73ae59a61ac5034dabce460429e568aff0e39 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 15:56:42 +1100 Subject: [PATCH 37/47] USB usb_init() consistent err/warning/debug messages --- usbutils.c | 72 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/usbutils.c b/usbutils.c index 422962f4..31489a08 100644 --- a/usbutils.c +++ b/usbutils.c @@ -781,11 +781,15 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find const struct libusb_interface_descriptor *idesc; const struct libusb_endpoint_descriptor *epdesc; unsigned char strbuf[STRBUFLEN+1]; + char devstr[STRBUFLEN+1]; int err, i, j, k; cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); cgpu->usbinfo.device_address = libusb_get_device_address(dev); + sprintf(devstr, "- %s device %d:%d", found->name, + cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); + cgusb = calloc(1, sizeof(*cgusb)); cgusb->found = found; @@ -793,7 +797,9 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_get_device_descriptor(dev, cgusb->descriptor); if (err) { - applog(LOG_ERR, "USB init failed to get descriptor, err %d", err); + applog(LOG_DEBUG, + "USB init failed to get descriptor, err %d %s", + err, devstr); goto dame; } @@ -801,31 +807,39 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find if (err) { switch (err) { case LIBUSB_ERROR_ACCESS: - applog(LOG_ERR, "USB init open device failed, err %d, you dont have priviledge to access the device", err); + applog(LOG_ERR, + "USB init open device failed, err %d, " + "you dont have priviledge to access %s", + err, devstr); break; #ifdef WIN32 // Windows specific message case LIBUSB_ERROR_NOT_SUPPORTED: - applog(LOG_ERR, "USB init, open device failed, err %d, you need to install a Windows USB driver for the device", err); + applog(LOG_ERR, + "USB init, open device failed, err %d, " + "you need to install a Windows USB driver for %s", + err, devstr); break; #endif default: - applog(LOG_ERR, "USB init, open device failed, err %d", err); + applog(LOG_DEBUG, + "USB init, open failed, err %d %s", + err, devstr); } goto dame; } if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { - applog(LOG_DEBUG, "USB init, kernel attached ..."); + applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); err = libusb_detach_kernel_driver(cgusb->handle, found->config); - if (err == 0) - applog(LOG_DEBUG, "USB init, kernel detached successfully"); - else { + if (err == 0) { + applog(LOG_DEBUG, + "USB init, kernel detached successfully %s", + devstr); + } else { applog(LOG_WARNING, - "USB init, kernel detach failed, err %s - %s device %d:%d in use?", - err, found->name, - (int)(cgpu->usbinfo.bus_number), - (int)(cgpu->usbinfo.device_address)); + "USB init, kernel detach failed, err %d in use? %s", + err, devstr); goto cldame; } } @@ -834,21 +848,23 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find if (err) { switch(err) { case LIBUSB_ERROR_BUSY: - applog(LOG_WARNING, "USB init, set config - %s device %d:%d in use", - found->name, (int)(cgpu->usbinfo.bus_number), - (int)(cgpu->usbinfo.device_address)); + applog(LOG_WARNING, + "USB init, set config %d in use %s", + found->config, devstr); break; default: - applog(LOG_DEBUG, "USB init, failed to set config to %d, err %d", - found->config, err); + applog(LOG_DEBUG, + "USB init, failed to set config to %d, err %d %s", + found->config, err, devstr); } goto cldame; } err = libusb_get_active_config_descriptor(dev, &config); if (err) { - applog(LOG_DEBUG, "USB init, failed to get config descriptor %d, err %d", - found->config, err); + applog(LOG_DEBUG, + "USB init, failed to get config descriptor %d, err %d %s", + found->config, err, devstr); goto cldame; } @@ -881,8 +897,17 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_claim_interface(cgusb->handle, found->interface); if (err) { - applog(LOG_DEBUG, "USB init, claim interface %d failed, err %d", - found->interface, err); + switch(err) { + case LIBUSB_ERROR_BUSY: + applog(LOG_WARNING, + "USB init, claim interface %d in use %s", + found->interface, devstr); + break; + default: + applog(LOG_DEBUG, + "USB init, claim interface %d failed, err %d %s", + found->interface, err, devstr); + } goto cldame; } @@ -916,7 +941,10 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find // cgusb->fwVersion <- for temp1/temp2 decision? or serial? (driver-modminer.c) // cgusb->interfaceVersion - applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); + applog(LOG_DEBUG, + "USB init %s usbver=%04x prod='%s' manuf='%s' serial='%s'", + devstr, cgusb->usbver, cgusb->prod_string, + cgusb->manuf_string, cgusb->serial_string); cgpu->usbdev = cgusb; From cb3e3ebfac5edd8ff696eaa31913ea5812bd4b05 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 20:37:28 +1100 Subject: [PATCH 38/47] USB system wide device locking on linux --- usbutils.c | 286 +++++++++++++++++++++++++++-------------------------- 1 file changed, 144 insertions(+), 142 deletions(-) diff --git a/usbutils.c b/usbutils.c index 31489a08..2e758a07 100644 --- a/usbutils.c +++ b/usbutils.c @@ -110,24 +110,10 @@ extern struct device_drv icarus_drv; extern struct device_drv modminer_drv; #endif -/* - * Our own internal list of used USB devices - * So two drivers or a single driver searching - * can't touch the same device during detection - */ -struct usb_list { - uint8_t bus_number; - uint8_t device_address; - uint8_t filler[2]; - struct usb_list *prev; - struct usb_list *next; -}; - #define STRBUFLEN 256 static const char *BLANK = ""; -static pthread_mutex_t *list_lock = NULL; -static struct usb_list *usb_head = NULL; +static bool stats_initialised = false; struct cg_usb_stats_item { uint64_t count; @@ -537,10 +523,7 @@ static void cgusb_check_init() { mutex_lock(&cgusb_lock); - if (list_lock == NULL) { - list_lock = calloc(1, sizeof(*list_lock)); - mutex_init(list_lock); - + if (stats_initialised == false) { // N.B. environment LIBUSB_DEBUG also sets libusb_set_debug() if (opt_usbdump >= 0) { libusb_set_debug(NULL, opt_usbdump); @@ -592,134 +575,163 @@ static void cgusb_check_init() mutex_unlock(&cgusb_lock); } -static bool in_use(libusb_device *dev, bool lock) -{ - struct usb_list *usb_tmp; - bool used = false; - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - if (lock) - mutex_lock(list_lock); - - if ((usb_tmp = usb_head)) - do { - if (bus_number == usb_tmp->bus_number - && device_address == usb_tmp->device_address) { - used = true; - break; - } - - usb_tmp = usb_tmp->next; - - } while (usb_tmp != usb_head); - - if (lock) - mutex_unlock(list_lock); - - return used; -} +#ifdef WIN32 +#else +#include +#include +#include +#include +#include +#include +#include +#include + +union semun { + int sem; + struct semid_ds *seminfo; + ushort *all; +}; +#endif -static void add_used(libusb_device *dev, bool lock) +// Any errors should always be printed since they will rarely if ever occur +// and thus it is best to always display them +static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { - struct usb_list *usb_tmp; - char buf[128]; - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - if (lock) - mutex_lock(list_lock); +#ifdef WIN32 +#else + struct semid_ds seminfo; + union semun opt; + char name[64]; + key_t key; + int fd, sem, count; + + sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd == -1) { + applog(LOG_ERR, + "SEM: %s USB open failed '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } + close(fd); + key = ftok(name, 'K'); + sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438); + if (sem < 0) { + if (errno != EEXIST) { + applog(LOG_ERR, + "SEM: %s USB failed to get '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } - if (in_use(dev, false)) { - if (lock) - mutex_unlock(list_lock); + sem = semget(key, 1, 0); + if (sem < 0) { + applog(LOG_ERR, + "SEM: %s USB failed to access '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } - sprintf(buf, "add_used() duplicate bus_number %d device_address %d", - (int)bus_number, (int)device_address); - quit(1, buf); + opt.seminfo = &seminfo; + count = 0; + while (++count) { + // Should NEVER take 100ms + if (count > 99) { + applog(LOG_ERR, + "SEM: %s USB timeout waiting for (%d) '%s'", + drv->dname, sem, name); + return false; + } + if (semctl(sem, 0, IPC_STAT, opt) == -1) { + applog(LOG_ERR, + "SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s", + drv->dname, sem, name, count, errno, strerror(errno)); + return false; + } + if (opt.seminfo->sem_otime != 0) + break; + nmsleep(1); + } } - usb_tmp = malloc(sizeof(*usb_tmp)); - - usb_tmp->bus_number = bus_number; - usb_tmp->device_address = device_address; - - if (usb_head) { - // add to end - usb_tmp->prev = usb_head->prev; - usb_tmp->next = usb_head; - usb_head->prev = usb_tmp; - usb_tmp->prev->next = usb_tmp; - } else { - usb_tmp->prev = usb_tmp; - usb_tmp->next = usb_tmp; - usb_head = usb_tmp; + struct sembuf sops[] = { + { 0, 0, IPC_NOWAIT | SEM_UNDO }, + { 0, 1, IPC_NOWAIT | SEM_UNDO } + }; + + if (semop(sem, sops, 2)) { + if (errno == EAGAIN) { + applog(LOG_WARNING, + "SEM: %s USB failed to get (%d) '%s' - device in use", + drv->dname, sem, name); + } else { + applog(LOG_DEBUG, + "SEM: %s USB failed to get (%d) '%s' err(%d) %s", + drv->dname, sem, name, errno, strerror(errno)); + } + return false; } - if (lock) - mutex_unlock(list_lock); + return true; +#endif } -static void release(uint8_t bus_number, uint8_t device_address, bool lock) +static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) { - struct usb_list *usb_tmp; - bool found = false; - char buf[128]; - - if (lock) - mutex_lock(list_lock); - - if ((usb_tmp = usb_head)) - do { - if (bus_number == usb_tmp->bus_number - && device_address == usb_tmp->device_address) { - found = true; - break; - } - - usb_tmp = usb_tmp->next; + return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev)); +} - } while (usb_tmp != usb_head); +// Any errors should always be printed since they will rarely if ever occur +// and thus it is best to always display them +static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) +{ +#ifdef WIN32 +#else + char name[64]; + key_t key; + int fd, sem; + + sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd == -1) { + applog(LOG_ERR, + "SEM: %s USB open failed '%s' for release err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return; + } + close(fd); + key = ftok(name, 'K'); + + sem = semget(key, 1, 0); + if (sem < 0) { + applog(LOG_ERR, + "SEM: %s USB failed to get '%s' for release err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return; + } - if (!found) { - if (lock) - mutex_unlock(list_lock); + struct sembuf sops[] = { + { 0, -1, SEM_UNDO } + }; - sprintf(buf, "release() unknown: bus_number %d device_address %d", - (int)bus_number, (int)device_address); - quit(1, buf); - } + // Allow a 10ms timeout + // exceeding this timeout means it would probably never succeed anyway + struct timespec timeout = { 0, 10000000 }; - if (usb_tmp->next == usb_tmp) { - usb_head = NULL; - } else { - if (usb_head == usb_tmp) - usb_head = usb_tmp->next; - usb_tmp->next->prev = usb_tmp->prev; - usb_tmp->prev->next = usb_tmp->next; + // Wait forever since we shoud be the one who has it + if (semtimedop(sem, sops, 1, &timeout)) { + applog(LOG_ERR, + "SEM: %d USB failed to release '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); } - if (lock) - mutex_unlock(list_lock); - - free(usb_tmp); + return; +#endif } -static void release_dev(libusb_device *dev, bool lock) +static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev) { - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - release(bus_number, device_address, lock); + cgminer_usb_unlock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev)); } static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) @@ -771,7 +783,7 @@ void release_cgpu(struct cgpu_info *cgpu) usb_uninit(cgpu); - release(cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address, true); + cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); } bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) @@ -1053,21 +1065,11 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi applog(LOG_DEBUG, "USB scan devices: found no devices"); for (i = 0; i < count; i++) { - mutex_lock(list_lock); - - if (in_use(list[i], false)) - mutex_unlock(list_lock); - else { - add_used(list[i], false); - - mutex_unlock(list_lock); - - found = usb_check(drv, list[i]); - if (!found) - release_dev(list[i], true); - else + found = usb_check(drv, list[i]); + if (found) { + if (cgminer_usb_lock(drv, list[i]) == true) if (!device_detect(list[i], found)) - release_dev(list[i], true); + cgminer_usb_unlock(drv, list[i]); } } From 829730408920371bdd18892ca5e208b72403b76e Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 20:41:29 +1100 Subject: [PATCH 39/47] USB device locking NOOP for windows (for now) --- usbutils.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/usbutils.c b/usbutils.c index 2e758a07..035e5621 100644 --- a/usbutils.c +++ b/usbutils.c @@ -598,6 +598,10 @@ union semun { static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 + // NOOP for now + drv = 0; + bus_number = device_address = 0; + return true; #else struct semid_ds seminfo; union semun opt; @@ -686,6 +690,9 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 + // NOOP for now + drv = 0; + bus_number = device_address = 0; #else char name[64]; key_t key; From 028da16bf804d5bdebaffa8a6e47ae94b6fa3d85 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 22:13:42 +1100 Subject: [PATCH 40/47] usbutils free found if not used --- usbutils.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 035e5621..9eab1e1f 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1073,10 +1073,13 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi for (i = 0; i < count; i++) { found = usb_check(drv, list[i]); - if (found) { - if (cgminer_usb_lock(drv, list[i]) == true) + if (found != NULL) { + if (cgminer_usb_lock(drv, list[i]) == false) + free(found); + else { if (!device_detect(list[i], found)) cgminer_usb_unlock(drv, list[i]); + } } } From 16fa090013c4ba1fb5eac4b9cfbe2dda4dc0691c Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 22:39:26 +1100 Subject: [PATCH 41/47] usbutils stats_initialised not set --- usbutils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usbutils.c b/usbutils.c index 9eab1e1f..3c03510a 100644 --- a/usbutils.c +++ b/usbutils.c @@ -570,6 +570,8 @@ static void cgusb_check_init() usb_commands[C_SETMODEM] = C_SETMODEM_S; usb_commands[C_PURGERX] = C_PURGERX_S; usb_commands[C_PURGETX] = C_PURGETX_S; + + stats_initialised = true; } mutex_unlock(&cgusb_lock); From 128e3270fbb3f82f811e5de0679eb08793f63ced Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 24 Jan 2013 02:39:37 +1100 Subject: [PATCH 42/47] USB system wide device locking on windows --- usbutils.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 7 deletions(-) diff --git a/usbutils.c b/usbutils.c index 3c03510a..42b23d38 100644 --- a/usbutils.c +++ b/usbutils.c @@ -600,10 +600,67 @@ union semun { static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 - // NOOP for now - drv = 0; - bus_number = device_address = 0; + struct cgpu_info *cgpu; + HANDLE usbMutex; + char name[64]; + DWORD res; + int i; + + sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + + usbMutex = CreateMutex(NULL, FALSE, name); + if (usbMutex == NULL) { + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' err (%d)", + drv->dname, name, GetLastError()); + return false; + } + + res = WaitForSingleObject(usbMutex, 0); + switch(res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // Am I using it already? + for (i = 0; i < total_devices; i++) { + cgpu = devices[i]; + if (cgpu->usbinfo.bus_number == bus_number && + cgpu->usbinfo.device_address == device_address && + cgpu->usbinfo.nodev == false) { + if (ReleaseMutex(usbMutex)) { + applog(LOG_WARNING, + "MTX: %s USB can't get '%s' - device in use", + drv->dname, name); + goto fail; + } + applog(LOG_ERR, + "MTX: %s USB can't get '%s' - device in use - failure (%d)", + drv->dname, name, GetLastError()); + goto fail; + } + } + return true; + case WAIT_TIMEOUT: + applog(LOG_WARNING, + "MTX: %s USB failed to get '%s' - device in use", + drv->dname, name); + goto fail; + case WAIT_FAILED: + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' err (%d)", + drv->dname, name, GetLastError()); + goto fail; + default: + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' unknown reply (%d)", + drv->dname, name, res); + goto fail; + } + + CloseHandle(usbMutex); return true; +fail: + CloseHandle(usbMutex); + return false; #else struct semid_ds seminfo; union semun opt; @@ -672,7 +729,7 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint drv->dname, sem, name); } else { applog(LOG_DEBUG, - "SEM: %s USB failed to get (%d) '%s' err(%d) %s", + "SEM: %s USB failed to get (%d) '%s' err (%d) %s", drv->dname, sem, name, errno, strerror(errno)); } return false; @@ -692,9 +749,26 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 - // NOOP for now - drv = 0; - bus_number = device_address = 0; + HANDLE usbMutex; + char name[64]; + + sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + + usbMutex = CreateMutex(NULL, FALSE, name); + if (usbMutex == NULL) { + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' for release err (%d)", + drv->dname, name, GetLastError()); + return; + } + + if (!ReleaseMutex(usbMutex)) + applog(LOG_ERR, + "MTX: %s USB failed to release '%s' err (%d)", + drv->dname, name, GetLastError()); + + CloseHandle(usbMutex); + return; #else char name[64]; key_t key; From 05157e0802972ee25b187ee7e0ba18d5a9e097a5 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 26 Jan 2013 21:49:20 +1100 Subject: [PATCH 43/47] USB in linux use the expected kernel config to check and detach - and set the configuration in linux also --- usbutils.c | 14 +++++++++----- usbutils.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 42b23d38..a34028e3 100644 --- a/usbutils.c +++ b/usbutils.c @@ -77,6 +77,7 @@ static struct usb_find_devices find_dev[] = { .name = "BFL", .idVendor = 0x0403, .idProduct = 0x6014, + .kernel = 0, .config = 1, .interface = 0, .timeout = BITFORCE_TIMEOUT_MS, @@ -89,13 +90,14 @@ static struct usb_find_devices find_dev[] = { .name = "MMQ", .idVendor = 0x1fc9, .idProduct = 0x0003, + .kernel = 0, .config = 1, .interface = 1, .timeout = MODMINER_TIMEOUT_MS, .epcount = ARRAY_SIZE(mmq_eps), .eps = mmq_eps }, #endif - { DRV_LAST, NULL, 0, 0, 0, 0, 0, 0, NULL } + { DRV_LAST, NULL, 0, 0, 0, 0, 0, 0, 0, NULL } }; #ifdef USE_BITFORCE @@ -924,9 +926,10 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto dame; } - if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { +#ifndef WIN32 + if (libusb_kernel_driver_active(cgusb->handle, found->kernel) == 1) { applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); - err = libusb_detach_kernel_driver(cgusb->handle, found->config); + err = libusb_detach_kernel_driver(cgusb->handle, found->kernel); if (err == 0) { applog(LOG_DEBUG, "USB init, kernel detached successfully %s", @@ -938,6 +941,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto cldame; } } +#endif err = libusb_set_configuration(cgusb->handle, found->config); if (err) { @@ -958,8 +962,8 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_get_active_config_descriptor(dev, &config); if (err) { applog(LOG_DEBUG, - "USB init, failed to get config descriptor %d, err %d %s", - found->config, err, devstr); + "USB init, failed to get config descriptor, err %d %s", + err, devstr); goto cldame; } diff --git a/usbutils.h b/usbutils.h index d63122f8..ac6ce0cd 100644 --- a/usbutils.h +++ b/usbutils.h @@ -55,6 +55,7 @@ struct usb_find_devices { const char *name; uint16_t idVendor; uint16_t idProduct; + int kernel; int config; int interface; unsigned int timeout; From 7388942bbd9471049a86ca3bbd2b92dc408cb512 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 26 Jan 2013 21:57:09 +1100 Subject: [PATCH 44/47] Stratum disconnect shares - count total against stale --- cgminer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index c42703fb..af1e668b 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4601,8 +4601,8 @@ static void clear_stratum_shares(struct pool *pool) if (cleared) { applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no); - pool->stale_shares++; - total_stale++; + pool->stale_shares += cleared; + total_stale += cleared; } } From 8fbc4dade6205e101b1bbc0ac4c169b8c886c188 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 28 Jan 2013 13:54:23 +1100 Subject: [PATCH 45/47] MMQ must copy USB bus:device due to usbinfo change --- driver-modminer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver-modminer.c b/driver-modminer.c index 2c850b84..02ad85dc 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -210,6 +210,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic tmp->device_path = strdup(devpath); tmp->usbdev = modminer->usbdev; + tmp->usbinfo.bus_number = modminer->usbinfo.bus_number; + tmp->usbinfo.device_address = modminer->usbinfo.device_address; // Only the first copy gets the already used stats if (!added) tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; From 212f32e5e03ac8b351fce8b2bc9a2f7317664419 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 29 Jan 2013 23:44:09 +1100 Subject: [PATCH 46/47] Split thr_info array into control_thr and mining_thr pointers so more mining threads can be added later --- api.c | 8 ++--- cgminer.c | 94 ++++++++++++++++++++++++++++--------------------- driver-cpu.c | 2 +- driver-opencl.c | 16 ++++----- miner.h | 3 +- 5 files changed, 69 insertions(+), 54 deletions(-) diff --git a/api.c b/api.c index a2470b0d..00d1f3ba 100644 --- a/api.c +++ b/api.c @@ -1800,9 +1800,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { - pga = thr_info[i].cgpu->cgminer_id; + thr = mining_thr[i]; + pga = thr->cgpu->cgminer_id; if (pga == dev) { - thr = &thr_info[i]; cgpu->deven = DEV_ENABLED; applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); @@ -2105,9 +2105,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } for (i = 0; i < gpu_threads; i++) { - gpu = thr_info[i].cgpu->device_id; + thr = mining_thr[i]; + gpu = thr->cgpu->device_id; if (gpu == id) { - thr = &thr_info[i]; if (thr->cgpu->status != LIFE_WELL) { message(io_data, MSG_GPUMRE, id, NULL, isjson); return; diff --git a/cgminer.c b/cgminer.c index af1e668b..3b4d77dc 100644 --- a/cgminer.c +++ b/cgminer.c @@ -146,7 +146,8 @@ bool opt_bfl_noncerange; #endif #define QUIET (opt_quiet || opt_realquiet) -struct thr_info *thr_info; +struct thr_info *control_thr; +struct thr_info **mining_thr; static int gwsched_thr_id; static int stage_thr_id; static int watchpool_thr_id; @@ -156,7 +157,7 @@ static int input_thr_id; #endif int gpur_thr_id; static int api_thr_id; -static int total_threads; +static int total_control_threads; #ifdef HAVE_LIBUSB pthread_mutex_t cgusb_lock; @@ -377,7 +378,7 @@ static void sharelog(const char*disposition, const struct work*work) return; thr_id = work->thr_id; - cgpu = thr_info[thr_id].cgpu; + cgpu = mining_thr[thr_id]->cgpu; pool = work->pool; t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); @@ -1722,7 +1723,7 @@ out: int dev_from_id(int thr_id) { - return thr_info[thr_id].cgpu->device_id; + return mining_thr[thr_id]->cgpu->device_id; } /* Make the change in the recent value adjust dynamically when the difference @@ -1894,7 +1895,7 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) static void text_print_status(int thr_id) { - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; char logline[256]; if (cgpu) { @@ -1960,7 +1961,7 @@ static int dev_width; static void curses_print_devstatus(int thr_id) { static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; char logline[256]; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; @@ -2212,7 +2213,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, char *hashshow, bool resubmit, char *worktime) { struct pool *pool = work->pool; - struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[work->thr_id]->cgpu; if (json_is_true(res) || (work->gbt && json_is_null(res))) { mutex_lock(&stats_lock); @@ -2362,7 +2363,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) char *s; bool rc = false; int thr_id = work->thr_id; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; struct pool *pool = work->pool; int rolltime; struct timeval tv_submit, tv_submit_reply; @@ -2744,18 +2745,18 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off watchpool thread"); /* Kill the watchpool thread */ - thr = &thr_info[watchpool_thr_id]; + thr = &control_thr[watchpool_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Killing off watchdog thread"); /* Kill the watchdog thread */ - thr = &thr_info[watchdog_thr_id]; + thr = &control_thr[watchdog_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Stopping mining threads"); /* Stop the mining threads*/ for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; thr_info_freeze(thr); thr->pause = true; } @@ -2765,17 +2766,17 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; thr_info_cancel(thr); } applog(LOG_DEBUG, "Killing off stage thread"); /* Stop the others */ - thr = &thr_info[stage_thr_id]; + thr = &control_thr[stage_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Killing off API thread"); - thr = &thr_info[api_thr_id]; + thr = &control_thr[api_thr_id]; thr_info_cancel(thr); } @@ -3369,7 +3370,7 @@ static void restart_threads(void) discard_stale(); for (i = 0; i < mining_threads; i++) - thr_info[i].work_restart = true; + mining_thr[i]->work_restart = true; mutex_lock(&restart_lock); pthread_cond_broadcast(&restart_cond); @@ -4409,16 +4410,16 @@ static void hashmeter(int thr_id, struct timeval *diff, local_mhashes = (double)hashes_done / 1000000.0; /* Update the last time this thread reported in */ if (thr_id >= 0) { - gettimeofday(&thr_info[thr_id].last, NULL); - thr_info[thr_id].cgpu->device_last_well = time(NULL); + gettimeofday(&(mining_thr[thr_id]->last), NULL); + mining_thr[thr_id]->cgpu->device_last_well = time(NULL); } secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); /* So we can call hashmeter from a non worker thread */ if (thr_id >= 0) { - struct thr_info *thr = &thr_info[thr_id]; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct thr_info *thr = mining_thr[thr_id]; + struct cgpu_info *cgpu = thr->cgpu; double thread_rolling = 0.0; int i; @@ -4908,7 +4909,7 @@ retry_stratum: calc_diff(work, 0); applog(LOG_DEBUG, "Pushing pooltest work to base pool"); - tq_push(thr_info[stage_thr_id].q, work); + tq_push(control_thr[stage_thr_id].q, work); total_getworks++; pool->getwork_requested++; ret = true; @@ -5858,7 +5859,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) sched_paused = true; for (i = 0; i < mining_threads; i++) { struct thr_info *thr; - thr = &thr_info[i]; + thr = mining_thr[i]; thr->pause = true; } @@ -5872,7 +5873,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) for (i = 0; i < mining_threads; i++) { struct thr_info *thr; - thr = &thr_info[i]; + thr = mining_thr[i]; /* Don't touch disabled devices */ if (thr->cgpu->deven == DEV_DISABLED) @@ -6709,14 +6710,23 @@ int main(int argc, char *argv[]) fork_monitor(); #endif // defined(unix) - total_threads = mining_threads + 7; - thr_info = calloc(total_threads, sizeof(*thr)); - if (!thr_info) - quit(1, "Failed to calloc thr_info"); + mining_thr = calloc(mining_threads, sizeof(thr)); + if (!mining_thr) + quit(1, "Failed to calloc mining_thr"); + for (i = 0; i < mining_threads; i++) { + mining_thr[i] = calloc(1, sizeof(*thr)); + if (!mining_thr[i]) + quit(1, "Failed to calloc mining_thr[%d]", i); + } - gwsched_thr_id = mining_threads; - stage_thr_id = mining_threads + 1; - thr = &thr_info[stage_thr_id]; + total_control_threads = 7; + control_thr = calloc(total_control_threads, sizeof(*thr)); + if (!control_thr) + quit(1, "Failed to calloc control_thr"); + + gwsched_thr_id = 0; + stage_thr_id = 1; + thr = &control_thr[stage_thr_id]; thr->q = tq_new(); if (!thr->q) quit(1, "Failed to tq_new"); @@ -6808,7 +6818,7 @@ begin_bench: cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j, ++k) { - thr = &thr_info[k]; + thr = mining_thr[k]; thr->id = k; thr->cgpu = cgpu; thr->device_thread = j; @@ -6853,15 +6863,15 @@ begin_bench: gettimeofday(&total_tv_start, NULL); gettimeofday(&total_tv_end, NULL); - watchpool_thr_id = mining_threads + 2; - thr = &thr_info[watchpool_thr_id]; + watchpool_thr_id = 2; + thr = &control_thr[watchpool_thr_id]; /* start watchpool thread */ if (thr_info_create(thr, NULL, watchpool_thread, NULL)) quit(1, "watchpool thread create failed"); pthread_detach(thr->pth); - watchdog_thr_id = mining_threads + 3; - thr = &thr_info[watchdog_thr_id]; + watchdog_thr_id = 3; + thr = &control_thr[watchdog_thr_id]; /* start watchdog thread */ if (thr_info_create(thr, NULL, watchdog_thread, NULL)) quit(1, "watchdog thread create failed"); @@ -6869,8 +6879,8 @@ begin_bench: #ifdef HAVE_OPENCL /* Create reinit gpu thread */ - gpur_thr_id = mining_threads + 4; - thr = &thr_info[gpur_thr_id]; + gpur_thr_id = 4; + thr = &control_thr[gpur_thr_id]; thr->q = tq_new(); if (!thr->q) quit(1, "tq_new failed for gpur_thr_id"); @@ -6879,8 +6889,8 @@ begin_bench: #endif /* Create API socket thread */ - api_thr_id = mining_threads + 5; - thr = &thr_info[api_thr_id]; + api_thr_id = 5; + thr = &control_thr[api_thr_id]; if (thr_info_create(thr, NULL, api_thread, thr)) quit(1, "API thread create failed"); @@ -6888,13 +6898,17 @@ begin_bench: /* Create curses input thread for keyboard input. Create this last so * that we know all threads are created since this can call kill_work * to try and shut down ll previous threads. */ - input_thr_id = mining_threads + 6; - thr = &thr_info[input_thr_id]; + input_thr_id = 6; + thr = &control_thr[input_thr_id]; if (thr_info_create(thr, NULL, input_thread, thr)) quit(1, "input thread create failed"); pthread_detach(thr->pth); #endif + /* Just to be sure */ + if (total_control_threads != 7) + quit(1, "incorrect total_control_threads (%d) should be 7", total_control_threads); + /* Once everything is set up, main() becomes the getwork scheduler */ while (42) { int ts, max_staged = opt_queue; diff --git a/driver-cpu.c b/driver-cpu.c index eb46f3d8..4b0c0865 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -768,7 +768,7 @@ static void cpu_detect() static void reinit_cpu_device(struct cgpu_info *cpu) { - tq_push(thr_info[cpur_thr_id].q, cpu); + tq_push(control_thr[cpur_thr_id].q, cpu); } static bool cpu_thread_prepare(struct thr_info *thr) diff --git a/driver-opencl.c b/driver-opencl.c index 966d8cd0..eacb0f76 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -616,7 +616,7 @@ void pause_dynamic_threads(int gpu) int i; for (i = 1; i < cgpu->threads; i++) { - struct thr_info *thr = &thr_info[i]; + struct thr_info *thr = mining_thr[i]; if (!thr->pause && cgpu->dynamic) { applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); @@ -705,7 +705,7 @@ retry: else wlog("%d\n", gpus[gpu].intensity); for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; if (thr->cgpu != cgpu) continue; get_datestamp(checkin, &thr->last); @@ -760,7 +760,7 @@ retry: } gpus[selected].deven = DEV_ENABLED; for (i = 0; i < mining_threads; ++i) { - thr = &thr_info[i]; + thr = mining_thr[i]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1147,14 +1147,14 @@ select_cgpu: gpu = cgpu->device_id; for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; if (!thr) { applog(LOG_WARNING, "No reference to thread %d exists", thr_id); continue; @@ -1172,7 +1172,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { int virtual_gpu; - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1209,7 +1209,7 @@ select_cgpu: get_datestamp(cgpu->init, &now); for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1263,7 +1263,7 @@ static void opencl_detect() static void reinit_opencl_device(struct cgpu_info *gpu) { - tq_push(thr_info[gpur_thr_id].q, gpu); + tq_push(control_thr[gpur_thr_id].q, gpu); } #ifdef HAVE_ADL diff --git a/miner.h b/miner.h index 2a74bdc0..e6d18c00 100644 --- a/miner.h +++ b/miner.h @@ -784,7 +784,8 @@ extern int num_processors; extern int hw_errors; extern bool use_syslog; extern bool opt_quiet; -extern struct thr_info *thr_info; +extern struct thr_info *control_thr; +extern struct thr_info **mining_thr; extern struct cgpu_info gpus[MAX_GPUDEVICES]; extern int gpu_threads; #ifdef USE_SCRYPT From 61ec1fe91f2a2da3511243848f04ddad9d0874de Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 30 Jan 2013 15:02:25 +1100 Subject: [PATCH 47/47] mutex all access to mining_thr --- api.c | 4 +++ cgminer.c | 66 ++++++++++++++++++++++++++++++++++++++----------- driver-opencl.c | 18 +++++++++++++- miner.h | 1 + 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/api.c b/api.c index 00d1f3ba..4998d97b 100644 --- a/api.c +++ b/api.c @@ -1800,7 +1800,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); pga = thr->cgpu->cgminer_id; if (pga == dev) { cgpu->deven = DEV_ENABLED; @@ -2105,7 +2107,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } for (i = 0; i < gpu_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); gpu = thr->cgpu->device_id; if (gpu == id) { if (thr->cgpu->status != LIFE_WELL) { diff --git a/cgminer.c b/cgminer.c index 3b4d77dc..1a43e77b 100644 --- a/cgminer.c +++ b/cgminer.c @@ -172,6 +172,7 @@ static pthread_rwlock_t blk_lock; static pthread_mutex_t sshare_lock; pthread_rwlock_t netacc_lock; +pthread_mutex_t mining_thr_lock; static pthread_mutex_t lp_lock; static pthread_cond_t lp_cond; @@ -378,7 +379,9 @@ static void sharelog(const char*disposition, const struct work*work) return; thr_id = work->thr_id; + mutex_lock(&mining_thr_lock); cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); pool = work->pool; t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); @@ -1723,7 +1726,13 @@ out: int dev_from_id(int thr_id) { - return mining_thr[thr_id]->cgpu->device_id; + struct cgpu_info *cgpu; + + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + + return cgpu->device_id; } /* Make the change in the recent value adjust dynamically when the difference @@ -1895,9 +1904,13 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) static void text_print_status(int thr_id) { - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; char logline[256]; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + if (cgpu) { get_statline(logline, cgpu); printf("%s\n", logline); @@ -1961,11 +1974,15 @@ static int dev_width; static void curses_print_devstatus(int thr_id) { static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; char logline[256]; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) return; @@ -2213,7 +2230,11 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, char *hashshow, bool resubmit, char *worktime) { struct pool *pool = work->pool; - struct cgpu_info *cgpu = mining_thr[work->thr_id]->cgpu; + struct cgpu_info *cgpu; + + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[work->thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); if (json_is_true(res) || (work->gbt && json_is_null(res))) { mutex_lock(&stats_lock); @@ -2363,13 +2384,17 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) char *s; bool rc = false; int thr_id = work->thr_id; - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; struct pool *pool = work->pool; int rolltime; struct timeval tv_submit, tv_submit_reply; char hashshow[64 + 4] = ""; char worktime[200] = ""; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + #ifdef __BIG_ENDIAN__ int swapcounter = 0; for (swapcounter = 0; swapcounter < 32; swapcounter++) @@ -2756,7 +2781,9 @@ static void __kill_work(void) applog(LOG_DEBUG, "Stopping mining threads"); /* Stop the mining threads*/ for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); thr_info_freeze(thr); thr->pause = true; } @@ -2766,7 +2793,9 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); thr_info_cancel(thr); } @@ -3369,8 +3398,10 @@ static void restart_threads(void) /* Discard staged work that is now stale */ discard_stale(); + mutex_lock(&mining_thr_lock); for (i = 0; i < mining_threads; i++) mining_thr[i]->work_restart = true; + mutex_unlock(&mining_thr_lock); mutex_lock(&restart_lock); pthread_cond_broadcast(&restart_cond); @@ -4406,19 +4437,22 @@ static void hashmeter(int thr_id, struct timeval *diff, bool showlog = false; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; + struct thr_info *thr; local_mhashes = (double)hashes_done / 1000000.0; /* Update the last time this thread reported in */ if (thr_id >= 0) { - gettimeofday(&(mining_thr[thr_id]->last), NULL); - mining_thr[thr_id]->cgpu->device_last_well = time(NULL); + mutex_lock(&mining_thr_lock); + thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); + gettimeofday(&(thr->last), NULL); + thr->cgpu->device_last_well = time(NULL); } secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); /* So we can call hashmeter from a non worker thread */ if (thr_id >= 0) { - struct thr_info *thr = mining_thr[thr_id]; struct cgpu_info *cgpu = thr->cgpu; double thread_rolling = 0.0; int i; @@ -5857,12 +5891,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) applog(LOG_WARNING, "Will restart execution as scheduled at %02d:%02d", schedstart.tm.tm_hour, schedstart.tm.tm_min); sched_paused = true; - for (i = 0; i < mining_threads; i++) { - struct thr_info *thr; - thr = mining_thr[i]; - - thr->pause = true; - } + mutex_lock(&mining_thr_lock); + for (i = 0; i < mining_threads; i++) + mining_thr[i]->pause = true; + mutex_unlock(&mining_thr_lock); } else if (sched_paused && should_run()) { applog(LOG_WARNING, "Restarting execution as per start time %02d:%02d scheduled", schedstart.tm.tm_hour, schedstart.tm.tm_min); @@ -5873,7 +5905,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) for (i = 0; i < mining_threads; i++) { struct thr_info *thr; + + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); /* Don't touch disabled devices */ if (thr->cgpu->deven == DEV_DISABLED) @@ -6426,6 +6461,7 @@ int main(int argc, char *argv[]) mutex_init(&sshare_lock); rwlock_init(&blk_lock); rwlock_init(&netacc_lock); + mutex_init(&mining_thr_lock); mutex_init(&lp_lock); if (unlikely(pthread_cond_init(&lp_cond, NULL))) @@ -6818,7 +6854,9 @@ begin_bench: cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j, ++k) { + mutex_lock(&mining_thr_lock); thr = mining_thr[k]; + mutex_unlock(&mining_thr_lock); thr->id = k; thr->cgpu = cgpu; thr->device_thread = j; diff --git a/driver-opencl.c b/driver-opencl.c index eacb0f76..299d8c40 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -616,7 +616,11 @@ void pause_dynamic_threads(int gpu) int i; for (i = 1; i < cgpu->threads; i++) { - struct thr_info *thr = mining_thr[i]; + struct thr_info *thr; + + mutex_lock(&mining_thr_lock); + thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); if (!thr->pause && cgpu->dynamic) { applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); @@ -705,7 +709,9 @@ retry: else wlog("%d\n", gpus[gpu].intensity); for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); if (thr->cgpu != cgpu) continue; get_datestamp(checkin, &thr->last); @@ -760,7 +766,9 @@ retry: } gpus[selected].deven = DEV_ENABLED; for (i = 0; i < mining_threads; ++i) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1147,14 +1155,18 @@ select_cgpu: gpu = cgpu->device_id; for (thr_id = 0; thr_id < mining_threads; ++thr_id) { + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); if (!thr) { applog(LOG_WARNING, "No reference to thread %d exists", thr_id); continue; @@ -1172,7 +1184,9 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { int virtual_gpu; + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1209,7 +1223,9 @@ select_cgpu: get_datestamp(cgpu->init, &now); for (thr_id = 0; thr_id < mining_threads; ++thr_id) { + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; diff --git a/miner.h b/miner.h index e6d18c00..f25b6263 100644 --- a/miner.h +++ b/miner.h @@ -737,6 +737,7 @@ extern pthread_mutex_t cgusb_lock; extern pthread_mutex_t hash_lock; extern pthread_mutex_t console_lock; extern pthread_mutex_t ch_lock; +extern pthread_mutex_t mining_thr_lock; extern pthread_mutex_t restart_lock; extern pthread_cond_t restart_cond;
'; - if ($prev !== null) - echo riginput($prev, 'Prev').' '; - echo " "; - if ($next !== null) - echo riginput($next, 'Next').' '; - echo ' '; - if (count($rigs) > 1) - echo " "; + if ($userlist === null || isset($_SESSION[$ses])) + { + if ($prev !== null) + echo riginput($prev, 'Prev').' '; + echo " "; + if ($next !== null) + echo riginput($next, 'Next').' '; + echo ' '; + if (count($rigs) > 1) + echo " "; + } if ($allowcustompages === true) - foreach ($customsummarypages as $pagename => $data) + { + if ($userlist === null || isset($_SESSION[$ses])) + $list = $customsummarypages; + else + { + if ($userlist !== null && isset($userlist['def'])) + $list = array_flip($userlist['def']); + else + $list = array(); + } + + foreach ($list as $pagename => $data) echo " "; + } echo ' '; if ($rig !== null && $readonly === false) @@ -1580,6 +1604,12 @@ function pagebuttons($rig, $pg) echo " "; } refreshbuttons(); + if (isset($_SESSION[$ses])) + echo " "; + else + if ($userlist !== null) + echo " "; + echo "
 
+
+ + +
+ + +
+ + + + + + + + +
 
+

LOGIN

Username:
+
Password:
+
+
+
No rigs defined