Browse Source

Merge pull request #336 from kanoi/usb2

mmq usb v0.4 + api usb stats
nfactor-troky
Con Kolivas 12 years ago
parent
commit
28f251e49e
  1. 15
      API-README
  2. 62
      FPGA-README
  3. 4
      Makefile.am
  4. 75
      api.c
  5. 21
      cgminer.c
  6. 6
      configure.ac
  7. 1012
      driver-modminer.c
  8. 30
      miner.h
  9. 1192
      usbutils.c
  10. 120
      usbutils.h

15
API-README

@ -330,6 +330,9 @@ The list of requests - a (*) means it requires privileged access - and replies a @@ -330,6 +330,9 @@ The list of requests - a (*) means it requires privileged access - and replies a
queue, scantime, expiry
N is an integer in the range 0 to 9999
substats USBSTATS Stats of all LIBUSB mining devices except ztex
e.g. Name=MMQ,ID=0,Stat=SendWork,Count=99,...|
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
in the cgminer status window
@ -383,7 +386,17 @@ miner.php - an example web page to access the API @@ -383,7 +386,17 @@ miner.php - an example web page to access the API
Feature Changelog for external applications using the API:
API V1.20
API V1.21
Added API commands:
'usbstats'
Modified API commands:
each MMQ shows up as 4 devices each with it's own stats
----------
API V1.20 (cgminer v2.8.5)
Modified API commands:
'pools' - add 'Has Stratum', 'Stratum Active', 'Stratum URL'

62
FPGA-README

