📄 skge.c
字号:
/****************************************************************************** * * Name: skge.c * Project: GEnesis, PCI Gigabit Ethernet Adapter * Version: $Revision: 1.74.2.66 $ * Date: $Date: 2008/03/04 13:49:19 $ * Purpose: The main driver source module * ******************************************************************************//****************************************************************************** * * (C)Copyright 1998-2002 SysKonnect GmbH. * (C)Copyright 2002-2007 Marvell. * * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet * Server Adapters. * * Address all question to: gr-msgg-linux@marvell.com * * LICENSE: * (C)Copyright Marvell. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. * /LICENSE * *****************************************************************************//****************************************************************************** * * Description: * * All source files in this sk98lin directory except of the sk98lin * Linux specific files * * - skdim.c * - skethtool.c * - skge.c * - skproc.c * - sky2.c * - Makefile * - h/skdrv1st.h * - h/skdrv2nd.h * - h/sktypes.h * - h/skversion.h * * are part of SysKonnect's common modules for the SK-9xxx adapters. * * Those common module files which are not Linux specific are used to * build drivers on different OS' (e.g. Windows, MAC OS) so that those * drivers are based on the same set of files * * At a first glance, this seems to complicate things unnescessarily on * Linux, but please do not try to 'clean up' them without VERY good * reasons, because this will make it more difficult to keep the sk98lin * driver for Linux in synchronisation with the other drivers running on * other operating systems. * ******************************************************************************/#include "h/skversion.h"#include <linux/module.h>#include <linux/init.h>#include <linux/ethtool.h>#ifdef USE_ASF_DASH_FW#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <net/if_inet6.h>#include <linux/ipv6.h>#endif#ifdef CONFIG_PROC_FS#include <linux/proc_fs.h>#endif#include "h/skdrv1st.h"#include "h/skdrv2nd.h"#include "h/skpcidevid.h"#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)#include <linux/moduleparam.h>#endif#undef ENABLE_FUTURE_ETH/******************************************************************************* * * Defines * ******************************************************************************//* for debuging on x86 only *//* #define BREAKPOINT() asm(" int $3"); *//* Set blink mode*/#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \ SK_DUP_LED_NORMAL | \ SK_LED_LINK100_ON)#define CLEAR_AND_START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START | CSR_IRQ_CL_F)#define START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START)#define CLEAR_TX_IRQ(Port,Prio) SK_OUT8(pAC->IoBase, TxQueueAddr[(Port)][(Prio)]+Q_CSR, CSR_IRQ_CL_F)/******************************************************************************* * * Local Function Prototypes * ******************************************************************************/static int __devinit sk98lin_init_device(struct pci_dev *pdev, const struct pci_device_id *ent);static void sk98lin_remove_device(struct pci_dev *pdev);#ifdef CONFIG_PM#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)static int sk98lin_suspend(struct pci_dev *pdev, pm_message_t state);#elsestatic int sk98lin_suspend(struct pci_dev *pdev, SK_U32 state);#endifstatic int sk98lin_resume(struct pci_dev *pdev);static void SkEnableWOMagicPacket(SK_AC *pAC, SK_IOC IoC, SK_MAC_ADDR MacAddr);#endif#ifdef USE_ASF_DASH_FWstatic void SkSetFWLinkParams(SK_AC *pAC, SK_IOC IoC, int Port);static void SkGeHandleLLCTimer(unsigned long ptr);static void SkGeHandleWakeupTimer(unsigned long ptr);#endif#ifdef Y2_RECOVERYstatic void SkGeHandleKernelTimer(unsigned long ptr);void SkGeCheckTimer(DEV_NET *pNet);static SK_BOOL CheckRXCounters(DEV_NET *pNet);static void CheckRxPath(DEV_NET *pNet);#endifstatic 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*, int*, SK_BOOL);#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)static SkIsrRetVar SkGeIsr(int irq, void *dev_id);#elsestatic SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id);#elsestatic SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);#endifstatic 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*);#ifdef CONFIG_SK98LIN_NAPIstatic int SkGePoll(struct net_device *dev, int *budget);static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL, int*, int);#elsestatic void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);#endif#ifdef SK_POLL_CONTROLLERstatic void SkGeNetPoll(struct SK_NET_DEVICE *dev);#endifstatic void ClearRxRing(SK_AC*, RX_PORT*);static void ClearTxRing(SK_AC*, TX_PORT*);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 int SkGeInitPCI(SK_AC *pAC);static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName);static int SkDrvInitAdapter(SK_AC *pAC, int devNbr);static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);extern void SkLocalEventQueue( SK_AC *pAC, SK_U32 Class, SK_U32 Event, SK_U32 Param1, SK_U32 Param2, SK_BOOL Flag);extern void SkLocalEventQueue64( SK_AC *pAC, SK_U32 Class, SK_U32 Event, SK_U64 Param, SK_BOOL Flag);static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);/******************************************************************************* * * Extern Function Prototypes * ******************************************************************************/extern SK_BOOL SkY2AllocateResources(SK_AC *pAC);extern void SkY2FreeResources(SK_AC *pAC);extern void SkY2AllocateRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);extern void SkY2FreeRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);extern void SkY2FreeTxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);#ifdef USE_ASF_DASH_FWextern void SkSendLLCPacket(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)extern SkIsrRetVar SkY2Isr(int irq,void *dev_id);#elseextern SkIsrRetVar SkY2Isr(int irq,void *dev_id,struct pt_regs *ptregs);#endifextern int SkY2Xmit(struct sk_buff *skb,struct SK_NET_DEVICE *dev);extern void SkY2PortStop(SK_AC *pAC,SK_IOC IoC,int Port,int Dir,int RstMode);extern void SkY2PortStart(SK_AC *pAC,SK_IOC IoC,int Port);extern int SkY2RlmtSend(SK_AC *pAC,int PortNr,struct sk_buff *pMessage);extern void SkY2RestartStatusUnit(SK_AC *pAC);extern void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);#ifdef CONFIG_SK98LIN_NAPIextern int SkY2Poll(struct net_device *dev, int *budget);#endifextern void SkDimEnableModerationIfNeeded(SK_AC *pAC); extern void SkDimStartModerationTimer(SK_AC *pAC);extern void SkDimModerate(SK_AC *pAC);#ifndef ENABLE_FUTURE_ETHextern int SkEthIoctl(struct net_device *netdev, struct ifreq *ifr);#else/* Ethtool functions */extern int SkGeGetSettings(struct net_device *dev, struct ethtool_cmd *ecmd);extern void SkGeGetDrvInfo(struct net_device *dev, struct ethtool_drvinfo *ecmd);extern void SkGeGetWolSettings(struct net_device *dev, struct ethtool_wolinfo *ecmd);extern void SkGeGetPauseParam(struct net_device *dev, struct ethtool_pauseparam *ecmd);extern int SkGeGetCoalesce(struct net_device *dev, struct ethtool_coalesce *ecmd);extern SK_U32 SkGeGetRxCsum(struct net_device *dev);extern void SkGeGetStrings(struct net_device *dev, u32 stringset, u8 *strings);extern int SkGeGetStatsLen(struct net_device *dev);extern void SkGeGetEthStats(struct net_device *dev, struct ethtool_stats *stats, u64 *data);extern int SkGeSetSettings(struct net_device *dev, struct ethtool_cmd *ecmd);extern int SkGeSetWolSettings(struct net_device *dev, struct ethtool_wolinfo *ewol);extern int SkGeSetPauseParam(struct net_device *dev, struct ethtool_pauseparam *ecmd);extern int SkGeSetCoalesce(struct net_device *dev, struct ethtool_coalesce *ecmd);extern int SkGeSetSG(struct net_device *dev, u32 data);extern int SkGeSetTxCsum(struct net_device *dev, u32 data);extern int SkGeSetRxCsum(struct net_device *dev, u32 data);extern int SkGePhysId(struct net_device *dev, u32 data);#endif#ifdef NETIF_F_TSOextern int SkGeSetTSO(struct net_device *netdev, u32 data);#endif#ifdef CONFIG_PROC_FSstatic 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);#endif#ifdef DEBUGstatic void DumpMsg(struct sk_buff*, char*);static void DumpData(char*, int);static void DumpLong(char*, int);#endif#ifdef USE_ASF_DASH_FWstatic int RamReadAddr(SK_AC *, SK_U32 , SK_U32 *, SK_U32 *, int);static int RamWriteAddr(SK_AC *, SK_U32 , SK_U32 , SK_U32 , int);#endif/* global variables *********************************************************/static const char *BootString = BOOT_STRING;struct SK_NET_DEVICE *SkGeRootDev = NULL;static SK_BOOL DoPrintInterfaceChange = SK_TRUE;/* local variables **********************************************************/static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};static int sk98lin_max_boards_found = 0;#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *pSkRootDir;#endifMODULE_DEVICE_TABLE(pci, sk98lin_pci_tbl);static struct pci_driver sk98lin_driver = { .name = DRIVER_FILE_NAME, .id_table = sk98lin_pci_tbl, .probe = sk98lin_init_device, .remove = __devexit_p(sk98lin_remove_device),#ifdef CONFIG_PM .suspend = sk98lin_suspend, .resume = sk98lin_resume#endif};/***************************************************************************** * * sk98lin_init_device - initialize the adapter * * Description: * This function initializes the adapter. Resources for * the adapter are allocated and the adapter is brought into Init 1 * state. * * Returns: * 0, if everything is ok * !=0, on error */static int __devinit sk98lin_init_device(struct pci_dev *pdev, const struct pci_device_id *ent){ static SK_BOOL sk98lin_boot_string = SK_FALSE; static SK_BOOL sk98lin_proc_entry = SK_FALSE; static int sk98lin_boards_found = 0; SK_AC *pAC; DEV_NET *pNet = NULL; struct SK_NET_DEVICE *dev = NULL; int retval;#ifdef CONFIG_PROC_FS int proc_root_initialized = 0; struct proc_dir_entry *pProcFile;#endif int pci_using_dac; retval = pci_enable_device(pdev); if (retval) { printk(KERN_ERR "Cannot enable PCI device, " "aborting.\n"); return retval; } dev = NULL; pNet = NULL; /* INSERT * We have to find the power-management capabilities */ /* Find power-management capability. */ pci_using_dac = 0; /* Set 32 bit DMA per default */ /* Configure DMA attributes. */ retval = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL); if (!retval) { pci_using_dac = 1; } else { retval = pci_set_dma_mask(pdev, (u64) 0xffffffff); if (retval) { printk(KERN_ERR "No usable DMA configuration, " "aborting.\n"); return retval; } } if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) { printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); return -ENODEV; } pNet = dev->priv; pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); if (pNet->pAC == NULL){ unregister_netdev(dev); dev->get_stats = NULL; kfree(dev->priv); printk(KERN_ERR "Unable to allocate adapter " "structure!\n"); return -ENODEV; } /* Print message */ if (!sk98lin_boot_string) { /* set display flag to TRUE so that */ /* we only display this string ONCE */ sk98lin_boot_string = SK_TRUE; printk("%s\n", BootString); } 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; dev->irq = pdev->irq; retval = SkGeInitPCI(pAC); if (retval) { printk("SKGE: PCI setup failed: %i\n", retval); unregister_netdev(dev); dev->get_stats = NULL; kfree(dev); return -ENODEV; } dev->open = &SkGeOpen; dev->stop = &SkGeClose; 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_POLL_CONTROLLER dev->poll_controller = SkGeNetPoll;#endif pAC->Index = sk98lin_boards_found; if (SkGeBoardInit(dev, pAC)) { unregister_netdev(dev); kfree(dev); return -ENODEV; } else { ProductStr(pAC); } if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; /* shifter to later moment in time... */ if (CHIP_ID_YUKON_2(pAC)) { dev->hard_start_xmit = &SkY2Xmit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -