summaryrefslogtreecommitdiff
path: root/drivers/staging/slicoss/slicoss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/slicoss/slicoss.c')
-rw-r--r--drivers/staging/slicoss/slicoss.c3128
1 files changed, 0 insertions, 3128 deletions
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
deleted file mode 100644
index a63d2295bd82..000000000000
--- a/drivers/staging/slicoss/slicoss.c
+++ /dev/null
@@ -1,3128 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2000-2006 Alacritech, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of Alacritech, Inc.
- *
- **************************************************************************/
-
-/*
- * FILENAME: slicoss.c
- *
- * The SLICOSS driver for Alacritech's IS-NIC products.
- *
- * This driver is supposed to support:
- *
- * Mojave cards (single port PCI Gigabit) both copper and fiber
- * Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
- * Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
- *
- * The driver was actually tested on Oasis and Kalahari cards.
- *
- *
- * NOTE: This is the standard, non-accelerated version of Alacritech's
- * IS-NIC driver.
- */
-
-#define KLUDGE_FOR_4GB_BOUNDARY 1
-#define DEBUG_MICROCODE 1
-#define DBG 1
-#define SLIC_INTERRUPT_PROCESS_LIMIT 1
-#define SLIC_OFFLOAD_IP_CHECKSUM 1
-#define STATS_TIMER_INTERVAL 2
-#define PING_TIMER_INTERVAL 1
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/netdevice.h>
-#include <linux/crc32.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-
-#include <linux/firmware.h>
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mii.h>
-#include <linux/if_vlan.h>
-#include <asm/unaligned.h>
-
-#include <linux/ethtool.h>
-#include <linux/uaccess.h>
-#include "slichw.h"
-#include "slic.h"
-
-static uint slic_first_init = 1;
-static char *slic_banner = "Alacritech SLIC Technology(tm) Server and Storage Accelerator (Non-Accelerated)";
-
-static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00";
-
-static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL };
-#define DEFAULT_INTAGG_DELAY 100
-static unsigned int rcv_count;
-
-#define DRV_NAME "slicoss"
-#define DRV_VERSION "2.0.1"
-#define DRV_AUTHOR "Alacritech, Inc. Engineering"
-#define DRV_DESCRIPTION "Alacritech SLIC Techonology(tm) "\
- "Non-Accelerated Driver"
-#define DRV_COPYRIGHT "Copyright 2000-2006 Alacritech, Inc. "\
- "All rights reserved."
-#define PFX DRV_NAME " "
-
-MODULE_AUTHOR(DRV_AUTHOR);
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_LICENSE("Dual BSD/GPL");
-
-static const struct pci_device_id slic_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) },
- { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) },
- { 0 }
-};
-
-static const struct ethtool_ops slic_ethtool_ops;
-
-MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
-
-static void slic_mcast_set_bit(struct adapter *adapter, char *address)
-{
- unsigned char crcpoly;
-
- /* Get the CRC polynomial for the mac address */
- /*
- * we use bits 1-8 (lsb), bitwise reversed,
- * msb (= lsb bit 0 before bitrev) is automatically discarded
- */
- crcpoly = ether_crc(ETH_ALEN, address) >> 23;
-
- /*
- * We only have space on the SLIC for 64 entries. Lop
- * off the top two bits. (2^6 = 64)
- */
- crcpoly &= 0x3F;
-
- /* OR in the new bit into our 64 bit mask. */
- adapter->mcastmask |= (u64)1 << crcpoly;
-}
-
-static void slic_mcast_set_mask(struct adapter *adapter)
-{
- if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) {
- /*
- * Turn on all multicast addresses. We have to do this for
- * promiscuous mode as well as ALLMCAST mode. It saves the
- * Microcode from having to keep state about the MAC
- * configuration.
- */
- slic_write32(adapter, SLIC_REG_MCASTLOW, 0xFFFFFFFF);
- slic_write32(adapter, SLIC_REG_MCASTHIGH, 0xFFFFFFFF);
- } else {
- /*
- * Commit our multicast mast to the SLIC by writing to the
- * multicast address mask registers
- */
- slic_write32(adapter, SLIC_REG_MCASTLOW,
- (u32)(adapter->mcastmask & 0xFFFFFFFF));
- slic_write32(adapter, SLIC_REG_MCASTHIGH,
- (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF));
- }
-}
-
-static void slic_timer_ping(ulong dev)
-{
- struct adapter *adapter;
- struct sliccard *card;
-
- adapter = netdev_priv((struct net_device *)dev);
- card = adapter->card;
-
- adapter->pingtimer.expires = jiffies + (PING_TIMER_INTERVAL * HZ);
- add_timer(&adapter->pingtimer);
-}
-
-/*
- * slic_link_config
- *
- * Write phy control to configure link duplex/speed
- *
- */
-static void slic_link_config(struct adapter *adapter,
- u32 linkspeed, u32 linkduplex)
-{
- u32 speed;
- u32 duplex;
- u32 phy_config;
- u32 phy_advreg;
- u32 phy_gctlreg;
-
- if (adapter->state != ADAPT_UP)
- return;
-
- if (linkspeed > LINK_1000MB)
- linkspeed = LINK_AUTOSPEED;
- if (linkduplex > LINK_AUTOD)
- linkduplex = LINK_AUTOD;
-
- if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) {
- if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) {
- /*
- * We've got a fiber gigabit interface, and register
- * 4 is different in fiber mode than in copper mode
- */
-
- /* advertise FD only @1000 Mb */
- phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD));
- /* enable PAUSE frames */
- phy_advreg |= PAR_ASYMPAUSE_FIBER;
- slic_write32(adapter, SLIC_REG_WPHY, phy_advreg);
-
- if (linkspeed == LINK_AUTOSPEED) {
- /* reset phy, enable auto-neg */
- phy_config =
- (MIICR_REG_PCR |
- (PCR_RESET | PCR_AUTONEG |
- PCR_AUTONEG_RST));
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
- } else { /* forced 1000 Mb FD*/
- /*
- * power down phy to break link
- * this may not work)
- */
- phy_config = (MIICR_REG_PCR | PCR_POWERDOWN);
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
- slic_flush_write(adapter);
- /*
- * wait, Marvell says 1 sec,
- * try to get away with 10 ms
- */
- mdelay(10);
-
- /*
- * disable auto-neg, set speed/duplex,
- * soft reset phy, powerup
- */
- phy_config =
- (MIICR_REG_PCR |
- (PCR_RESET | PCR_SPEED_1000 |
- PCR_DUPLEX_FULL));
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
- }
- } else { /* copper gigabit */
-
- /*
- * Auto-Negotiate or 1000 Mb must be auto negotiated
- * We've got a copper gigabit interface, and
- * register 4 is different in copper mode than
- * in fiber mode
- */
- if (linkspeed == LINK_AUTOSPEED) {
- /* advertise 10/100 Mb modes */
- phy_advreg =
- (MIICR_REG_4 |
- (PAR_ADV100FD | PAR_ADV100HD | PAR_ADV10FD
- | PAR_ADV10HD));
- } else {
- /*
- * linkspeed == LINK_1000MB -
- * don't advertise 10/100 Mb modes
- */
- phy_advreg = MIICR_REG_4;
- }
- /* enable PAUSE frames */
- phy_advreg |= PAR_ASYMPAUSE;
- /* required by the Cicada PHY */
- phy_advreg |= PAR_802_3;
- slic_write32(adapter, SLIC_REG_WPHY, phy_advreg);
- /* advertise FD only @1000 Mb */
- phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD));
- slic_write32(adapter, SLIC_REG_WPHY, phy_gctlreg);
-
- if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /*
- * if a Marvell PHY
- * enable auto crossover
- */
- phy_config =
- (MIICR_REG_16 | (MRV_REG16_XOVERON));
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
-
- /* reset phy, enable auto-neg */
- phy_config =
- (MIICR_REG_PCR |
- (PCR_RESET | PCR_AUTONEG |
- PCR_AUTONEG_RST));
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
- } else { /* it's a Cicada PHY */
- /* enable and restart auto-neg (don't reset) */
- phy_config =
- (MIICR_REG_PCR |
- (PCR_AUTONEG | PCR_AUTONEG_RST));
- slic_write32(adapter, SLIC_REG_WPHY,
- phy_config);
- }
- }
- } else {
- /* Forced 10/100 */
- if (linkspeed == LINK_10MB)
- speed = 0;
- else
- speed = PCR_SPEED_100;
- if (linkduplex == LINK_HALFD)
- duplex = 0;
- else
- duplex = PCR_DUPLEX_FULL;
-
- if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /*
- * if a Marvell PHY
- * disable auto crossover
- */
- phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF));
- slic_write32(adapter, SLIC_REG_WPHY, phy_config);
- }
-
- /* power down phy to break link (this may not work) */
- phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex));
- slic_write32(adapter, SLIC_REG_WPHY, phy_config);
- slic_flush_write(adapter);
- /* wait, Marvell says 1 sec, try to get away with 10 ms */
- mdelay(10);
-
- if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
- /*
- * if a Marvell PHY
- * disable auto-neg, set speed,
- * soft reset phy, powerup
- */
- phy_config =
- (MIICR_REG_PCR | (PCR_RESET | speed | duplex));
- slic_write32(adapter, SLIC_REG_WPHY, phy_config);
- } else { /* it's a Cicada PHY */
- /* disable auto-neg, set speed, powerup */
- phy_config = (MIICR_REG_PCR | (speed | duplex));
- slic_write32(adapter, SLIC_REG_WPHY, phy_config);
- }
- }
-}
-
-static int slic_card_download_gbrcv(struct adapter *adapter)
-{
- const struct firmware *fw;
- const char *file = "";
- int ret;
- u32 codeaddr;
- u32 instruction;
- int index = 0;
- u32 rcvucodelen = 0;
-
- switch (adapter->devid) {
- case SLIC_2GB_DEVICE_ID:
- file = "slicoss/oasisrcvucode.sys";
- break;
- case SLIC_1GB_DEVICE_ID:
- file = "slicoss/gbrcvucode.sys";
- break;
- default:
- return -ENOENT;
- }
-
- ret = request_firmware(&fw, file, &adapter->pcidev->dev);
- if (ret) {
- dev_err(&adapter->pcidev->dev,
- "Failed to load firmware %s\n", file);
- return ret;
- }
-
- rcvucodelen = *(u32 *)(fw->data + index);
- index += 4;
- switch (adapter->devid) {
- case SLIC_2GB_DEVICE_ID:
- if (rcvucodelen != oasis_rcv_ucode_len) {
- release_firmware(fw);
- return -EINVAL;
- }
- break;
- case SLIC_1GB_DEVICE_ID:
- if (rcvucodelen != gb_rcv_ucode_len) {
- release_firmware(fw);
- return -EINVAL;
- }
- break;
- }
- /* start download */
- slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN);
- /* download the rcv sequencer ucode */
- for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) {
- /* write out instruction address */
- slic_write32(adapter, SLIC_REG_RCV_WCS, codeaddr);
-
- instruction = *(u32 *)(fw->data + index);
- index += 4;
- /* write out the instruction data low addr */
- slic_write32(adapter, SLIC_REG_RCV_WCS, instruction);
-
- instruction = *(u8 *)(fw->data + index);
- index++;
- /* write out the instruction data high addr */
- slic_write32(adapter, SLIC_REG_RCV_WCS, instruction);
- }
-
- /* download finished */
- release_firmware(fw);
- slic_write32(adapter, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH);
- slic_flush_write(adapter);
-
- return 0;
-}
-
-MODULE_FIRMWARE("slicoss/oasisrcvucode.sys");
-MODULE_FIRMWARE("slicoss/gbrcvucode.sys");
-
-static int slic_card_download(struct adapter *adapter)
-{
- const struct firmware *fw;
- const char *file = "";
- int ret;
- u32 section;
- int thissectionsize;
- int codeaddr;
- u32 instruction;
- u32 baseaddress;
- u32 i;
- u32 numsects = 0;
- u32 sectsize[3];
- u32 sectstart[3];
- int ucode_start, index = 0;
-
- switch (adapter->devid) {
- case SLIC_2GB_DEVICE_ID:
- file = "slicoss/oasisdownload.sys";
- break;
- case SLIC_1GB_DEVICE_ID:
- file = "slicoss/gbdownload.sys";
- break;
- default:
- return -ENOENT;
- }
- ret = request_firmware(&fw, file, &adapter->pcidev->dev);
- if (ret) {
- dev_err(&adapter->pcidev->dev,
- "Failed to load firmware %s\n", file);
- return ret;
- }
- numsects = *(u32 *)(fw->data + index);
- index += 4;
- for (i = 0; i < numsects; i++) {
- sectsize[i] = *(u32 *)(fw->data + index);
- index += 4;
- }
- for (i = 0; i < numsects; i++) {
- sectstart[i] = *(u32 *)(fw->data + index);
- index += 4;
- }
- ucode_start = index;
- instruction = *(u32 *)(fw->data + index);
- index += 4;
- for (section = 0; section < numsects; section++) {
- baseaddress = sectstart[section];
- thissectionsize = sectsize[section] >> 3;
-
- for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
- /* Write out instruction address */
- slic_write32(adapter, SLIC_REG_WCS,
- baseaddress + codeaddr);
- /* Write out instruction to low addr */
- slic_write32(adapter, SLIC_REG_WCS,
- instruction);
- instruction = *(u32 *)(fw->data + index);
- index += 4;
-
- /* Write out instruction to high addr */
- slic_write32(adapter, SLIC_REG_WCS,
- instruction);
- instruction = *(u32 *)(fw->data + index);
- index += 4;
- }
- }
- index = ucode_start;
- for (section = 0; section < numsects; section++) {
- instruction = *(u32 *)(fw->data + index);
- baseaddress = sectstart[section];
- if (baseaddress < 0x8000)
- continue;
- thissectionsize = sectsize[section] >> 3;
-
- for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
- /* Write out instruction address */
- slic_write32(adapter, SLIC_REG_WCS,
- SLIC_WCS_COMPARE | (baseaddress +
- codeaddr));
- /* Write out instruction to low addr */
- slic_write32(adapter, SLIC_REG_WCS, instruction);
- instruction = *(u32 *)(fw->data + index);
- index += 4;
- /* Write out instruction to high addr */
- slic_write32(adapter, SLIC_REG_WCS, instruction);
- instruction = *(u32 *)(fw->data + index);
- index += 4;
- }
- }
- release_firmware(fw);
- /* Everything OK, kick off the card */
- mdelay(10);
-
- slic_write32(adapter, SLIC_REG_WCS, SLIC_WCS_START);
- slic_flush_write(adapter);
- /*
- * stall for 20 ms, long enough for ucode to init card
- * and reach mainloop
- */
- mdelay(20);
-
- return 0;
-}
-
-MODULE_FIRMWARE("slicoss/oasisdownload.sys");
-MODULE_FIRMWARE("slicoss/gbdownload.sys");
-
-static void slic_adapter_set_hwaddr(struct adapter *adapter)
-{
- struct sliccard *card = adapter->card;
-
- if ((adapter->card) && (card->config_set)) {
- memcpy(adapter->macaddr,
- card->config.mac_info[adapter->functionnumber].macaddr_a,
- sizeof(struct slic_config_mac));
- if (is_zero_ether_addr(adapter->currmacaddr))
- memcpy(adapter->currmacaddr, adapter->macaddr,
- ETH_ALEN);
- if (adapter->netdev)
- memcpy(adapter->netdev->dev_addr, adapter->currmacaddr,
- ETH_ALEN);
- }
-}
-
-static void slic_intagg_set(struct adapter *adapter, u32 value)
-{
- slic_write32(adapter, SLIC_REG_INTAGG, value);
- adapter->card->loadlevel_current = value;
-}
-
-static void slic_soft_reset(struct adapter *adapter)
-{
- if (adapter->card->state == CARD_UP) {
- slic_write32(adapter, SLIC_REG_QUIESCE, 0);
- slic_flush_write(adapter);
- mdelay(1);
- }
-
- slic_write32(adapter, SLIC_REG_RESET, SLIC_RESET_MAGIC);
- slic_flush_write(adapter);
-
- mdelay(1);
-}
-
-static void slic_mac_address_config(struct adapter *adapter)
-{
- u32 value;
- u32 value2;
-
- value = ntohl(*(__be32 *)&adapter->currmacaddr[2]);
- slic_write32(adapter, SLIC_REG_WRADDRAL, value);
- slic_write32(adapter, SLIC_REG_WRADDRBL, value);
-
- value2 = (u32)((adapter->currmacaddr[0] << 8 |
- adapter->currmacaddr[1]) & 0xFFFF);
-
- slic_write32(adapter, SLIC_REG_WRADDRAH, value2);
- slic_write32(adapter, SLIC_REG_WRADDRBH, value2);
-
- /*
- * Write our multicast mask out to the card. This is done
- * here in addition to the slic_mcast_addr_set routine
- * because ALL_MCAST may have been enabled or disabled
- */
- slic_mcast_set_mask(adapter);
-}
-
-static void slic_mac_config(struct adapter *adapter)
-{
- u32 value;
-
- /* Setup GMAC gaps */
- if (adapter->linkspeed == LINK_1000MB) {
- value = ((GMCR_GAPBB_1000 << GMCR_GAPBB_SHIFT) |
- (GMCR_GAPR1_1000 << GMCR_GAPR1_SHIFT) |
- (GMCR_GAPR2_1000 << GMCR_GAPR2_SHIFT));
- } else {
- value = ((GMCR_GAPBB_100 << GMCR_GAPBB_SHIFT) |
- (GMCR_GAPR1_100 << GMCR_GAPR1_SHIFT) |
- (GMCR_GAPR2_100 << GMCR_GAPR2_SHIFT));
- }
-
- /* enable GMII */
- if (adapter->linkspeed == LINK_1000MB)
- value |= GMCR_GBIT;
-
- /* enable fullduplex */
- if ((adapter->linkduplex == LINK_FULLD) ||
- (adapter->macopts & MAC_LOOPBACK)) {
- value |= GMCR_FULLD;
- }
-
- /* write mac config */
- slic_write32(adapter, SLIC_REG_WMCFG, value);
-
- /* setup mac addresses */
- slic_mac_address_config(adapter);
-}
-
-static void slic_config_set(struct adapter *adapter, bool linkchange)
-{
- u32 value;
- u32 rcr_reset;
-
- if (linkchange) {
- /* Setup MAC */
- slic_mac_config(adapter);
- rcr_reset = GRCR_RESET;
- } else {
- slic_mac_address_config(adapter);
- rcr_reset = 0;
- }
-
- if (adapter->linkduplex == LINK_FULLD) {
- /* setup xmtcfg */
- value = (GXCR_RESET | /* Always reset */
- GXCR_XMTEN | /* Enable transmit */
- GXCR_PAUSEEN); /* Enable pause */
-
- slic_write32(adapter, SLIC_REG_WXCFG, value);
-
- /* Setup rcvcfg last */
- value = (rcr_reset | /* Reset, if linkchange */
- GRCR_CTLEN | /* Enable CTL frames */
- GRCR_ADDRAEN | /* Address A enable */
- GRCR_RCVBAD | /* Rcv bad frames */
- (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
- } else {
- /* setup xmtcfg */
- value = (GXCR_RESET | /* Always reset */
- GXCR_XMTEN); /* Enable transmit */
-
- slic_write32(adapter, SLIC_REG_WXCFG, value);
-
- /* Setup rcvcfg last */
- value = (rcr_reset | /* Reset, if linkchange */
- GRCR_ADDRAEN | /* Address A enable */
- GRCR_RCVBAD | /* Rcv bad frames */
- (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
- }
-
- if (adapter->state != ADAPT_DOWN) {
- /* Only enable receive if we are restarting or running */
- value |= GRCR_RCVEN;
- }
-
- if (adapter->macopts & MAC_PROMISC)
- value |= GRCR_RCVALL;
-
- slic_write32(adapter, SLIC_REG_WRCFG, value);
-}
-
-/*
- * Turn off RCV and XMT, power down PHY
- */
-static void slic_config_clear(struct adapter *adapter)
-{
- u32 value;
- u32 phy_config;
-
- /* Setup xmtcfg */
- value = (GXCR_RESET | /* Always reset */
- GXCR_PAUSEEN); /* Enable pause */
-
- slic_write32(adapter, SLIC_REG_WXCFG, value);
-
- value = (GRCR_RESET | /* Always reset */
- GRCR_CTLEN | /* Enable CTL frames */
- GRCR_ADDRAEN | /* Address A enable */
- (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
-
- slic_write32(adapter, SLIC_REG_WRCFG, value);
-
- /* power down phy */
- phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN));
- slic_write32(adapter, SLIC_REG_WPHY, phy_config);
-}
-
-static bool slic_mac_filter(struct adapter *adapter,
- struct ether_header *ether_frame)
-{
- struct net_device *netdev = adapter->netdev;
- u32 opts = adapter->macopts;
-
- if (opts & MAC_PROMISC)
- return true;
-
- if (is_broadcast_ether_addr(ether_frame->ether_dhost)) {
- if (opts & MAC_BCAST) {
- adapter->rcv_broadcasts++;
- return true;
- }
-
- return false;
- }
-
- if (is_multicast_ether_addr(ether_frame->ether_dhost)) {
- if (opts & MAC_ALLMCAST) {
- adapter->rcv_multicasts++;
- netdev->stats.multicast++;
- return true;
- }
- if (opts & MAC_MCAST) {
- struct mcast_address *mcaddr = adapter->mcastaddrs;
-
- while (mcaddr) {
- if (ether_addr_equal(mcaddr->address,
- ether_frame->ether_dhost)) {
- adapter->rcv_multicasts++;
- netdev->stats.multicast++;
- return true;
- }
- mcaddr = mcaddr->next;
- }
-
- return false;
- }
-
- return false;
- }
- if (opts & MAC_DIRECTED) {
- adapter->rcv_unicasts++;
- return true;
- }
- return false;
-}
-
-static int slic_mac_set_address(struct net_device *dev, void *ptr)
-{
- struct adapter *adapter = netdev_priv(dev);
- struct sockaddr *addr = ptr;
-
- if (netif_running(dev))
- return -EBUSY;
- if (!adapter)
- return -EBUSY;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
-
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
-
- slic_config_set(adapter, true);
- return 0;
-}
-
-static void slic_timer_load_check(ulong cardaddr)
-{
- struct sliccard *card = (struct sliccard *)cardaddr;
- struct adapter *adapter = card->master;
- u32 load = card->events;
- u32 level = 0;
-
- if ((adapter) && (adapter->state == ADAPT_UP) &&
- (card->state == CARD_UP) && (slic_global.dynamic_intagg)) {
- if (adapter->devid == SLIC_1GB_DEVICE_ID) {
- if (adapter->linkspeed == LINK_1000MB) {
- level = 100;
- } else {
- if (load > SLIC_LOAD_5)
- level = SLIC_INTAGG_5;
- else if (load > SLIC_LOAD_4)
- level = SLIC_INTAGG_4;
- else if (load > SLIC_LOAD_3)
- level = SLIC_INTAGG_3;
- else if (load > SLIC_LOAD_2)
- level = SLIC_INTAGG_2;
- else if (load > SLIC_LOAD_1)
- level = SLIC_INTAGG_1;
- else
- level = SLIC_INTAGG_0;
- }
- if (card->loadlevel_current != level) {
- card->loadlevel_current = level;
- slic_write32(adapter, SLIC_REG_INTAGG, level);
- }
- } else {
- if (load > SLIC_LOAD_5)
- level = SLIC_INTAGG_5;
- else if (load > SLIC_LOAD_4)
- level = SLIC_INTAGG_4;
- else if (load > SLIC_LOAD_3)
- level = SLIC_INTAGG_3;
- else if (load > SLIC_LOAD_2)
- level = SLIC_INTAGG_2;
- else if (load > SLIC_LOAD_1)
- level = SLIC_INTAGG_1;
- else
- level = SLIC_INTAGG_0;
- if (card->loadlevel_current != level) {
- card->loadlevel_current = level;
- slic_write32(adapter, SLIC_REG_INTAGG, level);
- }
- }
- }
- card->events = 0;
- card->loadtimer.expires = jiffies + (SLIC_LOADTIMER_PERIOD * HZ);
- add_timer(&card->loadtimer);
-}
-
-static int slic_upr_queue_request(struct adapter *adapter,
- u32 upr_request,
- u32 upr_data,
- u32 upr_data_h,
- u32 upr_buffer, u32 upr_buffer_h)
-{
- struct slic_upr *upr;
- struct slic_upr *uprqueue;
-
- upr = kmalloc(sizeof(*upr), GFP_ATOMIC);
- if (!upr)
- return -ENOMEM;
-
- upr->adapter = adapter->port;
- upr->upr_request = upr_request;
- upr->upr_data = upr_data;
- upr->upr_buffer = upr_buffer;
- upr->upr_data_h = upr_data_h;
- upr->upr_buffer_h = upr_buffer_h;
- upr->next = NULL;
- if (adapter->upr_list) {
- uprqueue = adapter->upr_list;
-
- while (uprqueue->next)
- uprqueue = uprqueue->next;
- uprqueue->next = upr;
- } else {
- adapter->upr_list = upr;
- }
- return 0;
-}
-
-static void slic_upr_start(struct adapter *adapter)
-{
- struct slic_upr *upr;
-
- upr = adapter->upr_list;
- if (!upr)
- return;
- if (adapter->upr_busy)
- return;
- adapter->upr_busy = 1;
-
- switch (upr->upr_request) {
- case SLIC_UPR_STATS:
- if (upr->upr_data_h == 0) {
- slic_write32(adapter, SLIC_REG_RSTAT, upr->upr_data);
- } else {
- slic_write64(adapter, SLIC_REG_RSTAT64, upr->upr_data,
- upr->upr_data_h);
- }
- break;
-
- case SLIC_UPR_RLSR:
- slic_write64(adapter, SLIC_REG_LSTAT, upr->upr_data,
- upr->upr_data_h);
- break;
-
- case SLIC_UPR_RCONFIG:
- slic_write64(adapter, SLIC_REG_RCONFIG, upr->upr_data,
- upr->upr_data_h);
- break;
- case SLIC_UPR_PING:
- slic_write32(adapter, SLIC_REG_PING, 1);
- break;
- }
- slic_flush_write(adapter);
-}
-
-static int slic_upr_request(struct adapter *adapter,
- u32 upr_request,
- u32 upr_data,
- u32 upr_data_h,
- u32 upr_buffer, u32 upr_buffer_h)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&adapter->upr_lock, flags);
- rc = slic_upr_queue_request(adapter,
- upr_request,
- upr_data,
- upr_data_h, upr_buffer, upr_buffer_h);
- if (rc)
- goto err_unlock_irq;
-
- slic_upr_start(adapter);
-err_unlock_irq:
- spin_unlock_irqrestore(&adapter->upr_lock, flags);
- return rc;
-}
-
-static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
-{
- struct slic_shmemory *sm = &adapter->shmem;
- struct slic_shmem_data *sm_data = sm->shmem_data;
- u32 lst = sm_data->lnkstatus;
- uint linkup;
- unsigned char linkspeed;
- unsigned char linkduplex;
-
- if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
- dma_addr_t phaddr = sm->lnkstatus_phaddr;
-
- slic_upr_queue_request(adapter, SLIC_UPR_RLSR,
- cpu_to_le32(lower_32_bits(phaddr)),
- cpu_to_le32(upper_32_bits(phaddr)),
- 0, 0);
- return;
- }
- if (adapter->state != ADAPT_UP)
- return;
-
- linkup = lst & GIG_LINKUP ? LINK_UP : LINK_DOWN;
- if (lst & GIG_SPEED_1000)
- linkspeed = LINK_1000MB;
- else if (lst & GIG_SPEED_100)
- linkspeed = LINK_100MB;
- else
- linkspeed = LINK_10MB;
-
- if (lst & GIG_FULLDUPLEX)
- linkduplex = LINK_FULLD;
- else
- linkduplex = LINK_HALFD;
-
- if ((adapter->linkstate == LINK_DOWN) && (linkup == LINK_DOWN))
- return;
-
- /* link up event, but nothing has changed */
- if ((adapter->linkstate == LINK_UP) &&
- (linkup == LINK_UP) &&
- (adapter->linkspeed == linkspeed) &&
- (adapter->linkduplex == linkduplex))
- return;
-
- /* link has changed at this point */
-
- /* link has gone from up to down */
- if (linkup == LINK_DOWN) {
- adapter->linkstate = LINK_DOWN;
- netif_carrier_off(adapter->netdev);
- return;
- }
-
- /* link has gone from down to up */
- adapter->linkspeed = linkspeed;
- adapter->linkduplex = linkduplex;
-
- if (adapter->linkstate != LINK_UP) {
- /* setup the mac */
- slic_config_set(adapter, true);
- adapter->linkstate = LINK_UP;
- netif_carrier_on(adapter->netdev);
- }
-}
-
-static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
-{
- struct sliccard *card = adapter->card;
- struct slic_upr *upr;
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->upr_lock, flags);
- upr = adapter->upr_list;
- if (!upr) {
- spin_unlock_irqrestore(&adapter->upr_lock, flags);
- return;
- }
- adapter->upr_list = upr->next;
- upr->next = NULL;
- adapter->upr_busy = 0;
- switch (upr->upr_request) {
- case SLIC_UPR_STATS: {
- struct slic_shmemory *sm = &adapter->shmem;
- struct slic_shmem_data *sm_data = sm->shmem_data;
- struct slic_stats *stats = &sm_data->stats;
- struct slic_stats *old = &adapter->inicstats_prev;
- struct slicnet_stats *stst = &adapter->slic_stats;
-
- if (isr & ISR_UPCERR) {
- dev_err(&adapter->netdev->dev,
- "SLIC_UPR_STATS command failed isr[%x]\n", isr);
- break;
- }
-
- stst->tcp.xmit_tcp_segs +=
- stats->xmit_tcp_segs - old->xmit_tcp_segs;
-
- stst->tcp.xmit_tcp_bytes +=
- stats->xmit_tcp_bytes - old->xmit_tcp_bytes;
-
- stst->tcp.rcv_tcp_segs +=
- stats->rcv_tcp_segs - old->rcv_tcp_segs;
-
- stst->tcp.rcv_tcp_bytes +=
- stats->rcv_tcp_bytes - old->rcv_tcp_bytes;
-
- stst->iface.xmt_bytes +=
- stats->xmit_bytes - old->xmit_bytes;
-
- stst->iface.xmt_ucast +=
- stats->xmit_unicasts - old->xmit_unicasts;
-
- stst->iface.rcv_bytes +=
- stats->rcv_bytes - old->rcv_bytes;
-
- stst->iface.rcv_ucast +=
- stats->rcv_unicasts - old->rcv_unicasts;
-
- stst->iface.xmt_errors +=
- stats->xmit_collisions - old->xmit_collisions;
-
- stst->iface.xmt_errors += stats->xmit_excess_collisions -
- old->xmit_excess_collisions;
-
- stst->iface.xmt_errors +=
- stats->xmit_other_error - old->xmit_other_error;
-
- stst->iface.rcv_errors +=
- stats->rcv_other_error - old->rcv_other_error;
-
- stst->iface.rcv_discards += stats->rcv_drops - old->rcv_drops;
-
- if (stats->rcv_drops > old->rcv_drops)
- adapter->rcv_drops += (stats->rcv_drops -
- old->rcv_drops);
- memcpy(old, stats, sizeof(*stats));
- break;
- }
- case SLIC_UPR_RLSR:
- slic_link_upr_complete(adapter, isr);
- break;
- case SLIC_UPR_RCONFIG:
- break;
- case SLIC_UPR_PING:
- card->pingstatus |= (isr & ISR_PINGDSMASK);
- break;
- }
- kfree(upr);
- slic_upr_start(adapter);
- spin_unlock_irqrestore(&adapter->upr_lock, flags);
-}
-
-static int slic_config_get(struct adapter *adapter, u32 config, u32 config_h)
-{
- return slic_upr_request(adapter, SLIC_UPR_RCONFIG, config, config_h,
- 0, 0);
-}
-
-/*
- * Compute a checksum of the EEPROM according to RFC 1071.
- */
-static u16 slic_eeprom_cksum(void *eeprom, unsigned int len)
-{
- u16 *wp = eeprom;
- u32 checksum = 0;
-
- while (len > 1) {
- checksum += *(wp++);
- len -= 2;
- }
-
- if (len > 0)
- checksum += *(u8 *)wp;
-
- while (checksum >> 16)
- checksum = (checksum & 0xFFFF) + ((checksum >> 16) & 0xFFFF);
-
- return ~checksum;
-}
-
-static void slic_rspqueue_free(struct adapter *adapter)
-{
- int i;
- struct slic_rspqueue *rspq = &adapter->rspqueue;
-
- for (i = 0; i < rspq->num_pages; i++) {
- if (rspq->vaddr[i]) {
- pci_free_consistent(adapter->pcidev, PAGE_SIZE,
- rspq->vaddr[i], rspq->paddr[i]);
- }
- rspq->vaddr[i] = NULL;
- rspq->paddr[i] = 0;
- }
- rspq->offset = 0;
- rspq->pageindex = 0;
- rspq->rspbuf = NULL;
-}
-
-static int slic_rspqueue_init(struct adapter *adapter)
-{
- int i;
- struct slic_rspqueue *rspq = &adapter->rspqueue;
- u32 paddrh = 0;
-
- memset(rspq, 0, sizeof(struct slic_rspqueue));
-
- rspq->num_pages = SLIC_RSPQ_PAGES_GB;
-
- for (i = 0; i < rspq->num_pages; i++) {
- rspq->vaddr[i] = pci_zalloc_consistent(adapter->pcidev,
- PAGE_SIZE,
- &rspq->paddr[i]);
- if (!rspq->vaddr[i]) {
- dev_err(&adapter->pcidev->dev,
- "pci_alloc_consistent failed\n");
- slic_rspqueue_free(adapter);
- return -ENOMEM;
- }
-
- if (paddrh == 0) {
- slic_write32(adapter, SLIC_REG_RBAR,
- rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE);
- } else {
- slic_write64(adapter, SLIC_REG_RBAR64,
- rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE,
- paddrh);
- }
- }
- rspq->offset = 0;
- rspq->pageindex = 0;
- rspq->rspbuf = (struct slic_rspbuf *)rspq->vaddr[0];
- return 0;
-}
-
-static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
-{
- struct slic_rspqueue *rspq = &adapter->rspqueue;
- struct slic_rspbuf *buf;
-
- if (!(rspq->rspbuf->status))
- return NULL;
-
- buf = rspq->rspbuf;
- if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) {
- rspq->rsp