[phantom] Add new board type
[people/mcb30/gpxe.git] / src / drivers / net / phantom / phantom.c
index a9ccd4b..509a709 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2008 NetXen, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -1326,17 +1327,6 @@ static void phantom_close ( struct net_device *netdev ) {
        struct io_buffer *iobuf;
        unsigned int i;
 
-       /* BUG5671
-        *
-        * When the last TX context is destroyed, the firmware will
-        * pause the Egress Packet Generator (EPG).  The corresponding
-        * code that is supposed to unpause the EPG when the first TX
-        * context is created is #if 0'd out (with a comment saying
-        * FIXME).  The net result of this is that if you close and
-        * then reopen the interface, you will no longer be able to
-        * transmit packets.
-        */
-
        /* Shut down the port */
        phantom_del_macaddr ( phantom_port, netdev->ll_addr );
        phantom_del_macaddr ( phantom_port,
@@ -1455,9 +1445,20 @@ static void phantom_poll ( struct net_device *netdev ) {
 
                /* Check received opcode */
                sds_opcode = NX_GET ( sds, opcode );
-               switch ( sds_opcode ) {
-               case UNM_RXPKT_DESC:
-               case UNM_SYN_OFFLOAD:
+               if ( ( sds_opcode == UNM_RXPKT_DESC ) ||
+                    ( sds_opcode == UNM_SYN_OFFLOAD ) ) {
+
+                       /* Sanity check: ensure that all of the SDS
+                        * descriptor has been written.
+                        */
+                       if ( NX_GET ( sds, total_length ) == 0 ) {
+                               DBGC ( phantom, "Phantom %p port %d SDS %d "
+                                      "incomplete; deferring\n", phantom,
+                                      phantom_port->port, sds_consumer_idx );
+                               /* Leave for next poll() */
+                               break;
+                       }
+
                        /* Process received packet */
                        sds_handle = NX_GET ( sds, handle );
                        iobuf = phantom_port->rds_iobuf[sds_handle];
@@ -1469,25 +1470,27 @@ static void phantom_poll ( struct net_device *netdev ) {
                                phantom, phantom_port->port, sds_handle );
                        netdev_rx ( netdev, iobuf );
                        phantom_port->rds_iobuf[sds_handle] = NULL;
-                       break;
-               default:
+
+                       /* Update RDS consumer counter.  This is a
+                        * lower bound for the number of descriptors
+                        * that have been read by the hardware, since
+                        * the hardware must have read at least one
+                        * descriptor for each completion that we
+                        * receive.
+                        */
+                       rds_consumer_idx =
+                               ( ( rds_consumer_idx + 1 ) % PHN_NUM_RDS );
+                       phantom_port->rds_consumer_idx = rds_consumer_idx;
+
+               } else {
+
                        DBGC ( phantom, "Phantom %p port %d unexpected SDS "
                               "opcode %02x\n",
                               phantom, phantom_port->port, sds_opcode );
                        DBGC_HDA ( phantom, virt_to_bus ( sds ),
                                   sds, sizeof ( *sds ) );
-                       break;
                }
                        
-               /* Update RDS consumer counter.  This is a lower bound
-                * for the number of descriptors that have been read
-                * by the hardware, since the hardware must have read
-                * at least one descriptor for each completion that we
-                * receive.
-                */
-               rds_consumer_idx = ( ( rds_consumer_idx + 1 ) % PHN_NUM_RDS );
-               phantom_port->rds_consumer_idx = rds_consumer_idx;
-
                /* Clear status descriptor */
                memset ( sds, 0, sizeof ( *sds ) );
 
@@ -1631,6 +1634,7 @@ static int phantom_read_flash ( struct phantom_nic *phantom ) {
        /* Identify board type and number of ports */
        switch ( board_info.board_type ) {
        case UNM_BRDTYPE_P3_4_GB:
+       case UNM_BRDTYPE_P3_4_GB_MM:
                phantom->num_ports = 4;
                break;
        case UNM_BRDTYPE_P3_HMEZ: