Luke Dashjr 12 years ago
parent
commit
d6e7456691
3 changed files with 268 additions and 0 deletions
  1. 4 0
      Makefile.am
  2. 14 0
      configure.ac
  3. 250 0
      driver-technobit.c

+ 4 - 0
Makefile.am

@@ -261,6 +261,10 @@ bfgminer_CPPFLAGS += $(hidapi_CFLAGS)
 endif
 endif
 
+if USE_TECHNOBIT
+bfgminer_SOURCES += driver-technobit.c
+endif
+
 bin_PROGRAMS += bfgminer-rpc
 bfgminer_rpc_SOURCES = api-example.c
 bfgminer_rpc_LDADD = @WS2_LIBS@

+ 14 - 0
configure.ac

@@ -699,6 +699,20 @@ if test "x$libusb" = xyes; then
 fi
 
 
+driverlist="$driverlist technobit"
+technobit="no"
+AC_ARG_ENABLE([technobit],
+	[AC_HELP_STRING([--disable-technobit],[Compile support for TechnoBit (default enabled)])],
+	[technobit=$enableval],
+	[technobit=yes]
+	)
+if test "x$technobit" = xyes; then
+	AC_DEFINE([USE_TECHNOBIT], [1], [Defined to 1 if TechnoBit support is wanted])
+	need_fpgautils=yes
+fi
+AM_CONDITIONAL([USE_TECHNOBIT], [test x$technobit = xyes])
+
+
 algolist="$algolist scrypt"
 scrypt="no"
 

+ 250 - 0
driver-technobit.c

