+
/******************************************************************************
*
* Name: skge.c
* Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.29.2.6 $
- * Date: $Date: 2001/05/21 07:59:29 $
+ * Version: $Revision: 1.63 $
+ * Date: $Date: 2003/07/15 09:26:23 $
* Purpose: The main driver source module
*
******************************************************************************/
-
+
/******************************************************************************
*
- * (C)Copyright 1998-2001 SysKonnect GmbH.
+ * (C)Copyright 1998-2003 SysKonnect GmbH.
*
* Driver for SysKonnect Gigabit Ethernet Server Adapters:
*
+ * SK-9871 (single link 1000Base-ZX)
+ * SK-9872 (dual link 1000Base-ZX)
* SK-9861 (single link 1000Base-SX, VF45 Volition Plug)
* SK-9862 (dual link 1000Base-SX, VF45 Volition Plug)
* SK-9841 (single link 1000Base-LX)
* SK-9844 (dual link 1000Base-SX)
* SK-9821 (single link 1000Base-T)
* SK-9822 (dual link 1000Base-T)
- *
- * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
+ * SK-9881 (single link 1000Base-SX V2 LC)
+ * SK-9871 (single link 1000Base-ZX V2)
+ * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug)
+ * SK-9841 (single link 1000Base-LX V2)
+ * SK-9843 (single link 1000Base-SX V2)
+ * SK-9821 (single link 1000Base-T V2)
+ *
+ * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
* SysKonnects GEnesis Solaris driver
* Author: Christoph Goos (cgoos@syskonnect.de)
* Mirko Lindner (mlindner@syskonnect.de)
* History:
*
* $Log: skge.c,v $
- * Revision x.xx.x.x 2003/06/07 02:31:17 romieu@fr.zoreil.com
- * pci api style init.
- *
+ * Revision 1.63 2003/07/15 09:26:23 rroesler
+ * Fix: Removed memory leak when sending short padded frames
+ *
+ * Revision 1.62 2003/07/09 11:11:16 rroesler
+ * Fix: Call of ReceiveIrq() performed with parameter SK_FALSE in
+ * order not to hang the system with multiple spinlocks
+ *
+ * Revision 1.61 2003/07/08 07:32:41 rroesler
+ * Fix: Correct Kernel-version
+ *
+ * Revision 1.60 2003/07/07 15:42:30 rroesler
+ * Fix: Removed function pci_present() for 2.5/2.6 kernels (deprecated)
+ * Fix: Corrected warning in GetConfiguration()
+ *
+ * Revision 1.59 2003/07/07 09:44:32 rroesler
+ * Add: HW checksumming on kernel 2.5/2.6
+ * Add: padding of short frames (<60 bytes) with 0x00 instead of 0xaa
+ * Add: ConType parameter combining multiple other parameters into one
+ * Fix: Corrected bugreport #10721 (warning when changing MTU size)
+ * Fix: Removed obsolete function SetQueueSize()
+ * Fix: Function ChangeMtuSize() returns new MTU size in kernel 2.5/2.6
+ *
+ * Revision 1.58 2003/06/17 07:14:29 mlindner
+ * Add: Disable checksum functionality
+ * Fix: Unload module (Kernel 2.5)
+ *
+ * Revision 1.57 2003/06/05 14:55:27 mlindner
+ * Fix: ProcFS creation (Kernel 2.2.x)
+ * Fix: ProcFS OWNER (Kernel 2.2.x)
+ *
+ * Revision 1.56 2003/06/03 14:34:29 mlindner
+ * Add: Additions for SK_SLIM
+ * Fix: SkGeIoctl SK_IOCTL_GEN
+ *
+ * Revision 1.55 2003/05/26 13:00:52 mlindner
+ * Add: Support for Kernel 2.5/2.6
+ * Add: Support for new IO-control MIB data structure
+ * Add: New SkOsGetTime function
+ * Fix: Race condition with broken LM80 chip
+ * Fix: Race condition with padded frames
+ *
+ * Revision 1.54 2003/04/28 13:07:27 mlindner
+ * Fix: Delay race condition with some server machines
+ *
+ * Revision 1.53 2003/04/28 12:49:49 mlindner
+ * Fix: Code optimization
+ *
+ * Revision 1.52 2003/04/28 12:24:32 mlindner
+ * Fix: Disabled HW Error IRQ on 32-bit Yukon if sensor IRQ occurs
+ *
+ * Revision 1.51 2003/04/16 08:31:14 mlindner
+ * Fix: Kernel 2.2 compilation
+ *
+ * Revision 1.49 2003/04/10 09:08:51 mlindner
+ * Add: Blink mode verification
+ * Fix: Checksum calculation
+ *
+ * Revision 1.48 2003/03/21 14:48:38 rroesler
+ * Added code for interrupt moderation
+ *
+ * Revision 1.47 2003/03/12 13:56:15 mlindner
+ * Fix: Mac update during SK_DRV_NET_UP
+ *
+ * Revision 1.46 2003/02/25 14:16:36 mlindner
+ * Fix: Copyright statement
+ *
+ * Revision 1.45 2003/02/25 13:25:55 mlindner
+ * Add: Performance improvements
+ * Add: Support for various vendors
+ * Fix: Init function
+ *
+ * Revision 1.44 2003/01/09 09:25:26 mlindner
+ * Fix: Remove useless init_module/cleanup_module forward declarations
+ *
+ * Revision 1.43 2002/11/29 08:42:41 mlindner
+ * Fix: Boot message
+ *
+ * Revision 1.42 2002/11/28 13:30:23 mlindner
+ * Add: New frame check
+ *
+ * Revision 1.41 2002/11/27 13:55:18 mlindner
+ * Fix: Drop wrong csum packets
+ * Fix: Initialize proc_entry after hw check
+ *
+ * Revision 1.40 2002/10/31 07:50:37 tschilli
+ * Function SkGeInitAssignRamToQueues() from common module inserted.
+ * Autonegotiation is set to ON for all adapters.
+ * LinkSpeedUsed is used in link up status report.
+ * Role parameter will show up for 1000 Mbps links only.
+ * GetConfiguration() inserted after init level 1 in SkGeChangeMtu().
+ * All return values of SkGeInit() and SkGeInitPort() are checked.
+ *
+ * Revision 1.39 2002/10/02 12:56:05 mlindner
+ * Add: Support for Yukon
+ * Add: Support for ZEROCOPY, scatter-gather and hw checksum
+ * Add: New transmit ring function (use SG and TCP/UDP hardware checksumming)
+ * Add: New init function
+ * Add: Speed check and setup
+ * Add: Merge source for kernel 2.2.x and 2.4.x
+ * Add: Opcode check for tcp
+ * Add: Frame length check
+ * Fix: Transmit complete interrupt
+ * Fix: Interrupt moderation
+ *
+ * Revision 1.29.2.13 2002/01/14 12:44:52 mlindner
+ * Fix: Rlmt modes
+ *
+ * Revision 1.29.2.12 2001/12/07 12:06:18 mlindner
+ * Fix: malloc -> slab changes
+ *
+ * Revision 1.29.2.11 2001/12/06 15:19:20 mlindner
+ * Add: DMA attributes
+ * Fix: Module initialisation
+ * Fix: pci_map_single and pci_unmap_single replaced
+ *
+ * Revision 1.29.2.10 2001/12/06 09:56:50 mlindner
+ * Corrected some printk's
+ *
+ * Revision 1.29.2.9 2001/09/05 12:15:34 mlindner
+ * Add: LBFO Changes
+ * Fix: Counter Errors (Jumbo == to long errors)
+ * Fix: Changed pAC->PciDev declaration
+ * Fix: too short counters
+ *
+ * Revision 1.29.2.8 2001/06/25 12:10:44 mlindner
+ * fix: ReceiveIrq() changed.
+ *
+ * Revision 1.29.2.7 2001/06/25 08:07:05 mlindner
+ * fix: RLMT locking in ReceiveIrq() changed.
+ *
* Revision 1.29.2.6 2001/05/21 07:59:29 mlindner
* fix: MTU init problems
*
* Printing "ethX:" before adapter type at adapter init.
*
*
- * 10-Feb-1999 cg Created, based on Linux' acenic.c, 3c59x.c and
+ * 10-Feb-1999 cg Created, based on Linux' acenic.c, 3c59x.c and
* SysKonnects GEnesis Solaris driver
*
******************************************************************************/
*
* Possible compiler options (#define xxx / -Dxxx):
*
- * debugging can be enable by changing SK_DEBUG_CHKMOD and
+ * debugging can be enable by changing SK_DEBUG_CHKMOD and
* SK_DEBUG_CHKCAT in makefile (described there).
*
******************************************************************************/
-
+
/******************************************************************************
*
* Description:
#include "h/skdrv1st.h"
#include "h/skdrv2nd.h"
-/* defines ******************************************************************/
-
-#define DRV_MODULE_NAME "sk98lin"
-#define PFX DRV_MODULE_NAME ": "
+/*******************************************************************************
+ *
+ * Defines
+ *
+ ******************************************************************************/
/* for debuging on x86 only */
/* #define BREAKPOINT() asm(" int $3"); */
+/* use the transmit hw checksum driver functionality */
+#define USE_SK_TX_CHECKSUM
+
+/* use the receive hw checksum driver functionality */
+#define USE_SK_RX_CHECKSUM
+
+/* use the scatter-gather functionality with sendfile() */
+#define SK_ZEROCOPY
+
/* use of a transmit complete interrupt */
#define USE_TX_COMPLETE
-/* use interrupt moderation (for tx complete only) */
-// #define USE_INT_MOD
-#define INTS_PER_SEC 1000
-
/*
* threshold for copying small receive frames
* set to 0 to avoid copying, set to 9001 to copy all frames
*/
-#define SK_COPY_THRESHOLD 200
+#define SK_COPY_THRESHOLD 50
/* number of adapters that can be configured via command line params */
#define SK_MAX_CARD_PARAM 16
+
+
/*
- * use those defines for a compile-in version of the driver instead
+ * use those defines for a compile-in version of the driver instead
* of command line parameters
*/
+// #define LINK_SPEED_A {"Auto", }
+// #define LINK_SPEED_B {"Auto", }
// #define AUTO_NEG_A {"Sense", }
// #define AUTO_NEG_B {"Sense", }
// #define DUP_CAP_A {"Both", }
// #define ROLE_A {"Auto", }
// #define ROLE_B {"Auto", }
// #define PREF_PORT {"A", }
+// #define CON_TYPE {"Auto", }
// #define RLMT_MODE {"CheckLinkState", }
#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
-/* function prototypes ******************************************************/
-static void FreeResources(struct net_device *dev);
-static int SkGeBoardInit(struct net_device *dev, SK_AC *pAC);
+
+/* Set blink mode*/
+#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \
+ SK_DUP_LED_NORMAL | \
+ SK_LED_LINK100_ON)
+
+
+/* Isr return value */
+#define SkIsrRetVar irqreturn_t
+#define SkIsrRetNone IRQ_NONE
+#define SkIsrRetHandled IRQ_HANDLED
+
+
+/*******************************************************************************
+ *
+ * Local Function Prototypes
+ *
+ ******************************************************************************/
+
+static void FreeResources(struct SK_NET_DEVICE *dev);
+static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
static SK_BOOL BoardAllocMem(SK_AC *pAC);
static void BoardFreeMem(SK_AC *pAC);
static void BoardInitMem(SK_AC *pAC);
-static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**,
- int*, SK_BOOL);
-
-static irqreturn_t SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
-static irqreturn_t SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
-static int SkGeOpen(struct net_device *dev);
-static int SkGeClose(struct net_device *dev);
-static int SkGeXmit(struct sk_buff *skb, struct net_device *dev);
-static int SkGeSetMacAddr(struct net_device *dev, void *p);
-static void SkGeSetRxMode(struct net_device *dev);
-static struct net_device_stats *SkGeStats(struct net_device *dev);
-static int SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
+static int SkGeOpen(struct SK_NET_DEVICE *dev);
+static int SkGeClose(struct SK_NET_DEVICE *dev);
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
+static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
static void GetConfiguration(SK_AC*);
static void ProductStr(SK_AC*);
static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
static void FillRxRing(SK_AC*, RX_PORT*);
static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
-static void ReceiveIrq(SK_AC*, RX_PORT*);
+static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
static void ClearAndStartRx(SK_AC*, int);
static void ClearTxIrq(SK_AC*, int, int);
static void ClearRxRing(SK_AC*, RX_PORT*);
static void ClearTxRing(SK_AC*, TX_PORT*);
-static void SetQueueSizes(SK_AC *pAC);
-static int SkGeChangeMtu(struct net_device *dev, int new_mtu);
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
static void PortReInitBmu(SK_AC*, int);
static int SkGeIocMib(DEV_NET*, unsigned int, int);
+static void StartDrvCleanupTimer(SK_AC *pAC);
+static void StopDrvCleanupTimer(SK_AC *pAC);
+static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+/*******************************************************************************
+ *
+ * Extern Function Prototypes
+ *
+ ******************************************************************************/
-static const char SK_Root_Dir_entry[] = "sk98lin";
-static struct proc_dir_entry *pSkRootDir;
+static const char SK_Root_Dir_entry[] = "sk98lin";
+static struct proc_dir_entry *pSkRootDir;
+extern int sk_proc_read( char *buffer,
+ char **buffer_location,
+ off_t offset,
+ int buffer_length,
+ int *eof,
+ void *data);
-extern struct file_operations sk_proc_fops;
+extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
+extern void SkDimDisplayModerationSettings(SK_AC *pAC);
+extern void SkDimStartModerationTimer(SK_AC *pAC);
+extern void SkDimModerate(SK_AC *pAC);
#ifdef DEBUG
static void DumpMsg(struct sk_buff*, char*);
static void DumpLong(char*, int);
#endif
-
/* global variables *********************************************************/
-static int boards_found;
-struct inode_operations SkInodeOps;
-//static struct file_operations SkFileOps; /* with open/relase */
+static const char *BootString = BOOT_STRING;
+struct SK_NET_DEVICE *SkGeRootDev = NULL;
+static int probed __initdata = 0;
/* local variables **********************************************************/
static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-spinlock_t sk_devs_lock = SPIN_LOCK_UNLOCKED;
-static int SkGeDevInit(struct net_device *dev)
-{
- DEV_NET *pNet = dev->priv;
- int ret = 0;
-
- dev->open = &SkGeOpen;
- dev->stop = &SkGeClose;
- dev->hard_start_xmit = &SkGeXmit;
- dev->get_stats = &SkGeStats;
- dev->set_multicast_list = &SkGeSetRxMode;
- dev->set_mac_address = &SkGeSetMacAddr;
- dev->do_ioctl = &SkGeIoctl;
- dev->change_mtu = &SkGeChangeMtu;
-
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR "Unable to register etherdev\n");
- ret = -ENOMEM;
- goto out;
- }
- pNet->proc = create_proc_entry(dev->name, S_IFREG | 0444, pSkRootDir);
- if (pNet->proc) {
- pNet->proc->data = dev;
- pNet->proc->owner = THIS_MODULE;
- pNet->proc->proc_fops = &sk_proc_fops;
- }
-out:
- return ret;
-}
+static struct proc_dir_entry *pSkRootDir;
-static void SkGeDevCleanUp(struct net_device *dev)
-{
- DEV_NET *pNet = dev->priv;
-
- if (pNet->proc) {
- spin_lock(&sk_devs_lock);
- pNet->proc->data = NULL;
- spin_unlock(&sk_devs_lock);
- remove_proc_entry(dev->name, pSkRootDir);
- }
- unregister_netdev(dev);
-}
/*****************************************************************************
*
- * skge_init_one - init a single instance of a SK-98xx adapter
+ * skge_probe - find all SK-98xx adapters
*
* Description:
- * This function allocates resources for an SK-98xx adapter and brings
- * it into Init 1 state.
+ * This function scans the PCI bus for SK-98xx adapters. Resources for
+ * each adapter are allocated and the adapter is brought into Init 1
+ * state.
*
* Returns:
* 0, if everything is ok
- * <0, on error
+ * !=0, on error
*/
-static int __devinit skge_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __init skge_probe (void)
{
- SK_AC *pAC;
- DEV_NET *pNet;
- unsigned long base_address;
- struct net_device *dev;
- int ret;
+ int proc_root_initialized = 0;
+ int boards_found = 0;
+ int vendor_flag = SK_FALSE;
+ SK_AC *pAC;
+ DEV_NET *pNet = NULL;
+ struct proc_dir_entry *pProcFile;
+ struct pci_dev *pdev = NULL;
+ unsigned long base_address;
+ struct SK_NET_DEVICE *dev = NULL;
+ SK_BOOL DeviceFound = SK_FALSE;
+ SK_BOOL BootStringCount = SK_FALSE;
+
+ if (probed)
+ return -ENODEV;
+ probed++;
+
+
+ while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
+
+ if (pci_enable_device(pdev)) {
+ continue;
+ }
+ dev = NULL;
+ pNet = NULL;
+
+
+ SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
+ if (!vendor_flag)
+ continue;
-#ifndef MODULE
- static int version_disp = 0;
+ /* Configure DMA attributes. */
+ if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
+ pci_set_dma_mask(pdev, (u64) 0xffffffff))
+ continue;
-if (!version_disp++)
- printk(KERN_INFO "%s\n", BOOT_STRING);
-#endif
- ret = pci_enable_device(pdev);
- if (ret)
- goto out;
- /* Configure DMA attributes. */
- if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
- ret = pci_set_dma_mask(pdev, (u64) 0xffffffff);
- if (ret) {
- printk(KERN_ERR PFX "No usable DMA configuration\n");
- goto out_disable;
+ if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) {
+ printk(KERN_ERR "Unable to allocate etherdev "
+ "structure!\n");
+ break;
}
- }
- ret = -ENOMEM;
+ if (dev->priv == NULL) {
+ printk(KERN_ERR "Unable to allocate adapter "
+ "structure!\n");
+ break;
+ }
- dev = alloc_etherdev(sizeof(DEV_NET));
- if (!dev) {
- printk(KERN_ERR "Unable to allocate etherdev structure!\n");
- goto out_disable;
- }
+ pNet = dev->priv;
+ pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+ if (pNet->pAC == NULL){
+ kfree(dev->priv);
+ printk(KERN_ERR "Unable to allocate adapter "
+ "structure!\n");
+ break;
+ }
- pNet = dev->priv;
+ /* Print message */
+ if (!BootStringCount) {
+ /* set display flag to TRUE so that */
+ /* we only display this string ONCE */
+ BootStringCount = SK_TRUE;
+ printk("%s\n", BootString);
+ }
- pAC = kmalloc(sizeof(*pAC), GFP_KERNEL);
- if (pAC == NULL){
- printk(KERN_ERR "Unable to allocate adapter structure!\n");
- goto out_free_dev;
- }
+ memset(pNet->pAC, 0, sizeof(SK_AC));
+ pAC = pNet->pAC;
+ pAC->PciDev = pdev;
+ pAC->PciDevId = pdev->device;
+ pAC->dev[0] = dev;
+ pAC->dev[1] = dev;
+ sprintf(pAC->Name, "SysKonnect SK-98xx");
+ pAC->CheckQueue = SK_FALSE;
- memset(pAC, 0, sizeof(SK_AC));
- pNet->pAC = pAC;
- pAC->PciDev = *pdev;
- pAC->PciDevId = pdev->device;
- pAC->dev[0] = dev;
- pAC->dev[1] = dev;
- sprintf(pAC->Name, "SysKonnect SK-98xx");
- pAC->CheckQueue = SK_FALSE;
-
- pNet->Mtu = 1500;
- pNet->Up = 0;
- dev->irq = pdev->irq;
+ pNet->Mtu = 1500;
+ pNet->Up = 0;
+ dev->irq = pdev->irq;
+
+ SET_MODULE_OWNER(dev);
+ dev->open = &SkGeOpen;
+ dev->stop = &SkGeClose;
+ dev->hard_start_xmit = &SkGeXmit;
+ dev->get_stats = &SkGeStats;
+ dev->set_multicast_list = &SkGeSetRxMode;
+ dev->set_mac_address = &SkGeSetMacAddr;
+ dev->do_ioctl = &SkGeIoctl;
+ dev->change_mtu = &SkGeChangeMtu;
+ dev->flags &= ~IFF_RUNNING;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* Use only if yukon hardware */
+ /* SK and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+#endif
+#endif
- SET_MODULE_OWNER(dev);
- SET_NETDEV_DEV(dev, &pdev->dev);
- ret = SkGeDevInit(dev);
- if (ret < 0)
- goto out_free_priv;
+ /*
+ * Dummy value.
+ */
+ dev->base_addr = 42;
+ pci_set_master(pdev);
- /*
- * Dummy value.
- */
- dev->base_addr = 42;
- pci_set_master(pdev);
- base_address = pci_resource_start(pdev, 0);
+ pci_set_master(pdev);
+ base_address = pci_resource_start (pdev, 0);
#ifdef SK_BIG_ENDIAN
- /*
- * On big endian machines, we use the adapter's ability of
- * reading the descriptors as big endian.
- */
- {
+ /*
+ * On big endian machines, we use the adapter's aibility of
+ * reading the descriptors as big endian.
+ */
+ {
SK_U32 our2;
- SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
- our2 |= PCI_REV_DESC;
- SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
- }
-#endif /* BIG ENDIAN */
-
- /*
- * Remap the regs into kernel space.
- */
+ SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
+ our2 |= PCI_REV_DESC;
+ SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
+ }
+#endif
- pAC->IoBase = (char*)ioremap(base_address, 0x4000);
- if (!pAC->IoBase) {
- printk(KERN_ERR PFX "unable to map I/O register. "
- "SK 98xx device disabled.\n");
- ret = -EIO;
- goto out_dev_uninit;
- }
- pAC->Index = boards_found++;
+ /*
+ * Remap the regs into kernel space.
+ */
+ pAC->IoBase = (char*)ioremap(base_address, 0x4000);
- ret = SkGeBoardInit(dev, pAC);
- if (ret < 0)
- goto out_free_resources;
+ if (!pAC->IoBase){
+ printk(KERN_ERR "%s: Unable to map I/O register, "
+ "SK 98xx No. %i will be disabled.\n",
+ dev->name, boards_found);
+ kfree(dev);
+ break;
+ }
- memcpy((caddr_t) &dev->dev_addr,
- (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+ pAC->Index = boards_found;
+ if (SkGeBoardInit(dev, pAC)) {
+ FreeResources(dev);
+ kfree(dev);
+ continue;
+ }
- pNet->PortNr = 0;
- pNet->NetNr = 0;
+ memcpy((caddr_t) &dev->dev_addr,
+ (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
- /* More then one port found */
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- struct net_device *sec_dev;
+ /* First adapter... Create proc and print message */
+ if (!DeviceFound) {
+ DeviceFound = SK_TRUE;
+ SK_MEMCPY(&SK_Root_Dir_entry, BootString,
+ sizeof(SK_Root_Dir_entry) - 1);
+
+ /*Create proc (directory)*/
+ if(!proc_root_initialized) {
+ pSkRootDir = create_proc_entry(SK_Root_Dir_entry,
+ S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
+ pSkRootDir->owner = THIS_MODULE;
+ proc_root_initialized = 1;
+ }
- sec_dev = alloc_etherdev(sizeof(DEV_NET));
- if (!sec_dev) {
- printk(KERN_ERR PFX
- "Unable to allocate etherdev structure!\n");
- ret = -ENOMEM;
- goto out_free_resources;
}
- pAC->dev[1] = sec_dev;
- pNet = sec_dev->priv;
- pNet->PortNr = 1;
- pNet->NetNr = 1;
- pNet->pAC = pAC;
- pNet->Mtu = 1500;
- pNet->Up = 0;
- ret = SkGeDevInit(sec_dev);
- if (ret < 0)
- goto out_free_secondary_dev;
- memcpy((caddr_t) &sec_dev->dev_addr,
- (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+ /* Create proc file */
+ pProcFile = create_proc_entry(dev->name,
+ S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+ pSkRootDir);
+
+
+ pProcFile->read_proc = sk_proc_read;
+ pProcFile->write_proc = NULL;
+ pProcFile->nlink = 1;
+ pProcFile->size = sizeof(dev->name + 1);
+ pProcFile->data = (void *)pProcFile;
+ pProcFile->owner = THIS_MODULE;
+
+ pNet->PortNr = 0;
+ pNet->NetNr = 0;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* SG and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+#endif
+#endif
+
+ boards_found++;
+
+ /* More then one port found */
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) {
+ printk(KERN_ERR "Unable to allocate etherdev "
+ "structure!\n");
+ break;
+ }
+
+ pAC->dev[1] = dev;
+ pNet = dev->priv;
+ pNet->PortNr = 1;
+ pNet->NetNr = 1;
+ pNet->pAC = pAC;
+ pNet->Mtu = 1500;
+ pNet->Up = 0;
+
+ dev->open = &SkGeOpen;
+ dev->stop = &SkGeClose;
+ dev->hard_start_xmit = &SkGeXmit;
+ dev->get_stats = &SkGeStats;
+ dev->set_multicast_list = &SkGeSetRxMode;
+ dev->set_mac_address = &SkGeSetMacAddr;
+ dev->do_ioctl = &SkGeIoctl;
+ dev->change_mtu = &SkGeChangeMtu;
+ dev->flags &= ~IFF_RUNNING;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* SG and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+#endif
+#endif
+
+ pProcFile = create_proc_entry(dev->name,
+ S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+ pSkRootDir);
+
+
+ pProcFile->read_proc = sk_proc_read;
+ pProcFile->write_proc = NULL;
+ pProcFile->nlink = 1;
+ pProcFile->size = sizeof(dev->name + 1);
+ pProcFile->data = (void *)pProcFile;
+ pProcFile->owner = THIS_MODULE;
+
+ memcpy((caddr_t) &dev->dev_addr,
+ (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
+
+ printk("%s: %s\n", dev->name, pAC->DeviceStr);
+ printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+
+ }
+
- printk("%s: %s\n", sec_dev->name, pAC->DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+ /* Save the hardware revision */
+ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+ (pAC->GIni.GIPciHwRev & 0x0F);
+
+ /*
+ * This is bollocks, but we need to tell the net-init
+ * code that it shall go for the next device.
+ */
+#ifndef MODULE
+ dev->base_addr = 0;
+#endif
}
- pci_set_drvdata(pdev, dev);
- ret = 0;
-out:
- return ret;
+ /*
+ * If we're at this point we're going through skge_probe() for
+ * the first time. Return success (0) if we've initialized 1
+ * or more boards. Otherwise, return failure (-ENODEV).
+ */
-out_free_secondary_dev:
- kfree(pAC->dev[1]);
-out_free_resources:
- FreeResources(dev);
-out_dev_uninit:
- SkGeDevCleanUp(dev);
-out_free_priv:
- kfree(pAC);
-out_free_dev:
- kfree(dev);
-out_disable:
- pci_disable_device(pdev);
- goto out;
+ return boards_found;
+} /* skge_probe */
-} /* skge_init_one */
/*****************************************************************************
*
* Returns: N/A
*
*/
-static void FreeResources(struct net_device *dev)
+static void FreeResources(struct SK_NET_DEVICE *dev)
{
SK_U32 AllocFlag;
DEV_NET *pNet;
} /* FreeResources */
-MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");
+MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
MODULE_LICENSE("GPL");
+MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(ConType, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
/* not used, just there because every driver should have them: */
MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
MODULE_PARM(debug, "i");
+/* used for interrupt moderation */
+MODULE_PARM(IntsPerSec, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
+MODULE_PARM(Moderation, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Stats, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(AutoSizing, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+
+#ifdef LINK_SPEED_A
+static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef LINK_SPEED_B
+static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
#ifdef AUTO_NEG_A
static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
#endif
+#ifdef CON_TYPE
+static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
+#else
+static char *ConType[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
#ifdef PREF_PORT
static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
#else
static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
#endif
-
static int debug = 0; /* not used */
static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
+static int IntsPerSec[SK_MAX_CARD_PARAM];
+static char *Moderation[SK_MAX_CARD_PARAM];
+static char *ModerationMask[SK_MAX_CARD_PARAM];
+static char *AutoSizing[SK_MAX_CARD_PARAM];
+static char *Stats[SK_MAX_CARD_PARAM];
+
+
+/*****************************************************************************
+ *
+ * skge_init_module - module initialization function
+ *
+ * Description:
+ * Very simple, only call skge_probe and return approriate result.
+ *
+ * Returns:
+ * 0, if everything is ok
+ * !=0, on error
+ */
+static int __init skge_init_module(void)
+{
+ int cards;
+ SkGeRootDev = NULL;
+
+ /* just to avoid warnings ... */
+ debug = 0;
+ options[0] = 0;
+
+ cards = skge_probe();
+ if (cards == 0) {
+ printk("sk98lin: No adapter found.\n");
+ }
+ return cards ? 0 : -ENODEV;
+} /* skge_init_module */
+
+
/*****************************************************************************
*
- * skge_remove_one - remove a single instance of a SK-98xx adapter
+ * skge_cleanup_module - module unload function
*
* Description:
* Disable adapter if it is still running, free resources,
*
* Returns: N/A
*/
-static void __devexit skge_remove_one(struct pci_dev *pdev)
+static void __exit skge_cleanup_module(void)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = dev->priv;
- SK_AC *pAC = pNet->pAC;
- unsigned long Flags;
- SK_EVPARA EvPara;
+DEV_NET *pNet;
+SK_AC *pAC;
+struct SK_NET_DEVICE *next;
+unsigned long Flags;
+SK_EVPARA EvPara;
+ while (SkGeRootDev) {
+ pNet = (DEV_NET*) SkGeRootDev->priv;
+ pAC = pNet->pAC;
+ next = pAC->Next;
- netif_stop_queue(dev);
- SkGeYellowLED(pAC, pAC->IoBase, 0);
- if (pNet->proc) {
- spin_lock(&sk_devs_lock);
- pNet->proc->data = NULL;
- spin_unlock(&sk_devs_lock);
- remove_proc_entry(dev->name, pSkRootDir);
- }
+ netif_stop_queue(SkGeRootDev);
+ SkGeYellowLED(pAC, pAC->IoBase, 0);
- if (pAC->BoardLevel == 2) {
- /* board is still alive */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- EvPara.Para32[0] = 0;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- SkGeDeInit(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- pAC->BoardLevel = 0;
- /* We do NOT check here, if IRQ was pending, of course*/
- }
+ if(pAC->BoardLevel == SK_INIT_RUN) {
+ /* board is still alive */
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ EvPara.Para32[0] = 0;
+ EvPara.Para32[1] = -1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+ EvPara.Para32[0] = 1;
+ EvPara.Para32[1] = -1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+ SkEventDispatcher(pAC, pAC->IoBase);
+ /* disable interrupts */
+ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+ SkGeDeInit(pAC, pAC->IoBase);
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ pAC->BoardLevel = SK_INIT_DATA;
+ /* We do NOT check here, if IRQ was pending, of course*/
+ }
- if (pAC->BoardLevel == 1) {
- /* board is still alive */
- SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = 0;
- }
+ if(pAC->BoardLevel == SK_INIT_IO) {
+ /* board is still alive */
+ SkGeDeInit(pAC, pAC->IoBase);
+ pAC->BoardLevel = SK_INIT_DATA;
+ }
+
+ if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
+ unregister_netdev(pAC->dev[1]);
+ kfree(pAC->dev[1]);
+ }
- if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) {
- SkGeDevCleanUp(pAC->dev[1]);
- kfree(pAC->dev[1]);
+ FreeResources(SkGeRootDev);
+
+ SkGeRootDev->get_stats = NULL;
+ /*
+ * otherwise unregister_netdev calls get_stats with
+ * invalid IO ... :-(
+ */
+ unregister_netdev(SkGeRootDev);
+ kfree(SkGeRootDev);
+ kfree(pAC);
+ SkGeRootDev = next;
}
- FreeResources(dev);
+ /* clear proc-dir */
+ remove_proc_entry(pSkRootDir->name, proc_net);
+
+} /* skge_cleanup_module */
+
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
- dev->get_stats = NULL;
- /*
- * otherwise unregister_netdev calls get_stats with
- * invalid IO ... :-(
- */
- unregister_netdev(dev);
- kfree(dev);
- kfree(pAC);
- boards_found--;
-} /* skge_remove_one */
/*****************************************************************************
*
* 0, if everything is ok
* !=0, on error
*/
-static int __init SkGeBoardInit(struct net_device *dev, SK_AC *pAC)
+static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
short i;
unsigned long Flags;
char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
char *VerStr = VER_STRING;
int Ret; /* return code of request_irq */
+SK_BOOL DualNet;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
}
/* Initialize the mutexes */
-
for (i=0; i<SK_MAX_MACS; i++) {
spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
/* Does a RESET on board ...*/
- if (SkGeInit(pAC, pAC->IoBase, 0) != 0) {
+ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
printk("HWInit (0) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
return(-EAGAIN);
}
- SkI2cInit( pAC, pAC->IoBase, 0);
- SkEventInit(pAC, pAC->IoBase, 0);
- SkPnmiInit( pAC, pAC->IoBase, 0);
- SkAddrInit( pAC, pAC->IoBase, 0);
- SkRlmtInit( pAC, pAC->IoBase, 0);
- SkTimerInit(pAC, pAC->IoBase, 0);
+ SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
+ SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
+ SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
+ SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
+ SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
- pAC->BoardLevel = 0;
- pAC->RxBufSize = ETH_BUF_SIZE;
+ pAC->BoardLevel = SK_INIT_DATA;
+ pAC->RxBufSize = ETH_BUF_SIZE;
SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
/* level 1 init common modules here (HW init) */
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {
+ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
printk("HWInit (1) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
return(-EAGAIN);
}
- SkI2cInit( pAC, pAC->IoBase, 1);
- SkEventInit(pAC, pAC->IoBase, 1);
- SkPnmiInit( pAC, pAC->IoBase, 1);
- SkAddrInit( pAC, pAC->IoBase, 1);
- SkRlmtInit( pAC, pAC->IoBase, 1);
- SkTimerInit(pAC, pAC->IoBase, 1);
+ SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+ SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
GetConfiguration(pAC);
if (pAC->RlmtNets == 2) {
pAC->GIni.GIPortUsage = SK_MUL_LINK;
}
-
- pAC->BoardLevel = 1;
+ pAC->BoardLevel = SK_INIT_IO;
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
if (pAC->GIni.GIMacsFound == 2) {
Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
pAC->Name, dev);
} else {
- printk(KERN_WARNING "%s: illegal number of ports: %d\n",
+ printk(KERN_WARNING "%s: Invalid number of ports: %d\n",
dev->name, pAC->GIni.GIMacsFound);
return -EAGAIN;
}
+
if (Ret) {
- printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
+ printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n",
dev->name, dev->irq);
return -EAGAIN;
}
/* Alloc memory for this board (Mem for RxD/TxD) : */
if(!BoardAllocMem(pAC)) {
- printk("No memory for descriptor rings\n");
+ printk("No memory for descriptor rings.\n");
return(-EAGAIN);
}
pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
BoardInitMem(pAC);
-
- SetQueueSizes(pAC);
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+ if (pAC->RlmtNets == 2) {
+ DualNet = SK_TRUE;
+ }
+
+ if (SkGeInitAssignRamToQueues(
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+ BoardFreeMem(pAC);
+ printk("SkGeInitAssignRamToQueues failed.\n");
+ return(-EAGAIN);
+ }
/* Print adapter specific string from vpd */
ProductStr(pAC);
printk(" PrefPort:%c RlmtMode:%s\n",
'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
(pAC->RlmtMode==0) ? "Check Link State" :
- ((pAC->RlmtMode==1) ? "Check Link State" :
- ((pAC->RlmtMode==3) ? "Check Local Port" :
- ((pAC->RlmtMode==7) ? "Check Segmentation" :
+ ((pAC->RlmtMode==1) ? "Check Link State" :
+ ((pAC->RlmtMode==3) ? "Check Local Port" :
+ ((pAC->RlmtMode==7) ? "Check Segmentation" :
((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
SkGeYellowLED(pAC, pAC->IoBase, 1);
+ /*
+ * Register the device here
+ */
+ pAC->Next = SkGeRootDev;
+ SkGeRootDev = dev;
+
return (0);
} /* SkGeBoardInit */
AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+ RX_RING_SIZE + 8;
#endif
- pDescrMem = pci_alloc_consistent(&pAC->PciDev, AllocLength,
+
+ pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
&pAC->pDescrMemDMA);
+
if (pDescrMem == NULL) {
return (SK_FALSE);
}
pAC->pDescrMem = pDescrMem;
+ BusAddr = (unsigned long) pAC->pDescrMemDMA;
/* Descriptors need 8 byte alignment, and this is ensured
* by pci_alloc_consistent.
*/
- BusAddr = (unsigned long) pAC->pDescrMemDMA;
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n",
AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+ RX_RING_SIZE + 8;
#endif
- pci_free_consistent(&pAC->PciDev, AllocLength,
+
+ pci_free_consistent(pAC->PciDev, AllocLength,
pAC->pDescrMem, pAC->pDescrMemDMA);
pAC->pDescrMem = NULL;
} /* BoardFreeMem */
DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
DESCR_ALIGN;
DescrNum = TX_RING_SIZE / DescrSize;
- }
- else {
+ } else {
DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
DESCR_ALIGN;
DescrNum = RX_RING_SIZE / DescrSize;
pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
pDescr->pNextRxd = pNextDescr;
pDescr->TcpSumStarts = pAC->CsOfs;
- /* advance on step */
+
+ /* advance one step */
pPrevDescr = pDescr;
pDescr = pNextDescr;
pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
("PortReInitBmu "));
/* set address of first descriptor of ring in BMU */
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+
- TX_Q_CUR_DESCR_LOW,
+ SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
(uint32_t)(((caddr_t)
(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+
- TX_Q_DESCR_HIGH,
+ SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
(uint32_t)(((caddr_t)
(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW,
+ SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
pAC->RxPort[PortIndex].pRxDescrRing +
pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH,
+ SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
pAC->RxPort[PortIndex].pRxDescrRing +
pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
* Returns: N/A
*
*/
-static irqreturn_t SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
{
-struct net_device *dev = (struct net_device *)dev_id;
-
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
DEV_NET *pNet;
SK_AC *pAC;
SK_U32 IntSrc; /* interrupts source register contents */
*/
SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
if (IntSrc == 0) {
- return IRQ_NONE;
+ return SkIsrRetNone;
}
while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
#if 0 /* software irq currently not used */
- if (IntSrc & IRQ_SW) {
+ if (IntSrc & IS_IRQ_SW) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("Software IRQ\n"));
}
#endif
- if (IntSrc & IRQ_EOF_RX1) {
+ if (IntSrc & IS_R1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- SK_PNMI_CNT_RX_INTR(pAC,0);
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
}
- if (IntSrc & IRQ_EOF_RX2) {
+ if (IntSrc & IS_R2_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX2 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[1]);
- SK_PNMI_CNT_RX_INTR(pAC,1);
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 1);
}
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IRQ_EOF_AS_TX1) {
+ if (IntSrc & IS_XA1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
}
- if (IntSrc & IRQ_EOF_AS_TX2) {
+ if (IntSrc & IS_XA2_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
}
#if 0 /* only if sync. queues used */
- if (IntSrc & IRQ_EOF_SY_TX1) {
+ if (IntSrc & IS_XS1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
}
- if (IntSrc & IRQ_EOF_SY_TX2) {
+ if (IntSrc & IS_XS2_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
}
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
/* do all IO at once */
- if (IntSrc & IRQ_EOF_RX1)
+ if (IntSrc & IS_R1_F)
ClearAndStartRx(pAC, 0);
- if (IntSrc & IRQ_EOF_RX2)
+ if (IntSrc & IS_R2_F)
ClearAndStartRx(pAC, 1);
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IRQ_EOF_AS_TX1)
+ if (IntSrc & IS_XA1_F)
ClearTxIrq(pAC, 0, TX_PRIO_LOW);
- if (IntSrc & IRQ_EOF_AS_TX2)
+ if (IntSrc & IS_XA2_F)
ClearTxIrq(pAC, 1, TX_PRIO_LOW);
#endif
SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
} /* while (IntSrc & IRQ_MASK != 0) */
+ IntSrc &= pAC->GIni.GIValIrqMask;
if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ\n"));
+ ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
pAC->CheckQueue = SK_FALSE;
spin_lock(&pAC->SlowPathLock);
if (IntSrc & SPECIAL_IRQS)
SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
SkEventDispatcher(pAC, pAC->IoBase);
spin_unlock(&pAC->SlowPathLock);
}
/*
- * do it all again is case we cleared an interrupt that
+ * do it all again is case we cleared an interrupt that
* came in after handling the ring (OUTs may be delayed
* in hardware buffers, but are through after IN)
+ *
+ * rroesler: has been commented out and shifted to
+ * SkGeDrvEvent(), because it is timer
+ * guarded now
+ *
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
*/
- // ReceiveIrq(pAC, &pAC->RxPort[pAC->ActivePort]);
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- ReceiveIrq(pAC, &pAC->RxPort[1]);
-
-
-
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
- spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0 /* only if sync. queues used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-
- spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+ if (pAC->CheckQueue) {
+ pAC->CheckQueue = SK_FALSE;
+ spin_lock(&pAC->SlowPathLock);
+ SkEventDispatcher(pAC, pAC->IoBase);
+ spin_unlock(&pAC->SlowPathLock);
+ }
/* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- return IRQ_HANDLED;
+ return SkIsrRetHandled;
} /* SkGeIsr */
* Returns: N/A
*
*/
-static irqreturn_t SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
+static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
{
-struct net_device *dev = (struct net_device *)dev_id;
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
DEV_NET *pNet;
SK_AC *pAC;
SK_U32 IntSrc; /* interrupts source register contents */
*/
SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
if (IntSrc == 0) {
- return IRQ_NONE;
+ return SkIsrRetNone;
}
-
+
while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
#if 0 /* software irq currently not used */
- if (IntSrc & IRQ_SW) {
+ if (IntSrc & IS_IRQ_SW) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("Software IRQ\n"));
}
#endif
- if (IntSrc & IRQ_EOF_RX1) {
+ if (IntSrc & IS_R1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- SK_PNMI_CNT_RX_INTR(pAC,0);
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
}
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IRQ_EOF_AS_TX1) {
+ if (IntSrc & IS_XA1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
}
#if 0 /* only if sync. queues used */
- if (IntSrc & IRQ_EOF_SY_TX1) {
+ if (IntSrc & IS_XS1_F) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
}
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
/* do all IO at once */
- if (IntSrc & IRQ_EOF_RX1)
+ if (IntSrc & IS_R1_F)
ClearAndStartRx(pAC, 0);
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IRQ_EOF_AS_TX1)
+ if (IntSrc & IS_XA1_F)
ClearTxIrq(pAC, 0, TX_PRIO_LOW);
#endif
SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
} /* while (IntSrc & IRQ_MASK != 0) */
+ IntSrc &= pAC->GIni.GIValIrqMask;
if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ\n"));
+ ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
pAC->CheckQueue = SK_FALSE;
spin_lock(&pAC->SlowPathLock);
if (IntSrc & SPECIAL_IRQS)
SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
SkEventDispatcher(pAC, pAC->IoBase);
spin_unlock(&pAC->SlowPathLock);
}
/*
- * do it all again is case we cleared an interrupt that
+ * do it all again is case we cleared an interrupt that
* came in after handling the ring (OUTs may be delayed
* in hardware buffers, but are through after IN)
+ *
+ * rroesler: has been commented out and shifted to
+ * SkGeDrvEvent(), because it is timer
+ * guarded now
+ *
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
*/
- ReceiveIrq(pAC, &pAC->RxPort[0]);
-
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0 /* only if sync. queues used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
/* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- return IRQ_HANDLED;
+ return SkIsrRetHandled;
} /* SkGeIsrOnePort */
* != 0 on error
*/
static int SkGeOpen(
-struct net_device *dev)
+struct SK_NET_DEVICE *dev)
{
-DEV_NET *pNet;
-SK_AC *pAC;
-unsigned long Flags; /* for spin lock */
-int i;
-SK_EVPARA EvPara; /* an event parameter union */
+ DEV_NET *pNet;
+ SK_AC *pAC;
+ unsigned long Flags; /* for spin lock */
+ int i;
+ SK_EVPARA EvPara; /* an event parameter union */
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
- if (pAC->BoardLevel == 0) {
+
+ /* Set blink mode */
+ if (pAC->PciDev->vendor == 0x1186)
+ pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
+
+ if (pAC->BoardLevel == SK_INIT_DATA) {
/* level 1 init common modules here */
- if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {
- printk("%s: HWInit(1) failed\n", pAC->dev[pNet->PortNr]->name);
+ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+ printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
return (-1);
}
- SkI2cInit (pAC, pAC->IoBase, 1);
- SkEventInit (pAC, pAC->IoBase, 1);
- SkPnmiInit (pAC, pAC->IoBase, 1);
- SkAddrInit (pAC, pAC->IoBase, 1);
- SkRlmtInit (pAC, pAC->IoBase, 1);
- SkTimerInit (pAC, pAC->IoBase, 1);
- pAC->BoardLevel = 1;
- }
-
- if (pAC->BoardLevel != 2) {
- /* level 2 init modules here */
- SkGeInit (pAC, pAC->IoBase, 2);
- SkI2cInit (pAC, pAC->IoBase, 2);
- SkEventInit (pAC, pAC->IoBase, 2);
- SkPnmiInit (pAC, pAC->IoBase, 2);
- SkAddrInit (pAC, pAC->IoBase, 2);
- SkRlmtInit (pAC, pAC->IoBase, 2);
- SkTimerInit (pAC, pAC->IoBase, 2);
- pAC->BoardLevel = 2;
+ SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkEventInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO);
+ pAC->BoardLevel = SK_INIT_IO;
}
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- /* Enable transmit descriptor polling. */
+
+ if (pAC->BoardLevel != SK_INIT_RUN) {
+ /* tschilling: Level 2 init modules here, check return value. */
+ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
+ printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+ return (-1);
+ }
+ SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN);
+ pAC->BoardLevel = SK_INIT_RUN;
+ }
+
+ for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+ /* Enable transmit descriptor polling. */
SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
FillRxRing(pAC, &pAC->RxPort[i]);
}
SkGeYellowLED(pAC, pAC->IoBase, 1);
-#ifdef USE_INT_MOD
-/* moderate only TX complete interrupts (these are not time critical) */
-#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2)
- {
- unsigned long ModBase;
- ModBase = 53125000 / INTS_PER_SEC;
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK);
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
- }
-#endif
+ StartDrvCleanupTimer(pAC);
+ SkDimEnableModerationIfNeeded(pAC);
+ SkDimDisplayModerationSettings(pAC);
+
+ pAC->GIni.GIValIrqMask &= IRQ_MASK;
/* enable Interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
pAC->MaxPorts++;
pNet->Up = 1;
+ try_module_get(THIS_MODULE);
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeOpen suceeded\n"));
* error code - on error
*/
static int SkGeClose(
-struct net_device *dev)
+struct SK_NET_DEVICE *dev)
{
-DEV_NET *pNet;
-SK_AC *pAC;
+ DEV_NET *pNet;
+ SK_AC *pAC;
-unsigned long Flags; /* for spin lock */
-int i;
-int PortIdx;
-SK_EVPARA EvPara;
+ unsigned long Flags; /* for spin lock */
+ int i;
+ int PortIdx;
+ SK_EVPARA EvPara;
netif_stop_queue(dev);
-
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
- /*
+ StopDrvCleanupTimer(pAC);
+
+ /*
* Clear multicast table, promiscuous mode ....
*/
-
SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
SK_PROM_MODE_NONE);
SK_OUT32(pAC->IoBase, B0_IMSK, 0);
/* stop the hardware */
SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = 0;
+ pAC->BoardLevel = SK_INIT_DATA;
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
} else {
/* Stop port */
spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
[TX_PRIO_LOW].TxDesRingLock, Flags);
- SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
+ SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
SK_STOP_ALL, SK_HARD_RST);
spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
[TX_PRIO_LOW].TxDesRingLock, Flags);
}
+
if (pAC->RlmtNets == 1) {
/* clear all descriptor rings */
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i]);
+ ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[i]);
ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
}
} else {
/* clear port descriptor rings */
- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr]);
+ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
}
pAC->MaxPorts--;
pNet->Up = 0;
-
+
+ module_put(THIS_MODULE);
return (0);
} /* SkGeClose */
+
/*****************************************************************************
*
* SkGeXmit - Linux frame transmit function
* WARNING: returning 1 in 'tbusy' case caused system crashes (double
* allocated skb's) !!!
*/
-static int SkGeXmit(struct sk_buff *skb, struct net_device *dev)
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet;
SK_AC *pAC;
int Rc; /* return code of XmitFrame */
-
+
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
- if (pAC->RlmtNets == 2)
- Rc = XmitFrame(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], skb);
- else
- Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);
+ if ((!skb_shinfo(skb)->nr_frags) ||
+ (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+ /* Don't activate scatter-gather and hardware checksum */
+
+ if (pAC->RlmtNets == 2)
+ Rc = XmitFrame(
+ pAC,
+ &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+ skb);
+ else
+ Rc = XmitFrame(
+ pAC,
+ &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+ skb);
+ } else {
+ /* scatter-gather and hardware TCP checksumming anabled*/
+ if (pAC->RlmtNets == 2)
+ Rc = XmitFrameSG(
+ pAC,
+ &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+ skb);
+ else
+ Rc = XmitFrameSG(
+ pAC,
+ &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+ skb);
+ }
/* Transmitter out of resources? */
- if (Rc <= 0)
+ if (Rc <= 0) {
netif_stop_queue(dev);
+ }
/* If not taken, give buffer ownership back to the
* queueing layer.
* if necessary.
*
* Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
+ * > 0 - on succes: the number of bytes in the message
+ * = 0 - on resource shortage: this frame sent or dropped, now
+ * the ring is full ( -> set tbusy)
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
*/
static int XmitFrame(
-SK_AC *pAC, /* pointer to adapter context */
+SK_AC *pAC, /* pointer to adapter context */
TX_PORT *pTxPort, /* pointer to struct of port to send to */
-struct sk_buff *pMessage) /* pointer to send-message */
+struct sk_buff *pMessage) /* pointer to send-message */
{
-TXD *pTxd; /* the rxd to fill */
-unsigned long Flags;
-SK_U64 PhysAddr;
-int BytesSend;
+ TXD *pTxd; /* the rxd to fill */
+ TXD *pOldTxd;
+ unsigned long Flags;
+ SK_U64 PhysAddr;
+ int Protocol;
+ int IpHeaderLength;
+ int BytesSend = pMessage->len;
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("X"));
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-
+#ifndef USE_TX_COMPLETE
+ FreeTxDescriptors(pAC, pTxPort);
+#endif
if (pTxPort->TxdRingFree == 0) {
- /* no enough free descriptors in ring at the moment */
+ /*
+ ** no enough free descriptors in ring at the moment.
+ ** Maybe free'ing some old one help?
+ */
FreeTxDescriptors(pAC, pTxPort);
if (pTxPort->TxdRingFree == 0) {
spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_TX_PROGRESS,
("XmitFrame failed\n"));
- /* this message can not be sent now */
+ /*
+ ** the desired message can not be sent
+ ** Because tbusy seems to be set, the message
+ ** should not be freed here. It will be used
+ ** by the scheduler of the ethernet handler
+ */
return (-1);
}
}
- /* advance head counter behind descriptor needed for this frame */
+
+ /*
+ ** If the passed socket buffer is of smaller MTU-size than 60,
+ ** copy everything into new buffer and fill all bytes between
+ ** the original packet end and the new packet end of 60 with 0x00.
+ ** This is to resolve faulty padding by the HW with 0xaa bytes.
+ */
+ if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
+ skb_put(pMessage, (C_LEN_ETHERNET_MINSIZE-BytesSend));
+ memset( ((void *)(pMessage->data))+BytesSend,
+ 0, C_LEN_ETHERNET_MINSIZE-BytesSend);
+ }
+
+ /*
+ ** advance head counter behind descriptor needed for this frame,
+ ** so that needed descriptor is reserved from that on. The next
+ ** action will be to add the passed buffer to the TX-descriptor
+ */
pTxd = pTxPort->pTxdRingHead;
pTxPort->pTxdRingHead = pTxd->pNextTxd;
pTxPort->TxdRingFree--;
- /* the needed descriptor is reserved now */
-
- /*
- * everything allocated ok, so add buffer to descriptor
- */
#ifdef SK_DUMP_TX
DumpMsg(pMessage, "XmitFrame");
#endif
- /* set up descriptor and CONTROL dword */
- PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data &
- ~PAGE_MASK),
- pMessage->len,
- PCI_DMA_TODEVICE);
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ /*
+ ** First step is to map the data to be sent via the adapter onto
+ ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
+ ** and 2.6 need to use pci_map_page() for that mapping.
+ */
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMessage->data),
+ ((unsigned long) pMessage->data & ~PAGE_MASK),
+ pMessage->len,
+ PCI_DMA_TODEVICE);
+ pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pTxd->pMBuf = pMessage;
- pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF |
- TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE |
+ pTxd->pMBuf = pMessage;
+
+ if (pMessage->ip_summed == CHECKSUM_HW) {
+ Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xf);
+ if ((Protocol == C_PROTO_ID_TCP) && (pAC->GIni.GIChipRev != 0)) {
+ pTxd->TBControl = BMU_UDP_CHECK;
+ } else {
+ pTxd->TBControl = BMU_TCP_CHECK ;
+ }
+
+ IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER];
+ IpHeaderLength = (IpHeaderLength & 0xf) * 4;
+ pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */
+ pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
+ C_OFFSET_TCPHEADER_TCPCS;
+ pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+
+ pTxd->TBControl |= BMU_OWN | BMU_STF |
+ BMU_SW | BMU_EOF |
#ifdef USE_TX_COMPLETE
- TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len;
-#else
- TX_CTRL_EOF | pMessage->len;
+ BMU_IRQ_EOF |
#endif
-
- if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {
- /* previous descriptor already done, so give tx start cmd */
- /* StartTx(pAC, pTxPort->HwAddr); */
- SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);
+ pMessage->len;
+ } else {
+ pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK |
+ BMU_SW | BMU_EOF |
+#ifdef USE_TX_COMPLETE
+ BMU_IRQ_EOF |
+#endif
+ pMessage->len;
}
- pTxPort->pTxdRingPrev = pTxd;
-
-
- BytesSend = pMessage->len;
- /* after releasing the lock, the skb may be immidiately freed */
+
+ /*
+ ** If previous descriptor already done, give TX start cmd
+ */
+ pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
+ if ((pOldTxd->TBControl & BMU_OWN) == 0) {
+ SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+ }
+
+ /*
+ ** after releasing the lock, the skb may immediately be free'd
+ */
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
if (pTxPort->TxdRingFree != 0) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
return (BytesSend);
- }
- else {
- /* ring full: set tbusy on return */
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+ } else {
return (0);
}
+
} /* XmitFrame */
+/*****************************************************************************
+ *
+ * XmitFrameSG - fill one socket buffer into the transmit ring
+ * (use SG and TCP/UDP hardware checksumming)
+ *
+ * Description:
+ * This function puts a message into the transmit descriptor ring
+ * if there is a descriptors left.
+ *
+ * Returns:
+ * > 0 - on succes: the number of bytes in the message
+ * = 0 - on resource shortage: this frame sent or dropped, now
+ * the ring is full ( -> set tbusy)
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+static int XmitFrameSG(
+SK_AC *pAC, /* pointer to adapter context */
+TX_PORT *pTxPort, /* pointer to struct of port to send to */
+struct sk_buff *pMessage) /* pointer to send-message */
+{
+
+ TXD *pTxd;
+ TXD *pTxdFst;
+ TXD *pTxdLst;
+ int CurrFrag;
+ int BytesSend;
+ int IpHeaderLength;
+ int Protocol;
+ skb_frag_t *sk_frag;
+ SK_U64 PhysAddr;
+ unsigned long Flags;
+
+ spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+#ifndef USE_TX_COMPLETE
+ FreeTxDescriptors(pAC, pTxPort);
+#endif
+ if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+ FreeTxDescriptors(pAC, pTxPort);
+ if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+ SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_TX_PROGRESS,
+ ("XmitFrameSG failed - Ring full\n"));
+ /* this message can not be sent now */
+ return(-1);
+ }
+ }
+
+ pTxd = pTxPort->pTxdRingHead;
+ pTxdFst = pTxd;
+ pTxdLst = pTxd;
+ BytesSend = 0;
+ Protocol = 0;
+
+ /*
+ ** Map the first fragment (header) into the DMA-space
+ */
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMessage->data),
+ ((unsigned long) pMessage->data & ~PAGE_MASK),
+ skb_headlen(pMessage),
+ PCI_DMA_TODEVICE);
+
+ pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+
+ /*
+ ** Does the HW need to evaluate checksum for TCP or UDP packets?
+ */
+ if (pMessage->ip_summed == CHECKSUM_HW) {
+ pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage);
+ /*
+ ** We have to use the opcode for tcp here, because the
+ ** opcode for udp is not working in the hardware yet
+ ** (Revision 2.0)
+ */
+ Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xf);
+ if ((Protocol == C_PROTO_ID_TCP) && (pAC->GIni.GIChipRev != 0)) {
+ pTxd->TBControl |= BMU_UDP_CHECK;
+ } else {
+ pTxd->TBControl |= BMU_TCP_CHECK ;
+ }
+
+ IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4;
+ pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */
+ pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
+ C_OFFSET_TCPHEADER_TCPCS;
+ pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
+ } else {
+ pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
+ skb_headlen(pMessage);
+ }
+
+ pTxd = pTxd->pNextTxd;
+ pTxPort->TxdRingFree--;
+ BytesSend += skb_headlen(pMessage);
+
+ /*
+ ** Browse over all SG fragments and map each of them into the DMA space
+ */
+ for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
+ sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
+ /*
+ ** we already have the proper value in entry
+ */
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ sk_frag->page,
+ sk_frag->page_offset,
+ sk_frag->size,
+ PCI_DMA_TODEVICE);
+
+ pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+ pTxd->pMBuf = pMessage;
+
+ /*
+ ** Does the HW need to evaluate checksum for TCP or UDP packets?
+ */
+ if (pMessage->ip_summed == CHECKSUM_HW) {
+ pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD;
+ /*
+ ** We have to use the opcode for tcp here because the
+ ** opcode for udp is not working in the hardware yet
+ ** (revision 2.0)
+ */
+ if ( (Protocol == C_PROTO_ID_TCP) &&
+ (pAC->GIni.GIChipRev != 0) ) {
+ pTxd->TBControl |= BMU_UDP_CHECK ;
+ } else {
+ pTxd->TBControl |= BMU_TCP_CHECK ;
+ }
+ } else {
+ pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
+ }
+
+ /*
+ ** Do we have the last fragment?
+ */
+ if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
+#ifdef USE_TX_COMPLETE
+ pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size;
+#else
+ pTxd->TBControl |= BMU_EOF | sk_frag->size;
+#endif
+ pTxdFst->TBControl |= BMU_OWN | BMU_SW;
+
+ } else {
+ pTxd->TBControl |= sk_frag->size;
+ }
+ pTxdLst = pTxd;
+ pTxd = pTxd->pNextTxd;
+ pTxPort->TxdRingFree--;
+ BytesSend += sk_frag->size;
+ }
+
+ /*
+ ** If previous descriptor already done, give TX start cmd
+ */
+ if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
+ SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+ }
+
+ pTxPort->pTxdRingPrev = pTxdLst;
+ pTxPort->pTxdRingHead = pTxd;
+
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+
+ if (pTxPort->TxdRingFree > 0) {
+ return (BytesSend);
+ } else {
+ return (0);
+ }
+}
/*****************************************************************************
*
SK_U64 PhysAddr; /* address of DMA mapping */
pNewTail = pTxPort->pTxdRingTail;
- pTxd = pNewTail;
-
- /*
- * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame
- * or TX_CTRL_OWN_BMU bit set in any frame
- */
+ pTxd = pNewTail;
+ /*
+ ** loop forever; exits if BMU_SW bit not set in start frame
+ ** or BMU_OWN bit set in any frame
+ */
while (1) {
Control = pTxd->TBControl;
- if ((Control & TX_CTRL_SOFTWARE) == 0) {
- /*
- * software controllable bit is set in first
- * fragment when given to BMU. Not set means that
- * this fragment was never sent or is already
- * freed ( -> ring completely free now).
- */
+ if ((Control & BMU_SW) == 0) {
+ /*
+ ** software controllable bit is set in first
+ ** fragment when given to BMU. Not set means that
+ ** this fragment was never sent or is already
+ ** freed ( -> ring completely free now).
+ */
pTxPort->pTxdRingTail = pTxd;
- netif_start_queue(pAC->dev[pTxPort->PortIndex]);
+ netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
return;
}
- if (Control & TX_CTRL_OWN_BMU) {
+ if (Control & BMU_OWN) {
pTxPort->pTxdRingTail = pTxd;
if (pTxPort->TxdRingFree > 0) {
- netif_start_queue(pAC->dev[pTxPort->PortIndex]);
+ netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
}
return;
}
- /* release the DMA mapping */
+ /*
+ ** release the DMA mapping, because until not unmapped
+ ** this buffer is considered being under control of the
+ ** adapter card!
+ */
PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
PhysAddr |= (SK_U64) pTxd->VDataLow;
- pci_unmap_page(&pAC->PciDev, PhysAddr,
- pTxd->pMBuf->len,
- PCI_DMA_TODEVICE);
+ pci_unmap_page(pAC->PciDev, PhysAddr,
+ pTxd->pMBuf->len,
+ PCI_DMA_TODEVICE);
+
+ if (Control & BMU_EOF)
+ DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
- /* free message */
- DEV_KFREE_SKB_ANY(pTxd->pMBuf);
pTxPort->TxdRingFree++;
- pTxd->TBControl &= ~TX_CTRL_SOFTWARE;
+ pTxd->TBControl &= ~BMU_SW;
pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
} /* while(forever) */
} /* FreeTxDescriptors */
-
/*****************************************************************************
*
* FillRxRing - fill the receive ring with valid descriptors
pRxPort->pRxdRingTail = pRxd->pNextRxd;
pRxPort->RxdRingFree--;
Length = pAC->RxBufSize;
- PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
- virt_to_page(pMsgBlock->data),
- ((unsigned long) pMsgBlock->data &
- ~PAGE_MASK),
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
- pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMsgBlock->data),
+ ((unsigned long) pMsgBlock->data &
+ ~PAGE_MASK),
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
+
+ pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pRxd->pMBuf = pMsgBlock;
- pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |
- RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;
+ pRxd->pMBuf = pMsgBlock;
+ pRxd->RBControl = BMU_OWN |
+ BMU_STF |
+ BMU_IRQ_EOF |
+ BMU_TCP_CHECK |
+ Length;
return (SK_TRUE);
} /* FillRxDescriptor */
pRxPort->pRxdRingTail = pRxd->pNextRxd;
pRxPort->RxdRingFree--;
Length = pAC->RxBufSize;
- pRxd->VDataLow = PhysLow;
+
+ pRxd->VDataLow = PhysLow;
pRxd->VDataHigh = PhysHigh;
- pRxd->pMBuf = pMsg;
- pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |
- RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;
+ pRxd->pMBuf = pMsg;
+ pRxd->RBControl = BMU_OWN |
+ BMU_STF |
+ BMU_IRQ_EOF |
+ BMU_TCP_CHECK |
+ Length;
return;
} /* ReQueueRxBuffer */
-
/*****************************************************************************
*
* ReceiveIrq - handle a receive IRQ
* Returns: N/A
*/
static void ReceiveIrq(
-SK_AC *pAC, /* pointer to adapter context */
-RX_PORT *pRxPort) /* pointer to receive port struct */
+ SK_AC *pAC, /* pointer to adapter context */
+ RX_PORT *pRxPort, /* pointer to receive port struct */
+ SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
{
-RXD *pRxd; /* pointer to receive descriptors */
-SK_U32 Control; /* control field of descriptor */
-struct sk_buff *pMsg; /* pointer to message holding frame */
-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
-int FrameLength; /* total length of received frame */
-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA EvPara; /* an event parameter union */
-int PortIndex = pRxPort->PortIndex;
+RXD *pRxd; /* pointer to receive descriptors */
+SK_U32 Control; /* control field of descriptor */
+struct sk_buff *pMsg; /* pointer to message holding frame */
+struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
+int FrameLength; /* total length of received frame */
+int IpFrameLength;
+SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
+SK_EVPARA EvPara; /* an event parameter union */
+unsigned long Flags; /* for spin lock */
+int PortIndex = pRxPort->PortIndex;
unsigned int Offset;
unsigned int NumBytes;
unsigned int ForRlmt;
-SK_BOOL IsBc;
-SK_BOOL IsMc;
-SK_U32 FrameStat;
+SK_BOOL IsBc;
+SK_BOOL IsMc;
+SK_BOOL IsBadFrame; /* Bad frame */
+
+SK_U32 FrameStat;
unsigned short Csum1;
unsigned short Csum2;
unsigned short Type;
-int Result;
-SK_U64 PhysAddr;
+int Result;
+SK_U64 PhysAddr;
rx_start:
- /* do forever; exit if RX_CTRL_OWN_BMU found */
+ /* do forever; exit if BMU_OWN found */
for ( pRxd = pRxPort->pRxdRingHead ;
pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
pRxd = pRxd->pNextRxd,
pRxPort->RxdRingFree ++) {
/*
- * For a better understanding of this loop
- * Go through every descriptor beginning at the head
+ * For a better understanding of this loop
+ * Go through every descriptor beginning at the head
* Please note: the ring might be completely received so the OWN bit
* set is not a good crirteria to leave that loop.
* Therefore the RingFree counter is used.
Control = pRxd->RBControl;
/* check if this descriptor is ready */
- if ((Control & RX_CTRL_OWN_BMU) != 0) {
+ if ((Control & BMU_OWN) != 0) {
/* this descriptor is not yet ready */
/* This is the usual end of the loop */
/* We don't need to start the ring again */
FillRxRing(pAC, pRxPort);
return;
}
+ pAC->DynIrqModInfo.NbrProcessedDescr++;
/* get length of frame and check it */
- FrameLength = Control & RX_CTRL_LEN_MASK;
+ FrameLength = Control & BMU_BBC;
if (FrameLength > pAC->RxBufSize) {
goto rx_failed;
}
/* check for STF and EOF */
- if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) !=
- (RX_CTRL_STF | RX_CTRL_EOF)) {
+ if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
goto rx_failed;
}
-
+
/* here we have a complete frame in the ring */
pMsg = pRxd->pMBuf;
FrameStat = pRxd->FrameStat;
+
+ /* check for frame length mismatch */
+#define XMR_FS_LEN_SHIFT 18
+#define GMR_FS_LEN_SHIFT 16
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: Frame length mismatch (%u/%u).\n",
+ FrameLength,
+ (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+ goto rx_failed;
+ }
+ }
+ else {
+ if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: Frame length mismatch (%u/%u).\n",
+ FrameLength,
+ (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+ goto rx_failed;
+ }
+ }
+
+ /* Set Rx Status */
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ IsBc = (FrameStat & XMR_FS_BC) != 0;
+ IsMc = (FrameStat & XMR_FS_MC) != 0;
+ IsBadFrame = (FrameStat &
+ (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+ } else {
+ IsBc = (FrameStat & GMR_FS_BC) != 0;
+ IsMc = (FrameStat & GMR_FS_MC) != 0;
+ IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+ ((FrameStat & GMR_FS_RX_OK) == 0));
+ }
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
("Received frame of length %d on port %d\n",
FrameLength, PortIndex));
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
("Number of free rx descriptors: %d\n",
pRxPort->RxdRingFree));
- /*DumpMsg(pMsg, "Rx"); */
-
- if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID ||
+/* DumpMsg(pMsg, "Rx"); */
+
+ if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+#if 0
(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+#endif
/* there is a receive error in this frame */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("skge: Error in received frame, dropped!\n"
"Control: %x\nRxStat: %x\n",
Control, FrameStat));
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_dma_sync_single(&pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
+ pci_dma_sync_single(pAC->PciDev,
+ (dma_addr_t) PhysAddr,
+ FrameLength,
+ PCI_DMA_FROMDEVICE);
ReQueueRxBuffer(pAC, pRxPort, pMsg,
pRxd->VDataHigh, pRxd->VDataLow);
/*
* Short frame detected and allocation successfull
*/
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
/* use new skb and copy data */
skb_reserve(pNewMsg, 2);
skb_put(pNewMsg, FrameLength);
- pci_dma_sync_single(&pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
+ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+ pci_dma_sync_single(pAC->PciDev,
+ (dma_addr_t) PhysAddr,
+ FrameLength,
+ PCI_DMA_FROMDEVICE);
eth_copy_and_sum(pNewMsg, pMsg->data,
FrameLength, 0);
ReQueueRxBuffer(pAC, pRxPort, pMsg,
pRxd->VDataHigh, pRxd->VDataLow);
+
pMsg = pNewMsg;
}
PhysAddr |= (SK_U64) pRxd->VDataLow;
/* release the DMA mapping */
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_single(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
/* set length in message */
skb_put(pMsg, FrameLength);
/* hardware checksum */
Type = ntohs(*((short*)&pMsg->data[12]));
+
+#ifdef USE_SK_RX_CHECKSUM
if (Type == 0x800) {
Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
- if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {
- Result = SkCsGetReceiveInfo(pAC,
- &pMsg->data[14],
- Csum1, Csum2, pRxPort->PortIndex);
- if (Result ==
- SKCS_STATUS_IP_FRAGMENT ||
- Result ==
- SKCS_STATUS_IP_CSUM_OK ||
- Result ==
- SKCS_STATUS_TCP_CSUM_OK ||
- Result ==
- SKCS_STATUS_UDP_CSUM_OK) {
- pMsg->ip_summed =
- CHECKSUM_UNNECESSARY;
- }
- } /* checksum calculation valid */
+ IpFrameLength = (int) ntohs((unsigned short)
+ ((unsigned short *) pMsg->data)[8]);
+
+ /*
+ * Test: If frame is padded, a check is not possible!
+ * Frame not padded? Length difference must be 14 (0xe)!
+ */
+ if ((FrameLength - IpFrameLength) != 0xe) {
+ /* Frame padded => TCP offload not possible! */
+ pMsg->ip_summed = CHECKSUM_NONE;
+ } else {
+ /* Frame not padded => TCP offload! */
+ if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
+ (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
+ (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+ Result = SkCsGetReceiveInfo(pAC,
+ &pMsg->data[14],
+ Csum1, Csum2, pRxPort->PortIndex);
+ if (Result ==
+ SKCS_STATUS_IP_FRAGMENT ||
+ Result ==
+ SKCS_STATUS_IP_CSUM_OK ||
+ Result ==
+ SKCS_STATUS_TCP_CSUM_OK ||
+ Result ==
+ SKCS_STATUS_UDP_CSUM_OK) {
+ pMsg->ip_summed =
+ CHECKSUM_UNNECESSARY;
+ }
+ else if (Result ==
+ SKCS_STATUS_TCP_CSUM_ERROR ||
+ Result ==
+ SKCS_STATUS_UDP_CSUM_ERROR ||
+ Result ==
+ SKCS_STATUS_IP_CSUM_ERROR_UDP ||
+ Result ==
+ SKCS_STATUS_IP_CSUM_ERROR_TCP ||
+ Result ==
+ SKCS_STATUS_IP_CSUM_ERROR ) {
+ /* HW Checksum error */
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: CRC error. Frame dropped!\n"));
+ goto rx_failed;
+ } else {
+ pMsg->ip_summed =
+ CHECKSUM_NONE;
+ }
+ }/* checksumControl calculation valid */
+ } /* Frame length check */
} /* IP frame */
+#else
+ pMsg->ip_summed = CHECKSUM_NONE;
+#endif
} /* frame > SK_COPY_TRESHOLD */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
ForRlmt = SK_RLMT_RX_PROTOCOL;
+#if 0
IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+#endif
SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
IsBc, &Offset, &NumBytes);
if (NumBytes != 0) {
+#if 0
IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
- SK_RLMT_LOOKAHEAD(pAC, PortIndex,
+#endif
+ SK_RLMT_LOOKAHEAD(pAC, PortIndex,
&pMsg->data[Offset],
IsBc, IsMc, &ForRlmt);
}
}
else {
/* drop frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("D"));
DEV_KFREE_SKB(pMsg);
} /* if not for rlmt */
else {
/* packet for rlmt */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
pAC->IoBase, FrameLength);
memcpy((char*)(pRlmtMbuf->pData),
(char*)(pMsg->data),
FrameLength);
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+
+ /* SlowPathLock needed? */
+ if (SlowPathLock == SK_TRUE) {
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ SkEventQueue(pAC, SKGE_RLMT,
+ SK_RLMT_PACKET_RECEIVED,
+ EvPara);
+ pAC->CheckQueue = SK_TRUE;
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ } else {
+ SkEventQueue(pAC, SKGE_RLMT,
+ SK_RLMT_PACKET_RECEIVED,
+ EvPara);
+ pAC->CheckQueue = SK_TRUE;
+ }
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("Q"));
}
- if ((pAC->dev[pRxPort->PortIndex]->flags &
+ if ((pAC->dev[pRxPort->PortIndex]->flags &
(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
- (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
- SK_RLMT_RX_PROTOCOL) {
+ (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
+ SK_RLMT_RX_PROTOCOL) {
pMsg->dev = pAC->dev[pRxPort->PortIndex];
pMsg->protocol = eth_type_trans(pMsg,
pAC->dev[pRxPort->PortIndex]);
/* RXD ring is empty -> fill and restart */
FillRxRing(pAC, pRxPort);
/* do not start if called from Close */
- if (pAC->BoardLevel > 0) {
+ if (pAC->BoardLevel > SK_INIT_DATA) {
ClearAndStartRx(pAC, PortIndex);
}
return;
("Schrottdescriptor, length: 0x%x\n", FrameLength));
/* release the DMA mapping */
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
pRxd->pMBuf = NULL;
pRxPort->RxdRingFree++;
SK_AC *pAC, /* pointer to the adapter context */
int PortIndex) /* index of the receive port (XMAC) */
{
- SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL,
- RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF);
+ SK_OUT8(pAC->IoBase,
+ RxQueueAddr[PortIndex]+Q_CSR,
+ CSR_START | CSR_IRQ_CL_F);
} /* ClearAndStartRx */
int PortIndex, /* index of the transmit port (XMAC) */
int Prio) /* priority or normal queue */
{
- SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL,
- TX_Q_CTRL_CLR_I_EOF);
+ SK_OUT8(pAC->IoBase,
+ TxQueueAddr[PortIndex][Prio]+Q_CSR,
+ CSR_IRQ_CL_F);
} /* ClearTxIrq */
{
RXD *pRxd; /* pointer to the current descriptor */
unsigned long Flags;
- SK_U64 PhysAddr;
+SK_U64 PhysAddr;
if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
return;
pRxd = pRxPort->pRxdRingHead;
do {
if (pRxd->pMBuf != NULL) {
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
DEV_KFREE_SKB(pRxd->pMBuf);
pRxd->pMBuf = NULL;
}
- pRxd->RBControl &= RX_CTRL_OWN_BMU;
+ pRxd->RBControl &= BMU_OWN;
pRxd = pRxd->pNextRxd;
pRxPort->RxdRingFree++;
} while (pRxd != pRxPort->pRxdRingTail);
spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
} /* ClearRxRing */
-
/*****************************************************************************
*
* ClearTxRing - remove all buffers from the transmit ring
spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
pTxd = pTxPort->pTxdRingHead;
for (i=0; i<pAC->TxDescrPerRing; i++) {
- pTxd->TBControl &= ~TX_CTRL_OWN_BMU;
+ pTxd->TBControl &= ~BMU_OWN;
pTxd = pTxd->pNextTxd;
}
FreeTxDescriptors(pAC, pTxPort);
spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * SetQueueSizes - configure the sizes of rx and tx queues
- *
- * Description:
- * This function assigns the sizes for active and passive port
- * to the appropriate HWinit structure variables.
- * The passive port(s) get standard values, all remaining RAM
- * is given to the active port.
- * The queue sizes are in kbyte and must be multiple of 8.
- * The limits for the number of buffers filled into the rx rings
- * is also set in this routine.
- *
- * Returns:
- * none
- */
-static void SetQueueSizes(
-SK_AC *pAC) /* pointer to the adapter context */
-{
-int StandbyRam; /* adapter RAM used for a standby port */
-int RemainingRam; /* adapter RAM available for the active port */
-int RxRam; /* RAM used for the active port receive queue */
-int i; /* loop counter */
-
-if (pAC->RlmtNets == 1) {
- StandbyRam = SK_RLMT_STANDBY_QRXSIZE + SK_RLMT_STANDBY_QXASIZE +
- SK_RLMT_STANDBY_QXSSIZE;
- RemainingRam = pAC->GIni.GIRamSize -
- (pAC->GIni.GIMacsFound-1) * StandbyRam;
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxQSize = SK_RLMT_STANDBY_QRXSIZE;
- pAC->GIni.GP[i].PXSQSize = SK_RLMT_STANDBY_QXSSIZE;
- pAC->GIni.GP[i].PXAQSize = SK_RLMT_STANDBY_QXASIZE;
- }
- RxRam = (RemainingRam * 8 / 10) & ~7;
- pAC->GIni.GP[pAC->ActivePort].PRxQSize = RxRam;
- pAC->GIni.GP[pAC->ActivePort].PXSQSize = 0;
- pAC->GIni.GP[pAC->ActivePort].PXAQSize =
- (RemainingRam - RxRam) & ~7;
- pAC->RxQueueSize = RxRam;
- pAC->TxSQueueSize = 0;
- pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7;
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("queue sizes settings - rx:%d txA:%d txS:%d\n",
- pAC->RxQueueSize,pAC->TxAQueueSize, pAC->TxSQueueSize));
-} else {
- RemainingRam = pAC->GIni.GIRamSize/pAC->GIni.GIMacsFound;
- RxRam = (RemainingRam * 8 / 10) & ~7;
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxQSize = RxRam;
- pAC->GIni.GP[i].PXSQSize = 0;
- pAC->GIni.GP[i].PXAQSize = (RemainingRam - RxRam) & ~7;
- }
-
- pAC->RxQueueSize = RxRam;
- pAC->TxSQueueSize = 0;
- pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7;
-}
- for (i=0; i<SK_MAX_MACS; i++) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing;
- }
-
- if (pAC->RlmtNets == 2) {
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100;
- }
- } else {
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100;
- }
- /*
- * Do not set the Limit to 0, because this could cause
- * wrap around with ReQueue'ed buffers (a buffer could
- * be requeued in the same position, made accessible to
- * the hardware, and the hardware could change its
- * contents!
- */
- pAC->RxPort[pAC->ActivePort].RxFillLimit = 1;
- }
-
-#ifdef DEBUG
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("i: %d, RxQSize: %d, PXSQsize: %d, PXAQSize: %d\n",
- i,
- pAC->GIni.GP[i].PRxQSize,
- pAC->GIni.GP[i].PXSQSize,
- pAC->GIni.GP[i].PXAQSize));
- }
-#endif
-} /* SetQueueSizes */
-
-
/*****************************************************************************
*
* SkGeSetMacAddr - Set the hardware MAC address
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeSetMacAddr(struct net_device *dev, void *p)
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
{
DEV_NET *pNet = (DEV_NET*) dev->priv;
struct sockaddr *addr = p;
unsigned long Flags;
-
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeSetMacAddr starts now...\n"));
- if(netif_running(dev)) {
+ if(netif_running(dev))
return -EBUSY;
- }
+
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
* 0, if everything is ok
* !=0, on error
*/
-static void SkGeSetRxMode(struct net_device *dev)
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet;
pMcList->dmi_addr[5]));
}
SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-
}
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeChangeMtu(struct net_device *dev, int NewMtu)
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
{
DEV_NET *pNet;
DEV_NET *pOtherNet;
("SkGeChangeMtu starts now...\n"));
pNet = (DEV_NET*) dev->priv;
- pAC = pNet->pAC;
+ pAC = pNet->pAC;
if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
return -EINVAL;
}
+ if(pAC->BoardLevel != SK_INIT_RUN) {
+ return -EINVAL;
+ }
+
pNet->Mtu = NewMtu;
pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv;
- if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) {
+ if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
return(0);
}
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
-
pAC->RxBufSize = NewMtu + 32;
dev->mtu = NewMtu;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("New MTU: %d\n", NewMtu));
- if(pAC->BoardLevel != 2) {
- return 0;
- }
-
- /* prevent reconfiguration while changing the MTU */
-
- /* disable interrupts */
+ /*
+ ** Prevent any reconfiguration while changing the MTU
+ ** by disabling any interrupts
+ */
SK_OUT32(pAC->IoBase, B0_IMSK, 0);
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- /* Found more than one port */
- if ((pAC->GIni.GIMacsFound == 2 ) &&
- (pAC->RlmtNets == 2)) {
- /* Stop both ports */
- EvPara.Para32[0] = 0;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+ /*
+ ** Notify RLMT that any ports are to be stopped
+ */
+ EvPara.Para32[0] = 0;
+ EvPara.Para32[1] = -1;
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+ EvPara.Para32[0] = 1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
} else {
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
}
+ /*
+ ** After calling the SkEventDispatcher(), RLMT is aware about
+ ** the stopped ports -> configuration can take place!
+ */
SkEventDispatcher(pAC, pAC->IoBase);
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
spin_lock_irqsave(
&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
netif_stop_queue(pAC->dev[i]);
+
}
- /*
- * adjust number of rx buffers allocated
- */
+ /*
+ ** Depending on the desired MTU size change, a different number of
+ ** RX buffers need to be allocated
+ */
if (NewMtu > 1500) {
- /* use less rx buffers */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- /* Found more than one port */
- if ((pAC->GIni.GIMacsFound == 2 ) &&
- (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit =
- pAC->RxDescrPerRing - 100;
- } else {
- if (i == pAC->ActivePort)
- pAC->RxPort[i].RxFillLimit =
- pAC->RxDescrPerRing - 100;
- else
- pAC->RxPort[i].RxFillLimit =
- pAC->RxDescrPerRing - 10;
- }
+ /*
+ ** Use less rx buffers
+ */
+ for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+ (pAC->RxDescrPerRing / 4);
+ } else {
+ if (i == pAC->ActivePort) {
+ pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+ (pAC->RxDescrPerRing / 4);
+ } else {
+ pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+ (pAC->RxDescrPerRing / 10);
+ }
}
- }
- else {
- /* use normal anoumt of rx buffers */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- /* Found more than one port */
- if ((pAC->GIni.GIMacsFound == 2 ) &&
- (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit = 1;
- } else {
- if (i == pAC->ActivePort)
- pAC->RxPort[i].RxFillLimit = 1;
- else
- pAC->RxPort[i].RxFillLimit =
- pAC->RxDescrPerRing - 100;
- }
+ }
+ } else {
+ /*
+ ** Use the normal amount of rx buffers
+ */
+ for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ pAC->RxPort[i].RxFillLimit = 1;
+ } else {
+ if (i == pAC->ActivePort) {
+ pAC->RxPort[i].RxFillLimit = 1;
+ } else {
+ pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+ (pAC->RxDescrPerRing / 4);
+ }
}
+ }
}
-
- SkGeDeInit(pAC, pAC->IoBase);
+
+ SkGeDeInit(pAC, pAC->IoBase);
- /*
- * enable/disable hardware support for long frames
- */
+ /*
+ ** enable/disable hardware support for long frames
+ */
if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
+// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxCmd =
- XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
- }
- }
- else {
- if ((pAC->GIni.GIMacsFound == 2 ) &&
- (pAC->RlmtNets == 2)) {
- pAC->GIni.GIPortUsage = SK_MUL_LINK;
- } else {
- pAC->GIni.GIPortUsage = SK_RED_LINK;
- }
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxCmd = XM_RX_STRIP_FCS;
- }
+ } else {
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ pAC->GIni.GIPortUsage = SK_MUL_LINK;
+ } else {
+ pAC->GIni.GIPortUsage = SK_RED_LINK;
+ }
}
- SkGeInit( pAC, pAC->IoBase, 1);
- SkI2cInit( pAC, pAC->IoBase, 1);
- SkEventInit(pAC, pAC->IoBase, 1);
- SkPnmiInit( pAC, pAC->IoBase, 1);
- SkAddrInit( pAC, pAC->IoBase, 1);
- SkRlmtInit( pAC, pAC->IoBase, 1);
- SkTimerInit(pAC, pAC->IoBase, 1);
+ SkGeInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+ SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
- SkGeInit( pAC, pAC->IoBase, 2);
- SkI2cInit( pAC, pAC->IoBase, 2);
- SkEventInit(pAC, pAC->IoBase, 2);
- SkPnmiInit( pAC, pAC->IoBase, 2);
- SkAddrInit( pAC, pAC->IoBase, 2);
- SkRlmtInit( pAC, pAC->IoBase, 2);
- SkTimerInit(pAC, pAC->IoBase, 2);
+ /*
+ ** tschilling:
+ ** Speed and others are set back to default in level 1 init!
+ */
+ GetConfiguration(pAC);
+
+ SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN);
+ SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN);
+ SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
+ SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
+ SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
+ SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
- /*
- * clear and reinit the rx rings here
- */
+ /*
+ ** clear and reinit the rx rings here
+ */
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i]);
+ ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[i]);
FillRxRing(pAC, &pAC->RxPort[i]);
- /* Enable transmit descriptor polling. */
+ /*
+ ** Enable transmit descriptor polling
+ */
SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
FillRxRing(pAC, &pAC->RxPort[i]);
};
SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-#ifdef USE_INT_MOD
- {
- unsigned long ModBase;
- ModBase = 53125000 / INTS_PER_SEC;
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK);
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
- }
-#endif
+ SkDimEnableModerationIfNeeded(pAC);
+ SkDimDisplayModerationSettings(pAC);
netif_start_queue(pAC->dev[pNet->PortNr]);
for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
}
- /* enable Interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
+ /*
+ ** Enable Interrupts again
+ */
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
SkEventDispatcher(pAC, pAC->IoBase);
- /* Found more than one port */
- if ((pAC->GIni.GIMacsFound == 2 ) &&
- (pAC->RlmtNets == 2)) {
- /* Start both ports */
- EvPara.Para32[0] = pAC->RlmtNets;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
- EvPara);
-
+ /*
+ ** Notify RLMT about the changing and restarting one (or more) ports
+ */
+ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+ EvPara.Para32[0] = pAC->RlmtNets;
+ EvPara.Para32[1] = -1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
+ EvPara.Para32[0] = pNet->PortNr;
+ EvPara.Para32[1] = -1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- EvPara.Para32[1] = -1;
- EvPara.Para32[0] = pNet->PortNr;
+ if (pOtherNet->Up) {
+ EvPara.Para32[0] = pOtherNet->PortNr;
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-
- if (pOtherNet->Up) {
- EvPara.Para32[0] = pOtherNet->PortNr;
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_START, EvPara);
- }
+ }
} else {
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
}
SkEventDispatcher(pAC, pAC->IoBase);
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return 0;
+ /*
+ ** While testing this driver with latest kernel 2.5 (2.5.70), it
+ ** seems as if upper layers have a problem to handle a successful
+ ** return value of '0'. If such a zero is returned, the complete
+ ** system hangs for several minutes (!), which is in acceptable.
+ **
+ ** Currently it is not clear, what the exact reason for this problem
+ ** is. The implemented workaround for 2.5 is to return the desired
+ ** new MTU size if all needed changes for the new MTU size where
+ ** performed. In kernels 2.2 and 2.4, a zero value is returned,
+ ** which indicates the successful change of the mtu-size.
+ */
+ return NewMtu;
+
} /* SkGeChangeMtu */
* Returns:
* pointer to the statistic structure.
*/
-static struct net_device_stats *SkGeStats(struct net_device *dev)
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet = (DEV_NET*) dev->priv;
SK_AC *pAC = pNet->pAC;
SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
+SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
+SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
unsigned int Size; /* size of pnmi struct */
unsigned long Flags; /* for spin lock */
pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+
+ if (pNet->Mtu <= 1500) {
+ pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+ } else {
+ pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+ pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+ }
+
+
+ if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
+ pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
+
pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
{
DEV_NET *pNet;
SK_AC *pAC;
+void *pMemBuf;
SK_GE_IOCTL Ioctl;
unsigned int Err = 0;
-int Size;
+int Size = 0;
+int Ret = 0;
+unsigned int Length = 0;
+int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeIoctl starts now...\n"));
case SK_IOCTL_PRESETMIB:
if (!capable(CAP_NET_ADMIN)) return -EPERM;
case SK_IOCTL_GETMIB:
- if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
+ if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
Ioctl.Len<sizeof(pAC->PnmiStruct)?
Ioctl.Len : sizeof(pAC->PnmiStruct))) {
return -EFAULT;
return -EFAULT;
}
break;
+ case SK_IOCTL_GEN:
+ if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+ Length = Ioctl.Len;
+ } else {
+ Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+ }
+ if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+ return -EFAULT;
+ }
+ if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+ return -EFAULT;
+ }
+ if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
+ return -EFAULT;
+ }
+ if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+ return -EFAULT;
+ }
+ Ioctl.Len = Length;
+ if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+ return -EFAULT;
+ }
+ kfree(pMemBuf); /* cleanup everything */
+ break;
default:
Err = -EOPNOTSUPP;
}
+
return(Err);
+
} /* SkGeIoctl */
SK_AC *pAC) /* pointer to the adapter context structure */
{
SK_I32 Port; /* preferred port */
-int AutoNeg; /* auto negotiation off (0) or on (1) */
-int DuplexCap; /* duplex capabilities (0=both, 1=full, 2=half */
-int MSMode; /* master / slave mode selection */
SK_BOOL AutoSet;
SK_BOOL DupSet;
+int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
+int AutoNeg = 1; /* autoneg off (0) or on (1) */
+int DuplexCap = 0; /* 0=both,1=full,2=half */
+int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
+int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
+SK_BOOL IsConTypeDefined = SK_TRUE;
+SK_BOOL IsLinkSpeedDefined = SK_TRUE;
+SK_BOOL IsFlowCtrlDefined = SK_TRUE;
+SK_BOOL IsRoleDefined = SK_TRUE;
+SK_BOOL IsModeDefined = SK_TRUE;
/*
* The two parameters AutoNeg. and DuplexCap. map to one configuration
* parameter. The mapping is described by this table:
* -----------------------------------------------------------------
* Sense | AutoSense | AutoSense | AutoSense |
*/
-int Capabilities[3][3] =
- { { -1, SK_LMODE_FULL, SK_LMODE_HALF},
- {SK_LMODE_AUTOBOTH, SK_LMODE_AUTOFULL, SK_LMODE_AUTOHALF},
+int Capabilities[3][3] =
+ { { -1, SK_LMODE_FULL , SK_LMODE_HALF },
+ {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
{SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+
#define DC_BOTH 0
#define DC_FULL 1
#define DC_HALF 2
#define AN_OFF 0
#define AN_ON 1
#define AN_SENS 2
+#define M_CurrPort pAC->GIni.GP[Port]
- /* settings for port A */
- AutoNeg = AN_SENS; /* default: do auto Sense */
+ /*
+ ** Set the default values first for both ports!
+ */
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
+ }
+
+ /*
+ ** Check merged parameter ConType. If it has not been used,
+ ** verify any other parameter (e.g. AutoNeg) and use default values.
+ **
+ ** Stating both ConType and other lowlevel link parameters is also
+ ** possible. If this is the case, the passed ConType-parameter is
+ ** overwritten by the lowlevel link parameter.
+ **
+ ** The following settings are used for a merged ConType-parameter:
+ **
+ ** ConType DupCap AutoNeg FlowCtrl Role Speed
+ ** ------- ------ ------- -------- ---------- -----
+ ** Auto Both On SymOrRem Auto Auto
+ ** 100FD Full Off None <ignored> 100
+ ** 100HD Half Off None <ignored> 100
+ ** 10FD Full Off None <ignored> 10
+ ** 10HD Half Off None <ignored> 10
+ **
+ ** This ConType parameter is used for all ports of the adapter!
+ */
+ if ( (ConType != NULL) &&
+ (pAC->Index < SK_MAX_CARD_PARAM) &&
+ (ConType[pAC->Index] != NULL) ) {
+ if (strcmp(ConType[pAC->Index],"")==0) {
+ IsConTypeDefined = SK_FALSE; /* No ConType defined */
+ } else if (strcmp(ConType[pAC->Index],"Auto")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
+ }
+ } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+ }
+ } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+ }
+ } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+ }
+ } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+ }
+ } else {
+ printk("%s: Illegal value \"%s\" for ConType\n",
+ pAC->dev[0]->name, ConType[pAC->Index]);
+ IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+ }
+ } else {
+ IsConTypeDefined = SK_FALSE; /* No ConType defined */
+ }
+
+ /*
+ ** Parse any parameter settings for port A:
+ ** a) any LinkSpeed stated?
+ */
+ if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+ Speed_A[pAC->Index] != NULL) {
+ if (strcmp(Speed_A[pAC->Index],"")==0) {
+ IsLinkSpeedDefined = SK_FALSE;
+ } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ } else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+ LinkSpeed = SK_LSPEED_10MBPS;
+ } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+ LinkSpeed = SK_LSPEED_100MBPS;
+ } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ } else {
+ printk("%s: Illegal value \"%s\" for Speed_A\n",
+ pAC->dev[0]->name, Speed_A[pAC->Index]);
+ IsLinkSpeedDefined = SK_FALSE;
+ }
+ } else {
+ IsLinkSpeedDefined = SK_FALSE;
+ }
+
+ /*
+ ** Check speed parameter:
+ ** Only copper type adapter and GE V2 cards
+ */
+ if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+ (pAC->GIni.GICopperType != SK_TRUE)) &&
+ ((LinkSpeed != SK_LSPEED_AUTO) &&
+ (LinkSpeed != SK_LSPEED_1000MBPS))) {
+ printk("%s: Illegal value for Speed_A. "
+ "Not a copper card or GE V2 card\n Using "
+ "speed 1000\n", pAC->dev[0]->name);
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+
+ /*
+ ** Decide whether to set new config value if somethig valid has
+ ** been received.
+ */
+ if (IsLinkSpeedDefined) {
+ pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+ }
+
+ /*
+ ** b) Any Autonegotiation and DuplexCapabilities set?
+ ** Please note that both belong together...
+ */
+ AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
AutoSet = SK_FALSE;
if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
AutoNeg_A[pAC->Index] != NULL) {
AutoSet = SK_TRUE;
if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- }
- else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- }
- else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- }
- else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
+ AutoSet = SK_FALSE;
+ } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
+ AutoNeg = AN_ON;
+ } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
+ AutoNeg = AN_OFF;
+ } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
+ AutoNeg = AN_SENS;
+ } else {
+ printk("%s: Illegal value \"%s\" for AutoNeg_A\n",
+ pAC->dev[0]->name, AutoNeg_A[pAC->Index]);
}
- else printk("%s: Illegal value for AutoNeg_A\n",
- pAC->dev[0]->name);
}
DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
+ DupSet = SK_FALSE;
if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
DupCap_A[pAC->Index] != NULL) {
DupSet = SK_TRUE;
if (strcmp(DupCap_A[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- }
- else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- }
- else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- }
- else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
+ DupSet = SK_FALSE;
+ } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
+ DuplexCap = DC_BOTH;
+ } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
+ DuplexCap = DC_FULL;
+ } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
+ DuplexCap = DC_HALF;
+ } else {
+ printk("%s: Illegal value \"%s\" for DupCap_A\n",
+ pAC->dev[0]->name, DupCap_A[pAC->Index]);
}
- else printk("%s: Illegal value for DupCap_A\n",
- pAC->dev[0]->name);
}
- /* check for illegal combinations */
- if (AutoSet && AutoNeg==AN_SENS && DupSet) {
+ /*
+ ** Check for illegal combinations
+ */
+ if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
printk("%s, Port A: DuplexCapabilities"
" ignored using Sense mode\n", pAC->dev[0]->name);
}
+
if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
printk("%s, Port A: Illegal combination"
" of values AutoNeg. and DuplexCap.\n Using "
"Full Duplex\n", pAC->dev[0]->name);
-
DuplexCap = DC_FULL;
}
+
if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
DuplexCap = DC_FULL;
}
AutoNeg = AN_ON;
}
- /* set the desired mode */
- pAC->GIni.GP[0].PLinkModeConf =
- Capabilities[AutoNeg][DuplexCap];
+ /*
+ ** set the desired mode
+ */
+ if (AutoSet || DupSet) {
+ pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+ }
- pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+ /*
+ ** c) Any Flowcontrol-parameter set?
+ */
if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
FlowCtrl_A[pAC->Index] != NULL) {
if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
+ IsFlowCtrlDefined = SK_FALSE;
+ } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
+ FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+ } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
+ FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+ } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
+ FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+ } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
+ FlowCtrl = SK_FLOW_MODE_NONE;
+ } else {
+ printk("%s: Illegal value \"%s\" for FlowCtrl_A\n",
+ pAC->dev[0]->name, FlowCtrl_A[pAC->Index]);
+ IsFlowCtrlDefined = SK_FALSE;
}
- else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
- pAC->GIni.GP[0].PFlowCtrlMode =
- SK_FLOW_MODE_SYM_OR_REM;
- }
- else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
- pAC->GIni.GP[0].PFlowCtrlMode =
- SK_FLOW_MODE_SYMMETRIC;
- }
- else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
- pAC->GIni.GP[0].PFlowCtrlMode =
- SK_FLOW_MODE_LOC_SEND;
- }
- else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
- pAC->GIni.GP[0].PFlowCtrlMode =
- SK_FLOW_MODE_NONE;
- }
- else printk("Illegal value for FlowCtrl_A\n");
+ } else {
+ IsFlowCtrlDefined = SK_FALSE;
}
- if (AutoNeg==AN_OFF && pAC->GIni.GP[0].PFlowCtrlMode!=
- SK_FLOW_MODE_NONE) {
+
+ if (IsFlowCtrlDefined) {
+ if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
printk("%s, Port A: FlowControl"
" impossible without AutoNegotiation,"
" disabled\n", pAC->dev[0]->name);
- pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ FlowCtrl = SK_FLOW_MODE_NONE;
+ }
+ pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
}
- MSMode = SK_MS_MODE_AUTO; /* default: do auto select */
+ /*
+ ** d) What is with the RoleParameter?
+ */
if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
Role_A[pAC->Index] != NULL) {
if (strcmp(Role_A[pAC->Index],"")==0) {
+ IsRoleDefined = SK_FALSE;
+ } else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
+ MSMode = SK_MS_MODE_AUTO;
+ } else if (strcmp(Role_A[pAC->Index],"Master")==0) {
+ MSMode = SK_MS_MODE_MASTER;
+ } else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
+ MSMode = SK_MS_MODE_SLAVE;
+ } else {
+ printk("%s: Illegal value \"%s\" for Role_A\n",
+ pAC->dev[0]->name, Role_A[pAC->Index]);
+ IsRoleDefined = SK_FALSE;
}
- else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- }
- else if (strcmp(Role_A[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- }
- else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- }
- else printk("%s: Illegal value for Role_A\n",
- pAC->dev[0]->name);
+ } else {
+ IsRoleDefined = SK_FALSE;
+ }
+
+ if (IsRoleDefined == SK_TRUE) {
+ pAC->GIni.GP[0].PMSMode = MSMode;
}
- pAC->GIni.GP[0].PMSMode = MSMode;
+
- /* settings for port B */
+ /*
+ ** Parse any parameter settings for port B:
+ ** a) any LinkSpeed stated?
+ */
+ IsConTypeDefined = SK_TRUE;
+ IsLinkSpeedDefined = SK_TRUE;
+ IsFlowCtrlDefined = SK_TRUE;
+ IsModeDefined = SK_TRUE;
+
+ if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+ Speed_B[pAC->Index] != NULL) {
+ if (strcmp(Speed_B[pAC->Index],"")==0) {
+ IsLinkSpeedDefined = SK_FALSE;
+ } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ } else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+ LinkSpeed = SK_LSPEED_10MBPS;
+ } else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+ LinkSpeed = SK_LSPEED_100MBPS;
+ } else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ } else {
+ printk("%s: Illegal value \"%s\" for Speed_B\n",
+ pAC->dev[1]->name, Speed_B[pAC->Index]);
+ IsLinkSpeedDefined = SK_FALSE;
+ }
+ } else {
+ IsLinkSpeedDefined = SK_FALSE;
+ }
+
+ /*
+ ** Check speed parameter:
+ ** Only copper type adapter and GE V2 cards
+ */
+ if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+ (pAC->GIni.GICopperType != SK_TRUE)) &&
+ ((LinkSpeed != SK_LSPEED_AUTO) &&
+ (LinkSpeed != SK_LSPEED_1000MBPS))) {
+ printk("%s: Illegal value for Speed_B. "
+ "Not a copper card or GE V2 card\n Using "
+ "speed 1000\n", pAC->dev[1]->name);
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+
+ /*
+ ** Decide whether to set new config value if somethig valid has
+ ** been received.
+ */
+ if (IsLinkSpeedDefined) {
+ pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+ }
+
+ /*
+ ** b) Any Autonegotiation and DuplexCapabilities set?
+ ** Please note that both belong together...
+ */
AutoNeg = AN_SENS; /* default: do auto Sense */
AutoSet = SK_FALSE;
if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
AutoNeg_B[pAC->Index] != NULL) {
AutoSet = SK_TRUE;
if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- }
- else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- }
- else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- }
- else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
+ AutoSet = SK_FALSE;
+ } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
+ AutoNeg = AN_ON;
+ } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
+ AutoNeg = AN_OFF;
+ } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
+ AutoNeg = AN_SENS;
+ } else {
+ printk("%s: Illegal value \"%s\" for AutoNeg_B\n",
+ pAC->dev[0]->name, AutoNeg_B[pAC->Index]);
}
- else printk("Illegal value for AutoNeg_B\n");
}
DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
+ DupSet = SK_FALSE;
if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
DupCap_B[pAC->Index] != NULL) {
DupSet = SK_TRUE;
if (strcmp(DupCap_B[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- }
- else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- }
- else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- }
- else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
+ DupSet = SK_FALSE;
+ } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
+ DuplexCap = DC_BOTH;
+ } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
+ DuplexCap = DC_FULL;
+ } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
+ DuplexCap = DC_HALF;
+ } else {
+ printk("%s: Illegal value \"%s\" for DupCap_B\n",
+ pAC->dev[0]->name, DupCap_B[pAC->Index]);
}
- else printk("Illegal value for DupCap_B\n");
}
- /* check for illegal combinations */
+ /*
+ ** Check for illegal combinations
+ */
if (AutoSet && AutoNeg==AN_SENS && DupSet) {
printk("%s, Port B: DuplexCapabilities"
" ignored using Sense mode\n", pAC->dev[1]->name);
}
+
if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
printk("%s, Port B: Illegal combination"
" of values AutoNeg. and DuplexCap.\n Using "
"Full Duplex\n", pAC->dev[1]->name);
-
DuplexCap = DC_FULL;
}
+
if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
DuplexCap = DC_FULL;
}
AutoNeg = AN_ON;
}
- /* set the desired mode */
- pAC->GIni.GP[1].PLinkModeConf =
- Capabilities[AutoNeg][DuplexCap];
+ /*
+ ** set the desired mode
+ */
+ if (AutoSet || DupSet) {
+ pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+ }
- pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+ /*
+ ** c) Any FlowCtrl parameter set?
+ */
if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
FlowCtrl_B[pAC->Index] != NULL) {
if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
+ IsFlowCtrlDefined = SK_FALSE;
+ } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
+ FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+ } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
+ FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+ } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
+ FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+ } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
+ FlowCtrl = SK_FLOW_MODE_NONE;
+ } else {
+ printk("%s: Illegal value \"%s\" for FlowCtrl_B\n",
+ pAC->dev[0]->name, FlowCtrl_B[pAC->Index]);
+ IsFlowCtrlDefined = SK_FALSE;
}
- else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
- pAC->GIni.GP[1].PFlowCtrlMode =
- SK_FLOW_MODE_SYM_OR_REM;
- }
- else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
- pAC->GIni.GP[1].PFlowCtrlMode =
- SK_FLOW_MODE_SYMMETRIC;
- }
- else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
- pAC->GIni.GP[1].PFlowCtrlMode =
- SK_FLOW_MODE_LOC_SEND;
- }
- else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
- pAC->GIni.GP[1].PFlowCtrlMode =
- SK_FLOW_MODE_NONE;
- }
- else printk("Illegal value for FlowCtrl_B\n");
+ } else {
+ IsFlowCtrlDefined = SK_FALSE;
}
- if (AutoNeg==AN_OFF && pAC->GIni.GP[1].PFlowCtrlMode!=
- SK_FLOW_MODE_NONE) {
+
+ if (IsFlowCtrlDefined) {
+ if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
printk("%s, Port B: FlowControl"
" impossible without AutoNegotiation,"
" disabled\n", pAC->dev[1]->name);
- pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ FlowCtrl = SK_FLOW_MODE_NONE;
+ }
+ pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
}
- MSMode = SK_MS_MODE_AUTO; /* default: do auto select */
+ /*
+ ** d) What is the RoleParameter?
+ */
if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
Role_B[pAC->Index] != NULL) {
if (strcmp(Role_B[pAC->Index],"")==0) {
+ IsRoleDefined = SK_FALSE;
+ } else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
+ MSMode = SK_MS_MODE_AUTO;
+ } else if (strcmp(Role_B[pAC->Index],"Master")==0) {
+ MSMode = SK_MS_MODE_MASTER;
+ } else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
+ MSMode = SK_MS_MODE_SLAVE;
+ } else {
+ printk("%s: Illegal value \"%s\" for Role_B\n",
+ pAC->dev[1]->name, Role_B[pAC->Index]);
+ IsRoleDefined = SK_FALSE;
}
- else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- }
- else if (strcmp(Role_B[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- }
- else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- }
- else printk("%s: Illegal value for Role_B\n",
- pAC->dev[1]->name);
+ } else {
+ IsRoleDefined = SK_FALSE;
+ }
+
+ if (IsRoleDefined) {
+ pAC->GIni.GP[1].PMSMode = MSMode;
}
- pAC->GIni.GP[1].PMSMode = MSMode;
-
- /* settings for both ports */
+ /*
+ ** Evaluate settings for both ports
+ */
pAC->ActivePort = 0;
if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
PrefPort[pAC->Index] != NULL) {
if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
- pAC->ActivePort = 0;
- pAC->Rlmt.Net[0].Preference = -1; /* auto */
- pAC->Rlmt.Net[0].PrefPort = 0;
- }
- else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
- /*
- * do not set ActivePort here, thus a port
- * switch is issued after net up.
- */
- Port = 0;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
- }
- else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
- /*
- * do not set ActivePort here, thus a port
- * switch is issued after net up.
- */
- Port = 1;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
+ pAC->ActivePort = 0;
+ pAC->Rlmt.Net[0].Preference = -1; /* auto */
+ pAC->Rlmt.Net[0].PrefPort = 0;
+ } else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
+ /*
+ ** do not set ActivePort here, thus a port
+ ** switch is issued after net up.
+ */
+ Port = 0;
+ pAC->Rlmt.Net[0].Preference = Port;
+ pAC->Rlmt.Net[0].PrefPort = Port;
+ } else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
+ /*
+ ** do not set ActivePort here, thus a port
+ ** switch is issued after net up.
+ */
+ Port = 1;
+ pAC->Rlmt.Net[0].Preference = Port;
+ pAC->Rlmt.Net[0].PrefPort = Port;
+ } else {
+ printk("%s: Illegal value \"%s\" for PrefPort\n",
+ pAC->dev[0]->name, PrefPort[pAC->Index]);
}
- else printk("%s: Illegal value for PrefPort\n",
- pAC->dev[0]->name);
}
pAC->RlmtNets = 1;
-
+
if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
RlmtMode[pAC->Index] != NULL) {
if (strcmp(RlmtMode[pAC->Index], "") == 0) {
pAC->RlmtMode = 0;
- }
- else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+ } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- }
- else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK;
- }
- else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+ } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK |
- SK_RLMT_CHECK_SEG;
- }
- else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
+ SK_RLMT_CHECK_LOC_LINK;
+ } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+ pAC->RlmtMode = SK_RLMT_CHECK_LINK |
+ SK_RLMT_CHECK_LOC_LINK |
+ SK_RLMT_CHECK_SEG;
+ } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
(pAC->GIni.GIMacsFound == 2)) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- pAC->RlmtNets = 2;
- }
- else {
- printk("%s: Illegal value for"
- " RlmtMode, using default\n", pAC->dev[0]->name);
-
-printk("MacFound = %d\nRlmtMode = %s", pAC->GIni.GIMacsFound, RlmtMode[pAC->Index]);
-
-
+ pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+ pAC->RlmtNets = 2;
+ } else {
+ printk("%s: Illegal value \"%s\" for"
+ " RlmtMode, using default\n",
+ pAC->dev[0]->name, RlmtMode[pAC->Index]);
pAC->RlmtMode = 0;
}
- }
- else {
+ } else {
pAC->RlmtMode = 0;
}
+
+ /*
+ ** Check the interrupt moderation parameters
+ */
+ if (Moderation[pAC->Index] != NULL) {
+ if (strcmp(Moderation[pAC->Index], "Static") == 0) {
+ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+ } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
+ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
+ } else {
+ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+ }
+ } else {
+ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+ }
+
+ if (Stats[pAC->Index] != NULL) {
+ if (strcmp(Stats[pAC->Index], "Yes") == 0) {
+ pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
+ } else {
+ pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+ }
+ } else {
+ pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+ }
+
+ if (ModerationMask[pAC->Index] != NULL) {
+ if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+ } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
+ } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+ } else { /* some rubbish */
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+ }
+ } else { /* operator has stated nothing */
+ pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+ }
+
+ if (AutoSizing[pAC->Index] != NULL) {
+ if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
+ pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+ } else {
+ pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+ }
+ } else { /* operator has stated nothing */
+ pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+ }
+
+ if (IntsPerSec[pAC->Index] != 0) {
+ if ((IntsPerSec[pAC->Index]< 30)&&(IntsPerSec[pAC->Index]> 40000)) {
+ pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+ } else {
+ pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+ }
+ } else {
+ pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+ }
+
+ /*
+ ** Evaluate upper and lower moderation threshold
+ */
+ pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+ pAC->DynIrqModInfo.MaxModIntsPerSec +
+ (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+
+ pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+ pAC->DynIrqModInfo.MaxModIntsPerSec -
+ (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+
+ pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */
+
+
} /* GetConfiguration */
}
} /* ProductStr */
+/*****************************************************************************
+ *
+ * StartDrvCleanupTimer - Start timer to check for descriptors which
+ * might be placed in descriptor ring, but
+ * havent been handled up to now
+ *
+ * Description:
+ * This function requests a HW-timer fo the Yukon card. The actions to
+ * perform when this timer expires, are located in the SkDrvEvent().
+ *
+ * Returns: N/A
+ */
+static void
+StartDrvCleanupTimer(SK_AC *pAC) {
+ SK_EVPARA EventParam; /* Event struct for timer event */
+
+ SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+ EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
+ SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
+ SK_DRV_RX_CLEANUP_TIMER_LENGTH,
+ SKGE_DRV, SK_DRV_TIMER, EventParam);
+}
-
+/*****************************************************************************
+ *
+ * StopDrvCleanupTimer - Stop timer to check for descriptors
+ *
+ * Description:
+ * This function requests a HW-timer fo the Yukon card. The actions to
+ * perform when this timer expires, are located in the SkDrvEvent().
+ *
+ * Returns: N/A
+ */
+static void
+StopDrvCleanupTimer(SK_AC *pAC) {
+ SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
+ SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
+}
/****************************************************************************/
/* functions for common modules *********************************************/
* Nothing
*/
void SkDrvFreeRlmtMbuf(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* the IO-context */
+SK_AC *pAC, /* pointer to adapter context */
+SK_IOC IoC, /* the IO-context */
SK_MBUF *pMbuf) /* size of the requested buffer */
{
SK_MBUF *pFreeMbuf;
*/
SK_U64 SkOsGetTime(SK_AC *pAC)
{
- return jiffies;
+ SK_U64 PrivateJiffies;
+ SkOsGetTimeCurrent(pAC, &PrivateJiffies);
+ return PrivateJiffies;
} /* SkOsGetTime */
int PciAddr, /* PCI register address */
SK_U32 *pVal) /* pointer to store the read value */
{
- pci_read_config_dword(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgDWord */
int PciAddr, /* PCI register address */
SK_U16 *pVal) /* pointer to store the read value */
{
- pci_read_config_word(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_word(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgWord */
int PciAddr, /* PCI register address */
SK_U8 *pVal) /* pointer to store the read value */
{
- pci_read_config_byte(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgByte */
int PciAddr, /* PCI register address */
SK_U32 Val) /* pointer to store the read value */
{
- pci_write_config_dword(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_dword(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgDWord */
* Description:
* This routine writes a 16 bit value to the pci configuration
* space. The flag PciConfigUp indicates whether the config space
- * is accessible or must be set up first.
+ * is accesible or must be set up first.
*
* Returns:
* 0 - indicate everything worked ok.
int PciAddr, /* PCI register address */
SK_U16 Val) /* pointer to store the read value */
{
- pci_write_config_word(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_word(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgWord */
* Description:
* This routine writes a 8 bit value to the pci configuration
* space. The flag PciConfigUp indicates whether the config space
- * is accessible or must be set up first.
+ * is accesible or must be set up first.
*
* Returns:
* 0 - indicate everything worked ok.
int PciAddr, /* PCI register address */
SK_U8 Val) /* pointer to store the read value */
{
- pci_write_config_byte(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_byte(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgByte */
SK_EVPARA NewPara; /* parameter for further events */
int Stat;
unsigned long Flags;
+SK_BOOL DualNet;
switch (Event) {
case SK_DRV_ADAP_FAIL:
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+ pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
spin_unlock_irqrestore(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
/* clear rx ring from received frames */
- ReceiveIrq(pAC, &pAC->RxPort[FromPort]);
+ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
spin_lock_irqsave(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
- SkGeInitPort(pAC, IoC, FromPort);
+
+ /* tschilling: Handling of return value inserted. */
+ if (SkGeInitPort(pAC, IoC, FromPort)) {
+ if (FromPort == 0) {
+ printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+ } else {
+ printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+ }
+ }
SkAddrMcUpdate(pAC,IoC, FromPort);
PortReInitBmu(pAC, FromPort);
SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
("NET UP EVENT, Port: %d ", Param.Para32[0]));
printk("%s: network connection up using"
" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
- printk(" speed: 1000\n");
+
+ /* tschilling: Values changed according to LinkSpeedUsed. */
+ Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+ if (Stat == SK_LSPEED_STAT_10MBPS) {
+ printk(" speed: 10\n");
+ } else if (Stat == SK_LSPEED_STAT_100MBPS) {
+ printk(" speed: 100\n");
+ } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+ printk(" speed: 1000\n");
+ } else {
+ printk(" speed: unknown\n");
+ }
+
+ /* Mac update */
+ SkAddrMcUpdate(pAC,IoC, FromPort);
+
Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
if (Stat == SK_LMODE_STAT_AUTOHALF ||
Stat == SK_LMODE_STAT_AUTOFULL) {
else {
printk(" flowctrl: none\n");
}
- if (pAC->GIni.GP[FromPort].PhyType != SK_PHY_XMAC) {
- Stat = pAC->GIni.GP[FromPort].PMSStatus;
+
+ /* tschilling: Check against CopperType now. */
+ if ((pAC->GIni.GICopperType == SK_TRUE) &&
+ (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+ SK_LSPEED_STAT_1000MBPS)) {
+ Stat = pAC->GIni.GP[FromPort].PMSStatus;
if (Stat == SK_MS_STAT_MASTER ) {
printk(" role: master\n");
}
printk(" role: ???\n");
}
}
-
- if ((Param.Para32[0] != pAC->ActivePort) &&
+
+#ifdef SK_ZEROCOPY
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON)
+#ifdef USE_SK_TX_CHECKSUM
+ printk(" scatter-gather: enabled\n");
+#else
+ printk(" tx-checksum: disabled\n");
+#endif
+ else
+ printk(" scatter-gather: disabled\n");
+#else
+ printk(" scatter-gather: disabled\n");
+#endif
+
+#ifndef USE_SK_RX_CHECKSUM
+ printk(" rx-checksum: disabled\n");
+#endif
+
+
+ if ((Param.Para32[0] != pAC->ActivePort) &&
(pAC->RlmtNets == 1)) {
NewPara.Para32[0] = pAC->ActivePort;
NewPara.Para32[1] = Param.Para32[0];
SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
NewPara);
}
+
+ /* Inform the world that link protocol is up. */
+ pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+
break;
case SK_DRV_NET_DOWN: /* SK_U32 Reason */
/* action list 7 */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
("NET DOWN EVENT "));
printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name);
+ pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
break;
case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
- ReceiveIrq(pAC, &pAC->RxPort[FromPort]); /* clears rx ring */
- ReceiveIrq(pAC, &pAC->RxPort[ToPort]); /* clears rx ring */
+ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+ ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
spin_lock_irqsave(
&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
pAC->ActivePort = ToPort;
+#if 0
SetQueueSizes(pAC);
- SkGeInitPort(pAC, IoC, FromPort);
- SkGeInitPort(pAC, IoC, ToPort);
+#else
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+ if (pAC->RlmtNets == 2) {
+ DualNet = SK_TRUE;
+ }
+
+ if (SkGeInitAssignRamToQueues(
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+ spin_unlock_irqrestore(
+ &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+ printk("SkGeInitAssignRamToQueues failed.\n");
+ break;
+ }
+#endif
+ /* tschilling: Handling of return values inserted. */
+ if (SkGeInitPort(pAC, IoC, FromPort) ||
+ SkGeInitPort(pAC, IoC, ToPort)) {
+ printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+ }
if (Event == SK_DRV_SWITCH_SOFT) {
- SkXmRxTxEnable(pAC, IoC, FromPort);
+ SkMacRxTxEnable(pAC, IoC, FromPort);
}
- SkXmRxTxEnable(pAC, IoC, ToPort);
+ SkMacRxTxEnable(pAC, IoC, ToPort);
SkAddrSwap(pAC, IoC, FromPort, ToPort);
SkAddrMcUpdate(pAC, IoC, FromPort);
SkAddrMcUpdate(pAC, IoC, ToPort);
pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
skb_put(pMsg, pRlmtMbuf->Length);
if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
- pMsg) < 0)
+ pMsg) < 0)
+
DEV_KFREE_SKB_ANY(pMsg);
break;
+ case SK_DRV_TIMER:
+ if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+ /*
+ ** expiration of the moderation timer implies that
+ ** dynamic moderation is to be applied
+ */
+ SkDimStartModerationTimer(pAC);
+ SkDimModerate(pAC);
+ if (pAC->DynIrqModInfo.DisplayStats) {
+ SkDimDisplayModerationSettings(pAC);
+ }
+ } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
+ /*
+ ** check if we need to check for descriptors which
+ ** haven't been handled the last millisecs
+ */
+ StartDrvCleanupTimer(pAC);
+ if (pAC->GIni.GIMacsFound == 2) {
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
+ }
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
+ } else {
+ printk("Expiration of unknown timer\n");
+ }
+ break;
default:
break;
}
} /* SkErrorLog */
-#ifdef DEBUG /***************************************************************/
+#ifdef DEBUG
+/****************************************************************************/
/* "debug only" section *****************************************************/
/****************************************************************************/
* DumpData - print a data area
*
* Description:
- * This function prints a area of data to the system logfile/to the
+ * This function prints a area of data to the system logfile/to the
* console.
*
* Returns: N/A
* DumpLong - print a data area as long values
*
* Description:
- * This function prints a area of data to the system logfile/to the
+ * This function prints a area of data to the system logfile/to the
* console.
*
* Returns: N/A
printk("------------------------\n");
} /* DumpLong */
-#endif /* DEBUG */
-
-static struct pci_device_id skge_pci_tbl[] __devinitdata = {
- { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE,
- PCI_ANY_ID, PCI_ANY_ID, },
- { 0,}
-};
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
- .name = DRV_MODULE_NAME,
- .id_table = skge_pci_tbl,
- .probe = skge_init_one,
- .remove = __devexit_p(skge_remove_one),
-};
+#endif
-/*****************************************************************************
- *
- * skge_init - module initialization function
+/*******************************************************************************
*
- * Description:
- * root /proc directory allocation and pci driver invocation.
+ * End of file
*
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int __init skge_init(void)
-{
- int ret = -ENOMEM;
-
- /* just to avoid warnings ... */
- debug = 0;
- options[0] = 0;
-
- pSkRootDir = create_proc_entry(DRV_MODULE_NAME,
- S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
- if (pSkRootDir) {
- pSkRootDir->owner = THIS_MODULE;
- ret = pci_module_init(&skge_driver);
- if (ret)
- remove_proc_entry(pSkRootDir->name, proc_net);
- }
- return ret;
-} /* skge_init */
-
-
-static void __exit skge_cleanup(void)
-{
- remove_proc_entry(pSkRootDir->name, proc_net);
- pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_cleanup);
-
-/*
- * Local variables:
- * compile-command: "make"
- * End:
- */
+ ******************************************************************************/