Browse Source

x6500: Get FPGA probe working

Luke Dashjr 13 years ago
parent
commit
fadf8ca591
6 changed files with 101 additions and 19 deletions
  1. 58 1
      driver-x6500.c
  2. 29 13
      ft232r.c
  3. 2 0
      ft232r.h
  4. 7 5
      jtag.c
  5. 2 0
      jtag.h
  6. 3 0
      miner.h

+ 58 - 1
driver-x6500.c

@@ -10,6 +10,7 @@
 #include <libusb-1.0/libusb.h>
 #include <libusb-1.0/libusb.h>
 
 
 #include "dynclock.h"
 #include "dynclock.h"
+#include "jtag.h"
 #include "logging.h"
 #include "logging.h"
 #include "miner.h"
 #include "miner.h"
 #include "fpgautils.h"
 #include "fpgautils.h"
@@ -56,11 +57,67 @@ static void x6500_detect()
 	serial_detect_auto(&x6500_api, x6500_detect_one, x6500_detect_auto);
 	serial_detect_auto(&x6500_api, x6500_detect_one, x6500_detect_auto);
 }
 }
 
 
+static bool x6500_prepare(struct thr_info *thr)
+{
+	if (thr->device_thread)
+		return true;
+	
+	struct cgpu_info *x6500 = thr->cgpu;
+	mutex_init(&x6500->device_mutex);
+	struct ft232r_device_handle *ftdi = ft232r_open(x6500->cgpu_data);
+	x6500->cgpu_data = NULL;
+	if (!ftdi)
+		return false;
+	if (!ft232r_set_bitmode(ftdi, 0xee, 4))
+		return false;
+	if (!ft232r_purge_buffers(ftdi, FTDI_PURGE_BOTH))
+		return false;
+	x6500->device_ft232r = ftdi;
+	x6500->cgpu_data = calloc(1, 1);
+	
+	return true;
+}
+
+struct x6500_fpga_data {
+	struct jtag_port jtag;
+};
+
+static bool x6500_fpga_init(struct thr_info *thr)
+{
+	struct cgpu_info *x6500 = thr->cgpu;
+	struct ft232r_device_handle *ftdi = x6500->device_ft232r;
+	struct x6500_fpga_data *fpga;
+	uint8_t pinoffset = thr->device_thread ? 0x10 : 1;
+	
+	if (!ftdi)
+		return false;
+	
+	fpga = calloc(1, sizeof(*fpga));
+	fpga->jtag.ftdi = ftdi;
+	fpga->jtag.tck = pinoffset << 3;
+	fpga->jtag.tms = pinoffset << 2;
+	fpga->jtag.tdi = pinoffset << 1;
+	fpga->jtag.tdo = pinoffset << 0;
+	fpga->jtag.ignored = ~(fpga->jtag.tdo | fpga->jtag.tdi | fpga->jtag.tms | fpga->jtag.tck);
+	fpga->jtag.state = x6500->cgpu_data;
+	
+	applog(LOG_ERR, "jtag pins: tck=%02x tms=%02x tdi=%02x tdo=%02x", pinoffset << 3, pinoffset << 2, pinoffset << 1, pinoffset << 0);
+	
+	mutex_lock(&x6500->device_mutex);
+	if (!jtag_reset(&fpga->jtag)) {
+		applog(LOG_ERR, "jtag reset failed");
+		return false;
+	}
+	applog(LOG_ERR, "jtag detect returned %d", (int)jtag_detect(&fpga->jtag));
+	mutex_unlock(&x6500->device_mutex);
+}
+
 struct device_api x6500_api = {
 struct device_api x6500_api = {
 	.dname = "x6500",
 	.dname = "x6500",
 	.name = "XBS",
 	.name = "XBS",
 	.api_detect = x6500_detect,
 	.api_detect = x6500_detect,
-// 	.thread_init = x6500_fpga_init,
+	.thread_prepare = x6500_prepare,
+	.thread_init = x6500_fpga_init,
 // 	.scanhash = x6500_fpga_scanhash,
 // 	.scanhash = x6500_fpga_scanhash,
 // 	.thread_shutdown = x6500_fpga_shutdown,
 // 	.thread_shutdown = x6500_fpga_shutdown,
 };
 };

