Browse Source

Abstract UIO-specific code from bitforce driver into lowl-pci

Luke Dashjr 12 years ago
parent
commit
b43033f8fa
4 changed files with 302 additions and 96 deletions
  1. 1 1
      Makefile.am
  2. 33 95
      driver-bitforce.c
  3. 200 0
      lowl-pci.c
  4. 68 0
      lowl-pci.h

+ 1 - 1
Makefile.am

@@ -300,7 +300,7 @@ bfgminer_CPPFLAGS += $(hidapi_CFLAGS)
 endif
 endif
 
 
 if NEED_BFG_LOWL_PCI
 if NEED_BFG_LOWL_PCI
-bfgminer_SOURCES += lowl-pci.c
+bfgminer_SOURCES += lowl-pci.c lowl-pci.h
 endif
 endif
 
 
 bin_PROGRAMS += bfgminer-rpc
 bin_PROGRAMS += bfgminer-rpc

+ 33 - 95
driver-bitforce.c

@@ -16,22 +16,16 @@
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <string.h>
 #include <strings.h>
 #include <strings.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
-#ifdef HAVE_SYS_MMAN_H
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#endif
-
 #include "compat.h"
 #include "compat.h"
 #include "deviceapi.h"
 #include "deviceapi.h"
 #include "miner.h"
 #include "miner.h"
 #include "lowlevel.h"
 #include "lowlevel.h"
+#include "lowl-pci.h"
 #include "lowl-vcom.h"
 #include "lowl-vcom.h"
 #include "util.h"
 #include "util.h"
 
 
