⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsmos.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
📖 第 1 页 / 共 4 页
字号:

//******************************************************************************
//
//  NSMOS.C
//
//  Copyright (c) 2005 National Semiconductor Corporation.
//  All Rights Reserved
//
//  NSM Driver for MPL based MacPhyter Devices
//
//******************************************************************************

#include <nsm.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("NSC");
MODULE_DESCRIPTION("NSC DP8381X 10/100Mbps MacPhyter Ethernet");

// Max NICs supported by this driver
#define DP_MAX_NIC 8

// Globals                                                           
char DP_driverName[] = "DP8381X";
char DP_driverString[]="NSC Macphyter Driver";
char DP_driverVersionMaj = 1;  // Major Ver
char DP_driverVersionMin = 6;  // Minor Ver
char DP_driverVersion[] = "n.1.6";
char DP_copyright[] = "Copyright (c) 2005-2007 National Semiconductor";
char DP83815_ID[] = "DP83815 (MacPhyter-I)";
char DP83816_ID[] = "DP83816 (MacPhyter-II)";
char DP83818_ID[] = "DP83818 (MacPhyter-III)";
char UNKNOWN_ID[] = "UNKNOWN";

// Module Params

// Initialize all to -1 i.e not configured
#define DP_PARAM_INIT { [0 ... (DP_MAX_NIC - 1)] = -1}

#define DP_PARAM(PARM, DESC) \
static const int __devinitdata PARM[DP_MAX_NIC] = DP_PARAM_INIT; \
MODULE_PARM(PARM, "1-" __MODULE_STRING(DP_MAX_NIC) "i"); \
MODULE_PARM_DESC(PARM, DESC);

// Number of Transmit Descriptors (32bytes each)
// Default : 64
DP_PARAM(TxDCnt, "Number Of Transmit Descriptors");

// Number of Transmit Queues to be enabled
// Default : 1, Max : 4 (only on DP83818)
DP_PARAM(TxQCnt, "Number Of Transmit Queues");

// Number of Receive Descriptors (32bytes each)
// Default : 64
DP_PARAM(RxDCnt, "Number Of Receive Descriptors");

// Number of Receive Queues to be enabled
// Default : 1, Max : 1
DP_PARAM(RxQCnt, "Number Of Receive Queues");

// Desired Link Setup Mode
// 0 : Auto Negotiate (Default)
// 1 : Force Speed and Duplex Mode
DP_PARAM(LinkMode, "Link Setup Mode");

// Desired Link Speed 
// Note : If set in AutoNeg mode then this is the Max speed advertized
// 0 : 100Mbps (Default)
// 1 : 10Mbps 
DP_PARAM(LinkSpeed, "Link Speed");

// Desired Link Duplex Mode
// Note : If set in AutoNeg mode then this is the mode advertized
// 0 : Full Duplex (Default)
// 1 : Half Duplex
DP_PARAM(LinkDuplex, "Link Duplex Mode");

// Desired Link Pause Mode
// Note : If set in AutoNeg mode then this is the mode advertized
// 0 : Receive Pause Only (Default)
// 1 : Transmit Pause Only 
// 2 : Transmit and Receive Pause (Symmetrical)
// 3 : No Pause generation
DP_PARAM(LinkPause, "Link Pause Mode");

// Interrupt Holdoff in usec (Micro)
// Default : 100
// Max : 25500 (i.e. 25.5 msec)
DP_PARAM(IntTimeHold, "Interrupt Holdoff");

// Interrupt Holdoff in Tx pkt count
// Default : 2
// Max : 63
DP_PARAM(IntTxHold, "Interrupt Holdoff in Tx Packets");

// Interrupt Holdoff in Rx pkt count
// Default : 2
// Max : 63
DP_PARAM(IntRxHold, "Interrupt Holdoff in Rx Packets");

