Index: c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c
===================================================================
--- c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c	(revision 7e2187f4ad877301cd21434cbb9e30912bcd86ab)
+++ c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.c	(revision 301a2a3c0b46df149e0194b6742cdafc196a6656)
@@ -1,2 +1,3 @@
+void break_when_you_get_here();
 /*
  *******************************************************************
@@ -51,6 +52,10 @@
 #define SONIC_DEBUG_MEMORY           0x0002
 #define SONIC_DEBUG_MEMORY_ALLOCATE  0x0004
-
-#define SONIC_DEBUG      (SONIC_DEBUG_PRINT_REGISTERS|SONIC_DEBUG_MEMORY)
+#define SONIC_DEBUG_FRAGMENTS        0x0008
+#define SONIC_DEBUG_CAM              0x0008
+
+#define SONIC_DEBUG      (SONIC_DEBUG_MEMORY|SONIC_DEBUG_CAM) 
+/* SONIC_DEBUG_ALL */
+
 
 /*
@@ -187,4 +192,5 @@
   int                             rdaCount;
   ReceiveResourcePointer_t        rsa;
+  CamDescriptorPointer_t          cdp;
   ReceiveDescriptorPointer_t      rda;
   ReceiveDescriptorPointer_t      rdp_last;
@@ -245,5 +251,5 @@
  * Very simple minded -- just keeps trying till the memory is on a single page.
  */
