Browse Source

Merge commit 'fa59352' into littlefury

Conflicts:
	driver-bitfury.c
	libbitfury.c
	libbitfury.h
	spidevc.c
	spidevc.h
Luke Dashjr 12 years ago
parent
commit
fd682e1c0e
5 changed files with 219 additions and 131 deletions
  1. 9 4
      driver-bitfury.c
  2. 72 69
      libbitfury.c
  3. 5 3
      libbitfury.h
  4. 85 41
      spidevc.c
  5. 48 14
      spidevc.h

+ 9 - 4
driver-bitfury.c

@@ -26,6 +26,7 @@
 #include <sha2.h>
 #include <sha2.h>
 #include "libbitfury.h"
 #include "libbitfury.h"
 #include "util.h"
 #include "util.h"
+#include "spidevc.h"
 
 
 #define GOLDEN_BACKLOG 5
 #define GOLDEN_BACKLOG 5
 
 
@@ -46,7 +47,10 @@ static void bitfury_detect(void)
 	bitfury_info->threads = 1;
 	bitfury_info->threads = 1;
 
 
 	applog(LOG_INFO, "INFO: bitfury_detect");
 	applog(LOG_INFO, "INFO: bitfury_detect");
-	chip_n = libbitfury_detectChips(bitfury_info->devices);
+	spi_init();
+	if (!sys_spi)
+		return;
+	chip_n = libbitfury_detectChips(sys_spi, bitfury_info->devices);
 	if (!chip_n) {
 	if (!chip_n) {
 		applog(LOG_WARNING, "No Bitfury chips detected!");
 		applog(LOG_WARNING, "No Bitfury chips detected!");
 		return;
 		return;
@@ -81,12 +85,13 @@ static int64_t bitfury_scanHash(struct thr_info *thr)
 			devices[i].osc6_bits = 54;
 			devices[i].osc6_bits = 54;
 		}
 		}
 		for (i = 0; i < chip_n; i++) {
 		for (i = 0; i < chip_n; i++) {
-			send_reinit(devices[i].slot, devices[i].fasync, devices[i].osc6_bits);
+			send_reinit(devices[i].spi, devices[i].slot, devices[i].fasync, devices[i].osc6_bits);
 		}
 		}
 	}
 	}
 	first = 1;
 	first = 1;
 
 
 	for (chip = 0; chip < chip_n; chip++) {
 	for (chip = 0; chip < chip_n; chip++) {
+		devices[chip].spi = sys_spi;
 		devices[chip].job_switched = 0;
 		devices[chip].job_switched = 0;
 		if(!devices[chip].work) {
 		if(!devices[chip].work) {
 			devices[chip].work = get_queued(thr->cgpu);
 			devices[chip].work = get_queued(thr->cgpu);
@@ -162,9 +167,9 @@ static int64_t bitfury_scanHash(struct thr_info *thr)
 
 
 			if(short_out_t && ghash < 1.0) {
 			if(short_out_t && ghash < 1.0) {
 				applog(LOG_WARNING, "Chip_id %d FREQ CHANGE\n", chip);
 				applog(LOG_WARNING, "Chip_id %d FREQ CHANGE\n", chip);
-				send_freq(devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits - 1);
+				send_freq(devices[chip].spi, devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits - 1);
 				cgsleep_ms(1);
 				cgsleep_ms(1);
-				send_freq(devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits);
+				send_freq(devices[chip].spi, devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits);
 			}
 			}
 			shares_total += shares_found;
 			shares_total += shares_found;
 			shares_first += chip < 4 ? shares_found : 0;
 			shares_first += chip < 4 ? shares_found : 0;

+ 72 - 69
libbitfury.c

@@ -51,10 +51,10 @@ unsigned char disconf[4] = { 0, 0, 0, 0 };
 unsigned decnonce(unsigned in);
 unsigned decnonce(unsigned in);
 
 
 /* Configuration registers - control oscillators and such stuff. PROGRAMMED when magic number is matches, UNPROGRAMMED (default) otherwise */
 /* Configuration registers - control oscillators and such stuff. PROGRAMMED when magic number is matches, UNPROGRAMMED (default) otherwise */
-void config_reg(int cfgreg, int ena)
+void config_reg(struct spi_port *port, int cfgreg, int ena)
 {
 {
-	if (ena) spi_emit_data(0x7000+cfgreg*32, (void*)enaconf, 4);
-	else     spi_emit_data(0x7000+cfgreg*32, (void*)disconf, 4);
+	if (ena) spi_emit_data(port, 0x7000+cfgreg*32, (void*)enaconf, 4);
+	else     spi_emit_data(port, 0x7000+cfgreg*32, (void*)disconf, 4);
 }
 }
 
 
 #define FIRST_BASE 61
 #define FIRST_BASE 61
@@ -171,15 +171,18 @@ void ms3_compute(unsigned *p)
 	p[15] = a; p[14] = b; p[13] = c; p[12] = d; p[11] = e; p[10] = f; p[9] = g; p[8] = h;
 	p[15] = a; p[14] = b; p[13] = c; p[12] = d; p[11] = e; p[10] = f; p[9] = g; p[8] = h;
 }
 }
 
 
-void send_conf() {
-	config_reg(7,0); config_reg(8,0); config_reg(9,0); config_reg(10,0); config_reg(11,0);
-	config_reg(6,0); /* disable OUTSLK */
-	config_reg(4,1); /* Enable slow oscillator */
-	config_reg(1,0); config_reg(2,0); config_reg(3,0);
-	spi_emit_data(0x0100, (void*)counters, 16); /* Program counters correctly for rounds processing, here baby should start consuming power */
+void send_conf(struct spi_port *port) {
+	int i;
+	for (i = 7; i <= 11; ++i)
+		config_reg(port, i, 0);
+	config_reg(port, 6, 0); /* disable OUTSLK */
+	config_reg(port, 4, 1); /* Enable slow oscillator */
+	for (i = 1; i <= 3; ++i)
+		config_reg(port, i, 0);
+	spi_emit_data(port, 0x0100, counters, 16); /* Program counters correctly for rounds processing, here baby should start consuming power */
 }
 }
 
 
-void send_init() {
+void send_init(struct spi_port *port) {
 	/* Prepare internal buffers */
 	/* Prepare internal buffers */
 	/* PREPARE BUFFERS (INITIAL PROGRAMMING) */
 	/* PREPARE BUFFERS (INITIAL PROGRAMMING) */
 	unsigned w[16];
 	unsigned w[16];
@@ -191,53 +194,53 @@ void send_init() {
 
 
 	ms3_compute(&atrvec[0]);
 	ms3_compute(&atrvec[0]);
 	memset(&w, 0, sizeof(w)); w[3] = 0xffffffff; w[4] = 0x80000000; w[15] = 0x00000280;
 	memset(&w, 0, sizeof(w)); w[3] = 0xffffffff; w[4] = 0x80000000; w[15] = 0x00000280;
-	spi_emit_data(0x1000, (void*)w, 16*4);
-	spi_emit_data(0x1400, (void*)w,  8*4);
+	spi_emit_data(port, 0x1000, w, 16*4);
+	spi_emit_data(port, 0x1400, w,  8*4);
 	memset(w, 0, sizeof(w)); w[0] = 0x80000000; w[7] = 0x100;
 	memset(w, 0, sizeof(w)); w[0] = 0x80000000; w[7] = 0x100;
-	spi_emit_data(0x1900, (void*)&w[0],8*4); /* Prepare MS and W buffers! */
-	spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
+	spi_emit_data(port, 0x1900, &w[0],8*4); /* Prepare MS and W buffers! */
+	spi_emit_data(port, 0x3000, &atrvec[0], 19*4);
 }
 }
 
 
-void set_freq(int bits) {
+void set_freq(struct spi_port *port, int bits) {
 	uint64_t freq;
 	uint64_t freq;
 	unsigned char *osc6;
 	unsigned char *osc6;
 
 
 	osc6 = (unsigned char *)&freq;
 	osc6 = (unsigned char *)&freq;
 	freq = (1ULL << bits) - 1ULL;
 	freq = (1ULL << bits) - 1ULL;
 
 
-	spi_emit_data(0x6000, (void*)osc6, 8); /* Program internal on-die slow oscillator frequency */
-	config_reg(4,1); /* Enable slow oscillator */
+	spi_emit_data(port, 0x6000, osc6, 8); /* Program internal on-die slow oscillator frequency */
+	config_reg(port, 4, 1); /* Enable slow oscillator */
 }
 }
 
 
-void send_reinit(int slot, int chip_n, int n) {
-	spi_clear_buf();
-	spi_emit_break();
-	spi_emit_fasync(chip_n);
-	set_freq(n);
-	send_conf();
-	send_init();
+void send_reinit(struct spi_port *port, int slot, int chip_n, int n) {
+	spi_clear_buf(port);
+	spi_emit_break(port);
+	spi_emit_fasync(port, chip_n);
+	set_freq(port, n);
+	send_conf(port);
+	send_init(port);
 	tm_i2c_set_oe(slot);
 	tm_i2c_set_oe(slot);
-	spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+	spi_txrx(port);
 	tm_i2c_clear_oe(slot);
 	tm_i2c_clear_oe(slot);
 }
 }
 
 
-void send_shutdown(int slot, int chip_n) {
-	spi_clear_buf();
-	spi_emit_break();
-	spi_emit_fasync(chip_n);
-	config_reg(4,0); /* Disable slow oscillator */
+void send_shutdown(struct spi_port *port, int slot, int chip_n) {
+	spi_clear_buf(port);
+	spi_emit_break(port);
+	spi_emit_fasync(port, chip_n);
+	config_reg(port, 4, 0); /* Disable slow oscillator */
 	tm_i2c_set_oe(slot);
 	tm_i2c_set_oe(slot);
-	spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+	spi_txrx(port);
 	tm_i2c_clear_oe(slot);
 	tm_i2c_clear_oe(slot);
 }
 }
 
 
-void send_freq(int slot, int chip_n, int bits) {
-	spi_clear_buf();
-	spi_emit_break();
-	spi_emit_fasync(chip_n);
-	set_freq(bits);
+void send_freq(struct spi_port *port, int slot, int chip_n, int bits) {
+	spi_clear_buf(port);
+	spi_emit_break(port);
+	spi_emit_fasync(port, chip_n);
+	set_freq(port, bits);
 	tm_i2c_set_oe(slot);
 	tm_i2c_set_oe(slot);
-	spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+	spi_txrx(port);
 	tm_i2c_clear_oe(slot);
 	tm_i2c_clear_oe(slot);
 }
 }
 
 
@@ -259,7 +262,7 @@ int get_counter(unsigned int *newbuf, unsigned int *oldbuf) {
 	return 0;
 	return 0;
 }
 }
 
 
-int detect_chip(int chip_n) {
+int detect_chip(struct spi_port *port, int chip_n) {
 	int i;
 	int i;
 	unsigned newbuf[17], oldbuf[17];
 	unsigned newbuf[17], oldbuf[17];
 	unsigned ocounter;
 	unsigned ocounter;
@@ -272,28 +275,26 @@ int detect_chip(int chip_n) {
 	ms3_compute(&atrvec[0]);
 	ms3_compute(&atrvec[0]);
 	ms3_compute(&atrvec[20]);
 	ms3_compute(&atrvec[20]);
 	ms3_compute(&atrvec[40]);
 	ms3_compute(&atrvec[40]);
-	if (!spi_init())
-		return 0;
 
 
 
 
-	spi_clear_buf();
-	spi_emit_break(); /* First we want to break chain! Otherwise we'll get all of traffic bounced to output */
-	spi_emit_fasync(chip_n);
-	set_freq(52);  //54 - 3F, 53 - 1F
-	send_conf();
-	send_init();
-	spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+	spi_clear_buf(port);
+	spi_emit_break(port); /* First we want to break chain! Otherwise we'll get all of traffic bounced to output */
+	spi_emit_fasync(port, chip_n);
+	set_freq(port, 52);  //54 - 3F, 53 - 1F
+	send_conf(port);
+	send_init(port);
+	spi_txrx(port);
 
 
 	ocounter = 0;
 	ocounter = 0;
 	for (i = 0; i < BITFURY_DETECT_TRIES; i++) {
 	for (i = 0; i < BITFURY_DETECT_TRIES; i++) {
 		int counter;
 		int counter;
 
 
-		spi_clear_buf();
-		spi_emit_break();
-		spi_emit_fasync(chip_n);
-		spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
-		spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
-		memcpy(newbuf, spi_getrxbuf() + 4 + chip_n, 17*4);
+		spi_clear_buf(port);
+		spi_emit_break(port);
+		spi_emit_fasync(port, chip_n);
+		spi_emit_data(port, 0x3000, &atrvec[0], 19*4);
+		spi_txrx(port);
+		memcpy(newbuf, spi_getrxbuf(port) + 4 + chip_n, 17*4);
 
 
 		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
 		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
 		counter = get_counter(newbuf, oldbuf);
 		counter = get_counter(newbuf, oldbuf);
@@ -314,7 +315,7 @@ int detect_chip(int chip_n) {
 	return 0;
 	return 0;
 }
 }
 
 
-int libbitfury_detectChips(struct bitfury_device *devices) {
+int libbitfury_detectChips(struct spi_port *port, struct bitfury_device *devices) {
 	int n = 0;
 	int n = 0;
 	int i;
 	int i;
 	static bool slot_on[32];
 	static bool slot_on[32];
@@ -340,7 +341,7 @@ int libbitfury_detectChips(struct bitfury_device *devices) {
 			int chip_detected;
 			int chip_detected;
 			tm_i2c_set_oe(i);
 			tm_i2c_set_oe(i);
 			do {
 			do {
-				chip_detected = detect_chip(chip_n);
+				chip_detected = detect_chip(port, chip_n);
 				if (chip_detected) {
 				if (chip_detected) {
 					applog(LOG_WARNING, "BITFURY slot: %d, chip #%d detected", i, n);
 					applog(LOG_WARNING, "BITFURY slot: %d, chip #%d detected", i, n);
 					devices[n].slot = i;
 					devices[n].slot = i;
@@ -362,7 +363,7 @@ int libbitfury_detectChips(struct bitfury_device *devices) {
 void libbitfury_shutdownChips(struct bitfury_device *devices, int chip_n) {
 void libbitfury_shutdownChips(struct bitfury_device *devices, int chip_n) {
 	int i;
 	int i;
 	for (i = 0; i < chip_n; i++) {
 	for (i = 0; i < chip_n; i++) {
-		send_shutdown(devices[i].slot, devices[i].fasync);
+		send_shutdown(devices[i].spi, devices[i].slot, devices[i].fasync);
 	}
 	}
 	tm_i2c_close();
 	tm_i2c_close();
 }
 }
@@ -444,6 +445,7 @@ void work_to_payload(struct bitfury_payload *p, struct work *w) {
 }
 }
 
 
 void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
 void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
+	struct spi_port *port = bf->spi;
 	int chip_id;
 	int chip_id;
 	static unsigned second_run;
 	static unsigned second_run;
 
 
@@ -476,18 +478,19 @@ void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
 			d->otimer1 = d->timer1;
 			d->otimer1 = d->timer1;
 			d->timer1 = time;
 			d->timer1 = time;
 			/* Programming next value */
 			/* Programming next value */
-			spi_clear_buf(); spi_emit_break();
-			spi_emit_fasync(chip);
-			spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
+			spi_clear_buf(port);
+			spi_emit_break(port);
+			spi_emit_fasync(port, chip);
+			spi_emit_data(port, 0x3000, &atrvec[0], 19*4);
 			if (smart) {
 			if (smart) {
-				config_reg(3,0);
+				config_reg(port, 3, 0);
 			}
 			}
 			tm_i2c_set_oe(slot);
 			tm_i2c_set_oe(slot);
 			clock_gettime(CLOCK_REALTIME, &(time));
 			clock_gettime(CLOCK_REALTIME, &(time));
 			d_time = t_diff(time, d->predict1);
 			d_time = t_diff(time, d->predict1);
-			spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+			spi_txrx(port);
 			tm_i2c_clear_oe(slot);
 			tm_i2c_clear_oe(slot);
-			memcpy(newbuf, spi_getrxbuf()+4 + chip, 17*4);
+			memcpy(newbuf, spi_getrxbuf(port)+4 + chip, 17*4);
 
 
 			d->job_switched = newbuf[16] != oldbuf[16];
 			d->job_switched = newbuf[16] != oldbuf[16];
 
 
@@ -647,17 +650,17 @@ void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
 			if(smart) {
 			if(smart) {
 				d->otimer2 = d->timer2;
 				d->otimer2 = d->timer2;
 				d->timer2 = time;
 				d->timer2 = time;
-				spi_clear_buf();
-				spi_emit_break();
-				spi_emit_fasync(chip);
-				spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
+				spi_clear_buf(port);
+				spi_emit_break(port);
+				spi_emit_fasync(port, chip);
+				spi_emit_data(port, 0x3000, &atrvec[0], 19*4);
 				if (smart) {
 				if (smart) {
-					config_reg(3,1);
+					config_reg(port, 3, 1);
 				}
 				}
 				tm_i2c_set_oe(slot);
 				tm_i2c_set_oe(slot);
-				spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
+				spi_txrx(port);
 				tm_i2c_clear_oe(slot);
 				tm_i2c_clear_oe(slot);
-				memcpy(newbuf, spi_getrxbuf()+4 + chip, 17*4);
+				memcpy(newbuf, spi_getrxbuf(port)+4 + chip, 17*4);
 				d->counter2 = get_counter(newbuf, oldbuf);
 				d->counter2 = get_counter(newbuf, oldbuf);
 
 
 				d->req2_done = 1;
 				d->req2_done = 1;

+ 5 - 3
libbitfury.h

@@ -2,6 +2,7 @@
 #define __LIBBITFURY_H__
 #define __LIBBITFURY_H__
 
 
 #include "miner.h"
 #include "miner.h"
+#include "spidevc.h"
 
 
 #define BITFURY_STAT_N 1024
 #define BITFURY_STAT_N 1024
 
 
@@ -15,6 +16,7 @@ struct bitfury_payload {
 };
 };
 
 
 struct bitfury_device {
 struct bitfury_device {
+	struct spi_port *spi;
 	unsigned char osc6_bits;
 	unsigned char osc6_bits;
 	unsigned newbuf[17];
 	unsigned newbuf[17];
 	unsigned oldbuf[17];
 	unsigned oldbuf[17];
@@ -53,9 +55,9 @@ int libbitfury_readHashData(unsigned int *res);
 void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n);
 void libbitfury_sendHashData(struct bitfury_device *bf, int chip_n);
 void work_to_payload(struct bitfury_payload *p, struct work *w);
 void work_to_payload(struct bitfury_payload *p, struct work *w);
 struct timespec t_diff(struct timespec start, struct timespec end);
 struct timespec t_diff(struct timespec start, struct timespec end);
-extern void send_reinit(int slot, int chip_n, int n);
-extern void send_freq(int slot, int chip_n, int bits);
-int libbitfury_detectChips(struct bitfury_device *devices);
+extern void send_reinit(struct spi_port *, int slot, int chip_n, int n);
+extern void send_freq(struct spi_port *, int slot, int chip_n, int bits);
+extern int libbitfury_detectChips(struct spi_port *, struct bitfury_device *devices);
 void libbitfury_shutdownChips(struct bitfury_device *devices, int chip_n);
 void libbitfury_shutdownChips(struct bitfury_device *devices, int chip_n);
 
 
 #endif /* __LIBBITFURY_H__ */
 #endif /* __LIBBITFURY_H__ */

+ 85 - 41
spidevc.c

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright 2013 bitfury
  * Copyright 2013 bitfury
+ * Copyright 2013 Luke Dashjr
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * of this software and associated documentation files (the "Software"), to deal
@@ -22,8 +23,8 @@
 
 
 #include "spidevc.h"
 #include "spidevc.h"
 
 
-#include <stdbool.h>
 #include <sys/mman.h>
 #include <sys/mman.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -44,27 +45,42 @@
 
 
 #include "logging.h"
 #include "logging.h"
 
 
+#define HAVE_LINUX_SPI
+
+#ifdef HAVE_LINUX_SPI
+static bool sys_spi_txrx(struct spi_port *port);
 static volatile unsigned *gpio;
 static volatile unsigned *gpio;
+#endif
 
 
-bool spi_init(void)
+struct spi_port *sys_spi;
+
+void spi_init(void)
 {
 {
+#ifdef HAVE_LINUX_SPI
 	int fd;
 	int fd;
 	fd = open("/dev/mem",O_RDWR|O_SYNC);
 	fd = open("/dev/mem",O_RDWR|O_SYNC);
 	if (fd < 0)
 	if (fd < 0)
 	{
 	{
 		perror("/dev/mem trouble");
 		perror("/dev/mem trouble");
-		return false;
+		return;
 	}
 	}
 	gpio = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x20200000);
 	gpio = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x20200000);
 	if (gpio == MAP_FAILED)
 	if (gpio == MAP_FAILED)
 	{
 	{
 		perror("gpio mmap trouble");
 		perror("gpio mmap trouble");
-		return false;
+		return;
 	}
 	}
 	close(fd);
 	close(fd);
-	return true;
+	
+	sys_spi = malloc(sizeof(*sys_spi));
+	*sys_spi = (struct spi_port){
+		.txrx = sys_spi_txrx,
+	};
+#endif
 }
 }
 
 
+#ifdef HAVE_LINUX_SPI
+
 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
 #define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
 #define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
@@ -73,6 +89,7 @@ bool spi_init(void)
 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
 
 
 // Bit-banging reset, to reset more chips in chain - toggle for longer period... Each 3 reset cycles reset first chip in chain
 // Bit-banging reset, to reset more chips in chain - toggle for longer period... Each 3 reset cycles reset first chip in chain
+static
 void spi_reset(void)
 void spi_reset(void)
 {
 {
 	int i,j;
 	int i,j;
@@ -100,8 +117,18 @@ void spi_reset(void)
 	SET_GPIO_ALT(9,0);
 	SET_GPIO_ALT(9,0);
 }
 }
 
 
-int spi_txrx(const void *wrbuf, void *rdbuf, size_t bufsz)
+#define BAILOUT(s)  do{  \
+	perror(s);  \
+	close(fd);  \
+	return false;  \
+}while(0)
+
+static
+bool sys_spi_txrx(struct spi_port *port)
 {
 {
+	const void *wrbuf = spi_gettxbuf(port);
+	void *rdbuf = spi_getrxbuf(port);
+	size_t bufsz = spi_getbufsz(port);
 	int fd;
 	int fd;
 	int mode, bits, speed, rv, i, j;
 	int mode, bits, speed, rv, i, j;
 	struct spi_ioc_transfer tr[16];
 	struct spi_ioc_transfer tr[16];
@@ -111,13 +138,22 @@ int spi_txrx(const void *wrbuf, void *rdbuf, size_t bufsz)
 
 
 	spi_reset();
 	spi_reset();
 	fd = open("/dev/spidev0.0", O_RDWR);
 	fd = open("/dev/spidev0.0", O_RDWR);
-	if (fd < 0) { perror("Unable to open SPI device"); exit(1); }
-        if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0) { perror("Unable to set WR MODE"); close(fd); return -1; }
-        if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) { perror("Unable to set RD MODE"); close(fd); return -1; }
-        if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) { perror("Unable to set WR_BITS_PER_WORD"); close(fd); return -1; }
-        if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) { perror("Unable to set RD_BITS_PER_WORD"); close(fd); return -1; }
-        if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) { perror("Unable to set WR_MAX_SPEED_HZ"); close(fd); return -1; }
-        if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) { perror("Unable to set RD_MAX_SPEED_HZ"); close(fd); return -1; }
+	if (fd < 0) {
+		perror("Unable to open SPI device");
+		return false;
+	}
+	if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0)
+		BAILOUT("Unable to set WR MODE");
+	if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0)
+		BAILOUT("Unable to set RD MODE");
+	if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0)
+		BAILOUT("Unable to set WR_BITS_PER_WORD");
+	if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
+		BAILOUT("Unable to set RD_BITS_PER_WORD");
+	if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
+		BAILOUT("Unable to set WR_MAX_SPEED_HZ");
+	if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
+		BAILOUT("Unable to set RD_MAX_SPEED_HZ");
 
 
 	rv = 0;
 	rv = 0;
 	while (bufsz >= 4096) {
 	while (bufsz >= 4096) {
@@ -143,69 +179,77 @@ int spi_txrx(const void *wrbuf, void *rdbuf, size_t bufsz)
         i = rv;
         i = rv;
         for (j = 0; j < i; j++) {
         for (j = 0; j < i; j++) {
                 rv = (int)ioctl(fd, SPI_IOC_MESSAGE(1), (intptr_t)&tr[j]);
                 rv = (int)ioctl(fd, SPI_IOC_MESSAGE(1), (intptr_t)&tr[j]);
-                if (rv < 0) { perror("WTF!"); close(fd); return -1; }
+		if (rv < 0)
+			BAILOUT("WTF!");
         }
         }
 
 
 	close(fd);
 	close(fd);
 	spi_reset();
 	spi_reset();
 
 
-	return 0;
+	return true;
 }
 }
 
 
-#define SPIMAXSZ 256*1024
-static unsigned char spibuf[SPIMAXSZ], spibuf_rx[SPIMAXSZ];
-static unsigned spibufsz;
-
-void spi_clear_buf(void) { spibufsz = 0; }
-unsigned char *spi_getrxbuf(void) { return spibuf_rx; }
-unsigned char *spi_gettxbuf(void) { return spibuf; }
-unsigned spi_getbufsz(void) { return spibufsz; }
+#endif
 
 
-void spi_emit_buf_reverse(const char *str, unsigned sz)
+static
+void spi_emit_buf_reverse(struct spi_port *port, void *p, size_t sz)
 {
 {
-	unsigned i;
-	if (spibufsz + sz >= SPIMAXSZ) return;
-	for (i = 0; i < sz; i++) { // Reverse bit order in each byte!
+	unsigned char *str = p;
+	if (port->spibufsz + sz >= SPIMAXSZ)
+		return;
+	for (size_t i = 0; i < sz; ++i)
+	{
+		// Reverse bit order in each byte!
 		unsigned char p = str[i];
 		unsigned char p = str[i];
 		p = ((p & 0xaa)>>1) | ((p & 0x55) << 1);
 		p = ((p & 0xaa)>>1) | ((p & 0x55) << 1);
 		p = ((p & 0xcc)>>2) | ((p & 0x33) << 2);
 		p = ((p & 0xcc)>>2) | ((p & 0x33) << 2);
 		p = ((p & 0xf0)>>4) | ((p & 0x0f) << 4);
 		p = ((p & 0xf0)>>4) | ((p & 0x0f) << 4);
-		spibuf[spibufsz+i] = p;
+		port->spibuf[port->spibufsz++] = p;
 	}
 	}
-	spibufsz += sz;
 }
 }
 
 
-void spi_emit_buf(void *str, unsigned sz)
+static
+void spi_emit_buf(struct spi_port *port, void *str, size_t sz)
 {
 {
-	if (spibufsz + sz >= SPIMAXSZ) return;
-	memcpy(&spibuf[spibufsz], str, sz); spibufsz += sz;
+	if (port->spibufsz + sz >= SPIMAXSZ)
+		return;
+	memcpy(&port->spibuf[port->spibufsz], str, sz);
+	port->spibufsz += sz;
 }
 }
 
 
 /* TODO: in production, emit just bit-sequences! Eliminate padding to byte! */
 /* TODO: in production, emit just bit-sequences! Eliminate padding to byte! */
-void spi_emit_break(void) { spi_emit_buf("\x4", 1); }
-void spi_emit_fsync(void) { spi_emit_buf("\x6", 1); }
+void spi_emit_break(struct spi_port *port)
+{
+	spi_emit_buf(port, "\x4", 1);
+}
 
 
-void spi_emit_fasync(int n) {
+void spi_emit_fsync(struct spi_port *port)
+{
+	spi_emit_buf(port, "\x6", 1);
+}
+
+void spi_emit_fasync(struct spi_port *port, int n)
+{
 	int i;
 	int i;
 	for (i = 0; i < n; i++) {
 	for (i = 0; i < n; i++) {
-		spi_emit_buf("\x5", 1);
+		spi_emit_buf(port, "\x5", 1);
 	}
 	}
 }
 }
 
 
-void spi_emit_nop(int n) {
+void spi_emit_nop(struct spi_port *port, int n) {
 	int i;
 	int i;
 	for (i = 0; i < n; n++) {
 	for (i = 0; i < n; n++) {
-		spi_emit_buf("\x0", 1);
+		spi_emit_buf(port, "\x0", 1);
 	}
 	}
 }
 }
 
 
-void spi_emit_data(unsigned addr, const char *buf, unsigned len)
+void spi_emit_data(struct spi_port *port, uint16_t addr, void *buf, size_t len)
 {
 {
 	unsigned char otmp[3];
 	unsigned char otmp[3];
 	if (len < 4 || len > 128) return; /* This cannot be programmed in single frame! */
 	if (len < 4 || len > 128) return; /* This cannot be programmed in single frame! */
 	len /= 4; /* Strip */
 	len /= 4; /* Strip */
 	otmp[0] = (len - 1) | 0xE0;
 	otmp[0] = (len - 1) | 0xE0;
 	otmp[1] = (addr >> 8)&0xFF; otmp[2] = addr & 0xFF;
 	otmp[1] = (addr >> 8)&0xFF; otmp[2] = addr & 0xFF;
-	spi_emit_buf(otmp, 3);
-	spi_emit_buf_reverse(buf, len*4);
+	spi_emit_buf(port, otmp, 3);
+	spi_emit_buf_reverse(port, buf, len*4);
 }
 }

+ 48 - 14
spidevc.h

@@ -2,33 +2,67 @@
 #define SPIDEVC_H
 #define SPIDEVC_H
 
 
 #include <stdbool.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
+#define SPIMAXSZ (256*1024)
+
 /* Initialize SPI using this function */
 /* Initialize SPI using this function */
-bool spi_init(void);
+void spi_init(void);
+
+struct spi_port {
+	/* TX-RX single frame */
+	bool (*txrx)(struct spi_port *port);
+	
+	char spibuf[SPIMAXSZ], spibuf_rx[SPIMAXSZ];
+	size_t spibufsz;
+};
+
+extern struct spi_port *sys_spi;
 
 
-/* TX-RX single frame */
-int spi_txrx(const void *wrbuf, void *rdbuf, size_t bufsz);
 
 
 /* SPI BUFFER OPS */
 /* SPI BUFFER OPS */
-void spi_clear_buf(void);
-unsigned char *spi_getrxbuf(void);
-unsigned char *spi_gettxbuf(void);
-unsigned spi_getbufsz(void);
+static inline
+void spi_clear_buf(struct spi_port *port)
+{
+	port->spibufsz = 0;
+}
+
+static inline
+void *spi_getrxbuf(struct spi_port *port)
+{
+	return port->spibuf_rx;
+}
 
 
-void spi_emit_buf_reverse(const char *str, unsigned sz); /* INTERNAL USE: EMIT REVERSED BYTE SEQUENCE DIRECTLY TO STREAM */
-void spi_emit_buf(void *str, unsigned sz); /* INTERNAL USE: EMIT BYTE SEQUENCE DIRECTLY TO STREAM */
+static inline
+void *spi_gettxbuf(struct spi_port *port)
+{
+	return port->spibuf;
+}
 
 
-void spi_emit_break(void); /* BREAK CONNECTIONS AFTER RESET */
-void spi_emit_fsync(void); /* FEED-THROUGH TO NEXT CHIP SYNCHRONOUSLY (WITH FLIP-FLOP) */
-void spi_emit_fasync(int n); /* FEED-THROUGH TO NEXT CHIP ASYNCHRONOUSLY (WITHOUT FLIP-FLOP INTERMEDIATE) */
-void spi_emit_nop(int n);
+static inline
+size_t spi_getbufsz(struct spi_port *port)
+{
+	return port->spibufsz;
+}
+
+
+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) */
+extern void spi_emit_fasync(struct spi_port *port, int n); /* FEED-THROUGH TO NEXT CHIP ASYNCHRONOUSLY (WITHOUT FLIP-FLOP INTERMEDIATE) */
+extern void spi_emit_nop(struct spi_port *port, int n);
 
 
 /* TRANSMIT PROGRAMMING SEQUENCE (AND ALSO READ-BACK) */
 /* TRANSMIT PROGRAMMING SEQUENCE (AND ALSO READ-BACK) */
 /* addr is the destination address in bits (16-bit - 0 to 0xFFFF valid ones)
 /* addr is the destination address in bits (16-bit - 0 to 0xFFFF valid ones)
    buf is buffer to be transmitted, it will go at position spi_getbufsz()+3
    buf is buffer to be transmitted, it will go at position spi_getbufsz()+3
    len is length in _bytes_, should be 4 to 128 and be multiple of 4, as smallest
    len is length in _bytes_, should be 4 to 128 and be multiple of 4, as smallest
    transmission quantum is 32 bits */
    transmission quantum is 32 bits */
-void spi_emit_data(unsigned addr, const char *buf, unsigned len);
+extern void spi_emit_data(struct spi_port *port, uint16_t addr, void *buf, size_t len);
+
+static inline
+bool spi_txrx(struct spi_port *port)
+{
+	return port->txrx(port);
+}
 
 
 #endif
 #endif