[U-Boot-Users] [PATCH] fix BRCM570x related bugs

Vadim Bendebury vbendeb at google.com
Thu May 24 01:30:35 CEST 2007


This fixes numerous bugs in the u-boot bcm570x driver implementation.
The way the driver exists in u-boot before this fix, it allows to ping
a host o few times, but could never complete a tftp transfer of a
kernel image.

The main substance of the fixes is:
- make sure that receive buffer descriptors always have buffers
associated with them
- don't use shared memory structure to assess the chip state (race
conditions were causing  lost indications and timeouts). Use the
chip's registers and queues' contents to determine if the packet has
been sent/received
- initialize the phy as early as possible and keep it up even if the
interface is halted

testing included numerous file transfers - no transfer timeouts were
exibited. Befoire the fix no one transfer would complete, the system
would get stuck after transferring part of the file with numerous
timeouts along the way.

The MAKEALL is still running, so far so good.

Signed-off-by: vbendeb at google.com
==================================================

diff --git a/drivers/bcm570x.c b/drivers/bcm570x.c
index 5f632a6..7e283ee 100644
--- a/drivers/bcm570x.c
+++ b/drivers/bcm570x.c
@@ -6,8 +6,7 @@

 #include <common.h>

-#if (CONFIG_COMMANDS & CFG_CMD_NET) && (!defined(CONFIG_NET_MULTI)) && \
-       defined(CONFIG_BCM570x)
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_BCM570x)

 #ifdef CONFIG_BMW
 #include <mpc824x.h>
@@ -28,7 +27,6 @@
 /*
  * PCI memory base for Ethernet device as well as device Interrupt.
  */
-#define BCM570X_MBAR   0x80100000
 #define BCM570X_ILINE   1


@@ -36,6 +34,15 @@
 #define MAX_PACKET_SIZE 1600
 #define MAX_UNITS       4

+/* by default this driver uses the first interface's MAC address,
+ * if this needs to be changed, the platform specific config file
+ * should define BCM570X_MAC_ADDR_SRC as the appropriate field of the
+ * board descriptor structure (struct bd_info)
+ */
+#ifndef BCM570X_MAC_ADDR_SRC
+#define BCM570X_MAC_ADDR_SRC            bi_enetaddr
+#endif
+
 /* Globals to this module */
 int initialized = 0;
 unsigned int ioBase = 0;
@@ -116,6 +123,7 @@ typedef enum {
        BCM5702,
        BCM5703,
        BCM5703A31,
+       BCM5704,
        TC996T,
        TC996ST,
        TC996SSX,
@@ -152,6 +160,7 @@ static struct {
        {"BCM5702"},
        {"BCM5703"},
        {"BCM5703A31"},
+       {"BCM5704"},
        {"TC996T"},
        {"TC996ST"},
        {"TC996SSX"},
@@ -190,6 +199,7 @@ static struct {
        { "Broadcom BCM5702 1000Base-T" },
        { "Broadcom BCM5703 1000Base-T" },
        { "Broadcom BCM5703 1000Base-SX" },
+       { "Broadcom BCM5704 1000Base-T" },
        { "3Com 3C996 10/100/1000 Server NIC" },
        { "3Com 3C996 10/100/1000 Server NIC" },
        { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
@@ -249,6 +259,7 @@ struct pci_device_table {
        {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
        {0x14e4, 0x1646, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
        {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
+       {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 ,128,32},
        {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 ,128,32},
        {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 ,128,32},
        {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 ,128,32},
@@ -333,7 +344,8 @@ bcm570xReplenishRxBuffers(PUM_DEVICE_BLOCK pUmDevice)
 /*
  * Probe, Map, and Init 570x device.
  */
-int eth_init(bd_t *bis)
+int
+bcm570x_eth_init(bd_t *bis)
 {
     int i, rv, devFound = FALSE;
     pci_dev_t  devbusfn;
@@ -358,10 +370,11 @@ int eth_init(bd_t *bis)
            pci_write_config_dword(devbusfn,
                                   PCI_BASE_ADDRESS_1, 0);

-           ioBase = BCM570X_MBAR;
-
-           pci_write_config_dword(devbusfn,
-                                  PCI_BASE_ADDRESS_0, ioBase);
+           /* read the autoconfigured BAR value (don't forget to mask the
+            * four LSBs which carry extra information
+            */
+           pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &ioBase);
+           ioBase &= ~0xf;

            /*
             * Enable PCI memory, IO, and Master -- don't
@@ -392,8 +405,6 @@ int eth_init(bd_t *bis)
            /* Configure pci dev structure */
            pUmDevice->pdev = devbusfn;
            pUmDevice->index = 0;
-           pUmDevice->tx_pkt = 0;
-           pUmDevice->rx_pkt = 0;
            devFound = TRUE;
            break;
        }
@@ -457,8 +468,8 @@ int eth_init(bd_t *bis)
        (char*)malloc(strlen(board_info[bcm570xDevices[i].board_id].name)+1);
     strcpy(pUmDevice->name,board_info[bcm570xDevices[i].board_id].name);

-    memcpy(pDevice->NodeAddress, bis->bi_enetaddr, 6);
-    LM_SetMacAddress(pDevice, bis->bi_enetaddr);
+    memcpy(pDevice->NodeAddress, bis->BCM570X_MAC_ADDR_SRC, 6);
+    LM_SetMacAddress(pDevice, bis->BCM570X_MAC_ADDR_SRC);
     /* Init queues  .. */
     QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
                 MAX_RX_PACKET_DESC_COUNT);
@@ -495,8 +506,6 @@ int eth_init(bd_t *bis)

     pUmDevice->opened = 1;
     pUmDevice->tx_full = 0;
-    pUmDevice->tx_pkt = 0;
-    pUmDevice->rx_pkt = 0;
     printf("eth%d: %s @0x%lx,",
           pDevice->index, pUmDevice->name, (unsigned long)ioBase);
     printf(    "node addr ");
@@ -519,14 +528,22 @@ int eth_init(bd_t *bis)
        printf("Broadcom BCM5701 Integrated Copper ");
     else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID)
        printf("Broadcom BCM5703 Integrated Copper ");
+    else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID)
+       printf("Broadcom BCM5704 Integrated Copper ");
     else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
        printf("Broadcom BCM8002 SerDes ");
     else if (pDevice->EnableTbi)
        printf("Agilent HDMP-1636 SerDes ");
     else
-       printf("Unknown ");
+       printf("Unknown (ID:%x)", pDevice->PhyId & PHY_ID_MASK);
     printf("transceiver found\n");

+    /* start up the phy right away, reusing i as a scratch variable */
+    LM_ReadPhy(pDevice, PHY_CTRL_REG, (unsigned*) &i);
+    if (i & PHY_CTRL_LOWER_POWER_MODE) {
+           LM_WritePhy (pDevice, PHY_CTRL_REG, i & ~PHY_CTRL_LOWER_POWER_MODE);
+    }
+
     printf("eth%d: %s, MTU: %d,",
           pDevice->index, pDevice->BusSpeedStr, 1500);

@@ -605,39 +622,27 @@ eth_isr(void)
     }

     pUmDevice->interrupt = 0;
-
 }

 int
-eth_send(volatile void *packet, int length)
+bcm570x_eth_send(volatile void *packet, int length)
 {
-    int status = 0;
+    int start_time, status = 0;
 #if ET_DEBUG
     unsigned char* ptr = (unsigned char*)packet;
 #endif
     PLM_PACKET pPacket;
     PUM_PACKET pUmPacket;

-    /* Link down, return */
-    while(pDevice->LinkStatus == LM_STATUS_LINK_DOWN) {
-#if 0
-       printf("eth%d: link down - check cable or link partner.\n",
-              pUmDevice->index);
-#endif
-       eth_isr();
-
-       /* Wait to see link for one-half a second before sending ... */
-       udelay(1500000);
-
-    }
-
-    /* Clear sent flag */
-    pUmDevice->tx_pkt = 0;
-
     /* Previously blocked */
     if(pUmDevice->tx_full){
        printf("eth%d: tx blocked.\n", pUmDevice->index);
-       return 0;
+       return 1;
+    }
+
+    if (length <= 0){
+       printf("eth: bad packet size: %d\n", length);
+       return 2;
     }

     pPacket = (PLM_PACKET)
@@ -646,19 +651,14 @@ eth_send(volatile void *packet, int length)
     if (pPacket == 0) {
        pUmDevice->tx_full = 1;
        printf("bcm570xEndSend: TX full!\n");
-       return 0;
+       return 3;
     }

     if (pDevice->SendBdLeft.counter == 0) {
        pUmDevice->tx_full = 1;
        printf("bcm570xEndSend: no more TX descriptors!\n");
        QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
-       return 0;
-    }
-
-    if (length <= 0){
-       printf("eth: bad packet size: %d\n", length);
-       goto out;
+       return 4;
     }

     /* Get packet buffers and fragment list */
@@ -671,18 +671,22 @@ eth_send(volatile void *packet, int length)
        if (pUmPacket->skbuff == NULL){
            /* Packet was discarded */
            printf("TX: failed (1)\n");
-           status = 1;
+           status = 5;
        } else{
            printf("TX: failed (2)\n");
-           status = 2;
+           status = 6;
        }
        QQ_PushHead (&pDevice->TxPacketFreeQ.Container, pPacket);
        return status;
     }

     /* Copy packet to DMA buffer */
-    memset(pUmPacket->skbuff, 0x0, MAX_PACKET_SIZE);
+    if (length < MIN_ENET_FRAME_SIZE) {
+           length = MIN_ENET_FRAME_SIZE;
+    }
+
     memcpy((void*)pUmPacket->skbuff, (void*)packet, length);
+
     pPacket->PacketSize = length;
     pPacket->Flags |= SND_BD_FLAG_END|SND_BD_FLAG_COAL_NOW;
     pPacket->u.Tx.FragCount = 1;
@@ -697,21 +701,30 @@ eth_send(volatile void *packet, int length)
        if (pUmPacket->skbuff == NULL){
            printf("TX failed (1)!\n");
            /* Packet was discarded */
-           status = 3;
+           status = 7;
        } else {
            /* A resource problem ... */
            printf("TX failed (2)!\n");
-           status = 4;
+           status = 8;
        }

        if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) == 0) {
            printf("TX: emptyQ!\n");
+           status = 5;
            pUmDevice->tx_full = 1;
        }
