From: till straumann <till.straum...@alumni.tu-berlin.de>

Update #4344
---
 .../powerpc/beatnik/include/bsp/mv643xx_eth.h |   85 +-
 bsps/powerpc/beatnik/net/if_mve/mv643xx_eth.c |  343 ++-
 .../beatnik/net/if_mve/mv643xx_eth_bsdnet.c   | 2601 ++---------------
 3 files changed, 575 insertions(+), 2454 deletions(-)

diff --git a/bsps/powerpc/beatnik/include/bsp/mv643xx_eth.h 
b/bsps/powerpc/beatnik/include/bsp/mv643xx_eth.h
index eefca62603..f963b91d3d 100644
--- a/bsps/powerpc/beatnik/include/bsp/mv643xx_eth.h
+++ b/bsps/powerpc/beatnik/include/bsp/mv643xx_eth.h
@@ -3,24 +3,11 @@
 
 struct mveth_private;
 
-/* Clear multicast filters                        */
-void
-BSP_mve_mcast_filter_clear(struct mveth_private *mp);
-void
-BSP_mve_mcast_filter_accept_all(struct mveth_private *mp);
-void
-BSP_mve_mcast_filter_accept_add(struct mveth_private *mp, unsigned char 
*enaddr);
-void
-BSP_mve_mcast_filter_accept_del(struct mveth_private *mp, unsigned char 
*enaddr);
-/* Stop hardware and clean out the rings */
-void
-BSP_mve_stop_hw(struct mveth_private *mp);
-
 struct mveth_private *
-BSP_mve_setup_1(
-       struct mveth_private*,
+BSP_mve_create(
        int              unit,
-       void     (*isr)(void *isr_arg),
+       rtems_id tid,
+       void     (*isr)(void*isr_arg),
        void     *isr_arg,
        void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
        void *cleanup_txbuf_arg,
@@ -32,6 +19,23 @@ BSP_mve_setup_1(
        int             irq_mask
 );
 
+/* Enable/disable promiscuous mode */
+void
+BSP_mve_promisc_set(struct mveth_private *mp, int promisc);
+
+/* Clear multicast filters                        */
+void
+BSP_mve_mcast_filter_clear(struct mveth_private *mp);
+void
+BSP_mve_mcast_filter_accept_all(struct mveth_private *mp);
+void
+BSP_mve_mcast_filter_accept_add(struct mveth_private *mp, unsigned char 
*enaddr);
+void
+BSP_mve_mcast_filter_accept_del(struct mveth_private *mp, unsigned char 
*enaddr);
+/* Stop hardware and clean out the rings */
+void
+BSP_mve_stop_hw(struct mveth_private *mp);
+
 /* MAIN RX-TX ROUTINES
  *
  * BSP_mve_swipe_tx():  descriptor scavenger; releases mbufs
@@ -44,6 +48,33 @@ BSP_mve_setup_1(
 /* clean up the TX ring freeing up buffers */
 int
 BSP_mve_swipe_tx(struct mveth_private *mp);
+
+/* Enqueue a mbuf chain or a raw data buffer for transmission;
+ * RETURN: #bytes sent or -1 if there are not enough descriptors
+ *         -2 is returned if the caller should attempt to
+ *         repackage the chain into a smaller one.
+ *
+ * Comments: software cache-flushing incurs a penalty if the
+ *           packet cannot be queued since it is flushed anyways.
+ *           The algorithm is slightly more efficient in the normal
+ *                      case, though.
+ */
+
+typedef struct MveEthBufIter {
+       void  *hdl;    /* opaque handle for the iterator implementor */
+       void  *data;   /* data to be sent                            */
+       size_t len;    /* data size (in octets)                      */
+       void  *uptr;   /* user-pointer to go into the descriptor;
+                      note: cleanup_txbuf is only called for desriptors
+                               where this field is non-NULL (for historical
+                               reasons)                             */
+} MveEthBufIter;
+
+typedef MveEthBufIter *(*MveEthBufIterNext)(const MveEthBufIter*);
+
+int
+BSP_mve_send_buf_chain(struct mveth_private *mp, MveEthBufIterNext next, 
MveEthBufIter *it);
+
 int
 BSP_mve_send_buf_raw(
        struct mveth_private *mp,
@@ -51,6 +82,7 @@ BSP_mve_send_buf_raw(
        int                   h_len,
        void                 *data_p,
     int                   d_len);
+
 /* send received buffers upwards and replace them
  * with freshly allocated ones;
  * ASSUMPTION: buffer length NEVER changes and is set
@@ -82,6 +114,14 @@ BSP_mve_detach(struct mveth_private *mp);
 void
 BSP_mve_init_hw(struct mveth_private *mp, int promisc, unsigned char *enaddr);
 
+#define MV643XX_MEDIA_FD   (1<<0)
+#define MV643XX_MEDIA_10   (1<<8)
+#define MV643XX_MEDIA_100  (2<<8)
+#define MV643XX_MEDIA_1000 (3<<8)
+#define MV643XX_MEDIA_SPEED_MSK (0xff00)
+void
+BSP_mve_update_serial_port(struct mveth_private *mp, int media);
+
 /* read ethernet address from hw to buffer */
 void
 BSP_mve_read_eaddr(struct mveth_private *mp, unsigned char *oeaddr);
@@ -90,12 +130,19 @@ void
 BSP_mve_enable_irqs(struct mveth_private *mp);
 void
 BSP_mve_disable_irqs(struct mveth_private *mp);
+
+#define MV643XX_ETH_IRQ_RX_DONE                                                
(1<<2)
+#define MV643XX_ETH_EXT_IRQ_TX_DONE                                    (1<<0)
+#define MV643XX_ETH_EXT_IRQ_LINK_CHG                           (1<<16)
 uint32_t
 BSP_mve_ack_irqs(struct mveth_private *mp);
+
 void
 BSP_mve_enable_irq_mask(struct mveth_private *mp, uint32_t mask);
+
 uint32_t
 BSP_mve_disable_irq_mask(struct mveth_private *mp, uint32_t mask);
+
 uint32_t
 BSP_mve_ack_irq_mask(struct mveth_private *mp, uint32_t mask);
 
@@ -108,4 +155,10 @@ BSP_mve_mii_read(struct mveth_private *mp, unsigned addr);
 unsigned
 BSP_mve_mii_write(struct mveth_private *mp, unsigned addr, unsigned v);
 
+unsigned
+BSP_mve_mii_read_early(int port, unsigned addr);
+
+unsigned
+BSP_mve_mii_write_early(int port, unsigned addr, unsigned v);
+
 #endif
diff --git a/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth.c 
b/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth.c
index d002fd52ce..26fe7db9e6 100644
--- a/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth.c
+++ b/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth.c
@@ -94,6 +94,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <stdlib.h>
 
 #include <bsp/mv643xx_eth.h>
 
@@ -748,17 +749,6 @@ struct mveth_private {
 };
 
 /* GLOBAL VARIABLES */
-#ifdef MVETH_DEBUG_TX_DUMP
-int mveth_tx_dump = 0;
-#endif
-
-/* register access protection mutex */
-STATIC rtems_id mveth_mtx = 0;
-#define REGLOCK()      do { \
-               if ( RTEMS_SUCCESSFUL != rtems_semaphore_obtain(mveth_mtx, 
RTEMS_WAIT, RTEMS_NO_TIMEOUT) ) \
-                       rtems_panic(DRVNAME": unable to lock register 
protection mutex"); \
-               } while (0)
-#define REGUNLOCK()    rtems_semaphore_release(mveth_mtx)
 
 /* Format strings for statistics messages */
 static const char *mibfmt[] = {
@@ -1059,6 +1049,14 @@ uint32_t x;
        MV_WRITE(MV643XX_ETH_MAC_ADDR_LO(mp->port_num), x);
 }
 
+static inline int
+port2phy(int port)
+{
+       port &= 0x1f;
+       /* during early init we may not know the phy and we are given a port 
number instead! */
+       return  ( (MV_READ(MV643XX_ETH_PHY_ADDR_R) >> (5*port)) & 0x1f );
+}
+
 /* PHY/MII Interface
  *
  * Read/write a PHY register;
@@ -1068,8 +1066,8 @@ uint32_t  x;
  *       If non-bsd drivers are running on a subset of IFs proper
  *       locking of all shared registers must be implemented!
  */
-unsigned
-BSP_mve_mii_read(struct mveth_private *mp, unsigned addr)
+static unsigned
+do_mii_read(int phy, unsigned addr)
 {
 unsigned v;
 unsigned wc = 0;
@@ -1082,7 +1080,7 @@ unsigned wc = 0;
                wc++;
        } while ( MV643XX_ETH_SMI_BUSY & v );
 
-       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (mp->phy<<16) | 
MV643XX_ETH_SMI_OP_RD );
+       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (phy<<16) | 
MV643XX_ETH_SMI_OP_RD );
 
        do {
                v = MV_READ(MV643XX_ETH_SMI_R);
@@ -1095,7 +1093,19 @@ unsigned wc = 0;
 }
 
 unsigned
-BSP_mve_mii_write(struct mveth_private *mp, unsigned addr, unsigned v)
+BSP_mve_mii_read(struct mveth_private *mp, unsigned addr)
+{
+       return do_mii_read(mp->phy, addr);
+}
+
+unsigned
+BSP_mve_mii_read_early(int port, unsigned addr)
+{
+       return do_mii_read(port2phy(port), addr);
+}
+
+static unsigned
+do_mii_write(int phy, unsigned addr, unsigned v)
 {
 unsigned wc = 0;
 
@@ -1110,11 +1120,24 @@ unsigned wc = 0;
        while ( MV643XX_ETH_SMI_BUSY & MV_READ(MV643XX_ETH_SMI_R) )
                wc++ /* wait */;
 
-       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (mp->phy<<16) | 
MV643XX_ETH_SMI_OP_WR | v );
+       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (phy<<16) | 
MV643XX_ETH_SMI_OP_WR | v );
 
        return wc;
 }
 
+unsigned
+BSP_mve_mii_write(struct mveth_private *mp, unsigned addr, unsigned v)
+{
+       return do_mii_write( mp->phy, addr, v );
+}
+
+unsigned
+BSP_mve_mii_write_early(int port, unsigned addr, unsigned v)
+{
+       return do_mii_write(port2phy(port), addr, v);
+}
+
+
 /* MID-LAYER SUPPORT ROUTINES */
 
 /* Start TX if descriptors are exhausted */
@@ -1151,6 +1174,19 @@ uint32_t active_q;
        return active_q;
 }
 
+void
+BSP_mve_promisc_set(struct mveth_private *mp, int promisc)
+{
+uint32_t              v;
+
+       v = MV_READ(MV643XX_ETH_PORT_CONFIG_R(mp->port_num));
+       if ( (mp->promisc = promisc) )
+               v |= MV643XX_ETH_UNICAST_PROMISC_MODE;
+       else
+               v &= ~MV643XX_ETH_UNICAST_PROMISC_MODE;
+       MV_WRITE(MV643XX_ETH_PORT_CONFIG_R(mp->port_num), v);
+}
+
 /* update serial port settings from current link status */
 
 void
@@ -1367,7 +1403,7 @@ register uint8_t *d = to, *s = fro;
 #endif
 
 static int
-mveth_assign_desc_raw(MvEthTxDesc d, void *buf, int len, unsigned long extra)
+mveth_assign_desc_raw(MvEthTxDesc d, void *buf, int len, void *uptr, unsigned 
long extra)
 {
 int rval = (d->byte_cnt = len);
 
@@ -1389,6 +1425,7 @@ int rval = (d->byte_cnt = len);
        {
                d->buf_ptr  = CPUADDR2ENET( (unsigned long)buf );
        }
+       d->u_buf    = uptr;
        d->l4i_chk  = 0;
        return rval;
 }
@@ -1477,9 +1514,8 @@ MvEthTxDesc d;
 
 /* PUBLIC LOW-LEVEL DRIVER ACCESS */
 
-static struct mveth_private *
-mve_setup_internal(
-       struct mveth_private *mp,
+struct mveth_private *
+BSP_mve_create(
        int              unit,
        rtems_id tid,
        void     (*isr)(void*isr_arg),
@@ -1493,8 +1529,8 @@ mve_setup_internal(
        int             tx_ring_size,
        int             irq_mask
 )
-
 {
+struct mveth_private *mp;
 int                  InstallISRSuccessful;
 
        if ( unit <= 0 || unit > MV643XXETH_NUM_DRIVER_SLOTS ) {
@@ -1510,25 +1546,20 @@ int                  InstallISRSuccessful;
                return 0;
        }
 
-       /* lazy init of mutex (non thread-safe! - we assume 1st initialization 
is single-threaded) */
-       if ( ! mveth_mtx ) {
-               rtems_status_code sc;
-               sc = rtems_semaphore_create(
-                               rtems_build_name('m','v','e','X'),
-                               1,
-                               RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | 
RTEMS_INHERIT_PRIORITY | RTEMS_DEFAULT_ATTRIBUTES,
-                               0,
-                               &mveth_mtx);
-               if ( RTEMS_SUCCESSFUL != sc ) {
-                       rtems_error(sc,DRVNAME": creating mutex\n");
-                       rtems_panic("unable to proceed\n");
-               }
+       if ( tx_ring_size < 1 ) {
+               printk(DRVNAME": tx ring size must not be zero (networking 
configuration issue?)\n");
+               return 0;
        }
 
-       memset(mp, 0, sizeof(*mp));
+       if ( rx_ring_size < 1 ) {
+               printk(DRVNAME": rx ring size must not be zero (networking 
configuration issue?)\n");
+               return 0;
+       }
+
+       mp = calloc( 1, sizeof *mp );
 
        mp->port_num          = unit-1;
-       mp->phy               = (MV_READ(MV643XX_ETH_PHY_ADDR_R) >> 
(5*mp->port_num)) & 0x1f;
+       mp->phy               = port2phy(mp->port_num);
 
        mp->tid               = tid;
        mp->isr               = isr;
@@ -1540,8 +1571,8 @@ int                  InstallISRSuccessful;
        mp->consume_rxbuf     = consume_rxbuf;
        mp->consume_rxbuf_arg = consume_rxbuf_arg;
 
-       mp->rbuf_count = rx_ring_size ? rx_ring_size : MV643XX_RX_RING_SIZE;
-       mp->xbuf_count = tx_ring_size ? tx_ring_size : MV643XX_TX_RING_SIZE;
+       mp->rbuf_count = rx_ring_size;
+       mp->xbuf_count = tx_ring_size;
 
        if ( mp->xbuf_count > 0 )
                mp->xbuf_count += TX_NUM_TAG_SLOTS;
@@ -1551,16 +1582,10 @@ int                  InstallISRSuccessful;
        if ( mp->xbuf_count < 0 )
                mp->xbuf_count = 0;
 
-#ifdef BSDBSD
        /* allocate ring area; add 1 entry -- room for alignment */
        assert( !mp->ring_area );
-       mp->ring_area = malloc(
-                                                       sizeof(*mp->ring_area) *
-                                                               (mp->rbuf_count 
+ mp->xbuf_count + 1),
-                                                       M_DEVBUF,
-                                                       M_WAIT );
+       mp->ring_area = malloc( sizeof(*mp->ring_area) * (mp->rbuf_count + 
mp->xbuf_count + 1) );
        assert( mp->ring_area );
-#endif
 
        BSP_mve_stop_hw(mp);
 
@@ -1587,37 +1612,56 @@ int                  InstallISRSuccessful;
        return mp;
 }
 
-struct mveth_private *
-BSP_mve_setup_1(
-       struct mveth_private *mp,
-       int              unit,
-       void     (*isr)(void *isr_arg),
-       void     *isr_arg,
-       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
-       void *cleanup_txbuf_arg,
-       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
-       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
-       void *consume_rxbuf_arg,
-       int             rx_ring_size,
-       int             tx_ring_size,
-       int             irq_mask
-)
+void
+BSP_mve_update_serial_port(struct mveth_private *mp, int media)
 {
-       if ( irq_mask && 0 == isr ) {
-               printk(DRVNAME": must supply an ISR if irq_msk not zero\n");
-               return 0;       
+int port = mp->port_num;
+uint32_t old, new;
+
+       new = old = MV_READ(MV643XX_ETH_SERIAL_CONTROL_R(port));
+
+       /* mask speed and duplex settings */
+       new &= ~(  MV643XX_ETH_SET_GMII_SPEED_1000
+                        | MV643XX_ETH_SET_MII_SPEED_100
+                        | MV643XX_ETH_SET_FULL_DUPLEX );
+
+       if ( (MV643XX_MEDIA_FD & media) )
+               new |= MV643XX_ETH_SET_FULL_DUPLEX;
+
+       switch ( (media & MV643XX_MEDIA_SPEED_MSK) ) {
+               default: /* treat as 10 */
+                       break;
+               case MV643XX_MEDIA_100:
+                       new |= MV643XX_ETH_SET_MII_SPEED_100;
+                       break;
+               case MV643XX_MEDIA_1000:
+                       new |= MV643XX_ETH_SET_GMII_SPEED_1000;
+                       break;
        }
 
-       return mve_setup_internal(
-                               mp,
-                               unit,
-                               0,
-                               isr, isr_arg,
-                               cleanup_txbuf, cleanup_txbuf_arg,
-                               alloc_rxbuf,
-                               consume_rxbuf, consume_rxbuf_arg,
-                               rx_ring_size, tx_ring_size,
-                               irq_mask);
+
+       if ( new != old ) {
+               if ( ! (MV643XX_ETH_SERIAL_PORT_ENBL & new) ) {
+                       /* just write */
+                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
+               } else {
+                       uint32_t were_running;
+
+                       were_running = mveth_stop_tx(port);
+
+                       old &= ~MV643XX_ETH_SERIAL_PORT_ENBL;
+                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), old);
+                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
+                       /* linux driver writes twice... */
+                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
+
+                       if ( were_running ) {
+                               
MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
+                       }
+               }
+       }
+       /* If TX stalled because there was no buffer then whack it */
+       mveth_start_tx(mp);
 }
 
 rtems_id
@@ -1629,24 +1673,14 @@ BSP_mve_get_tid(struct mveth_private *mp)
 int
 BSP_mve_detach(struct mveth_private *mp)
 {
-#ifdef BSDBSD
-int unit = mp->port_num;
-#endif
        BSP_mve_stop_hw(mp);
        if ( mp->irq_mask || mp->xirq_mask ) {
                if ( !BSP_remove_rtems_irq_handler( &irq_data[mp->port_num] ) )
                        return -1;
        }
-#ifdef BSDBSD
-#warning FIXME
-       free( (void*)mp->ring_area, M_DEVBUF );
-#endif
+       free( (void*)mp->ring_area );
        memset(mp, 0, sizeof(*mp));
        __asm__ __volatile__("":::"memory");
-       /* mark as unused */
-#ifdef BSDBSD
-       theMvEths[unit].arpcom.ac_if.if_init = 0;
-#endif
        return 0;
 }
 
@@ -1692,6 +1726,133 @@ register MvEthTxDesc    d;
        return rval;
 }
 
+int
+BSP_mve_send_buf_chain(struct mveth_private *mp, MveEthBufIterNext next, 
MveEthBufIter *it)
+{
+int                                            rval;
+register MvEthTxDesc   l,d,h;
+int                                            nmbs;
+MveEthBufIter           head = *it;
+
+       rval = 0;
+
+       /* if no descriptor is available; try to wipe the queue */
+       if ( (mp->avail < 1) && MVETH_CLEAN_ON_SEND(mp)<=0 ) {
+               /* Maybe TX is stalled and needs to be restarted */
+               mveth_start_tx(mp);
+               return -1;
+       }
+
+       h = mp->d_tx_h;
+
+#ifdef MVETH_TESTING 
+       assert( !h->buf_ptr );
+       assert( !h->mb      );
+#endif
+
+       /* Don't use the first descriptor yet because BSP_mve_swipe_tx()
+        * needs mp->d_tx_h->buf_ptr == NULL as a marker. Hence, we
+        * start with the second mbuf and fill the first descriptor
+        * last.
+        */
+
+       l = h;
+       d = NEXT_TXD(h);
+
+       mp->avail--;
+
+       nmbs = 1;
+       while ( (it = next(it)) ) {
+               if ( 0 == it->len )
+                       continue;       /* skip empty mbufs */
+
+               nmbs++;
+
+               if ( mp->avail < 1 && MVETH_CLEAN_ON_SEND(mp)<=0 ) {
+                       /* Maybe TX was stalled - try to restart */
+                       mveth_start_tx(mp);
+
+                       /* not enough descriptors; cleanup...
+                        * the first slot was never used, so we start
+                        * at mp->d_tx_h->next;
+                        */
+                       for ( l = NEXT_TXD(h); l!=d; l=NEXT_TXD(l) ) {
+#ifdef MVETH_TESTING
+                               assert( l->mb == 0 );
+#endif
+                               l->buf_ptr  = 0;
+                               l->cmd_sts  = 0;
+                               mp->avail++;
+                       }
+                       mp->avail++;
+                       if ( nmbs > TX_AVAILABLE_RING_SIZE(mp) ) {
+                               /* this chain will never fit into the ring */
+                               if ( nmbs > mp->stats.maxchain )
+                                       mp->stats.maxchain = nmbs;
+                               mp->stats.repack++;
+                               /* caller may reorganize chain */
+                               return -2;
+                       }
+                       return -1;
+               }
+
+               mp->avail--;
+
+#ifdef MVETH_TESTING
+               assert( d != h      );
+               assert( !d->buf_ptr );
+#endif
+
+               /* fill this slot */
+               rval += mveth_assign_desc_raw(d, it->data, it->len, it->uptr, 
TDESC_DMA_OWNED);
+
+               FLUSH_BUF( (uint32_t)it->data, it->len );
+
+               l = d;
+               d = NEXT_TXD(d);
+
+               FLUSH_DESC(l);
+       }
+
+       /* fill first slot - don't release to DMA yet */
+       rval += mveth_assign_desc_raw(h, head.data, head.len, head.uptr, 
TDESC_FRST);
+
+
+       FLUSH_BUF((uint32_t)head.data, head.len);
+
+
+       /* tag last slot; this covers the case where 1st==last */
+       l->cmd_sts      |= TDESC_LAST | TDESC_INT_ENA;
+
+       FLUSH_DESC(l);
+
+       /* Tag end; make sure chip doesn't try to read ahead of here! */
+       l->next->cmd_sts = 0;
+       FLUSH_DESC(l->next);
+
+       membarrier();
+
+       /* turn over the whole chain by flipping ownership of the first desc */
+       h->cmd_sts |= TDESC_DMA_OWNED;
+
+       FLUSH_DESC(h);
+
+       membarrier();
+
+       /* notify the device */
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
+
+       /* Update softc */
+       mp->stats.packet++;
+       if ( nmbs > mp->stats.maxchain )
+               mp->stats.maxchain = nmbs;
+
+       /* remember new head */
+       mp->d_tx_h = d;
+
+       return rval; /* #bytes sent */
+}
+
 int
 BSP_mve_send_buf_raw(
        struct mveth_private *mp,
@@ -1754,7 +1915,7 @@ int                     frst_len;
                assert( d != h      );
                assert( !d->buf_ptr );
 #endif
-               rval += mveth_assign_desc_raw(d, data_p, d_len, 
TDESC_DMA_OWNED);
+               rval += mveth_assign_desc_raw(d, data_p, d_len, 0, 
TDESC_DMA_OWNED);
                FLUSH_BUF( (uint32_t)data_p, d_len );
                d->u_buf = data_p;
 
@@ -1765,7 +1926,7 @@ int                     frst_len;
        }
 
        /* fill first slot with raw buffer - don't release to DMA yet */
-       rval       += mveth_assign_desc_raw(h, frst_buf, frst_len, TDESC_FRST);
+       rval       += mveth_assign_desc_raw(h, frst_buf, frst_len, 0, 
TDESC_FRST);
 
        FLUSH_BUF( (uint32_t)frst_buf, frst_len);
 
@@ -2158,8 +2319,8 @@ BSP_mve_ack_irq_mask(struct mveth_private *mp, uint32_t 
mask)
        return mveth_ack_irqs(mp, mask);
 }
 
-static void
-dump_update_stats(struct mveth_private *mp, FILE *f)
+void
+BSP_mve_dump_stats(struct mveth_private *mp, FILE *f)
 {
 int      p = mp->port_num;
 int      idx;
@@ -2198,9 +2359,3 @@ uint32_t v;
        }
        fprintf(f, "\n");
 }
-
-void
-BSP_mve_dump_stats(struct mveth_private *mp, FILE *f)
-{
-       dump_update_stats(mp, f);
-}
diff --git a/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth_bsdnet.c 
b/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth_bsdnet.c
index a2efdce8e1..2e841c5e8b 100644
--- a/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth_bsdnet.c
+++ b/bsps/powerpc/beatnik/net/if_mve/mv643xx_eth_bsdnet.c
@@ -74,14 +74,12 @@
  *       further down...
  */
 
-/*
 #ifndef KERNEL
 #define KERNEL
 #endif
 #ifndef _KERNEL
 #define _KERNEL
 #endif
-*/
 
 #include <rtems.h>
 #include <rtems/bspIo.h>
@@ -95,14 +93,15 @@
 #include <errno.h>
 #include <inttypes.h>
 
+#include <bsp/mv643xx_eth.h>
 
-#ifdef BSDBSD
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <dev/mii/mii.h>
 #include <net/if_var.h>
+#include <net/if_arp.h>
 #include <net/if_media.h>
 
 /* Not so nice; would be more elegant not to depend on C library but the
@@ -125,14 +124,11 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
-#endif /* BSDBSD */
 
-#ifdef BSDBSD
 #include <rtems/rtems_mii_ioctl.h>
 
 #include <bsp/early_enet_link_status.h>
 #include <bsp/if_mve_pub.h>
-#endif /* BSDBSD */
 
 /* CONFIGURABLE PARAMETERS */
 
@@ -149,12 +145,6 @@
 /* Enable debugging messages and some support routines  (dump rings etc.)      
              */      
 #undef  MVETH_DEBUG
 
-/* Hack for driver development; rtems bsdnet doesn't implement detaching an 
interface :-(
- * but this hack allows us to unload/reload the driver module which makes 
development
- * a lot less painful.
- */
-#undef MVETH_DETACH_HACK
-
 /* Ring sizes */
 
 #ifdef MVETH_TESTING
@@ -201,154 +191,8 @@
 
 #define TX_NUM_TAG_SLOTS                       1 /* leave room for tag; must 
not be 0 */
 
-/* This is REAL; chip reads from 64-bit down-aligned buffer
- * if the buffer size is < 8 !!! for buffer sizes 8 and upwards
- * alignment is not an issue. This was verified using the
- * 'mve_smallbuf_test.c'
- */
-#define ENABLE_TX_WORKAROUND_8_BYTE_PROBLEM
-
-/* Chip register configuration values */
-#define        MVETH_PORT_CONFIG_VAL                   (0                      
        \
-                       | MV643XX_ETH_DFLT_RX_Q(0)                              
        \
-                       | MV643XX_ETH_DFLT_RX_ARP_Q(0)                          
\
-                       | MV643XX_ETH_DFLT_RX_TCP_Q(0)                          
\
-                       | MV643XX_ETH_DFLT_RX_UDP_Q(0)                          
\
-                       | MV643XX_ETH_DFLT_RX_BPDU_Q(0)                         
\
-                       )
-
-
-#define        MVETH_PORT_XTEND_CONFIG_VAL             0
-
-#ifdef OLDCONFIGVAL
-#define        MVETH_SERIAL_CTRL_CONFIG_VAL    (0                              
\
-                        | MV643XX_ETH_FORCE_LINK_PASS                          
\
-                        | MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOWCTL     \
-                        | MV643XX_ETH_ADVERTISE_SYMMETRIC_FLOWCTL      \
-                        | MV643XX_ETH_BIT9_UNKNOWN                             
        \
-                        | MV643XX_ETH_FORCE_LINK_FAIL_DISABLE          \
-                        | MV643XX_ETH_SC_MAX_RX_1552                           
\
-                        | MV643XX_ETH_SET_FULL_DUPLEX                          
\
-                        | MV643XX_ETH_ENBL_FLOWCTL_TX_RX_IN_FD         \
-                        )
-#endif
-/* If we enable autoneg (duplex, speed, ...) then it seems
- * that the chip automatically updates link settings
- * (correct link settings are reflected in PORT_STATUS_R).
- * However, when we disable aneg in the PHY then things
- * can get messed up and the port doesn't work anymore.
- * => we follow the linux driver in disabling all aneg
- * in the serial config reg. and manually updating the
- * speed & duplex bits when the phy link status changes.
- * FIXME: don't know what to do about pause/flow-ctrl.
- * It is best to just use ANEG anyways!!!
- */
-#define        MVETH_SERIAL_CTRL_CONFIG_VAL    (0                              
\
-                        | MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLEX      \
-                        | MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOWCTL     \
-                        | MV643XX_ETH_ADVERTISE_SYMMETRIC_FLOWCTL      \
-                        | MV643XX_ETH_BIT9_UNKNOWN                             
        \
-                        | MV643XX_ETH_FORCE_LINK_FAIL_DISABLE          \
-                        | MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII      \
-                        | MV643XX_ETH_SC_MAX_RX_1552                           
\
-                        )
-
-#define        MVETH_SERIAL_CTRL_CONFIG_MSK    (0                              
\
-                        | MV643XX_ETH_SERIAL_PORT_ENBL                         
\
-                        | MV643XX_ETH_FORCE_LINK_PASS                          
\
-                        | MV643XX_ETH_SC_MAX_RX_MASK                           
\
-                        )
-
-
-#ifdef __PPC__
-#define MVETH_SDMA_CONFIG_VAL                  (0                              
\
-                       | MV643XX_ETH_RX_BURST_SZ_4_64BIT                       
\
-                       | MV643XX_ETH_TX_BURST_SZ_4_64BIT                       
\
-                       )
-#else
-#define MVETH_SDMA_CONFIG_VAL                  (0                              
\
-                       | MV643XX_ETH_RX_BURST_SZ_16_64BIT                      
\
-                       | MV643XX_ETH_TX_BURST_SZ_16_64BIT                      
\
-                       )
-#endif
-
-/* minimal frame size we accept */
-#define MVETH_MIN_FRAMSZ_CONFIG_VAL    40
-
-/* END OF CONFIGURABLE SECTION */
-
-/*
- * Here's stuff I learned about this chip:
- *
- *
- * RX interrupt flags:
- *
- * broadcast packet RX: 0x00000005
- *           last buf:  0x00000c05
- *           overrun:   0x00000c00           
- * unicast   packet RX: 0x00000005
- * bad CRC received:    0x00000005
- *
- * clearing 0x00000004 -> clears 0x00000001
- * clearing 0x00000400 -> clears 0x00000800
- *
- * --> 0x0801 are probably some sort of summary bits.
- *
- * TX interrupt flags:
- *
- * broadcast packet in 1 buf: xcause: 0x00000001 (cause 0x00080000)
- *        into disconn. link:             "                 "
- *
- * in some cases, I observed  xcause: 0x00000101 (reason for 0x100 unknown
- * but the linux driver accepts it also).
- *
- *
- * Here a few more ugly things about this piece of hardware I learned
- * (painfully, painfully; spending many many hours & nights :-()
- *
- * a) Especially in the case of 'chained' descriptors, the DMA keeps
- *    clobbering 'cmd_sts' long after it cleared the OWNership flag!!!
- *    Only after the whole chain is processed (OWN cleared on the
- *    last descriptor) it is safe to change cmd_sts.
- *    However, in the case of hardware snooping I found that the
- *    last descriptor in chain has its cmd_sts still clobbered *after*
- *    checking ownership!, I.e.,
- *        if ( ! OWN & cmd_sts ) {
- *            cmd_sts = 0;
- *        }
- *    --> sometimes, cmd_sts is STILL != 0 here
- *
- * b) Sometimes, the OWNership flag is *not cleared*.  
- * 
- * c) Weird things happen if the chip finds a descriptor with 'OWN'
- *    still set (i.e., not properly loaded), i.e., corrupted packets
- *    are sent [with OK checksum since the chip calculates it]. 
- *
- * Combine a+b+c and we end up with a real mess.
- *
- * The fact that the chip doesn't reliably reset OWN and that OTOH,
- * it can't be reliably reset by the driver and still, the chip needs
- * it for proper communication doesn't make things easy...
- *
- * Here the basic workarounds:
- *
- *     - In addition to check OWN, the scavenger compares the "currently
- *       served desc" register to the descriptor it tries to recover and
- *       ignores OWN if they do not match. Hope this is OK.
- *       Otherwise, we could scan the list of used descriptors and proceed
- *       recycling descriptors if we find a !OWNed one behind the target...
- *
- *     - Always keep an empty slot around to mark the end of the list of
- *       jobs. The driver clears the descriptor ahead when enqueueing a new
- *       packet.
- */
-
 #define DRVNAME                        "mve"
-#define MAX_NUM_SLOTS  3
-
-#if MV643XXETH_NUM_DRIVER_SLOTS > MAX_NUM_SLOTS
-#error "mv643xxeth: only MAX_NUM_SLOTS supported"
-#endif
+#define MAX_NUM_SLOTS   3
 
 #ifdef NDEBUG
 #error "Driver uses assert() statements with side-effects; MUST NOT define 
NDEBUG"
@@ -360,21 +204,6 @@
 #define STATIC static
 #endif
 
