Commit 8e82c24a5d391e7a4d14b37d9ffac7003bfb5b9c

Kano 2012-08-23T12:38:29

Merge branch 'minerphp'

diff --git a/API-README b/API-README
index 5ab1c72..d4efaf6 100644
--- a/API-README
+++ b/API-README
@@ -42,7 +42,7 @@ To give an IP address/subnet access to a group you use the group letter
 in front of the IP address instead of W: e.g. P:192.168.0/32
 An IP address/subnet can only be a member of one group
 A sample API group would be:
- --api-groups P:switchpool:enablepool:addpool:disablepool:removepool.poolpriority:*
+ --api-groups P:switchpool:enablepool:addpool:disablepool:removepool:poolpriority:*
 This would create a group 'P' that can do all current pool commands and all
 non-priviliged commands - the '*' means all non-priviledged commands
 Without the '*' the group would only have access to the pool commands
@@ -339,7 +339,7 @@ miner.php - an example web page to access the API
 Feature Changelog for external applications using the API:
 
 
-API V1.17
+API V1.17 (cgminer v2.7.1)
 
 Added API commands:
  'coin'
@@ -755,6 +755,31 @@ Below is each variable that can be changed and an explanation of each
 ---------
 
 Default:
+ $dfmt = 'H:i:s j-M-Y \U\T\CP';
+
+Define the date format used to print full length dates
+If you get the string 'UTCP' on the end of your dates shown, that
+means you are using an older version of PHP and you can instead use:
+ $dfmt = 'H:i:s j-M-Y \U\T\CO';
+
+The PHP documentation on the date format is here:
+ http://us.php.net/manual/en/function.date.php
+
+---------
+
+Default:
+ $title = 'Mine';
+
+Web page title
+If you know PHP you can of course use code to define it e.g.
+ $title = 'My Rig at: '.date($dfmt);
+
+Which would set the web page title to something like:
+ My Rig at: 10:34:00 22-Aug-2012 UTC+10:00
+
+---------
+
+Default:
  $readonly = false;
 
 Set $readonly to true to force miner.php to be readonly
@@ -957,7 +982,7 @@ The section defines what data you want in the summary table and the Fields
 define what data you want shown from that section
 
 Standard sections are:
- SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG, DEVDETAILS, DEVS, STATS
+ SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG, DEVDETAILS, DEVS, STATS, COIN
 
 Fields are the names as shown on the headers on the normal pages
 
@@ -966,6 +991,7 @@ Fields can be 'name=new name' to display 'name' with a different heading
 
 There are also now joined sections:
  SUMMARY+POOL, SUMMARY+DEVS, SUMMARY+CONFIG, DEVS+NOTIFY, DEVS+DEVDETAILS
+ SUMMARY+COIN
 
 These sections are an SQL join of the two sections and the fields in them
 are named section.field where section. is the section the field comes from
@@ -976,11 +1002,11 @@ Also note:
 - empty columns (e.g. an unknown field) are not shown
 - missing field data shows as blank
 - the field name '*' matches all fields except in joined sections
-  (useful for STATS)
+  (useful for STATS and COIN)
 
 There are 2 hard coded sections:
- DATE - displays a date table like 'Summary'
- RIGS - displays a rig table like 'Summary'
+ DATE - displays a date table like at the start of 'Summary'
+ RIGS - displays a rig table like at the start of 'Summary'
 
 Each custom summary requires a second array, that can be empty, listing fields
 to be totaled for each section
@@ -1037,7 +1063,7 @@ Each table will have the chosen details for all the rigs specified in $rigs
 	section.fieldname, not just fieldname
 
 	The join code automatically adds 2 fields to each GPU device: 'Name' and 'ID'
-	They don't exist in the API 'devs' output but you can correctly calculate
+	They don't exist in the API 'devs' output but I can correctly calculate
 	them from the GPU device data
 	These two fields are used to join DEVS to NOTIFY i.e. find the NOTIFY
 	record that has the same Name and ID as the DEVS record and join them
diff --git a/FPGA-README b/FPGA-README
index 0c4da8a..5688c78 100644
--- a/FPGA-README
+++ b/FPGA-README
@@ -1,6 +1,7 @@
 
 This README contains extended details about FPGA mining with cgminer
 
+
 Bitforce
 
 --bfl-range         Use nonce range on bitforce devices if supported
@@ -13,6 +14,28 @@ a cost of 1% in overall hashrate so this feature is disabled by default. It
 is only recommended you enable this if you are mining with a minirig on
 p2pool.
 
