+static int
+netxen_loopback_test(struct net_device *netdev, int fint, void *ptr)
+{
+       int                                             ii, ret;
+       unsigned char                   *data;
+       netxen_send_test_t              args;
+
+       if ((ret = copy_from_user(&args, ptr, sizeof(args)))) {
+               return (-LB_UCOPY_PARAM_ERR);
+       }
+
+       if (tx_user_packet_data != NULL) {
+               kfree(tx_user_packet_data);
+               tx_user_packet_data = NULL;
+       }
+
+       if (args.count != 0) { /* user data */
+               tx_user_packet_data = kmalloc(args.count + 16, GFP_KERNEL);
+               if (tx_user_packet_data == NULL)
+                       return (-LB_NOMEM_ERR);
+               memset(tx_user_packet_data, 0xFF, 16);
+               /* XXX args.ifg should be u64 */
+               if (copy_from_user(tx_user_packet_data+16,
+                               (char *)(uptr_t)args.ifg, args.count)) {
+                       kfree(tx_user_packet_data);
+                       tx_user_packet_data = NULL;
+                       return (-LB_UCOPY_DATA_ERR);
+               }
+               tx_user_packet_length = args.count + 16;
+               rx_datalen = (tx_user_packet_length - 14) * 16;
+       } else {  /* use local data */
+               tx_user_packet_data = kmalloc(sizeof(XMIT_DATA) + 16, 
GFP_KERNEL);
+               if (tx_user_packet_data == NULL)
+                       return (-LB_NOMEM_ERR);
+               memset(tx_user_packet_data, 0xFF, 14);
+               memcpy(tx_user_packet_data + 16, XMIT_DATA, sizeof(XMIT_DATA));
+               tx_user_packet_length = sizeof(XMIT_DATA) + 16;
+               rx_datalen = (sizeof(XMIT_DATA) + 2) * 16;
+       }
+       if ((rx_user_packet_data = kmalloc(rx_datalen, GFP_KERNEL)) == NULL){
+               ret = -LB_NOMEM_ERR;
+               goto end;
+       }
+       rx_user_pos = 0;
+
+       if (fint == 1) {
+               loopback_start = 1;
+               xge_loopback(1);
+       }
+
+       tx_stop = 0;
+       capture_input = 1;
+       captured = 0;
+       args.count = 16;
+       if ((ret = tx_test(netdev, &args)) != 0) {
+               ret = -LB_TX_NOSKB_ERR;
+        capture_input = 0;
+               goto end;
+       }
+
+       mdelay(1000); /* wait for data to come back */
+       capture_input = 0;
+
+       if (rx_user_pos != rx_datalen) {
+               ret = -LB_SHORT_DATA_ERR;
+               goto end;
+       }
+
+       data = rx_user_packet_data;
+       /* check received bytes against tx_user_packet_data */
+       for (ii = 0; ii < 16; ++ii) {
+               if (*((uint16_t *)data) != (uint16_t)ii) {
+                       ret = -LB_SEQUENCE_ERR;
+                       goto end;
+               }
+               if (memcmp(tx_user_packet_data + 16, data + 2,
+                                tx_user_packet_length - 16)
+                        != 0) {
+                       ret = -LB_DATA_ERR;
+                       goto end;
+               }
+               data += (tx_user_packet_length - 14);
+       }
+       ret = LB_TEST_OK;
+
+end:
+       tx_stop = 1;
+       if (fint == 1) {
+               xge_loopback(0);
+               loopback_start = 0;
+       }
+       if (tx_user_packet_data != NULL) {
+               kfree(tx_user_packet_data);
+               tx_user_packet_data = NULL;
+       }
+       kfree(rx_user_packet_data);
+       rx_user_packet_data = NULL;
+       return(ret);
+}
+
+static int
+netxen_link_test(netxen_adapter *adapter)
+{
+    long rv;
+
+       rv = xge_link_status ();
+       return((rv == XG_LINK_DOWN) ? (-1) : (0));
+}
+
+int netxentest_pegstuck(netxen_crbword_t addr, U64 reg, int loop, struct 
netxen_adapter_s *adapter)
+{
+       int                     i;
+       netxen_crbword_t        temp;
+
+       for (i = 0; i < loop; ++i) {
+               NetXen_CRB_READ_CHECK_ADAPTER(reg, &temp, adapter);
+               if (temp != addr)
+                       return (0);
+       }
+       return (-1);
+}
+
+static int
+netxen_hw_test(netxen_adapter *adapter)
+{
+       netxen_crbword_t        temp;
+       int                             ii, rc = HW_TEST_OK;
+       uint64_t                base, address;
+
+    /* DMA Status*/
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(0), &temp, adapter);
+       if ((temp & 0x3) == 0x3) {
+               rc = -HW_DMA_BZ_0;
+               goto done;
+       }
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(1), &temp, adapter);
+       if ((temp & 0x3) == 0x3) {
+               rc = -HW_DMA_BZ_1;
+               goto done;
+       }
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(2), &temp, adapter);
+       if ((temp & 0x3) == 0x3) {
+               rc = -HW_DMA_BZ_2;
+               goto done;
+       }
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(3), &temp, adapter);
+       if ((temp & 0x3) == 0x3) {
+               rc = -HW_DMA_BZ_3;
+               goto done;
+       }
+
+       /* SRE Status */
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_PBI_ACTIVE_STATUS, &temp, 
adapter);
+       if ((temp & 0x1) == 0) {
+               rc = -HW_SRE_PBI_HALT;
+               goto done;
+       }
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_L1RE_CTL, &temp, adapter);
+    if ((temp & 0x20000000) != 0) {
+               rc = -HW_SRE_L1IPQ;
+               goto done;
+       }
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_L2RE_CTL, &temp, adapter);
+    if ((temp & 0x20000000) != 0) {
+               rc = -HW_SRE_L2IFQ;
+               goto done;
+       }
+
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_INT_STATUS, &temp, adapter);
+       if ((temp & 0xc0ff) != 0) {
+               if ((temp & 0x1) != 0) {
+                       rc = -HW_PQ_W_PAUSE;
+                       goto done;
+               }
+               if ((temp & 0x2) != 0) {
+                       rc = -HW_PQ_W_FULL;
+                       goto done;
+               }
+               if ((temp & 0x4) != 0) {
+                       rc = -HW_IFQ_W_PAUSE;
+                       goto done;
+               }
+               if ((temp & 0x8) != 0) {
+                       rc = -HW_IFQ_W_FULL;
+                       goto done;
+               }
+               if ((temp & 0x10) != 0) {
+                       rc = -HW_MEN_BP_TOUT;
+                       goto done;
+               }
+               if ((temp & 0x20) != 0) {
+                       rc = -HW_DOWN_BP_TOUT;
+                       goto done;
+               }
+               if ((temp & 0x40) != 0) {
+                       rc = -HW_FBUFF_POOL_WM;
+                       goto done;
+               }
+               if ((temp & 0x80) != 0) {
+                       rc = -HW_PBUF_ERR;
+                       goto done;
+               }
+               if ((temp & 0x4000) != 0) {
+                       rc = -HW_FM_MSG_HDR;
+                       goto done;
+               }
+               if ((temp & 0x8000) != 0) {
+                       rc = -HW_FM_MSG;
+                       goto done;
+               }
+       }
+
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_INT_STATUS, &temp, adapter);
+
+       if ((temp & 0x3f00) != 0) {
+               if ((temp & 0x100) != 0) {
+                       rc = -HW_EPG_MSG_BUF;
+                       goto done;
+               }
+               if ((temp & 0x200) != 0) {
+                       rc = -HW_EPG_QREAD_TOUT;
+                       goto done;
+               }
+               if ((temp & 0x400) != 0) {
+                       rc = -HW_EPG_QWRITE_TOUT;
+                       goto done;
+               }
+               if ((temp & 0x800) != 0) {
+                       rc = -HW_EPG_CQ_W_FULL;
+                       goto done;
+               }
+               if ((temp & 0x1000) != 0) {
+                       rc = -HW_EPG_MSG_CHKSM;
+                       goto done;
+               }
+               if ((temp & 0x2000) != 0) {
+                       rc = -HW_EPG_MTLQ_TOUT;
+                       goto done;
+               }
+       }
+
+       /* Pegs */
+
+       for (ii = 0; ii < 4; ++ii) {
+           base = PEG_NETWORK_BASE(ii);
+               address = base | CRB_REG_EX_PC;
+               NetXen_CRB_READ_CHECK_ADAPTER(address, &temp, adapter);
+               rc = netxentest_pegstuck(temp, address, PEG_LOOP, adapter);
+               if (rc != 0) {
+                       rc = -(HW_PEG0 + ii);
+                       goto done;
+               }
+       }
+
+done:
+       return (rc);
+}
+
+static int
+netxen_cis_test(netxen_adapter *adapter)
+{
+       netxen_crbword_t        temp, temp1;
+       int                     ret = CIS_TEST_OK;
+
+       /* Read CAM RAM CRB registers: producer and consumer index for
+        command descriptors. Make sure that P==C or P-C=n0,
+         where n is acceptable number (what range?)*/
+       NetXen_CRB_READ_CHECK_ADAPTER(CRB_CMD_PRODUCER_OFFSET, &temp, adapter);
+       NetXen_CRB_READ_CHECK_ADAPTER(CRB_CMD_CONSUMER_OFFSET, &temp1, adapter);
+
+       if (DIDX_DIF(temp, temp1) > CIS_WATERMARK)
+               ret = -CIS_WMARK;
+       return (ret);
+}
+
+static int
+netxen_cr_test(netxen_adapter *adapter)
+{
+
+       netxen_crbword_t        temp;
+       int                     ret = CR_TEST_OK;
+
+       NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_MODE, &temp, adapter);
+
+       if ((temp & 0x03) == 0) {
+               ret = -CR_NIU_MODE;
+               goto done;
+       }
+
+    if (adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G ||
+        adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_IMEZ ||
+        adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_HMEZ ||
+        adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_CX4)
+           NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_XGE_CONFIG_0, &temp, 
adapter);
+    else
+           NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_GB_MAC_CONFIG_0(0), &temp, 
adapter);
+
+    if ((temp & 0x5) !=        0x5)    /* Tx or Rx not enabled */
+        ret = -CR_PHY;
+
+done:
+       return (ret);
+}
+
+/*
+ * netxen_nic_ioctl ()    We provide the tcl/phanmon support through these
+ * ioctls.
+ */
+static int
+netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+        int                   err     = 0;
+        struct netxen_port      *port    = netdev->priv;
+        struct netxen_adapter_s *adapter = port->adapter;
+
+        DPRINTK(1, INFO, "doing ioctl for %s\n", netdev->name);
+        switch (cmd) {
+        case NetXen_NIC_CMD:
+                err = netxen_nic_do_ioctl(adapter, (void *) ifr->ifr_data, 
port);
+                break;
+
+        case NetXen_NIC_NAME:
+                DPRINTK(1, INFO, "ioctl cmd for NetXen\n");
+                if (ifr->ifr_data) {
+                        put_user(port->portnum, (uint16_t *)ifr->ifr_data);
+                }
+                break;
+
+                       case NetXen_NIC_SEND_TEST:
+                               err = netxen_send_test(netdev, (void 
*)ifr->ifr_data);
+                break;
+
+                       case NetXen_NIC_IRQ_TEST:
+                                err = netxen_irq_test(adapter);
+                                break;
+
+                       case NetXen_NIC_ILB_TEST:
+                                err = netxen_loopback_test(netdev, 1, (void 
*)ifr->ifr_data);
+                                break;
+
+                       case NetXen_NIC_ELB_TEST:
+                                err = netxen_loopback_test(netdev, 0, (void 
*)ifr->ifr_data);
+                                break;
+
+                       case NetXen_NIC_LINK_TEST:
+                                err = netxen_link_test(adapter);
+                                break;
+
+                       case NetXen_NIC_HW_TEST:
+                                err = netxen_hw_test(adapter);
+                                break;
+
+                       case NetXen_NIC_CIS_TEST:
+                                err = netxen_cis_test(adapter);
+                                break;
+
+                       case NetXen_NIC_CR_TEST:
+                                err = netxen_cr_test(adapter);
+                                break;
+
+                       default:
+                DPRINTK(1, INFO, "ioctl cmd %x not supported\n", cmd);
+                err = -EOPNOTSUPP;
+                break;
+        }
+
+        return err;
+}
+
+static int
+netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+        struct net_device *netdev = pci_get_drvdata(pdev);
+        struct netxen_port   *port   = netdev->priv;
+
+        netif_device_detach(netdev);
+
+        if(netif_running(netdev)) {
+                netif_carrier_off(netdev);
+                netif_stop_queue(netdev);
+                port->state = PORT_SUSPEND;
+                netxen_nic_down(port);
+        }
+
+/*        pci_save_state(pdev, port->pci_state);        */
+/*        pci_disable_device(pdev);        */
+
+        return 0;
+}
+
+static int
+netxen_nic_resume(struct pci_dev *pdev)
+{
+       uint32_t ret;
+        struct net_device *netdev = pci_get_drvdata(pdev);
+        struct netxen_port   *port = netdev->priv;
+        ret = pci_enable_device(pdev);
+        port->state = PORT_UP;
+        netif_device_attach(netdev);
+        return ret;
+}
+
+int
+netxen_nic_fill_statistics(struct netxen_adapter_s *adapter, struct 
netxen_port *port,
+                       struct netxen_statistics *netxen_stats)
+{
+       unsigned long flags;
+       void* addr;
+       if(adapter->ahw.board_type == NetXen_NIC_XGBE) {
+               write_lock_irqsave(&adapter->adapter_lock, flags);
+               netxen_nic_pci_change_crbwindow(adapter, 0);
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_TX_BYTE_CNT, 
&(netxen_stats->tx_bytes));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_TX_FRAME_CNT, 
&(netxen_stats->tx_packets));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_RX_BYTE_CNT, 
&(netxen_stats->rx_bytes));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_RX_FRAME_CNT, 
&(netxen_stats->rx_packets));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_AGGR_ERROR_CNT, 
&(netxen_stats->rx_errors));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_CRC_ERROR_CNT, 
&(netxen_stats->rx_CRC_errors));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_OVERSIZE_FRAME_ERR, 
&(netxen_stats->rx_long_length_error));
+               NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_UNDERSIZE_FRAME_ERR, 
&(netxen_stats->rx_short_length_error));
+
+               /* For reading rx_MAC_error bit different procedure */
+/*             NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_TEST_MUX_CTL, 0x15);
+               NetXen_NIC_LOCKED_READ_REG((NetXen_CRB_NIU + 0xC0), &temp);
+               netxen_stats->rx_MAC_errors = temp & 0xff; */
+
+               netxen_nic_pci_change_crbwindow(adapter, 1);
+               write_unlock_irqrestore(&adapter->adapter_lock, flags);
+       } else {
+               spin_lock_bh(&adapter->tx_lock);
+               netxen_stats->tx_bytes = port->stats.txbytes;
+               netxen_stats->tx_packets = port->stats.xmitedframes +
+                                       port->stats.xmitfinished;
+               netxen_stats->rx_bytes = port->stats.rxbytes;
+               netxen_stats->rx_packets = port->stats.no_rcv;
+               netxen_stats->rx_errors = port->stats.rcvdbadskb;
+               netxen_stats->tx_errors = port->stats.nocmddescriptor;
+               netxen_stats->rx_short_length_error = port->stats.uplcong;
+               netxen_stats->rx_long_length_error = port->stats.uphcong;
+               netxen_stats->rx_CRC_errors = 0;
+               netxen_stats->rx_MAC_errors = 0;
+               spin_unlock_bh(&adapter->tx_lock);
+       }
+       return 0;
+}
+
+int
+netxen_nic_clear_statistics(struct netxen_adapter_s *adapter,
+                               struct netxen_port *port)
+{
+       unsigned long flags;
+       void* addr;
+       int data = 0;
+
+       write_lock_irqsave(&adapter->adapter_lock, flags);
+       netxen_nic_pci_change_crbwindow(adapter, 0);
+
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_TX_BYTE_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_TX_FRAME_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_RX_BYTE_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_RX_FRAME_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_AGGR_ERROR_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_CRC_ERROR_CNT, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_OVERSIZE_FRAME_ERR, &data);
+       NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_UNDERSIZE_FRAME_ERR, &data);
+
+       netxen_nic_pci_change_crbwindow(adapter, 1);
+       write_unlock_irqrestore(&adapter->adapter_lock, flags);
+       netxen_nic_clear_stats(adapter);
+       return 0;
+}
+static int
+netxen_nic_do_ioctl(struct netxen_adapter_s *adapter, void * u_data,
+                       struct netxen_port *port)
+{
+        netxen_nic_ioctl_data_t data;
+        netxen_nic_ioctl_data_t *up_data;
+        int retval = 0;
+       struct netxen_statistics netxen_stats;
+
+        up_data = (void*)u_data;
+
+        DPRINTK(1, INFO, "doing ioctl for %p\n", adapter);
+        if (copy_from_user(&data, up_data, sizeof(data))) {
+                /* evil user tried to crash the kernel */
+                DPRINTK(1, ERR, "bad copy from userland: %d\n",
+                                 (int)sizeof(data));
+                retval = -EFAULT;
+                goto error_out;
+        }
+
+        /* Shouldn't access beyond legal limits of  "char u[64];" member */
+        if (!data.ptr && (data.size >  sizeof(data.u))) {
+                /* evil user tried to crash the kernel */
+                DPRINTK(1, ERR, "bad size: %d\n", data.size);
+                retval = -EFAULT;
+                goto error_out;
+        }
+
+        switch (data.cmd) {
+        case netxen_nic_cmd_pci_read:
+                if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
+                                                &(data.u), data.size)))
+                        goto error_out;
+                if (copy_to_user((void*)&(up_data->u), &(data.u),
+                                        data.size)) {
+                        DPRINTK(1, ERR, "bad copy to userland: %d\n",
+                                        (int)sizeof(data));
+                        retval = -EFAULT;
+                        goto error_out;
+                }
+                data.rv = 0;
+                break;
+
+        case netxen_nic_cmd_pci_write:
+                data.rv = netxen_nic_hw_write_wx(adapter, data.off,  &(data.u),
+                                            data.size);
+                break;
+
+        case netxen_nic_cmd_pci_mem_read:
+                DPRINTK(1, INFO, "doing %s for %p\n", 
"netxen_nic_cmd_pci_mm_rd",
+                                 adapter);
+                netxen_nic_pci_mem_read(adapter, data.off, &(data.u), 
data.size);
+                if (copy_to_user((void*)&(up_data->u), &(data.u), data.size)){
+                        DPRINTK(1, ERR, "bad copy to userland: %d\n",
+                                        (int)sizeof(data));
+                        retval = -EFAULT;
+                        goto error_out;
+                }
+                data.rv = 0;
+                DPRINTK(1, INFO, "read %lx\n", (unsigned long)data.u);
+                break;
+
+        case netxen_nic_cmd_pci_mem_write:
+                netxen_nic_pci_mem_write(adapter, data.off,  &(data.u),
+                                        data.size);
+                data.rv = 0; /* write always succeeds */
+                break;
+
+   case netxen_nic_cmd_pci_config_read:
+                switch(data.size) {
+                case 1:
+                        data.rv = pci_read_config_byte(adapter->ahw.pdev,
+                                                        data.off,
+                                                        (char *)&(data.u));
+                        break;
+                case 2:
+                        data.rv = pci_read_config_word(adapter->ahw.pdev,
+                                                        data.off,
+                                                        (short *)&(data.u));
+                        break;
+                case 4:
+                        data.rv = pci_read_config_dword(adapter->ahw.pdev,
+                                                        data.off,
+                                                        (u32 *)&(data.u));
+                        break;
+                }
+                if(copy_to_user((void*)&(up_data->u), &(data.u), data.size)) {
+                        DPRINTK(1, ERR, "bad copy to userland: %d\n",
+                                         (int)sizeof(data));
+                        retval = -EFAULT;
+                        goto error_out;
+                }
+                break;
+
+        case netxen_nic_cmd_pci_config_write:
+                switch(data.size) {
+                case 1:
+                        data.rv = pci_write_config_byte(adapter->ahw.pdev,
+                                                        data.off,
+                                                        *(char *)&(data.u));
+                        break;
+                case 2:
+                        data.rv = pci_write_config_word(adapter->ahw.pdev,
+                                                        data.off,
+                                                        *(short *)&(data.u));
+                        break;
+                case 4:
+                        data.rv = pci_write_config_dword(adapter->ahw.pdev,
+                                                        data.off,
+                                                        *(u32 *)&(data.u));
+                        break;
+                }
+                break;
+
+       case netxen_nic_cmd_get_stats:
+               data.rv = netxen_nic_fill_statistics(adapter, port, 
&netxen_stats);
+               if(copy_to_user((void*) (up_data->ptr), (void*)&netxen_stats,
+                               sizeof(struct netxen_statistics))) {
+                       DPRINTK(1, ERR, "bad copy to userland: %d\n",
+                                       (int)sizeof(netxen_stats));
+                        retval = -EFAULT;
+                       goto error_out;
+               }
+               up_data->rv = data.rv;
+               break;
+
+       case netxen_nic_cmd_clear_stats:
+               data.rv = netxen_nic_clear_statistics(adapter, port);
+               up_data->rv = data.rv;
+               break;
+
+        case netxen_nic_cmd_get_version:
+                if(copy_to_user((void*)&(up_data->u), 
NetXen_NIC_LINUX_VERSIONID,
+                                sizeof(NetXen_NIC_LINUX_VERSIONID))) {
+                        DPRINTK(1, ERR, "bad copy to userland: %d\n",
+                                         (int)sizeof(data));
+                        retval = -EFAULT;
+                        goto error_out;
+                }
+                break;
+
+
+        default:
+                DPRINTK(1, INFO, "bad command %d for %p\n", data.cmd, adapter);
+                retval = -EOPNOTSUPP;
+                goto error_out;
+        }
+        put_user(data.rv, &(up_data->rv));
+        DPRINTK(1, INFO, "done ioctl for %p well.\n", adapter);
+
+error_out:
+        return retval;
+
+}
+
+static int
+netxen_nic_port_read_proc(char *buf, char **start, off_t offset, int count,
+                        int *eof, void *data)
+{
+        struct net_device *netdev = (struct net_device *)data;
+        int                len = 0;
+        struct netxen_port   *port  = netdev->priv;
+
+        if (netdev == NULL) {
+                len = sprintf(buf, "No Statistics available now. Device is"
+                                   " NULL\n");
+                *eof = 1;
+                return len;
+        }
+        len  = sprintf(buf, "NetXen NIC port statistics\n");
+        len += sprintf(buf+len, "\n");
+        len += sprintf(buf+len, "Interface Name           : %s\n",
+                       netdev->name);
+        len += sprintf(buf+len, "Port Number              : %d\n",
+                       port->portnum);
+        len += sprintf(buf+len, "Bad SKB                  : %lld\n",
+                       port->stats.rcvdbadskb);
+        len += sprintf(buf+len, "Xmit called              : %lld\n",
+                       port->stats.xmitcalled);
+        len += sprintf(buf+len, "Xmited Frames            : %lld\n",
+                       port->stats.xmitedframes);
+        len += sprintf(buf+len, "Bad SKB length           : %lld\n",
+                       port->stats.badskblen);
+        len += sprintf(buf+len, "Cmd Desc Error           : %lld\n",
+                       port->stats.nocmddescriptor);
+        len += sprintf(buf+len, "Polled for Rcv           : %lld\n",
+                       port->stats.polled);
+        len += sprintf(buf+len, "Recieved Desc            : %lld\n",
+                       port->stats.no_rcv);
+        len += sprintf(buf+len, "Rcv to stack             : %lld\n",
+                       port->stats.uphappy);
+        len += sprintf(buf+len, "Stack dropped            : %lld\n",
+                       port->stats.updropped);
+        len += sprintf(buf+len, "Low congestion           : %lld\n",
+                       port->stats.uplcong);
+        len += sprintf(buf+len, "High congestion          : %lld\n",
+                       port->stats.uphcong);
+        len += sprintf(buf+len, "Medium congestion        : %lld\n",
+                       port->stats.upmcong);
+        len += sprintf(buf+len, "Rcv bad return           : %lld\n",
+                       port->stats.updunno);
+        len += sprintf(buf+len, "SKBs Freed               : %lld\n",
+                       port->stats.skbfreed);
+        len += sprintf(buf+len, "Xmit finished            : %lld\n",
+                       port->stats.xmitfinished);
+        len += sprintf(buf+len, "Tx dropped SKBs          : %lld\n",
+                       port->stats.txdropped);
+        len += sprintf(buf+len, "Tx got NULL SKBs         : %lld\n",
+                       port->stats.txnullskb);
+        len += sprintf(buf+len, "Rcv of CSUMed SKB        : %lld\n",
+                      port->stats.csummed);
+        len += sprintf(buf+len, "\n");
+        *eof = 1;
+        return len;
+}
+
+/* /proc interface to export debug info to the userland */
+static int
+netxen_nic_read_proc(char *buf, char **start, off_t offset, int count,int *eof,
+                  void *data)
+{
+        struct netxen_adapter_s *adapter = (struct netxen_adapter_s *)data;
+        int                   i, j;
+        int                   len = 0;
+
+        if (adapter == NULL) {
+                len = sprintf(buf, "No Statistics available now."
+                                   " Adapter is NULL\n");
+                *eof = 1;
+                return len;
+        }
+        len  = sprintf(buf, "NetXen NIC statistics\n");
+        len += sprintf(buf+len, "\n");
+        len += sprintf(buf+len, "Ring Statistics\n");
+        len += sprintf(buf+len, "Command Producer    : %d\n",
+                        adapter->cmdProducer);
+        len += sprintf(buf+len, "LastCommand Consumer: %d\n",
+                       adapter->lastCmdConsumer);
+        for (i = 0; i < MAX_RCV_CTX; ++i) {
+                for (j = 0; j < NUM_RCV_DESC_RINGS; j++) {
+                        len += sprintf(buf+len, "Rcv Ring %d\n", j);
+                        len += sprintf(buf+len, "\tRecieve Producer [%d]:"
+                                   " %d\n", i,
+                                   adapter->recv_ctx[i].rcv_desc[j].producer);
+                }
+                len += sprintf(buf+len, "Status(Rcv) Producer[%d]: %d\n",
+                                    i, adapter->recv_ctx[i].statusRxProducer);
+                len += sprintf(buf+len, "Status(Rcv) Consumer[%d]: %d\n",
+                                    i, adapter->recv_ctx[i].statusRxConsumer);
+        }
+        len += sprintf(buf+len, "\n");
+        len += sprintf(buf+len, "Adapter Statistics\n");
+        len += sprintf(buf+len, "Interrupts      : %lld\n",
+                        adapter->stats.ints);
+        len += sprintf(buf+len, "Host Interrupts : %lld\n",
+                        adapter->stats.hostints);
+        len += sprintf(buf+len, "Other Interrupts: %lld\n",
+                        adapter->stats.otherints);
+        len += sprintf(buf+len, "Recieve Events  : %lld\n",
+                        adapter->stats.process_rcv);
+        len += sprintf(buf+len, "Transmit        : %lld\n",
+                        adapter->stats.process_xmit);
+        len += sprintf(buf+len, "No Transmit     : %lld\n",
+                        adapter->stats.noxmitdone);
+        len += sprintf(buf+len, "Xmit csummed    : %lld\n",
+                        adapter->stats.xmitcsummed);
+        len += sprintf(buf+len, "Posted          : %lld\n",
+                        adapter->stats.post_called);
+        len += sprintf(buf+len, "Posted          : %lld\n",
+                        adapter->stats.posted);
+        len += sprintf(buf+len, "Last post count : %lld\n",
+                        adapter->stats.lastposted);
+        for (i = 0; i < MAX_RCV_CTX; ++i) {
+                for (j = 0; j < NUM_RCV_DESC_RINGS; j++) {
+                        len += sprintf(buf+len, "Rcv Ring %d\n", j);
+                        len += sprintf(buf+len, "\tfree Rx buffers[%d] : %d\n",
+                                i,
+                                adapter->recv_ctx[i].rcv_desc[j].rcv_free);
+                        len += sprintf(buf+len, "\tpending Rx[%d]  : %d\n",
+                                i,
+                                adapter->recv_ctx[i].rcv_desc[j].rcv_pending);
+                }
+        }
+        len += sprintf(buf+len, "Pending Cmd cnt : %d\n",
+                        adapter->pendingCmdCount);
+        len += sprintf(buf+len, "Free Cmd Count  : %d\n",
+                        adapter->freeCmdCount);
+        len += sprintf(buf+len, "Good SKB posts  : %lld\n",
+                        adapter->stats.goodskbposts);
+        *eof = 1;
+        return len;
+}
+
+static struct pci_driver netxen_driver = {
+        .name     = netxen_nic_driver_name,
+        .id_table = netxen_pci_tbl,
+        .probe    = netxen_nic_probe,
+        .remove   = __devexit_p(netxen_nic_remove),
+        .suspend  = netxen_nic_suspend,
+        .resume   = netxen_nic_resume
+};
+
+/* Driver Registration on NetXen card    */
+
+static int __init
+netxen_init_module(void)
+{
+        int i;
+        printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+        netxen_proc_dir_entry = proc_mkdir(netxen_nic_driver_name, proc_net);
+        if (!netxen_proc_dir_entry) {
+                printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
+                               netxen_nic_driver_name, netxen_nic_driver_name);
+                return -ENOMEM;
+        }
+        netxen_proc_dir_entry->owner = THIS_MODULE;
+
+        cmd_desc_cache = kmem_cache_create("cmd_desc_cache",
+                sizeof(cmdDescType0_t) * ((MAX_BUFFERS_PER_CMD/4)+3),
+                ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS, NULL, NULL);
+        cmd_buff_cache = kmem_cache_create("cmd_buff_cache",
+                sizeof(struct netxen_cmd_buffer), ARCH_KMALLOC_MINALIGN,
+                ARCH_KMALLOC_FLAGS, NULL, NULL);
+        for (i=0; i<NR_CPUS; i++) {
+                cmd_desc_array[i] =
+                    (cmdDescType0_t *) kmem_cache_alloc (cmd_desc_cache,
+                                                            SLAB_ATOMIC);
+                cmd_buff_array[i] =
+                    (struct netxen_cmd_buffer *) kmem_cache_alloc 
(cmd_buff_cache,
+                                                                SLAB_ATOMIC);
+        }
+
+        pci_module_init(&netxen_driver);
+
+        if (netxen_nic_probe_err != 0) {
+                for (i=0; i<NR_CPUS; i++) {
+                        if (cmd_desc_array[i])
+                                kmem_cache_free(cmd_desc_cache,
+                                                    cmd_desc_array[i]);
+                        if (cmd_buff_array[i])
+                                kmem_cache_free(cmd_buff_cache,
+                                                    cmd_buff_array[i]);
+                }
+                kmem_cache_destroy(cmd_desc_cache);
+                kmem_cache_destroy(cmd_buff_cache);
+                remove_proc_entry(netxen_proc_dir_entry->name, proc_net);
+        }
+        return netxen_nic_probe_err;
+}
+
+module_init(netxen_init_module);
+
+static void __exit
+netxen_exit_module(void)
+{
+        int i;
+       struct netxen_adapter_s *adapter;
+
+        if (tx_user_packet_data != NULL) {
+                kfree(tx_user_packet_data);
+                tx_user_packet_data = NULL;
+                tx_user_packet_length = 0;
+        }
+       for(i=0; i<MAX_NUM_CARDS; i++)
+       {
+               adapter = adapterlist[i];
+               if (adapter == NULL)
+                       continue;
+               if (adapter->netlist != NULL && adapter->netlist->netdev != 
NULL) {
+/*                     struct net_device *netdev = netxen_netlist->netdev;
+                       struct netxen_port *port = netdev->priv;
+                       struct netxen_adapter_s *adapter = port->adapter;
+*/
+                       read_lock(&adapter->adapter_lock);
+                       netxen_nic_disable_int(adapter);
+                       read_unlock(&adapter->adapter_lock);
+                       pinit_from_rom(adapter, 0);
+               }
+       }
+
+        /*
+         * Wait for some time to allow the dma to drain, if any.
+         */
+        mdelay(5);
+        pci_unregister_driver(&netxen_driver);
+        remove_proc_entry(netxen_proc_dir_entry->name, proc_net);
+        for (i=0; i<NR_CPUS; i++) {
+                if (cmd_desc_array[i])
+                        kmem_cache_free(cmd_desc_cache, cmd_desc_array[i]);
+                if (cmd_buff_array[i])
+                        kmem_cache_free(cmd_buff_cache, cmd_buff_array[i]);
+        }
+        kmem_cache_destroy(cmd_desc_cache);
+        kmem_cache_destroy(cmd_buff_cache);
+}
+module_exit(netxen_exit_module);
+

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to