-struct mveth_private;
-
-/* Clear multicast filters                        */
-void
-BSP_mve_mcast_filter_clear(struct mveth_private *mp);
-void
-BSP_mve_mcast_filter_accept_all(struct mveth_private *mp);
-void
-BSP_mve_mcast_filter_accept_add(struct mveth_private *mp, unsigned char 
*enaddr);
-void
-BSP_mve_mcast_filter_accept_del(struct mveth_private *mp, unsigned char 
*enaddr);
-/* Stop hardware and clean out the rings */
-void
-BSP_mve_stop_hw(struct mveth_private *mp);
-
 struct mveth_private *
 BSP_mve_setup(
        int              unit,
@@ -389,99 +218,6 @@ BSP_mve_setup(
        int             irq_mask
 );
 
-struct mveth_private *
-BSP_mve_setup_1(
-       int              unit,
-       void     (*isr)(void *isr_arg),
-       void     *isr_arg,
-       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
-       void *cleanup_txbuf_arg,
-       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
-       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
-       void *consume_rxbuf_arg,
-       int             rx_ring_size,
-       int             tx_ring_size,
-       int             irq_mask
-);
-
-/* MAIN RX-TX ROUTINES
- *
- * BSP_mve_swipe_tx():  descriptor scavenger; releases mbufs
- * BSP_mve_send_buf():  xfer mbufs from IF to chip
- * BSP_mve_swipe_rx():  enqueue received mbufs to interface
- *                    allocate new ones and yield them to the
- *                    chip.
- */
-
-/* clean up the TX ring freeing up buffers */
-int
-BSP_mve_swipe_tx(struct mveth_private *mp);
-int
-BSP_mve_send_buf_raw(
-       struct mveth_private *mp,
-       void                 *head_p,
-       int                   h_len,
-       void                 *data_p,
-    int                   d_len);
-/* send received buffers upwards and replace them
- * with freshly allocated ones;
- * ASSUMPTION: buffer length NEVER changes and is set
- *                             when the ring is initialized.
- * TS 20060727: not sure if this assumption is still necessary - I believe it 
isn't.
- */
-int
-BSP_mve_swipe_rx(struct mveth_private *mp);
-
-rtems_id
-BSP_mve_get_tid(struct mveth_private *mp);
-int
-BSP_mve_detach(struct mveth_private *mp);
-
-/* Fire up the low-level driver
- *
- * - make sure hardware is halted
- * - enable cache snooping
- * - clear address filters
- * - clear mib counters
- * - reset phy
- * - initialize (or reinitialize) descriptor rings
- * - check that the firmware has set up a reasonable mac address.
- * - generate unicast filter entry for our mac address
- * - write register config values to the chip
- * - start hardware (serial port and SDMA)
- */
-
-void
-BSP_mve_init_hw(struct mveth_private *mp, int promisc, unsigned char *enaddr);
-
-/* read ethernet address from hw to buffer */
-void
-BSP_mve_read_eaddr(struct mveth_private *mp, unsigned char *oeaddr);
-
-void
-BSP_mve_enable_irqs(struct mveth_private *mp);
-void
-BSP_mve_disable_irqs(struct mveth_private *mp);
-uint32_t
-BSP_mve_ack_irqs(struct mveth_private *mp);
-void
-BSP_mve_enable_irq_mask(struct mveth_private *mp, uint32_t mask);
-uint32_t
-BSP_mve_disable_irq_mask(struct mveth_private *mp, uint32_t mask);
-uint32_t
-BSP_mve_ack_irq_mask(struct mveth_private *mp, uint32_t mask);
-
-void
-BSP_mve_dump_stats(struct mveth_private *mp, FILE *f);
-
-unsigned
-mveth_mii_read(struct mveth_private *mp, unsigned addr);
-
-unsigned
-mveth_mii_write(struct mveth_private *mp, unsigned addr, unsigned v);
-
-
-
 #define TX_AVAILABLE_RING_SIZE(mp)             ((mp)->xbuf_count - 
(TX_NUM_TAG_SLOTS))
 
 /* macros for ring alignment; proper alignment is a hardware req; . */
@@ -805,120 +541,15 @@ mveth_mii_write(struct mveth_private *mp, unsigned addr, 
unsigned v);
  */
 typedef uint32_t Dma_addr_t;
 
-typedef volatile struct mveth_rx_desc {
-#ifndef __BIG_ENDIAN__
-#error "descriptor declaration not implemented for little endian machines"
-#endif
-       uint16_t        byte_cnt;
-       uint16_t        buf_size;
-       uint32_t        cmd_sts;                                        /* 
control and status */
-       Dma_addr_t      next_desc_ptr;                          /* next 
descriptor (as seen from DMA) */
-       Dma_addr_t      buf_ptr;
-       /* fields below here are not used by the chip */
-       void            *u_buf;                                         /* user 
buffer */
-       volatile struct mveth_rx_desc *next;    /* next descriptor (CPU 
address; next_desc_ptr is a DMA address) */
-       uint32_t        pad[2];
-} __attribute__(( aligned(RING_ALIGNMENT) )) MvEthRxDescRec, *MvEthRxDesc;
-
-typedef volatile struct mveth_tx_desc {
-#ifndef __BIG_ENDIAN__
-#error "descriptor declaration not implemented for little endian machines"
-#endif
-       uint16_t        byte_cnt;
-       uint16_t        l4i_chk;
-       uint32_t        cmd_sts;                                        /* 
control and status */
-       Dma_addr_t      next_desc_ptr;                          /* next 
descriptor (as seen from DMA) */
-       Dma_addr_t      buf_ptr;
-       /* fields below here are not used by the chip */
-       uint32_t        workaround[2];                          /* use this 
space to work around the 8byte problem (is this real?) */
-       void            *u_buf;                                         /* user 
buffer */
-       volatile struct mveth_tx_desc *next;    /* next descriptor (CPU 
address; next_desc_ptr is a DMA address)   */
-} __attribute__(( aligned(RING_ALIGNMENT) )) MvEthTxDescRec, *MvEthTxDesc;
-
-/* Assume there are never more then 64k aliasing entries */
-typedef uint16_t Mc_Refcnt[MV643XX_ETH_NUM_MCAST_ENTRIES*4];
-
-/* driver private data and bsdnet interface structure */
-struct mveth_private {
-       MvEthRxDesc             rx_ring;                                        
/* pointers to aligned ring area             */
-       MvEthTxDesc             tx_ring;                                        
/* pointers to aligned ring area             */
-       MvEthRxDesc             ring_area;                                      
/* allocated ring area                       */
-       int                             rbuf_count, xbuf_count;         /* 
saved ring sizes from ifconfig            */
-       int                             port_num;
-       int                             phy;
-       MvEthRxDesc             d_rx_t;                                         
/* tail of the RX ring; next received packet */
-       MvEthTxDesc             d_tx_t, d_tx_h;                         
-       uint32_t                rx_desc_dma, tx_desc_dma;       /* ring address 
as seen by DMA; (1:1 on this BSP) */
-       int                             avail;
-       void            (*isr)(void*);
-       void            *isr_arg;
-       /* Callbacks to handle buffers */
-       void                    (*cleanup_txbuf)(void*, void*, int);    /* 
callback to cleanup TX buffer */
-       void                    *cleanup_txbuf_arg;
-       void                    *(*alloc_rxbuf)(int *psize, uintptr_t *paddr);  
/* allocate RX buffer  */
-       void                    (*consume_rxbuf)(void*, void*,  int);   /* 
callback to consume RX buffer */
-       void                    *consume_rxbuf_arg;
-       rtems_id        tid;
-       uint32_t                irq_mask;                                       
/* IRQs we use                              */
-       uint32_t                xirq_mask;
-    int             promisc;
-       struct          {
-               unsigned                irqs;
-               unsigned                maxchain;
-               unsigned                repack;
-               unsigned                packet;
-               unsigned                odrops;                                 
/* no counter in core code                   */
-               struct {
-                       uint64_t        good_octs_rcvd;         /* 64-bit */
-                       uint32_t        bad_octs_rcvd;
-                       uint32_t        internal_mac_tx_err;
-                       uint32_t        good_frames_rcvd;
-                       uint32_t        bad_frames_rcvd;
-                       uint32_t        bcast_frames_rcvd;
-                       uint32_t        mcast_frames_rcvd;
-                       uint32_t        frames_64_octs;
-                       uint32_t        frames_65_127_octs;
-                       uint32_t        frames_128_255_octs;
-                       uint32_t        frames_256_511_octs;
-                       uint32_t        frames_512_1023_octs;
-                       uint32_t        frames_1024_max_octs;
-                       uint64_t        good_octs_sent;         /* 64-bit */
-                       uint32_t        good_frames_sent;
-                       uint32_t        excessive_coll;
-                       uint32_t        mcast_frames_sent;
-                       uint32_t        bcast_frames_sent;
-                       uint32_t        unrec_mac_ctrl_rcvd;
-                       uint32_t        fc_sent;
-                       uint32_t        good_fc_rcvd;
-                       uint32_t        bad_fc_rcvd;
-                       uint32_t        undersize_rcvd;
-                       uint32_t        fragments_rcvd;
-                       uint32_t        oversize_rcvd;
-                       uint32_t        jabber_rcvd;
-                       uint32_t        mac_rx_err;
-                       uint32_t        bad_crc_event;
-                       uint32_t        coll;
-                       uint32_t        late_coll;
-               } mib;
-       }                       stats;
-       struct {
-               Mc_Refcnt       specl, other;
-       }           mc_refcnt;
-};
-
 /* stuff needed for bsdnet support */
-#ifdef BSDBSD
 struct mveth_bsdsupp {
        int                             oif_flags;                              
        /* old / cached if_flags */
 };
-#endif /*BSDBSD*/
 
 struct mveth_softc {
-#ifdef BSDBSD
        struct arpcom                   arpcom;
        struct mveth_bsdsupp    bsd;
-#endif /*BSDBSD*/
-       struct mveth_private    pvt;
+       struct mveth_private    *pvt;
 };
 
 /* GLOBAL VARIABLES */
