Browse Source

init commit2

jstefanop 8 years ago
parent
commit
df75c5dbc5
3 changed files with 489 additions and 231 deletions
  1. 374 172
      driver-futurebit.c
  2. 114 59
      lowl-vcom.c
  3. 1 0
      lowl-vcom.h

+ 374 - 172
driver-futurebit.c

@@ -23,38 +23,38 @@
 #include "lowlevel.h"
 #include "lowl-vcom.h"
 #include "util.h"
-
+#include <bwltc-commands.h>
 
 static const uint8_t futurebit_max_chips = 0x01;
-#define FUTUREBIT_DEFAULT_FREQUENCY  104
-#define FUTUREBIT_MIN_CLOCK          104
-#define FUTUREBIT_MAX_CLOCK          400
+#define FUTUREBIT_DEFAULT_FREQUENCY  600
+#define FUTUREBIT_MIN_CLOCK          384
+#define FUTUREBIT_MAX_CLOCK          1020
 // Number of seconds chip of 54 cores @ 352mhz takes to scan full range
-#define FUTUREBIT_HASH_SPEED         4090.0
+#define FUTUREBIT_HASH_SPEED         1130.0
 #define FUTUREBIT_MAX_NONCE          0xffffffff
 #define FUTUREBIT_READ_SIZE            8
