summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/lib/libbsp/sparc/leon2/include/bsp.h4
-rw-r--r--c/src/lib/libbsp/sparc/leon2/include/leon.h8
-rw-r--r--c/src/lib/libbsp/sparc/leon3/include/bsp.h4
-rw-r--r--c/src/lib/libbsp/sparc/leon3/include/leon.h8
-rw-r--r--c/src/libchip/network/greth.c68
5 files changed, 85 insertions, 7 deletions
diff --git a/c/src/lib/libbsp/sparc/leon2/include/bsp.h b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
index 3375d1034f..994f89bd8c 100644
--- a/c/src/lib/libbsp/sparc/leon2/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
@@ -60,6 +60,10 @@ extern int rtems_smc91111_driver_attach_leon2(
#define HAS_SMC91111
+/* Configure GRETH driver */
+#define GRETH_SUPPORTED
+#define GRETH_MEM_LOAD(addr) leon_r32_no_cache(addr)
+
/*
* The synchronous trap is an arbitrarily chosen software trap.
*/
diff --git a/c/src/lib/libbsp/sparc/leon2/include/leon.h b/c/src/lib/libbsp/sparc/leon2/include/leon.h
index 168ebe5b52..c183c90ff4 100644
--- a/c/src/lib/libbsp/sparc/leon2/include/leon.h
+++ b/c/src/lib/libbsp/sparc/leon2/include/leon.h
@@ -369,6 +369,14 @@ extern LEON_Register_Map LEON_REG;
#define LEON_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003
#define LEON_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003
+/* Load 32-bit word by forcing a cache-miss */
+static inline unsigned int leon_r32_no_cache(uintptr_t addr)
+{
+ unsigned int tmp;
+ asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr));
+ return tmp;
+}
+
#endif /* !ASM */
#ifdef __cplusplus
diff --git a/c/src/lib/libbsp/sparc/leon3/include/bsp.h b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
index 340ec6f126..421d850272 100644
--- a/c/src/lib/libbsp/sparc/leon3/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
@@ -73,6 +73,10 @@ extern int rtems_leon_greth_driver_attach(
#define HAS_SMC91111
+/* Configure GRETH driver */
+#define GRETH_SUPPORTED
+#define GRETH_MEM_LOAD(addr) leon_r32_no_cache(addr)
+
extern int CPU_SPARC_HAS_SNOOPING;
diff --git a/c/src/lib/libbsp/sparc/leon3/include/leon.h b/c/src/lib/libbsp/sparc/leon3/include/leon.h
index b953e59b40..cd50629176 100644
--- a/c/src/lib/libbsp/sparc/leon3/include/leon.h
+++ b/c/src/lib/libbsp/sparc/leon3/include/leon.h
@@ -326,6 +326,14 @@ extern int LEON3_Cpu_Index;
#define LEON_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003
#define LEON_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003
+/* Load 32-bit word by forcing a cache-miss */
+static inline unsigned int leon_r32_no_cache(uintptr_t addr)
+{
+ unsigned int tmp;
+ asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr));
+ return tmp;
+}
+
#endif /* !ASM */
#ifdef __cplusplus
diff --git a/c/src/libchip/network/greth.c b/c/src/libchip/network/greth.c
index aff4d0f896..df3c143278 100644
--- a/c/src/libchip/network/greth.c
+++ b/c/src/libchip/network/greth.c
@@ -12,10 +12,10 @@
*/
#include <rtems.h>
-
-#define GRETH_SUPPORTED
#include <bsp.h>
+#ifdef GRETH_SUPPORTED
+
#include <inttypes.h>
#include <errno.h>
#include <rtems/bspIo.h>
@@ -57,6 +57,11 @@ extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int );
extern void ipalign(struct mbuf *m);
#endif
+/* Used when reading from memory written by GRETH DMA unit */
+#ifndef GRETH_MEM_LOAD
+#define GRETH_MEM_LOAD(addr) (*(volatile unsigned int *)(addr))
+#endif
+
/*
* Number of OCs supported by this driver
*/
@@ -499,6 +504,45 @@ auto_neg_done:
print_init_info(sc);
}
+#ifdef CPU_U32_FIX
+
+/*
+ * Routine to align the received packet so that the ip header
+ * is on a 32-bit boundary. Necessary for cpu's that do not
+ * allow unaligned loads and stores and when the 32-bit DMA
+ * mode is used.
+ *
+ * Transfers are done on word basis to avoid possibly slow byte
+ * and half-word writes.
+ */
+
+void ipalign(struct mbuf *m)
+{
+ unsigned int *first, *last, data;
+ unsigned int tmp;
+
+ if ((((int) m->m_data) & 2) && (m->m_len)) {
+ last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
+ first = (unsigned int *) (((int) m->m_data) & ~3);
+ tmp = GRETH_MEM_LOAD(first);
+ tmp = tmp << 16;
+ first++;
+ do {
+ /* When snooping is not available the LDA instruction must be used
+ * to avoid the cache to return an illegal value.
+ * Load with forced cache miss
+ */
+ data = GRETH_MEM_LOAD(first);
+ *first = tmp | (data >> 16);
+ tmp = data << 16;
+ first++;
+ } while (first <= last);
+
+ m->m_data = (caddr_t)(((int) m->m_data) + 2);
+ }
+}
+#endif
+
void
greth_Daemon (void *arg)
{
@@ -510,6 +554,7 @@ greth_Daemon (void *arg)
rtems_event_set events;
rtems_interrupt_level level;
int first;
+ unsigned int tmp;
for (;;)
{
@@ -539,7 +584,7 @@ greth_Daemon (void *arg)
/* Scan for Received packets */
again:
while (!((len_status =
- dp->rxdesc[dp->rx_ptr].ctrl) & GRETH_RXD_ENABLE))
+ GRETH_MEM_LOAD(&dp->rxdesc[dp->rx_ptr].ctrl)) & GRETH_RXD_ENABLE))
{
bad = 0;
if (len_status & GRETH_RXD_TOOLONG)
@@ -583,10 +628,18 @@ again:
len - sizeof (struct ether_header);
eh = mtod (m, struct ether_header *);
+
m->m_data += sizeof (struct ether_header);
#ifdef CPU_U32_FIX
- if(!(dp->gbit_mac))
+ if(!dp->gbit_mac) {
+ /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */
+ tmp = GRETH_MEM_LOAD((uintptr_t)eh);
+ tmp = GRETH_MEM_LOAD(4+(uintptr_t)eh);
+ tmp = GRETH_MEM_LOAD(8+(uintptr_t)eh);
+ tmp = GRETH_MEM_LOAD(12+(uintptr_t)eh);
+
ipalign(m); /* Align packet on 32-bit boundary */
+ }
#endif
ether_input (ifp, eh, m);
@@ -641,7 +694,7 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
/*
* Is there a free descriptor available?
*/
- if ( dp->txdesc[dp->tx_ptr].ctrl & GRETH_TXD_ENABLE ){
+ if (GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].ctrl) & GRETH_TXD_ENABLE){
/* No. */
inside = 0;
return 1;
@@ -651,7 +704,7 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
n = m;
len = 0;
- temp = (unsigned char *) dp->txdesc[dp->tx_ptr].addr;
+ temp = (unsigned char *) GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].addr);
#ifdef GRETH_DEBUG
printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp);
#endif
@@ -814,7 +867,7 @@ int greth_process_tx_gbit(struct greth_softc *sc)
*/
for (;;){
/* Reap Sent packets */
- while((sc->tx_cnt > 0) && !(sc->txdesc[sc->tx_dptr].ctrl) && !(sc->txdesc[sc->tx_dptr].ctrl & GRETH_TXD_ENABLE)) {
+ while((sc->tx_cnt > 0) && !(GRETH_MEM_LOAD(&sc->txdesc[sc->tx_dptr].ctrl) & GRETH_TXD_ENABLE)) {
m_free(sc->txmbuf[sc->tx_dptr]);
sc->tx_dptr = (sc->tx_dptr + 1) % sc->txbufs;
sc->tx_cnt--;
@@ -1146,3 +1199,4 @@ rtems_greth_driver_attach (struct rtems_bsdnet_ifconfig *config,
return 1;
};
+#endif