@@ -0,0 +1,250 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "deviceapi.h"
+#include "fpgautils.h"
+#include "miner.h"
+#include "util.h"
+
+BFG_REGISTER_DRIVER(technobit_drv)
+
+#define TECHNOBIT_PKT_HEADER_SIZE (1 + 1 + 1 + 2)
+#define TECHNOBIT_LOWEST_ADDRESS  (0x3000)
+#define TECHNOBIT_HIGHEST_ADDRESS (0x7000)  /* ??? */
+#define TECHNOBIT_MAX_DATA_SIZE 510
+
+struct technobit_state {
+	uint8_t datain[TECHNOBIT_PKT_HEADER_SIZE + (255 * 2) + 1];
+	size_t datainlen;
+};
+
+static
+uint8_t technobit_chksum(const void * const data, const size_t datasz)
+{
+	const uint8_t *bytes = data;
+	uint8_t r = 0;
+	size_t i;
+	
+	for (i = 0; i < datasz; ++i, ++bytes)
+		r += *bytes;
+	
+	return r;
+}
+
+static
+bool technobit_send(const int fd, const uint8_t cmd, const uint16_t addr, const void * const data, const size_t datasz)
+{
+	const size_t sz2 = TECHNOBIT_PKT_HEADER_SIZE + datasz;
+	const size_t pktsz = sz2 + 1;
+	uint8_t pkt[pktsz];
+	pkt[0] = '\x53';
+	pkt[1] = datasz / 2;
+	pkt[2] = cmd;
+	pkt[3] = addr & 0xff;
+	pkt[4] = addr >> 8;
+	memcpy(&pkt[5], data, datasz);
+	pkt[sz2] = technobit_chksum(pkt, sz2);
+	
+	if (opt_dev_protocol)
+	{
+		char hex[(pktsz * 2) + 1];
+		bin2hex(hex, pkt, pktsz);
+		applog(LOG_DEBUG, "%s(%d,'%c',0x%04x,...,%u): %s",
+		       __func__, fd, (int)cmd, (unsigned)addr, (unsigned)datasz, hex);
+	}
+	
+	return (write(fd, pkt, pktsz) == pktsz);
+}
+
+static
+bool technobit_recv(struct technobit_state * const state, const int fd, uint8_t * const out_cmd, uint16_t * const out_addr, void * const out_datap, size_t * const out_datasz)
+{
+	void ** const out_datap2 = out_datap;
+	int skip = 0;
+	const ssize_t r = read(fd, &state->datain[state->datainlen], sizeof(state->datain) - state->datainlen);
+	if (r <= 0)
+		return false;
+	if (opt_dev_protocol)
+	{
+		char hex[(r * 2) + 1];
+		bin2hex(hex, &state->datain[state->datainlen], r);
+		applog(LOG_DEBUG, "%s: %s", __func__, hex);
+	}
+	state->datainlen += r;
+	
+reskip2:
+	while (state->datain[skip] != '\x53')
+		++skip;
+	state->datainlen -= skip;
+	memmove(state->datain, &state->datain[skip], state->datainlen);
+	
+	if (state->datainlen <= TECHNOBIT_PKT_HEADER_SIZE)
+		return false;
+	
+	const uint16_t addr = (state->datain[4] << 8) | state->datain[3];
+	if (addr < TECHNOBIT_LOWEST_ADDRESS || addr > TECHNOBIT_HIGHEST_ADDRESS)
+	{
+reskip:
+		skip = 1;
+		goto reskip2;
+	}
+	
+	const size_t datasz = state->datain[1] * 2;
+	const size_t pktsz = TECHNOBIT_PKT_HEADER_SIZE + datasz;
+	if (state->datainlen <= pktsz)
+		return false;
+	
+	const uint8_t chksum = technobit_chksum(state->datain, pktsz);
+	if (state->datain[pktsz] != chksum)
+		goto reskip;
+	
+	*out_cmd = state->datain[2];
+	*out_addr = addr;
+	*out_datap2 = &state->datain[TECHNOBIT_PKT_HEADER_SIZE];
+	*out_datasz = datasz;
+	return true;
+}
+
+static
+bool technobit_request_read(const int fd, const uint16_t addr, uint16_t sz)
+{
+	const uint8_t data[2] = { sz & 0xff, sz >> 8 };
+	return technobit_send(fd, 'R', addr, data, sizeof(data));
+}
+
+static
+bool technobit_detect_one(const char * const devpath)
+{
+	struct cgpu_info *cgpu;
+	
+	// TODO
+	
+	cgpu = malloc(sizeof(*cgpu));
+	*cgpu = (struct cgpu_info){
+		.drv = &technobit_drv,
+		.device_path = strdup(devpath),
+		.device_fd = -1,
+		.deven = DEV_ENABLED,
+		.threads = 1,
+	};
+	return add_cgpu(cgpu);
+}
+
+static void technobit_detect(void)
+{
+	generic_detect(&technobit_drv, technobit_detect_one, NULL, 0);
+}
+
+
+static
+bool technobit_init(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct technobit_state *state;
+	
+	state = cgpu->device_data = malloc(sizeof(*state));
+	*state = (struct technobit_state){
+		.datainlen = 0,
+	};
+	
+	// TODO
+	// REQUEST  16 bits read from 3004
+	// receive  16 bits read from 6800
+	// receive 192 bits read from 3000
+	// receive  32 bits read from 6494
+	// receive  64 bits read from 649c
+	// REQUEST 736 bits write to  4000
+	// REQUEST  16 bits read from 3004
+	// receive  16 bits read from 6800
+	// receive confirmation of 736 bits write to 4000
+	// recieve  16 bits read from 3004
+	// recieve  16 bits read from 6800
+	// REQUEST 736 bits write to  4000
+	// REQUEST  16 bits read from 3004
+	// recieve  16 bits read from 6800
+	// recieve  
+	
+	timer_set_now(&thr->tv_poll);
+	return true;
+}
+
+static
+bool technobit_queue_append(struct thr_info * const thr, struct work * const work)
+{
+	//struct cgpu_info * const cgpu = thr->cgpu;
+	// TODO
+	thr->queue_full = true;
+	return false;
+}
+
+static
+void technobit_queue_flush(struct thr_info * const thr)
+{
+	// TODO
+}
+
+static
+void technobit_poll(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct technobit_state * const state = cgpu->device_data;
+	int fd = cgpu->device_fd;
+	
+	if (unlikely(fd == -1))
+	{
+		fd = cgpu->device_fd = serial_open(cgpu->device_path, 38400, 0, true);
+		if (fd == -1)
+			applogr(, LOG_ERR, "%"PRIpreprv": Failed to open %s",
+			        cgpu->proc_repr, cgpu->device_path);
+		technobit_request_read(fd, 0x3004, 1);
+	}
+	
+	uint8_t cmd, *datap;
+	uint16_t addr;
+	size_t datasz;
+	
+	if (technobit_recv(state, fd, &cmd, &addr, &datap, &datasz))
+	{
+		if (opt_debug)
+		{
+			char hexdata[(datasz * 2) + 1];
+			bin2hex(hexdata, datap, datasz);
+			applog(LOG_DEBUG, "%"PRIpreprv": Received cmd=%02x addr=%04x data=%s",
+			       cgpu->proc_repr, cmd, addr, hexdata);
+		}
+	}
+	
+	timer_set_delay_from_now(&thr->tv_poll, 10000);
+}
+
+
+struct device_drv technobit_drv = {
+	.dname = "technobit",
+	.name = "HEX",
+	.drv_detect = technobit_detect,
+	
+	.thread_init = technobit_init,
+	
+	.minerloop = minerloop_queue,
+	.queue_append = technobit_queue_append,
+	.queue_flush = technobit_queue_flush,
+	.poll = technobit_poll,
+};