@ -6,7 +6,65 @@ ModMinerQuad (MMQ) @@ -6,7 +6,65 @@ ModMinerQuad (MMQ)
------------------
The mining bitstream does not survive a power cycle, so cgminer will upload
it, if it needs to, before it starts mining
it, if it needs to, before it starts mining (approx 7min 40sec)
The red LED also flashes while it is uploading the bitstream
-
When mining on windows, the driver being used will determine if mining will work.
If the driver doesn't allow mining, you will get a "USB init," error message
i.e. one of:
open device failed, err %d, you need to install a Windows USB driver for the device
or
kernel detach failed :(
or
claim interface %d failed, err %d
The best solution for this is to use a tool called Zadig to set the driver:
http://sourceforge.net/projects/libwdi/files/zadig/
This allows you set the driver for the device to be WinUSB which is usually
required to make it work if your having problems
You must also make sure you are using the latest libusb-1.0.dll supplied
with cgminer (not the libusbx version)
-
There is a hidden option in cgminer to dump out a lot of information
about USB that will help the developers to assist you if you are having
problems:
--usb-dump 0
It will only help if you have a working MMQ device attached to the computer
-
If the MMQ doesn't respond to cgminer at all, or the red LED isn't flashing
then you will need to reset the MMQ
The red LED should always be flashing when it is mining or ready to mine
To reset the MMQ, you are best to press the left "RESET" button on the
backplane, then unplug and replug the USB cable
If your MMQ doesn't have a button on the "RESET" pad, you need to join
the two left pads of the "RESET" pad with conductive wire to reset it.
Cutting a small (metal) paper-clip in half works well for this
Then unplug the USB cable, wait for 5 seconds, then plug it back in
After you press reset, the red LED near the USB port should blink continuously
If it still wont work, power off, wait for 5 seconds, then power on the MMQ
This of course means it will upload the bitstream again when you start cgminer
-
Device 0 is on the power end of the board
-
@ -64,7 +122,7 @@ a (hack) solution to this is to blacklist the MMQ USB device in @@ -64,7 +122,7 @@ a (hack) solution to this is to blacklist the MMQ USB device in
Adding 2 lines like this (just above APC) should help
# MMQ
ATTRS{idVendor}=="ifc9", ATTRS{idProduct}=="0003", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="0003", ENV{ID_MM_DEVICE_IGNORE}="1"
The change will be lost and need to be re-done, next time you update the
modem-manager software

4
Makefile.am

@ -38,7 +38,7 @@ cgminer_SOURCES := cgminer.c @@ -38,7 +38,7 @@ cgminer_SOURCES := cgminer.c
cgminer_SOURCES += elist.h miner.h compat.h bench_block.h \
util.c util.h uthash.h logging.h \
sha2.c sha2.h api.c
sha2.c sha2.h api.c usbutils.h
cgminer_SOURCES += logging.c
@ -91,7 +91,7 @@ cgminer_SOURCES += driver-icarus.c @@ -91,7 +91,7 @@ cgminer_SOURCES += driver-icarus.c
endif
if HAS_MODMINER
cgminer_SOURCES += driver-modminer.c
cgminer_SOURCES += driver-modminer.c usbutils.c
bitstreamsdir = $(bindir)/bitstreams
dist_bitstreams_DATA = bitstreams/*
endif

75
api.c

@ -131,7 +131,7 @@ static const char SEPARATOR = '|'; @@ -131,7 +131,7 @@ static const char SEPARATOR = '|';
#define SEPSTR "|"
static const char GPUSEP = ',';
static const char *APIVERSION = "1.20";
static const char *APIVERSION = "1.21";
static const char *DEAD = "Dead";
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
static const char *SICK = "Sick";
@ -227,6 +227,7 @@ static const char *OSINFO = @@ -227,6 +227,7 @@ static const char *OSINFO =
#define _MINECOIN "COIN"
#define _DEBUGSET "DEBUG"
#define _SETCONFIG "SETCONFIG"
#define _USBSTATS "USBSTATS"
static const char ISJSON = '{';
#define JSON0 "{"
@ -266,6 +267,7 @@ static const char ISJSON = '{'; @@ -266,6 +267,7 @@ static const char ISJSON = '{';
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
#define JSON_USBSTATS JSON1 _USBSTATS JSON2
#define JSON_END JSON4 JSON5
static const char *JSON_COMMAND = "command";
@ -369,6 +371,8 @@ static const char *JSON_PARAMETER = "parameter"; @@ -369,6 +371,8 @@ static const char *JSON_PARAMETER = "parameter";
#define MSG_INVNUM 84
#define MSG_CONPAR 85
#define MSG_CONVAL 86
#define MSG_USBSTA 87
#define MSG_NOUSTA 88
enum code_severity {
SEVERITY_ERR,
@ -533,6 +537,8 @@ struct CODES { @@ -533,6 +537,8 @@ struct CODES {
{ SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" },
{ SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" },
{ SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" },
{ SEVERITY_SUCC, MSG_USBSTA, PARAM_NONE, "USB Statistics" },
{ SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" },
{ SEVERITY_FAIL, 0, 0, NULL }
};
@ -1383,27 +1389,8 @@ static void pgastatus(int pga, bool isjson) @@ -1383,27 +1389,8 @@ static void pgastatus(int pga, bool isjson)
frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1);
#endif
#ifdef USE_MODMINER
// TODO: a modminer has up to 4 devices but only 1 set of data for all ...
// except 4 sets of data for temp/clock
// So this should change in the future to just find the single temp/clock
// if the modminer code splits the device into seperate devices later
// For now, just display the highest temp and the average clock
if (cgpu->api == &modminer_api) {
int tc = cgpu->threads;
int i;
temp = 0;
if (tc > 4)
tc = 4;
for (i = 0; i < tc; i++) {
struct thr_info *thr = cgpu->thr[i];
struct modminer_fpga_state *state = thr->cgpu_data;
if (state->temp > temp)
temp = state->temp;
frequency += state->clock;
}
frequency /= (tc ? tc : 1);
}
if (cgpu->api == &modminer_api)
frequency = cgpu->clock;
#endif
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
@ -2990,6 +2977,49 @@ static void setconfig(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __m @@ -2990,6 +2977,49 @@ static void setconfig(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __m
strcpy(io_buffer, message(MSG_SETCONFIG, value, param, isjson));
}
static void usbstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{
struct api_data *root = NULL;
#ifdef USE_MODMINER
char buf[TMPBUFSIZ];
int count = 0;
root = api_usb_stats(&count);
#endif
if (!root) {
strcpy(io_buffer, message(MSG_NOUSTA, 0, NULL, isjson));
return;
}
#ifdef USE_MODMINER
strcpy(io_buffer, message(MSG_USBSTA, 0, NULL, isjson));
if (isjson) {
strcat(io_buffer, COMMA);
strcat(io_buffer, JSON_USBSTATS);
}
root = print_data(root, buf, isjson);
strcat(io_buffer, buf);
while (42) {
root = api_usb_stats(&count);
if (!root)
break;
strcat(io_buffer, COMMA);
root = print_data(root, buf, isjson);
strcat(io_buffer, buf);
}
if (isjson)
strcat(io_buffer, JSON_CLOSE);
#endif
}
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
struct CMDS {
@ -3045,6 +3075,7 @@ struct CMDS { @@ -3045,6 +3075,7 @@ struct CMDS {
{ "coin", minecoin, false },
{ "debug", debugstate, true },
{ "setconfig", setconfig, true },
{ "usbstats", usbstats, false },
{ NULL, NULL, false }
};

21
cgminer.c

@ -146,6 +146,9 @@ bool opt_disable_pool = true; @@ -146,6 +146,9 @@ bool opt_disable_pool = true;
char *opt_icarus_options = NULL;
char *opt_icarus_timing = NULL;
bool opt_worktime;
#ifdef HAVE_LIBUSB
int opt_usbdump = -1;
#endif
char *opt_kernel_path;
char *cgminer_path;
@ -167,6 +170,10 @@ int gpur_thr_id; @@ -167,6 +170,10 @@ int gpur_thr_id;
static int api_thr_id;
static int total_threads;
#ifdef HAVE_LIBUSB
pthread_mutex_t cgusb_lock;
#endif
static pthread_mutex_t hash_lock;
static pthread_mutex_t qd_lock;
static pthread_mutex_t *stgd_lock;
@ -1099,6 +1106,11 @@ static struct opt_table opt_config_table[] = { @@ -1099,6 +1106,11 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_ARG("--user|-u",
set_user, NULL, NULL,
"Username for bitcoin JSON-RPC server"),
#ifdef HAVE_LIBUSB
OPT_WITH_ARG("--usb-dump",
set_int_0_to_10, opt_show_intval, &opt_usbdump,
opt_hidden),
#endif
#ifdef HAVE_OPENCL
OPT_WITH_ARG("--vectors|-v",
set_vector, NULL, NULL,
@ -6583,8 +6595,15 @@ int main(int argc, char *argv[]) @@ -6583,8 +6595,15 @@ int main(int argc, char *argv[])
for (i = 0; i < argc; i++)
initial_args[i] = strdup(argv[i]);
initial_args[argc] = NULL;
#ifdef HAVE_LIBUSB
libusb_init(NULL);
int err = libusb_init(NULL);
if (err) {
fprintf(stderr, "libusb_init() failed err %d", err);
fflush(stderr);
quit(1, "libusb_init() failed");
}
mutex_init(&cgusb_lock);
#endif
mutex_init(&hash_lock);

6
configure.ac

@ -321,7 +321,7 @@ fi @@ -321,7 +321,7 @@ fi
AM_CONDITIONAL([HAS_YASM], [test x$has_yasm = xtrue])
if test "x$bitforce$modminer" != xnono; then
if test "x$bitforce" != xno; then
AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])],
[libudev=$withval],
[libudev=auto]
@ -343,7 +343,7 @@ AM_CONDITIONAL([HAVE_LIBUDEV], [test x$libudev != xno]) @@ -343,7 +343,7 @@ AM_CONDITIONAL([HAVE_LIBUDEV], [test x$libudev != xno])
PKG_PROG_PKG_CONFIG()
if test "x$ztex" != xno; then
if test "x$ztex$modminer" != xnono; then
case $target in
*-*-freebsd*)
LIBUSB_LIBS="-lusb"
@ -502,7 +502,7 @@ else @@ -502,7 +502,7 @@ else
echo " Ztex.FPGAs...........: Disabled"
fi
if test "x$bitforce$modminer" != xnono; then
if test "x$bitforce" != xno; then
echo " libudev.detection....: $libudev"
fi

1012
driver-modminer.c

File diff suppressed because it is too large Load Diff

30
miner.h

@ -110,6 +110,10 @@ static inline int fsync (int fd) @@ -110,6 +110,10 @@ static inline int fsync (int fd)
#include "libztex.h"
#endif
#ifdef USE_MODMINER
#include "usbutils.h"
#endif
#if !defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define bswap_16 __builtin_bswap16
#define bswap_32 __builtin_bswap32
@ -360,9 +364,20 @@ struct cgpu_info { @@ -360,9 +364,20 @@ struct cgpu_info {
union {
#ifdef USE_ZTEX
struct libztex_device *device_ztex;
#endif
#ifdef USE_MODMINER
struct cg_usb_device *usbdev;
#endif
int device_fd;
};
#ifdef USE_MODMINER
int usbstat;
char fpgaid;
unsigned char clock;
pthread_mutex_t *modminer_mutex;
bool tried_two_byte_temp;
bool one_byte_temp;
#endif
#ifdef USE_BITFORCE
struct timeval work_start_tv;
unsigned int wait_ms;
@ -373,9 +388,8 @@ struct cgpu_info { @@ -373,9 +388,8 @@ struct cgpu_info {
bool nonce_range;
bool polling;
bool flash_led;
#endif
pthread_mutex_t device_mutex;
#endif
enum dev_enable deven;
int accepted;
int rejected;
@ -654,6 +668,9 @@ extern bool opt_restart; @@ -654,6 +668,9 @@ extern bool opt_restart;
extern char *opt_icarus_options;
extern char *opt_icarus_timing;
extern bool opt_worktime;
#ifdef HAVE_LIBUSB
extern int opt_usbdump;
#endif
#ifdef USE_BITFORCE
extern bool opt_bfl_noncerange;
#endif
@ -684,6 +701,10 @@ extern int opt_queue; @@ -684,6 +701,10 @@ extern int opt_queue;
extern int opt_scantime;
extern int opt_expiry;
#ifdef HAVE_LIBUSB
extern pthread_mutex_t cgusb_lock;
#endif
extern pthread_mutex_t console_lock;
extern pthread_mutex_t ch_lock;
@ -998,9 +1019,10 @@ struct modminer_fpga_state { @@ -998,9 +1019,10 @@ struct modminer_fpga_state {
uint32_t hashes;
char next_work_cmd[46];
char fpgaid;
unsigned char clock;
float temp;
bool overheated;
bool new_work;
uint32_t shares;
uint32_t shares_last_hw;

1192
usbutils.c

File diff suppressed because it is too large Load Diff

120
usbutils.h

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
/*
* 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.
*/
#ifndef USBUTILS_H
#define USBUTILS_H
#include <libusb.h>
// Use the device defined timeout
#define DEVTIMEOUT 0
// For endpoints defined in usb_find_devices.eps,
// the first two must be the default IN and OUT
#define DEFAULT_EP_IN 0
#define DEFAULT_EP_OUT 1
struct usb_endpoints {
uint8_t att;
uint16_t size;
unsigned char ep;
bool found;
};
struct usb_find_devices {
int drv;
const char *name;
uint16_t idVendor;
uint16_t idProduct;
int config;
int interface;
unsigned int timeout;
int epcount;
struct usb_endpoints *eps;
};
struct cg_usb_device {
struct usb_find_devices *found;
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;
char *manuf_string;
char *serial_string;
unsigned char fwVersion; // ??
unsigned char interfaceVersion; // ??
};
enum usb_cmds {
C_PING = 0,
C_CLEAR,
C_REQUESTVERSION,
C_GETVERSION,
C_REQUESTFPGACOUNT,
C_GETFPGACOUNT,
C_STARTPROGRAM,
C_STARTPROGRAMSTATUS,
C_PROGRAM,
C_PROGRAMSTATUS,
C_PROGRAMSTATUS2,
C_FINALPROGRAMSTATUS,
C_SETCLOCK,
C_REPLYSETCLOCK,
C_REQUESTUSERCODE,
C_GETUSERCODE,
C_REQUESTTEMPERATURE,
C_GETTEMPERATURE,
C_SENDWORK,
C_SENDWORKSTATUS,
C_REQUESTWORKSTATUS,
C_GETWORKSTATUS,
C_MAX
};
struct device_api;
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 *));
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_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds);
void usb_cleanup();
#define usb_read(cgpu, buf, bufsiz, read, cmd) \
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd)
#define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \
_usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd)
#define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd)
#define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \
_usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd)
#define usb_write(cgpu, buf, bufsiz, wrote, cmd) \
_usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd)
#define usb_write_ep(cgpu, ep, buf, bufsiz, wrote, cmd) \
_usb_write(cgpu, ep, buf, bufsiz, wrote, DEVTIMEOUT, cmd)
#define usb_write_timeout(cgpu, buf, bufsiz, wrote, timeout, cmd) \
_usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, timeout, cmd)
#define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \
_usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd)
#endif
Loading…
Cancel
Save