// Driver Operation Mode
// 0 : Normal (Default)
// 1 : Monitor (National Semiconductor Internal)
// 2 : Load Only (National Semiconductor Internal)
DP_PARAM(OpMode, "Driver Operational Mode");

// Desired Wol Events (Logical OR)
// 0x01  :  MPL_WOL_MAGIC - Enable wake on Magic Pattern.
// 0x04  :  MPL_WOL_BROADCAST - Enable wake on any broadcast packet.
// 0x08  :  MPL_WOL_MULTICAST - Enable wake on multicast packet.
// 0x10  :  MPL_WOL_DIRECTED - Enable wake on directed (unicast) packet to 
//                             the device's address.
// 0x20  :  MPL_WOL_LINK - Enable wake on link status change.
// 0x40  :  MPL_WOL_ARP - Enable wake on any ARP packet.
DP_PARAM(Wol, "Wake-on-LAN Events");

#ifdef NSM_DIAG_MODE
// Number of pkts possible in the status queue
// Default : 256
DP_PARAM(DiagStsQueue, "Size of the Diag Status Queue");
#endif //NSM_DIAG_MODE

#ifdef NSM_DEBUG
// NSM (OS Specific Module) Debug Zones to be enabled
DP_PARAM(NsmDebugZones, "Debug Zones For NSM Module");

// MPL (Hardware Abstraction Layer) Debug Zones to be enabled
DP_PARAM(MplDebugZones, "Debug Zones For MPL Module");

// Debug Zones for this file
   NS_UINT NsmDbgSettings =
                     DBG_INFO | 
                     DBG_FUNC |
                     DBG_TMP  |
                     DBG_ERR; 

   NS_UINT MplPathZones = 
                     DZONE_MPL_INIT_DOWN |
                     DZONE_MPL_TRANS     |
                     DZONE_MPL_RECV      |
                     DZONE_MPL_INTR      |
                     DZONE_MPL_LINK      |
                     DZONE_MPL_PWR       |
                     DZONE_MPL_DIAG      |
                     DZONE_MPL_MISC;

   NS_UINT MplMsgZones = 
                     DZONE_MPL_INIT_DOWN |
                     DZONE_MPL_TRANS     |
                     DZONE_MPL_RECV      |
                     DZONE_MPL_INTR      |
                     DZONE_MPL_LINK      |
                     DZONE_MPL_PWR       |
                     DZONE_MPL_DIAG      |
                     DZONE_MPL_MISC;
#else
   NS_UINT NsmDbgSettings = 0x0; 
   NS_UINT MplPathZones = 0x0; 
   NS_UINT MplMsgZones = 0x0; 
#endif

// Adapter count
unsigned NsmAdapterCnt = 0x0;

/*********************************************************************
 *  PCI device list for NSC MacPhyter adapters
 *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
 *    Class, Class Mask, String Index }
 *  Last device should be 0
 *********************************************************************/