-#define futurebit_max_clusters_per_chip  6
-#define futurebit_max_cores_per_cluster  9
-static const uint8_t futurebit_g_head[] = {
-    0xd4, 0x59, 0x2d, 0x01, 0x1d, 0x01, 0x8e, 0xa7, 0x4e, 0xbb, 0x17, 0xb8, 0x06, 0x6b, 0x2a, 0x75,
-    0x83, 0x99, 0xd5, 0xf1, 0x9b, 0x5c, 0x60, 0x73, 0xd0, 0x9b, 0x50, 0x0d, 0x92, 0x59, 0x82, 0xad,
-    0xc4, 0xb3, 0xed, 0xd3, 0x52, 0xef, 0xe1, 0x46, 0x67, 0xa8, 0xca, 0x9f, 0x27, 0x9f, 0x63, 0x30,
-    0xcc, 0xbb, 0xb9, 0x10, 0x3b, 0x9e, 0x3a, 0x53, 0x50, 0x76, 0x50, 0x52, 0x08, 0x1d, 0xdb, 0xae,
-    0x89, 0x8f, 0x1e, 0xf6, 0xb8, 0xc6, 0x4f, 0x3b, 0xce, 0xf7, 0x15, 0xf6,    0,    0,    0,    1,
-	   0,    0,    0,    1, 0x8e, 0xa7,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-	   0,    0,    0,    0,    0,    0,    0
+//#define futurebit_max_clusters_per_chip  6
+//#define futurebit_max_cores_per_cluster  9
+unsigned char job2[] = {
+0x3c, 0xff, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+0x07, 0x00, 0x00, 0x00, 0xd7, 0xa2, 0xea, 0xb0, 0xc2, 0xd7, 0x6f, 0x1e, 0x33, 0xa4, 0xb5, 0x3e,
+0x0e, 0xb2, 0x84, 0x34, 0x89, 0x5a, 0x8b, 0x10, 0xfb, 0x19, 0x7d, 0x76, 0xe6, 0xe0, 0x38, 0x60,
+0x15, 0x3f, 0x6a, 0x6e, 0x00, 0x00, 0x00, 0x04, 0xb5, 0x93, 0x93, 0x27, 0xf7, 0xc9, 0xfb, 0x26,
+0xdf, 0x3b, 0xde, 0xc0, 0xa6, 0x6c, 0xae, 0x10, 0xb5, 0x53, 0xb7, 0x61, 0x5d, 0x67, 0xa4, 0x97,
+0xe8, 0x7f, 0x06, 0xa6, 0x27, 0xfc, 0xd5, 0x57, 0x44, 0x38, 0xb8, 0x4d, 0xb1, 0xfe, 0x4f, 0x5f,
+0x31, 0xaa, 0x47, 0x3d, 0x3d, 0xb4, 0xfc, 0x03, 0xa2, 0x78, 0x92, 0x44, 0xa1, 0x39, 0xb0, 0x35,
+0xe1, 0x46, 0x04, 0x1e, 0x8c, 0x0a, 0xad, 0x28, 0x58, 0xec, 0x78, 0x3c, 0x1b, 0x00, 0xa4, 0x43
 };
 
 
+
 BFG_REGISTER_DRIVER(futurebit_drv)
 
 static const struct bfg_set_device_definition futurebit_set_device_funcs_probe[];
 
 struct futurebit_chip {
     uint8_t chipid;
-    uint8_t global_reg[8];
-    uint16_t chip_mask[futurebit_max_clusters_per_chip];
-    uint32_t clst_offset[futurebit_max_clusters_per_chip];
     unsigned active_cores;
     unsigned freq;
 };
@@ -64,10 +64,7 @@ void futurebit_chip_init(struct futurebit_chip * const chip, const uint8_t chipi
 {
     *chip = (struct futurebit_chip){
         .chipid = chipid,
-        .global_reg = {0, 4, 0x40, 0, 0, 0, 0, 1},
-        .chip_mask = {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-        .clst_offset = {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-        .active_cores = 54,
+        .active_cores = 64,
         .freq = FUTUREBIT_DEFAULT_FREQUENCY,
     };
 }
@@ -75,109 +72,239 @@ void futurebit_chip_init(struct futurebit_chip * const chip, const uint8_t chipi
 static
 void futurebit_reset_board(const int fd)
 {
- 
+
     if(set_serial_rts(fd, BGV_HIGH) == BGV_ERROR)
         applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
-    
-    cgsleep_ms(100);
-    
+
+    cgsleep_ms(1000);
+
     if(set_serial_rts(fd, BGV_LOW) == BGV_ERROR)
         applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
 }
 
+
+int futurebit_write(const int fd,  const void *buf, size_t buflen)
+{
+	int repeat = 0;
+	int size = 0;
+	int ret = 0;
+	int nwrite = 0;
+
+	char output[(buflen * 2) + 1];
+    bin2hex(output, buf, buflen);
+    applog(LOG_DEBUG, "WRITE BUFFER %s", output);
+
+	while(size < buflen)
+	{
+		nwrite = write(fd, buf, buflen);
+        //applog(LOG_DEBUG, "FutureBit Write SIZE: %u", nwrite);
+		if (nwrite < 0)
+		{
+			applog(LOG_ERR, "FutureBit Write error: %s", strerror(errno));
+			break;
+		}
+
+		size += nwrite;
+
+		if (repeat++ > 1)
+		{
+			break;
+		}
+
+	}
+
+	return 0;
+}
+
 static
-void futurebit_set_diag_mode(struct futurebit_chip * const chip, bool diag_enable)
+bool futurebit_read (const int fd, unsigned char *buf, int read_amount)
 {
-    if (diag_enable)
-        chip->global_reg[1] |= 1;
-    else
-        chip->global_reg[1] &= ~1;
+
+	ssize_t nread = 0;
+	int size = 0;
+	int repeat = 0;
+
+
+
+	while(size < read_amount)
+	{
+		nread = read(fd, buf, read_amount);
+		if(nread < 0)
+            return false;
+
+		size += nread;
+
+		//char output[(read_amount * 2) + 1];
+       // bin2hex(output, buf, read_amount);
+        //applog(LOG_DEBUG, "READ BUFFER %s", output);
+
+		if (repeat++ > 0)
+		{
+			break;
+		}
+	}
+
+#if 0
+	int i;
+	for (i=0; i<size; i++)
+	{
+		printf("0x%02x ", buf[i]);
+	}
+	printf("\n");
+#endif
+
+	return true;
 }
 
 static
-bool futurebit_write_global_reg(const int fd, const struct futurebit_chip * const chip)
+char futurebit_read_register(const int fd, uint32_t chip, uint32_t moudle, uint32_t RegAddr)
 {
-    uint8_t buf[112];
-    memset(&buf, 0, 102);
-    memcpy(&buf[102], &chip->global_reg[0], 8);
-    buf[110] = 0;
-    buf[111] = 0xff;
-    
-    if (write(fd, buf, sizeof(buf)) != sizeof(buf))
-        return false;
-    return true;
+	uint8_t read_reg_data[8]={0};
+	uint8_t read_reg_cmd[16]={0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0xc3};
+
+
+	read_reg_cmd[1] = chip;
+	read_reg_cmd[2] = moudle;
+	read_reg_cmd[3] = 0x80|RegAddr; //read
+
+
+	static int nonce=0;
+	futurebit_write(fd, read_reg_cmd, 9);
+
+
+	cgsleep_us(100000);
+	if(!futurebit_read(fd, read_reg_data, 8))
+        applog(LOG_DEBUG, "FutureBit read register fail");
+
+
+    applog(LOG_DEBUG, "FutureBit Read Return:");
+    for (int i=0; i<8; i++)
+		{
+			applog(LOG_DEBUG,"0x%02x ", read_reg_data[i]);
+		}
+    applog(LOG_DEBUG,"\n");
+
+    return read_reg_data[0];
+}
+
+unsigned
+int futurebit_write_register(const int fd, uint32_t chipId, uint32_t moudle, uint32_t Regaddr, uint32_t value)
+{
+	bool ret =true;
+	uint8_t read_reg_cmd[16]={0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0xc3};
+
+	read_reg_cmd[1] = chipId;
+	read_reg_cmd[2] = moudle;
+	read_reg_cmd[3] = 0x7f&Regaddr; //&0x7f->write\BF\BFbit[7]:1 read, 0 write
+	read_reg_cmd[4] = value&0xff;
+	read_reg_cmd[5] = (value>>8)&0xff;
+	read_reg_cmd[6] = (value>>16)&0xff;
+	read_reg_cmd[7] = (value>>24)&0xff;
+
+
+	futurebit_write(fd, read_reg_cmd, 9);
+
+	return  ret;
 }
 
 static
-bool futurebit_write_cluster_reg(const int fd, const struct futurebit_chip * const chip, const uint16_t cores_active, const uint32_t offset, const uint8_t clstid)
+void futurebit_send_cmds(const int fd, const unsigned char *cmds[])
 {
-    uint8_t buf[112];
-    memset(&buf, 0, 104);
-    pk_u16be(buf, 104, cores_active);
-    pk_u32be(buf, 106, offset);
-    buf[110] = clstid;
-    buf[111] = 0xfe;
-    //applog(LOG_DEBUG, " %u: %u: %u : %u", buf[106], buf[107], buf[108], buf[109]);
-    if (write(fd, buf, sizeof(buf)) != sizeof(buf))
-        return false;
-    return true;
+	int i;
+	for(i = 0; cmds[i] != NULL; i++)
+	{
+		futurebit_write(fd, cmds[i] + 1, cmds[i][0]);
+		cgsleep_us(10000);
+	}
 }
 
+//921600bps: 3C ff f8 20 1f 01 82 f6
+static
+void futurebit_set_baudrate(const int fd)
+{
+	const uint8_t cmd[] = {0x3C, 0xff, 0xf8, 0x20, 0x1f, 0x01, 0x82, 0xf6, 0xC3};
+	futurebit_write(fd, cmd, 9);
+	cgsleep_us(100000);
+	serial_change_baud(fd, 921600);
+}
 
 static
-bool futurebit_init_pll(const int fd, struct futurebit_chip * const chip)
+void futurebit_set_frequency(const int fd, uint32_t freq)
 {
-    unsigned freq = chip->freq;
-    uint8_t bytes1;
-    uint8_t bytes2;
-    uint8_t divider;
-    
-    if (freq <= 200){
-        divider = (freq - 8)/8;
-        divider <<= 1;
-        bytes1 = 0x70 | ((divider & 0xf0) >> 4);
-        bytes2 = 0x30 | ((divider & 0xf0) >> 4);
-        
-    }else {
-        divider = (freq - 16)/16;
-        divider <<= 1;
-        bytes1 = 0x60 | ((divider & 0xf0) >> 4);
-        bytes2 = 0x20 | ((divider & 0xf0) >> 4);
-    }
-    
-    uint8_t bytes3 = 0x00 | ((divider & 0x0f) << 4);
-    
-    pk_u16be(chip->global_reg, 2, 0x4000);
-    chip->global_reg[1] |= 0xc;
-    if (!futurebit_write_global_reg(fd, chip))
-        return false;
-    
-    chip->global_reg[2] = bytes1;
-    chip->global_reg[3] = bytes3;
-    cgsleep_ms(50);
-    if (!futurebit_write_global_reg(fd, chip))
-        return false;
-    
-    chip->global_reg[2] = bytes2;
-    chip->global_reg[1] &= ~8;
-    cgsleep_ms(50);
-    if (!futurebit_write_global_reg(fd, chip))
-        return false;
-    
-    chip->global_reg[1] &= ~4;
-    cgsleep_ms(50);
-    if (!futurebit_write_global_reg(fd, chip))
-        return false;
-    
-    return true;
+        struct frequecy *p;
+        unsigned char **cmd = cmd_set_600M;
+        int i;
+
+        for (i=0; i<ARRAY_LEN; i++)
+        {
+            if (fre_array[i].freq ==  freq)
+            {
+                cmd = fre_array[i].cmd;
+            }
+        }
+
+        futurebit_send_cmds(fd, cmd);
+
+}
+
+void futurebit_config_all_chip(const int fd, uint32_t freq)
+{
+	uint32_t reg_val;
+	int i;
+
+	futurebit_reset_board(fd);
+
+	futurebit_send_cmds(fd, cmd_auto_address);
+	cgsleep_us(100000);
+	//futurebit_set_baudrate(fd);
+	//cgsleep_us(100000);
+	futurebit_set_frequency(fd, freq);
+	cgsleep_us(100000);
+
+
+#if 1
+	futurebit_write_register(fd, 0xff, 0xf8,0x22,0x11090005);//feed through
+	cgsleep_us(100000);
+#endif
+
+	reg_val = 0xffffffff/futurebit_max_chips;
+	for (i=1; i<(futurebit_max_chips+1); i++)
+	{
+		futurebit_write_register(fd, i, 0x40, 0x00, reg_val*(i-1));
+		cgsleep_us(100000);
+	}
+
+	futurebit_send_cmds(fd, gcp_cmd_reset);
+	cgsleep_us(100000);
+
+
 }
 
+void futurebit_pull_up_payload(const int fd)
+{
+		char i;
+		unsigned int regval = 0;
+
+		//pull up payload by steps.
+        for (i=0; i<8; i++)
+        {
+            regval  |= (0x0f<<(4*i));
+            futurebit_write_register(fd, 0xff, 0xf8, 0x04, regval);
+            cgsleep_us(35000);
+            futurebit_write_register(fd, 0xff, 0xf8, 0x05, regval);
+            cgsleep_us(35000);
+            futurebit_write(fd, job2,144) ;
+            cgsleep_us(35000);
+        }
+}
+
+
 static
 bool futurebit_send_golden(const int fd, const struct futurebit_chip * const chip, const void * const data, const void * const target_p)
 {
     uint8_t buf[112];
     const uint8_t * const target = target_p;
-    
+
     memcpy(buf, data, 80);
     if (target && !target[0x1f])
         memcpy(&buf[80], target, 0x20);
@@ -186,11 +313,11 @@ bool futurebit_send_golden(const int fd, const struct futurebit_chip * const chi
         memset(&buf[80], 0xff, 0x1f);
         buf[111] = 0;
     }
-    
+
     //char output[(sizeof(buf) * 2) + 1];
     //bin2hex(output, buf, sizeof(buf));
     //applog(LOG_DEBUG, "GOLDEN OUTPUT %s", output);
-    
+
     if (write(fd, buf, sizeof(buf)) != sizeof(buf))
         return false;
     return true;
@@ -200,29 +327,83 @@ static
 bool futurebit_send_work(const struct thr_info * const thr, struct work * const work)
 {
     struct cgpu_info *device = thr->cgpu;
-    uint8_t buf[112];
+
+    uint32_t *pdata = work->data;
+    uint32_t *midstate = work->midstate;
+	const uint32_t *ptarget = work->target;
+
+    int i, bpos;
+    unsigned char bin[156];
+    // swab for big endian
+    uint32_t midstate2[8];
+    uint32_t data2[20];
+    uint32_t target2[8];
+    for(i = 0; i < 19; i++)
+    {
+        data2[i] = htole32(pdata[i]);
+        if(i >= 8) continue;
+        target2[i] = htole32(ptarget[i]);
+        midstate2[i] = htole32(midstate[i]);
+    }
+
+
+    data2[19] = 0;
+
+    memset(bin, 0, sizeof(bin));
+    bpos = 0;  memcpy(bin, "\x3c\xff\x40\x01", 4);
+   // bpos += 4;  memcpy(bin + bpos, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00", 32);     //target
+    bpos += 4;  memcpy(bin + bpos, (unsigned char *)target2, 32);  memset(bin + bpos, 0, 24);
+    bpos += 32; memcpy(bin + bpos, (unsigned char *)midstate2, 32);   //midstateno
+    bpos += 32; memcpy(bin + bpos, (unsigned char *)data2, 76);		 //blockheader 76 bytes (ignore last 4bytes nounce)
+    bpos += 76;
+
+   /* char szVal[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xff\x7f\x00\x00\x00fb357fbeda2ee2a93b841afac3e58173d4a97a400a84a4ec27c47ef5e9322ca620000000b99512c06534b34f62d0a88a5f90ac1857f0c02a1b6e6bb3185aec323b0eb79d2983a6d34c0e59272444dc28b1041e6114939ca8cdbd99f4058ef4965e293ba7598b98cc1a25e34f"; // source string
+
+    char szOutput[144];
+
+    size_t nLen = strlen(szVal);
+    // Make sure it is even.
+    if ((nLen % 2) == 1)
+    {
+        printf("Error string must be even number of digits %s", szVal);
+    }
+
+    // Process each set of characters as a single character.
+    nLen >>= 1;
+    for (size_t idx = 0; idx < nLen; idx++)
+    {
+        char acTmp[3];
+        sscanf(szVal + (idx << 1), "%2s", acTmp);
+        szOutput[idx] = (char)strtol(acTmp, NULL, 16);
+    }
+    */
+    futurebit_write(device->device_fd, bin, 144);//144bytes
+
+
+   /* uint8_t buf[112];
     uint8_t cmd[112];
     const uint8_t * const target = work->target;
-    
+
     unsigned char swpdata[80];
-    
+
     //buf[0] = 0;
     //memset(&buf[1], 0xff, 0x1f);
     memset(&buf[0], 0, 0x18);
     memcpy(&buf[24], &target[24], 0x8);
-    
+
     swap32tobe(swpdata, work->data, 80/4);
     memcpy(&buf[32], swpdata, 80);
-    
+
     for (int i = 0; i<112; i++) {
         cmd[i] = buf[111 - i];
     }
-    
+
     if (write(device->device_fd, cmd, sizeof(cmd)) != sizeof(cmd))
         return false;
-    
+
+*/
     work->blk.nonce = FUTUREBIT_MAX_NONCE;
-    
+
     return true;
 }
 
@@ -231,57 +412,68 @@ bool futurebit_detect_one(const char * const devpath)
 {
     struct futurebit_chip *chips = NULL;
     unsigned total_cores = 0;
-    
+    uint32_t  regval = 0;
+
     const int fd = serial_open(devpath, 115200, 1, true);
     if (fd < 0)
         return_via_applog(err, , LOG_DEBUG, "%s: %s %s", futurebit_drv.dname, "Failed to open", devpath);
-    
+
     applog(LOG_DEBUG, "%s: %s %s", futurebit_drv.dname, "Successfully opened", devpath);
-    
+
     futurebit_reset_board(fd);
-    
+
+    if(futurebit_read_register(fd, 0xff, 0xf8, 0xa6) != 0x3c)
+        return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "find chip", devpath);
+
+
+
     // Init chips, setup PLL, and scan for good cores
     chips = malloc(futurebit_max_chips * sizeof(*chips));
-    
+
     struct futurebit_chip * const dummy_chip = &chips[0];
     futurebit_chip_init(dummy_chip, 0);
-    
+
     // pick up any user-defined settings passed in via --set
     drv_set_defaults(&futurebit_drv, futurebit_set_device_funcs_probe, dummy_chip, devpath, detectone_meta_info.serial, 1);
-    
+
     unsigned freq = dummy_chip->freq;
-    
+
     applog(LOG_DEBUG, "%s: %s %u mhz", futurebit_drv.dname, "Core clock set to", freq);
-    
-    {
-        uint8_t buf[8];
-        for (unsigned i = 0; i < futurebit_max_chips; ++i)
-        {
-            struct futurebit_chip * const chip = &chips[i];
-            futurebit_chip_init(chip, i);
-            chip->freq = freq;
-            
+
+
+    struct futurebit_chip * const chip = &chips[0];
+    futurebit_chip_init(chip, 0);
+    chip->freq = freq;
+
+    futurebit_config_all_chip(fd, freq);
+
+    futurebit_pull_up_payload(fd);
+
             //chip->global_reg[1] = 0x05;
             //if (!futurebit_write_global_reg(fd, chip))
             //    return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "global", devpath);
             //cgsleep_ms(50);
-            futurebit_set_diag_mode(chip, true);
+
+
+
+
+            /*futurebit_set_diag_mode(chip, true);
             if (!futurebit_init_pll(fd, chip))
                 return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "init PLL", devpath);
             cgsleep_ms(50);
             if (!futurebit_send_golden(fd, chip, futurebit_g_head, NULL))
                 return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "send scan job", devpath);
-            
+
             while (serial_read(fd, buf, 8) == 8)
             {
-                
+
                 const uint8_t clsid = buf[7];
                 if (clsid >= futurebit_max_clusters_per_chip)
                     applog(LOG_DEBUG, "%s: Bad %s id (%u) during scan of %s chip %u", futurebit_drv.dname, "cluster", clsid, devpath, i);
                 const uint8_t coreid = buf[6];
                 if (coreid >= futurebit_max_cores_per_cluster)
                     applog(LOG_DEBUG, "%s: Bad %s id (%u) during scan of %s chip %u", futurebit_drv.dname, "core", coreid, devpath, i);
-                
+
                 if (buf[0] != 0xd9 || buf[1] != 0xeb || buf[2] != 0x86 || buf[3] != 0x63) {
                     //chips[i].chip_good[clsid][coreid] = false;
                     applog(LOG_DEBUG, "%s: Bad %s at core (%u) during scan of %s chip %u cluster %u", futurebit_drv.dname, "nonce", coreid, devpath, i, clsid);
@@ -292,24 +484,24 @@ bool futurebit_detect_one(const char * const devpath)
             }
         }
     }
-    
+
     applog(LOG_DEBUG, "%s: Identified %d cores on %s", futurebit_drv.dname, total_cores, devpath);
-    
+
     if (total_cores == 0)
         goto err;
-    
+
     futurebit_reset_board(fd);
-    
+
     // config nonce ranges per cluster based on core responses
     unsigned mutiple = FUTUREBIT_MAX_NONCE / total_cores;
     uint32_t n_offset = 0x00000000;
-    
+
     for (unsigned i = 0; i < futurebit_max_chips; ++i)
     {
         struct futurebit_chip * const chip = &chips[i];
-        
+
         chips[i].active_cores = total_cores;
-        
+
         //chip->global_reg[1] = 0x04;
         //if (!futurebit_write_global_reg(fd, chip))
         //return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "global", devpath);
@@ -318,33 +510,34 @@ bool futurebit_detect_one(const char * const devpath)
         if (!futurebit_init_pll(fd, chip))
             return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "init PLL", devpath);
         cgsleep_ms(50);
-        
+
         for (unsigned x = 0; x < futurebit_max_clusters_per_chip; ++x) {
             unsigned gc = 0;
-            
+
             uint16_t core_mask = chips[i].chip_mask[x];
             chips[i].clst_offset[x] = n_offset;
-            
+
             applog(LOG_DEBUG, "OFFSET %u MASK %u CHIP %u CLUSTER %u", n_offset, core_mask, i, x);
-            
+
             if (!futurebit_write_cluster_reg(fd, chip, core_mask, n_offset, x))
                 return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", futurebit_drv.dname, "send config register", devpath);
-            
+
             for (unsigned z = 0; z < 15; ++z) {
                 if (core_mask & 0x0001)
                     gc += 1;
                 core_mask >>= 1;
             }
-            
+
             n_offset += mutiple * gc;
-            
+
             cgsleep_ms(50);
         }
     }
-    
+    */
+
     if (serial_claim_v(devpath, &futurebit_drv))
         goto err;
-    
+
     //serial_close(fd);
     struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
     *cgpu = (struct cgpu_info){
@@ -357,9 +550,9 @@ bool futurebit_detect_one(const char * const devpath)
     };
     // NOTE: Xcode's clang has a bug where it cannot find fields inside anonymous unions (more details in fpgautils)
     cgpu->device_fd = fd;
-    
+
     return add_cgpu(cgpu);
-    
+
 err:
     if (fd >= 0)
         serial_close(fd);
@@ -376,29 +569,38 @@ void futurebit_submit_nonce(struct thr_info * const thr, const uint8_t buf[8], s
 {
     struct cgpu_info *device = thr->cgpu;
     struct futurebit_chip *chips = device->device_data;
-    
-    uint32_t nonce = *(uint32_t *)buf;
-    nonce = bswap_32(nonce);
-    
+
+    uint32_t nonce;
+
+    // swab for big endian
+    memcpy((unsigned char *)&nonce, buf+4, 4);
+    nonce = htole32(nonce);
+
+    char output[(8 * 2) + 1];
+    bin2hex(output, buf, 8);
+    applog(LOG_DEBUG, "NONCE %s", output);
+
     submit_nonce(thr, work, nonce);
-    
-    // hashrate calc
-    
+
+    /* hashrate calc
+
     const uint8_t clstid = buf[7];
     uint32_t range = chips[0].clst_offset[clstid];
 
     struct timeval now_tv;
     timer_set_now(&now_tv);
     int elapsed_ms = ms_tdiff(&now_tv, &start_tv);
-    
+
     double total_hashes = ((nonce - range)/9.0) * chips[0].active_cores;
     double hashes_per_ms = total_hashes/elapsed_ms;
     uint64_t hashes = hashes_per_ms * ms_tdiff(&now_tv, &thr->_tv_last_hashes_done_call);
-    
+
     if(hashes_per_ms < 1500 && hashes < 100000000)
         hashes_done2(thr, hashes, NULL);
     else
         hashes_done2(thr, 100000, NULL);
+
+        */
 }
 
 // send work to the device
@@ -409,46 +611,46 @@ int64_t futurebit_scanhash(struct thr_info *thr, struct work *work, int64_t __ma
     int fd = device->device_fd;
     struct futurebit_chip *chips = device->device_data;
     struct timeval start_tv, nonce_range_tv;
-    
+
     // amount of time it takes this device to scan a nonce range:
     uint32_t nonce_full_range_sec = FUTUREBIT_HASH_SPEED * 352.0 / FUTUREBIT_DEFAULT_FREQUENCY * 54.0 / chips[0].active_cores;
     // timer to break out of scanning should we close in on an entire nonce range
     // should break out before the range is scanned, so we are doing 95% of the range
     uint64_t nonce_near_range_usec = (nonce_full_range_sec * 1000000. * 0.95);
     timer_set_delay_from_now(&nonce_range_tv, nonce_near_range_usec);
-    
+
     // start the job
     timer_set_now(&start_tv);
-    
+
     if (!futurebit_send_work(thr, work)) {
         applog(LOG_DEBUG, "Failed to start job");
         dev_error(device, REASON_DEV_COMMS_ERROR);
     }
-    
-    uint8_t buf[8];
+
+    unsigned char buf[12];
     int read = 0;
     bool range_nearly_scanned = false;
-    
+
     while (!thr->work_restart                                              // true when new work is available (miner.c)
-           && ((read = serial_read(fd, buf, 8)) >= 0)                         // only check for failure - allow 0 bytes
+           && ((read = serial_read(fd, buf, 8)) >= 0)                       // only check for failure - allow 0 bytes
            && !(range_nearly_scanned = timer_passed(&nonce_range_tv, NULL)))  // true when we've nearly scanned a nonce range
     {
         if (read == 0)
             continue;
-        
+
         if (read == 8) {
             futurebit_submit_nonce(thr, buf, work, start_tv);
         }
         else
             applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
     }
-    
+
     if (read == -1)
     {
         applog(LOG_ERR, "%s: Failed to read result", device->dev_repr);
         dev_error(device, REASON_DEV_COMMS_ERROR);
     }
-    
+
     return 0;
 }
 
@@ -466,9 +668,9 @@ static
 void futurebit_thread_shutdown(struct thr_info *thr)
 {
     struct cgpu_info *device = thr->cgpu;
-    
+
     futurebit_reset_board(device->device_fd);
-    
+
     serial_close(device->device_fd);
 }
 
@@ -486,14 +688,14 @@ const char *futurebit_set_clock(struct cgpu_info * const device, const char * co
 {
     struct futurebit_chip * const chip = device->device_data;
     int val = atoi(setting);
-    
-    if (val < FUTUREBIT_MIN_CLOCK || val > FUTUREBIT_MAX_CLOCK || (val%8)) {
+
+    if (val < FUTUREBIT_MIN_CLOCK || val > FUTUREBIT_MAX_CLOCK ) {
         sprintf(replybuf, "invalid clock: '%s' valid range %d-%d. Clock must be a mutiple of 8 between 104-200mhz, and a mutiple of 16 between 208-400mhz",
                 setting, FUTUREBIT_MIN_CLOCK, FUTUREBIT_MAX_CLOCK);
         return replybuf;
     } else
         chip->freq = val;
-    
+
     return NULL;
 }
 
@@ -511,10 +713,10 @@ struct device_drv futurebit_drv = {
     .lowl_probe = futurebit_lowl_probe,
     // specify mining type - scanhash
     .minerloop = minerloop_scanhash,
-    
+
     // scanhash mining hooks
     .scanhash = futurebit_scanhash,
-    
+
     // teardown device
     .thread_shutdown = futurebit_thread_shutdown,
 };

+ 114 - 59
lowl-vcom.c

@@ -149,14 +149,14 @@ char *_decode_udev_enc_dup(const char *s)
 {
 	if (!s)
 		return NULL;
-	
+
 	char *o = malloc(strlen(s) + 1);
 	if (!o)
 	{
 		applog(LOG_ERR, "Failed to malloc in _decode_udev_enc_dup");
 		return NULL;
 	}
-	
+
 	_decode_udev_enc(o, s);
 	return o;
 }
@@ -182,11 +182,11 @@ void _vcom_devinfo_scan_udev(struct lowlevel_device_info ** const devinfo_list)
 
 		const char * const devpath = udev_device_get_devnode(device);
 		devinfo = _vcom_devinfo_findorcreate(devinfo_list, devpath);
-		
+
 		BFGINIT(devinfo->manufacturer, _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_VENDOR_ENC")));
 		BFGINIT(devinfo->product, _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_MODEL_ENC")));
 		BFGINIT(devinfo->serial, _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_SERIAL_SHORT")));
-		
+
 		udev_device_unref(device);
 	}
 	udev_enumerate_unref(enumerate);
@@ -313,7 +313,7 @@ void _vcom_devinfo_scan_devserial(struct lowlevel_device_info ** const devinfo_l
 	char devpath[sizeof(udevdir) + 1 + NAME_MAX];
 	char *devfile = devpath + sizeof(udevdir);
 	struct lowlevel_device_info *devinfo;
-	
+
 	D = opendir(udevdir);
 	if (!D)
 		return;
@@ -337,7 +337,7 @@ char *_sysfs_do_read(const char *devpath, char *devfile, const char *append)
 {
 	char buf[0x40];
 	FILE *F;
-	
+
 	strcpy(devfile, append);
 	F = fopen(devpath, "r");
 	if (F)
@@ -354,7 +354,7 @@ char *_sysfs_do_read(const char *devpath, char *devfile, const char *append)
 	}
 	else
 		buf[0] = '\0';
-	
+
 	return buf[0] ? strdup(buf) : NULL;
 }
 
@@ -366,11 +366,11 @@ void _sysfs_find_tty(char *devpath, char *devfile, struct lowlevel_device_info *
 	struct dirent *de;
 	char ttybuf[0x10] = "/dev/";
 	char *mydevfile = strdup(devfile);
-	
+
 	DT = opendir(devpath);
 	if (!DT)
 		goto out;
-	
+
 	while ( (de = readdir(DT)) )
 	{
 		if (strncmp(de->d_name, "tty", 3))
@@ -384,7 +384,7 @@ void _sysfs_find_tty(char *devpath, char *devfile, struct lowlevel_device_info *
 		}
 		if (strncmp(&de->d_name[3], "USB", 3) && strncmp(&de->d_name[3], "ACM", 3))
 			continue;
-		
+
 		strcpy(&ttybuf[5], de->d_name);
 		devinfo = _vcom_devinfo_findorcreate(devinfo_list, ttybuf);
 		if (!devinfo)
@@ -394,7 +394,7 @@ void _sysfs_find_tty(char *devpath, char *devfile, struct lowlevel_device_info *
 		BFGINIT(devinfo->serial, _sysfs_do_read(devpath, devfile, "/serial"));
 	}
 	closedir(DT);
-	
+
 out:
 	free(mydevfile);
 }
@@ -409,7 +409,7 @@ void _vcom_devinfo_scan_sysfs(struct lowlevel_device_info ** const devinfo_list)
 	char devpath[sizeof(devroot) + (NAME_MAX * 3)];
 	char *devfile, *upfile;
 	size_t len, len2;
-	
+
 	D = opendir(devroot);
 	if (!D)
 		return;
@@ -421,22 +421,22 @@ void _vcom_devinfo_scan_sysfs(struct lowlevel_device_info ** const devinfo_list)
 		upfile = &devpath[devrootlen + 1];
 		memcpy(upfile, de->d_name, len);
 		devfile = upfile + len;
-		
+
 		devfile[0] = '\0';
 		DS = opendir(devpath);
 		if (!DS)
 			continue;
 		devfile[0] = '/';
 		++devfile;
-		
+
 		while ( (de = readdir(DS)) )
 		{
 			if (strncmp(de->d_name, upfile, len))
 				continue;
-			
+
 			len2 = strlen(de->d_name);
 			memcpy(devfile, de->d_name, len2 + 1);
-			
+
 			_sysfs_find_tty(devpath, devfile, devinfo_list);
 		}
 		closedir(DS);
@@ -454,7 +454,7 @@ char *windows_usb_get_port_path(HANDLE hubh, const int portno)
 {
 	size_t namesz;
 	ULONG rsz;
-	
+
 	{
 		USB_NODE_CONNECTION_NAME pathinfo = {
 			.ConnectionIndex = portno,
@@ -463,17 +463,17 @@ char *windows_usb_get_port_path(HANDLE hubh, const int portno)
 			applogfailinfor(NULL, LOG_ERR, "ioctl (1)", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
 		namesz = pathinfo.ActualLength;
 	}
-	
+
 	const size_t bufsz = sizeof(USB_NODE_CONNECTION_NAME) + namesz;
 	uint8_t buf[bufsz];
 	USB_NODE_CONNECTION_NAME *path = (USB_NODE_CONNECTION_NAME *)buf;
 	*path = (USB_NODE_CONNECTION_NAME){
 		.ConnectionIndex = portno,
 	};
-	
+
 	if (!(DeviceIoControl(hubh, IOCTL_USB_GET_NODE_CONNECTION_NAME, path, bufsz, path, bufsz, &rsz, NULL) && rsz >= sizeof(*path)))
 		applogfailinfor(NULL, LOG_ERR, "ioctl (2)", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	return ucs2_to_utf8_dup(path->NodeName, path->ActualLength);
 }
 
@@ -482,11 +482,11 @@ char *windows_usb_get_string(HANDLE hubh, const int portno, const uint8_t descid
 {
 	if (!descid)
 		return NULL;
-	
+
 	const size_t descsz_max = sizeof(USB_STRING_DESCRIPTOR) + MAXIMUM_USB_STRING_LENGTH;
 	const size_t reqsz = sizeof(USB_DESCRIPTOR_REQUEST) + descsz_max;
 	uint8_t buf[reqsz];
-	
+
 	USB_DESCRIPTOR_REQUEST * const req = (USB_DESCRIPTOR_REQUEST *)buf;
 	USB_STRING_DESCRIPTOR * const desc = (USB_STRING_DESCRIPTOR *)&req[1];
 	*req = (USB_DESCRIPTOR_REQUEST){
@@ -499,14 +499,14 @@ char *windows_usb_get_string(HANDLE hubh, const int portno, const uint8_t descid
 	};
 	// Need to explicitly zero the output memory
 	memset(desc, '\0', descsz_max);
-	
+
 	ULONG descsz;
 	if (!DeviceIoControl(hubh, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, req, reqsz, req, reqsz, &descsz, NULL))
 		applogfailinfor(NULL, LOG_DEBUG, "ioctl", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	if (descsz < 2 || desc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE || desc->bLength > descsz - sizeof(USB_DESCRIPTOR_REQUEST) || desc->bLength % 2)
 		applogfailr(NULL, LOG_ERR, "sanity check");
-	
+
 	return ucs2_to_utf8_dup(desc->bString, desc->bLength);
 }
 
@@ -519,16 +519,16 @@ void _vcom_devinfo_scan_windows__hubport(struct lowlevel_device_info ** const de
 	const size_t conninfosz = sizeof(USB_NODE_CONNECTION_INFORMATION) + (sizeof(USB_PIPE_INFO) * 30);
 	uint8_t buf[conninfosz];
 	USB_NODE_CONNECTION_INFORMATION * const conninfo = (USB_NODE_CONNECTION_INFORMATION *)buf;
-	
+
 	conninfo->ConnectionIndex = portno;
-	
+
 	ULONG respsz;
 	if (!DeviceIoControl(hubh, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, conninfo, conninfosz, conninfo, conninfosz, &respsz, NULL))
 		applogfailinfor(, LOG_ERR, "ioctl", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	if (conninfo->ConnectionStatus != DeviceConnected)
 		return;
-	
+
 	if (conninfo->DeviceIsHub)
 	{
 		const char * const hubpath = windows_usb_get_port_path(hubh, portno);
@@ -536,7 +536,7 @@ void _vcom_devinfo_scan_windows__hubport(struct lowlevel_device_info ** const de
 			_vcom_devinfo_scan_windows__hub(devinfo_list, hubpath);
 		return;
 	}
-	
+
 	const USB_DEVICE_DESCRIPTOR * const devdesc = &conninfo->DeviceDescriptor;
 	char * const serial = windows_usb_get_string(hubh, portno, devdesc->iSerialNumber);
 	if (!serial)
@@ -570,7 +570,7 @@ out:
 		applogfailinfor(, LOG_ERR, "get expected type for PortName registry key value", "%ld", (long)type);
 		goto out;
 	}
-	
+
 	devinfo = _vcom_devinfo_findorcreate(devinfo_list, devpath);
 	if (!devinfo)
 	{
@@ -590,7 +590,7 @@ void _vcom_devinfo_scan_windows__hub(struct lowlevel_device_info ** const devinf
 {
 	HANDLE hubh;
 	USB_NODE_INFORMATION nodeinfo;
-	
+
 	{
 		char deviceName[4 + strlen(hubpath) + 1];
 		sprintf(deviceName, "\\\\.\\%s", hubpath);
@@ -598,15 +598,15 @@ void _vcom_devinfo_scan_windows__hub(struct lowlevel_device_info ** const devinf
 		if (hubh == INVALID_HANDLE_VALUE)
 			applogr(, LOG_ERR, "Error opening USB hub device %s for autodetect: %s", deviceName, bfg_strerror(GetLastError(), BST_SYSTEM));
 	}
-	
+
 	ULONG nBytes;
 	if (!DeviceIoControl(hubh, IOCTL_USB_GET_NODE_INFORMATION, &nodeinfo, sizeof(nodeinfo), &nodeinfo, sizeof(nodeinfo), &nBytes, NULL))
 		applogfailinfor(, LOG_ERR, "ioctl", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	const int portcount = nodeinfo.u.HubInformation.HubDescriptor.bNumberOfPorts;
 	for (int i = 1; i <= portcount; ++i)
 		_vcom_devinfo_scan_windows__hubport(devinfo_list, hubh, i);
-	
+
 	CloseHandle(hubh);
 }
 
@@ -615,7 +615,7 @@ char *windows_usb_get_root_hub_path(HANDLE hcntlrh)
 {
 	size_t namesz;
 	ULONG rsz;
-	
+
 	{
 		USB_ROOT_HUB_NAME pathinfo;
 		if (!DeviceIoControl(hcntlrh, IOCTL_USB_GET_ROOT_HUB_NAME, 0, 0, &pathinfo, sizeof(pathinfo), &rsz, NULL))
@@ -624,14 +624,14 @@ char *windows_usb_get_root_hub_path(HANDLE hcntlrh)
 			applogfailinfor(NULL, LOG_ERR, "ioctl (1)", "Size too small (%d < %d)", (int)rsz, (int)sizeof(pathinfo));
 		namesz = pathinfo.ActualLength;
 	}
-	
+
 	const size_t bufsz = sizeof(USB_ROOT_HUB_NAME) + namesz;
 	uint8_t buf[bufsz];
 	USB_ROOT_HUB_NAME *hubpath = (USB_ROOT_HUB_NAME *)buf;
-	
+
 	if (!(DeviceIoControl(hcntlrh, IOCTL_USB_GET_ROOT_HUB_NAME, NULL, 0, hubpath, bufsz, &rsz, NULL) && rsz >= sizeof(*hubpath)))
 		applogfailinfor(NULL, LOG_ERR, "ioctl (2)", "%s", bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	return ucs2_to_utf8_dup(hubpath->RootHubName, hubpath->ActualLength);
 }
 
@@ -669,7 +669,7 @@ void _vcom_devinfo_scan_windows(struct lowlevel_device_info ** const devinfo_lis
 	SP_DEVINFO_DATA devinfodata = {
 		.cbSize = sizeof(devinfodata),
 	};
-	
+
 	for (int i = 0; SetupDiEnumDeviceInfo(devinfo, i, &devinfodata); ++i)
 		_vcom_devinfo_scan_windows__hcntlr(devinfo_list, &devinfo, i);
 	SetupDiDestroyDeviceInfoList(devinfo);
@@ -716,7 +716,7 @@ void _vcom_devinfo_scan_ftdi(struct lowlevel_device_info ** const devinfo_list)
 	LOAD_SYM(FT_Open);
 	LOAD_SYM(FT_GetComPortNumber);
 	LOAD_SYM(FT_Close);
-	
+
 	ftStatus = FT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY);
 	if (ftStatus != FT_OK) {
 		applog(LOG_DEBUG, "FTDI device count failed, not using FTDI autodetect");
@@ -735,11 +735,11 @@ void _vcom_devinfo_scan_ftdi(struct lowlevel_device_info ** const devinfo_list)
 		applog(LOG_DEBUG, "FTDI device list failed, not using FTDI autodetect");
 		goto out;
 	}
-	
+
 	for (i = numDevs; i > 0; ) {
 		--i;
 		bufptrs[i][64] = '\0';
-		
+
 		FT_HANDLE ftHandle;
 		if (FT_OK != FT_Open(i, &ftHandle))
 			continue;
@@ -748,10 +748,10 @@ void _vcom_devinfo_scan_ftdi(struct lowlevel_device_info ** const devinfo_list)
 		FT_Close(ftHandle);
 		if (FT_OK != ftStatus || lComPortNumber < 0)
 			continue;
-		
+
 		applog(LOG_ERR, "FT_GetComPortNumber(%p (%ld), %ld)", ftHandle, (long)i, (long)lComPortNumber);
 		sprintf(devpathnum, "%d", (int)lComPortNumber);
-		
+
 		devinfo = _vcom_devinfo_findorcreate(devinfo_list, devpath);
 		if (!devinfo)
 			continue;
@@ -849,12 +849,12 @@ int _serial_autodetect(detectone_func_t detectone, ...)
 	va_list needles;
 	char *needles_array[0x10];
 	int needlecount = 0;
-	
+
 	va_start(needles, detectone);
 	while ( (needles_array[needlecount++] = va_arg(needles, void *)) )
 	{}
 	va_end(needles);
-	
+
 	return _lowlevel_detect(_serial_autodetect_found_cb, NULL, (const char **)needles_array, detectone);
 }
 
@@ -864,7 +864,7 @@ struct lowlevel_device_info *vcom_devinfo_scan()
 	struct lowlevel_device_info *devinfo_hash = NULL;
 	struct lowlevel_device_info *devinfo_list = NULL;
 	struct lowlevel_device_info *devinfo, *tmp;
-	
+
 	// All 3 USB Strings available:
 #ifndef WIN32
 	_vcom_devinfo_scan_sysfs(&devinfo_hash);
@@ -893,14 +893,14 @@ struct lowlevel_device_info *vcom_devinfo_scan()
 	_vcom_devinfo_scan_lsdev(&devinfo_hash);
 #endif
 	_vcom_devinfo_scan_user(&devinfo_hash);
-	
+
 	// Convert hash to simple list
 	HASH_ITER(hh, devinfo_hash, devinfo, tmp)
 	{
 		LL_PREPEND(devinfo_list, devinfo);
 	}
 	HASH_CLEAR(hh, devinfo_hash);
-	
+
 	return devinfo_list;
 }
 
@@ -1066,7 +1066,7 @@ bool vcom_set_timeout_ms(const int fdDev, const unsigned timeout_ms)
 	return (SetCommTimeouts(hSerial, &cto) != 0);
 #else
 	struct termios my_termios;
-	
+
 	tcgetattr(fdDev, &my_termios);
 	my_termios.c_cc[VTIME] = (cc_t)((timeout_ms + 99) / 100);
 	return (tcsetattr(fdDev, TCSANOW, &my_termios) == 0);
@@ -1135,7 +1135,7 @@ int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool p
 
 	return _open_osfhandle((intptr_t)hSerial, 0);
 #else
-	int fdDev = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY);
+	int fdDev = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY | O_SYNC);
 
 	if (unlikely(fdDev == -1))
 	{
@@ -1146,7 +1146,7 @@ int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool p
 
 		return -1;
 	}
-	
+
 #if defined(LOCK_EX) && defined(LOCK_NB)
 	if (likely(!flock(fdDev, LOCK_EX | LOCK_NB)))
 		applog(LOG_DEBUG, "Acquired exclusive advisory lock on %s", devpath);
@@ -1181,10 +1181,11 @@ int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool p
 		{
 			cfsetispeed(&my_termios, speed);
 			cfsetospeed(&my_termios, speed);
+            cfsetspeed(&my_termios,  speed);
 		}
 	}
 
-	my_termios.c_cflag &= ~(CSIZE | PARENB);
+	my_termios.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
 	my_termios.c_cflag |= CS8;
 	my_termios.c_cflag |= CREAD;
 #ifdef USE_AVALON
@@ -1224,6 +1225,60 @@ int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool p
 #endif
 }
 
+extern int serial_change_baud(int fd, unsigned long baud)
+{
+#ifdef WIN32
+    if (fd == -1)
+		return BGV_ERROR;
+	const HANDLE fh = (HANDLE)_get_osfhandle(fd);
+	if (fh == INVALID_HANDLE_VALUE)
+		return BGV_ERROR;
+
+    if (baud)
+	{
+
+	COMMCONFIG comCfg = {0};
+	comCfg.dwSize = sizeof(COMMCONFIG);
+	comCfg.wVersion = 1;
+	comCfg.dcb.DCBlength = sizeof(DCB);
+	comCfg.dcb.BaudRate = baud;
+	comCfg.dcb.fBinary = 1;
+	comCfg.dcb.fDtrControl = DTR_CONTROL_ENABLE;
+	comCfg.dcb.fRtsControl = RTS_CONTROL_ENABLE;
+	comCfg.dcb.ByteSize = 8;
+
+		if (!SetCommConfig(fh, &comCfg, sizeof(comCfg)))
+			// FIXME: We should probably be setting even if baud is clear (in which case, only LOG_DEBUG this)
+			applog(LOG_WARNING, "%s: %s failed: %s", devpath, "SetCommConfig", bfg_strerror(GetLastError(), BST_SYSTEM));
+
+	}
+  #else
+
+    struct termios my_termios;
+
+	if (tcgetattr(fd, &my_termios))
+		applog(baud ? LOG_WARNING : LOG_DEBUG, "%s: %s failed: tcgetattr", bfg_strerror(errno, BST_ERRNO));
+	else
+	{
+
+
+	if (baud)
+	{
+		speed_t speed = tiospeed_t(baud);
+		if (speed == B0)
+			applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud);
+		else
+		{
+			cfsetispeed(&my_termios, speed);
+			cfsetospeed(&my_termios, speed);
+            tcflush(fd, TCIOFLUSH);
+		}
+	}
+
+	}
+  #endif
+}
+
 int serial_close(const int fd)
 {
 #if defined(LOCK_EX) && defined(LOCK_NB) && defined(LOCK_UN)
@@ -1270,7 +1325,7 @@ enum bfg_gpio_value _set_serial_cmflag(int fd, int flag, bool val)
 		return BGV_ERROR;
 
 	ioctl(fd, TIOCMGET, &flags);
-	
+
 	if (val)
 		flags |= flag;
 	else
@@ -1313,20 +1368,20 @@ enum bfg_gpio_value _set_serial_cmflag(int fd, void (*setfunc)(DCB*, bool), bool
 	const HANDLE fh = (HANDLE)_get_osfhandle(fd);
 	if (fh == INVALID_HANDLE_VALUE)
 		return BGV_ERROR;
-	
+
 	DCB dcb;
 	if (!GetCommState(fh, &dcb))
 		applogr(BGV_ERROR, LOG_DEBUG, "Failed to %s"IN_FMT_FFL": %s",
 		        "GetCommState", __FILE__, fname, __LINE__,
 		        bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	setfunc(&dcb, val);
-	
+
 	if (!SetCommState(fh, &dcb))
 		applogr(BGV_ERROR, LOG_DEBUG, "Failed to %s"IN_FMT_FFL": %s",
 		        "GetCommState", __FILE__, fname, __LINE__,
 		        bfg_strerror(GetLastError(), BST_SYSTEM));
-	
+
 	return val ? BGV_HIGH : BGV_LOW;
 }
 #define _set_serial_cmflag2(name, field, trueval, falseval)  \

+ 1 - 0
lowl-vcom.h

@@ -32,6 +32,7 @@ extern struct device_drv *bfg_claim_serial(struct device_drv * const, const bool
 #define serial_claim_v(devpath, drv)  bfg_claim_serial(drv, true , devpath)
 
 extern int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool purge);
+extern int serial_change_baud(int fd, unsigned long baud);
 extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol);
 #define serial_read(fd, buf, count)  \
 	_serial_read(fd, (char*)(buf), count, NULL)