-SONIC_STATIC void * sonic_allocate (unsigned int nbytes)
+SONIC_STATIC void * sonic_allocate(unsigned int nbytes)
 {
   void *p;
@@ -386,5 +392,4 @@
                   ~(IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
     );
-    dp->rxInterrupts++;
     dp->txInterrupts++;
     rtems_event_send (dp->txWaitTid, INTERRUPT_EVENT);
@@ -414,4 +419,6 @@
   while ((dp->tdaActiveCount != 0)
       && ((status = dp->tdaTail->status) != 0)) {
+
+/* printf( "retire TDA %p (0x%04x)\n", dp->tdaTail, status ); */
     /*
      * Check for errors which stop the transmitter.
@@ -589,4 +596,8 @@
     packetSize += bp->cnt;
 
+#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
+    printf( "fp %p 0x%04x%04x %d\n",
+      fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
+#endif
     /*
      * Break out of the loop if this mbuf is the last in the frame.
@@ -601,10 +612,14 @@
   if  ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
     int padSize = 64 - packetSize;
+    fp++;
     fp->frag_lsw = LSW(padBuf);
     fp->frag_msw = MSW(padBuf);
     fp->frag_size = padSize;
+#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
+    printf( "PAD fp %p 0x%04x%04x %d\n",
+         fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
+#endif
     packetSize += padSize;
     i++;
-    fp++;
   }
 
@@ -613,5 +628,5 @@
    */
   tdp->pkt_size = packetSize;
-  tdp->frag_count = i;
+  tdp->frag_count = i + 1;
   tdp->status = 0;
 
@@ -619,7 +634,13 @@
    * Chain onto list and start transmission.
    */
-  tdp->linkp = &fp->frag_link;
+  tdp->linkp = &(fp+1)->frag_link;
   *tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
   *dp->tdaHead->linkp &= ~TDA_LINK_EOL;
+  sonic_write_register(
+     rp,
+     SONIC_REG_IMR,
+     sonic_read_register( rp, SONIC_REG_IMR) |
+            (IMR_PINTEN | IMR_PTXEN | IMR_TXEREN)
+  );
   sonic_write_register( rp, SONIC_REG_CR, CR_TXP );
   dp->tdaActiveCount++;
@@ -803,5 +824,5 @@
     }
 
-printf( "Incoming packet %p\n", rdp );
+/* printf( "Incoming packet %p\n", rdp ); */
 
     /*
@@ -813,4 +834,5 @@
       void *p;
 
+/* printf( "Valid packet\n" ); */
       /*
        * Get the mbuf pointer
@@ -829,4 +851,5 @@
        */
       bp->cnt = rdp->byte_count - sizeof (uint32);
+/* printf( "Routing the packet\n" ); */
       net_route (iface, &bp);
 
@@ -930,14 +953,5 @@
   ReceiveResourcePointer_t rwp, rea;
   struct mbuf *bp;
-  struct CamDescriptor{
-    struct {
-      rtems_unsigned32  cep;  /* CAM Entry Pointer */
-      rtems_unsigned32  cap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
-      rtems_unsigned32  cap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
-      rtems_unsigned32  cap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
-    } desc[16];
-    rtems_unsigned32  ce;
-  };
-  volatile struct CamDescriptor *cdp;
+  CamDescriptorPointer_t cdp;
 
   /*
@@ -962,5 +976,5 @@
 
   dp->tdaActiveCount = 0;
-  dp->tdaTail = sonic_allocate (dp->tdaCount * sizeof *tdp);
+  dp->tdaTail = sonic_allocate(dp->tdaCount * sizeof *tdp);
 #if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
   printf( "tdaTail = %p\n", dp->tdaTail );
@@ -968,18 +982,26 @@
   otdp = tdp = dp->tdaTail;
   for (i = 0 ; i < dp->tdaCount ; i++) {
+    /*
+     *  status, pkt_config, pkt_size, and all fragment fields 
+     *  are set to zero by sonic_allocate.
+     */
+
+/* XXX not used by other drivers 
     if (i & 1)
       tdp->pkt_config = TDA_CONFIG_PINT;
-    else
-      tdp->pkt_config = 0;
-    tdp->frag_count = 1;
-    if (i == (dp->tdaCount - 1))
-      tdp->next = (TransmitDescriptor_t *)dp->tdaTail;
-    else
-      tdp->next = (TransmitDescriptor_t *)(tdp + 1);
+*/
+
+    tdp->frag_count        = 1;
+    tdp->frag[0].frag_link = LSW(tdp + 1);
+    tdp->link_pad          = LSW(tdp + 1) | TDA_LINK_EOL;
+    otdp->linkp            = &((tdp + 1)->frag[0].frag_link);
+    tdp->next              = (TransmitDescriptor_t *)(tdp + 1);
     otdp = tdp;
-    tdp = tdp->next;
-  }
-  dp->tdaHead = otdp;
-  dp->tdaHead->linkp = &dp->tdaHead->frag[0].frag_link;
+    tdp++;
+  }
+  dp->tdaHead = otdp;  /* XXX why? */
+  otdp->link_pad = LSW(dp->tdaTail) | TDA_LINK_EOL;
+  otdp->next = (TransmitDescriptor_t *)dp->tdaTail;
+  otdp->linkp = &dp->tdaHead->frag[0].frag_link;
 
   /*
@@ -987,9 +1009,16 @@
    *  Leaves ordp pointing at the `end' of the list and
    *  dp->rda pointing at the `beginning' of the list.
-   */
-
-  dp->rda = sonic_allocate (dp->rdaCount * sizeof(ReceiveDescriptor_t));
+   *
+   *  NOTE: The RDA and CDP must have the same MSW for their addresses.
+   */
+
+  dp->rda = sonic_allocate(
+              (dp->rdaCount * sizeof(ReceiveDescriptor_t)) + 
+                sizeof(CamDescriptor_t) );
+  dp->cdp = (CamDescriptorPointer_t) ((unsigned char *)dp->rda +
+        (dp->rdaCount * sizeof(ReceiveDescriptor_t)));
 #if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
   printf( "rda area = %p\n", dp->rda );
+  printf( "cdp area = %p\n", dp->cdp );
 #endif
 
@@ -1022,5 +1051,5 @@
    */
 