@@ -926,110 +557,26 @@ struct mveth_softc {
 int mveth_tx_dump = 0;
 #endif
 
-/* THE array of driver/bsdnet structs */
-
-/* If detaching/module unloading is enabled, the main driver data
- * structure must remain in memory; hence it must reside in its own
- * 'dummy' module...
- */
-#ifdef  MVETH_DETACH_HACK
-extern
-#else
-STATIC
-#endif
-struct mveth_softc theMvEths[MV643XXETH_NUM_DRIVER_SLOTS]
-#ifndef MVETH_DETACH_HACK
-= {{{{0}},}}
-#endif
-;
-
-#ifdef BSDBSD
-/* daemon task id */
-STATIC rtems_id        mveth_tid = 0;
-#endif /*BSDBSD*/
-
 /* register access protection mutex */
 STATIC rtems_id mveth_mtx = 0;
+
 #define REGLOCK()      do { \
                if ( RTEMS_SUCCESSFUL != rtems_semaphore_obtain(mveth_mtx, 
RTEMS_WAIT, RTEMS_NO_TIMEOUT) ) \
                        rtems_panic(DRVNAME": unable to lock register 
protection mutex"); \
                } while (0)
 #define REGUNLOCK()    rtems_semaphore_release(mveth_mtx)
 
-/* Format strings for statistics messages */
-static const char *mibfmt[] = {
-       "  GOOD_OCTS_RCVD:      %"PRIu64"\n",
-       0,
-       "  BAD_OCTS_RCVD:       %"PRIu32"\n",
-       "  INTERNAL_MAC_TX_ERR: %"PRIu32"\n",
-       "  GOOD_FRAMES_RCVD:    %"PRIu32"\n",
-       "  BAD_FRAMES_RCVD:     %"PRIu32"\n",
-       "  BCAST_FRAMES_RCVD:   %"PRIu32"\n",
-       "  MCAST_FRAMES_RCVD:   %"PRIu32"\n",
-       "  FRAMES_64_OCTS:      %"PRIu32"\n",
-       "  FRAMES_65_127_OCTS:  %"PRIu32"\n",
-       "  FRAMES_128_255_OCTS: %"PRIu32"\n",
-       "  FRAMES_256_511_OCTS: %"PRIu32"\n",
-       "  FRAMES_512_1023_OCTS:%"PRIu32"\n",
-       "  FRAMES_1024_MAX_OCTS:%"PRIu32"\n",
-       "  GOOD_OCTS_SENT:      %"PRIu64"\n",
-       0,
-       "  GOOD_FRAMES_SENT:    %"PRIu32"\n",
-       "  EXCESSIVE_COLL:      %"PRIu32"\n",
-       "  MCAST_FRAMES_SENT:   %"PRIu32"\n",
-       "  BCAST_FRAMES_SENT:   %"PRIu32"\n",
-       "  UNREC_MAC_CTRL_RCVD: %"PRIu32"\n",
-       "  FC_SENT:             %"PRIu32"\n",
-       "  GOOD_FC_RCVD:        %"PRIu32"\n",
-       "  BAD_FC_RCVD:         %"PRIu32"\n",
-       "  UNDERSIZE_RCVD:      %"PRIu32"\n",
-       "  FRAGMENTS_RCVD:      %"PRIu32"\n",
-       "  OVERSIZE_RCVD:       %"PRIu32"\n",
-       "  JABBER_RCVD:         %"PRIu32"\n",
-       "  MAC_RX_ERR:          %"PRIu32"\n",
-       "  BAD_CRC_EVENT:       %"PRIu32"\n",
-       "  COLL:                %"PRIu32"\n",
-       "  LATE_COLL:           %"PRIu32"\n",
-};
+/* THE array of driver/bsdnet structs */
 
-/* Interrupt Handler Connection */
-
-/* forward decls + implementation for IRQ API funcs */
-
-static void mveth_isr(rtems_irq_hdl_param unit);
-static void mveth_isr_1(rtems_irq_hdl_param unit);
-static void noop(const rtems_irq_connect_data *unused)  {}
-static int  noop1(const rtems_irq_connect_data *unused) { return 0; }
-
-static rtems_irq_connect_data irq_data[MAX_NUM_SLOTS] = {
-       {
-               BSP_IRQ_ETH0,
-               0,
-               (rtems_irq_hdl_param)0,
-               noop,
-               noop,
-               noop1
-       },
-       {
-               BSP_IRQ_ETH1,
-               0,
-               (rtems_irq_hdl_param)1,
-               noop,
-               noop,
-               noop1
-       },
-       {
-               BSP_IRQ_ETH2,
-               0,
-               (rtems_irq_hdl_param)2,
-               noop,
-               noop,
-               noop1
-       },
-};
+STATIC
+struct mveth_softc theMvEths[MV643XXETH_NUM_DRIVER_SLOTS]
+= {{{{0}},}}
+;
+
+/* daemon task id */
+STATIC rtems_id        mveth_tid = 0;
 
 /* MII Ioctl Interface */
-#ifdef BSDMII
 
 /* mdio / mii interface wrappers for rtems_mii_ioctl API */
 
@@ -1038,7 +585,7 @@ static int mveth_mdio_r(int phy, void *uarg, unsigned reg, 
uint32_t *pval)
        if ( phy > 1 )
                return -1;
 
-       *pval = mveth_mii_read(uarg, reg);
+       *pval = BSP_mve_mii_read(uarg, reg);
        return 0;
 }
 
@@ -1046,7 +593,7 @@ static int mveth_mdio_w(int phy, void *uarg, unsigned reg, 
uint32_t val)
 {
        if ( phy > 1 )
                return -1;
-       mveth_mii_write(uarg, reg, val);
+       BSP_mve_mii_write(uarg, reg, val);
        return 0;
 }
 
@@ -1056,1701 +603,252 @@ static struct rtems_mdio_info mveth_mdio = {
        has_gmii: 1,
 };
 
-#endif /* BSDBSD */
-
-/* LOW LEVEL SUPPORT ROUTINES */
-
-/* Software Cache Coherency */
-#ifndef ENABLE_HW_SNOOPING
-#ifndef __PPC__
-#error "Software cache coherency maintenance is not implemented for your CPU 
architecture"
-#endif
-
-static inline unsigned INVAL_DESC(volatile void *d)
-{
-typedef const char cache_line[PPC_CACHE_ALIGNMENT];
-       asm volatile("dcbi 0, %1":"=m"(*(cache_line*)d):"r"(d));
-       return (unsigned)d;     /* so this can be used in comma expression */
-}
-
-static inline void FLUSH_DESC(volatile void *d)
-{
-typedef const char cache_line[PPC_CACHE_ALIGNMENT];
-       asm volatile("dcbf 0, %0"::"r"(d),"m"(*(cache_line*)d));
-}
-
-static inline void FLUSH_BARRIER(void)
-{
-       asm volatile("eieio");
-}
-
-/* RX buffers are always cache-line aligned
- * ASSUMPTIONS:
- *   - 'addr' is cache aligned
- *   -  len   is a multiple >0 of cache lines
- */
-static inline void INVAL_BUF(register uintptr_t addr, register int len)
-{
-typedef char maxbuf[2048]; /* more than an ethernet packet */
-       do {
-               len -= RX_BUF_ALIGNMENT;
-               asm volatile("dcbi %0, %1"::"b"(addr),"r"(len));
-       } while (len > 0);
-       asm volatile("":"=m"(*(maxbuf*)addr));
-}
-
-/* Flushing TX buffers is a little bit trickier; we don't really know their
- * alignment but *assume* adjacent addresses are covering 'ordinary' memory
- * so that flushing them does no harm!
- */
-static inline void FLUSH_BUF(register uintptr_t addr, register int len)
-{
-       asm volatile("":::"memory");
-       len = MV643XX_ALIGN(len, RX_BUF_ALIGNMENT);
-       do { 
-               asm volatile("dcbf %0, %1"::"b"(addr),"r"(len));
-               len -= RX_BUF_ALIGNMENT;
-       } while ( len >= 0 );
-}
-
-#else /* hardware snooping enabled */
-
-/* inline this to silence compiler warnings */
-static inline int INVAL_DESC(volatile void *d)
-{ return 0; }
-
-#define FLUSH_DESC(d)  NOOP()
-#define INVAL_BUF(b,l) NOOP()
-#define FLUSH_BUF(b,l) NOOP()
-#define FLUSH_BARRIER()        NOOP()
-
-#endif /* cache coherency support */
-
-/* Synchronize memory access */
-#ifdef __PPC__
-static inline void membarrier(void)
-{
-       asm volatile("sync":::"memory");
-}
-#else
-#error "memory barrier instruction not defined (yet) for this CPU"
-#endif
-
-/* Enable and disable interrupts at the device */
-static inline void
-mveth_enable_irqs(struct mveth_private *mp, uint32_t mask)
-{
-rtems_interrupt_level l;
-uint32_t val;
-       rtems_interrupt_disable(l);
-
-       val  = MV_READ(MV643XX_ETH_INTERRUPT_ENBL_R(mp->port_num));
-       val  = (val | mask | MV643XX_ETH_IRQ_EXT_ENA) & mp->irq_mask;
-
-       MV_WRITE(MV643XX_ETH_INTERRUPT_ENBL_R(mp->port_num),        val);
-
-       val  = MV_READ(MV643XX_ETH_INTERRUPT_EXTEND_ENBL_R(mp->port_num));
-       val  = (val | mask) & mp->xirq_mask;
-       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_ENBL_R(mp->port_num), val);
-
-       rtems_interrupt_enable(l);
-}
-
-static inline uint32_t
-mveth_disable_irqs(struct mveth_private *mp, uint32_t mask)
-{
-rtems_interrupt_level l;
-uint32_t val,xval,tmp;
-       rtems_interrupt_disable(l);
-
-       val  = MV_READ(MV643XX_ETH_INTERRUPT_ENBL_R(mp->port_num));
-       tmp  = ( (val & ~mask) | MV643XX_ETH_IRQ_EXT_ENA ) & mp->irq_mask;
-       MV_WRITE(MV643XX_ETH_INTERRUPT_ENBL_R(mp->port_num),        tmp);
-
-       xval = MV_READ(MV643XX_ETH_INTERRUPT_EXTEND_ENBL_R(mp->port_num));
-       tmp  = (xval & ~mask) & mp->xirq_mask;
-       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_ENBL_R(mp->port_num), tmp);
-
-       rtems_interrupt_enable(l);
-
-       return (val | xval);
-}
-
-/* This should be safe even w/o turning off interrupts if multiple
- * threads ack different bits in the cause register (and ignore
- * other ones) since writing 'ones' into the cause register doesn't
- * 'stick'.
- */
-
-static inline uint32_t
-mveth_ack_irqs(struct mveth_private *mp, uint32_t mask)
-{
-register uint32_t x,xe,p;
-
-               p  = mp->port_num;
-               /* Get cause */
-               x  = MV_READ(MV643XX_ETH_INTERRUPT_CAUSE_R(p));
-
-               /* Ack interrupts filtering the ones we're interested in */
-
-               /* Note: EXT_IRQ bit clears by itself if EXT interrupts are 
cleared */
-               MV_WRITE(MV643XX_ETH_INTERRUPT_CAUSE_R(p), ~ (x & mp->irq_mask 
& mask));
-
-                               /* linux driver tests 1<<1 as a summary bit for 
extended interrupts;
-                                * the mv64360 seems to use 1<<19 for that 
purpose; for the moment,
-                                * I just check both.
-                                * Update: link status irq (1<<16 in xe) 
doesn't set (1<<19) in x!
-                                */
-               if ( 1 /* x & 2 */ )
-               {
-                       xe = MV_READ(MV643XX_ETH_INTERRUPT_EXTEND_CAUSE_R(p));
-
-                       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_CAUSE_R(p), ~ (xe 
& mp->xirq_mask & mask));
-               } else {
-                       xe = 0;
-               }
-#ifdef MVETH_TESTING
-               if (    ((x & MV643XX_ETH_ALL_IRQS) & ~MV643XX_ETH_KNOWN_IRQS)
-                        || ((xe & MV643XX_ETH_ALL_EXT_IRQS) & 
~MV643XX_ETH_KNOWN_EXT_IRQS) ) {
-                       fprintf(stderr, "Unknown IRQs detected; leaving all 
disabled for debugging:\n");
-                       fprintf(stderr, "Cause reg was 0x%08x, ext cause 
0x%08x\n", x, xe);
-                       mp->irq_mask  = 0;
-                       mp->xirq_mask = 0;
-               }
-#endif
-               /* luckily, the extended and 'normal' interrupts we use don't 
overlap so
-                * we can just OR them into a single word
-                */
-               return  (xe & mp->xirq_mask) | (x & mp->irq_mask);
-}
-
-static void mveth_isr(rtems_irq_hdl_param arg)
-{
-unsigned unit = (unsigned)arg;
-       mveth_disable_irqs(&theMvEths[unit].pvt, -1);
-       theMvEths[unit].pvt.stats.irqs++;
-#ifdef BSDBSD
-#warning FIXME
-       rtems_bsdnet_event_send( theMvEths[unit].pvt.tid, 1<<unit );
-#endif
-}
-
-static void mveth_isr_1(rtems_irq_hdl_param arg)
-{
-unsigned              unit = (unsigned)arg;
-struct mveth_private *mp   = &theMvEths[unit].pvt;
-
-       mp->stats.irqs++;
-       mp->isr(mp->isr_arg);
-}
-
-static void
-mveth_clear_mib_counters(struct mveth_private *mp)
-{
-register int           i;
-register uint32_t      b;
-       /* reading the counters resets them */
-       b = MV643XX_ETH_MIB_COUNTERS(mp->port_num);
-       for (i=0; i< MV643XX_ETH_NUM_MIB_COUNTERS; i++, b+=4)
-               (void)MV_READ(b);
-}
-
-/* Reading a MIB register also clears it. Hence we read the lo
- * register first, then the hi one. Correct reading is guaranteed since
- * the 'lo' register cannot overflow after it is read since it had
- * been reset to 0.
- */
-static unsigned long long
-read_long_mib_counter(int port_num, int idx)
-{
-unsigned long lo;
-unsigned long long hi;
-       lo = MV_READ(MV643XX_ETH_MIB_COUNTERS(port_num)+(idx<<2));
-       idx++;
-       hi = MV_READ(MV643XX_ETH_MIB_COUNTERS(port_num)+(idx<<2));
-       return (hi<<32) | lo;
-}
-
-static inline unsigned long
-read_mib_counter(int port_num, int idx)
-{
-       return MV_READ(MV643XX_ETH_MIB_COUNTERS(port_num)+(idx<<2));
-}
-
-
-/* write ethernet address from buffer to hardware (need to change unicast 
filter after this) */
-static void
-mveth_write_eaddr(struct mveth_private *mp, unsigned char *eaddr)
-{
-int                    i;
-uint32_t       x;
-
-       /* build hi word */
-       for (i=4,x=0; i; i--, eaddr++) {
-               x = (x<<8) | *eaddr;
-       }
-       MV_WRITE(MV643XX_ETH_MAC_ADDR_HI(mp->port_num), x);
-
-       /* build lo word */
-       for (i=2,x=0; i; i--, eaddr++) {
-               x = (x<<8) | *eaddr;
-       }
-       MV_WRITE(MV643XX_ETH_MAC_ADDR_LO(mp->port_num), x);
-}
-
-/* PHY/MII Interface
- *
- * Read/write a PHY register;
- * 
- * NOTE: The SMI register is shared among the three devices.
- *       Protection is provided by the global networking semaphore.
- *       If non-bsd drivers are running on a subset of IFs proper
- *       locking of all shared registers must be implemented!
- */
-unsigned
-mveth_mii_read(struct mveth_private *mp, unsigned addr)
-{
-unsigned v;
-unsigned wc = 0;
-
-       addr  &= 0x1f;
-
-       /* wait until not busy */
-       do {
-               v = MV_READ(MV643XX_ETH_SMI_R);
-               wc++;
-       } while ( MV643XX_ETH_SMI_BUSY & v );
-
-       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (mp->phy<<16) | 
MV643XX_ETH_SMI_OP_RD );
-
-       do {
-               v = MV_READ(MV643XX_ETH_SMI_R);
-               wc++;
-       } while ( MV643XX_ETH_SMI_BUSY & v );
-
-       if (wc>0xffff)
-               wc = 0xffff;
-       return (wc<<16) | (v & 0xffff);
-}
-
-unsigned
-mveth_mii_write(struct mveth_private *mp, unsigned addr, unsigned v)
-{
-unsigned wc = 0;
-
-       addr  &= 0x1f;
-       v     &= 0xffff;
-
-       /* busywait is ugly but not preventing ISRs or high priority tasks from
-        * preempting us
-        */
-
-       /* wait until not busy */
-       while ( MV643XX_ETH_SMI_BUSY & MV_READ(MV643XX_ETH_SMI_R) )
-               wc++ /* wait */;
-
-       MV_WRITE(MV643XX_ETH_SMI_R, (addr <<21 ) | (mp->phy<<16) | 
MV643XX_ETH_SMI_OP_WR | v );
-
-       return wc;
-}
-
-/* MID-LAYER SUPPORT ROUTINES */
-
-/* Start TX if descriptors are exhausted */
-static __inline__ void
-mveth_start_tx(struct mveth_private *mp)
-{
-uint32_t running;
-       if ( mp->avail <= 0 ) {
-               running = 
MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num));
-               if ( ! (running & MV643XX_ETH_TX_START(0)) ) {
-                       
MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
-               }
-       }
-}
-
-/* Stop TX and wait for the command queues to stop and the fifo to drain */
-static uint32_t
-mveth_stop_tx(int port)
-{
-uint32_t active_q;
-
-       active_q = (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(port)) & 
MV643XX_ETH_TX_ANY_RUNNING);
-
-       if ( active_q ) {
-               /* Halt TX and wait for activity to stop */
-               MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(port), 
MV643XX_ETH_TX_STOP_ALL);
-               while ( MV643XX_ETH_TX_ANY_RUNNING & 
MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(port)) )
-                       /* poll-wait */;
-               /* Wait for Tx FIFO to drain */
-               while ( ! (MV643XX_ETH_PORT_STATUS_R(port) & 
MV643XX_ETH_PORT_STATUS_TX_FIFO_EMPTY) )
-                       /* poll-wait */;
-       }
-
-       return active_q;
-}
-
-/* update serial port settings from current link status */
-#ifdef BSDMII
-static void
-mveth_update_serial_port(struct mveth_private *mp, int media)
+static struct mveth_private *
+mve_setup_bsd(
+       int              unit,
+       rtems_id tid,
+       void     (*isr)(void *isr_arg),
+       void     *isr_arg,
+       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
+       void *cleanup_txbuf_arg,
+       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
+       void *consume_rxbuf_arg,
+       int             rx_ring_size,
+       int             tx_ring_size,
+       int             irq_mask
+)
 {
-int port = mp->port_num;
-uint32_t old, new;
-
-       new = old = MV_READ(MV643XX_ETH_SERIAL_CONTROL_R(port));
-
-       /* mask speed and duplex settings */
-       new &= ~(  MV643XX_ETH_SET_GMII_SPEED_1000
-                        | MV643XX_ETH_SET_MII_SPEED_100
-                        | MV643XX_ETH_SET_FULL_DUPLEX );
-
-       if ( IFM_FDX & media )
-               new |= MV643XX_ETH_SET_FULL_DUPLEX;
-
-       switch ( IFM_SUBTYPE(media) ) {
-               default: /* treat as 10 */
-                       break;
-               case IFM_100_TX:
-                       new |= MV643XX_ETH_SET_MII_SPEED_100;
-                       break;
-               case IFM_1000_T:
-                       new |= MV643XX_ETH_SET_GMII_SPEED_1000;
-                       break;
-       }
-
-
-       if ( new != old ) {
-               if ( ! (MV643XX_ETH_SERIAL_PORT_ENBL & new) ) {
-                       /* just write */
-                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
-               } else {
-                       uint32_t were_running;
-
-                       were_running = mveth_stop_tx(port);
-
-                       old &= ~MV643XX_ETH_SERIAL_PORT_ENBL;
-                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), old);
-                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
-                       /* linux driver writes twice... */
-                       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(port), new);
-
-                       if ( were_running ) {
-                               
MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
-                       }
-               }
-       }
-}
-#endif /*BSDMII*/
-
-
-void
-BSP_mve_mcast_filter_clear(struct mveth_private *mp)
-{
-int                 i;
-register uint32_t      s,o;
-uint32_t            v = mp->promisc ? 0x01010101 : 0x00000000;
-       s = MV643XX_ETH_DA_FILTER_SPECL_MCAST_TBL(mp->port_num);
-       o = MV643XX_ETH_DA_FILTER_OTHER_MCAST_TBL(mp->port_num);
-       for (i=0; i<MV643XX_ETH_NUM_MCAST_ENTRIES; i++) {
-               MV_WRITE(s,v);
-               MV_WRITE(o,v);
-               s+=4;
-               o+=4;
-       }
-       for (i=0; i<sizeof(mp->mc_refcnt.specl)/sizeof(mp->mc_refcnt.specl[0]); 
i++) {
-               mp->mc_refcnt.specl[i] = 0;
-               mp->mc_refcnt.other[i] = 0;
-       }
-}
-
-void
-BSP_mve_mcast_filter_accept_all(struct mveth_private *mp)
-{
-int                 i;
-register uint32_t      s,o;
-       s = MV643XX_ETH_DA_FILTER_SPECL_MCAST_TBL(mp->port_num);
-       o = MV643XX_ETH_DA_FILTER_OTHER_MCAST_TBL(mp->port_num);
-       for (i=0; i<MV643XX_ETH_NUM_MCAST_ENTRIES; i++) {
-               MV_WRITE(s,0x01010101);
-               MV_WRITE(o,0x01010101);
-               s+=4;
-               o+=4;
-               /* Not clear what we should do with the reference count.
-                * For now just increment it.
-                */
-               for (i=0; 
i<sizeof(mp->mc_refcnt.specl)/sizeof(mp->mc_refcnt.specl[0]); i++) {
-                       mp->mc_refcnt.specl[i]++;
-                       mp->mc_refcnt.other[i]++;
-               }
-       }
-}
-
-static void add_entry(uint32_t off, uint8_t hash, Mc_Refcnt *refcnt)
-{
-uint32_t val;
-uint32_t slot = hash & 0xfc;
-
-       if ( 0 == (*refcnt)[hash]++ ) {
-               val = MV_READ(off+slot) | ( 1 << ((hash&3)<<3) );
-               MV_WRITE(off+slot, val);
-       }
-}
-
-static void del_entry(uint32_t off, uint8_t hash, Mc_Refcnt *refcnt)
-{
-uint32_t val;
-uint32_t slot = hash & 0xfc;
-
-       if ( (*refcnt)[hash] > 0 && 0 == --(*refcnt)[hash] ) {
-               val = MV_READ(off+slot) & ~( 1 << ((hash&3)<<3) );
-               MV_WRITE(off+slot, val);
-       }
-}
-
-void
-BSP_mve_mcast_filter_accept_add(struct mveth_private *mp, unsigned char 
*enaddr)
-{
-uint32_t   hash;
-static const char spec[]={0x01,0x00,0x5e,0x00,0x00};
-static const char bcst[]={0xff,0xff,0xff,0xff,0xff,0xff};
-uint32_t   tabl;
-Mc_Refcnt  *refcnt;
-
-       if ( ! (0x01 & enaddr[0]) ) {
-               /* not a multicast address; ignore */
-               return;
-       }
-
-       if ( 0 == memcmp(enaddr, bcst, sizeof(bcst)) ) {
-               /* broadcast address; ignore */
-               return;
-       }
-
-       if ( 0 == memcmp(enaddr, spec, sizeof(spec)) ) {
-               hash   = enaddr[5];
-               tabl   = MV643XX_ETH_DA_FILTER_SPECL_MCAST_TBL(mp->port_num);
-               refcnt = &mp->mc_refcnt.specl;
-       } else {
-               uint32_t test, mask;
-               int      i;
-               /* algorithm used by linux driver */
-               for ( hash=0, i=0; i<6; i++ ) {
-                       hash = (hash ^ enaddr[i]) << 8;
-                       for ( test=0x8000, mask=0x8380; test>0x0080; test>>=1, 
mask>>=1 ) {
-                               if ( hash & test )
-                                       hash ^= mask;
-                       }
-               }
-               tabl   = MV643XX_ETH_DA_FILTER_OTHER_MCAST_TBL(mp->port_num);
-               refcnt = &mp->mc_refcnt.other;
-       }
-       add_entry(tabl, hash, refcnt);
-}
-
-void
-BSP_mve_mcast_filter_accept_del(struct mveth_private *mp, unsigned char 
*enaddr)
-{
-uint32_t   hash;
-static const char spec[]={0x01,0x00,0x5e,0x00,0x00};
-static const char bcst[]={0xff,0xff,0xff,0xff,0xff,0xff};
-uint32_t   tabl;
-Mc_Refcnt  *refcnt;
-
-       if ( ! (0x01 & enaddr[0]) ) {
-               /* not a multicast address; ignore */
-               return;
-       }
-
-       if ( 0 == memcmp(enaddr, bcst, sizeof(bcst)) ) {
-               /* broadcast address; ignore */
-               return;
-       }
-
-       if ( 0 == memcmp(enaddr, spec, sizeof(spec)) ) {
-               hash   = enaddr[5];
-               tabl   = MV643XX_ETH_DA_FILTER_SPECL_MCAST_TBL(mp->port_num);
-               refcnt = &mp->mc_refcnt.specl;
-       } else {
-               uint32_t test, mask;
-               int      i;
-               /* algorithm used by linux driver */
-               for ( hash=0, i=0; i<6; i++ ) {
-                       hash = (hash ^ enaddr[i]) << 8;
-                       for ( test=0x8000, mask=0x8380; test>0x0080; test>>=1, 
mask>>=1 ) {
-                               if ( hash & test )
-                                       hash ^= mask;
-                       }
-               }
-               tabl   = MV643XX_ETH_DA_FILTER_OTHER_MCAST_TBL(mp->port_num);
-               refcnt = &mp->mc_refcnt.other;
-       }
-       del_entry(tabl, hash, refcnt);
-}
-
-/* Clear all address filters (multi- and unicast) */
-static void
-mveth_clear_addr_filters(struct mveth_private *mp)
-{
-register int      i;
-register uint32_t u;
-       u = MV643XX_ETH_DA_FILTER_UNICAST_TBL(mp->port_num);
-       for (i=0; i<MV643XX_ETH_NUM_UNICAST_ENTRIES; i++) {
-               MV_WRITE(u,0);
-               u+=4;
-       }
-       BSP_mve_mcast_filter_clear(mp);
-}
-
-/* Setup unicast filter for a given MAC address (least significant nibble) */
-static void
-mveth_ucfilter(struct mveth_private *mp, unsigned char mac_lsbyte, int accept)
-{
-unsigned nib, slot, bit;
-uint32_t       val;
-       /* compute slot in table */
-       nib  = mac_lsbyte & 0xf;        /* strip nibble     */
-       slot = nib & ~3;                        /* (nibble/4)*4     */
-       bit  = (nib &  3)<<3;           /*  8*(nibble % 4)  */
-       val = MV_READ(MV643XX_ETH_DA_FILTER_UNICAST_TBL(mp->port_num) + slot);
-       if ( accept ) {
-               val |= 0x01 << bit;
-       } else {
-               val &= 0x0e << bit;
-       }
-       MV_WRITE(MV643XX_ETH_DA_FILTER_UNICAST_TBL(mp->port_num) + slot, val);
-}
-
-#if defined( ENABLE_TX_WORKAROUND_8_BYTE_PROBLEM ) && 0
-/* Currently unused; small unaligned buffers seem to be rare
- * so we just use memcpy()...
- */
-
-/* memcpy for 0..7 bytes; arranged so that gcc
- * optimizes for powerpc...
- */
-
-static inline void memcpy8(void *to, void *fr, unsigned x)
-{
-register uint8_t *d = to, *s = fro;
-
-       d+=l; s+=l;
-       if ( l & 1 ) {
-               *--d=*--s;
-       }
-       if ( l & 2 ) {
-               /* pre-decrementing causes gcc to use auto-decrementing
-                * PPC instructions (lhzu rx, -2(ry))
-                */
-               d-=2; s-=2;
-               /* use memcpy; don't cast to short -- accessing
-                * misaligned data as short is not portable
-                * (but it works on PPC).
-                */
-               __builtin_memcpy(d,s,2);
-       }
-       if ( l & 4 ) {
-               d-=4; s-=4;
-               /* see above */
-               __builtin_memcpy(d,s,4);
-       }
-}
-#endif
-
-#ifdef BSDBSD
-/* Assign values (buffer + user data) to a tx descriptor slot */
-static int
-mveth_assign_desc(MvEthTxDesc d, struct mbuf *m, unsigned long extra)
-{
-int rval = (d->byte_cnt = m->m_len);
-
-#ifdef MVETH_TESTING
-       assert( !d->mb      );
-       assert(  m->m_len   );
-#endif
-
-       /* set CRC on all descriptors; seems to be necessary */
-       d->cmd_sts  = extra | (TDESC_GEN_CRC | TDESC_ZERO_PAD);
-
-#ifdef ENABLE_TX_WORKAROUND_8_BYTE_PROBLEM
-       /* The buffer must be 64bit aligned if the payload is <8 (??) */
-       if ( rval < 8 && ((mtod(m, uintptr_t)) & 7) ) {
-               d->buf_ptr = CPUADDR2ENET( d->workaround );
-               memcpy((void*)d->workaround, mtod(m, void*), rval);
-       } else
-#endif
-       {
-               d->buf_ptr  = CPUADDR2ENET( mtod(m, unsigned long) );
-       }
-       d->l4i_chk  = 0;
-       return rval;
-}
-#endif /*BSDBSD*/
-
-static int
-mveth_assign_desc_raw(MvEthTxDesc d, void *buf, int len, unsigned long extra)
-{
-int rval = (d->byte_cnt = len);
-
-#ifdef MVETH_TESTING
-       assert( !d->u_buf );
-       assert(  len   );
-#endif
-
-       /* set CRC on all descriptors; seems to be necessary */
-       d->cmd_sts  = extra | (TDESC_GEN_CRC | TDESC_ZERO_PAD);
-
-#ifdef ENABLE_TX_WORKAROUND_8_BYTE_PROBLEM
-       /* The buffer must be 64bit aligned if the payload is <8 (??) */
-       if ( rval < 8 && ( ((uintptr_t)buf) & 7) ) {
-               d->buf_ptr = CPUADDR2ENET( d->workaround );
-               memcpy((void*)d->workaround, buf, rval);
-       } else
-#endif
-       {
-               d->buf_ptr  = CPUADDR2ENET( (unsigned long)buf );
-       }
-       d->l4i_chk  = 0;
-       return rval;
-}
-
-/*
- * Ring Initialization
- *
- * ENDIAN ASSUMPTION: DMA engine matches CPU endianness (???)
- *
- * Linux driver discriminates __LITTLE and __BIG endian for re-arranging
- * the u16 fields in the descriptor structs. However, no endian conversion
- * is done on the individual fields (SDMA byte swapping is disabled on LE).
- */
-
-STATIC int
-mveth_init_rx_desc_ring(struct mveth_private *mp)
-{
-int i,sz;
-MvEthRxDesc    d;
-uintptr_t baddr;
-
-       memset((void*)mp->rx_ring, 0, sizeof(*mp->rx_ring)*mp->rbuf_count);
-
-       mp->rx_desc_dma = CPUADDR2ENET(mp->rx_ring);
-
-       for ( i=0, d = mp->rx_ring; i<mp->rbuf_count; i++, d++ ) {
-               d->u_buf = mp->alloc_rxbuf(&sz, &baddr);
-               assert( d->u_buf );
-
-#ifndef ENABLE_HW_SNOOPING
-               /* could reduce the area to max. ethernet packet size */
-               INVAL_BUF(baddr, sz);
-#endif
-
-               d->buf_size = sz;
-               d->byte_cnt = 0;
-               d->cmd_sts  = RDESC_DMA_OWNED | RDESC_INT_ENA;
-               d->next         = mp->rx_ring + (i+1) % mp->rbuf_count;
-
-               d->buf_ptr  = CPUADDR2ENET( baddr );
-               d->next_desc_ptr = CPUADDR2ENET(d->next);
-               FLUSH_DESC(d);
-       }
-       FLUSH_BARRIER();
-
-       mp->d_rx_t = mp->rx_ring;
-
-       /* point the chip to the start of the ring */
-       
MV_WRITE(MV643XX_ETH_RX_Q0_CURRENT_DESC_PTR(mp->port_num),mp->rx_desc_dma);
-
-
-       return i;
-}
-
-STATIC int
-mveth_init_tx_desc_ring(struct mveth_private *mp)
-{
-int i;
-MvEthTxDesc d;
-
-       memset((void*)mp->tx_ring, 0, sizeof(*mp->tx_ring)*mp->xbuf_count);
-
-       /* DMA and CPU live in the same address space (rtems) */
-       mp->tx_desc_dma = CPUADDR2ENET(mp->tx_ring);
-       mp->avail       = TX_AVAILABLE_RING_SIZE(mp);
-
-       for ( i=0, d=mp->tx_ring; i<mp->xbuf_count; i++,d++ ) {
-               d->l4i_chk  = 0;
-               d->byte_cnt = 0;
-               d->cmd_sts  = 0;
-               d->buf_ptr  = 0;
-
-               d->next     = mp->tx_ring + (i+1) % mp->xbuf_count;
-               d->next_desc_ptr = CPUADDR2ENET(d->next);
-               FLUSH_DESC(d);
-       }
-       FLUSH_BARRIER();
-
-       mp->d_tx_h = mp->d_tx_t = mp->tx_ring;
-
-       /* point the chip to the start of the ring */
-       
MV_WRITE(MV643XX_ETH_TX_Q0_CURRENT_DESC_PTR(mp->port_num),mp->tx_desc_dma);
-
-       return i;
-}
-
-/* PUBLIC LOW-LEVEL DRIVER ACCESS */
-
-static struct mveth_private *
-mve_setup_internal(
-       int              unit,
-       rtems_id tid,
-       void     (*isr)(void*isr_arg),
-       void     *isr_arg,
-       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
-       void *cleanup_txbuf_arg,
-       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
-       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
-       void *consume_rxbuf_arg,
-       int             rx_ring_size,
-       int             tx_ring_size,
-       int             irq_mask
-)
-
-{
-struct mveth_private *mp;
-#ifdef BSDBSD
-struct ifnet         *ifp;
-#endif
-int                  InstallISRSuccessful;
-
-       if ( unit <= 0 || unit > MV643XXETH_NUM_DRIVER_SLOTS ) {
-               printk(DRVNAME": Bad unit number %i; must be 1..%i\n", unit, 
MV643XXETH_NUM_DRIVER_SLOTS);
-               return 0;
-       }
-#ifdef BSDBSD
-#warning FIXME
-       ifp = &theMvEths[unit-1].arpcom.ac_if;
-       if ( ifp->if_init ) {
-               if ( ifp->if_init ) {
-                       printk(DRVNAME": instance %i already attached.\n", 
unit);
-                       return 0;
-               }
-       }
-#endif
-
-       if ( rx_ring_size < 0 && tx_ring_size < 0 )
-               return 0;
-
-       if ( MV_64360 != BSP_getDiscoveryVersion(0) ) {
-               printk(DRVNAME": not mv64360 chip\n");
-               return 0;
-       }
-
-       /* lazy init of mutex (non thread-safe! - we assume 1st initialization 
is single-threaded) */
-       if ( ! mveth_mtx ) {
-               rtems_status_code sc;
-               sc = rtems_semaphore_create(
-                               rtems_build_name('m','v','e','X'),
-                               1,
-                               RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | 
RTEMS_INHERIT_PRIORITY | RTEMS_DEFAULT_ATTRIBUTES,
-                               0,
-                               &mveth_mtx);
-               if ( RTEMS_SUCCESSFUL != sc ) {
-                       rtems_error(sc,DRVNAME": creating mutex\n");
-                       rtems_panic("unable to proceed\n");
-               }
-       }
-
-       mp = &theMvEths[unit-1].pvt;
-
-       memset(mp, 0, sizeof(*mp));
-
-       mp->port_num          = unit-1;
-       mp->phy               = (MV_READ(MV643XX_ETH_PHY_ADDR_R) >> 
(5*mp->port_num)) & 0x1f;
-
-       mp->tid               = tid;
-       mp->isr               = isr;
-       mp->isr_arg           = isr_arg;
-
-       mp->cleanup_txbuf     = cleanup_txbuf;
-       mp->cleanup_txbuf_arg = cleanup_txbuf_arg;
-       mp->alloc_rxbuf       = alloc_rxbuf;
-       mp->consume_rxbuf     = consume_rxbuf;
-       mp->consume_rxbuf_arg = consume_rxbuf_arg;
-
-       mp->rbuf_count = rx_ring_size ? rx_ring_size : MV643XX_RX_RING_SIZE;
-       mp->xbuf_count = tx_ring_size ? tx_ring_size : MV643XX_TX_RING_SIZE;
-
-       if ( mp->xbuf_count > 0 )
-               mp->xbuf_count += TX_NUM_TAG_SLOTS;
-
-       if ( mp->rbuf_count < 0 )
-               mp->rbuf_count = 0;
-       if ( mp->xbuf_count < 0 )
-               mp->xbuf_count = 0;
-
-#ifdef BSDBSD
-       /* allocate ring area; add 1 entry -- room for alignment */
-       assert( !mp->ring_area );
-       mp->ring_area = malloc(
-                                                       sizeof(*mp->ring_area) *
-                                                               (mp->rbuf_count 
+ mp->xbuf_count + 1),
-                                                       M_DEVBUF,
-                                                       M_WAIT );
-       assert( mp->ring_area );
-#endif
-
-       BSP_mve_stop_hw(mp);
-
-       if ( irq_mask ) {
-               irq_data[mp->port_num].hdl = tid ? mveth_isr : mveth_isr_1;     
-               InstallISRSuccessful = BSP_install_rtems_irq_handler( 
&irq_data[mp->port_num] );
-               assert( InstallISRSuccessful );
-       }
-
-#ifdef BSDBSD
-#warning fixme
-       /* mark as used */
-       ifp->if_init = (void*)(-1);
-#endif
-
-       if ( rx_ring_size < 0 )
-               irq_mask &= ~ MV643XX_ETH_IRQ_RX_DONE;
-       if ( tx_ring_size < 0 )
-               irq_mask &= ~ MV643XX_ETH_EXT_IRQ_TX_DONE;
-
-       mp->irq_mask = (irq_mask & MV643XX_ETH_IRQ_RX_DONE);
-       if ( (irq_mask &= (MV643XX_ETH_EXT_IRQ_TX_DONE | 
MV643XX_ETH_EXT_IRQ_LINK_CHG)) ) {
-               mp->irq_mask |= MV643XX_ETH_IRQ_EXT_ENA;
-               mp->xirq_mask = irq_mask;
-       } else {
-               mp->xirq_mask = 0;
-       }
-
-       return mp;
-}
-
-struct mveth_private *
-BSP_mve_setup(
-       int              unit,
-       rtems_id tid,
-       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
-       void *cleanup_txbuf_arg,
-       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
-       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
-       void *consume_rxbuf_arg,
-       int             rx_ring_size,
-       int             tx_ring_size,
-       int             irq_mask
-)
-{
-struct ifnet         *ifp;
-struct mveth_private *mp,
+struct ifnet         *ifp;
+struct mveth_private *mp;
 
        if ( unit <= 0 || unit > MV643XXETH_NUM_DRIVER_SLOTS ) {
                printk(DRVNAME": Bad unit number %i; must be 1..%i\n", unit, 
MV643XXETH_NUM_DRIVER_SLOTS);
                return 0;
-       }
-
-       if ( irq_mask && 0 == tid ) {
-               printk(DRVNAME": must supply a TID if irq_msk not zero\n");
-               return 0;       
-       }
-
-       ifp = &theMvEths[unit-1].arpcom.ac_if;
-
-       if ( ifp->if_init ) {
-               if ( ifp->if_init ) {
-                       printk(DRVNAME": instance %i already attached.\n", 
unit);
-                       return 0;
-               }
-       }
-
-       mp  = &theMvEths[unit-1].pvt;
-
-       if ( 0 == mve_setup_internal(
-                               mp,
-                               unit,
-                               tid,
-                               0, 0,
-                               cleanup_txbuf, cleanup_txbuf_arg,
-                               alloc_rxbuf,
-                               consume_rxbuf, consume_rxbuf_arg,
-                               rx_ring_size, tx_ring_size,
-                               irq_mask) ) {
-               return 0;
-       }
-
-       /* mark as used */
-       ifp->if_init = (void*)(-1);
-
-       return mp;
-}
-
-struct mveth_private *
-BSP_mve_setup_1(
-       int              unit,
-       void     (*isr)(void *isr_arg),
-       void     *isr_arg,
-       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
-       void *cleanup_txbuf_arg,
-       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
-       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
-       void *consume_rxbuf_arg,
-       int             rx_ring_size,
-       int             tx_ring_size,
-       int             irq_mask
-)
-{
-       if ( irq_mask && 0 == isr ) {
-               printk(DRVNAME": must supply an ISR if irq_msk not zero\n");
-               return 0;       
-       }
-
-       return mve_setup_internal(
-                               unit,
-                               0,
-                               isr, isr_arg,
-                               cleanup_txbuf, cleanup_txbuf_arg,
-                               alloc_rxbuf,
-                               consume_rxbuf, consume_rxbuf_arg,
-                               rx_ring_size, tx_ring_size,
-                               irq_mask);
-}
-
-rtems_id
-BSP_mve_get_tid(struct mveth_private *mp)
-{
-    return mp->tid;
-}
-
-int
-BSP_mve_detach(struct mveth_private *mp)
-{
-#ifdef BSDBSD
-int unit = mp->port_num;
-#endif
-       BSP_mve_stop_hw(mp);
-       if ( mp->irq_mask || mp->xirq_mask ) {
-               if ( !BSP_remove_rtems_irq_handler( &irq_data[mp->port_num] ) )
-                       return -1;
-       }
-#ifdef BSDBSD
-#warning FIXME
-       free( (void*)mp->ring_area, M_DEVBUF );
-#endif
-       memset(mp, 0, sizeof(*mp));
-       __asm__ __volatile__("":::"memory");
-       /* mark as unused */
-#ifdef BSDBSD
-       theMvEths[unit].arpcom.ac_if.if_init = 0;
-#endif
-       return 0;
-}
-
-/* MAIN RX-TX ROUTINES
- *
- * BSP_mve_swipe_tx():  descriptor scavenger; releases mbufs
- * BSP_mve_send_buf():  xfer mbufs from IF to chip
- * BSP_mve_swipe_rx():  enqueue received mbufs to interface
- *                    allocate new ones and yield them to the
- *                    chip.
- */
-
-/* clean up the TX ring freeing up buffers */
-int
-BSP_mve_swipe_tx(struct mveth_private *mp)
-{
-int                                            rval = 0;
-register MvEthTxDesc   d;
-
-       for ( d = mp->d_tx_t; d->buf_ptr; d = NEXT_TXD(d) ) {
-
-               INVAL_DESC(d);
-
-               if (    (TDESC_DMA_OWNED & d->cmd_sts)
-                        &&     (uint32_t)d == 
MV_READ(MV643XX_ETH_CURRENT_SERVED_TX_DESC(mp->port_num)) )
-                       break;
-
-               /* d->u_buf is only set on the last descriptor in a chain;
-                * we only count errors in the last descriptor;
-                */
-               if ( d->u_buf ) {
-                       mp->cleanup_txbuf(d->u_buf, mp->cleanup_txbuf_arg, 
(d->cmd_sts & TDESC_ERROR) ? 1 : 0);
-                       d->u_buf = 0;
-               }
-
-               d->buf_ptr = 0;
-
-               rval++;
-       }
-       mp->d_tx_t = d;
-       mp->avail += rval;
-
-       return rval;
-}
-
-#ifdef BSDBSD
-
-/* allocate a new cluster and copy an existing chain there;
- * old chain is released...
- */
-static struct mbuf *
-repackage_chain(struct mbuf *m_head)
-{
-struct mbuf *m;
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-
-       if ( !m ) {
-               goto bail;
-       }
-
-       MCLGET(m, M_DONTWAIT);
-
-       if ( !(M_EXT & m->m_flags) ) {
-               m_freem(m);
-               m = 0;
-               goto bail;
-       }
-
-       m_copydata(m_head, 0, MCLBYTES, mtod(m, caddr_t));
-       m->m_pkthdr.len = m->m_len = m_head->m_pkthdr.len;
-
-bail:
-       m_freem(m_head);
-       return m;
-}
-
-/* Enqueue a mbuf chain or a raw data buffer for transmission;
- * RETURN: #bytes sent or -1 if there are not enough descriptors
- *
- * If 'len' is <=0 then 'm_head' is assumed to point to a mbuf chain.
- * OTOH, a raw data packet may be send (non-BSD driver) by pointing
- * m_head to the start of the data and passing 'len' > 0.
- *
- * Comments: software cache-flushing incurs a penalty if the
- *           packet cannot be queued since it is flushed anyways.
- *           The algorithm is slightly more efficient in the normal
- *                      case, though.
- */
-int
-BSP_mve_send_buf(struct mveth_private *mp, void *m_head, void *data_p, int len)
-{
-int                                            rval;
-register MvEthTxDesc   l,d,h;
-register struct mbuf   *m1;
-int                                            nmbs;
-int                                            ismbuf = (len <= 0);
-
-/* Only way to get here is when we discover that the mbuf chain
- * is too long for the tx ring
- */
-startover:
-
-       rval = 0;
-
-#ifdef MVETH_TESTING 
-       assert(m_head);
-#endif
-
-       /* if no descriptor is available; try to wipe the queue */
-       if ( (mp->avail < 1) && MVETH_CLEAN_ON_SEND(mp)<=0 ) {
-               /* Maybe TX is stalled and needs to be restarted */
-               mveth_start_tx(mp);
-               return -1;
-       }
-
-       h = mp->d_tx_h;
-
-#ifdef MVETH_TESTING 
-       assert( !h->buf_ptr );
-       assert( !h->mb      );
-#endif
-
-       if ( ! (m1 = m_head) )
-               return 0;
-
-       if ( ismbuf ) {
-               /* find first mbuf with actual data */
-               while ( 0 == m1->m_len ) {
-                       if ( ! (m1 = m1->m_next) ) {
-                               /* end reached and still no data to send ?? */
-                               m_freem(m_head);
-                               return 0;
-                       }
-               }
-       }
-
-       /* Don't use the first descriptor yet because BSP_mve_swipe_tx()
-        * needs mp->d_tx_h->buf_ptr == NULL as a marker. Hence, we
-        * start with the second mbuf and fill the first descriptor
-        * last.
-        */
-
-       l = h;
-       d = NEXT_TXD(h);
-
-       mp->avail--;
-
-       nmbs = 1;
-       if ( ismbuf ) {
-                       register struct mbuf *m;
-                       for ( m=m1->m_next; m; m=m->m_next ) {
-                                       if ( 0 == m->m_len )
-                                                       continue;       /* skip 
empty mbufs */
-
-                                       nmbs++;
-
-                                       if ( mp->avail < 1 && 
MVETH_CLEAN_ON_SEND(mp)<=0 ) {
-                                                       /* Maybe TX was stalled 
- try to restart */
-                                                       mveth_start_tx(mp);
-
-                                                       /* not enough 
descriptors; cleanup...
-                                                        * the first slot was 
never used, so we start
-                                                        * at mp->d_tx_h->next;
-                                                        */
-                                                       for ( l = NEXT_TXD(h); 
l!=d; l=NEXT_TXD(l) ) {
-#ifdef MVETH_TESTING
-                                                                       assert( 
l->mb == 0 );
-#endif
-                                                                       
l->buf_ptr  = 0;
-                                                                       
l->cmd_sts  = 0;
-                                                                       
mp->avail++;
-                                                       }
-                                                       mp->avail++;
-                                                       if ( nmbs > 
TX_AVAILABLE_RING_SIZE(mp) ) {
-                                                                       /* this 
chain will never fit into the ring */
-                                                                       if ( 
nmbs > mp->stats.maxchain )
-                                                                               
        mp->stats.maxchain = nmbs;
-                                                                       
mp->stats.repack++;
-                                                                       if ( ! 
(m_head = repackage_chain(m_head)) ) {
-                                                                               
        /* no cluster available */
-                                                                               
        mp->stats.odrops++;
-                                                                               
        return 0;
-                                                                       }
-                                                                       goto 
startover;
-                                                       }
-                                                       return -1;
-                                       }
-
-                                       mp->avail--;
-
-#ifdef MVETH_TESTING
-                                       assert( d != h      );
-                                       assert( !d->buf_ptr );
-#endif
-
-                                       /* fill this slot */
-                                       rval += mveth_assign_desc(d, m, 
TDESC_DMA_OWNED);
-
-                                       FLUSH_BUF(mtod(m, uint32_t), m->m_len);
-
-                                       l = d;
-                                       d = NEXT_TXD(d);
-
-                                       FLUSH_DESC(l);
-                       }
-
-               /* fill first slot - don't release to DMA yet */
-               rval += mveth_assign_desc(h, m1, TDESC_FRST);
-
-
-               FLUSH_BUF(mtod(m1, uint32_t), m1->m_len);
-
-       } else {
-               /* fill first slot with raw buffer - don't release to DMA yet */
-               rval += mveth_assign_desc_raw(h, data_p, len, TDESC_FRST);
-
-               FLUSH_BUF( (uint32_t)data_p, len);
-       }
-
-       /* tag last slot; this covers the case where 1st==last */
-       l->cmd_sts      |= TDESC_LAST | TDESC_INT_ENA;
-       /* mbuf goes into last desc */
-       l->u_buf         = m_head;
-
-
-       FLUSH_DESC(l);
-
-       /* Tag end; make sure chip doesn't try to read ahead of here! */
-       l->next->cmd_sts = 0;
-       FLUSH_DESC(l->next);
-
-#ifdef MVETH_DEBUG_TX_DUMP
-       if ( (mveth_tx_dump & (1<<mp->port_num)) ) {
-               int ll,kk;
-               if ( ismbuf ) {
-                       struct mbuf *m;
-                       for ( kk=0, m=m_head; m; m=m->m_next) {
-                               for ( ll=0; ll<m->m_len; ll++ ) {
-                                       printf("%02X ",*(mtod(m,char*) + ll));
-                                       if ( ((++kk)&0xf) == 0 )
-                                               printf("\n");
-                               }
-                       }
-               } else {
-                       for ( ll=0; ll<len; ) {
-                               printf("%02X ",*((char*)data_p + ll));
-                               if ( ((++ll)&0xf) == 0 )
-                                       printf("\n");
-                       }       
-               }
-               printf("\n");
-       }
-#endif
-
-       membarrier();
-
-       /* turn over the whole chain by flipping ownership of the first desc */
-       h->cmd_sts |= TDESC_DMA_OWNED;
-
-       FLUSH_DESC(h);
-
-       membarrier();
-
-       /* notify the device */
-       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
-
-       /* Update softc */
-       mp->stats.packet++;
-       if ( nmbs > mp->stats.maxchain )
-               mp->stats.maxchain = nmbs;
-
-       /* remember new head */
-       mp->d_tx_h = d;
-
-       return rval; /* #bytes sent */
-}
-#endif /* BSDBSD */
-
-int
-BSP_mve_send_buf_raw(
-       struct mveth_private *mp,
-       void                 *head_p,
-       int                   h_len,
-       void                 *data_p,
-    int                   d_len)
-{
-int                                            rval;
-register MvEthTxDesc   l,d,h;
-int                                            needed;
-void                    *frst_buf;
-int                     frst_len;
-
-       rval = 0;
-
-#ifdef MVETH_TESTING 
-       assert(header || data);
-#endif
-
-       needed = head_p && data_p ? 2 : 1;
-
-       /* if no descriptor is available; try to wipe the queue */
-       if (   ( mp->avail < needed )
-        && ( MVETH_CLEAN_ON_SEND(mp) <= 0 || mp->avail < needed ) ) {
-               /* Maybe TX was stalled and needs a restart */
-               mveth_start_tx(mp);
-               return -1;
-       }
-
-       h = mp->d_tx_h;
-
-#ifdef MVETH_TESTING 
-       assert( !h->buf_ptr );
-       assert( !h->mb      );
-#endif
-
-       /* find the 'first' user buffer */
-       if ( (frst_buf = head_p) ) {
-               frst_len = h_len;
-       } else {
-               frst_buf = data_p;
-               frst_len = d_len;
-       }
-
-       /* Don't use the first descriptor yet because BSP_mve_swipe_tx()
-        * needs mp->d_tx_h->buf_ptr == NULL as a marker. Hence, we
-        * start with the second (optional) slot and fill the first
-     * descriptor last.
-        */
-
-       l = h;
-       d = NEXT_TXD(h);
-
-       mp->avail--;
-
-       if ( needed > 1 ) {
-               mp->avail--;
-#ifdef MVETH_TESTING
-               assert( d != h      );
-               assert( !d->buf_ptr );
-#endif
-               rval += mveth_assign_desc_raw(d, data_p, d_len, 
TDESC_DMA_OWNED);
-               FLUSH_BUF( (uint32_t)data_p, d_len );
-               d->u_buf = data_p;
-
-               l = d;
-               d = NEXT_TXD(d);
-
-               FLUSH_DESC(l);
-       }
-
-       /* fill first slot with raw buffer - don't release to DMA yet */
-       rval       += mveth_assign_desc_raw(h, frst_buf, frst_len, TDESC_FRST);
-
-       FLUSH_BUF( (uint32_t)frst_buf, frst_len);
-
-       /* tag last slot; this covers the case where 1st==last */
-       l->cmd_sts |= TDESC_LAST | TDESC_INT_ENA;
-
-       /* first buffer of 'chain' goes into last desc */
-       l->u_buf    = frst_buf;
-
-       FLUSH_DESC(l);
-
-       /* Tag end; make sure chip doesn't try to read ahead of here! */
-       l->next->cmd_sts = 0;
-       FLUSH_DESC(l->next);
-
-       membarrier();
-
-       /* turn over the whole chain by flipping ownership of the first desc */
-       h->cmd_sts |= TDESC_DMA_OWNED;
-
-       FLUSH_DESC(h);
-
-       membarrier();
-
-       /* notify the device */
-       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_TX_START(0));
-
-       /* Update softc */
-       mp->stats.packet++;
-       if ( needed > mp->stats.maxchain )
-               mp->stats.maxchain = needed;
-
-       /* remember new head */
-       mp->d_tx_h = d;
-
-       return rval; /* #bytes sent */
-}
-
-/* send received buffers upwards and replace them
- * with freshly allocated ones;
- * ASSUMPTION: buffer length NEVER changes and is set
- *                             when the ring is initialized.
- * TS 20060727: not sure if this assumption is still necessary - I believe it 
isn't.
- */
-
-int
-BSP_mve_swipe_rx(struct mveth_private *mp)
-{
-int                                            rval = 0, err;
-register MvEthRxDesc   d;
-void                                   *newbuf;
-int                                            sz;
-uintptr_t                              baddr;
-
-       for ( d = mp->d_rx_t; ! (INVAL_DESC(d), (RDESC_DMA_OWNED & 
d->cmd_sts)); d=NEXT_RXD(d) ) {
-
-#ifdef MVETH_TESTING 
-               assert(d->u_buf);
-#endif
-
-               err = (RDESC_ERROR & d->cmd_sts);
-
-               if ( err || !(newbuf = mp->alloc_rxbuf(&sz, &baddr)) ) {
-                       /* drop packet and recycle buffer */
-                       newbuf = d->u_buf;
-                       mp->consume_rxbuf(0, mp->consume_rxbuf_arg, err ? -1 : 
0);
-               } else {
-#ifdef MVETH_TESTING
-                       assert( d->byte_cnt > 0 );
-#endif
-                       mp->consume_rxbuf(d->u_buf, mp->consume_rxbuf_arg, 
d->byte_cnt);
-
-#ifndef ENABLE_HW_SNOOPING
-                       /* could reduce the area to max. ethernet packet size */
-                       INVAL_BUF(baddr, sz);
-#endif
-                       d->u_buf    = newbuf;
-                       d->buf_ptr  = CPUADDR2ENET(baddr);
-                       d->buf_size = sz;
-                       FLUSH_DESC(d);
-               }
-
-               membarrier();
-
-               d->cmd_sts = RDESC_DMA_OWNED | RDESC_INT_ENA;
-
-               FLUSH_DESC(d);
-
-               rval++;
-       }
-       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_RX_START(0));
-       mp->d_rx_t = d;
-       return rval;
-}
-
-/* Stop hardware and clean out the rings */
-void
-BSP_mve_stop_hw(struct mveth_private *mp)
-{
-MvEthTxDesc    d;
-MvEthRxDesc    r;
-int                    i;
-
-       mveth_disable_irqs(mp, -1);
+       }
 
