From cb3323b7b5b267c566c9b18626f0e8d5599c8928 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 29 Feb 2012 21:17:10 +1100 Subject: [PATCH 01/19] Add API support for Icarus and Bitforce --- README | 22 ++++- api.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 282 insertions(+), 30 deletions(-) diff --git a/README b/README index ba9d86ad..9ee3a3d2 100644 --- a/README +++ b/README @@ -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: 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 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 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 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 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 diff --git a/api.c b/api.c index dd2af0b7..edab0724 100644 --- a/api.c +++ b/api.c @@ -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 @@ #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 = ","; 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"; #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 = '{'; #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"; #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 { 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 { { 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 { 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) { 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) 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) 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, 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, 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, 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) } } +#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) 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 } 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) 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 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 { { "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 }, From 0fdf31dc272c16ea03b5209cf0020c1c46e11372 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 4 Mar 2012 14:05:39 +1100 Subject: [PATCH 02/19] icarus.c set the windows TODO timeout --- icarus.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/icarus.c b/icarus.c index 1d59657d..b50aaae7 100644 --- a/icarus.c +++ b/icarus.c @@ -100,7 +100,10 @@ static int icarus_open(const char *devpath) NULL, OPEN_EXISTING, 0, NULL); if (unlikely(hSerial == INVALID_HANDLE_VALUE)) return -1; - /* TODO: Needs setup read block time. just like VTIME = 10 */ + + COMMTIMEOUTS cto = {1000, 0, 1000, 0, 1000}; + SetCommTimeouts(hSerial, &cto); + return _open_osfhandle((LONG)hSerial, 0); #endif } From caa02f81a552798df46e9671b541fe66a23309a1 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 4 Mar 2012 14:37:38 +1100 Subject: [PATCH 03/19] icarus.c modify (regular) timeout warning to only be debug --- icarus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icarus.c b/icarus.c index b50aaae7..48dabe57 100644 --- a/icarus.c +++ b/icarus.c @@ -123,7 +123,7 @@ static int icarus_gets(unsigned char *buf, size_t bufLen, int fd) rc++; if (rc == ICARUS_READ_FAULT_COUNT) { - applog(LOG_WARNING, + applog(LOG_DEBUG, "Icarus Read: No data in %d seconds", rc); return 1; } From 1f118078eba7926b325fe21a8794a0ecb2b5c1f6 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 4 Mar 2012 14:51:11 +1100 Subject: [PATCH 04/19] api.c: correct error messages --- api.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/api.c b/api.c index edab0724..d7f8a97f 100644 --- a/api.c +++ b/api.c @@ -524,6 +524,21 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) case PARAM_GPUMAX: sprintf(ptr, codes[i].description, paramid, nDevs - 1); break; +#if defined(USE_BITFORCE) || defined(USE_ICARUS) + case PARAM_PGAMAX: + pga = numpgas(); + sprintf(ptr, codes[i].description, paramid, pga - 1); + break; +#endif +#ifdef WANT_CPUMINE + case PARAM_CPUMAX: + if (opt_n_threads > 0) + cpu = num_processors; + else + cpu = 0; + sprintf(ptr, codes[i].description, paramid, cpu - 1); + break; +#endif case PARAM_PMAX: sprintf(ptr, codes[i].description, total_pools); break; From 702dd0f86f88159ed81c2780087b76138e60f9a7 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 6 Mar 2012 18:51:16 +1100 Subject: [PATCH 05/19] miner.php split devs output for different devices --- miner.php | 79 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/miner.php b/miner.php index d385a8ff..8f37dfcc 100644 --- a/miner.php +++ b/miner.php @@ -158,7 +158,8 @@ function fmt($section, $name, $value) switch ($section.'.'.$name) { - case 'GPU0.Last Share Time': + case 'GPU.Last Share Time': + case 'PGA.Last Share Time': return date('H:i:s', $value); break; case 'SUMMARY.Elapsed': @@ -190,11 +191,13 @@ function fmt($section, $name, $value) } } break; - case 'GPU0.Utility': + case 'GPU.Utility': + case 'PGA.Utility': case 'SUMMARY.Utility': return $value.'/m'; break; - case 'GPU0.Temperature': + case 'GPU.Temperature': + case 'PGA.Temperature': return $value.'°C'; break; } @@ -202,8 +205,37 @@ function fmt($section, $name, $value) return $value; } # +global $poolcmd; +$poolcmd = array( 'Switch to' => 'switchpool', + 'Enable' => 'enablepool', + 'Disable' => 'disablepool' ); +# +function showhead($cmd, $item, $values) +{ + global $poolcmd; + + echo ''; + + foreach ($values as $name => $value) + { + if ($name == '0') + $name = ' '; + echo "$name"; + } + + if ($cmd == 'pools') + foreach ($poolcmd as $name => $pcmd) + echo "$name"; + + echo ''; +} +# function details($cmd, $list) { + global $poolcmd; + + $dfmt = 'H:i:s j-M-Y \U\T\CP'; + $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal'); $tb = ''; @@ -211,7 +243,7 @@ function details($cmd, $list) echo $tb; - echo ''; + echo ''; echo $te.$tb; @@ -219,49 +251,30 @@ function details($cmd, $list) { echo ''; echo ''; + if (isset($list['STATUS']['When'])) + echo ''; $sta = $list['STATUS']['STATUS']; echo ''; echo ''; echo ''; } - echo $te.$tb; $section = ''; - $poolcmd = array( 'Switch to' => 'switchpool', - 'Enable' => 'enablepool', - 'Disable' => 'disablepool' ); - foreach ($list as $item => $values) { - if ($item != 'STATUS') - { - $section = $item; - - echo ''; - - foreach ($values as $name => $value) - { - if ($name == '0') - $name = ' '; - echo ""; - } - - if ($cmd == 'pools') - foreach ($poolcmd as $name => $pcmd) - echo ""; + if ($item == 'STATUS') + continue; - echo ''; + $sectionname = ereg_replace('[0-9]', '', $item); - break; + if ($sectionname != $section) + { + echo $te.$tb; + showhead($cmd, $item, $values); + $section = $sectionname; } - } - - foreach ($list as $item => $values) - { - if ($item == 'STATUS') - continue; echo ''; From 84aa0d693b71fb77090a637fa36555f01ee82eb5 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 13 Mar 2012 23:36:02 +1100 Subject: [PATCH 06/19] miner.php: ereg_replace is DEPRECATED so use preg_replace instead --- miner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner.php b/miner.php index 8f37dfcc..945f3aec 100644 --- a/miner.php +++ b/miner.php @@ -267,7 +267,7 @@ function details($cmd, $list) if ($item == 'STATUS') continue; - $sectionname = ereg_replace('[0-9]', '', $item); + $sectionname = preg_replace('/\d/', '', $item); if ($sectionname != $section) { From 22ff7a406951f97af57cbca75d282c4bbf41a3e7 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 14 Mar 2012 20:29:45 +1100 Subject: [PATCH 07/19] miner.php: option for readonly or check privileged access --- miner.php | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/miner.php b/miner.php index 945f3aec..6e501ba6 100644 --- a/miner.php +++ b/miner.php @@ -1,12 +1,27 @@ Mine @@ -177,55 +185,87 @@ function getparam($name, $both = false) # function fmt($section, $name, $value) { + $errorclass = ' class=err'; + $warnclass = ' class=warn'; $b = ' '; + $ret = $value; + $class = ''; + switch ($section.'.'.$name) { case 'GPU.Last Share Time': case 'PGA.Last Share Time': - return date('H:i:s', $value); + $ret = date('H:i:s', $value); break; case 'SUMMARY.Elapsed': $s = $value % 60; $value -= $s; $value /= 60; if ($value == 0) - { - return $s.'s'; - } + $ret = $s.'s'; else { $m = $value % 60; $value -= $m; $value /= 60; if ($value == 0) - { - return sprintf("%dm$b%02ds", $m, $s); - } + $ret = sprintf("%dm$b%02ds", $m, $s); else { $h = $value % 24; $value -= $h; $value /= 24; if ($value == 0) - return sprintf("%dh$b%02dm$b%02ds", $h, $m, $s); + $ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s); else - return sprintf("%ddays$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s); + $ret = sprintf("%ddays$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s); } } break; + case 'NOTIFY.Last Well': + if ($value == '0') + { + $ret = 'Never'; + $class = $warnclass; + } + else + $ret = date('H:i:s', $value); + break; + case 'NOTIFY.Last Not Well': + if ($value == '0') + $ret = 'Never'; + else + { + $ret = date('H:i:s', $value); + $class = $errorclass; + } + break; + case 'NOTIFY.Reason Not Well': + if ($value != 'None') + $class = $errorclass; + break; case 'GPU.Utility': case 'PGA.Utility': case 'SUMMARY.Utility': - return $value.'/m'; + $ret = $value.'/m'; break; case 'GPU.Temperature': case 'PGA.Temperature': - return $value.'°C'; + $ret = $value.'°C'; break; } - return $value; + if ($section == 'NOTIFY') + { + $code = preg_split('/ /', $name); + if (count($code) > 1) + if ($code[0] == 'Thread' || $code[0] == 'Dev') + if ($value != '0') + $class = $errorclass; + } + + return array($ret, $class); } # global $poolcmd; @@ -302,7 +342,10 @@ function details($cmd, $list) echo ''; foreach ($values as $name => $value) - echo ''; + { + list($showvalue, $class) = fmt($section, $name, $value); + echo "$showvalue"; + } if ($cmd == 'pools' && $readonly === false) { @@ -444,7 +487,7 @@ function process($cmds, $rd, $ro) # function display() { - global $error, $readonly; + global $error, $readonly, $notify; $error = null; @@ -464,8 +507,12 @@ function display() $cmds = array( 'devs' => 'device list', 'summary' => 'summary information', - 'pools' => 'pool list', - 'config' => 'cgminer config'); + 'pools' => 'pool list'); + + if ($notify) + $cmds['notify'] = 'device status'; + + $cmds['config'] = 'cgminer config'; process($cmds, $rd, $ro); From 25f914a3345b274bbeb0942e0dee621c4385c053 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 24 Mar 2012 23:20:48 +1100 Subject: [PATCH 17/19] api.c miner.php add a '*' to the front of all notify counters - simplifies future support of new counters --- api.c | 6 ++++-- miner.php | 10 ++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/api.c b/api.c index 8c86252c..8a95a626 100644 --- a/api.c +++ b/api.c @@ -1638,8 +1638,10 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson) break; } + // ALL counters (and only counters) must start the name with a '*' + // Simplifies future external support for adding new counters if (isjson) - sprintf(buf, "%s{\"NOTIFY\":%d,\"Name\":\"%s\",\"ID\":%d,\"Last Well\":%lu,\"Last Not Well\":%lu,\"Reason Not Well\":\"%s\",\"Thread Fail Init\":%d,\"Thread Zero Hash\":%d,\"Thread Fail Queue\":%d,\"Dev Sick Idle 60s\":%d,\"Dev Dead Idle 600s\":%d,\"Dev Nostart\":%d,\"Dev Over Heat\":%d,\"Dev Thermal Cutoff\":%d}" JSON_CLOSE, + sprintf(buf, "%s{\"NOTIFY\":%d,\"Name\":\"%s\",\"ID\":%d,\"Last Well\":%lu,\"Last Not Well\":%lu,\"Reason Not Well\":\"%s\",\"*Thread Fail Init\":%d,\"*Thread Zero Hash\":%d,\"*Thread Fail Queue\":%d,\"*Dev Sick Idle 60s\":%d,\"*Dev Dead Idle 600s\":%d,\"*Dev Nostart\":%d,\"*Dev Over Heat\":%d,\"*Dev Thermal Cutoff\":%d}" JSON_CLOSE, device > 0 ? "," : "", device, cgpu->api->name, cgpu->device_id, cgpu->device_last_well, cgpu->device_last_not_well, reason, cgpu->thread_fail_init_count, cgpu->thread_zero_hash_count, @@ -1647,7 +1649,7 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson) cgpu->dev_dead_idle_600_count, cgpu->dev_nostart_count, cgpu->dev_over_heat_count, cgpu->dev_thermal_cutoff_count); else - sprintf(buf, "NOTIFY=%d,Name=%s,ID=%d,Last Well=%lu,Last Not Well=%lu,Reason Not Well=%s,Thread Fail Init=%d,Thread Zero Hash=%d,Thread Fail Queue=%d,Dev Sick Idle 60s=%d,Dev Dead Idle 600s=%d,Dev Nostart=%d,Dev Over Heat=%d,Dev Thermal Cutoff=%d%c", + sprintf(buf, "NOTIFY=%d,Name=%s,ID=%d,Last Well=%lu,Last Not Well=%lu,Reason Not Well=%s,*Thread Fail Init=%d,*Thread Zero Hash=%d,*Thread Fail Queue=%d,*Dev Sick Idle 60s=%d,*Dev Dead Idle 600s=%d,*Dev Nostart=%d,*Dev Over Heat=%d,*Dev Thermal Cutoff=%d%c", device, cgpu->api->name, cgpu->device_id, cgpu->device_last_well, cgpu->device_last_not_well, reason, cgpu->thread_fail_init_count, cgpu->thread_zero_hash_count, diff --git a/miner.php b/miner.php index 14b249ee..5cdcc7e4 100644 --- a/miner.php +++ b/miner.php @@ -256,14 +256,8 @@ function fmt($section, $name, $value) break; } - if ($section == 'NOTIFY') - { - $code = preg_split('/ /', $name); - if (count($code) > 1) - if ($code[0] == 'Thread' || $code[0] == 'Dev') - if ($value != '0') - $class = $errorclass; - } + if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0') + $class = $errorclass; return array($ret, $class); } From cba2d84622801256a0205ff5b6d46793661b9e5d Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 26 Mar 2012 22:00:00 +1100 Subject: [PATCH 18/19] Change email due to SPAM --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index c95f6a9f..b58f3588 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ Original CPU mining software: Jeff Garzik GPU mining and rewrite: Con Kolivas 15qSxP1SQcUX3o4nhkfdbgyoWEFMomJ4rZ BitFORCE FPGA mining and refactor: Luke Dashjr 1NbRmS6a4dniwHHoSS9v3tEYUpP1Z5VVdL -API+: Andrew Smith 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm +API+: Andrew Smith 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm From 0699061ade403a3a823bd2320bb01c67a35b4268 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 28 Mar 2012 10:50:28 +1100 Subject: [PATCH 19/19] api.c devicecode/osinfo incorrectly swapped for json --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index 8a95a626..1879c38f 100644 --- a/api.c +++ b/api.c @@ -681,7 +681,7 @@ 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,\"PGA Count\":%d,\"CPU Count\":%d,\"Pool Count\":%d,\"ADL\":\"%s\",\"ADL in use\":\"%s\",\"Strategy\":\"%s\",\"Log Interval\":%d,\"Device Code\":\"%s\",\"OS\":\"%s\"}" JSON_CLOSE, nDevs, pgacount, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval, OSINFO, DEVICECODE); + 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,\"Device Code\":\"%s\",\"OS\":\"%s\"}" JSON_CLOSE, nDevs, pgacount, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval, DEVICECODE, OSINFO); else 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,Device Code=%s,OS=%s%c", nDevs, pgacount, cpucount, total_pools, adl, adlinuse, strategies[pool_strategy].s, opt_log_interval, DEVICECODE, OSINFO, SEPARATOR);
Date: '.date('H:i:s j-M-Y \U\T\CP').'
Date: '.date($dfmt).'
Computer: '.$list['STATUS']['Description'].'When: '.date($dfmt, $list['STATUS']['When']).'Status: '.$stas[$sta].'Message: '.$list['STATUS']['Msg'].'
$name$name
'.fmt($section, $name, $value).'