+
+       return status;
     }

-    while(pUmDevice->tx_pkt == 0){
-       /* Service TX */
+    start_time = get_timer(0);
+    while(!QQ_Empty(&pDevice->TxPacketActiveQ.Container)){
+       if (get_timer(start_time) > (CFG_HZ/10)) {
+           printf("TX: timeout!\n");
+           return 9;
+       }
+
+       /* get tx Serviced */
        eth_isr();
     }
 #if ET_DEBUG
@@ -722,87 +735,62 @@ eth_send(volatile void *packet, int length)
           ptr[6],ptr[7],ptr[8],ptr[9],ptr[10],ptr[11],ptr[12],
           ptr[13],ptr[14],ptr[15]);
 #endif
-    pUmDevice->tx_pkt = 0;
-    QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
-
     /* Done with send */
- out:
-    return status;
+    return 0;
 }


-/* Ethernet receive */
-int
-eth_rx(void)
+void
+bcm570x_eth_rx(void)
 {
-    PLM_PACKET          pPacket = NULL;
-    PUM_PACKET          pUmPacket = NULL;
-    void *skb;
-    int size=0;
+       int size=0;

-    while(TRUE) {
-
-    bcm570x_service_isr:
-       /* Pull down packet if it is there */
+       /* Pull down packets if any */
        eth_isr();

-       /* Indicate RX packets called */
-       if(pUmDevice->rx_pkt){
-           /* printf("eth_rx: got a packet...\n"); */
-           pUmDevice->rx_pkt = 0;
-       } else {
-           /* printf("eth_rx: waiting for packet...\n"); */
-           goto bcm570x_service_isr;
-       }
+       while(QQ_GetEntryCnt(&pDevice->RxPacketReceivedQ.Container)) {
+               PLM_PACKET          pPacket;
+               PUM_PACKET          pUmPacket;

-       pPacket = (PLM_PACKET)
-           QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
+               pPacket = (PLM_PACKET)
+                       QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);

-       if (pPacket == 0){
-           printf("eth_rx: empty packet!\n");
-           goto bcm570x_service_isr;
-       }
+               if (pPacket == 0){
+                       printf("eth_rx: empty packet!\n");
+                       continue;
+               }

-       pUmPacket = (PUM_PACKET) pPacket;
+               pUmPacket = (PUM_PACKET) pPacket;
 #if ET_DEBUG
-       printf("eth_rx: packet @0x%x\n",
-              (int)pPacket);
+               printf("eth_rx: packet @0x%x\n",
+                      (int)pPacket);
 #endif
-       /* If the packet generated an error, reuse buffer */
-       if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
-           ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
-
-           /* reuse skb */
-           QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
-           printf("eth_rx: error in packet dma!\n");
-           goto bcm570x_service_isr;
-       }
-
-       /* Set size and address */
-       skb = pUmPacket->skbuff;
-       size = pPacket->PacketSize;
-
-       /* Pass the packet up to the protocol
-        * layers.
-        */
-       NetReceive(skb, size);
+               /* If the packet generated an error, reuse buffer */
+               if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
+                   ((size = pPacket->PacketSize) > pDevice->RxMtu)) {
+                       printf("eth_rx: error in packet dma!\n");
+               } else {
+                       void *skb;

-       /* Free packet buffer */
-       bcm570xPktFree (pUmDevice->index, skb);
-       pUmPacket->skbuff = NULL;
+                       /* Set size and address */
+                       skb = pUmPacket->skbuff;
+                       size = pPacket->PacketSize;

-       /* Reuse SKB */
-       QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+                       /* Pass the packet up to the protocol
+                        * layers.
+                        */
+                       NetReceive(skb, size);
+               }