-  dp->rsa = sonic_allocate ((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa);
+  dp->rsa = sonic_allocate((dp->rdaCount + RRA_EXTRA_COUNT) * sizeof *dp->rsa);
 #if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
   printf( "rsa area = %p\n", dp->rsa );
@@ -1050,4 +1079,5 @@
      * Set up RRA entry
      */
+
     rwp->buff_ptr_lsw = LSW(bp->data);
     rwp->buff_ptr_msw = MSW(bp->data);
@@ -1087,4 +1117,5 @@
   sonic_write_register( rp, SONIC_REG_FAET, 0xFFFF );
   sonic_write_register( rp, SONIC_REG_MPT, 0xFFFF );
+  sonic_write_register( rp, SONIC_REG_RSC, 0 );
 
   /*
@@ -1102,4 +1133,5 @@
    * Set up Resource Area pointers
    */
+
   sonic_write_register( rp, SONIC_REG_URRA, MSW(dp->rsa) );
   sonic_write_register( rp, SONIC_REG_RSA, LSW(dp->rsa) );
@@ -1109,5 +1141,4 @@
   sonic_write_register( rp, SONIC_REG_RRP, LSW(dp->rsa) );
   sonic_write_register( rp, SONIC_REG_RWP, LSW(dp->rsa) ); /* XXX was rea */
-  sonic_write_register( rp, SONIC_REG_RSC, 0 );
 
   sonic_write_register( rp, SONIC_REG_URDA, MSW(dp->rda) );
@@ -1145,10 +1176,18 @@
    */
   hwaddr = dp->iface->hwaddr;
-  cdp = (struct CamDescriptor *)dp->rsa;
+  cdp = dp->cdp;
+
   for (i=0 ; i<16 ; i++ ) {
+    /*
+     *  cap0, cap1, and cap2 are zeroed by sonic_allocate.
+     */
     cdp->desc[i].cep = i;
   }
 
   cdp->desc[0].cep = 0;      /* Fill first entry in CAM */
+#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
+  printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n",
+     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );
+#endif
   cdp->desc[0].cap2 = hwaddr[0] << 8 | hwaddr[1];
   cdp->desc[0].cap1 = hwaddr[2] << 8 | hwaddr[3];
@@ -1167,4 +1206,16 @@
 
   sonic_write_register( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
+
+#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
+  sonic_write_register( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
+    printf ("Loaded Ethernet address into SONIC CAM.\n"
+      "  Wrote %04x%04x%04x - %#x\n"
+      "   Read %04x%04x%04x - %#x\n", 
+        cdp->desc[0].cap2, cdp->desc[0].cap1, cdp->desc[0].cap0, cdp->ce,
+        sonic_read_register( rp, SONIC_REG_CAP2 ),
+        sonic_read_register( rp, SONIC_REG_CAP1 ),
+        sonic_read_register( rp, SONIC_REG_CAP0 ),
+        sonic_read_register( rp, SONIC_REG_CE ));
+#endif
 
   sonic_write_register( rp, SONIC_REG_CEP, 0 );  /* Select first entry in CAM */
@@ -1181,10 +1232,8 @@
         sonic_read_register( rp, SONIC_REG_CAP0 ),
         sonic_read_register( rp, SONIC_REG_CE ));
-#if 0
     rtems_panic ("SONIC LCAM");
-#endif
-  }
-
-  sonic_write_register( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX );
+  }
+
+  sonic_write_register(rp, SONIC_REG_CR, CR_TXP | CR_RXEN | CR_STP);
 
   /*
@@ -1444,3 +1493,2 @@
   return value;
 }
-
Index: c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h
===================================================================
--- c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h	(revision 7e2187f4ad877301cd21434cbb9e30912bcd86ab)
+++ c/src/lib/libbsp/powerpc/dmv177/sonic/sonic.h	(revision 301a2a3c0b46df149e0194b6742cdafc196a6656)
@@ -333,4 +333,16 @@
 typedef volatile ReceiveDescriptor_t *ReceiveDescriptorPointer_t;
 
+typedef struct {
+  struct {
+    rtems_unsigned32  cep;  /* CAM Entry Pointer */
+    rtems_unsigned32  cap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
+    rtems_unsigned32  cap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
+    rtems_unsigned32  cap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
+  } desc[16];
+  rtems_unsigned32  ce;
+} CamDescriptor_t;
+
+typedef volatile CamDescriptor_t *CamDescriptorPointer_t;
+
 /*
  * Receive status
