bflsc28 - allow setting clock and volt from the API ascset command
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
diff --git a/API-README b/API-README
index 62d3c47..6f95526 100644
--- a/API-README
+++ b/API-README
@@ -443,6 +443,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
AVA+BTB opt=freq val=256 to 1024 - chip frequency
BTB opt=millivolts val=1000 to 1400 - corevoltage
MBA opt=reset val=0 to chipcount - reset a chip
+ BMA opt=volt val=0-9 opt=clock val=0-15
lcd LCD An all-in-one short status summary of the miner
e.g. Elapsed,GHS av,GHS 5m,GHS 5s,Temp,
diff --git a/driver-bflsc.c b/driver-bflsc.c
index 51d2196..6dcff7b 100644
--- a/driver-bflsc.c
+++ b/driver-bflsc.c
@@ -987,6 +987,70 @@ static void bflsc_flush_work(struct cgpu_info *bflsc)
flush_one_dev(bflsc, dev);
}
+static void bflsc_set_volt(struct cgpu_info *bflsc, int dev)
+{
+ struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
+ char buf[BFLSC_BUFSIZ+1];
+ char msg[16];
+ int err, amount;
+ bool sent;
+
+ // Device is gone
+ if (bflsc->usbinfo.nodev)
+ return;
+
+ snprintf(msg, sizeof(msg), "V%dX", sc_info->volt_next);
+
+ mutex_lock(&bflsc->device_mutex);
+
+ err = send_recv_ss(bflsc, dev, &sent, &amount,
+ msg, strlen(msg), C_SETVOLT,
+ buf, sizeof(buf)-1, C_REPLYSETVOLT, READ_NL);
+ mutex_unlock(&(bflsc->device_mutex));
+
+ if (!sent)
+ bflsc_applog(bflsc, dev, C_SETVOLT, amount, err);
+ else {
+ // Don't care
+ }
+
+ sc_info->volt_next_stat = false;
+
+ return;
+}
+
+static void bflsc_set_clock(struct cgpu_info *bflsc, int dev)
+{
+ struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
+ char buf[BFLSC_BUFSIZ+1];
+ char msg[16];
+ int err, amount;
+ bool sent;
+
+ // Device is gone
+ if (bflsc->usbinfo.nodev)
+ return;
+
+ snprintf(msg, sizeof(msg), "F%dX", sc_info->clock_next);
+
+ mutex_lock(&bflsc->device_mutex);
+
+ err = send_recv_ss(bflsc, dev, &sent, &amount,
+ msg, strlen(msg), C_SETCLOCK,
+ buf, sizeof(buf)-1, C_REPLYSETCLOCK, READ_NL);
+ mutex_unlock(&(bflsc->device_mutex));
+
+ if (!sent)
+ bflsc_applog(bflsc, dev, C_SETCLOCK, amount, err);
+ else {
+ // Don't care
+ }
+
+ sc_info->clock_next_stat = false;
+
+ return;
+}
+
static void bflsc_flash_led(struct cgpu_info *bflsc, int dev)
{
struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
@@ -1076,6 +1140,14 @@ static bool bflsc_get_temp(struct cgpu_info *bflsc, int dev)
return false;
}
+ if (sc_info->volt_next_stat || sc_info->clock_next_stat) {
+ if (sc_info->volt_next_stat)
+ bflsc_set_volt(bflsc, dev);
+ if (sc_info->clock_next_stat)
+ bflsc_set_clock(bflsc, dev);
+ return true;
+ }
+
// Flash instead of Temp
if (sc_info->flash_led) {
bflsc_flash_led(bflsc, dev);
@@ -2087,6 +2159,61 @@ static bool bflsc_get_stats(struct cgpu_info *bflsc)
return allok;
}
+static char *bflsc_set(struct cgpu_info *bflsc, char *option, char *setting, char *replybuf)
+{
+ struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
+ int val;
+
+ if (sc_info->ident != IDENT_BMA) {
+ strcpy(replybuf, "no set options available");
+ return replybuf;
+ }
+
+ if (strcasecmp(option, "help") == 0) {
+ sprintf(replybuf, "volt: range 0-9 clock: range 0-15");
+ return replybuf;
+ }
+
+ if (strcasecmp(option, "volt") == 0) {
+ if (!setting || !*setting) {
+ sprintf(replybuf, "missing volt setting");
+ return replybuf;
+ }
+
+ val = atoi(setting);
+ if (val < 0 || val > 9) {
+ sprintf(replybuf, "invalid volt: '%s' valid range 0-9",
+ setting);
+ }
+
+ sc_info->volt_next = val;
+ sc_info->volt_next_stat = true;
+
+ return NULL;
+ }
+
+ if (strcasecmp(option, "clock") == 0) {
+ if (!setting || !*setting) {
+ sprintf(replybuf, "missing clock setting");
+ return replybuf;
+ }
+
+ val = atoi(setting);
+ if (val < 0 || val > 15) {
+ sprintf(replybuf, "invalid clock: '%s' valid range 0-15",
+ setting);
+ }
+
+ sc_info->clock_next = val;
+ sc_info->clock_next_stat = true;
+
+ return NULL;
+ }
+
+ sprintf(replybuf, "Unknown option: %s", option);
+ return replybuf;
+}
+
static void bflsc_identify(struct cgpu_info *bflsc)
{
struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
@@ -2225,6 +2352,7 @@ struct device_drv bflsc_drv = {
.get_api_stats = bflsc_api_stats,
.get_statline_before = get_bflsc_statline_before,
.get_stats = bflsc_get_stats,
+ .set_device = bflsc_set,
.identify_device = bflsc_identify,
.thread_prepare = bflsc_thread_prepare,
.thread_init = bflsc_thread_init,
diff --git a/driver-bflsc.h b/driver-bflsc.h
index 6431ba2..4778993 100644
--- a/driver-bflsc.h
+++ b/driver-bflsc.h
@@ -156,6 +156,11 @@ struct bflsc_info {
struct bflsc_work *bworks;
uint64_t cortex_nonces[0x80];
uint64_t cortex_hw[0x80];
+
+ int volt_next;
+ bool volt_next_stat;
+ int clock_next;
+ bool clock_next_stat;
};
#define BFLSC_XLINKHDR '@'
diff --git a/usbutils.h b/usbutils.h
index 993977b..dfb987c 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -292,6 +292,8 @@ struct cg_usb_info {
USB_ADD_COMMAND(C_FINALPROGRAMSTATUS, "FinalProgramStatus") \
USB_ADD_COMMAND(C_SETCLOCK, "SetClock") \
USB_ADD_COMMAND(C_REPLYSETCLOCK, "ReplySetClock") \
+ USB_ADD_COMMAND(C_SETVOLT, "SetVolt") \
+ USB_ADD_COMMAND(C_REPLYSETVOLT, "ReplySetVolt") \
USB_ADD_COMMAND(C_REQUESTUSERCODE, "RequestUserCode") \
USB_ADD_COMMAND(C_GETUSERCODE, "GetUserCode") \
USB_ADD_COMMAND(C_REQUESTTEMPERATURE, "RequestTemperature") \