-       return 0; /* Got a packet, bail ... */
-    }
-    return size;
+               /* Reuse SKB */
+               QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
+       }
 }


 /* Shut down device */
 void
-eth_halt(void)
+bcm570x_eth_halt(void)
 {
     int i;
     if ( initialized)
@@ -1130,7 +1118,6 @@ MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
        pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
        pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
     }
-    pDevice->NicSendBd = TRUE;

     /* Don't update status blocks during interrupt */
     pDevice->RxCoalescingTicksDuringInt = 0;
@@ -1264,16 +1251,6 @@ MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice,
PLM_PACKET pPacket)
     PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
     PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
     void *skbnew;
-    int len = 0;
-
-    if (len == 0)
-       return (LM_STATUS_SUCCESS);
-
-    if (len > MAX_PACKET_SIZE){
-       printf ("eth%d: xmit frame discarded, too big!, size = %d\n",
-               pUmDevice->index, len);
-       return (LM_STATUS_FAILURE);
-    }

     skbnew = bcm570xPktAlloc(pUmDevice->index, MAX_PACKET_SIZE);

@@ -1290,15 +1267,6 @@ MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice,
PLM_PACKET pPacket)
     return (LM_STATUS_SUCCESS);
 }

-
-LM_STATUS
-MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
-{
-    PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
-    pUmDevice->rx_pkt = 1;
-    return LM_STATUS_SUCCESS;
-}
-
 LM_STATUS
 MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
 {
@@ -1330,7 +1298,6 @@ MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)

        pUmPacket->skbuff = 0;
        QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
