Browse Source

neptune: Initial probing driver

Luke Dashjr 11 years ago
parent
commit
1d62420966
5 changed files with 168 additions and 5 deletions
  1. 7 0
      Makefile.am
  2. 16 2
      configure.ac
  3. 140 0
      driver-neptune.c
  4. 4 2
      lowl-spi.c
  5. 1 1
      lowl-spi.h

+ 7 - 0
Makefile.am

@@ -69,6 +69,9 @@ bfgminer_LDADD += $(libblkmaker_LIBS)
 bfgminer_LDFLAGS += $(libblkmaker_LDFLAGS)
 bfgminer_CPPFLAGS += $(libblkmaker_CFLAGS)
 
+bfgminer_CPPFLAGS += $(zlib_CFLAGS)
+bfgminer_LDADD += $(zlib_LIBS)
+
 # common sources
 bfgminer_SOURCES := miner.c
 
@@ -286,6 +289,10 @@ if HAS_MODMINER
 bfgminer_SOURCES += driver-modminer.c
 endif
 
+if USE_NEPTUNE
+bfgminer_SOURCES += driver-neptune.c
+endif
+
 if HAS_X6500
 bfgminer_SOURCES += driver-x6500.c jtag.c jtag.h
 endif

+ 16 - 2
configure.ac

@@ -753,6 +753,20 @@ fi
 AM_CONDITIONAL([HAS_KLONDIKE], [test x$klondike = xyes])
 
 
