diff options
-rw-r--r-- | c/src/lib/libbsp/sparc/leon2/include/bsp.h | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon2/include/leon.h | 8 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/include/bsp.h | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon3/include/leon.h | 8 | ||||
-rw-r--r-- | c/src/libchip/network/greth.c | 68 |
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 |