-       pUmDevice->tx_pkt = 1;
     }
     if (pUmDevice->tx_full) {
        if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
@@ -1688,4 +1655,230 @@ QQ_GetTail(
     return pQueue->Array[Idx];
 }

-#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_BCM570x */
+#if defined ETHERNET_DEBUG
+
+static void bcm_5750x_dump_rcb(T3_RCB* rcb, const char* name)
+{
+       if (rcb->u.s.Flags & T3_RCB_FLAG_RING_DISABLED) {
+               return;
+       }
+
+       printf("%s at %p\n", name, rcb->HostRingAddr.Low);
+}
+
+void static bcm570x_dump_status_block(void)
+{
+       int     ii;
+       T3_RCB  rcb;
+
+       printf("Status: 0x%x\n", pDevice->pStatusBlkVirt->Status);
+
+       /* now, check out all three rx producer rings (host to MAC) */
+#define HANDLE_RCB(r, src)                                                \
+  r.HostRingAddr.Low = REG_RD(pDevice, RcvDataBdIn.src.HostRingAddr.Low);  \
+  r.HostRingAddr.High = REG_RD(pDevice, RcvDataBdIn.src.HostRingAddr.High);\
+  r.u.MaxLen_Flags = REG_RD(pDevice, RcvDataBdIn.src.u.MaxLen_Flags);     \
+       bcm_5750x_dump_rcb(&r, #src)
+
+       HANDLE_RCB(rcb, JumboRcvRcb);
+       HANDLE_RCB(rcb, StdRcvRcb);
+       HANDLE_RCB(rcb, MiniRcvRcb);
+
+       printf ("Ring  Send Consumer        Rx producer\n");
+       for (ii = 0; ii < 16; ii++) {
+               printf(" %2.2d        %3.3d                %3.3d\n", ii,
+                       pDevice->pStatusBlkVirt->Idx[ii].SendConIdx,
+                       pDevice->pStatusBlkVirt->Idx[ii].RcvProdIdx);
+       }
+}
+
+static void bcm570x_check_status_block(void)
+{
+       unsigned value;
+
+       memset(pDevice->pStatusBlkVirt, 0, sizeof(*pDevice->pStatusBlkVirt));
+       if (pDevice->pStatusBlkVirt->Status) {
+               /* just in case...*/
+               printf("status block not cleared!\n");
+               return;
+       }
+
+       value = REG_RD(pDevice, HostCoalesce.Mode);
+       REG_WR(pDevice, HostCoalesce.Mode, value | HOST_COALESCE_NOW);
+
+       value = get_timer(0);
+       while (!pDevice->pStatusBlkVirt->Status) {
+               if (get_timer(value) > (CFG_HZ/10)) {
+                       printf("%s:%d can't retrieve status!\n",
+                              __FUNCTION__, __LINE__);
+                       return;
+               }
+       }
+
+       bcm570x_dump_status_block();
+}
+
+static void bcm570x_dump(void)
+{
+       int ii, producer, consumer, ring_size;
+       T3_RCV_BD* ring;
+
+       producer = MB_REG_RD(pDevice, Mailbox.RcvStdProdIdx.Low);
+       consumer = pDevice->pStatusBlkVirt->RcvStdConIdx;
+
+       printf("Device base          = %p\n", pDevice->pMemView);
+       printf("UmDevice base        = %p\n", pUmDevice);
+       printf("Rx Producer indx(sw) = %d\n", pDevice->RxStdProdIdx);
+       printf("Rx Producer indx(hw) = %d\n", producer);
+       printf("Tx producer indx(sw) = %d\n", pDevice->SendProdIdx);
+       printf("Rx Status block at   = %p\n", pDevice->pStatusBlkVirt);
+
+       bcm570x_dump_status_block();
+
+       ring = (T3_RCV_BD*) REG_RD(pDevice,
+                                  RcvDataBdIn.StdRcvRcb.HostRingAddr.Low);
+       ring_size = REG_RD(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags)>>16;
+
+       printf("rx buffer list (%d->%d):\n", consumer, producer);
+       ii = 0;
+       while (consumer != producer){
+               T3_RCV_BD* bd;
+               bd = ring + consumer++;
+               if (!(ii++%4)) {
+                       printf ("\n");
+               }
+               printf("%8.8p:%8.8p:%3.3d:%4.4d ", bd,
+                                  bd->HostAddr.Low, bd->Index, bd->Len);
+               if (consumer == ring_size) {
+                       consumer = 0;
+               }
+       }
+       printf ("\n");
+}
+
+#if defined(CONFIG_NET_MULTI)
+static
+#endif
+void bcm570x_info(struct eth_device* p, int argc, char* argv[])
+{
+       if (argc < 1) {
+               bcm570x_dump();
+               return;
+       }
+
+       if (MATCH(argv[0], "status")) {
+               bcm570x_check_status_block();
+               return;
+       }
+}
+
+#endif /* ETHERNET_DEBUG ^^^ defined */
+
+#if defined(CONFIG_NET_MULTI)
+
+int bcm570x_init(struct eth_device *dev, bd_t * bd)
+{
+        if (initialized) {
+                 LM_UINT32 Value32;
+                 LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32);
+
+                 if (Value32 & PHY_CTRL_LOWER_POWER_MODE) {
+                          /* if phy is down - bring it back up */
+                          LM_WritePhy (pDevice, PHY_CTRL_REG,
+                              Value32 & ~PHY_CTRL_LOWER_POWER_MODE);
+                 }
+                 return 1;
+        }
+        return 0;
+}
+
+void bcm570x_halt(struct eth_device *dev)
+{
+       /* let's do nothing here - why not to keep the interface up at all
+        * times? */
+}
+
+int
+bcm570x_send(struct eth_device *dev, volatile void *packet, int length)
+{
+        if (initialized) {
+                 return bcm570x_eth_send( packet, length );
+        }
+        return -1;
+}
+
+int bcm570x_recv( struct eth_device* p )
+{
+        if (initialized) {
+                 bcm570x_eth_rx();
+        }
+        return 0;
+}
+
+int bcm570x_initialize( bd_t * bis )
+{
+        struct eth_device *dev;
+
+        if (bcm570x_eth_init( bis )) {
+                 printf( "%s:%d - init failed!\n", __FUNCTION__, __LINE__ );
+                 return -1;
+        }
+
+        dev = (struct eth_device *)malloc(sizeof *dev);
+        if ( !dev ) {
+                 printf( "%s:%d - dev allocation failed!\n",
+                                            __FUNCTION__, __LINE__ );
+                 return -1;
+        }
+
+        memset (dev, 0, sizeof (*dev));
+        memcpy (dev->enetaddr, bis->BCM570X_MAC_ADDR_SRC,
+                sizeof(dev->enetaddr));
+
+        memcpy(dev->name, pUmDevice->name,
+               min (strlen (pUmDevice->name), sizeof (dev->name)));
+
+        dev->init = bcm570x_init;
+        dev->halt = bcm570x_halt;
+        dev->send = bcm570x_send;
+        dev->recv = bcm570x_recv;
+#if defined ETHERNET_DEBUG
+        dev->info = bcm570x_info;
+#endif
+        eth_register(dev);
+
+        return 0;
+}
+
+#else /* CONFIG_NET_MULTI ^^^ defined   vvv  NOT defined */
+
+/* wrappers to comply with the non CONFIG_NET_MULTI mode */
+
+int
+eth_init( bd_t *bis )
+{
+       return bcm570x_eth_init(bis);
+}
+
+int
+eth_send(volatile void *packet, int length)
+{
+       return eth_send(packet, length);
+}
+
+int
+eth_rx( void )
+{
+       bcm570x_eth_rx();
+       return 0;
+}
+
+void
+eth_halt(void)
+{
+       bcm570x_eth_halt();
+}
+
+#endif /* CONFIG_NET_MULTI ^^^ not defined */
+
+#endif /* CFG_CMD_NET && CONFIG_BCM570x */
diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h
index 607f3fd..40d1946 100644
--- a/drivers/bcm570x_lm.h
+++ b/drivers/bcm570x_lm.h
@@ -425,7 +425,6 @@ LM_STATUS MM_WriteConfig32(PLM_DEVICE_BLOCK
pDevice, LM_UINT32 Offset,
     LM_UINT32 Value32);
 LM_STATUS MM_MapMemBase(PLM_DEVICE_BLOCK pDevice);
 LM_STATUS MM_MapIoBase(PLM_DEVICE_BLOCK pDevice);
-LM_STATUS MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice);
 LM_STATUS MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice);
 LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
 LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);
diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h
index b7cbf8a..88362dd 100644
--- a/drivers/bcm570x_mm.h
+++ b/drivers/bcm570x_mm.h
@@ -87,8 +87,6 @@ typedef struct _UM_DEVICE_BLOCK {
        volatile int interrupt;
        int tasklet_pending;
        int tasklet_busy;            /* new -- unsupported */
-       int rx_pkt;
-       int tx_pkt;
 #ifdef NICE_SUPPORT   /* unsupported, this is a linux ioctl */
        void (*nice_rx)(void*, void* );
        void* nice_ctx;
diff --git a/drivers/tigon3.c b/drivers/tigon3.c
index ec2cd2a..5086592 100644
--- a/drivers/tigon3.c
+++ b/drivers/tigon3.c
@@ -12,8 +12,7 @@
 /******************************************************************************/
 #include <common.h>
 #include <asm/types.h>
-#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \
-       defined(CONFIG_TIGON3)
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_TIGON3)
 #ifdef CONFIG_BMW
 #include <mpc824x.h>
 #endif
@@ -21,7 +20,6 @@
 #include <linux/byteorder/big_endian.h>
 #include "bcm570x_mm.h"

-#define EMBEDDED 1
 /******************************************************************************/
 /* Local functions. */
 /******************************************************************************/
@@ -1040,7 +1038,8 @@ PLM_DEVICE_BLOCK pDevice)
        pDevice->BondId != GRC_MISC_BD_ID_5703 &&
        pDevice->BondId != GRC_MISC_BD_ID_5703S &&
        pDevice->BondId != GRC_MISC_BD_ID_5704 &&
-       pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE)
+       pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE &&
+        pDevice->BondId != GRC_MISC_BD_ID_5704_A2)
     {
        return LM_STATUS_UNKNOWN_ADAPTER;
     }
@@ -1652,15 +1651,14 @@ PLM_DEVICE_BLOCK pDevice)
     /* Set power state to D0. */
     LM_SetPowerState(pDevice, LM_POWER_STATE_D0);

+#define QUEUE_INIT(x)  QQ_InitQueue(&pDevice->x.Container, \
+                                       ARRAY_SIZE(pDevice->x.EntryBuffer))
     /* Intialize the queues. */
-    QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container,
-       MAX_RX_PACKET_DESC_COUNT);
-    QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
-       MAX_RX_PACKET_DESC_COUNT);
-
-    QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT);
-    QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT);
-    QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT);
+    QUEUE_INIT(RxPacketReceivedQ);
+    QUEUE_INIT(RxPacketFreeQ);
+    QUEUE_INIT(TxPacketFreeQ);
+    QUEUE_INIT(TxPacketActiveQ);
+    QUEUE_INIT(TxPacketXmittedQ);

     /* Allocate shared memory for: status block, the buffers for receive */
     /* rings -- standard, mini, jumbo, and return rings. */
@@ -1780,13 +1778,17 @@ PLM_DEVICE_BLOCK pDevice)
     /* Allocate memory for packet descriptors. */
     Size = (pDevice->RxPacketDescCnt +
        pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE;
-    Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket);
+    Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID*)(void*)&pPacket);
     if(Status != LM_STATUS_SUCCESS)
     {
        return Status;
     }
     pDevice->pPacketDescBase = (PLM_VOID) pPacket;

+#if ET_DEBUG
+ printf("LM_Init_adapter: TX descriptors located at 0x%x\n", (void *)pPacket);
+#endif
+
     /* Create transmit packet descriptors from the memory block and add them */
     /* to the TxPacketFreeQ for each send ring. */
     for(j = 0; j < pDevice->TxPacketDescCnt; j++)
@@ -1803,6 +1805,9 @@ PLM_DEVICE_BLOCK pDevice)
        pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE);
     } /* for(j.. */