+C source is included for a bitforce firmware flash utility on Linux only:
+ bitforce-firmware-flash.c
+Using this, you can change the bitstream firmware on bitforce singles.
+It is untested with other devices. Use at your own risk!
+
+To compile:
+ make bitforce-firmware-flash
+To flash your BFL, specify the BFL port and the flash file e.g.:
+ sudo ./bitforce-firmware-flash /dev/ttyUSB0 alphaminer_832.bfl
+It takes a bit under 3 minutes to flash a BFL and shows a progress % counter
+Once it completes, you may also need to wait about 15 seconds,
+then power the BFL off and on again
+
+If you get an error at the end of the BFL flash process stating:
+ "Error reading response from ZBX"
+it may have worked successfully anyway.
+Test mining on it to be sure if it worked or not.
+
+You need to give cgminer about 10 minutes mining with the BFL to be sure of
+the MH/s value reported with the changed firmware - and the MH/s reported
+will be less than the firmware speed since you lose work on every block change.
+
 
 Icarus
 
diff --git a/Makefile.am b/Makefile.am
index d938910..e37abf4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,8 @@ endif
 EXTRA_DIST	= example.conf m4/gnulib-cache.m4 linux-usb-cgminer \
 		  ADL_SDK/readme.txt api-example.php miner.php	\
 		  API.class API.java api-example.c windows-build.txt \