@@ -91,7 +85,7 @@ struct bitforce_lowl_interface {
 struct bitforce_data {
 struct bitforce_data {
 	struct bitforce_lowl_interface *lowlif;
 	struct bitforce_lowl_interface *lowlif;
 	bool is_open;
 	bool is_open;
-	volatile uint32_t *bar[3];
+	struct lowl_pci_handle *lph;
 	uint8_t lasttag;
 	uint8_t lasttag;
 	bytes_t getsbuf;
 	bytes_t getsbuf;
 	int xlink_id;
 	int xlink_id;
@@ -176,89 +170,55 @@ static struct bitforce_lowl_interface bfllif_vcom = {
 	.write = bitforce_vcom_write,
 	.write = bitforce_vcom_write,
 };
 };
 
 
-#ifdef HAVE_SYS_MMAN_H
+#ifdef NEED_BFG_LOWL_PCI
 static
 static
-void *bitforce_mmap_bar(const char * const devpath, const int bar, const size_t sz, const int prot)
+bool bitforce_pci_open(struct cgpu_info * const dev)
 {
 {
-	char buf[0x100];
-	snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/resource%d", devpath, bar);
-	const int fd = open(buf, O_RDWR);
-	if (fd == -1)
-		return MAP_FAILED;
-	void * const rv = mmap(NULL, sz, prot, MAP_SHARED, fd, 0);
-	close(fd);
-	return rv;
-}
-
-static
-bool bitforce_uio_open(struct cgpu_info * const dev)
-{
-	struct bitforce_data * const devdata = dev->device_data;
 	const char * const devpath = dev->device_path;
 	const char * const devpath = dev->device_path;
-	devdata->bar[0] = bitforce_mmap_bar(devpath, 0, 0x1000, PROT_WRITE);
-	if (devdata->bar[0] == MAP_FAILED)
-	{
-		applog(LOG_ERR, "%s: mmap bar 0 failed", dev->dev_repr);
-mapfailA:
-		devdata->bar[0] = NULL;
+	struct bitforce_data * const devdata = dev->device_data;
+	devdata->lph = lowl_pci_open(devpath, LP_BARINFO(
+		LP_BAR(0, 0x1000, O_WRONLY),
+		LP_BAR(1, 0x1000, O_RDONLY),
+		LP_BAR(2,   0x80, O_RDWR),
+	));
+	if (!devdata->lph)
 		return false;
 		return false;
-	}
-	devdata->bar[1] = bitforce_mmap_bar(devpath, 1, 0x1000, PROT_READ);
-	if (devdata->bar[1] == MAP_FAILED)
-	{
-		applog(LOG_ERR, "%s: mmap bar 1 failed", dev->dev_repr);
-mapfailB:
-		munmap((void*)devdata->bar[0], 0x1000);
-		goto mapfailA;
-	}
-	devdata->bar[2] = bitforce_mmap_bar(devpath, 2,   0x80, PROT_READ | PROT_WRITE);
-	if (devdata->bar[2] == MAP_FAILED)
-	{
-		applog(LOG_ERR, "%s: mmap bar 2 failed", dev->dev_repr);
-		munmap((void*)devdata->bar[1], 0x1000);
-		goto mapfailB;
-	}
-	const volatile uint32_t * const respreg = &devdata->bar[2][2];
-	devdata->lasttag = (*respreg >> 16) & 0xff;
+	devdata->lasttag = (lowl_pci_get_word(devdata->lph, 2, 2) >> 16) & 0xff;
 	devdata->is_open = true;
 	devdata->is_open = true;
 	return devdata->is_open;
 	return devdata->is_open;
 }
 }
 
 
 static
 static
-void bitforce_uio_close(struct cgpu_info * const dev)
+void bitforce_pci_close(struct cgpu_info * const dev)
 {
 {
 	struct bitforce_data * const devdata = dev->device_data;
 	struct bitforce_data * const devdata = dev->device_data;
 	if (devdata->is_open)
 	if (devdata->is_open)
 	{
 	{
-		munmap((void*)devdata->bar[0], 0x1000);
-		munmap((void*)devdata->bar[1], 0x1000);
-		munmap((void*)devdata->bar[2],   0x80);
+		lowl_pci_close(devdata->lph);
 		devdata->is_open = false;
 		devdata->is_open = false;
 	}
 	}
 }
 }
 
 
 static
 static
-void bitforce_uio_gets(char * const buf, size_t bufLen, struct cgpu_info * const dev)
+void bitforce_pci_gets(char * const buf, size_t bufLen, struct cgpu_info * const dev)
 {
 {
 	struct bitforce_data * const devdata = dev->device_data;
 	struct bitforce_data * const devdata = dev->device_data;
-	const volatile uint32_t * const respreg = &devdata->bar[2][2];
-	const volatile uint32_t *respdata = devdata->bar[1];
 	const uint32_t looking_for = (uint32_t)devdata->lasttag << 0x10;
 	const uint32_t looking_for = (uint32_t)devdata->lasttag << 0x10;
 	uint32_t resp;
 	uint32_t resp;
 	bytes_t *b = &devdata->getsbuf;
 	bytes_t *b = &devdata->getsbuf;
 	
 	
 	if (!bytes_len(&devdata->getsbuf))
 	if (!bytes_len(&devdata->getsbuf))
 	{
 	{
-		while (((resp = *respreg) & 0xff0000) != looking_for)
+		while (((resp = lowl_pci_get_word(devdata->lph, 2, 2)) & 0xff0000) != looking_for)
 			cgsleep_ms(1);
 			cgsleep_ms(1);
 		
 		
 		resp &= 0xffff;
 		resp &= 0xffff;
 		if (unlikely(resp > 0x1000))
 		if (unlikely(resp > 0x1000))
 			resp = 0x1000;
 			resp = 0x1000;
 		
 		
-		const uint32_t respwords = (resp + 3) / 4;
-		swap32tobe(bytes_preappend(b, respwords * 4), (void*)respdata, respwords);
-		bytes_postappend(b, resp);
+		void * const buf = bytes_preappend(b, resp + LOWL_PCI_GET_DATA_PADDING);
+		if (lowl_pci_read_data(devdata->lph, buf, resp, 1, 0))
+			bytes_postappend(b, resp);
 	}
 	}
 	
 	
 	ssize_t linelen = (bytes_find(b, '\n') + 1) ?: bytes_len(b);
 	ssize_t linelen = (bytes_find(b, '\n') + 1) ?: bytes_len(b);
@@ -271,51 +231,29 @@ void bitforce_uio_gets(char * const buf, size_t bufLen, struct cgpu_info * const
 }
 }
 
 
 static
 static
-ssize_t bitforce_uio_write(struct cgpu_info * const dev, const void * const bufp, ssize_t bufLen)
+ssize_t bitforce_pci_write(struct cgpu_info * const dev, const void * const bufp, ssize_t bufLen)
 {
 {
 	const uint8_t *buf = bufp;
 	const uint8_t *buf = bufp;
 	struct bitforce_data * const devdata = dev->device_data;
 	struct bitforce_data * const devdata = dev->device_data;
-	volatile uint32_t * const cmdreg = &devdata->bar[2][0];
-	volatile uint32_t * cmdbuf = devdata->bar[0];
-	uint32_t lastu32;
 	
 	
 	if (unlikely(bufLen > 0x1000))
 	if (unlikely(bufLen > 0x1000))
 		return 0;
 		return 0;
 	
 	
-	while (bufLen > 3)
-	{
-		*(cmdbuf++) = ((uint32_t)buf[0] << 0x18)
-		            | ((uint32_t)buf[1] << 0x10)
-		            | ((uint16_t)buf[2] <<    8)
-		            | buf[3];
-		buf += 4;
-		bufLen -= 4;
-	}
-	lastu32 = 0;
-	switch (bufLen)
-	{
-		case 3:
-			lastu32 |= ((uint16_t)buf[2] <<    8);
-		case 2:
-			lastu32 |= ((uint32_t)buf[1] << 0x10);
-		case 1:
-			lastu32 |= ((uint32_t)buf[0] << 0x18);
-			*cmdbuf = lastu32;
-		default:
-			;
-	}
+	if (!lowl_pci_set_data(devdata->lph, buf, bufLen, 0, 0))
+		return 0;
 	if (++devdata->lasttag == 0)
 	if (++devdata->lasttag == 0)
 		++devdata->lasttag;
 		++devdata->lasttag;
-	*cmdreg = ((uint32_t)devdata->lasttag << 0x10) | bufLen;
+	if (!lowl_pci_set_word(devdata->lph, 2, 0, ((uint32_t)devdata->lasttag << 0x10) | bufLen))
+		return 0;
 	
 	
 	return bufLen;
 	return bufLen;
 }
 }
 
 
-static struct bitforce_lowl_interface bfllif_uio = {
-	.open = bitforce_uio_open,
-	.close = bitforce_uio_close,
-	.gets = bitforce_uio_gets,
-	.write = bitforce_uio_write,
+static struct bitforce_lowl_interface bfllif_pci = {
+	.open = bitforce_pci_open,
+	.close = bitforce_pci_close,
+	.gets = bitforce_pci_gets,
+	.write = bitforce_pci_write,
 };
 };
 #endif
 #endif
 
 
@@ -462,7 +400,7 @@ int bitforce_chips_to_plan_for(int parallel, int chipcount) {
 static
 static
 bool bitforce_lowl_match(const struct lowlevel_device_info * const info)
 bool bitforce_lowl_match(const struct lowlevel_device_info * const info)
 {
 {
-#ifdef HAVE_SYS_MMAN_H
+#ifdef NEED_BFG_LOWL_PCI
 	if (info->lowl == &lowl_pci)
 	if (info->lowl == &lowl_pci)
 		return info->vid == BFL_PCI_VENDOR_ID;
 		return info->vid == BFL_PCI_VENDOR_ID;
 #endif
 #endif
@@ -647,9 +585,9 @@ bool bitforce_detect_one(const char * const devpath)
 static
 static
 bool bitforce_lowl_probe(const struct lowlevel_device_info * const info)
 bool bitforce_lowl_probe(const struct lowlevel_device_info * const info)
 {
 {
-#ifdef HAVE_SYS_MMAN_H
+#ifdef NEED_BFG_LOWL_PCI
 	if (info->lowl == &lowl_pci)
 	if (info->lowl == &lowl_pci)
-		return bitforce_detect_oneof(info->path, &bfllif_uio);
+		return bitforce_detect_oneof(info->path, &bfllif_pci);
 #endif
 #endif
 	return vcom_lowl_probe_wrapper(info, bitforce_detect_one);
 	return vcom_lowl_probe_wrapper(info, bitforce_detect_one);
 }
 }

+ 200 - 0
lowl-pci.c

@@ -9,16 +9,24 @@
 
 
 #include "config.h"
 #include "config.h"
 
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 
 #include <utlist.h>
 #include <utlist.h>
 
 
+#include <sys/mman.h>
+
+#include "logging.h"
 #include "lowlevel.h"
 #include "lowlevel.h"
+#include "lowl-pci.h"
+#include "miner.h"
 #include "util.h"
 #include "util.h"
 
 
 static
 static
@@ -63,6 +71,198 @@ struct lowlevel_device_info *pci_devinfo_scan()
 	return devinfo_list;
 	return devinfo_list;
 }
 }
 
 
+struct lowl_pci_interface {
+	struct lowl_pci_handle *(*open)(const char *path, const struct _lowl_pci_config *);
+	void (*close)(struct lowl_pci_handle *);
+	const uint32_t *(*get_words)(struct lowl_pci_handle *, void *buf, size_t words, int bar, off_t);
+	const void *(*get_data)(struct lowl_pci_handle *, void *buf, size_t, int bar, off_t);
+	bool (*set_words)(struct lowl_pci_handle *, const uint32_t *, size_t, int bar, off_t);
+	bool (*set_data)(struct lowl_pci_handle *, const void *, size_t, int bar, off_t);
+};
+
+struct lowl_pci_handle {
+	const char *path;
+	const struct lowl_pci_interface *lpi;
+	uint32_t *bar[6];
+	size_t barsz[6];
+};
+
+static
+void lowl_pci_close_mmap(struct lowl_pci_handle * const lph)
+{
+	for (int i = 0; i < 6; ++i)
+		if (lph->bar[i])
+			munmap(lph->bar[i], lph->barsz[i]);
+	free(lph);
+}
+
+static
+const uint32_t *lowl_pci_get_words_mmap(struct lowl_pci_handle * const lph, void * const buf, const size_t words, const int bar, const off_t offset)
+{
+	return &lph->bar[bar][offset];
+}
+
+static
+bool lowl_pci_set_words_mmap(struct lowl_pci_handle * const lph, const uint32_t *buf, const size_t words, const int bar, const off_t offset)
+{
+	uint32_t *dest = &lph->bar[bar][offset];
+	for (int i = 0; i < words; ++i)
+		*(dest++) = *(buf++);
+	return true;
+}
+
+static
+const void *lowl_pci_get_data_from_words(struct lowl_pci_handle * const lph, void * const bufp, const size_t sz, const int bar, const off_t offset)
+{
+	uint8_t * const buf = bufp;
+	const off_t offset32 = offset / 4;
+	const off_t offset8  = offset % 4;
+	const size_t words = (sz + offset8 + 3) / 4;
+	const uint32_t * const wdata = lowl_pci_get_words(lph, buf, words, bar, offset32);
+	swap32tobe(buf, wdata, words);
+	return &buf[offset8];
+}
+
+static
+bool lowl_pci_set_data_in_words(struct lowl_pci_handle * const lph, const void * const bufp, size_t sz, const int bar, const off_t offset)
+{
+	const uint8_t *buf = bufp;
+	const off_t offset32 = offset / 4;
+	off_t offset8  = offset % 4;
+	const size_t words = (sz + offset8 + 3) / 4;
+	uint32_t wdata[words], *wdp = wdata;
+	if (offset8)
+	{
+		const uint32_t * const p = lowl_pci_get_words(lph, wdata, 1, bar, offset32);
+		if (unlikely(!p))
+			return false;
+		wdata[0] = *p >> (32 - (8 * offset8));
+	}
+	for ( ; sz; --sz)
+	{
+		*wdp = (*wdp << 8) | *(buf++);
+		if (++offset8 == 4)
+		{
+			offset8 = 0;
+			++wdp;
+		}
+	}
+	if (offset8)
+	{
+		uint32_t u;
+		const uint32_t * const p = lowl_pci_get_words(lph, &u, 1, bar, offset32 + words - 1);
+		if (unlikely(!p))
+			return false;
+		const int n = 32 - (8 * offset8);
+		wdp[0] <<= n;
+		wdp[0] |= *p & ((1 << n) - 1);
+	}
+	return lowl_pci_set_words(lph, wdata, words, bar, offset32);
+}
+
+static const struct lowl_pci_interface lpi_uio;
+
+static
+int _file_mode_to_mmap_prot(const int mode)
+{
+	switch (mode)
+	{
+		case O_RDONLY:
+			return PROT_READ;
+		case O_WRONLY:
+			return PROT_WRITE;
+		case O_RDWR:
+			return PROT_READ | PROT_WRITE;
+		default:
+			return -1;
+	}
+}
+
+static
+void *_uio_mmap_bar(const char * const path, const int bar, const size_t sz, const int prot)
+{
+	char buf[0x100];
+	snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/resource%d", path, bar);
+	const int fd = open(buf, O_RDWR);
+	if (fd == -1)
+		return MAP_FAILED;
+	void * const rv = mmap(NULL, sz, prot, MAP_SHARED, fd, 0);
+	close(fd);
+	return rv;
+}
+
+struct lowl_pci_handle *lowl_pci_open_uio(const char * const path, const struct _lowl_pci_config * const barcfgs)
+{
+	struct lowl_pci_handle * const lph = malloc(sizeof(*lph));
+	*lph = (struct lowl_pci_handle){
+		.path = path,
+		.lpi = &lpi_uio,
+	};
+	for (const struct _lowl_pci_config *barcfg = barcfgs; barcfg->bar != -1; ++barcfg)
+	{
+		const int barno = barcfg->bar;
+		const int prot = _file_mode_to_mmap_prot(barcfg->mode);
+		if (unlikely(prot == -1))
+			goto err;
+		lph->bar[barno] = _uio_mmap_bar(path, barno, barcfg->sz, prot);
+		lph->barsz[barno] = barcfg->sz;
+		if (lph->bar[barno] == MAP_FAILED)
+		{
+			applog(LOG_ERR, "mmap %s bar %d failed", path, barno);
+			goto err;
+		}
+	}
+	return lph;
+
+err:
+	for (int i = 0; i < 6; ++i)
+		if (lph->bar[i])
+			munmap(lph->bar[i], lph->barsz[i]);
+	free(lph);
+	return NULL;
+}
+
+static const struct lowl_pci_interface lpi_uio = {
+	.open = lowl_pci_open_uio,
+	.close = lowl_pci_close_mmap,
+	.get_words = lowl_pci_get_words_mmap,
+	.get_data  = lowl_pci_get_data_from_words,
+	.set_words = lowl_pci_set_words_mmap,
+	.set_data  = lowl_pci_set_data_in_words,
+};
+
+struct lowl_pci_handle *lowl_pci_open(const char * const path, const struct _lowl_pci_config * const barcfgs)
+{
+	return
+		lpi_uio.open(path, barcfgs) ?:
+		false;
+}
+
+const uint32_t *lowl_pci_get_words(struct lowl_pci_handle * const lph, void * const buf, const size_t words, const int bar, const off_t offset)
+{
+	return lph->lpi->get_words(lph, buf, words, bar, offset);
+}
+
+const void *lowl_pci_get_data(struct lowl_pci_handle * const lph, void * const buf, const size_t sz, const int bar, const off_t offset)
+{
+	return lph->lpi->get_data(lph, buf, sz, bar, offset);
+}
+
+bool lowl_pci_set_words(struct lowl_pci_handle * const lph, const uint32_t * const buf, const size_t words, const int bar, const off_t offset)
+{
+	return lph->lpi->set_words(lph, buf, words, bar, offset);
+}
+
+bool lowl_pci_set_data(struct lowl_pci_handle * const lph, const void * const buf, const size_t sz, const int bar, const off_t offset)
+{
+	return lph->lpi->set_data(lph, buf, sz, bar, offset);
+}
+
+void lowl_pci_close(struct lowl_pci_handle * const lph)
+{
+	return lph->lpi->close(lph);
+}
+
 struct lowlevel_driver lowl_pci = {
 struct lowlevel_driver lowl_pci = {
 	.dname = "pci",
 	.dname = "pci",
 	.devinfo_scan = pci_devinfo_scan,
 	.devinfo_scan = pci_devinfo_scan,

+ 68 - 0
lowl-pci.h

@@ -0,0 +1,68 @@
+#ifndef BFG_LOWL_PCI_H
+#define BFG_LOWL_PCI_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+struct lowl_pci_handle;
+
+struct _lowl_pci_config {
+	int bar;
+	size_t sz;
+	int mode;
+};
+extern struct lowl_pci_handle *lowl_pci_open(const char *, const struct _lowl_pci_config *);
+#define LP_BARINFO(...)  (struct _lowl_pci_config[]){__VA_ARGS__ { .bar = -1 }}
+#define LP_BAR(barno, size, mode)  {barno, size, mode}
+extern void lowl_pci_close(struct lowl_pci_handle *);
+
+// Don't assume buf is used in any specific way! Memory returned may be mmap'd (and thus change after call)
+extern const uint32_t *lowl_pci_get_words(struct lowl_pci_handle *, void *buf, size_t words, int bar, off_t);
+extern bool lowl_pci_set_words(struct lowl_pci_handle *, const uint32_t *, size_t, int bar, off_t);
+// buf passed to lowl_pci_get_data must have at least LOWL_PCI_GET_DATA_PADDING bytes more than size to read
+#define LOWL_PCI_GET_DATA_PADDING 6
+extern const void *lowl_pci_get_data(struct lowl_pci_handle *, void *buf, size_t, int bar, off_t);
+extern bool lowl_pci_set_data(struct lowl_pci_handle *, const void *, size_t, int bar, off_t);
+
+static inline
+uint32_t lowl_pci_get_word(struct lowl_pci_handle * const lph, const int bar, const off_t offset)
+{
+	uint32_t buf[1];
+	const uint32_t * const p = lowl_pci_get_words(lph, buf, 1, bar, offset);
+	if (!p)
+		return 0;
+	return *p;
+}
+
+static inline
+bool lowl_pci_set_word(struct lowl_pci_handle * const lph, const int bar, const off_t offset, const uint32_t val)
+{
+	return lowl_pci_set_words(lph, &val, 1, bar, offset);
+}
+
+static inline
+bool lowl_pci_read_words(struct lowl_pci_handle * const lph, void * const buf, const size_t words, const int bar, const off_t offset)
+{
+	const void * const p = lowl_pci_get_words(lph, buf, words, bar, offset);
+	if (!p)
+		return false;
+	if (buf != p)
+		memmove(buf, p, words * 4);
+	return true;
+}
+
+static inline
+bool lowl_pci_read_data(struct lowl_pci_handle * const lph, void * const buf, const size_t sz, const int bar, const off_t offset)
+{
+	const void * const p = lowl_pci_get_data(lph, buf, sz, bar, offset);
+	if (!p)
+		return false;
+	if (buf != p)
+		memmove(buf, p, sz);
+	return true;
+}
+
+#endif