+#if ET_DEBUG
+ printf("LM_Init_adapter: RX descriptors located at 0x%x\n", (void *)pPacket);
+#endif
     /* Create receive packet descriptors from the memory block and add them */
     /* to the RxPacketFreeQ.  Create the Standard packet descriptors. */
     for(j = 0; j < pDevice->RxStdDescCnt; j++)
@@ -2822,7 +2827,14 @@ PLM_DEVICE_BLOCK pDevice)
     {
        if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0)
        {
-           Value16 = REG_RD(pDevice, PciCfg.PciXCommand);
+           /*
+            * Patched to remove warnings; need A0 chip to test.
+            * If you can test this and find it wrong, please fix.
+            * Might need BYTE_SWAP_16_BIT() here and on store,
+            * but that logic is in disarray in this code.
+            */
+           volatile u16 *p16 = &pDevice->pMemView->PciCfg.PciXCommand;
+           Value16 = *p16;
            Value16 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK);
            Value16 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) &
                PCIX_CMD_MAX_BURST_MASK);
@@ -2831,7 +2843,7 @@ PLM_DEVICE_BLOCK pDevice)
                Value16 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL)
                   & PCIX_CMD_MAX_SPLIT_MASK;
            }
-           REG_WR(pDevice, PciCfg.PciXCommand, Value16);
+           *p16 = Value16;
        }
     }

@@ -3026,137 +3038,6 @@ LM_EnableInterrupt(
 /* Return:
        */
 /*    LM_STATUS_SUCCESS
        */
 /******************************************************************************/
-#if 0
-LM_STATUS
-LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
-{
-    LM_UINT32 FragCount;
-    PT3_SND_BD pSendBd;
-    PT3_SND_BD pShadowSendBd;
-    LM_UINT32 Value32, Len;
-    LM_UINT32 Idx;
-
-    if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) {
-       return LM_5700SendPacket(pDevice, pPacket);
-    }
-
-    /* Update the SendBdLeft count. */
-    atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft);
-
-    /* Initalize the send buffer descriptors. */
-    Idx = pDevice->SendProdIdx;
-
-    pSendBd = &pDevice->pSendBdVirt[Idx];
-
-    /* Next producer index. */
-    if (pDevice->NicSendBd == TRUE)
-    {
-       T3_64BIT_HOST_ADDR paddr;
-
-       pShadowSendBd = &pDevice->ShadowSendBd[Idx];
-       for(FragCount = 0; ; )
-       {
-           MM_MapTxDma(pDevice, pPacket, &paddr, &Len, FragCount);
-           /* Initialize the pointer to the send buffer fragment. */
-           if (paddr.High != pShadowSendBd->HostAddr.High)
-           {
-               __raw_writel(paddr.High, &(pSendBd->HostAddr.High));
-               pShadowSendBd->HostAddr.High = paddr.High;
-           }
-           __raw_writel(paddr.Low, &(pSendBd->HostAddr.Low));
-
-           /* Setup the control flags and send buffer size. */
-           Value32 = (Len << 16) | pPacket->Flags;
-
-           Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
-
-           FragCount++;
-           if (FragCount >= pPacket->u.Tx.FragCount)
-           {
-               Value32 |= SND_BD_FLAG_END;
-               if (Value32 != pShadowSendBd->u1.Len_Flags)
-               {
-                   __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
-                   pShadowSendBd->u1.Len_Flags = Value32;
-               }
-               if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
-                   __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
-               }
-               break;
-           }
-           else
-           {
-               if (Value32 != pShadowSendBd->u1.Len_Flags)
-               {
-                   __raw_writel(Value32, &(pSendBd->u1.Len_Flags));
-                   pShadowSendBd->u1.Len_Flags = Value32;
-               }
-               if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) {
-                   __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag));
-               }
-           }
-
-           pSendBd++;
-           pShadowSendBd++;
-           if (Idx == 0)
-           {
-               pSendBd = &pDevice->pSendBdVirt[0];
-               pShadowSendBd = &pDevice->ShadowSendBd[0];
-           }
-       } /* for */
-
-       /* Put the packet descriptor in the ActiveQ. */
-       QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
-
-       wmb();
-       MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx);
-
-    }
-    else
-    {
-       for(FragCount = 0; ; )
-       {
-           /* Initialize the pointer to the send buffer fragment. */
-           MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount);
-
-           pSendBd->u2.VlanTag = pPacket->VlanTag;
-
-           /* Setup the control flags and send buffer size. */
-           Value32 = (Len << 16) | pPacket->Flags;
-
-           Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK;
-
-           FragCount++;
-           if (FragCount >= pPacket->u.Tx.FragCount)
-           {
-               pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END;
-               break;
-           }
-           else
-           {
-               pSendBd->u1.Len_Flags = Value32;
-           }
-           pSendBd++;
-           if (Idx == 0)
-           {
-               pSendBd = &pDevice->pSendBdVirt[0];
-           }
-       } /* for */
-
-       /* Put the packet descriptor in the ActiveQ. */
-       QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket);
-
-       wmb();
-       MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx);
-
-    }
-
-    /* Update the producer index. */
-    pDevice->SendProdIdx = Idx;
-
-    return LM_STATUS_SUCCESS;
-}
-#endif

 LM_STATUS
 LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