-		  bitstreams/* API-README FPGA-README SCRYPT-README
+		  bitstreams/* API-README FPGA-README SCRYPT-README \
+		  bitforce-firmware-flash.c
 
 SUBDIRS		= lib compat ccan
 
diff --git a/bitforce-firmware-flash.c b/bitforce-firmware-flash.c
new file mode 100644
index 0000000..b4f6aca
--- /dev/null
+++ b/bitforce-firmware-flash.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012 Luke Dashjr
+ *
+ * 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.
+ */
+
+#define _BSD_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libgen.h>
+#include <arpa/inet.h>
+
+#define BFL_FILE_MAGIC   "BFLDATA"
+#define BFL_UPLOAD_MAGIC "NGH-STREAM"
+
+#define myassert(expr, n, ...) \
+do {  \
+	if (!(expr)) {  \
+		fprintf(stderr, __VA_ARGS__);  \
+		return n;  \
+	}  \
+} while(0)
+
+#define ERRRESP(buf)  buf, (buf[strlen(buf)-1] == '\n' ? "" : "\n")
+
+#define WAITFOROK(n, msg) \
+do {  \
+	myassert(fgets(buf, sizeof(buf), BFL), n, "Error reading response from " msg "\n");  \
+	myassert(!strcmp(buf, "OK\n"), n, "Invalid response from " msg ": %s%s", ERRRESP(buf));  \
+} while(0)
+
+int main(int argc, char**argv)
+{
+	myassert(argc == 3, 1, "Usage: %s <serialdev> <firmware.bfl>\n", argv[0]);
+	setbuf(stdout, NULL);
+	
+	// Check filename
+	char *FWname = basename(strdup(argv[2]));
+	size_t FWnameLen = strlen(FWname);
+	myassert(FWnameLen <= 255, 0x0f, "Firmware filename '%s' is too long\n", FWname);
+	uint8_t n8 = FWnameLen;
+	
+	// Open and check firmware file
+	FILE *FW = fopen(argv[2], "r");
+	myassert(FW, 0x10, "Failed to open '%s' for reading\n", argv[2]);
+	char buf[0x20];
+	myassert(1 == fread(buf, 7, 1, FW), 0x10, "Failed to read from '%s'\n", argv[2]);
+	myassert(!memcmp(buf, BFL_FILE_MAGIC, sizeof(BFL_FILE_MAGIC)-1), 0x11, "'%s' doesn't look like a BFL firmware\n", argv[2]);
+	myassert(!fseek(FW, 0, SEEK_END), 0x12, "Failed to find end of '%s'\n", argv[2]);
+	long FWlen = ftell(FW);
+	myassert(FWlen > 0, 0x12, "Couldn't get size of '%s'\n", argv[2]);
+	myassert(!fseek(FW, 7, SEEK_SET), 0x12, "Failed to rewind firmware file after getting size\n");
+	FWlen -= 7;
+	printf("Firmware file looks OK :)\n");
+	
+	// Open device
+	FILE *BFL = fopen(argv[1], "r+");
+	myassert(BFL, 0x20, "Failed to open '%s' for read/write\n", argv[1]);
+	myassert(!setvbuf(BFL, NULL, _IOFBF, 1032), 0x21, "Failed to setup buffer for device");
+	
+	// ZAX: Start firmware upload
+	printf("Starting firmware upload... ");
+	myassert(1 == fwrite("ZAX", 3, 1, BFL), 0x22, "Failed to issue ZAX command\n");
+	WAITFOROK(0x22, "ZAX");
+	
+	// Firmware upload header
+	myassert(1 == fwrite(BFL_UPLOAD_MAGIC, sizeof(BFL_UPLOAD_MAGIC)-1, 1, BFL), 0x23, "Failed to send firmware upload header (magic)\n");
+	uint32_t n32 = htonl(FWlen - FWlen / 6);
+	myassert(1 == fwrite(&n32, sizeof(n32), 1, BFL), 0x23, "Failed to send firmware upload header (size)\n");
+	myassert(1 == fwrite("\0\0", 2        , 1, BFL), 0x23, "Failed to send firmware upload header (padding 1)\n");
+	myassert(1 == fwrite(&n8, sizeof(n8)  , 1, BFL), 0x23, "Failed to send firmware upload header (filename length)\n");
+	myassert(1 == fwrite(FWname, n8       , 1, BFL), 0x23, "Failed to send firmware upload header (filename)\n");
+	myassert(1 == fwrite("\0>>>>>>>>", 9  , 1, BFL), 0x23, "Failed to send firmware upload header (padding 2)\n");
+	WAITFOROK(0x23, "firmware upload header");
+	printf("OK, sending...\n");
+	
+	// Actual firmware upload
+	long i, j;
+	for (i = 0, j = 0; i < FWlen; ++i) {
+		myassert(1 == fread(&n8, sizeof(n8), 1, FW), 0x30, "Error reading data from firmware file\n");
+		if (5 == i % 6)
+			continue;
+		n8 ^= 0x2f;
+		myassert(1 == fwrite(&n8, sizeof(n8), 1, BFL), 0x31, "Error sending data to device\n");
+		if (!(++j % 0x400)) {
+			myassert(1 == fwrite(">>>>>>>>", 8, 1, BFL), 0x32, "Error sending block-finish to device\n");
+			printf("\r%5.2f%% complete", (double)i * 100. / (double)FWlen);
+			WAITFOROK(0x32, "block-finish");
+		}
+	}
+	printf("\r100%% complete :)\n");
+	myassert(1 == fwrite(">>>>>>>>", 8, 1, BFL), 0x3f, "Error sending upload-finished to device\n");
+	myassert(fgets(buf, sizeof(buf), BFL), 0x3f, "Error reading response from upload-finished\n");
+	myassert(!strcmp(buf, "DONE\n"), 0x3f, "Invalid response from upload-finished: %s%s", ERRRESP(buf));
+
+	// ZBX: Finish programming
+	printf("Waiting for device... ");
+	myassert(1 == fwrite("ZBX", 3, 1, BFL), 0x40, "Failed to issue ZBX command\n");
+	WAITFOROK(0x40, "ZBX");
+	printf("All done! Try mining to test the flash succeeded.\n");
+
+	return 0;
+}
diff --git a/miner.php b/miner.php
index 52d2d14..198f0cf 100644
--- a/miner.php
+++ b/miner.php
@@ -762,6 +762,7 @@ function fmt($section, $name, $value, $when, $alldata)
 			$class = $warnclass;
 		break;
 	case 'STATUS.When':
+	case 'COIN.Current Block Time':
 		$ret = date($dfmt, $value);
 		break;
 	case 'BUTTON.Rig':
@@ -1457,7 +1458,8 @@ $sectionmap = array(
 	'NOTIFY' => 'notify',
 	'DEVDETAILS' => 'devdetails',
 	'STATS' => 'stats',
-	'CONFIG' => 'config');
+	'CONFIG' => 'config',
+	'COIN' => 'coin');
 #
 function joinfields($section1, $section2, $join, $results)
 {
@@ -1592,6 +1594,7 @@ function joinsections($sections, $results, $errors)
 				case 'POOL':
 				case 'DEVS':
 				case 'CONFIG':
+				case 'COIN':
 					$sectionmap[$section] = $section;
 					$results[$section] = joinall($both[0], $both[1], $results);
 					break;