Browse Source

Merge branch 'rpc_fulldev' into bfgminer

Luke Dashjr 12 years ago
parent
commit
ef69ec68fa
4 changed files with 270 additions and 125 deletions
  1. 55 9
      README.RPC
  2. 203 116
      api.c
  3. 1 0
      miner.h
  4. 11 0
      miner.php

+ 55 - 9
README.RPC

@@ -151,13 +151,13 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               Will not report PGAs if PGA mining is disabled
                               Will not report CPUs if CPU mining is disabled
 
+ procs         DEVS           The details of each processor in the same format
+                              and details as for DEVS
+
  devscan|info  DEVS           Probes for a device specified by info, which is
                               the same format as the --scan-serial command line
                               option
 
- devdetail     DEVS           Each available device with their fixed details
-                              e.g. GPU=0,Driver=opencl,Kernel=diablo,Model=...|
-
  gpu|N         GPU            The details of a single GPU number N in the same
                               format and details as for DEVS
 
@@ -167,6 +167,9 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               Use 'pgacount' or 'config' first to see if there
                               are any
 
+ proc|N        PGA            The details of a single processor number N in the
+                              same format and details as for DEVS
+
  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
@@ -177,6 +180,8 @@ The list of requests - a (*) means it requires privileged access - and replies:
  pgacount      PGAS           Count=N| <- the number of PGAs
                               Always returns 0 if PGA mining is disabled
 
+ proccount     PGAS           Count=N| <- the number of processors
+
  cpucount      CPUS           Count=N| <- the number of CPUs
                               Always returns 0 if CPU mining is disabled
 
@@ -295,9 +300,21 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               This is only available if PGA mining is enabled
 
  pgaidentify|N (*)
+               none           This is equivalent to PROCIDENTIFY on the first
+                              processor of any given device
+                              This is only available if PGA mining is enabled
+
+ procenable|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the enable request
+
+ procdisable|N (*)
+               none           There is no reply section just the STATUS section
+                              stating the results of the disable request
+
+ procidentify|N (*)
                none           There is no reply section just the STATUS section
                               stating the results of the identify request
-                              This is only available if PGA mining is enabled
                               On most supported devices, it will flash the led
                               for approximately 4s
                               All unsupported devices, it will return a warning
@@ -313,7 +330,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
  devdetails    DEVDETAILS     Each device with a list of their static details
                               This lists all devices including those not
                               supported by the 'devs' command
-                              e.g. DEVDETAILS=0,Name=PGA,ID=0,ProcID=0,Driver=bitforce,...|
+                              e.g. DEVDETAILS=0,Name=BFL,ID=0,ProcID=0,Driver=bitforce,...|
 
  restart (*)   none           There is no status section but just a single
                               "RESTART" reply before BFGMiner restarts
@@ -366,13 +383,17 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               coinbase-sig (string)
 
  pgaset|N,opt[,val] (*)
+               none           This is equivalent to PROCSET on the first
+                              processor of any given device
+                              This is only available if PGA mining is enabled
+
+ procset|N,opt[,val] (*)
                none           There is no reply section just the STATUS section
-                              stating the results of setting PGA N with
+                              stating the results of setting processor N with
                               opt[,val]
-                              This is only available if PGA mining is enabled
 
-                              If the PGA does not support any set options, it
-                              will always return a WARN stating pgaset isn't
+                              If the processor does not support any set options,
+                              it will always return a WARN stating pgaset isn't
                               supported
 
                               If opt=help it will return an INFO status with a
@@ -445,6 +466,31 @@ api-example.py - a Python script to access the API
 Feature Changelog for external applications using the API:
 
 
+API V2.0
+
+Removed API commands:
+ 'devdetail' - Use newer 'devdetails' for same information.
+
+Modified API commands:
+ 'devs' - display status of each full device only (not processors)
+ 'pga' - lookup and display device by device (not processor) number
+ 'pgacount' - count only full devices (not processors)
+ 'pgaenable' - enable all processors for a numbered full device
+ 'pgadisable' - disable all processors for a numbered full device
+ 'pgaidentify' - choose first processor of numbered full device
+ 'pgaset' - choose first processor of numbered full device
+
+Added API commands:
+ 'procs'
+ 'proc'
+ 'proccount'
+ 'procenable'
+ 'procdisable'
+ 'procidentify'
+ 'procset'
+
+----------
+
 API V1.25.3 (BFGMiner v3.2.0)
 
 Modified API commands:

