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