-       mveth_stop_tx(mp->port_num);
+       ifp = &theMvEths[unit-1].arpcom.ac_if;
 
-       /* cleanup TX rings */
-       if (mp->d_tx_t) { /* maybe ring isn't initialized yet */
-               for ( i=0, d=mp->tx_ring; i<mp->xbuf_count; i++, d++ ) {
-                       /* should be safe to clear ownership */
-                       d->cmd_sts &= ~TDESC_DMA_OWNED;
-                       FLUSH_DESC(d);
+       if ( ifp->if_init ) {
+               if ( ifp->if_init ) {
+                       printk(DRVNAME": instance %i already attached.\n", 
unit);
+                       return 0;
                }
-               FLUSH_BARRIER();
+       }
 
-               BSP_mve_swipe_tx(mp);
+       mp  = theMvEths[unit-1].pvt;
 
-#ifdef MVETH_TESTING 
-               assert( mp->d_tx_h == mp->d_tx_t );
-               for ( i=0, d=mp->tx_ring; i<mp->xbuf_count; i++, d++ ) {
-                       assert( !d->buf_ptr );
-               }
-#endif
+       if ( ! (mp = BSP_mve_create(
+                               unit,
+                               tid,
+                               isr, isr_arg,
+                               cleanup_txbuf, cleanup_txbuf_arg,
+                               alloc_rxbuf,
+                               consume_rxbuf, consume_rxbuf_arg,
+                               rx_ring_size, tx_ring_size,
+                               irq_mask)) ) {
+               return 0;
        }
+       theMvEths[unit-1].pvt = mp;
 
-       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_RX_STOP_ALL);
-       while ( MV643XX_ETH_RX_ANY_RUNNING & 
MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_R(mp->port_num)) )
-               /* poll-wait */;
-
-       /* stop serial port */
-       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num),
-               MV_READ(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num))
-               & ~( MV643XX_ETH_SERIAL_PORT_ENBL | 
MV643XX_ETH_FORCE_LINK_FAIL_DISABLE | MV643XX_ETH_FORCE_LINK_PASS)
-               );
-
-       /* clear pending interrupts */
-       MV_WRITE(MV643XX_ETH_INTERRUPT_CAUSE_R(mp->port_num), 0);
-       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_CAUSE_R(mp->port_num), 0);
-
-       /* cleanup RX rings */
-       if ( mp->rx_ring ) {
-               for ( i=0, r=mp->rx_ring; i<mp->rbuf_count; i++, r++ ) {
-                       /* should be OK to clear ownership flag */
-                       r->cmd_sts = 0;
-                       FLUSH_DESC(r);
-                       mp->consume_rxbuf(r->u_buf, mp->consume_rxbuf_arg, 0);
-                       r->u_buf = 0;
+       /* lazy init of mutex (non thread-safe! - we assume 1st initialization 
is single-threaded) */
+       if ( ! mveth_mtx ) {
+               rtems_status_code sc;
+               sc = rtems_semaphore_create(
+                               rtems_build_name('m','v','e','X'),
+                               1,
+                               RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | 
RTEMS_INHERIT_PRIORITY | RTEMS_DEFAULT_ATTRIBUTES,
+                               0,
+                               &mveth_mtx);
+               if ( RTEMS_SUCCESSFUL != sc ) {
+                       rtems_error(sc,DRVNAME": creating mutex\n");
+                       rtems_panic("unable to proceed\n");
                }
-               FLUSH_BARRIER();
        }
 
+       /* mark as used */
+       ifp->if_init = (void*)(-1);
 
+       return mp;
 }
 
-uint32_t mveth_serial_ctrl_config_val = MVETH_SERIAL_CTRL_CONFIG_VAL;
-
-/* Fire up the low-level driver
- *
- * - make sure hardware is halted
- * - enable cache snooping
- * - clear address filters
- * - clear mib counters
- * - reset phy
- * - initialize (or reinitialize) descriptor rings
- * - check that the firmware has set up a reasonable mac address.
- * - generate unicast filter entry for our mac address
- * - write register config values to the chip
- * - start hardware (serial port and SDMA)
- */
-
-void
-BSP_mve_init_hw(struct mveth_private *mp, int promisc, unsigned char *enaddr)
+struct mveth_private *
+BSP_mve_setup(
+       int              unit,
+       rtems_id tid,
+       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
+       void *cleanup_txbuf_arg,
+       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
+       void *consume_rxbuf_arg,
+       int             rx_ring_size,
+       int             tx_ring_size,
+       int             irq_mask
+)
 {
-int                                    i;
-uint32_t                       v;
-static int                     inited = 0;
-
-#ifdef MVETH_DEBUG
-       printk(DRVNAME"%i: Entering BSP_mve_init_hw()\n", mp->port_num+1);
-#endif
-
-       /* since enable/disable IRQ routine only operate on select bitsets
-        * we must make sure everything is masked initially.
-        */
-       MV_WRITE(MV643XX_ETH_INTERRUPT_ENBL_R(mp->port_num),        0);
-       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_ENBL_R(mp->port_num), 0);
-
-       BSP_mve_stop_hw(mp);
-
-       memset(&mp->stats, 0, sizeof(mp->stats));
-
-       mp->promisc = promisc;
-
-       /* MotLoad has cache snooping disabled on the ENET2MEM windows.
-        * Some comments in (linux) indicate that there are errata
-        * which cause problems which would be a real bummer.
-        * We try it anyways...
-        */
-       if ( !inited ) {
-       unsigned long disbl, bar;
-               inited = 1;     /* FIXME: non-thread safe lazy init */
-               disbl = MV_READ(MV643XX_ETH_BAR_ENBL_R);
-                       /* disable all 6 windows */
-                       MV_WRITE(MV643XX_ETH_BAR_ENBL_R, 
MV643XX_ETH_BAR_DISBL_ALL);
-                       /* set WB snooping on enabled bars */
-                       for ( i=0; i<MV643XX_ETH_NUM_BARS*8; i+=8 ) {
-                               if ( (bar = MV_READ(MV643XX_ETH_BAR_0 + i)) && 
MV_READ(MV643XX_ETH_SIZE_R_0 + i) ) {
-#ifdef ENABLE_HW_SNOOPING
-                                       MV_WRITE(MV643XX_ETH_BAR_0 + i, bar | 
MV64360_ENET2MEM_SNOOP_WB);
-#else
-                                       MV_WRITE(MV643XX_ETH_BAR_0 + i, bar & 
~MV64360_ENET2MEM_SNOOP_MSK);
-#endif
-                                       /* read back to flush fifo [linux 
comment] */
-                                       (void)MV_READ(MV643XX_ETH_BAR_0 + i);
-                               }
-                       }
-                       /* restore/re-enable */
-               MV_WRITE(MV643XX_ETH_BAR_ENBL_R, disbl);
+       if ( irq_mask && 0 == tid ) {
+               printk(DRVNAME": must supply a TID if irq_msk not zero\n");
+               return 0;       
        }
 
-       mveth_clear_mib_counters(mp);
-       mveth_clear_addr_filters(mp);
-
-/*     Just leave it alone...
-       reset_phy();
-*/
-
-       if ( mp->rbuf_count > 0 ) {
-               mp->rx_ring = (MvEthRxDesc)MV643XX_ALIGN(mp->ring_area, 
RING_ALIGNMENT);
-               mveth_init_rx_desc_ring(mp);
-       }
+       return mve_setup_bsd(
+                               unit,
+                               tid,
+                               0, 0,
+                               cleanup_txbuf, cleanup_txbuf_arg,
+                               alloc_rxbuf,
+                               consume_rxbuf, consume_rxbuf_arg,
+                               rx_ring_size, tx_ring_size,
+                               irq_mask);
+}
 
-       if ( mp->xbuf_count > 0 ) {
-               mp->tx_ring = (MvEthTxDesc)mp->rx_ring + mp->rbuf_count;
-               mveth_init_tx_desc_ring(mp);
+struct mveth_private *
+BSP_mve_setup_1(
+       int              unit,
+       void     (*isr)(void *isr_arg),
+       void     *isr_arg,
+       void (*cleanup_txbuf)(void *user_buf, void *closure, int 
error_on_tx_occurred), 
+       void *cleanup_txbuf_arg,
+       void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+       void (*consume_rxbuf)(void *user_buf, void *closure, int len),
+       void *consume_rxbuf_arg,
+       int             rx_ring_size,
+       int             tx_ring_size,
+       int             irq_mask
+)
+{
+       if ( irq_mask && 0 == isr ) {
+               printk(DRVNAME": must supply an ISR if irq_msk not zero\n");
+               return 0;       
        }
 
-       if ( enaddr ) {
-               /* set ethernet address from arpcom struct */
-#ifdef MVETH_DEBUG
-               printk(DRVNAME"%i: Writing MAC addr ", mp->port_num+1);
-               for (i=5; i>=0; i--) {
-                       printk("%02X%c", enaddr[i], i?':':'\n');
-               }
-#endif
-               mveth_write_eaddr(mp, enaddr);
-       }
+       return mve_setup_bsd(
+                               unit,
+                               0,
+                               isr, isr_arg,
+                               cleanup_txbuf, cleanup_txbuf_arg,
+                               alloc_rxbuf,
+                               consume_rxbuf, consume_rxbuf_arg,
+                               rx_ring_size, tx_ring_size,
+                               irq_mask);
+}
 
-       /* set mac address and unicast filter */
+/* allocate a new cluster and copy an existing chain there;
+ * old chain is released...
+ */
+static struct mbuf *
+repackage_chain(struct mbuf *m_head)
+{
+struct mbuf *m;
+       MGETHDR(m, M_DONTWAIT, MT_DATA);
 
-       {
-       uint32_t machi, maclo;
-               maclo = MV_READ(MV643XX_ETH_MAC_ADDR_LO(mp->port_num));
-               machi = MV_READ(MV643XX_ETH_MAC_ADDR_HI(mp->port_num));
-               /* ASSUME: firmware has set the mac address for us
-                *         - if assertion fails, we have to do more work...
-                */
-               assert( maclo && machi && maclo != 0xffffffff && machi != 
0xffffffff );
-               mveth_ucfilter(mp, maclo&0xff, 1/* accept */);
-       }
-       
-       /* port, serial and sdma configuration */
-       v = MVETH_PORT_CONFIG_VAL;
-       if ( promisc ) {
-               /* multicast filters were already set up to
-                * accept everything (mveth_clear_addr_filters())
-                */
-               v |= MV643XX_ETH_UNICAST_PROMISC_MODE;
-       } else {
-               v &= ~MV643XX_ETH_UNICAST_PROMISC_MODE;
+       if ( !m ) {
+               goto bail;
        }
-       MV_WRITE(MV643XX_ETH_PORT_CONFIG_R(mp->port_num),
-                               v);
-       MV_WRITE(MV643XX_ETH_PORT_CONFIG_XTEND_R(mp->port_num),
-                               MVETH_PORT_XTEND_CONFIG_VAL);
 
-       v  = MV_READ(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num));
-       v &= ~(MVETH_SERIAL_CTRL_CONFIG_MSK);
-       v |= mveth_serial_ctrl_config_val;
-       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num), v);
+       MCLGET(m, M_DONTWAIT);
 
-#ifdef BSDMII
-#warning FIXME
-       i = IFM_MAKEWORD(0, 0, 0, 0);
-       if ( 0 == BSP_mve_media_ioctl(mp, SIOCGIFMEDIA, &i) ) {
-           if ( (IFM_LINK_OK & i) ) {
-                       mveth_update_serial_port(mp, i);
-               }
+       if ( !(M_EXT & m->m_flags) ) {
+               m_freem(m);
+               m = 0;
+               goto bail;
        }
-#endif
-
-       /* enable serial port */
-       v  = MV_READ(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num));
-       MV_WRITE(MV643XX_ETH_SERIAL_CONTROL_R(mp->port_num),
-                               v | MV643XX_ETH_SERIAL_PORT_ENBL);
 
-#ifndef __BIG_ENDIAN__
-#error "byte swapping needs to be disabled for little endian machines"
-#endif
-       MV_WRITE(MV643XX_ETH_SDMA_CONFIG_R(mp->port_num), 
MVETH_SDMA_CONFIG_VAL);
+       m_copydata(m_head, 0, MCLBYTES, mtod(m, caddr_t));
+       m->m_pkthdr.len = m->m_len = m_head->m_pkthdr.len;
 
-       /* allow short frames */
-       MV_WRITE(MV643XX_ETH_RX_MIN_FRAME_SIZE_R(mp->port_num), 
MVETH_MIN_FRAMSZ_CONFIG_VAL);
+bail:
+       m_freem(m_head);
+       return m;
+}
 