+driverlist="$driverlist neptune"
+AC_ARG_ENABLE([neptune],
+	[AC_HELP_STRING([--enable-neptune],[Compile support for KnCMiner Neptune (default disabled)])],
+	[neptune=$enableval],
+	[neptune=$ddno]
+	)
+if test "x$neptune" = xyes; then
+	PKG_CHECK_MODULES([zlib],[zlib])
+	AC_DEFINE([USE_NEPTUNE], [1], [Defined to 1 if Neptune support is wanted])
+	need_lowl_spi=yes
+fi
+AM_CONDITIONAL([USE_NEPTUNE], [test x$neptune = xyes])
+
+
 driverlist="$driverlist x6500"
 AC_ARG_ENABLE([x6500],
 	[AC_HELP_STRING([--disable-x6500],[Compile support for X6500 (default if libusb)])],
@@ -1871,8 +1885,8 @@ echo "------------------------------------------------------------------------"
 echo "$PACKAGE $VERSION configuration options summary"
 echo "------------------------------------------------------------------------"
 echo
-echo "  CFLAGS...............: "`wordfilter "$CPPFLAGS $AUTOSCAN_CPPFLAGS $NCURSES_CPPFLAGS $PTHREAD_FLAGS $CFLAGS $LIBUSB_CFLAGS $JANSSON_CFLAGS $PTHREAD_FLAGS $libblkmaker_CFLAGS $hidapi_CFLAGS"`
-echo "  LDFLAGS..............: "`wordfilter "$LDFLAGS $AUTOSCAN_LIBS $PTHREAD_FLAGS $libblkmaker_LDFLAGS $PTHREAD_LIBS $LIBS $DLOPEN_FLAGS $LIBCURL_LIBS $JANSSON_LIBS $NCURSES_LIBS $PDCURSES_LIBS $WS2_LIBS $MATH_LIBS $UDEV_LIBS $LIBUSB_LIBS $RT_LIBS $sensors_LIBS $libblkmaker_LIBS"`
+echo "  CFLAGS...............: "`wordfilter "$CPPFLAGS $AUTOSCAN_CPPFLAGS $NCURSES_CPPFLAGS $PTHREAD_FLAGS $zlib_CFLAGS $CFLAGS $LIBUSB_CFLAGS $JANSSON_CFLAGS $PTHREAD_FLAGS $libblkmaker_CFLAGS $hidapi_CFLAGS"`
+echo "  LDFLAGS..............: "`wordfilter "$LDFLAGS $AUTOSCAN_LIBS $PTHREAD_FLAGS $libblkmaker_LDFLAGS $PTHREAD_LIBS $zlib_LIBS $LIBS $DLOPEN_FLAGS $LIBCURL_LIBS $JANSSON_LIBS $NCURSES_LIBS $PDCURSES_LIBS $WS2_LIBS $MATH_LIBS $UDEV_LIBS $LIBUSB_LIBS $RT_LIBS $sensors_LIBS $libblkmaker_LIBS"`
 echo "  Installation.prefix..: $prefix"
 echo
 echo "${lowllist_print}" | tr '~' '\n'

+ 140 - 0
driver-neptune.c

@@ -0,0 +1,140 @@
+/*
+ * Copyright 2014 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 <stdint.h>
+
+#include <linux/spi/spidev.h>
+
+#include <zlib.h>
+
+#include "deviceapi.h"
+#include "lowl-spi.h"
+#include "util.h"
+
+#define NEPTUNE_SPI_SPEED  3000000
+#define NEPTUNE_SPI_DELAY  0
+#define NEPTUNE_SPI_MODE  (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
+#define NEPTUNE_SPI_BITS  8
+#define NEPTUNE_MAX_CHANNEL  6
+#define NEPTUNE_MAX_DIES_PER_CHANNEL  4
+#define NEPTUNE_VERSION  0xa002
+
+BFG_REGISTER_DRIVER(neptune_drv)
+
+enum neptune_cmd {
+	NEPTUNE_GETINFO = 0x80,
+};
+
+static
+void neptune_spi_emit_to_channel(struct spi_port * const spi, const uint8_t channel, const uint8_t datasz)
+{
+	const uint8_t muxheader[2] = {0x80 | channel, datasz};
+	spi_emit_buf(spi, muxheader, sizeof(muxheader));
+}
+
+void *neptune_spi_emit_cmd(struct spi_port * const spi, const uint8_t channel, const uint8_t die, const uint8_t core, const enum neptune_cmd cmd, const void * const data, const uint8_t datasz, const uint8_t responsesz)
+{
+	const uint8_t cmdhdr[4] = {cmd, die, core >> 8, core & 0xff};
+	neptune_spi_emit_to_channel(spi, channel, sizeof(cmdhdr) + datasz);
+	spi_emit_buf(spi, cmdhdr, sizeof(cmdhdr));
+	void * const rv = spi_emit_buf(spi, data, datasz);
+	if (datasz < responsesz)
+		spi_emit_nop(spi, responsesz - datasz);
+	uint32_t crc = crc32(0, NULL, 0);
+	crc = crc32(crc, cmdhdr, sizeof(cmdhdr));
+	if (datasz)
+		crc = crc32(crc, data, datasz);
+	uint8_t crcb[4];
+	pk_u32be(crcb, 0, crc);
+	spi_emit_buf(spi, crcb, sizeof(crcb));
+	return rv;
+}
+
+static
+bool neptune_detect_one(const char * const devpath)
+{
+	struct cgpu_info *prev_cgpu = NULL, *cgpu;
+	
+	spi_init();
+	
+	struct spi_port * const spi = malloc(sizeof(*spi));
+	memset(spi, 0, sizeof(*spi));
+	spi->txrx = linux_spi_txrx;
+	spi->repr = neptune_drv.dname;
+	spi->logprio = LOG_ERR;
+	spi->speed = NEPTUNE_SPI_SPEED;
+	spi->delay = NEPTUNE_SPI_DELAY;
+	spi->mode = NEPTUNE_SPI_MODE;
+	spi->bits = NEPTUNE_SPI_BITS;
+	
+	const int fd = spi_open(spi, devpath);
+	if (unlikely(fd == -1))
+	{
+		free(spi);
+		applogr(false, LOG_DEBUG, "%s: Failed to open %s", neptune_drv.dname, devpath);
+	}
+	
+	for (int channel = 0; channel < NEPTUNE_MAX_CHANNEL; ++channel)
+	{
+		unsigned total_cores = 0;
+		for (int die = 0; die < NEPTUNE_MAX_DIES_PER_CHANNEL; ++die)
+		{
+			uint8_t *rx = neptune_spi_emit_cmd(spi, channel, die, 0, NEPTUNE_GETINFO, NULL, 0, 12);
+			spi_txrx(spi);
+			unsigned cores = upk_u16be(rx, 0);
+			unsigned version = upk_u16be(rx, 2);
+			if (version != NEPTUNE_VERSION)
+				continue;
+			
+			// Read (and ignore) core status
+			size_t bytes_to_ignore = cores / 4;
+			neptune_spi_emit_to_channel(spi, channel, bytes_to_ignore);
+			spi_emit_nop(spi, bytes_to_ignore);
+			
+			total_cores += cores;
+		}
+		if (!total_cores)
+			continue;
+		
+		cgpu = malloc(sizeof(*cgpu));
+		*cgpu = (struct cgpu_info){
+			.drv = &neptune_drv,
+			.device_path = strdup(devpath),
+			.procs = total_cores,
+			.threads = prev_cgpu ? 0 : 1,
+		};
+		if (!add_cgpu_slave(cgpu, prev_cgpu))
+			continue;
+		prev_cgpu = cgpu;
+	}
+	
+	return prev_cgpu;
+}
+
+static
+int neptune_detect_auto(void)
+{
+	if (neptune_detect_one("/dev/spidev1.0"))
+		return 1;
+	return 0;
+}
+
+static
+void neptune_detect(void)
+{
+	generic_detect(&neptune_drv, neptune_detect_one, neptune_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
+}
+
+struct device_drv neptune_drv = {
+	.dname = "neptune",
+	.name = "NEP",
+	.drv_detect = neptune_detect,
+};

+ 4 - 2
lowl-spi.c

@@ -270,12 +270,14 @@ void *spi_emit_buf_reverse(struct spi_port *port, const void *p, size_t sz)
 	return rv;
 }
 
-void spi_emit_buf(struct spi_port * const port, const void * const str, const size_t sz)
+void *spi_emit_buf(struct spi_port * const port, const void * const str, const size_t sz)
 {
+	void * const rv = &port->spibuf_rx[port->spibufsz];
 	if (port->spibufsz + sz >= SPIMAXSZ)
-		return;
+		return NULL;
 	memcpy(&port->spibuf[port->spibufsz], str, sz);
 	port->spibufsz += sz;
+	return rv;
 }
 
 /* TODO: in production, emit just bit-sequences! Eliminate padding to byte! */

+ 1 - 1
lowl-spi.h

@@ -68,7 +68,7 @@ size_t spi_getbufsz(struct spi_port *port)
 	return port->spibufsz;
 }
 
-extern void spi_emit_buf(struct spi_port *, const void *, size_t);
+extern void *spi_emit_buf(struct spi_port *, const void *, size_t);
 
 extern void spi_emit_break(struct spi_port *port); /* BREAK CONNECTIONS AFTER RESET */
 extern void spi_emit_fsync(struct spi_port *port); /* FEED-THROUGH TO NEXT CHIP SYNCHRONOUSLY (WITH FLIP-FLOP) */