From c9973e18879c7608d0d4499230301c8a60755530 Mon Sep 17 00:00:00 2001
From: "Wesley W. Terpstra" <w.terpstra@gsi.de>
Date: Fri, 4 May 2012 15:24:25 +0000
Subject: [PATCH] Implement the mandatory Etherbone config space registers.
 Currently hardcode SDWB address as hardware does not support it.

---
 driver/pcie_wb.c  | 28 ++++++++++++++++++++++++----
 driver/pcie_wb.h  |  2 ++
 driver/wishbone.c | 34 +++++++++++++++++++++++++---------
 driver/wishbone.h |  1 +
 4 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/driver/pcie_wb.c b/driver/pcie_wb.c
index f06aa19..19ad7ed 100644
--- a/driver/pcie_wb.c
+++ b/driver/pcie_wb.c
@@ -29,7 +29,7 @@
 
 static unsigned int debug = 0;
 
-void wb_cycle(struct wishbone* wb, int on)
+static void wb_cycle(struct wishbone* wb, int on)
 {
 	struct pcie_wb_dev* dev;
 	unsigned char* control;
@@ -44,7 +44,7 @@ void wb_cycle(struct wishbone* wb, int on)
 	if (!on) mutex_unlock(&dev->mutex);
 }
 
-void wb_byteenable(struct wishbone* wb, unsigned char be)
+static void wb_byteenable(struct wishbone* wb, unsigned char be)
 {
 	struct pcie_wb_dev* dev;
 	
@@ -92,7 +92,7 @@ void wb_byteenable(struct wishbone* wb, unsigned char be)
 	}
 }
 
-void wb_write(struct wishbone* wb, wb_addr_t addr, wb_data_t data)
+static void wb_write(struct wishbone* wb, wb_addr_t addr, wb_data_t data)
 {
 	struct pcie_wb_dev* dev;
 	unsigned char* control;
@@ -125,7 +125,7 @@ void wb_write(struct wishbone* wb, wb_addr_t addr, wb_data_t data)
 	}
 }
 
-wb_data_t wb_read(struct wishbone* wb, wb_addr_t addr)
+static wb_data_t wb_read(struct wishbone* wb, wb_addr_t addr)
 {
 	struct pcie_wb_dev* dev;
 	unsigned char* control;
@@ -158,11 +158,31 @@ wb_data_t wb_read(struct wishbone* wb, wb_addr_t addr)
 	return 0;
 }
 
+static wb_data_t wb_read_cfg(struct wishbone *wb, wb_addr_t addr)
+{
+	struct pcie_wb_dev* dev;
+	unsigned char* control;
+	
+	dev = container_of(wb, struct pcie_wb_dev, wb);
+	control = dev->pci_res[0].addr;
+	
+	rmb();	// has to be executed before reading
+	
+	switch (addr) {
+	case 0:  return ioread32(control + ERROR_FLAG_HIGH);
+	case 4:  return ioread32(control + ERROR_FLAG_LOW);
+	case 8:  return 0;        // ioread32(control + SDWB_ADDRESS_HIGH);
+	case 12: return 0x300000; // ioread32(control + SDWB_ADDRESS_LOW);
+	default: return 0;
+	}
+}
+
 static const struct wishbone_operations wb_ops = {
 	.cycle      = wb_cycle,
 	.byteenable = wb_byteenable,
 	.write      = wb_write,
 	.read       = wb_read,
+	.read_cfg   = wb_read_cfg,
 };
 
 #if 0
diff --git a/driver/pcie_wb.h b/driver/pcie_wb.h
index 84be7d9..0d51eca 100644
--- a/driver/pcie_wb.h
+++ b/driver/pcie_wb.h
@@ -15,6 +15,8 @@
 #define ERROR_FLAG_LOW		12
 #define WINDOW_OFFSET_HIGH	16
 #define WINDOW_OFFSET_LOW	20
+#define SDWB_ADDRESS_HIGH	24
+#define SDWB_ADDRESS_LOW	28
 
 #define WINDOW_HIGH	0xFFFF0000UL
 #define WINDOW_LOW	0x0000FFFCUL
diff --git a/driver/wishbone.c b/driver/wishbone.c
index ab8ba66..2a78c6c 100644
--- a/driver/wishbone.c
+++ b/driver/wishbone.c
@@ -102,18 +102,26 @@ static void etherbone_process(struct etherbone_context* context)
 			wb_addr_t base_address;
 			unsigned char j;
 			int wff = flags & ETHERBONE_WFF;
+			int wca = flags & ETHERBONE_WCA;
 			
 			/* Erase the header */
 			eb_from_cpu(buf+i, 0);
 			i = RING_INDEX(i + sizeof(wb_data_t));
 			base_address = eb_to_cpu(buf+i);
 			
-			for (j = wcount; j > 0; --j) {
-				eb_from_cpu(buf+i, 0);
-				i = RING_INDEX(i + sizeof(wb_data_t));
-				wops->write(wb, base_address, eb_to_cpu(buf+i));
-				
-				if (!wff) base_address += sizeof(wb_data_t);
+			if (wca) {
+				for (j = wcount; j > 0; --j) {
+					eb_from_cpu(buf+i, 0);
+					i = RING_INDEX(i + sizeof(wb_data_t));
+				}
+			} else {
+				for (j = wcount; j > 0; --j) {
+					eb_from_cpu(buf+i, 0);
+					i = RING_INDEX(i + sizeof(wb_data_t));
+					wops->write(wb, base_address, eb_to_cpu(buf+i));
+					
+					if (!wff) base_address += sizeof(wb_data_t);
+				}
 			}
 		}
 		
@@ -126,13 +134,21 @@ static void etherbone_process(struct etherbone_context* context)
 		
 		if (rcount > 0) {
 			unsigned char j;
+			int rca = flags & ETHERBONE_RCA;
 			
 			/* Move past header, and leave BaseRetAddr intact */
 			i = RING_INDEX(i + sizeof(wb_data_t) + sizeof(wb_data_t));
 			
-			for (j = rcount; j > 0; --j) {
-				eb_from_cpu(buf+i, wops->read(wb, eb_to_cpu(buf+i)));
-				i = RING_INDEX(i + sizeof(wb_data_t));
+			if (rca) {
+				for (j = rcount; j > 0; --j) {
+					eb_from_cpu(buf+i, wops->read_cfg(wb, eb_to_cpu(buf+i)));
+					i = RING_INDEX(i + sizeof(wb_data_t));
+				}
+			} else {
+				for (j = rcount; j > 0; --j) {
+					eb_from_cpu(buf+i, wops->read(wb, eb_to_cpu(buf+i)));
+					i = RING_INDEX(i + sizeof(wb_data_t));
+				}
 			}
 		}
 		
diff --git a/driver/wishbone.h b/driver/wishbone.h
index f137a29..7ed3da7 100644
--- a/driver/wishbone.h
+++ b/driver/wishbone.h
@@ -26,6 +26,7 @@ struct wishbone_operations
 	void (*byteenable)(struct wishbone* wb, unsigned char mask);
 	void (*write)(struct wishbone* wb, wb_addr_t addr, wb_data_t);
 	wb_data_t (*read)(struct wishbone* wb, wb_addr_t addr);
+	wb_data_t (*read_cfg)(struct wishbone* wb, wb_addr_t addr);
 };
 
 /* One per wishbone backend hardware */
-- 
GitLab