Browse Source

knc: Basic detection of boards on expected i2c buses

Luke Dashjr 12 years ago
parent
commit
e3afcc5748
4 changed files with 161 additions and 0 deletions
  1. 4 0
      Makefile.am
  2. 23 0
      configure.ac
  3. 122 0
      driver-knc.c
  4. 12 0
      miner.c

+ 4 - 0
Makefile.am

@@ -213,6 +213,10 @@ if HAS_AVALON
 bfgminer_SOURCES += driver-avalon.c driver-avalon.h hexdump.c
 endif
 
+if USE_KNC
+bfgminer_SOURCES += driver-knc.c
+endif
+
 if HAS_MODMINER
 bfgminer_SOURCES += driver-modminer.c
 endif

+ 23 - 0
configure.ac

@@ -382,6 +382,29 @@ if test "x$avalon" = xyes; then
 fi
 AM_CONDITIONAL([HAS_AVALON], [test x$avalon = xyes])
 
+driverlist="$driverlist knc"
+AC_ARG_ENABLE([knc],
+	[AC_HELP_STRING([--enable-knc],[Compile support for KnC (default disabled)])],
+	[knc=$enableval],
+	[knc=no]
+	)
+if test "x$knc" = xyes; then
+	AC_CHECK_HEADERS([linux/i2c-dev-user.h])
+	AC_CHECK_DECL([i2c_smbus_read_word_data],[true],[
+	],[
+		#ifdef HAVE_LINUX_I2C_DEV_USER_H
+		#include <linux/i2c-dev-user.h>
+		#else
+		#ifdef NEED_LINUX_I2C_H
+		#include <linux/i2c.h>
+		#endif
+		#include <linux/i2c-dev.h>
+		#endif
+	])
+	AC_DEFINE([USE_KNC], [1], [Defined to 1 if KnC support is wanted])
+fi
+AM_CONDITIONAL([USE_KNC], [test x$knc = xyes])
+
 httpsrv=auto
 AC_ARG_WITH([libmicrohttpd],
 	[AC_HELP_STRING([--without-libmicrohttpd],[Compile support for libmicrohttpd getwork server (default enabled)])],

+ 122 - 0
driver-knc.c

@@ -0,0 +1,122 @@
+/*
+ * 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 <stddef.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_LINUX_I2C_DEV_USER_H
+#include <linux/i2c-dev-user.h>
+#else
+#include <linux/i2c-dev.h>
+#endif
+
+#include "deviceapi.h"
+
+struct device_drv knc_drv;
+
+static
+bool _check_value(const char * const devpath, const int i, const int32_t r, const uint8_t reg, const int32_t expected)
+{
+	if (expected == r)
+		return true;
+	
+	if (r == -1)
+		applog(LOG_DEBUG, "%s: %s: Error when reading slave %d register 0x%2x: %s",
+		       knc_drv.dname, devpath, i, reg, bfg_strerror(errno, BST_ERRNO));
+	else
+		applog(LOG_DEBUG, "%s: %s: Slave %d register 0x%2x is 0x%x, not 0x%x as expected",
+		       knc_drv.dname, devpath, i, reg, r, expected);
+	
+	return false;
+}
+
+static
+bool knc_detect_one(const char *devpath)
+{
+	struct cgpu_info *cgpu;
+	const int first_slave = 16, last_slave = 23;
+	int procs;
+	int i;
+	int32_t r;
+	const int fd = open(devpath, O_RDWR);
+	
+	if (unlikely(fd == -1))
+	{
+		applog(LOG_DEBUG, "%s: Failed to open %s", knc_drv.dname, devpath);
+		return false;
+	}
+	
+	for (i = first_slave; i <= last_slave; ++i)
+	{
+		if (ioctl(fd, I2C_SLAVE, i))
+		{
+			applog(LOG_DEBUG, "%s: %s: Failed to select I2C_SLAVE %d",
+			       knc_drv.dname, devpath, i);
+			continue;
+		}
+		r = i2c_smbus_read_byte_data(fd, 0x98);
+		if (!_check_value(devpath, i, r, 0x98, 0x11))
+			continue;
+		r = i2c_smbus_read_word_data(fd, 0xd0);
+		if (!_check_value(devpath, i, r, 0xd0, 0x10))
+			continue;
+		
+		applog(LOG_DEBUG, "%s: %s: Found i2c slave %d",
+		       knc_drv.dname, devpath, i);
+		
+		procs += 6;
+	}
+	
+	if (!procs)
+		return false;
+	
+	cgpu = malloc(sizeof(*cgpu));
+	*cgpu = (struct cgpu_info){
+		.drv = &knc_drv,
+		.device_path = strdup(devpath),
+		.deven = DEV_ENABLED,
+		.procs = procs,
+		.threads = 1,
+	};
+	return add_cgpu(cgpu);
+}
+
+static int knc_detect_auto(void)
+{
+	const int first_bus = 3, last_bus = 8;
+	char devpath[] = "/dev/i2c-N";
+	int found = 0, i;
+	
+	for (i = first_bus; i <= last_bus; ++i)
+	{
+		devpath[9] = '0' + i;
+		if (knc_detect_one(devpath))
+			++found;
+	}
+	
+	return found;
+}
+
+static void knc_detect(void)
+{
+	generic_detect(&knc_drv, knc_detect_one, knc_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
+}
+
+struct device_drv knc_drv = {
+	.dname = "knc",
+	.name = "KNC",
+	.drv_detect = knc_detect,
+};

+ 12 - 0
miner.c

@@ -2085,6 +2085,9 @@ static char *opt_verusage_and_exit(const char *extra)
 #ifdef USE_ICARUS
 		"icarus "
 #endif
+#ifdef USE_KNC
+		"knc "
+#endif
 #ifdef USE_MODMINER
 		"modminer "
 #endif
@@ -9721,6 +9724,10 @@ extern struct device_drv icarus_drv;
 extern struct device_drv avalon_drv;
 #endif
 
+#ifdef USE_KNC
+extern struct device_drv knc_drv;
+#endif
+
 #ifdef USE_LITTLEFURY
 extern struct device_drv littlefury_drv;
 #endif
@@ -9836,6 +9843,11 @@ void drv_detect_all()
 		bigpic_drv.drv_detect();
 #endif
 
+#ifdef USE_KNC
+	if (!opt_scrypt)
+		knc_drv.drv_detect();
+#endif
+
 #ifdef USE_MODMINER
 	if (!opt_scrypt)
 		modminer_drv.drv_detect();