#define PCI_DEVICE_ID_DP8381X 0x0020
static struct pci_device_id DP_pciTable[] = {
   { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_DP8381X, 
     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
   { 0, }
};
MODULE_DEVICE_TABLE(pci, DP_pciTable);


// PCI driver struct for this driver
static struct pci_driver DP_driver = {
   name:     DP_driverName,
   id_table: DP_pciTable,
   probe:    NsmProbe,
   remove:   NsmRemove,
#ifdef CONFIG_PM
   suspend:  NsmSuspend,
   resume:   NsmResume
#endif
};

// Locals
static NS_VOID readPciInfo(NSM_CONTEXT *adapter);
static NS_VOID setDataFields(NSM_CONTEXT *adapter);
static NS_VOID readUserOptions(NSM_CONTEXT *adapter);
static NS_BOOLEAN configMac(NSM_CONTEXT *adapter);
static NS_BOOLEAN configLink(NSM_CONTEXT *adapter);
static NS_VOID linkTask(unsigned long data);

static 
NS_SINT __init NsmInitModule(void)
{
   NI(NsmInitModule);

   // Print driver ver
   printk(KERN_INFO"%s - version %s\n%s\n", DP_driverString,
                                   DP_driverVersion,
                                   DP_copyright);

   /* Register to PCI subsystem */
   NO(NsmInitModule);
   return pci_module_init(&DP_driver);
}

static 
NS_VOID __exit NsmExitModule(void)
{
   NI(NsmExitModule);
   // UnRegister from PCI subsystem
   pci_unregister_driver(&DP_driver);

   NO(NsmExitModule);
   return;
}

// Module entry/exit points
module_init(NsmInitModule);
module_exit(NsmExitModule);

NS_SINT
NsmProbe(struct pci_dev *pdev, const struct pci_device_id *id)
{
   struct net_device *netdev = NULL;
   NSM_CONTEXT *adapter;
   NS_CHAR *nicId = NULL;

   NI(NsmProbe);

   // Make sure we are not exceeding our max card count
   if (NsmAdapterCnt == DP_MAX_NIC)
   {
      NSM_DBG(DBG_ERR,("Card Found exceeds limit \n"));

      NO(NsmProbe);
      return -ENODEV;
   }
    
   // Enable this PCI device
   if(pci_enable_device(pdev) != 0) \
   {
      NSM_DBG(DBG_ERR,("pci_enable_device failed\n"));

      NO(NsmProbe);
      return -ENODEV;
   }

   // Set the device as Master capable
   pci_set_master(pdev);

   // Check to see if our PCI addressing needs are supported
   if(!pci_dma_supported(pdev, NSM_DMA_MASK))
   {
      NSM_DBG(DBG_ERR,("PCI DMA not supported by the system\n"));

      NO(NsmProbe);
      return -ENODEV;
   }
   else
      pdev->dma_mask = NSM_DMA_MASK;

   // Init the net device, allocate adapter context
   netdev = alloc_etherdev(sizeof (NSM_CONTEXT));
   if(netdev == NULL) 
   {
      NSM_DBG(DBG_ERR,("Unable to allocate net_device struct\n"));

      NO(NsmProbe);
      return -ENOMEM;
   }

   // Init adapter context
   adapter = (NSM_CONTEXT *) netdev->priv;
   memset(adapter, 0, sizeof(NSM_CONTEXT));
   adapter->netdev = netdev;
   adapter->pdev = pdev;
   adapter->regAddr = NULL;
   pci_set_drvdata(pdev, netdev);

   // Default MTU
   netdev->mtu = ENET_MTU;

   if (pci_request_regions(pdev, DP_driverName))
   {
      NSM_DBG(DBG_ERR,("pci_request_region failed\n"));
      NsmRemove(pdev);

      NO(NsmProbe);
      return -ENOMEM;
   }

#ifdef NSM_IO_MAP
   // We are operating on the IO space
   netdev->base_addr = pci_resource_start(pdev, BAR_0);
   adapter->regAddr =  (NS_VOID *)netdev->base_addr;
   netdev->mem_start = pci_resource_start(pdev, BAR_0);
   netdev->mem_end = netdev->mem_start + pci_resource_len(pdev, BAR_0);
#else
   // We are operating on the Mem space
   // Remap the IO region
   adapter->regAddr = ioremap(pci_resource_start(pdev, BAR_1), 
                               pci_resource_len(pdev, BAR_1));

   if(adapter->regAddr == NULL) 
   {
      NSM_DBG(DBG_ERR,("ioremap failed\n"));
      NsmRemove(pdev);

      NO(NsmProbe);
      return -ENOMEM;
   }
   else
   {
     // Let the Net stack know about the IO region
     netdev->base_addr =  pci_resource_start(pdev, BAR_1);
     netdev->mem_start = pci_resource_start(pdev, BAR_1);
     netdev->mem_end = netdev->mem_start + pci_resource_len(pdev, BAR_1);
   }
#endif

   // Read the Pci info
   readPciInfo(adapter);

   // Set default values for this adapter struct
   setDataFields(adapter);

   // Read module params and note in adapter struct
   readUserOptions(adapter);

   // Enable MPL debug levels
   MplDebEnablePathTracing(MplPathZones);
   MplDebEnableMsgsAndChecks(MplMsgZones);

   // MPL Intializations
   adapter->mplContext = NULL;
   if (MplInitialize(adapter, adapter->regAddr, adapter->opMode, 
                              &adapter->mplContext) 
        != NS_STATUS_SUCCESS)
   {
      NsmRemove(pdev);
      NO(NsmProbe);
      printk(KERN_INFO"%s - Failed to Initialize Device! \n", 
                                   DP_driverString);
      return -ENODEV;
   }

   // Set the Netdevice entry points for this adapter
   netdev->open               = &NsmOpen;
   netdev->stop               = &NsmClose;
   netdev->hard_start_xmit    = &NsmXmit;
   netdev->get_stats          = &NsmStats;
   netdev->set_multicast_list = &NsmSetMulti;
   netdev->set_mac_address    = &NsmSetMac;
   netdev->do_ioctl           = &NsmIoctl;
   netdev->change_mtu         = &NsmChangeMtu;

   // Register this device to Net Stack
   SET_MODULE_OWNER(netdev);
#ifdef L26
   SET_NETDEV_DEV(netdev, &pdev->dev);
#endif
   if (register_netdev(netdev))
   {
      NsmRemove(pdev);

      NO(NsmProbe);
      return -ENODEV;
   }
   else
   {
      adapter->netdevReg = NS_TRUE;
   }

   // Hold-off the netdev till we have a link
   netif_carrier_off(netdev);

   // Note our irq - The line itself requested after we are open
   netdev->irq = pdev->irq;

   // Set Netdevice features - FM: Checksum?
   netdev->features = NETIF_F_SG;

   // Note the instance count for this adapter and increment cards found
   adapter->cardIndex = ++NsmAdapterCnt;

   nicId = UNKNOWN_ID;
   if (adapter->opMode != MPL_MODE_LOAD_ONLY)
   {
      // Get the current mac addr
      MplGetMacAddress(adapter->mplContext, NS_FALSE, netdev->dev_addr);

      // Display device
      adapter->deviceId = MplGetDeviceId(adapter->mplContext);
      switch (adapter->deviceId)
      {
         case MPL_DEVICE_ID_DP83815 : nicId = DP83815_ID;
                                      break;
         case MPL_DEVICE_ID_DP83816 : nicId = DP83816_ID;
                                      break;
         case MPL_DEVICE_ID_DP83818 : nicId = DP83818_ID;
                                      break;
         default                    : nicId = UNKNOWN_ID;
      }
   }

   adapter->verMajor = DP_driverVersionMaj;
   adapter->verMinor = DP_driverVersionMin;

   printk("%s: v-%d.%d NSC-%s:%x-%x Mem:0x%p  IRQ:%d  RegAddr:0x%p Mode:%d \n",
             netdev->name,adapter->verMajor, adapter->verMinor,
              nicId, adapter->pciSubVendorId, 
               adapter->pciSubDeviceId, (void *)netdev->mem_start, netdev->irq,
                adapter->regAddr, adapter->opMode);

   // AOK!
   NO(NsmProbe);
   return 0;
}

#ifdef CONFIG_PM
NS_SINT
NsmSuspend(struct pci_dev *pdev, NS_UINT state)
{
   struct net_device *netdev = pci_get_drvdata(pdev);
   NSM_CONTEXT *adapter = (NSM_CONTEXT *) netdev->priv;
   MPL_STATUS status;

   rtnl_lock();
   if (netif_running(netdev)) 
   {
      // We are currently running so, prep for suspend
      
      // Disable further Interrupts
      MplInterruptDisable(adapter->mplContext);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -