Commit 9487ba05cdbed2f9135ab030e91b2a06cc4cbbfb

Kano 2012-09-04T12:52:11

API/BFL identify a device - currently only BFL to flash the led

diff --git a/API-README b/API-README
index 4f812c1..8a686fc 100644
--- a/API-README
+++ b/API-README
@@ -259,6 +259,22 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               stating the results of the disable request
                               This is only available if PGA mining is enabled
 
+ pgaidentify|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
+                              and currently only BFL singles support this command
+                              On a BFL single it will flash the led on the front
+                              of the device for appoximately 4s
+                              All other non BFL PGA devices will return an error
+                              status message stating that they dont support it
+                              This adds a 4s delay to the BFL share being processed
+                              so you may get a message stating that procssing took
+                              longer than 7000ms if the request was sent towards
+                              the end of the timing of any work being worked on
+                              e.g.: BFL0: took 8438ms - longer than 7000ms
+                              You should ignore this
+
  devdetails    DEVDETAILS     Each device with a list of their static details
                               This lists all devices including those not supported
                               by the 'devs' command
@@ -359,6 +375,7 @@ API V1.19
 
 Added API commands:
  'debug'
+ 'pgaidentify|N'
 
 Modified API commands:
  Change pool field name 'Diff1 Shares' to 'Diff1 Work'
diff --git a/api.c b/api.c
index a812381..839ea66 100644
--- a/api.c
+++ b/api.c
@@ -393,6 +393,8 @@ static const char *JSON_PARAMETER = "parameter";
 #define MSG_FOO 77
 #define MSG_MINECOIN 78
 #define MSG_DEBUGSET 79
+#define MSG_PGAIDENT 80
+#define MSG_PGANOID 81
 
 enum code_severity {
 	SEVERITY_ERR,
@@ -547,6 +549,10 @@ struct CODES {
  { SEVERITY_SUCC,  MSG_FOO,	PARAM_BOOL,	"Failover-Only set to %s" },
  { SEVERITY_SUCC,  MSG_MINECOIN,PARAM_NONE,	"CGMiner coin" },
  { SEVERITY_SUCC,  MSG_DEBUGSET,PARAM_STR,	"Debug settings" },
+#ifdef HAVE_AN_FPGA
+ { SEVERITY_SUCC,  MSG_PGAIDENT,PARAM_PGA,	"Identify command sent to PGA%d" },
+ { SEVERITY_ERR,   MSG_PGANOID,	PARAM_PGA,	"PGA%d does not support identify" },
+#endif
  { SEVERITY_FAIL, 0, 0, NULL }
 };
 
@@ -1700,6 +1706,44 @@ static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __
 
 	strcpy(io_buffer, message(MSG_PGADIS, id, NULL, isjson));
 }
+
+static void pgaidentify(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+{
+	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;
+	}
+
+	int dev = pgadevice(id);
+	if (dev < 0) { // Should never happen
+		strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson));
+		return;
+	}
+
+	struct cgpu_info *cgpu = devices[dev];
+	struct device_api *api = cgpu->api;
+
+	if (!api->identify_device)
+		strcpy(io_buffer, message(MSG_PGANOID, id, NULL, isjson));
+	else {
+		api->identify_device(cgpu);
+		strcpy(io_buffer, message(MSG_PGAIDENT, id, NULL, isjson));
+	}
+}
 #endif
 
 #ifdef WANT_CPUMINE
@@ -2888,6 +2932,7 @@ struct CMDS {
 	{ "pga",		pgadev,		false },
 	{ "pgaenable",		pgaenable,	true },
 	{ "pgadisable",		pgadisable,	true },
+	{ "pgaidentify",	pgaidentify,	true },
 #endif
 #ifdef WANT_CPUMINE
 	{ "cpu",		cpudev,		false },
diff --git a/driver-bitforce.c b/driver-bitforce.c
index 64cc51a..c1107fe 100644
--- a/driver-bitforce.c
+++ b/driver-bitforce.c
@@ -99,6 +99,7 @@ static bool bitforce_detect_one(const char *devpath)
 	}
 
 	BFwrite(fdDev, "ZGX", 3);
+	pdevbuf[0] = '\0';
 	BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 	if (unlikely(!pdevbuf[0])) {
 		applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)");
