diff --git a/Makefile.am b/Makefile.am index 20db8a2d..41a8a1df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,6 +68,10 @@ endif # HAVE_x86_64 endif # HAS_YASM endif # HAS_CPUMINE +if NEED_FPGAUTILS +cgminer_SOURCES += fpgautils.c +endif + if HAS_BITFORCE cgminer_SOURCES += driver-bitforce.c endif diff --git a/README b/README index af78af1e..5a58dc48 100644 --- a/README +++ b/README @@ -129,6 +129,7 @@ Options for both config file and command line: --debug|-D Enable debug output --expiry|-E Upper bound on how many seconds after getting work we consider a share from it stale (default: 120) --failover-only Don't leak work to backup pools when primary pool is lagging +--kernel-path|-K Specify a path to where bitstream and kernel files are (default: "/usr/local/bin") --load-balance Change multipool strategy from failover to even load balance --log|-l Interval in seconds between log output (default: 5) --monitor|-m Use custom pipe cmd for output messages @@ -184,7 +185,6 @@ GPU only options: --gpu-vddc Set the GPU voltage in Volts - one value for all or separate by commas for per card. --intensity|-I Intensity of GPU scanning (d or -10 -> 10, default: d to maintain desktop interactivity) --kernel|-k Override kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated ---kernel-path|-K Specify a path to where the kernel .cl files are (default: "/usr/local/bin") --ndevs|-n Enumerate number of detected GPUs and exit --no-restart Do not attempt to restart GPUs that hang --temp-hysteresis Set how much the temperature can fluctuate outside limits when automanaging speeds (default: 3) diff --git a/cgminer.c b/cgminer.c index 2bbfb0a4..1c31fa09 100644 --- a/cgminer.c +++ b/cgminer.c @@ -54,6 +54,13 @@ #include #endif +#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_MODMINER) +# define USE_FPGA +# define USE_FPGA_SERIAL +#elif defined(USE_ZTEX) +# define USE_FPGA +#endif + enum workio_commands { WC_GET_WORK, WC_SUBMIT_WORK, @@ -468,7 +475,7 @@ static char *set_int_1_to_10(const char *arg, int *i) return set_int_range(arg, i, 1, 10); } -#if defined(USE_BITFORCE) || defined(USE_ICARUS) +#ifdef USE_FPGA_SERIAL static char *add_serial(char *arg) { string_elist_add(arg, &scan_devices); @@ -768,7 +775,7 @@ static struct opt_table opt_config_table[] = { opt_hidden #endif ), -#if defined(WANT_CPUMINE) && (defined(HAVE_OPENCL) || defined(USE_BITFORCE) || defined(USE_ICARUS)) +#if defined(WANT_CPUMINE) && (defined(HAVE_OPENCL) || defined(USE_FPGA)) OPT_WITHOUT_ARG("--enable-cpu|-C", opt_set_bool, &opt_usecpu, "Enable CPU mining with other mining (default: no CPU mining if other devices exist)"), @@ -818,9 +825,13 @@ static struct opt_table opt_config_table[] = { OPT_WITH_ARG("--intensity|-I", set_intensity, NULL, NULL, "Intensity of GPU scanning (d or " _MIN_INTENSITY_STR " -> " _MAX_INTENSITY_STR ", default: d to maintain desktop interactivity)"), +#endif +#if defined(HAVE_OPENCL) || defined(HAVE_MODMINER) OPT_WITH_ARG("--kernel-path|-K", opt_set_charp, opt_show_charp, &opt_kernel_path, - "Specify a path to where the kernel .cl files are"), + "Specify a path to where bitstream and kernel files are"), +#endif +#ifdef HAVE_OPENCL OPT_WITH_ARG("--kernel|-k", set_kernel, NULL, NULL, "Override kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"), @@ -899,7 +910,7 @@ static struct opt_table opt_config_table[] = { OPT_WITHOUT_ARG("--round-robin", set_rr, &pool_strategy, "Change multipool strategy from failover to round robin on failure"), -#if defined(USE_BITFORCE) || defined(USE_ICARUS) +#ifdef USE_FPGA_SERIAL OPT_WITH_ARG("--scan-serial|-S", add_serial, NULL, NULL, "Serial port to probe for FPGA Mining device"), @@ -927,7 +938,7 @@ static struct opt_table opt_config_table[] = { opt_set_bool, &use_syslog, "Use system log for output messages (default: standard error)"), #endif -#if defined(HAVE_ADL) || defined(USE_BITFORCE) +#if defined(HAVE_ADL) || defined(USE_BITFORCE) || defined(USE_MODMINER) OPT_WITH_ARG("--temp-cutoff", set_temp_cutoff, opt_show_intval, &opt_cutofftemp, "Temperature where a device will be automatically disabled, one value or comma separated list"), @@ -3729,15 +3740,21 @@ bool hashtest(const struct work *work) } -bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) +bool test_nonce(struct work *work, uint32_t nonce) { work->data[64 + 12 + 0] = (nonce >> 0) & 0xff; work->data[64 + 12 + 1] = (nonce >> 8) & 0xff; work->data[64 + 12 + 2] = (nonce >> 16) & 0xff; work->data[64 + 12 + 3] = (nonce >> 24) & 0xff; + return hashtest(work); +} + +bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce) +{ /* Do one last check before attempting to submit the work */ - if (!hashtest(work)) { + /* Side effect: sets work->data for us */ + if (!test_nonce(work, nonce)) { applog(LOG_INFO, "Share below target"); return true; } diff --git a/configure.ac b/configure.ac index 685deac7..0d4baf94 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,7 @@ else fi +AM_CONDITIONAL([NEED_FPGAUTILS], [test x$icarus$bitforce$ztex != xnonono]) 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]) diff --git a/driver-bitforce.c b/driver-bitforce.c index a59338cd..aa22deee 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -13,62 +13,17 @@ #include #include #include -#include -#include -#ifndef WIN32 -#include -#include -#include -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif -#else -#include -#include -#endif #include #include "config.h" -#ifdef HAVE_LIBUDEV -#include -#endif - -#include "elist.h" +#include "fpgautils.h" #include "miner.h" struct device_api bitforce_api; -static int BFopen(const char *devpath) -{ -#ifdef WIN32 - HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (unlikely(hSerial == INVALID_HANDLE_VALUE)) - return -1; - - COMMTIMEOUTS cto = {30000, 0, 30000, 0, 30000}; - SetCommTimeouts(hSerial, &cto); - - return _open_osfhandle((LONG)hSerial, 0); -#else - int fdDev = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY); - if (likely(fdDev != -1)) { - struct termios pattr; - - tcgetattr(fdDev, &pattr); - pattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - pattr.c_oflag &= ~OPOST; - pattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - pattr.c_cflag &= ~(CSIZE | PARENB); - pattr.c_cflag |= CS8; - tcsetattr(fdDev, TCSANOW, &pattr); - } - tcflush(fdDev, TCOFLUSH); - tcflush(fdDev, TCIFLUSH); - return fdDev; -#endif -} +#define BFopen(devpath) serial_open(devpath, 0, -1, true) static void BFgets(char *buf, size_t bufLen, int fd) { @@ -98,9 +53,6 @@ static bool bitforce_detect_one(const char *devpath) char *s; char pdevbuf[0x100]; - if (total_devices == MAX_DEVICES) - return false; - int fdDev = BFopen(devpath); if (unlikely(fdDev == -1)) { applog(LOG_DEBUG, "BitForce Detect: Failed to open %s", devpath); @@ -134,103 +86,17 @@ static bool bitforce_detect_one(const char *devpath) return add_cgpu(bitforce); } -static bool bitforce_detect_auto_udev() +static char bitforce_detect_auto() { -#ifdef HAVE_LIBUDEV - struct udev *udev = udev_new(); - struct udev_enumerate *enumerate = udev_enumerate_new(udev); - struct udev_list_entry *list_entry; - bool foundany = false; - - udev_enumerate_add_match_subsystem(enumerate, "tty"); - udev_enumerate_add_match_property(enumerate, "ID_MODEL", "BitFORCE*SHA256"); - udev_enumerate_scan_devices(enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { - struct udev_device *device = udev_device_new_from_syspath( - udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(list_entry) - ); - if (!device) - continue; - - const char *devpath = udev_device_get_devnode(device); - if (devpath) { - foundany = true; - bitforce_detect_one(devpath); - } - - udev_device_unref(device); - } - udev_enumerate_unref(enumerate); - udev_unref(udev); - - return foundany; -#else - return false; -#endif -} - -static bool bitforce_detect_auto_devserial() -{ -#ifndef WIN32 - DIR *D; - struct dirent *de; - const char udevdir[] = "/dev/serial/by-id"; - char devpath[sizeof(udevdir) + 1 + NAME_MAX]; - char *devfile = devpath + sizeof(udevdir); - bool foundany = false; - - D = opendir(udevdir); - if (!D) - return false; - memcpy(devpath, udevdir, sizeof(udevdir) - 1); - devpath[sizeof(udevdir) - 1] = '/'; - while ( (de = readdir(D)) ) { - if (!strstr(de->d_name, "BitFORCE_SHA256")) - continue; - foundany = true; - strcpy(devfile, de->d_name); - bitforce_detect_one(devpath); - } - closedir(D); - - return foundany; -#else - return false; -#endif -} - -static void bitforce_detect_auto() -{ - bitforce_detect_auto_udev() ?: - bitforce_detect_auto_devserial() ?: + return + serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?: + serial_autodetect_devserial(bitforce_detect_one, "BitFORCE_SHA256") ?: 0; } static void bitforce_detect() { - struct string_elist *iter, *tmp; - const char*s; - bool found = false; - bool autoscan = false; - - list_for_each_entry_safe(iter, tmp, &scan_devices, list) { - s = iter->string; - if (!strncmp("bitforce:", iter->string, 9)) - s += 9; - if (!strcmp(s, "auto")) - autoscan = true; - else - if (!strcmp(s, "noauto")) - found = true; - else if (bitforce_detect_one(s)) { - string_elist_del(iter); - found = true; - } - } - - if (autoscan || !found) - bitforce_detect_auto(); + serial_detect_auto("bitforce", bitforce_detect_one, bitforce_detect_auto); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) diff --git a/driver-icarus.c b/driver-icarus.c index 75ab5e3f..ee9800c4 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -49,6 +49,7 @@ #endif #include "elist.h" +#include "fpgautils.h" #include "miner.h" // The serial I/O speed - Linux uses a define 'B115200' in bits/termios.h @@ -69,10 +70,8 @@ ASSERT1(sizeof(uint32_t) == 4); // Fraction of a second, USB timeout is measured in // i.e. 10 means 1/10 of a second #define TIME_FACTOR 10 -// In Linux it's 10 per second, thus value = 10/TIME_FACTOR = -#define LINUX_TIMEOUT_VALUE 1 -// In Windows it's 1000 per second, thus value = 1000/TIME_FACTOR = -#define WINDOWS_TIMEOUT_VALUE 100 +// It's 10 per second, thus value = 10/TIME_FACTOR = +#define ICARUS_READ_FAULT_DECISECONDS 1 // In timing mode: Default starting value until an estimate can be obtained // 5 seconds allows for up to a ~840MH/s device @@ -196,63 +195,8 @@ static void rev(unsigned char *s, size_t l) } } -static int icarus_open(const char *devpath) -{ -#ifndef WIN32 - struct termios my_termios; - - int serialfd = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY); - - if (serialfd == -1) - return -1; - - tcgetattr(serialfd, &my_termios); - my_termios.c_cflag = B115200; - my_termios.c_cflag |= CS8; - my_termios.c_cflag |= CREAD; - my_termios.c_cflag |= CLOCAL; - my_termios.c_cflag &= ~(CSIZE | PARENB); - - my_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | - ISTRIP | INLCR | IGNCR | ICRNL | IXON); - my_termios.c_oflag &= ~OPOST; - my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - my_termios.c_cc[VTIME] = LINUX_TIMEOUT_VALUE; /* how long to block */ - my_termios.c_cc[VMIN] = 0; - tcsetattr(serialfd, TCSANOW, &my_termios); - - tcflush(serialfd, TCOFLUSH); - tcflush(serialfd, TCIFLUSH); - - return serialfd; -#else - COMMCONFIG comCfg; - - HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, - NULL, OPEN_EXISTING, 0, NULL); - if (unlikely(hSerial == INVALID_HANDLE_VALUE)) - return -1; - - // thanks to af_newbie for pointers about this - memset(&comCfg, 0 , sizeof(comCfg)); - comCfg.dwSize = sizeof(COMMCONFIG); - comCfg.wVersion = 1; - comCfg.dcb.DCBlength = sizeof(DCB); - comCfg.dcb.BaudRate = ICARUS_IO_SPEED; - comCfg.dcb.fBinary = 1; - comCfg.dcb.fDtrControl = DTR_CONTROL_ENABLE; - comCfg.dcb.fRtsControl = RTS_CONTROL_ENABLE; - comCfg.dcb.ByteSize = 8; - - SetCommConfig(hSerial, &comCfg, sizeof(comCfg)); - - // How long to block - COMMTIMEOUTS cto = {WINDOWS_TIMEOUT_VALUE, 0, WINDOWS_TIMEOUT_VALUE, 0, WINDOWS_TIMEOUT_VALUE}; - SetCommTimeouts(hSerial, &cto); - - return _open_osfhandle((LONG)hSerial, 0); -#endif -} +#define icarus_open2(devpath, purge) serial_open(devpath, 115200, ICARUS_READ_FAULT_DECISECONDS, purge) +#define icarus_open(devpath) icarus_open2(devpath, false) static int icarus_gets(unsigned char *buf, int fd, struct timeval *tv_finish, int thr_id, int read_count) { @@ -435,10 +379,7 @@ static bool icarus_detect_one(const char *devpath) unsigned char ob_bin[64], nonce_bin[ICARUS_READ_SIZE]; char *nonce_hex; - if (total_devices == MAX_DEVICES) - return false; - - fd = icarus_open(devpath); + fd = icarus_open2(devpath, true); if (unlikely(fd == -1)) { applog(LOG_ERR, "Icarus Detect: Failed to open %s", devpath); return false; @@ -503,18 +444,7 @@ static bool icarus_detect_one(const char *devpath) static void icarus_detect() { - struct string_elist *iter, *tmp; - const char*s; - - list_for_each_entry_safe(iter, tmp, &scan_devices, list) { - s = iter->string; - if (!strncmp("icarus:", iter->string, 7)) - s += 7; - if (!strcmp(s, "auto") || !strcmp(s, "noauto")) - continue; - if (icarus_detect_one(s)) - string_elist_del(iter); - } + serial_detect("icarus", icarus_detect_one); } static bool icarus_prepare(struct thr_info *thr) diff --git a/fpgautils.c b/fpgautils.c new file mode 100644 index 00000000..39f3abd3 --- /dev/null +++ b/fpgautils.c @@ -0,0 +1,273 @@ +/* + * Copyright 2012 Luke Dashjr + * Copyright 2012 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 + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. See COPYING for more details. + */ + +#include "config.h" + +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#else +#include +#include +#endif + +#ifdef HAVE_LIBUDEV +#include +#endif + +#include "elist.h" +#include "fpgautils.h" +#include "logging.h" +#include "miner.h" + +char +serial_autodetect_udev(detectone_func_t detectone, const char*prodname) +{ +#ifdef HAVE_LIBUDEV + if (total_devices == MAX_DEVICES) + return 0; + + struct udev *udev = udev_new(); + struct udev_enumerate *enumerate = udev_enumerate_new(udev); + struct udev_list_entry *list_entry; + char found = 0; + + udev_enumerate_add_match_subsystem(enumerate, "tty"); + udev_enumerate_add_match_property(enumerate, "ID_MODEL", prodname); + udev_enumerate_scan_devices(enumerate); + udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { + struct udev_device *device = udev_device_new_from_syspath( + udev_enumerate_get_udev(enumerate), + udev_list_entry_get_name(list_entry) + ); + if (!device) + continue; + + const char *devpath = udev_device_get_devnode(device); + if (devpath && detectone(devpath)) + ++found; + + udev_device_unref(device); + + if (total_devices == MAX_DEVICES) + break; + } + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return found; +#else + return 0; +#endif +} + +char +serial_autodetect_devserial(detectone_func_t detectone, const char*prodname) +{ +#ifndef WIN32 + if (total_devices == MAX_DEVICES) + return 0; + + DIR *D; + struct dirent *de; + const char udevdir[] = "/dev/serial/by-id"; + char devpath[sizeof(udevdir) + 1 + NAME_MAX]; + char *devfile = devpath + sizeof(udevdir); + char found = 0; + + D = opendir(udevdir); + if (!D) + return 0; + memcpy(devpath, udevdir, sizeof(udevdir) - 1); + devpath[sizeof(udevdir) - 1] = '/'; + while ( (de = readdir(D)) ) { + if (!strstr(de->d_name, prodname)) + continue; + strcpy(devfile, de->d_name); + if (detectone(devpath)) { + ++found; + if (total_devices == MAX_DEVICES) + break; + } + } + closedir(D); + + return found; +#else + return 0; +#endif +} + +char +_serial_detect(const char*dnamec, size_t dnamel, detectone_func_t detectone, autoscan_func_t autoscan, bool force_autoscan) +{ + if (total_devices == MAX_DEVICES) + return 0; + + struct string_elist *iter, *tmp; + const char*s; + bool inhibitauto = false; + bool forceauto = false; + char found = 0; + + list_for_each_entry_safe(iter, tmp, &scan_devices, list) { + s = iter->string; + if (!strncmp(dnamec, iter->string, dnamel)) + s += dnamel; + if (!strcmp(s, "auto")) + forceauto = true; + else + if (!strcmp(s, "noauto")) + inhibitauto = true; + else + if (detectone(s)) { + string_elist_del(iter); + inhibitauto = true; + ++found; + if (total_devices == MAX_DEVICES) + break; + } + } + + if ((forceauto || !inhibitauto) && autoscan && total_devices < MAX_DEVICES) + found += autoscan(); + + return found; +} + +int +serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge) +{ +#ifdef WIN32 + HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (unlikely(hSerial == INVALID_HANDLE_VALUE)) + return -1; + + // thanks to af_newbie for pointers about this + COMMCONFIG comCfg = {0}; + comCfg.dwSize = sizeof(COMMCONFIG); + comCfg.wVersion = 1; + comCfg.dcb.DCBlength = sizeof(DCB); + comCfg.dcb.BaudRate = baud; + comCfg.dcb.fBinary = 1; + comCfg.dcb.fDtrControl = DTR_CONTROL_ENABLE; + comCfg.dcb.fRtsControl = RTS_CONTROL_ENABLE; + comCfg.dcb.ByteSize = 8; + + SetCommConfig(hSerial, &comCfg, sizeof(comCfg)); + + const DWORD ctoms = (timeout == -1) ? 30000 : (timeout * 100); + COMMTIMEOUTS cto = {ctoms, 0, ctoms, 0, ctoms}; + SetCommTimeouts(hSerial, &cto); + + if (purge) { + PurgeComm(hSerial, PURGE_RXABORT); + PurgeComm(hSerial, PURGE_TXABORT); + PurgeComm(hSerial, PURGE_RXCLEAR); + PurgeComm(hSerial, PURGE_TXCLEAR); + } + + return _open_osfhandle((LONG)hSerial, 0); +#else + int fdDev = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY); + + if (unlikely(fdDev == -1)) + return -1; + + struct termios pattr; + tcgetattr(fdDev, &pattr); + pattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + pattr.c_oflag &= ~OPOST; + pattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + pattr.c_cflag &= ~(CSIZE | PARENB); + pattr.c_cflag |= CS8; + + switch (baud) { + case 0: break; + case 115200: pattr.c_cflag = B115200; break; + default: + applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud); + } + pattr.c_cflag |= CREAD | CLOCAL; + + if (timeout >= 0) { + pattr.c_cc[VTIME] = (cc_t)timeout; + pattr.c_cc[VMIN] = 0; + } + + tcsetattr(fdDev, TCSANOW, &pattr); + if (purge) + tcflush(fdDev, TCIOFLUSH); + return fdDev; +#endif +} + +ssize_t +_serial_read(int fd, char *buf, size_t bufsiz, char *eol) +{ + ssize_t len, tlen = 0; + while (bufsiz) { + len = read(fd, buf, eol ? 1 : bufsiz); + if (len < 1) + break; + tlen += len; + if (eol && *eol == buf[0]) + break; + buf += len; + bufsiz -= len; + } + return tlen; +} + +static FILE* +_open_bitstream(const char*path, const char*subdir, const char*filename) +{ + char fullpath[PATH_MAX]; + strcpy(fullpath, path); + strcat(fullpath, "/"); + if (subdir) { + strcat(fullpath, subdir); + strcat(fullpath, "/"); + } + strcat(fullpath, filename); + return fopen(fullpath, "rb"); +} +#define _open_bitstream(path, subdir) do { \ + f = _open_bitstream(path, subdir, filename); \ + if (f) \ + return f; \ +} while(0) + +#define _open_bitstream3(path) do { \ + _open_bitstream(path, dname); \ + _open_bitstream(path, "bitstreams"); \ + _open_bitstream(path, NULL); \ +} while(0) + +FILE* +open_bitstream(const char*dname, const char*filename) +{ + FILE *f; + + _open_bitstream3(opt_kernel_path); + _open_bitstream3(cgminer_path); + _open_bitstream3("."); + + return NULL; +} diff --git a/fpgautils.h b/fpgautils.h new file mode 100644 index 00000000..7b8b3317 --- /dev/null +++ b/fpgautils.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Luke Dashjr + * + * 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 + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. See COPYING for more details. + */ + +#ifndef FPGAUTILS_H +#define FPGAUTILS_H + +#include +#include + +typedef bool(*detectone_func_t)(const char*); +typedef char(*autoscan_func_t)(); + +extern char _serial_detect(const char*dnamec, size_t dnamel, detectone_func_t, autoscan_func_t, bool force_autoscan); +#define serial_detect_fauto(dname, detectone, autoscan) \ + _serial_detect(dname ":", sizeof(dname)+1, detectone, autoscan, true) +#define serial_detect_auto(dname, detectone, autoscan) \ + _serial_detect(dname ":", sizeof(dname)+1, detectone, autoscan, false) +#define serial_detect(dname, detectone) \ + _serial_detect(dname ":", sizeof(dname)+1, detectone, NULL, false) +extern char serial_autodetect_devserial(detectone_func_t, const char*prodname); +extern char serial_autodetect_udev (detectone_func_t, const char*prodname); + +extern int serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge); +extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char*eol); +#define serial_read(fd, buf, count) \ + _serial_read(fd, (char*)(buf), count, NULL) +#define serial_read_line(fd, buf, bufsiz, eol) \ + _serial_read(fd, buf, count, &eol) +#define serial_close(fd) close(fd) + +extern FILE*open_bitstream(const char*dname, const char*filename); + +#endif diff --git a/libztex.c b/libztex.c index ffc2e67d..636c12c4 100644 --- a/libztex.c +++ b/libztex.c @@ -22,6 +22,8 @@ #include #include + +#include "fpgautils.h" #include "miner.h" #include "libztex.h" @@ -150,7 +152,7 @@ static int libztex_configureFpgaHS(struct libztex_device *ztex, const char* firm libusb_claim_interface(ztex->hndl, settings[1]); for (tries = 3; tries > 0; tries--) { - fp = fopen(firmware, "rb"); + fp = open_bitstream("ztex", firmware); if (!fp) { applog(LOG_ERR, "%s: failed to read firmware '%s'", ztex->repr, firmware); return -2; @@ -245,7 +247,7 @@ static int libztex_configureFpgaLS(struct libztex_device *ztex, const char* firm } for (tries = 10; tries > 0; tries--) { - fp = fopen(firmware, "rb"); + fp = open_bitstream("ztex", firmware); if (!fp) { applog(LOG_ERR, "%s: failed to read firmware '%s'", ztex->repr, firmware); return -2; @@ -316,12 +318,11 @@ static int libztex_configureFpgaLS(struct libztex_device *ztex, const char* firm int libztex_configureFpga(struct libztex_device *ztex) { - char buf[256] = "bitstreams/"; + char buf[256]; int rv; - memset(&buf[11], 0, 245); - strcpy(&buf[11], ztex->bitFileName); - strcpy(&buf[strlen(buf)], ".bit"); + strcpy(buf, ztex->bitFileName); + strcat(buf, ".bit"); rv = libztex_configureFpgaHS(ztex, buf, true, 2); if (rv != 0) rv = libztex_configureFpgaLS(ztex, buf, true, 2); diff --git a/miner.h b/miner.h index f358e2bb..e06cb76c 100644 --- a/miner.h +++ b/miner.h @@ -743,6 +743,7 @@ struct work { }; extern void get_datestamp(char *, struct timeval *); +extern bool test_nonce(struct work *work, uint32_t nonce); bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlogprint(const char *f, ...);