+ 29 - 13
ft232r.c

@@ -138,6 +138,7 @@ int ft232r_detect(const char *product_needle, const char *serial, foundusb_func_
 #define FTDI_REQUEST_RESET           0
 #define FTDI_REQUEST_RESET           0
 #define FTDI_REQUEST_SET_BAUDRATE    3
 #define FTDI_REQUEST_SET_BAUDRATE    3
 #define FTDI_REQUEST_SET_BITMODE  0x0b
 #define FTDI_REQUEST_SET_BITMODE  0x0b
+#define FTDI_REQUEST_GET_PINS     0x0c
 
 
 #define FTDI_BAUDRATE_3M  0,0
 #define FTDI_BAUDRATE_3M  0,0
 
 
@@ -162,6 +163,7 @@ struct ft232r_device_handle *ft232r_open(libusb_device *dev)
 		applog(LOG_ERR, "ft232r_open: Error opening device");
 		applog(LOG_ERR, "ft232r_open: Error opening device");
 		return NULL;
 		return NULL;
 	}
 	}
+	libusb_reset_device(devh);
 	libusb_detach_kernel_driver(devh, 0);
 	libusb_detach_kernel_driver(devh, 0);
 	if (libusb_set_configuration(devh, 1)) {
 	if (libusb_set_configuration(devh, 1)) {
 		applog(LOG_ERR, "ft232r_open: Error setting configuration");
 		applog(LOG_ERR, "ft232r_open: Error setting configuration");
@@ -171,10 +173,6 @@ struct ft232r_device_handle *ft232r_open(libusb_device *dev)
 		applog(LOG_ERR, "ft232r_open: Error claiming interface");
 		applog(LOG_ERR, "ft232r_open: Error claiming interface");
 		return NULL;
 		return NULL;
 	}
 	}
-	if (libusb_set_interface_alt_setting(devh, 0, 0)) {
-		applog(LOG_ERR, "ft232r_open: Error setting interface alt");
-		return NULL;
-	}
 	if (libusb_control_transfer(devh, FTDI_REQTYPE_OUT, FTDI_REQUEST_SET_BAUDRATE, FTDI_BAUDRATE_3M, NULL, 0, FTDI_TIMEOUT) < 0) {
 	if (libusb_control_transfer(devh, FTDI_REQTYPE_OUT, FTDI_REQUEST_SET_BAUDRATE, FTDI_BAUDRATE_3M, NULL, 0, FTDI_TIMEOUT) < 0) {
 		applog(LOG_ERR, "ft232r_open: Error performing control transfer");
 		applog(LOG_ERR, "ft232r_open: Error performing control transfer");
 		return NULL;
 		return NULL;
@@ -184,7 +182,7 @@ struct ft232r_device_handle *ft232r_open(libusb_device *dev)
 	ftdi->h = devh;
 	ftdi->h = devh;
 
 
 	struct libusb_config_descriptor *cfg;
 	struct libusb_config_descriptor *cfg;
-	if (libusb_get_config_descriptor(dev, 1, &cfg)) {
+	if (libusb_get_config_descriptor(dev, 0, &cfg)) {
 		applog(LOG_ERR, "ft232r_open: Error getting config descriptor");
 		applog(LOG_ERR, "ft232r_open: Error getting config descriptor");
 		return NULL;
 		return NULL;
 	}
 	}
@@ -200,6 +198,13 @@ struct ft232r_device_handle *ft232r_open(libusb_device *dev)
 	return ftdi;
 	return ftdi;
 }
 }
 
 
