Browse Source

Dummy driver example

Luke Dashjr 12 years ago
parent
commit
8d13f05264
5 changed files with 241 additions and 1 deletions
  1. 4 0
      Makefile.am
  2. 3 0
      api.c
  3. 13 0
      configure.ac
  4. 211 0
      driver-dummy.c
  5. 10 1
      miner.c

+ 4 - 0
Makefile.am

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

+ 3 - 0
api.c

@@ -117,6 +117,9 @@ static const char *DEVICECODE = ""
 #ifdef USE_AVALON
 #ifdef USE_AVALON
 			"AVA "
 			"AVA "
 #endif
 #endif
+#ifdef USE_BFGDUMMY
+			"EMP "
+#endif
 #ifdef USE_LIBMICROHTTPD
 #ifdef USE_LIBMICROHTTPD
 			"SGW "
 			"SGW "
 #endif
 #endif

+ 13 - 0
configure.ac

@@ -385,6 +385,19 @@ if test "x$avalon" = xyes; then
 fi
 fi
 AM_CONDITIONAL([HAS_AVALON], [test x$avalon = xyes])
 AM_CONDITIONAL([HAS_AVALON], [test x$avalon = xyes])
 
 
+driverlist="$driverlist dummydrv"
+dummydrv=no
+AC_ARG_ENABLE([dummydrv],
+	[AC_HELP_STRING([--disable-dummydrv],[Compile support for Dummy Driver (default enabled)])],
+	[dummydrv=$enableval],
+	[dummydrv=yes]
+	)
+if test "x$dummydrv" = xyes; then
+	AC_DEFINE([USE_BFGDUMMY], [1], [Defined to 1 if Dummy Driver support is wanted])
+	need_fpgautils=yes
+fi
+AM_CONDITIONAL([USE_BFGDUMMY], [test x$dummydrv = xyes])
+
 driverlist="$driverlist knc"
 driverlist="$driverlist knc"
 AC_ARG_ENABLE([knc],
 AC_ARG_ENABLE([knc],
 	[AC_HELP_STRING([--enable-knc],[Compile support for KnC (default disabled)])],
 	[AC_HELP_STRING([--enable-knc],[Compile support for KnC (default disabled)])],

+ 211 - 0
driver-dummy.c

@@ -0,0 +1,211 @@
+/*
+ * 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 <ctype.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include "deviceapi.h"
+#include "fpgautils.h"
+#include "logging.h"
+#include "miner.h"
+
+struct device_drv dummy_drv;
+
+static
+bool dummy_send_command(const int fd, const uint8_t cmd, const void * const data, const size_t datasz)
+{
+	if (1 != write(fd, &cmd, 1))
+		return false;
+	if (datasz)
+		if (write(fd, data, datasz) != datasz)
+			return false;
+	return true;
+}
+
+static
+int dummy_recv_reply(const int fd, void * const bufp, const uint8_t cmd)
+{
+	uint8_t chk, len;
+	uint8_t * const buf = bufp;
+	
+	if (1 != read(fd, &chk, 1) || (cmd && chk != cmd))
+		return -1;
+	if (1 != read(fd, &len, 1))
+		return -1;
+	buf[0] = chk;
+	if (len)
+		if (len != read(fd, &buf[1], len))
+			return -1;
+	if (1 != read(fd, &chk, 1) || chk != '\x0a')
+		return -1;
+	return len;
+}
+
+static
+int dummy_do_command(const int fd, void * const buf, const uint8_t cmd, const void * const data, const size_t datasz)
+{
+	if (!dummy_send_command(fd, cmd, data, datasz))
+		return -1;
+	return dummy_recv_reply(fd, buf, tolower(cmd));
+}
+
+static
+bool dummy_detect_one(const char * const devpath)
+{
+	uint8_t buf[0x100];
+	int n;
+	const int fd = serial_open(devpath, 38400, 1, true);
+	if (fd == -1)
+		return false;
+	
+	buf[0] = '\0';
+	n = dummy_do_command(fd, buf, 'V', NULL, 0);
+	if (buf[1] != 'M' || buf[2] != 'P')
+	{
+		serial_close(fd);
+		return false;
+	}
+	
+	n = dummy_do_command(fd, buf, 'R', NULL, 0);
+	n = dummy_do_command(fd, buf, 'I', NULL, 0);
+	serial_close(fd);
+	
+	if (serial_claim_v(devpath, &dummy_drv))
+		return false;
+	
+	struct cgpu_info *cgpu = malloc(sizeof(*cgpu));
+	*cgpu = (struct cgpu_info){
+		.drv = &dummy_drv,
+		.device_path = strdup(devpath),
+		.device_fd = -1,
+		.threads = 1,
+		.procs = buf[1],
+	};
+	add_cgpu(cgpu);
+	
+	return true;
+}
+
+static int dummy_detect_auto()
+{
+	return serial_autodetect(dummy_detect_one, "Dummy BFGMiner Device");
+}
+
+static void dummy_detect()
+{
+	serial_detect_auto(&dummy_drv, dummy_detect_one, dummy_detect_auto);
+}
+
+static bool dummy_init(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	
+	int fd = serial_open(cgpu->device_path, 38400, 1, true);
+	if (unlikely(-1 == fd))
+	{
+		applog(LOG_ERR, "%"PRIpreprv": Failed to open %s",
+		       cgpu->proc_repr, cgpu->device_path);
+		return false;
+	}
+	
+	cgpu->device_fd = fd;
+	
+	applog(LOG_INFO, "%"PRIpreprv": Opened %s", cgpu->proc_repr, cgpu->device_path);
+	
+	return true;
+}
+
+static
+bool dummy_queue_append(struct thr_info * const thr, struct work * const work)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	const int fd = cgpu->device_fd;
+	uint8_t buf[0x100];
+	
+	if (thr->queue_full)
+		return false;
+	
+	memcpy(&buf[   0], work->midstate , 0x20);
+	memcpy(&buf[0x20], &work->data[64], 0x0c);
+	dummy_do_command(fd, buf, 'Q', buf, 0x2c);
+	
+	if (thr->work)
+	{
+		dummy_send_command(fd, 'W', &buf[2], 1);
+		thr->queue_full = true;
+	}
+	else
+		dummy_send_command(fd, 'J', &buf[2], 1);
+	
+	return true;
+}
+
+static
+void dummy_queue_flush(struct thr_info * const thr)
+{
+	// TODO
+}
+
+static
+void dummy_poll(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu, *proc;
+	const int fd = cgpu->device_fd;
+	struct thr_info *mythr;
+	uint8_t buf[0x100];
+	int n, i, engineid;
+	uint32_t nonce;
+	
+	n = dummy_recv_reply(fd, buf, 0);
+	if (n == -1)
+		goto out;
+	
+	if (buf[0] == 'j')
+		goto out;
+	
+	if (buf[1] & 0x80)
+	{
+		engineid = buf[1] & 0x7f;
+		proc = cgpu;
+		for (i = 0; i < engineid; ++i)
+			proc = proc->next_proc;
+		mythr = proc->thr[0];
+		nonce = buf[2] | (buf[3] << 8) | (buf[4] << 16) | (buf[5] << 24);
+		submit_nonce(mythr, thr->work, nonce);
+		goto out;
+	}
+	
+	thr->queue_full = false;
+	
+out:
+	timer_set_delay_from_now(&thr->tv_poll, 10000);
+}
+
+struct device_drv dummy_drv = {
+	.dname = "dummy",
+	.name = "EMP",
+	.drv_detect = dummy_detect,
+	
+	.thread_init = dummy_init,
+	
+	.minerloop = minerloop_queue,
+	.queue_append = dummy_queue_append,
+	.queue_flush = dummy_queue_flush,
+	.poll = dummy_poll,
+};

+ 10 - 1
miner.c

@@ -92,7 +92,7 @@
 #include "scrypt.h"
 #include "scrypt.h"
 #endif
 #endif
 
 
-#if defined(USE_AVALON) || defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_MODMINER) || defined(USE_NANOFURY) || defined(USE_X6500) || defined(USE_ZTEX)
+#if defined(USE_AVALON) || defined(USE_BITFORCE) || defined(USE_BFGDUMMY) || defined(USE_ICARUS) || defined(USE_MODMINER) || defined(USE_NANOFURY) || defined(USE_X6500) || defined(USE_ZTEX)
 #	define USE_FPGA
 #	define USE_FPGA
 #endif
 #endif
 
 
@@ -10119,6 +10119,10 @@ extern struct device_drv icarus_drv;
 extern struct device_drv avalon_drv;
 extern struct device_drv avalon_drv;
 #endif
 #endif
 
 
+#ifdef USE_BFGDUMMY
+extern struct device_drv dummy_drv;
+#endif
+
 #ifdef USE_KNC
 #ifdef USE_KNC
 extern struct device_drv knc_drv;
 extern struct device_drv knc_drv;
 #endif
 #endif
@@ -10241,6 +10245,11 @@ void drv_detect_all()
 		bigpic_drv.drv_detect();
 		bigpic_drv.drv_detect();
 #endif
 #endif
 
 
+#ifdef USE_BFGDUMMY
+	if (!opt_scrypt)
+		dummy_drv.drv_detect();
+#endif
+
 #ifdef USE_KNC
 #ifdef USE_KNC
 	if (!opt_scrypt)
 	if (!opt_scrypt)
 		knc_drv.drv_detect();
 		knc_drv.drv_detect();