Browse Source

Add API support for Icarus and Bitforce

nfactor-troky
Kano 12 years ago
parent
commit
cb3323b7b5
  1. 22
      README
  2. 290
      api.c

22
README

@ -594,7 +594,7 @@ An example request in both formats to set GPU 0 fan to 80%: @@ -594,7 +594,7 @@ An example request in both formats to set GPU 0 fan to 80%:
The format of each reply (unless stated otherwise) is a STATUS section
followed by an optional detail section
For API version 1.4:
For API version 1.4 and later:
The STATUS section is:
@ -620,7 +620,7 @@ The STATUS section is: @@ -620,7 +620,7 @@ The STATUS section is:
This defaults to the cgminer version but is the value of --api-description
if it was specified at runtime.
For API version 1.4:
For API version 1.5:
The list of requests - a (*) means it requires privileged access - and replies are:
@ -631,6 +631,7 @@ The list of requests - a (*) means it requires privileged access - and replies a @@ -631,6 +631,7 @@ The list of requests - a (*) means it requires privileged access - and replies a
config CONFIG Some miner configuration information:
GPU Count=N, <- the number of GPUs
PGA Count=N, <- the number of PGAs
CPU Count=N, <- the number of CPUs
Pool Count=N, <- the number of Pools
ADL=X, <- Y or N if ADL is compiled in the code
@ -644,16 +645,22 @@ The list of requests - a (*) means it requires privileged access - and replies a @@ -644,16 +645,22 @@ The list of requests - a (*) means it requires privileged access - and replies a
pools POOLS The status of each pool
e.g. Pool=0,URL=http://pool.com:6311,Status=Alive,...|
devs DEVS Each available CPU and GPU with their details
devs DEVS Each available GPU, PGA and CPU with their details
e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in seconds
(or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Will not report PGAs if PGA mining is disabled
Will not report CPUs if CPU mining is disabled
gpu|N GPU The details of a single GPU number N in the same
format and details as for DEVS
pga|N PGA The details of a single PGA number N in the same
format and details as for DEVS
This is only available if PGA mining is enabled
Use 'pgacount' or 'config' first to see if there are any
cpu|N CPU The details of a single CPU number N in the same
format and details as for DEVS
This is only available if CPU mining is enabled
@ -661,6 +668,9 @@ The list of requests - a (*) means it requires privileged access - and replies a @@ -661,6 +668,9 @@ The list of requests - a (*) means it requires privileged access - and replies a
gpucount GPUS Count=N| <- the number of GPUs
pgacount PGAS Count=N| <- the number of PGAs
Always returns 0 if PGA mining is disabled
cpucount CPUS Count=N| <- the number of CPUs
Always returns 0 if CPU mining is disabled
@ -921,6 +931,12 @@ it fail when php is installed properly but I only get errors about Sockets not @@ -921,6 +931,12 @@ it fail when php is installed properly but I only get errors about Sockets not
working in the logs?
A: http://us.php.net/manual/en/sockets.installation.php
Q: What is a PGA?
A: At the moment, cgminer supports 2 FPGA's: Icarus and BitForce.
They are Field-Programmable Gate Arrays that have been programmed to do Bitcoin
mining. Since the acronym needs to be only 3 characters, the "Field-" part has
been skipped.
---
This code is provided entirely free of charge by the programmer in his spare

290
api.c

@ -6,6 +6,10 @@ @@ -6,6 +6,10 @@
* 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.
*
* Note: the code always includes GPU support even if there are no GPUs
* this simplifies handling multiple other device code being included
* depending on compile options
*/
#include "config.h"
@ -134,12 +138,13 @@ @@ -134,12 +138,13 @@
#endif
// Big enough for largest API request
// though a PC with 100s of CPUs may exceed the size ...
// though a PC with 100s of PGAs/CPUs may exceed the size ...
// Current code assumes it can socket send this size also
#define MYBUFSIZ 32768
#define MYBUFSIZ 32768 // TODO: intercept before it's exceeded
// Number of requests to queue - normally would be small
#define QUEUE 10
// However lots of PGA's may mean more
#define QUEUE 100
static char *io_buffer = NULL;
static char *msg_buffer = NULL;
@ -152,7 +157,7 @@ static const char *COMMA = ","; @@ -152,7 +157,7 @@ static const char *COMMA = ",";
static const char SEPARATOR = '|';
static const char GPUSEP = ',';
static const char *APIVERSION = "1.4";
static const char *APIVERSION = "1.5";
static const char *DEAD = "Dead";
static const char *SICK = "Sick";
static const char *NOSTART = "NoStart";
@ -170,14 +175,19 @@ static const char *NO = "N"; @@ -170,14 +175,19 @@ static const char *NO = "N";
#define _STATUS "STATUS"
#define _VERSION "VERSION"
#define _MINECON "CONFIG"
#define _GPU "GPU"
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
#define _PGA "PGA"
#endif
#ifdef WANT_CPUMINE
#define _CPU "CPU"
#endif
#define _GPU "GPU"
#define _CPUS "CPUS"
#define _GPUS "GPUS"
#define _PGAS "PGAS"
#define _CPUS "CPUS"
#define _BYE "BYE"
static const char ISJSON = '{';
@ -196,11 +206,16 @@ static const char ISJSON = '{'; @@ -196,11 +206,16 @@ static const char ISJSON = '{';
#define JSON_MINECON JSON1 _MINECON JSON2
#define JSON_GPU JSON1 _GPU JSON2
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
#define JSON_PGA JSON1 _PGA JSON2
#endif
#ifdef WANT_CPUMINE
#define JSON_CPU JSON1 _CPU JSON2
#endif
#define JSON_GPUS JSON1 _GPUS JSON2
#define JSON_PGAS JSON1 _PGAS JSON2
#define JSON_CPUS JSON1 _CPUS JSON2
#define JSON_BYE JSON1 _BYE JSON1
#define JSON_CLOSE JSON3
@ -269,6 +284,14 @@ static const char *JSON_PARAMETER = "parameter"; @@ -269,6 +284,14 @@ static const char *JSON_PARAMETER = "parameter";
#define MSG_TOOMANYP 54
#define MSG_ADDPOOL 55
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
#define MSG_PGANON 56
#define MSG_PGADEV 57
#define MSG_INVPGA 58
#endif
#define MSG_NUMPGA 59
enum code_severity {
SEVERITY_ERR,
SEVERITY_WARN,
@ -279,16 +302,17 @@ enum code_severity { @@ -279,16 +302,17 @@ enum code_severity {
enum code_parameters {
PARAM_GPU,
PARAM_PGA,
PARAM_CPU,
PARAM_GPUMAX,
PARAM_PGAMAX,
PARAM_CPUMAX,
PARAM_PMAX,
PARAM_POOLMAX,
#ifdef WANT_CPUMINE
PARAM_GCMAX,
#else
PARAM_GMAX,
#endif
// Single generic case: have the code resolve it - see below
PARAM_DMAX,
PARAM_CMD,
PARAM_POOL,
PARAM_STR,
@ -310,25 +334,43 @@ struct CODES { @@ -310,25 +334,43 @@ struct CODES {
{ SEVERITY_ERR, MSG_GPUNON, PARAM_NONE, "No GPUs" },
{ SEVERITY_SUCC, MSG_POOL, PARAM_PMAX, "%d Pool(s)" },
{ SEVERITY_ERR, MSG_NOPOOL, PARAM_NONE, "No pools" },
{ SEVERITY_SUCC, MSG_DEVS, PARAM_DMAX, "%d GPU(s)"
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
" - %d PGA(s)"
#endif
#ifdef WANT_CPUMINE
{ SEVERITY_SUCC, MSG_DEVS, PARAM_GCMAX, "%d GPU(s) - %d CPU(s)" },
{ SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs/CPUs" },
#else
{ SEVERITY_SUCC, MSG_DEVS, PARAM_GMAX, "%d GPU(s)" },
{ SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs" },
" - %d CPU(s)"
#endif
},
{ SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs"
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
"/PGAs"
#endif
#ifdef WANT_CPUMINE
"/CPUs"
#endif
},
{ SEVERITY_SUCC, MSG_SUMM, PARAM_NONE, "Summary" },
{ SEVERITY_INFO, MSG_GPUDIS, PARAM_GPU, "GPU %d set disable flag" },
{ SEVERITY_INFO, MSG_GPUREI, PARAM_GPU, "GPU %d restart attempted" },
{ SEVERITY_ERR, MSG_INVCMD, PARAM_NONE, "Invalid command" },
{ SEVERITY_ERR, MSG_MISID, PARAM_NONE, "Missing device id parameter" },
{ SEVERITY_SUCC, MSG_GPUDEV, PARAM_GPU, "GPU%d" },
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
{ SEVERITY_ERR, MSG_PGANON, PARAM_NONE, "No PGAs" },
{ SEVERITY_SUCC, MSG_PGADEV, PARAM_PGA, "PGA%d" },
{ SEVERITY_ERR, MSG_INVPGA, PARAM_PGAMAX, "Invalid PGA id %d - range is 0 - %d" },
#endif
#ifdef WANT_CPUMINE
{ SEVERITY_ERR, MSG_CPUNON, PARAM_NONE, "No CPUs" },
{ SEVERITY_SUCC, MSG_CPUDEV, PARAM_CPU, "CPU%d" },
{ SEVERITY_ERR, MSG_INVCPU, PARAM_CPUMAX, "Invalid CPU id %d - range is 0 - %d" },
#endif
{ SEVERITY_SUCC, MSG_NUMGPU, PARAM_NONE, "GPU count" },
{ SEVERITY_SUCC, MSG_NUMPGA, PARAM_NONE, "PGA count" },
{ SEVERITY_SUCC, MSG_NUMCPU, PARAM_NONE, "CPU count" },
{ SEVERITY_SUCC, MSG_VERSION, PARAM_NONE, "CGMiner versions" },
{ SEVERITY_ERR, MSG_INVJSON, PARAM_NONE, "Invalid JSON" },
@ -382,6 +424,54 @@ struct IP4ACCESS { @@ -382,6 +424,54 @@ struct IP4ACCESS {
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
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
static int numpgas()
{
int count = 0;
int i;
for (i = 0; i < total_devices; i++) {
#ifdef USE_BITFORCE
if (devices[i]->api == &bitforce_api)
count++;
#endif
#ifdef USE_ICARUS
if (devices[i]->api == &icarus_api)
count++;
#endif
}
return count;
}
static int pgadevice(int pgaid)
{
int count = 0;
int i;
for (i = 0; i < total_devices; i++) {
#ifdef USE_BITFORCE
if (devices[i]->api == &bitforce_api)
count++;
#endif
#ifdef USE_ICARUS
if (devices[i]->api == &icarus_api)
count++;
#endif
if (count == (pgaid + 1))
return i;
}
return -1;
}
#endif
// All replies (except BYE) start with a message
// thus for JSON, message() inserts JSON_START at the front
// and send_result() adds JSON_END at the end
@ -389,6 +479,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) @@ -389,6 +479,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
{
char severity;
char *ptr;
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
int pga;
#endif
#ifdef WANT_CPUMINE
int cpu;
#endif
@ -421,6 +514,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) @@ -421,6 +514,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
switch(codes[i].params) {
case PARAM_GPU:
case PARAM_PGA:
case PARAM_CPU:
sprintf(ptr, codes[i].description, paramid);
break;
@ -436,20 +530,26 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) @@ -436,20 +530,26 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
case PARAM_POOLMAX:
sprintf(ptr, codes[i].description, paramid, total_pools - 1);
break;
case PARAM_DMAX:
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
pga = numpgas();
#endif
#ifdef WANT_CPUMINE
case PARAM_GCMAX:
if (opt_n_threads > 0)
cpu = num_processors;
else
cpu = 0;
#endif
sprintf(ptr, codes[i].description, nDevs, cpu);
break;
#else
case PARAM_GMAX:
sprintf(ptr, codes[i].description, nDevs);
break;
sprintf(ptr, codes[i].description, nDevs
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
, pga
#endif
#ifdef WANT_CPUMINE
, cpu
#endif
);
break;
case PARAM_CMD:
sprintf(ptr, codes[i].description, JSON_COMMAND);
break;
@ -500,6 +600,7 @@ static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, @@ -500,6 +600,7 @@ static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
{
char buf[BUFSIZ];
int pgacount = 0;
int cpucount = 0;
char *adlinuse = (char *)NO;
#ifdef HAVE_ADL
@ -516,6 +617,10 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, @@ -516,6 +617,10 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
const char *adl = NO;
#endif
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
pgacount = numpgas();
#endif
#ifdef WANT_CPUMINE
cpucount = opt_n_threads > 0 ? num_processors : 0;
#endif
@ -523,9 +628,9 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, @@ -523,9 +628,9 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
strcpy(io_buffer, message(MSG_MINECON, 0, NULL, isjson));
if (isjson)
sprintf(buf, "," JSON_MINECON "{\"GPU Count\":%d,\"CPU Count\":%d,\"Pool Count\":%d,\"ADL\":\"%s\",\"ADL in use\":\"%s\",\"Strategy\":\"%s\",\"Log Interval\":\"%d\"}" JSON_CLOSE, nDevs, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval);
sprintf(buf, "," JSON_MINECON "{\"GPU Count\":%d,\"PGA Count\":%d,\"CPU Count\":%d,\"Pool Count\":%d,\"ADL\":\"%s\",\"ADL in use\":\"%s\",\"Strategy\":\"%s\",\"Log Interval\":\"%d\"}" JSON_CLOSE, nDevs, pgacount, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval);
else
sprintf(buf, _MINECON ",GPU Count=%d,CPU Count=%d,Pool Count=%d,ADL=%s,ADL in use=%s,Strategy=%s,Log Interval=%d%c", nDevs, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval, SEPARATOR);
sprintf(buf, _MINECON ",GPU Count=%d,PGA Count=%d,CPU Count=%d,Pool Count=%d,ADL=%s,ADL in use=%s,Strategy=%s,Log Interval=%d%c", nDevs, pgacount, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval, SEPARATOR);
strcat(io_buffer, buf);
}
@ -589,6 +694,59 @@ static void gpustatus(int gpu, bool isjson) @@ -589,6 +694,59 @@ static void gpustatus(int gpu, bool isjson)
}
}
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
static void pgastatus(int pga, bool isjson)
{
char buf[BUFSIZ];
char *enabled;
char *status;
int numpga = numpgas();
if (numpga > 0 && pga >= 0 && pga < numpga) {
int dev = pgadevice(pga);
if (dev < 0) // Should never happen
return;
struct cgpu_info *cgpu = devices[dev];
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
if (cgpu->deven != DEV_DISABLED)
enabled = (char *)YES;
else
enabled = (char *)NO;
if (cgpu->status == LIFE_DEAD)
status = (char *)DEAD;
else if (cgpu->status == LIFE_SICK)
status = (char *)SICK;
else if (cgpu->status == LIFE_NOSTART)
status = (char *)NOSTART;
else
status = (char *)ALIVE;
if (isjson)
sprintf(buf, "{\"PGA\":%d,\"Name\":\"%s\",\"ID\":%d,\"Enabled\":\"%s\",\"Status\":\"%s\",\"Temperature\":%.2f,\"MHS av\":%.2f,\"MHS %ds\":%.2f,\"Accepted\":%d,\"Rejected\":%d,\"Hardware Errors\":%d,\"Utility\":%.2f,\"Last Share Pool\":%d,\"Last Share Time\":%lu,\"Total MH\":%.4f}",
pga, cgpu->api->name, cgpu->device_id,
enabled, status, cgpu->temp,
cgpu->total_mhashes / total_secs, opt_log_interval, cgpu->rolling,
cgpu->accepted, cgpu->rejected, cgpu->hw_errors, cgpu->utility,
((unsigned long)(cgpu->last_share_pool_time) > 0) ? cgpu->last_share_pool : -1,
(unsigned long)(cgpu->last_share_pool_time), cgpu->total_mhashes);
else
sprintf(buf, "PGA=%d,Name=%s,ID=%d,Enabled=%s,Status=%s,Temperature=%.2f,MHS av=%.2f,MHS %ds=%.2f,Accepted=%d,Rejected=%d,Hardware Errors=%d,Utility=%.2f,Last Share Pool=%d,Last Share Time=%lu,Total MH=%.4f%c",
pga, cgpu->api->name, cgpu->device_id,
enabled, status, cgpu->temp,
cgpu->total_mhashes / total_secs, opt_log_interval, cgpu->rolling,
cgpu->accepted, cgpu->rejected, cgpu->hw_errors, cgpu->utility,
((unsigned long)(cgpu->last_share_pool_time) > 0) ? cgpu->last_share_pool : -1,
(unsigned long)(cgpu->last_share_pool_time), cgpu->total_mhashes, SEPARATOR);
strcat(io_buffer, buf);
}
}
#endif
#ifdef WANT_CPUMINE
static void cpustatus(int cpu, bool isjson)
{
@ -623,6 +781,7 @@ static void cpustatus(int cpu, bool isjson) @@ -623,6 +781,7 @@ static void cpustatus(int cpu, bool isjson)
static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
{
int devcount = 0;
int i;
if (nDevs == 0 && opt_n_threads == 0) {
@ -638,19 +797,37 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b @@ -638,19 +797,37 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
}
for (i = 0; i < nDevs; i++) {
if (isjson && i > 0)
if (isjson && devcount > 0)
strcat(io_buffer, COMMA);
gpustatus(i, isjson);
devcount++;
}
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
int numpga = numpgas();
if (numpga > 0)
for (i = 0; i < numpga; i++) {
if (isjson && devcount > 0)
strcat(io_buffer, COMMA);
pgastatus(i, isjson);
devcount++;
}
#endif
#ifdef WANT_CPUMINE
if (opt_n_threads > 0)
for (i = 0; i < num_processors; i++) {
if (isjson && (i > 0 || nDevs > 0))
if (isjson && devcount > 0)
strcat(io_buffer, COMMA);
cpustatus(i, isjson);
devcount++;
}
#endif
@ -691,6 +868,42 @@ static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson) @@ -691,6 +868,42 @@ static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
strcat(io_buffer, JSON_CLOSE);
}
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
{
int numpga = numpgas();
int id;
if (numpga == 0) {
strcpy(io_buffer, message(MSG_PGANON, 0, NULL, isjson));
return;
}
if (param == NULL || *param == '\0') {
strcpy(io_buffer, message(MSG_MISID, 0, NULL, isjson));
return;
}
id = atoi(param);
if (id < 0 || id >= numpga) {
strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson));
return;
}
strcpy(io_buffer, message(MSG_PGADEV, id, NULL, isjson));
if (isjson) {
strcat(io_buffer, COMMA);
strcat(io_buffer, JSON_PGA);
}
pgastatus(id, isjson);
if (isjson)
strcat(io_buffer, JSON_CLOSE);
}
#endif
#ifdef WANT_CPUMINE
static void cpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
{
@ -949,6 +1162,25 @@ static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo @@ -949,6 +1162,25 @@ static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
strcat(io_buffer, buf);
}
static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
{
char buf[BUFSIZ];
int count = 0;
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
count = numpgas();
#endif
strcpy(io_buffer, message(MSG_NUMPGA, 0, NULL, isjson));
if (isjson)
sprintf(buf, "," JSON_PGAS "{\"Count\":%d}" JSON_CLOSE, count);
else
sprintf(buf, _PGAS ",Count=%d%c", count, SEPARATOR);
strcat(io_buffer, buf);
}
static void cpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
{
char buf[BUFSIZ];
@ -1350,10 +1582,14 @@ struct CMDS { @@ -1350,10 +1582,14 @@ struct CMDS {
{ "gpudisable", gpudisable, true },
{ "gpurestart", gpurestart, true },
{ "gpu", gpudev, false },
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
{ "pga", pgadev, false },
#endif
#ifdef WANT_CPUMINE
{ "cpu", cpudev, false },
#endif
{ "gpucount", gpucount, false },
{ "pgacount", pgacount, false },
{ "cpucount", cpucount, false },
{ "switchpool", switchpool, true },
{ "addpool", addpool, true },

Loading…
Cancel
Save