summaryrefslogtreecommitdiffstats
path: root/c/src/libchip/network/greth.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/libchip/network/greth.c')
-rw-r--r--c/src/libchip/network/greth.c68
1 files changed, 61 insertions, 7 deletions
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