Port-alpha archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

TC alpha bus_space functions



Hi,

while writing "slhci at tc" support, I noticed TC bus_space functions for alpha don't work as they should (tc_bus_mem.c). Consideration of dense vs. sparse space seems problematic, especially for widths < 4.

I found information mainly in

[1] https://web-docs.gsi.de/~kraemer/COLLECTION/DEC/d3syspmb.pdf
[2] http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623255

and a dirty (but tested) hack based on this is attached as an example. It would be great if someone could have a look and do a cleaner version preferably.

Especially the end of ([2] section 12.2.2) provides a summary of which "instruction" to use for which data width in which space, and possible side effects (unintentional double reads/writes) in dense space...

Regards,
Felix
Index: tc/tc_bus_mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/tc/tc_bus_mem.c,v
retrieving revision 1.35
diff -u -p -r1.35 tc_bus_mem.c
--- tc/tc_bus_mem.c	4 Nov 2013 16:55:31 -0000	1.35
+++ tc/tc_bus_mem.c	21 Jul 2016 16:50:46 -0000
@@ -367,29 +367,39 @@ tc_mem_barrier(void *v, bus_space_handle
 static inline uint8_t
 tc_mem_read_1(void *v, bus_space_handle_t memh, bus_size_t off)
 {
-	volatile uint8_t *p;
 
 	alpha_mb();		/* XXX XXX XXX */
 
-	if ((memh & TC_SPACE_SPARSE) != 0)
-		panic("tc_mem_read_1 not implemented for sparse space");
+	if ((memh & TC_SPACE_SPARSE) != 0) {
+		volatile uint32_t *p;
 
-	p = (uint8_t *)(memh + off);
-	return (*p);
+		p = (uint32_t *)(memh + ((off & ((bus_size_t)-1 << 2)) << 1));
+		return ((*p >> ((off & 3) * 8)) & 0xff);
+	} else {
+		volatile uint8_t *p;
+
+		p = (uint8_t *)(memh + off);
+		return (*p);
+	}
 }
 
 static inline uint16_t
 tc_mem_read_2(void *v, bus_space_handle_t memh, bus_size_t off)
 {
-	volatile uint16_t *p;
 
 	alpha_mb();		/* XXX XXX XXX */
 
-	if ((memh & TC_SPACE_SPARSE) != 0)
-		panic("tc_mem_read_2 not implemented for sparse space");
+	if ((memh & TC_SPACE_SPARSE) != 0) {
+		volatile uint32_t *p;
 
-	p = (uint16_t *)(memh + off);
-	return (*p);
+		p = (uint32_t *)(memh + ((off & ((bus_size_t)-1 << 2)) << 1));
+		return ((*p >> ((off & 2) * 8)) & 0xffff);
+	} else {
+		volatile uint16_t *p;
+
+		p = (uint16_t *)(memh + off);
+		return (*p);
+	}
 }
 
 static inline uint32_t
@@ -467,17 +477,13 @@ tc_mem_write_1(void *v, bus_space_handle
 
 	if ((memh & TC_SPACE_SPARSE) != 0) {
 		volatile uint64_t *p;
-		off &= 0x3;
-
-		p = (uint64_t *)(memh + (off << 1));
+		uint64_t mask = UINT64_C(0x1) << (32 + (off & 3));
 
-		*p = val;
-	} else {
-		volatile uint8_t *p;
+		p = (uint64_t *)(memh + ((off & ((bus_size_t)-1 << 2)) << 1));
+		*p = mask | ((uint64_t)val << ((off & 3) * 8));
+	} else
+		panic("tc_mem_write_1 not implemented for dense space");
 
-		p = (uint8_t *)(memh + off);
-		*p = val;
-	}
 	alpha_mb();		/* XXX XXX XXX */
 }
 
@@ -487,18 +493,13 @@ tc_mem_write_2(void *v, bus_space_handle
 
 	if ((memh & TC_SPACE_SPARSE) != 0) {
 		volatile uint64_t *p;
+		uint64_t mask = UINT64_C(0x3) << (32 + (off & 2));
 
-		off &= 0x3;
-
-		p = (uint64_t *)(memh + (off << 1));
+		p = (uint64_t *)(memh + ((off & ((bus_size_t)-1 << 2)) << 1));
+		*p = mask | ((uint64_t)val << ((off & 2) * 8));
+	} else
+		panic("tc_mem_write_2 not implemented for dense space");
 
-		*p = val;
-	} else {
-		volatile uint16_t *p;
-
-		p = (uint16_t *)(memh + off);
-		*p = val;
-	}
 	alpha_mb();		/* XXX XXX XXX */
 }
 
@@ -513,6 +514,7 @@ tc_mem_write_4(void *v, bus_space_handle
 	else
 		p = (uint32_t *)(memh + off);
 	*p = val;
+
 	alpha_mb();		/* XXX XXX XXX */
 }
 
@@ -526,6 +528,7 @@ tc_mem_write_8(void *v, bus_space_handle
 
 	p = (uint64_t *)(memh + off);
 	*p = val;
+
 	alpha_mb();		/* XXX XXX XXX */
 }
 


Home | Main Index | Thread Index | Old Index