+ 203 - 116
api.c

@@ -532,6 +532,7 @@ static bool do_a_quit;
 static bool do_a_restart;
 
 static time_t when = 0;	// when the request occurred
+static bool per_proc;
 
 struct IP4ACCESS {
 	in_addr_t ip;
@@ -1113,6 +1114,8 @@ static int numpgas()
 		if (devices[i]->drv == &cpu_drv)
 			continue;
 #endif
+		if (devices[i]->device != devices[i] && !per_proc)
+			continue;
 		++count;
 	}
 	rd_unlock(&devices_lock);
@@ -1134,6 +1137,8 @@ static int pgadevice(int pgaid)
 		if (devices[i]->drv == &cpu_drv)
 			continue;
 #endif
+		if (devices[i]->device != devices[i] && !per_proc)
+			continue;
 		++count;
 		if (count == (pgaid + 1))
 			goto foundit;
@@ -1401,6 +1406,8 @@ static const char *status2str(enum alive status)
 			return INIT;
 		case LIFE_WAIT:
 			return WAIT;
+		case LIFE_MIXED:
+			return "Mixed";
 		default:
 			return UNKNOWN;
 	}
@@ -1411,28 +1418,41 @@ struct api_data *api_add_device_identifier(struct api_data *root, struct cgpu_in
 {
 	root = api_add_string(root, "Name", cgpu->drv->name, false);
 	root = api_add_int(root, "ID", &(cgpu->device_id), false);
-	root = api_add_int(root, "ProcID", &(cgpu->proc_id), false);
+	if (per_proc)
+		root = api_add_int(root, "ProcID", &(cgpu->proc_id), false);
 	return root;
 }
 
-static void devdetail_an(struct io_data *io_data, struct cgpu_info *cgpu, bool isjson, bool precom)
+static
+int find_index_by_cgpu(struct cgpu_info *cgpu)
 {
-	struct api_data *root = NULL;
-	char buf[TMPBUFSIZ];
 	int n = 0, i;
-
-	cgpu_utility(cgpu);
-
+	
 	rd_lock(&devices_lock);
-	for (i = 0; i < total_devices; ++i) {
+	for (i = 0; i < total_devices; ++i)
+	{
 		if (devices[i] == cgpu)
 			break;
+		if (devices[i]->device != devices[i] && !per_proc)
+			continue;
 		if (cgpu->devtype == devices[i]->devtype)
 			++n;
 	}
 	rd_unlock(&devices_lock);
+	return n;
+}
 
-	root = api_add_int(root, (char*)cgpu->devtype, &n, true);
+static void devdetail_an(struct io_data *io_data, struct cgpu_info *cgpu, bool isjson, bool precom)
+{
+	struct api_data *root = NULL;
+	char buf[TMPBUFSIZ];
+	int n;
+
+	cgpu_utility(cgpu);
+
+	n = find_index_by_cgpu(cgpu);
+
+	root = api_add_int(root, "DEVDETAILS", &n, true);
 	root = api_add_device_identifier(root, cgpu);
 	root = api_add_string(root, "Driver", cgpu->drv->dname, false);
 	if (cgpu->kname)
@@ -1449,56 +1469,93 @@ static void devdetail_an(struct io_data *io_data, struct cgpu_info *cgpu, bool i
 	io_add(io_data, buf);
 }
 
-static void devstatus_an(struct io_data *io_data, struct cgpu_info *cgpu, bool isjson, bool precom)
+static
+void devstatus_an(struct io_data *io_data, struct cgpu_info *cgpu, bool isjson, bool precom)
 {
+	struct cgpu_info *proc;
 	struct api_data *root = NULL;
 	char buf[TMPBUFSIZ];
-	int n = 0, i;
-
-	cgpu_utility(cgpu);
+	int n;
 
-	rd_lock(&devices_lock);
-	for (i = 0; i < total_devices; ++i) {
-		if (devices[i] == cgpu)
+	n = find_index_by_cgpu(cgpu);
+
+	bool enabled = false;
+	double total_mhashes = 0, rolling = 0, utility = 0;
+	enum alive status = cgpu->status;
+	float temp = -1;
+	int accepted = 0, rejected = 0, hw_errors = 0;
+	int diff1 = 0, bad_nonces = 0;
+	double diff_accepted = 0, diff_rejected = 0;
+	int last_share_pool = -1;
+	time_t last_share_pool_time = -1, last_device_valid_work = -1;
+	double last_share_diff = -1;
+	for (proc = cgpu; proc; proc = proc->next_proc)
+	{
+		cgpu_utility(proc);
+		if (proc->deven != DEV_DISABLED)
+			enabled = true;
+		total_mhashes += proc->total_mhashes;
+		rolling += proc->rolling;
+		utility += proc->utility;
+		accepted += proc->accepted;
+		rejected += proc->rejected;
+		hw_errors += proc->hw_errors;
+		diff1 += proc->diff1;
+		diff_accepted += proc->diff_accepted;
+		diff_rejected += proc->diff_rejected;
+		bad_nonces += proc->bad_nonces;
+		if (status != proc->status)
+			status = LIFE_MIXED;
+		if (proc->temp > temp)
+			temp = proc->temp;
+		if (proc->last_share_pool_time > last_share_pool_time)
+		{
+			last_share_pool_time = proc->last_share_pool_time;
+			last_share_pool = proc->last_share_pool;
+			last_share_diff = proc->last_share_diff;
+		}
+		if (proc->last_device_valid_work > last_device_valid_work)
+			last_device_valid_work = proc->last_device_valid_work;
+		if (per_proc)
 			break;
-		if (cgpu->devtype == devices[i]->devtype)
-			++n;
 	}
-	rd_unlock(&devices_lock);
 
 	root = api_add_int(root, (char*)cgpu->devtype, &n, true);
 	root = api_add_device_identifier(root, cgpu);
-	root = api_add_string(root, "Enabled", bool2str(cgpu->deven != DEV_DISABLED), false);
-	root = api_add_string(root, "Status", status2str(cgpu->status), false);
-	if (cgpu->temp)
-		root = api_add_temp(root, "Temperature", &cgpu->temp, false);
-	double mhs = cgpu->total_mhashes / cgpu_runtime(cgpu);
+	root = api_add_string(root, "Enabled", bool2str(enabled), false);
+	root = api_add_string(root, "Status", status2str(status), false);
+	if (temp > 0)
+		root = api_add_temp(root, "Temperature", &temp, false);
+	double mhs = total_mhashes / cgpu_runtime(cgpu);
 	root = api_add_mhs(root, "MHS av", &mhs, false);
 	char mhsname[27];
 	sprintf(mhsname, "MHS %ds", opt_log_interval);
-	root = api_add_mhs(root, mhsname, &(cgpu->rolling), false);
-	root = api_add_int(root, "Accepted", &(cgpu->accepted), false);
-	root = api_add_int(root, "Rejected", &(cgpu->rejected), false);
-	root = api_add_int(root, "Hardware Errors", &(cgpu->hw_errors), false);
-	root = api_add_utility(root, "Utility", &(cgpu->utility), false);
-	int last_share_pool = cgpu->last_share_pool_time > 0 ?
-				cgpu->last_share_pool : -1;
-	root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
-	root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
-	root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
-	root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false);
-	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);
-	root = api_add_time(root, "Last Valid Work", &(cgpu->last_device_valid_work), false);
-	double hwp = (cgpu->bad_nonces + cgpu->diff1) ?
-			(double)(cgpu->bad_nonces) / (double)(cgpu->bad_nonces + cgpu->diff1) : 0;
+	root = api_add_mhs(root, mhsname, &rolling, false);
+	root = api_add_int(root, "Accepted", &accepted, false);
+	root = api_add_int(root, "Rejected", &rejected, false);
+	root = api_add_int(root, "Hardware Errors", &hw_errors, false);
+	root = api_add_utility(root, "Utility", &utility, false);
+	if (last_share_pool != -1)
+	{
+		root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
+		root = api_add_time(root, "Last Share Time", &last_share_pool_time, false);
+	}
+	root = api_add_mhtotal(root, "Total MH", &total_mhashes, false);
+	root = api_add_int(root, "Diff1 Work", &diff1, false);
+	root = api_add_diff(root, "Difficulty Accepted", &diff_accepted, false);
+	root = api_add_diff(root, "Difficulty Rejected", &diff_rejected, false);
+	if (last_share_diff > 0)
+		root = api_add_diff(root, "Last Share Difficulty", &last_share_diff, false);
+	if (last_device_valid_work != -1)
+		root = api_add_time(root, "Last Valid Work", &last_device_valid_work, false);
+	double hwp = (bad_nonces + diff1) ?
+			(double)(bad_nonces) / (double)(bad_nonces + diff1) : 0;
 	root = api_add_percent(root, "Device Hardware%", &hwp, false);
-	double rejp = cgpu->diff1 ?
-			(double)(cgpu->diff_rejected) / (double)(cgpu->diff1) : 0;
+	double rejp = diff1 ?
+			(double)(diff_rejected) / (double)(diff1) : 0;
 	root = api_add_percent(root, "Device Rejected%", &rejp, false);
 
-	if (cgpu->drv->get_api_extra_device_status)
+	if (per_proc && cgpu->drv->get_api_extra_device_status)
 		root = api_add_extra(root, cgpu->drv->get_api_extra_device_status(cgpu));
 
 	root = print_data(root, buf, isjson, precom);
@@ -1534,8 +1591,9 @@ static void cpustatus(struct io_data *io_data, int cpu, bool isjson, bool precom
 #endif
 
 static void
-devinfo_internal(void (*func)(struct io_data *, struct cgpu_info*, bool, bool), struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
+devinfo_internal(void (*func)(struct io_data *, struct cgpu_info*, bool, bool), int msg, struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
 {
+	struct cgpu_info *cgpu;
 	bool io_open = false;
 	int i;
 
@@ -1545,12 +1603,14 @@ devinfo_internal(void (*func)(struct io_data *, struct cgpu_info*, bool, bool),
 	}
 
 
-	message(io_data, MSG_DEVS, 0, NULL, isjson);
+	message(io_data, msg, 0, NULL, isjson);
 	if (isjson)
 		io_open = io_add(io_data, COMSTR JSON_DEVS);
 
 	for (i = 0; i < total_devices; ++i) {
-		func(io_data, get_devices(i), isjson, isjson && i > 0);
+		cgpu = get_devices(i);
+		if (per_proc || cgpu->device == cgpu)
+			func(io_data, cgpu, isjson, isjson && i > 0);
 	}
 
 	if (isjson && io_open)
@@ -1559,12 +1619,12 @@ devinfo_internal(void (*func)(struct io_data *, struct cgpu_info*, bool, bool),
 
 static void devdetail(struct io_data *io_data, SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
-	return devinfo_internal(devdetail_an, io_data, c, param, isjson, group);
+	return devinfo_internal(devdetail_an, MSG_DEVDETAILS, io_data, c, param, isjson, group);
 }
 
 static void devstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
 {
-	return devinfo_internal(devstatus_an, io_data, c, param, isjson, group);
+	return devinfo_internal(devstatus_an, MSG_DEVS, io_data, c, param, isjson, group);
 }
 
 #ifdef HAVE_OPENCL
@@ -1662,9 +1722,10 @@ static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *p
 
 static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
-	struct cgpu_info *cgpu;
+	struct cgpu_info *cgpu, *proc;
 	int numpga = numpgas();
 	int id;
+	bool already;
 
 	if (numpga == 0) {
 		message(io_data, MSG_PGANON, 0, NULL, isjson);
@@ -1690,10 +1751,21 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
 
 	cgpu = get_devices(dev);
 
-	applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s",
-			id, dev, cgpu->proc_repr_ns);
+	applog(LOG_DEBUG, "API: request to pgaenable %s id %d device %d %s",
+			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 
-	if (cgpu->deven != DEV_DISABLED) {
+	already = true;
+	for (proc = cgpu; proc; proc = proc->next_proc)
+	{
+		if (proc->deven == DEV_DISABLED)
+		{
+			proc_enable(proc);
+			already = false;
+		}
+	}
+	
+	if (already)
+	{
 		message(io_data, MSG_PGALRENA, id, NULL, isjson);
 		return;
 	}
@@ -1705,16 +1777,15 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
 	}
 #endif
 
-	proc_enable(cgpu);
-
 	message(io_data, MSG_PGAENA, id, NULL, isjson);
 }
 
 static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
 {
-	struct cgpu_info *cgpu;
+	struct cgpu_info *cgpu, *proc;
 	int numpga = numpgas();
 	int id;
+	bool already;
 
 	if (numpga == 0) {
 		message(io_data, MSG_PGANON, 0, NULL, isjson);
@@ -1740,16 +1811,25 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
 
 	cgpu = get_devices(dev);
 
-	applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s",
-			id, dev, cgpu->proc_repr_ns);
+	applog(LOG_DEBUG, "API: request to pgadisable %s id %d device %d %s",
+			per_proc ? "proc" : "dev", id, dev, cgpu->proc_repr_ns);
 
-	if (cgpu->deven == DEV_DISABLED) {
+	already = true;
+	for (proc = cgpu; proc; proc = proc->next_proc)
+	{
+		if (proc->deven != DEV_DISABLED)
+		{
+			cgpu->deven = DEV_DISABLED;
+			already = false;
+		}
+	}
+	
+	if (already)
+	{
 		message(io_data, MSG_PGALRDIS, id, NULL, isjson);
 		return;
 	}
 
-	cgpu->deven = DEV_DISABLED;
-
 	message(io_data, MSG_PGADIS, id, NULL, isjson);
 }
 
@@ -2693,14 +2773,43 @@ void privileged(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_un
 
 void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, bool isjson, __maybe_unused char group)
 {
+	struct cgpu_info *proc;
 	struct api_data *root = NULL;
 	char buf[TMPBUFSIZ];
 	char *reason;
+	
+	time_t last_not_well = 0;
+	enum dev_reason uninitialised_var(enum_reason);
+	int thread_fail_init_count = 0, thread_zero_hash_count = 0, thread_fail_queue_count = 0;
+	int dev_sick_idle_60_count = 0, dev_dead_idle_600_count = 0;
+	int dev_nostart_count = 0, dev_over_heat_count = 0, dev_thermal_cutoff_count = 0, dev_comms_error_count = 0, dev_throttle_count = 0;
 
-	if (cgpu->device_last_not_well == 0)
+	for (proc = cgpu; proc; proc = proc->next_proc)
+	{
+		if (proc->device_last_not_well > last_not_well)
+		{
+			last_not_well = proc->device_last_not_well;
+			enum_reason = proc->device_not_well_reason;
+			thread_fail_init_count   += proc->thread_fail_init_count;
+			thread_zero_hash_count   += proc->thread_zero_hash_count;
+			thread_fail_queue_count  += proc->thread_fail_queue_count;
+			dev_sick_idle_60_count   += proc->dev_sick_idle_60_count;
+			dev_dead_idle_600_count  += proc->dev_dead_idle_600_count;
+			dev_nostart_count        += proc->dev_nostart_count;
+			dev_over_heat_count      += proc->dev_over_heat_count;
+			dev_thermal_cutoff_count += proc->dev_thermal_cutoff_count;
+			dev_comms_error_count    += proc->dev_comms_error_count;
+			dev_throttle_count       += proc->dev_throttle_count;
+		}
+		if (per_proc)
+			break;
+	}
+	
+	if (last_not_well == 0)
 		reason = REASON_NONE;
 	else
-		switch(cgpu->device_not_well_reason) {
+		switch (enum_reason)
+		{
 			case REASON_THREAD_FAIL_INIT:
 				reason = REASON_THREAD_FAIL_INIT_STR;
 				break;
@@ -2737,29 +2846,31 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b
 	// Simplifies future external support for identifying new counters
 	root = api_add_int(root, "NOTIFY", &device, false);
 	root = api_add_device_identifier(root, cgpu);
-	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);
+	if (per_proc)
+		root = api_add_time(root, "Last Well", &(cgpu->device_last_well), false);
+	root = api_add_time(root, "Last Not Well", &last_not_well, false);
 	root = api_add_string(root, "Reason Not Well", reason, false);
-	root = api_add_int(root, "*Thread Fail Init", &(cgpu->thread_fail_init_count), false);
-	root = api_add_int(root, "*Thread Zero Hash", &(cgpu->thread_zero_hash_count), false);
-	root = api_add_int(root, "*Thread Fail Queue", &(cgpu->thread_fail_queue_count), false);
-	root = api_add_int(root, "*Dev Sick Idle 60s", &(cgpu->dev_sick_idle_60_count), false);
-	root = api_add_int(root, "*Dev Dead Idle 600s", &(cgpu->dev_dead_idle_600_count), false);
-	root = api_add_int(root, "*Dev Nostart", &(cgpu->dev_nostart_count), false);
-	root = api_add_int(root, "*Dev Over Heat", &(cgpu->dev_over_heat_count), false);
-	root = api_add_int(root, "*Dev Thermal Cutoff", &(cgpu->dev_thermal_cutoff_count), false);
-	root = api_add_int(root, "*Dev Comms Error", &(cgpu->dev_comms_error_count), false);
-	root = api_add_int(root, "*Dev Throttle", &(cgpu->dev_throttle_count), false);
+	root = api_add_int(root, "*Thread Fail Init", &thread_fail_init_count, false);
+	root = api_add_int(root, "*Thread Zero Hash", &thread_zero_hash_count, false);
+	root = api_add_int(root, "*Thread Fail Queue", &thread_fail_queue_count, false);
+	root = api_add_int(root, "*Dev Sick Idle 60s", &dev_sick_idle_60_count, false);
+	root = api_add_int(root, "*Dev Dead Idle 600s", &dev_dead_idle_600_count, false);
+	root = api_add_int(root, "*Dev Nostart", &dev_nostart_count, false);
+	root = api_add_int(root, "*Dev Over Heat", &dev_over_heat_count, false);
+	root = api_add_int(root, "*Dev Thermal Cutoff", &dev_thermal_cutoff_count, false);
+	root = api_add_int(root, "*Dev Comms Error", &dev_comms_error_count, false);
+	root = api_add_int(root, "*Dev Throttle", &dev_throttle_count, false);
 
 	root = print_data(root, buf, isjson, isjson && (device > 0));
 	io_add(io_data, buf);
 }
 
-static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group)
+static
+void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group)
 {
 	struct cgpu_info *cgpu;
 	bool io_open = false;
-	int i;
+	int i, n = 0;
 
 	if (total_devices == 0) {
 		message(io_data, MSG_NODEVS, 0, NULL, isjson);
@@ -2773,43 +2884,8 @@ static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
 
 	for (i = 0; i < total_devices; i++) {
 		cgpu = get_devices(i);
-		notifystatus(io_data, i, cgpu, isjson, group);
-	}
-
-	if (isjson && io_open)
-		io_close(io_data);
-}
-
-static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
-{
-	struct api_data *root = NULL;
-	char buf[TMPBUFSIZ];
-	bool io_open = false;
-	struct cgpu_info *cgpu;
-	int i;
-
-	if (total_devices == 0) {
-		message(io_data, MSG_NODEVS, 0, NULL, isjson);
-		return;
-	}
-
-	message(io_data, MSG_DEVDETAILS, 0, NULL, isjson);
-
-	if (isjson)
-		io_open = io_add(io_data, COMSTR JSON_DEVDETAILS);
-
-	for (i = 0; i < total_devices; i++) {
-		cgpu = get_devices(i);
-
-		root = api_add_int(root, "DEVDETAILS", &i, false);
-		root = api_add_device_identifier(root, cgpu);
-		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);
-
-		root = print_data(root, buf, isjson, isjson && (i > 0));
-		io_add(io_data, buf);
+		if (cgpu->device == cgpu || per_proc)
+			notifystatus(io_data, n++, cgpu, isjson, group);
 	}
 
 	if (isjson && io_open)
@@ -3253,7 +3329,7 @@ struct CMDS {
 	{ "config",		minerconfig,	false },
 	{ "devscan",		devscan,	false },
 	{ "devs",		devstatus,	false },
-	{ "devdetail",	devdetail,	false },
+	{ "procs",		devstatus,	false },
 	{ "pools",		poolstatus,	false },
 	{ "summary",		summary,	false },
 #ifdef HAVE_OPENCL
@@ -3267,6 +3343,10 @@ struct CMDS {
 	{ "pgaenable",		pgaenable,	true },
 	{ "pgadisable",		pgadisable,	true },
 	{ "pgaidentify",	pgaidentify,	true },
+	{ "proc",		pgadev,		false },
+	{ "procenable",		pgaenable,	true },
+	{ "procdisable",		pgadisable,	true },
+	{ "procidentify",	pgaidentify,	true },
 #endif
 #ifdef WANT_CPUMINE
 	{ "cpuenable",		cpuenable,	true },
@@ -3276,6 +3356,7 @@ struct CMDS {
 #endif
 	{ "gpucount",		gpucount,	false },
 	{ "pgacount",		pgacount,	false },
+	{ "proccount",		pgacount,	false },
 	{ "cpucount",		cpucount,	false },
 	{ "switchpool",		switchpool,	true },
 	{ "addpool",		addpool,	true },
@@ -3294,7 +3375,9 @@ struct CMDS {
 	{ "quit",		doquit,		true },
 	{ "privileged",		privileged,	true },
 	{ "notify",		notify,		false },
-	{ "devdetails",		devdetails,	false },
+	{ "procnotify",		notify,		false },
+	{ "devdetails",		devdetail,	false },
+	{ "procdetails",		devdetail,	false },
 	{ "restart",		dorestart,	true },
 	{ "stats",		minerstats,	false },
 	{ "check",		checkcommand,	false },
@@ -3304,6 +3387,7 @@ struct CMDS {
 	{ "setconfig",		setconfig,	true },
 #ifdef HAVE_AN_FPGA
 	{ "pgaset",		pgaset,		true },
+	{ "procset",		pgaset,		true },
 #endif
 	{ "zero",		dozero,		true },
 	{ NULL,			NULL,		false }
@@ -4083,7 +4167,10 @@ void api(int api_thr_id)
 						if (strcmp(cmd, cmds[i].name) == 0) {
 							sprintf(cmdbuf, "|%s|", cmd);
 							if (ISPRIVGROUP(group) || strstr(COMMANDS(group), cmdbuf))
+							{
+								per_proc = !strncmp(cmds[i].name, "proc", 4);
 								(cmds[i].func)(io_data, c, param, isjson, group);
+							}
 							else {
 								message(io_data, MSG_ACCDENY, 0, cmds[i].name, isjson);
 								applog(LOG_DEBUG, "API: access denied to '%s' for '%s' command", connectaddr, cmds[i].name);

+ 1 - 0
miner.h

@@ -226,6 +226,7 @@ enum alive {
 	LIFE_WAIT,
 	LIFE_INIT2,  // Still initializing, but safe to call functions
 	LIFE_DEAD2,  // Totally dead, NOT safe to call functions
+	LIFE_MIXED,  // Only valid in display variables, NOT on devices
 };
 
 

+ 11 - 0
miner.php

@@ -12,6 +12,7 @@ global $ignorerefresh, $changerefresh, $autorefresh;
 global $allowcustompages, $customsummarypages;
 global $miner_font_family, $miner_font_size;
 global $colouroverride, $placebuttons, $userlist;
+global $per_proc;
 #
 # See README.RPC for more details of these variables and how
 # to configure miner.php
@@ -26,6 +27,9 @@ $readonly = false;
 # Set $userlist to null to allow anyone access or read README.RPC
 $userlist = null;
 #
+# Set $per_proc to false to display only full device summaries
+$per_proc = true;
+#
 # 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;
@@ -531,6 +535,13 @@ function api($rig, $cmd)
 {
  global $haderror, $error;
  global $miner, $port, $hidefields;
+ global $per_proc;
+
+ if ($per_proc)
+ {
+	$cmd = preg_replace('/^devs\b/', 'procs', $cmd);
+	$cmd = preg_replace('/^pga/', 'proc', $cmd);
+ }
 
  $socket = getsock($rig, $miner, $port);
  if ($socket != null)