-       MV_WRITE(MV643XX_ETH_INTERRUPT_CAUSE_R(mp->port_num), 0);
-       MV_WRITE(MV643XX_ETH_INTERRUPT_EXTEND_CAUSE_R(mp->port_num), 0);
-       /* TODO: set irq coalescing */
+typedef struct BsdMveIter {
+       MveEthBufIter it;
+       struct mbuf  *m;
+       struct mbuf  *h;
+} BsdMveIter;
 
-       /* enable Rx */
-       if ( mp->rbuf_count > 0 ) {
-               MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_R(mp->port_num), 
MV643XX_ETH_RX_START(0));
+static MveEthBufIter *fillIter(struct mbuf *m, BsdMveIter *it)
+{
+       if ( (it->m = (void*)m) ) {
+               it->it.data = mtod(m, void*);
+               it->it.len  = m->m_len;
+               it->it.uptr = m->m_next ? it->h : 0;
+               return (MveEthBufIter*)it;
        }
+       return 0;
+}
 
-       mveth_enable_irqs(mp, -1);
-
-#ifdef MVETH_DEBUG
-       printk(DRVNAME"%i: Leaving BSP_mve_init_hw()\n", mp->port_num+1);
-#endif
+static MveEthBufIter *nextBuf(const MveEthBufIter *arg)
+{
+BsdMveIter *it = (BsdMveIter*)arg;
+       return fillIter( it->m->m_next, it );
 }
 