@@ -3594,9 +3475,6 @@ PLM_DEVICE_BLOCK pDevice)
     {
        /* Indicate packets to the protocol. */
        MM_IndicateTxPackets(pDevice);
-
-       /* Indicate received packets to the protocols. */
-       MM_IndicateRxPackets(pDevice);
     }
     else
     {
@@ -4020,14 +3898,6 @@ LM_ServiceInterrupts(
     LM_ServiceTxInterrupt(pDevice);

     /* No spinlock for this queue since this routine is serialized. */
-    if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container))
-    {
-       /* Indicate receive packets. */
-       MM_IndicateRxPackets(pDevice);
-       /*       LM_QueueRxPackets(pDevice); */
-    }
-
-    /* No spinlock for this queue since this routine is serialized. */
     if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container))
     {
        MM_IndicateTxPackets(pDevice);
@@ -6197,4 +6067,4 @@ LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8
pBufferVirt,
     }
     return LM_STATUS_SUCCESS;
 }
-#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_TIGON3 */
+#endif /* CFG_CMD_NET, CONFIG_TIGON3 */
diff --git a/drivers/tigon3.h b/drivers/tigon3.h
index ea4367d..a2c690c 100644
--- a/drivers/tigon3.h
+++ b/drivers/tigon3.h
@@ -2403,6 +2403,7 @@ typedef struct {
     #define GRC_MISC_BD_ID_5702FE                       0x00004000
     #define GRC_MISC_BD_ID_5704                         0x00000000
     #define GRC_MISC_BD_ID_5704CIOBE                    0x00004000
+    #define GRC_MISC_BD_ID_5704_A2                     0x00008000

     /* Miscellaneous local control register. */
     T3_32BIT_REGISTER LocalCtrl;
diff --git a/include/common.h b/include/common.h
index 3c4b37b..acbbcb2 100644
--- a/include/common.h
+++ b/include/common.h
@@ -634,4 +634,6 @@ void        show_boot_progress (int status);
 #error Read section CONFIG_SKIP_LOWLEVEL_INIT in README.
 #endif

+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
 #endif /* __COMMON_H_ */
diff --git a/include/net.h b/include/net.h
index 461e038..e5ac66f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -84,7 +84,8 @@ typedef void  rxhand_f(uchar *, unsigned, unsigned, unsigned);
  */
 typedef void   thand_f(void);

-#define NAMESIZE 16
+/* some ETH interface names in bcm5704 driver are pretty long...*/
+#define ETH_NAMESIZE 50

 enum eth_state_t {
        ETH_STATE_INIT,
@@ -93,7 +94,7 @@ enum eth_state_t {
 };

 struct eth_device {
-       char name[NAMESIZE];
+       char name[ETH_NAMESIZE];
        unsigned char enetaddr[6];
        int iobase;
        int state;
@@ -105,13 +106,27 @@ struct eth_device {

        struct eth_device *next;
        void *priv;
+#ifdef ETHERNET_DEBUG
+       void (*info) (struct eth_device*, int argc, char* argv[]);
+#endif
 };

+#ifdef ETHERNET_DEBUG
+
+typedef void bypass_rx_f( volatile uchar*, int);
+
+extern void set_bypass_rx( bypass_rx_f f );
+extern void remove_bypass_rx( void );
+
+#endif
+
 extern int eth_initialize(bd_t *bis);          /* Initialize network
subsystem */
 extern int eth_register(struct eth_device* dev);/* Register network
device     */
 extern void eth_try_another(int first_restart);        /* Change the
device            */
 #ifdef CONFIG_NET_MULTI
 extern void eth_set_current(void);             /* set nterface to
ethcur var.  */
+                       /* traverse the list of registered ethernet
interfaces */
+extern char *eth_get_next_name (char* this_name);
 #endif
 extern struct eth_device *eth_get_dev(void);   /* get the current
device MAC   */
 extern struct eth_device *eth_get_dev_by_name(char *devname); /* get
device    */
@@ -458,4 +473,10 @@ extern void        copy_filename (char *dst, char
*src, int size);

 /**********************************************************************/

+/*
+ * this definition should be used by all ethernet drivers
+ */
+#define MAC_ADDR_SIZE        6
+#define MIN_ENET_FRAME_SIZE  60  /* crcless */
+
 #endif /* __NET_H__ */




More information about the U-Boot mailing list