@@ -309,6 +310,7 @@ void bitforce_init(struct cgpu_info *bitforce)
 
 	do {
 		BFwrite(fdDev, "ZGX", 3);
+		pdevbuf[0] = '\0';
 		BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 
 		if (unlikely(!pdevbuf[0])) {
@@ -338,6 +340,37 @@ void bitforce_init(struct cgpu_info *bitforce)
 	mutex_unlock(&bitforce->device_mutex);
 }
 
+static void bitforce_flash_led(struct cgpu_info *bitforce)
+{
+	int fdDev = bitforce->device_fd;
+
+	if (!fdDev)
+		return;
+
+	/* Do not try to flash the led if we're polling for a result to
+	 * minimise the chance of interleaved results */
+	if (bitforce->polling)
+		return;
+
+	/* It is not critical flashing the led so don't get stuck if we
+	 * can't grab the mutex here */
+	if (mutex_trylock(&bitforce->device_mutex))
+		return;
+
+	BFwrite(fdDev, "ZMX", 3);
+
+	/* Once we've tried - don't do it until told to again */
+	bitforce->flash_led = false;
+
+	/* However, this stops anything else getting a reply
+	 * So best to delay any other access to the BFL */
+	sleep(4);
+
+	mutex_unlock(&bitforce->device_mutex);
+
+	return; // nothing is returned by the BFL
+}
+
 static bool bitforce_get_temp(struct cgpu_info *bitforce)
 {
 	int fdDev = bitforce->device_fd;
@@ -348,16 +381,23 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
 		return false;
 
 	/* Do not try to get the temperature if we're polling for a result to
-	 * minimise the change of interleaved results */
+	 * minimise the chance of interleaved results */
 	if (bitforce->polling)
 		return true;
 
-	/* It is not critical getting temperature so don't get stuck if  we
+	// Flash instead of Temp - doing both can be too slow
+	if (bitforce->flash_led) {
+		bitforce_flash_led(bitforce);
+ 		return true;
+	}
+
+	/* It is not critical getting temperature so don't get stuck if we
 	 * can't grab the mutex here */
 	if (mutex_trylock(&bitforce->device_mutex))
 		return false;
 
 	BFwrite(fdDev, "ZLX", 3);
+	pdevbuf[0] = '\0';
 	BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 	mutex_unlock(&bitforce->device_mutex);
 	
@@ -414,6 +454,7 @@ re_send:
 		BFwrite(fdDev, "ZPX", 3);
 	else
 		BFwrite(fdDev, "ZDX", 3);
+	pdevbuf[0] = '\0';
 	BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 	if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) {
 		mutex_unlock(&bitforce->device_mutex);
@@ -453,6 +494,7 @@ re_send:
 		BFwrite(fdDev, ob, 68);
 	}
 
+	pdevbuf[0] = '\0';
 	BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 	mutex_unlock(&bitforce->device_mutex);
 
@@ -496,6 +538,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
 
 		mutex_lock(&bitforce->device_mutex);
 		BFwrite(fdDev, "ZFX", 3);
+		pdevbuf[0] = '\0';
 		BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 		mutex_unlock(&bitforce->device_mutex);
 
@@ -640,6 +683,11 @@ static bool bitforce_get_stats(struct cgpu_info *bitforce)
 	return bitforce_get_temp(bitforce);
 }
 
+static void bitforce_identify(struct cgpu_info *bitforce)
+{
+	bitforce->flash_led = true;
+}
+
 static bool bitforce_thread_init(struct thr_info *thr)
 {
 	struct cgpu_info *bitforce = thr->cgpu;
@@ -676,6 +724,7 @@ struct device_api bitforce_api = {
 	.reinit_device = bitforce_init,
 	.get_statline_before = get_bitforce_statline_before,
 	.get_stats = bitforce_get_stats,
+	.identify_device = bitforce_identify,
 	.thread_prepare = bitforce_thread_prepare,
 	.thread_init = bitforce_thread_init,
 	.scanhash = bitforce_scanhash,
diff --git a/miner.h b/miner.h
index 7234cf6..6ac8d93 100644
--- a/miner.h
+++ b/miner.h
@@ -239,6 +239,7 @@ struct device_api {
 	void (*get_statline)(char*, struct cgpu_info*);
 	struct api_data *(*get_api_stats)(struct cgpu_info*);
 	bool (*get_stats)(struct cgpu_info*);
+	void (*identify_device)(struct cgpu_info*); // e.g. to flash a led
 
 	// Thread-specific functions
 	bool (*thread_prepare)(struct thr_info*);
@@ -337,6 +338,7 @@ struct cgpu_info {
 	uint32_t nonces;
 	bool nonce_range;
 	bool polling;
+	bool flash_led;
 #endif
 	pthread_mutex_t		device_mutex;