-/* read ethernet address from hw to buffer */
-void
-BSP_mve_read_eaddr(struct mveth_private *mp, unsigned char *oeaddr)
+int
+BSP_mve_send_buf(struct mveth_private *mp, void *m_head, void *data_p, int len)
 {
-int                            i;
-uint32_t               x;
-unsigned char  buf[6], *eaddr;
+int                                            rval;
+register struct mbuf   *m1;
+BsdMveIter              iter;
 
-       eaddr = oeaddr ? oeaddr : buf;
+/* Only way to get here is when we discover that the mbuf chain
+ * is too long for the tx ring
+ */
+startover:
 
-       eaddr += 5;
-       x = MV_READ(MV643XX_ETH_MAC_ADDR_LO(mp->port_num));
+       rval = 0;
 
-       /* lo word */
-       for (i=2; i; i--, eaddr--) {
-               *eaddr = (unsigned char)(x & 0xff);
-               x>>=8;
-       }
+#ifdef MVETH_TESTING 
+       assert(m_head);
+#endif
+
+       if ( ! (m1 = m_head) )
+               return 0;
 
-       x = MV_READ(MV643XX_ETH_MAC_ADDR_HI(mp->port_num));
-       /* hi word */
-       for (i=4; i; i--, eaddr--) {
-               *eaddr = (unsigned char)(x & 0xff);
-               x>>=8;
+       /* find first mbuf with actual data */
+       while ( 0 == m1->m_len ) {
+               if ( ! (m1 = m1->m_next) ) {
+                       /* end reached and still no data to send ?? */
+                       m_freem(m_head);
+                       return 0;
+               }
        }
 
-       if ( !oeaddr ) {
-               printf("%02X",buf[0]);
-               for (i=1; i<sizeof(buf); i++)
-                       printf(":%02X",buf[i]);
+#ifdef MVETH_DEBUG_TX_DUMP
+       if ( (mveth_tx_dump & (1<<mp->port_num)) ) {
+               int ll,kk;
+               struct mbuf *m;
+               for ( kk=0, m=m_head; m; m=m->m_next) {
+                       for ( ll=0; ll<m->m_len; ll++ ) {
+                               printf("%02X ",*(mtod(m,char*) + ll));
+                               if ( ((++kk)&0xf) == 0 )
+                                       printf("\n");
+                       }
+               }
                printf("\n");
        }
+#endif
+
+       fillIter( m_head, &iter );
+       iter.h = m_head;
+
+       rval = BSP_mve_send_buf_chain( mp, nextBuf, &iter.it );
+
+       if ( -2 == rval ) {
+               if ( ! (m_head = repackage_chain( m_head )) ) {
+                       /* no cluster available */
+                       /* No access to this counter, unfortunately             
        
+                       mp->stats.odrops++;
+                        */
+                       return 0;
+               }
+               goto startover;
+       }
+
+       return rval;
 }
 
-#ifdef BSDMII
 int
 BSP_mve_media_ioctl(struct mveth_private *mp, int cmd, int *parg)
 {
@@ -2770,46 +868,7 @@ int rval;
        REGUNLOCK();
        return rval;
 }
-#endif
-
-void
-BSP_mve_enable_irqs(struct mveth_private *mp)
-{
-       mveth_enable_irqs(mp, -1);
-}
-
-void
-BSP_mve_disable_irqs(struct mveth_private *mp)
-{
-       mveth_disable_irqs(mp, -1);
-}
-
-uint32_t
-BSP_mve_ack_irqs(struct mveth_private *mp)
-{
-       return mveth_ack_irqs(mp, -1);
-}
-
-
-void
-BSP_mve_enable_irq_mask(struct mveth_private *mp, uint32_t mask)
-{
-       mveth_enable_irqs(mp, mask);
-}
-
-uint32_t
-BSP_mve_disable_irq_mask(struct mveth_private *mp, uint32_t mask)
-{
-       return mveth_disable_irqs(mp, mask);
-}
 
-uint32_t
-BSP_mve_ack_irq_mask(struct mveth_private *mp, uint32_t mask)
-{
-       return mveth_ack_irqs(mp, mask);
-}
-
-#ifdef BSDMII
 int
 BSP_mve_ack_link_chg(struct mveth_private *mp, int *pmedia)
 {
@@ -2817,9 +876,25 @@ int media = IFM_MAKEWORD(0,0,0,0);
 
        if ( 0 == BSP_mve_media_ioctl(mp, SIOCGIFMEDIA, &media)) {
                if ( IFM_LINK_OK & media ) {
-                       mveth_update_serial_port(mp, media);
-                       /* If TX stalled because there was no buffer then whack 
it */
-                       mveth_start_tx(mp);
+                       int serport_cfg = 0;
+
+                       if ( IFM_FDX & media ) {
+                               serport_cfg |= MV643XX_MEDIA_FD;
+                       }
+
+                       switch ( IFM_SUBTYPE(media) ) {
+                               default: /* treat as 10 */
+                                       serport_cfg |= MV643XX_MEDIA_10;
+                                       break;
+                               case IFM_100_TX:
+                                       serport_cfg |= MV643XX_MEDIA_100;
+                                       break;
+                               case IFM_1000_T:
+                                       serport_cfg |= MV643XX_MEDIA_1000;
+                                       break;
+                       }
+
+                       BSP_mve_update_serial_port(mp, serport_cfg);
                }
                if ( pmedia )
                        *pmedia = media;
@@ -2827,9 +902,6 @@ int media = IFM_MAKEWORD(0,0,0,0);
        }
        return -1;
 }
-#endif
-
-#ifdef BSDBSD
 
 /* BSDNET SUPPORT/GLUE ROUTINES */
 
@@ -2839,7 +911,7 @@ mveth_set_filters(struct ifnet *ifp);
 STATIC void
 mveth_stop(struct mveth_softc *sc)
 {
-       BSP_mve_stop_hw(&sc->pvt);
+       BSP_mve_stop_hw(sc->pvt);
        sc->arpcom.ac_if.if_timer = 0;
 }
 
@@ -2938,56 +1010,6 @@ struct mbuf  *mb  = buf;
        ifp->if_obytes += mb->m_pkthdr.len;
        m_freem(mb);
 }
-#endif /*BSDBSD*/
-
-static void
-dump_update_stats(struct mveth_private *mp, FILE *f)
-{
-int      p = mp->port_num;
-int      idx;
-uint32_t v;
-
-       if ( !f )
-               f = stdout;
-
-       fprintf(f, DRVNAME"%i Statistics:\n",        mp->port_num + 1);
-       fprintf(f, "  # IRQS:                 %i\n", mp->stats.irqs);
-       fprintf(f, "  Max. mbuf chain length: %i\n", mp->stats.maxchain);
-       fprintf(f, "  # repacketed:           %i\n", mp->stats.repack);
-       fprintf(f, "  # packets:              %i\n", mp->stats.packet);
-       fprintf(f, "MIB Counters:\n");
-       for ( idx = MV643XX_ETH_MIB_GOOD_OCTS_RCVD_LO>>2;
-                       idx < MV643XX_ETH_NUM_MIB_COUNTERS;
-                       idx++ ) {
-               switch ( idx ) {
-                       case MV643XX_ETH_MIB_GOOD_OCTS_RCVD_LO>>2:
-                               mp->stats.mib.good_octs_rcvd += 
read_long_mib_counter(p, idx);
-                               fprintf(f, mibfmt[idx], 
mp->stats.mib.good_octs_rcvd);
-                               idx++;
-                               break;
-
-                       case MV643XX_ETH_MIB_GOOD_OCTS_SENT_LO>>2:
-                               mp->stats.mib.good_octs_sent += 
read_long_mib_counter(p, idx);
-                               fprintf(f, mibfmt[idx], 
mp->stats.mib.good_octs_sent);
-                               idx++;
-                               break;
-
-                       default:
-                               v = ((uint32_t*)&mp->stats.mib)[idx] += 
read_mib_counter(p, idx);
-                               fprintf(f, mibfmt[idx], v);
-                               break;
-               }
-       }
-       fprintf(f, "\n");
-}
-
-void
-BSP_mve_dump_stats(struct mveth_private *mp, FILE *f)
-{
-       dump_update_stats(mp, f);
-}
-
-#ifdef BSDBSD
 
 /* BSDNET DRIVER CALLBACKS */
 
@@ -2998,10 +1020,10 @@ struct mveth_softc      *sc  = arg;
 struct ifnet           *ifp = &sc->arpcom.ac_if;
 int                 media;
 
-       BSP_mve_init_hw(&sc->pvt, ifp->if_flags & IFF_PROMISC, 
sc->arpcom.ac_enaddr);
+       BSP_mve_init_hw(sc->pvt, ifp->if_flags & IFF_PROMISC, 
sc->arpcom.ac_enaddr);
 
        media = IFM_MAKEWORD(0, 0, 0, 0);
-       if ( 0 == BSP_mve_media_ioctl(&sc->pvt, SIOCGIFMEDIA, &media) ) {
+       if ( 0 == BSP_mve_media_ioctl(sc->pvt, SIOCGIFMEDIA, &media) ) {
            if ( (IFM_LINK_OK & media) ) {
                        ifp->if_flags &= ~IFF_OACTIVE;
                } else {
@@ -3026,7 +1048,7 @@ struct mbuf                       *m  = 0;
 
        while ( ifp->if_snd.ifq_head ) {
                IF_DEQUEUE( &ifp->if_snd, m );
-               if ( BSP_mve_send_buf(&sc->pvt, m, 0, 0) < 0 ) {
+               if ( BSP_mve_send_buf(sc->pvt, m, 0, 0) < 0 ) {
                        IF_PREPEND( &ifp->if_snd, m);
                        ifp->if_flags |= IFF_OACTIVE;
                        break;
@@ -3055,22 +1077,16 @@ static void
 mveth_set_filters(struct ifnet *ifp)
 {
 struct mveth_softc  *sc = ifp->if_softc;
-uint32_t              v;
 
-       v = MV_READ(MV643XX_ETH_PORT_CONFIG_R(sc->pvt.port_num));
-       if ( ifp->if_flags & IFF_PROMISC )
-               v |= MV643XX_ETH_UNICAST_PROMISC_MODE;
-       else
-               v &= ~MV643XX_ETH_UNICAST_PROMISC_MODE;
-       MV_WRITE(MV643XX_ETH_PORT_CONFIG_R(sc->pvt.port_num), v);
+       BSP_mve_promisc_set( sc->pvt, !!(ifp->if_flags & IFF_PROMISC));
 
        if ( ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI) ) {
-               BSP_mve_mcast_filter_accept_all(&sc->pvt);
+               BSP_mve_mcast_filter_accept_all(sc->pvt);
        } else {
                struct ether_multi     *enm;
                struct ether_multistep step;
 
-               BSP_mve_mcast_filter_clear( &sc->pvt );
+               BSP_mve_mcast_filter_clear( sc->pvt );
                
                ETHER_FIRST_MULTI(step, (struct arpcom *)ifp, enm);
 
@@ -3078,7 +1094,7 @@ uint32_t              v;
                        if ( memcmp(enm->enm_addrlo, enm->enm_addrhi, 
ETHER_ADDR_LEN) )
                                assert( !"Should never get here; IFF_ALLMULTI 
should be set!" );
 
-                       BSP_mve_mcast_filter_accept_add(&sc->pvt, 
enm->enm_addrlo);
+                       BSP_mve_mcast_filter_accept_add(sc->pvt, 
enm->enm_addrlo);
 
                        ETHER_NEXT_MULTI(step, enm);
                }
@@ -3102,14 +1118,6 @@ int                                      f;
                                        mveth_init(sc);
                                } else {
                                        if ( (f & IFF_PROMISC) != 
(sc->bsd.oif_flags & IFF_PROMISC) ) {
-                                               /* Note: in all other scenarios 
the 'promisc' flag
-                                                * in the low-level driver 
[which affects the way
-                                                * the multicast filter is 
setup: accept none vs.
-                                                * accept all in promisc mode] 
is eventually
-                                                * set when the IF is brought 
up...
-                                                */
-                                               sc->pvt.promisc = (f & 
IFF_PROMISC);
-
                                                mveth_set_filters(ifp);
                                        }
                                        /* FIXME: other flag changes are 
ignored/unimplemented */
@@ -3125,7 +1133,7 @@ int                                       f;
 
                case SIOCGIFMEDIA:
                case SIOCSIFMEDIA:
-                       error = BSP_mve_media_ioctl(&sc->pvt, cmd, 
&ifr->ifr_media);
+                       error = BSP_mve_media_ioctl(sc->pvt, cmd, 
&ifr->ifr_media);
                break;
  
                case SIOCADDMULTI:
@@ -3146,7 +1154,7 @@ int                                       f;
                break;
 
                case SIO_RTEMS_SHOW_STATS:
-                       dump_update_stats(&sc->pvt, stdout);
+                       BSP_mve_dump_stats(sc->pvt, stdout);
                break;
 
                default:
@@ -3187,13 +1195,13 @@ rtems_event_set         evs;
                                        continue;
                                }
 
-                               x = mveth_ack_irqs(&sc->pvt, -1);
+                               x = BSP_mve_ack_irqs(sc->pvt);
 
                                if ( MV643XX_ETH_EXT_IRQ_LINK_CHG & x ) {
                                        /* phy status changed */
                                        int media;
 
-                                       if ( 0 == 
BSP_mve_ack_link_chg(&sc->pvt, &media) ) {
+                                       if ( 0 == BSP_mve_ack_link_chg(sc->pvt, 
&media) ) {
                                                if ( IFM_LINK_OK & media ) {
                                                        ifp->if_flags &= 
~IFF_OACTIVE;
                                                        mveth_start(ifp);
@@ -3204,26 +1212,24 @@ rtems_event_set         evs;
                                        }
                                }
                                /* free tx chain */
-                               if ( (MV643XX_ETH_EXT_IRQ_TX_DONE & x) && 
BSP_mve_swipe_tx(&sc->pvt) ) {
+                               if ( (MV643XX_ETH_EXT_IRQ_TX_DONE & x) && 
BSP_mve_swipe_tx(sc->pvt) ) {
                                        ifp->if_flags &= ~IFF_OACTIVE;
-                                       if ( TX_AVAILABLE_RING_SIZE(&sc->pvt) 
== sc->pvt.avail )
+#warning FIXME
+#ifdef BSDBSD
+                                       if ( TX_AVAILABLE_RING_SIZE(sc->pvt) == 
sc->pvt->avail )
                                                ifp->if_timer = 0;
+#endif
                                        mveth_start(ifp);
                                }
                                if ( (MV643XX_ETH_IRQ_RX_DONE & x) )
-                                       BSP_mve_swipe_rx(&sc->pvt);
+                                       BSP_mve_swipe_rx(sc->pvt);
 
-                               mveth_enable_irqs(&sc->pvt, -1);
+                               BSP_mve_enable_irqs(sc->pvt);
                        }
                }
        }
 }
 
-#ifdef  MVETH_DETACH_HACK
-static int mveth_detach(struct mveth_softc *sc);
-#endif
-
-
 /* PUBLIC RTEMS BSDNET ATTACH FUNCTION */
 int
 rtems_mve_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching)
@@ -3241,8 +1247,6 @@ struct    ifnet           *ifp;
 
        sc  = &theMvEths[unit-1];
        ifp = &sc->arpcom.ac_if;
-       sc->pvt.port_num = unit-1;
-       sc->pvt.phy      = (MV_READ(MV643XX_ETH_PHY_ADDR_R) >> 
(5*sc->pvt.port_num)) & 0x1f;
 
        if ( attaching ) {
                if ( ifp->if_init ) {
@@ -3275,7 +1279,7 @@ struct    ifnet           *ifp;
                        return -1;
                }
 
-               if ( nmbclusters < sc->pvt.rbuf_count * cfgUnits + 60 /* 
arbitrary */ )  {
+               if ( nmbclusters < ifcfg->rbuf_count * cfgUnits + 60 /* 
arbitrary */ )  {
                        printk(DRVNAME"%i: (mv643xx ethernet) Your application 
has not enough mbuf clusters\n", unit);
                        printk(     "                         configured for 
this driver.\n");
                        return -1;
@@ -3285,7 +1289,7 @@ struct    ifnet           *ifp;
                        memcpy(sc->arpcom.ac_enaddr, ifcfg->hardware_address, 
ETHER_ADDR_LEN);
                } else {
                        /* read back from hardware assuming that MotLoad 
already had set it up */
-                       BSP_mve_read_eaddr(&sc->pvt, sc->arpcom.ac_enaddr);
+                       BSP_mve_read_eaddr(sc->pvt, sc->arpcom.ac_enaddr);
                }
 
                ifp->if_softc                   = sc;
@@ -3318,29 +1322,18 @@ struct  ifnet           *ifp;
 
                /* NOTE: ether_output drops packets if ifq_len >= ifq_maxlen
                 *       but this is the packet count, not the fragment count!
-               ifp->if_snd.ifq_maxlen  = sc->pvt.xbuf_count;
+               ifp->if_snd.ifq_maxlen  = sc->pvt->buf_count;
                */
                ifp->if_snd.ifq_maxlen  = ifqmaxlen;
 
-#ifdef  MVETH_DETACH_HACK
-               if ( !ifp->if_addrlist ) /* do only the first time [reattach 
hack] */
-#endif
                {
                        if_attach(ifp);
                        ether_ifattach(ifp);
                }
 
        } else {
-#ifdef  MVETH_DETACH_HACK
-               if ( !ifp->if_init ) {
-                       printk(DRVNAME": instance %i not attached.\n", unit);
-                       return -1;
-               }
-               return mveth_detach(sc);
-#else
                printk(DRVNAME": interface detaching not implemented\n");
                return -1;
-#endif
        }
 
        return 0;
@@ -3353,8 +1346,6 @@ mveth_early_init(int idx)
        if ( idx < 0 || idx >= MV643XXETH_NUM_DRIVER_SLOTS )
                return -1;
 
-       /* determine the phy */
-       theMvEths[idx].pvt.phy = (MV_READ(MV643XX_ETH_PHY_ADDR_R) >> (5*idx)) & 
0x1f;
        return 0;
 }
 
@@ -3366,7 +1357,7 @@ int rval;
        if ( idx < 0 || idx >= MV643XXETH_NUM_DRIVER_SLOTS )
                return -1;
 
-       rval = mveth_mii_read(&theMvEths[idx].pvt, reg);
+       rval = BSP_mve_mii_read_early(idx, reg);
        return rval < 0 ? rval : rval & 0xffff;
 }
 
@@ -3376,7 +1367,7 @@ mveth_early_write_phy(int idx, unsigned reg, unsigned val)
        if ( idx < 0 || idx >= MV643XXETH_NUM_DRIVER_SLOTS )
                return -1;
 
-       mveth_mii_write(&theMvEths[idx].pvt, reg, val);
+       BSP_mve_mii_write_early(idx, reg, val);
        return 0;
 }
 
@@ -3391,8 +1382,6 @@ rtems_mve_early_link_check_ops = {
 
 /* DEBUGGING */
 
-#endif /*BSDBSD*/
-
 #ifdef MVETH_DEBUG
 /* Display/dump descriptor rings */
 
@@ -3404,7 +1393,7 @@ if (1) {
 MvEthRxDesc pr;
 printf("RX:\n");
 
-       for (i=0, pr=sc->pvt.rx_ring; i<sc->pvt.rbuf_count; i++, pr++) {
+       for (i=0, pr=sc->pvt->rx_ring; i<sc->pvt->rbuf_count; i++, pr++) {
 #ifndef ENABLE_HW_SNOOPING
                /* can't just invalidate the descriptor - if it contains
                 * data that hasn't been flushed yet, we create an 
inconsistency...
@@ -3423,7 +1412,7 @@ printf("RX:\n");
 if (1) {
 MvEthTxDesc pt;
 printf("TX:\n");
-       for (i=0, pt=sc->pvt.tx_ring; i<sc->pvt.xbuf_count; i++, pt++) {
+       for (i=0, pt=sc->pvt->tx_ring; i<sc->pvt->xbuf_count; i++, pt++) {
 #ifndef ENABLE_HW_SNOOPING
                rtems_bsdnet_semaphore_obtain();
                INVAL_DESC(pt);
@@ -3441,79 +1430,3 @@ printf("TX:\n");
 }
 
 #endif
-
-/* DETACH HACK DETAILS */
-
-#ifdef  MVETH_DETACH_HACK
-int
-_cexpModuleFinalize(void *mh)
-{
-int i;
-       for ( i=0; i<MV643XXETH_NUM_DRIVER_SLOTS; i++ ) {
-               if ( theMvEths[i].arpcom.ac_if.if_init ) {
-                       printf("Interface %i still attached; refuse to 
unload\n", i+1);
-                       return -1;
-               }
-       }
-       /* delete task; since there are no attached interfaces, it should block
-        * for events and hence not hold the semaphore or other resources...
-        */
-       rtems_task_delete(mveth_tid);
-       return 0;
-}
-
-/* ugly hack to allow unloading/reloading the driver core.
- * needed because rtems' bsdnet release doesn't implement
- * if_detach(). Therefore, we bring the interface down but
- * keep the device record alive...
- */
-static void
-ether_ifdetach_pvt(struct ifnet *ifp)
-{
-        ifp->if_flags = 0;
-        ifp->if_ioctl = 0;
-        ifp->if_start = 0;
-        ifp->if_watchdog = 0;
-        ifp->if_init  = 0;
-}
-
-static int
-mveth_detach(struct mveth_softc *sc)
-{
-struct ifnet   *ifp = &sc->arpcom.ac_if;
-       if ( ifp->if_init ) {
-               if ( ifp->if_flags & (IFF_UP | IFF_RUNNING) ) {
-                       printf(DRVNAME"%i: refuse to detach; interface still 
up\n",sc->pvt.port_num+1);
-                       return -1;
-               }
-               mveth_stop(sc);
-/* not implemented in BSDnet/RTEMS (yet) but declared in header */
-#define ether_ifdetach ether_ifdetach_pvt
-               ether_ifdetach(ifp);
-       }
-       free( (void*)sc->pvt.ring_area, M_DEVBUF );
-       sc->pvt.ring_area = 0;
-       sc->pvt.tx_ring   = 0;
-       sc->pvt.rx_ring   = 0;
-       sc->pvt.d_tx_t    = sc->pvt.d_tx_h   = 0;
-       sc->pvt.d_rx_t    = 0;
-       sc->pvt.avail     = 0;
-       /* may fail if ISR was not installed yet */
-       BSP_remove_rtems_irq_handler( &irq_data[sc->pvt.port_num] );
-       return 0;
-}
-
-#ifdef MVETH_DEBUG
-struct rtems_bsdnet_ifconfig mveth_dbg_config = {
-       name:                           DRVNAME"1",
-       attach:                         rtems_mve_attach,
-       ip_address:                     "192.168.2.10",         /* not used by 
rtems_bsdnet_attach */
-       ip_netmask:                     "255.255.255.0",        /* not used by 
rtems_bsdnet_attach */
-       hardware_address:       0, /* (void *) */
-       ignore_broadcast:       0,                                      /* TODO 
driver should honour this  */
-       mtu:                            0,
-       rbuf_count:                     0,                                      
/* TODO driver should honour this  */
-       xbuf_count:                     0,                                      
/* TODO driver should honour this  */
-};
-#endif
-#endif
-- 
2.26.2

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to