+void ft232r_close(struct ft232r_device_handle *dev)
+{
+	libusb_release_interface(dev->h, 0);
+	libusb_reset_device(dev->h);
+	libusb_close(dev->h);
+}
+
 bool ft232r_purge_buffers(struct ft232r_device_handle *dev, enum ft232r_reset_purge purge)
 bool ft232r_purge_buffers(struct ft232r_device_handle *dev, enum ft232r_reset_purge purge)
 {
 {
 	if (purge & FTDI_PURGE_RX)
 	if (purge & FTDI_PURGE_RX)
@@ -213,6 +218,8 @@ bool ft232r_purge_buffers(struct ft232r_device_handle *dev, enum ft232r_reset_pu
 
 
 bool ft232r_set_bitmode(struct ft232r_device_handle *dev, uint8_t mask, uint8_t mode)
 bool ft232r_set_bitmode(struct ft232r_device_handle *dev, uint8_t mask, uint8_t mode)
 {
 {
+	if (libusb_control_transfer(dev->h, FTDI_REQTYPE_OUT, FTDI_REQUEST_SET_BITMODE, mask, FTDI_INDEX, NULL, 0, FTDI_TIMEOUT))
+		return false;
 	return !libusb_control_transfer(dev->h, FTDI_REQTYPE_OUT, FTDI_REQUEST_SET_BITMODE, (mode << 8) | mask, FTDI_INDEX, NULL, 0, FTDI_TIMEOUT);
 	return !libusb_control_transfer(dev->h, FTDI_REQTYPE_OUT, FTDI_REQUEST_SET_BITMODE, (mode << 8) | mask, FTDI_INDEX, NULL, 0, FTDI_TIMEOUT);
 }
 }
 
 
@@ -260,20 +267,24 @@ ssize_t ft232r_write_all(struct ft232r_device_handle *dev, void *data, size_t co
 
 
 ssize_t ft232r_read(struct ft232r_device_handle *dev, void *data, size_t count)
 ssize_t ft232r_read(struct ft232r_device_handle *dev, void *data, size_t count)
 {
 {
-	if (!dev->ibufLen) {
+	// First 2 bytes are FTDI status or something
+	while (dev->ibufLen <= 2) {
+		// TODO: Implement a timeout for status byte repeating
 		int transferred = ft232r_readwrite(dev, dev->i, dev->ibuf, sizeof(dev->ibuf));
 		int transferred = ft232r_readwrite(dev, dev->i, dev->ibuf, sizeof(dev->ibuf));
 		if (transferred <= 0)
 		if (transferred <= 0)
 			return transferred;
 			return transferred;
 		dev->ibufLen = transferred;
 		dev->ibufLen = transferred;
 	}
 	}
+	unsigned char *ibufs = &dev->ibuf[2];
+	size_t ibufsLen = dev->ibufLen - 2;
 	
 	
-	if (count > dev->ibufLen)
-		count = dev->ibufLen;
-	memcpy(data, dev->ibuf, count);
-	if (count < dev->ibufLen) {
-		dev->ibufLen -= count;
-		memmove(dev->ibuf, &dev->ibuf[count], dev->ibufLen);
-	}
+	if (count > ibufsLen)
+		count = ibufsLen;
+	memcpy(data, ibufs, count);
+	dev->ibufLen -= count;
+	ibufsLen -= count;
+	if (ibufsLen)
+		memmove(ibufs, &ibufs[count], ibufsLen);
 	return count;
 	return count;
 }
 }
 
 
@@ -282,6 +293,11 @@ ssize_t ft232r_read_all(struct ft232r_device_handle *dev, void *data, size_t cou
 	return ft232r_rw_all(ft232r_read, dev, data, count);
 	return ft232r_rw_all(ft232r_read, dev, data, count);
 }
 }
 
 
+bool ft232r_get_pins(struct ft232r_device_handle *dev, uint8_t *pins)
+{
+	return libusb_control_transfer(dev->h, FTDI_REQTYPE_IN, FTDI_REQUEST_GET_PINS, 0, FTDI_INDEX, pins, 1, FTDI_TIMEOUT) == 1;
+}
+
 #if 0
 #if 0
 int main() {
 int main() {
 	libusb_init(NULL);
 	libusb_init(NULL);

+ 2 - 0
ft232r.h

@@ -29,11 +29,13 @@ extern void ft232r_scan();
 extern void ft232r_scan_free();
 extern void ft232r_scan_free();
 extern int ft232r_detect(const char *product_needle, const char *serial, foundusb_func_t);
 extern int ft232r_detect(const char *product_needle, const char *serial, foundusb_func_t);
 extern struct ft232r_device_handle *ft232r_open(libusb_device *);
 extern struct ft232r_device_handle *ft232r_open(libusb_device *);
+extern void ft232r_close(struct ft232r_device_handle *);
 extern bool ft232r_purge_buffers(struct ft232r_device_handle *, enum ft232r_reset_purge);
 extern bool ft232r_purge_buffers(struct ft232r_device_handle *, enum ft232r_reset_purge);
 extern bool ft232r_set_bitmode(struct ft232r_device_handle *, uint8_t mask, uint8_t mode);
 extern bool ft232r_set_bitmode(struct ft232r_device_handle *, uint8_t mask, uint8_t mode);
 extern ssize_t ft232r_write(struct ft232r_device_handle *, void *data, size_t count);
 extern ssize_t ft232r_write(struct ft232r_device_handle *, void *data, size_t count);
 extern ssize_t ft232r_write_all(struct ft232r_device_handle *, void *data, size_t count);
 extern ssize_t ft232r_write_all(struct ft232r_device_handle *, void *data, size_t count);
 extern ssize_t ft232r_read(struct ft232r_device_handle *, void *buf, size_t count);
 extern ssize_t ft232r_read(struct ft232r_device_handle *, void *buf, size_t count);
 extern ssize_t ft232r_read_all(struct ft232r_device_handle *, void *data, size_t count);
 extern ssize_t ft232r_read_all(struct ft232r_device_handle *, void *data, size_t count);
+extern bool ft232r_get_pins(struct ft232r_device_handle *, uint8_t *pins);
 
 
 #endif
 #endif

+ 7 - 5
jtag.c

@@ -20,16 +20,18 @@
 // NOTE: The order of tms and tdi here are inverted from LPC1343CodeBase
 // NOTE: The order of tms and tdi here are inverted from LPC1343CodeBase
 bool jtag_clock(struct jtag_port *jp, bool tms, bool tdi, bool *tdo)
 bool jtag_clock(struct jtag_port *jp, bool tms, bool tdi, bool *tdo)
 {
 {
-	unsigned char buf[4];
-	memset(buf, (tms ? (1 << jp->tms) : 0)
-	          | (tdi ? (1 << jp->tdi) : 0), sizeof(buf));
-	buf[1] |= jp->tck;
+	unsigned char buf[3];
+	memset(buf, (*jp->state & jp->ignored)
+	          | (tms ? jp->tms : 0)
+	          | (tdi ? jp->tdi : 0), sizeof(buf));
+	buf[0] |= jp->tck;
 	if (ft232r_write_all(jp->ftdi, buf, sizeof(buf)) != sizeof(buf))
 	if (ft232r_write_all(jp->ftdi, buf, sizeof(buf)) != sizeof(buf))
 		return false;
 		return false;
 	if (ft232r_read_all(jp->ftdi, buf, sizeof(buf)) != sizeof(buf))
 	if (ft232r_read_all(jp->ftdi, buf, sizeof(buf)) != sizeof(buf))
 		return false;
 		return false;
 	if (tdo)
 	if (tdo)
-		*tdo = buf[3] & jp->tdo;
+		*tdo = (buf[2] & jp->tdo);
+	*jp->state = buf[2];
 	return true;
 	return true;
 }
 }
 
 

+ 2 - 0
jtag.h

@@ -11,6 +11,8 @@ struct jtag_port {
 	uint8_t tms;
 	uint8_t tms;
 	uint8_t tdi;
 	uint8_t tdi;
 	uint8_t tdo;
 	uint8_t tdo;
+	uint8_t ignored;
+	uint8_t *state;
 };
 };
 
 
 enum jtagreg {
 enum jtagreg {

+ 3 - 0
miner.h

@@ -377,6 +377,9 @@ struct cgpu_info {
 		struct libztex_device *device_ztex;
 		struct libztex_device *device_ztex;
 #endif
 #endif
 		int device_fd;
 		int device_fd;
+#ifdef USE_X6500
+		struct ft232r_device_handle *device_ft232r;
+#endif
 	};
 	};
 #ifdef USE_BITFORCE
 #ifdef USE_BITFORCE
 	struct timeval work_start_tv;
 	struct timeval work_start_tv;