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

📄 rcpci45.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ****  RCpci45.c  ********  ---------------------------------------------------------------------**  ---     Copyright (c) 1998, 1999, RedCreek Communications Inc.    ---**  ---                   All rights reserved.                        ---**  ---------------------------------------------------------------------**** Written by Pete Popov and Brian Moyle.**** Known Problems** ** None known at this time.****  TODO:**      -Get rid of the wait loops in the API and replace them**       with system independent delays ...something like**       "delayms(2)".  However, under normal circumstances, the **       delays are very short so they're not a problem.****  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.**  This program is distributed in the hope that it will be useful,**  but WITHOUT ANY WARRANTY; without even the implied warranty of**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the**  GNU General Public License for more details.**  You should have received a copy of the GNU General Public License**  along with this program; if not, write to the Free Software**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.****   **  Pete Popov, January 11,99: Fixed a couple of 2.1.x problems **  (virt_to_bus() not called), tested it under 2.2pre5 (as a module), and **  added a #define(s) to enable the use of the same file for both, the 2.0.x **  kernels as well as the 2.1.x.****  Ported to 2.1.x by Alan Cox 1998/12/9. ****  Sometime in mid 1998, written by Pete Popov and Brian Moyle.*****************************************************************************/static char *version ="RedCreek Communications PCI linux driver version 2.02\n";#include <linux/module.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/in.h>#include <linux/ioport.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/bios32.h>#include <linux/timer.h>#include <asm/irq.h>            /* For NR_IRQS only. */#include <asm/bitops.h>#include <asm/io.h>#if LINUX_VERSION_CODE >= 0x020100#define LINUX_2_1#endif#ifdef LINUX_2_1#include <asm/uaccess.h>#endif#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#define RC_LINUX_MODULE#include "rclanmtl.h"#include "rcif.h"#define RUN_AT(x) (jiffies + (x))#define NEW_MULTICAST#include <linux/delay.h>#ifndef LINUX_2_1#define ioremap vremap#define iounmap vfree#endif/* PCI/45 Configuration space values */#define RC_PCI45_VENDOR_ID  0x4916#define RC_PCI45_DEVICE_ID  0x1960#define MAX_ETHER_SIZE        1520  #define MAX_NMBR_RCV_BUFFERS    96#define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16#define BD_SIZE 3           /* Bucket Descriptor size */#define BD_LEN_OFFSET 2     /* Bucket Descriptor offset to length field *//* RedCreek LAN device Target ID */#define RC_LAN_TARGET_ID  0x10 /* RedCreek's OSM default LAN receive Initiator */#define DEFAULT_RECV_INIT_CONTEXT  0xA17  static U32 DriverControlWord =  0;static void rc_timer(unsigned long);/* * Driver Private Area, DPA. */typedef struct{    /*      *    pointer to the device structure which is part     * of the interface to the Linux kernel.     */    struct device *dev;                     char devname[8];                /* "ethN" string */    U8     id;                        /* the AdapterID */    U32    pci_addr;               /* the pci address of the adapter */    U32    bus;    U32    function;    struct timer_list timer;        /*  timer */    struct enet_statistics  stats; /* the statistics structure */    struct device *next;            /* points to the next RC adapter */    unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/    unsigned char shutdown;    unsigned char reboot;    unsigned char nexus;    PU8    PLanApiPA;             /* Pointer to Lan Api Private Area */}DPA, *PDPA;#define MAX_ADAPTERS 32static PDPA  PCIAdapters[MAX_ADAPTERS] = {    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};static int RCinit(struct device *dev);static int RCscan(struct device *dev);static int RCfound_device(struct device *, int, int, int, int, int, int);static int RCopen(struct device *);static int RC_xmit_packet(struct sk_buff *, struct device *);static void RCinterrupt(int, void *, struct pt_regs *);static int RCclose(struct device *dev);static struct enet_statistics *RCget_stats(struct device *);static int RCioctl(struct device *, struct ifreq *, int);static int RCconfig(struct device *, struct ifmap *);static void RCxmit_callback(U32, U16, PU32, U16);static void RCrecv_callback(U32, U8, U32, PU32, U16);static void RCreset_callback(U32, U32, U32, U16);static void RCreboot_callback(U32, U32, U32, U16);static int RC_allocate_and_post_buffers(struct device *, int);/* A list of all installed RC devices, for removing the driver module. */static struct device *root_RCdev = NULL;#ifdef MODULEint init_module(void)#elseint rcpci_probe(struct device *dev)#endif{    int cards_found;#ifdef MODULE    cards_found = RCscan(NULL);#else    cards_found = RCscan(dev);#endif    if (cards_found)        printk(version);    return cards_found ? 0 : -ENODEV;}static int RCscan(struct device *dev){    int cards_found = 0;    static int pci_index = 0;    if (!pcibios_present())         return cards_found;    for (;pci_index < 0x8; pci_index++)     {        unsigned char pci_bus, pci_device_fn;        int scan_status;        int board_index = 0;        unsigned char pci_irq_line;        unsigned short pci_command, vendor, device, class;        unsigned int pci_ioaddr;        scan_status =              (pcibios_find_device (RC_PCI45_VENDOR_ID,                                   RC_PCI45_DEVICE_ID,                                   pci_index,                                   &pci_bus,                                   &pci_device_fn));#ifdef RCDEBUG        printk("rc scan_status = 0x%X\n", scan_status);#endif        if (scan_status != PCIBIOS_SUCCESSFUL)            break;        pcibios_read_config_word(pci_bus,                                  pci_device_fn,                                  PCI_VENDOR_ID, &vendor);        pcibios_read_config_word(pci_bus,                                  pci_device_fn,                                 PCI_DEVICE_ID, &device);        pcibios_read_config_byte(pci_bus,                                  pci_device_fn,                                 PCI_INTERRUPT_LINE, &pci_irq_line);        pcibios_read_config_dword(pci_bus,                                   pci_device_fn,                                  PCI_BASE_ADDRESS_0, &pci_ioaddr);        pcibios_read_config_word(pci_bus,                                  pci_device_fn,                                 PCI_CLASS_DEVICE, &class);        pci_ioaddr &= ~0xf;#ifdef RCDEBUG        printk("rc: Found RedCreek PCI adapter\n");        printk("rc: pci class = 0x%x  0x%x \n", class, class>>8);        printk("rc: pci_bus = %d,  pci_device_fn = %d\n", pci_bus, pci_device_fn);        printk("rc: pci_irq_line = 0x%x \n", pci_irq_line);        printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr);#endif        if (check_region(pci_ioaddr, 2*32768))        {            printk("rc: check_region failed\n");            continue;        }#ifdef RCDEBUG        else        {            printk("rc: check_region passed\n");        }#endif                   /*         * Get and check the bus-master and latency values.         * Some PCI BIOSes fail to set the master-enable bit.         */        pcibios_read_config_word(pci_bus,                                  pci_device_fn,                                 PCI_COMMAND,                                  &pci_command);        if ( ! (pci_command & PCI_COMMAND_MASTER)) {            printk("rc: PCI Master Bit has not been set!\n");                                    pci_command |= PCI_COMMAND_MASTER;            pcibios_write_config_word(pci_bus,                                       pci_device_fn,                                      PCI_COMMAND,                                       pci_command);        }        if ( ! (pci_command & PCI_COMMAND_MEMORY)) {            /*             * If the BIOS did not set the memory enable bit, what else             * did it not initialize?  Skip this adapter.             */            printk("rc: Adapter %d, PCI Memory Bit has not been set!\n",                   cards_found);            printk("rc: Bios problem? \n");            continue;        }                        if (!RCfound_device(dev, pci_ioaddr, pci_irq_line,                          pci_bus, pci_device_fn,                          board_index++, cards_found))        {            dev = 0;            cards_found++;        }    }#ifdef RCDEBUG    printk("rc: found %d cards \n", cards_found);#endif    return cards_found;}static int RCinit(struct device *dev){    dev->open = &RCopen;    dev->hard_start_xmit = &RC_xmit_packet;    dev->stop = &RCclose;    dev->get_stats = &RCget_stats;    dev->do_ioctl = &RCioctl;    dev->set_config = &RCconfig;    return 0;}static intRCfound_device(struct device *dev, int memaddr, int irq,                int bus, int function, int product_index, int card_idx){    int dev_size = 32768;            unsigned long *vaddr=0;    PDPA pDpa;    int init_status;    /*      * Allocate and fill new device structure.      * We need enough for struct device plus DPA plus the LAN API private     * area, which requires a minimum of 16KB.  The top of the allocated     * area will be assigned to struct device; the next chunk will be     * assigned to DPA; and finally, the rest will be assigned to the     * the LAN API layer.     */#ifdef MODULE    dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);    if (!dev)    {        printk("rc: unable to kmalloc dev\n");        return 1;       }    memset(dev, 0, dev_size);    /*     * dev->priv will point to the start of DPA.     */    dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);#else    dev->priv = 0;    dev->priv = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);    if (!dev->priv)    {        printk("rc: unable to kmalloc private area\n");        return 1;      }    memset(dev->priv, 0, dev_size);#endif#ifdef RCDEBUG    printk("rc: dev = 0x%x, dev->priv = 0x%x\n", (uint)dev, (uint)dev->priv);#endif    pDpa = dev->priv;    if (!dev->name)        dev->name = pDpa->devname;    pDpa->dev = dev;            /* this is just for easy reference */    pDpa->function = function;    pDpa->bus = bus;    pDpa->id = card_idx;        /* the device number */    pDpa->pci_addr = memaddr;    PCIAdapters[card_idx] = pDpa;#ifdef RCDEBUG    printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);#endif    /*     * Save the starting address of the LAN API private area.  We'll     * pass that to RCInitI2OMsgLayer().     */    pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);#ifdef RCDEBUG    printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);#endif        /* The adapter is accessable through memory-access read/write, not     * I/O read/write.  Thus, we need to map it to some virtual address     * area in order to access the registers are normal memory.     */    vaddr = (ulong *) ioremap (memaddr, 2*32768);#ifdef RCDEBUG    printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n",            (uint)dev, (uint)dev->priv, (uint)vaddr);#endif    dev->base_addr = (unsigned long)vaddr;    dev->irq = irq;    dev->interrupt = 0;    /*     * Request a shared interrupt line.     */    if ( request_irq(dev->irq, (void *)RCinterrupt,                     SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )    {        printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );        iounmap(vaddr);        kfree(dev);        return 1;    }    init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr,                   pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA),                  (PFNTXCALLBACK)RCxmit_callback,                  (PFNRXCALLBACK)RCrecv_callback,                  (PFNCALLBACK)RCreboot_callback);    if (init_status)    {        printk("rc: Unable to initialize msg layer\n");        free_irq(dev->irq, dev);        iounmap(vaddr);        kfree(dev);        return 1;    }    if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))    {        printk("rc: Unable to get adapter MAC\n");        free_irq(dev->irq, dev);        iounmap(vaddr);        kfree(dev);        return 1;    }    DriverControlWord |= WARM_REBOOT_CAPABLE;    RCReportDriverCapability(pDpa->id, DriverControlWord);    dev->init = &RCinit;    ether_setup(dev);            /* linux kernel interface */    pDpa->next = root_RCdev;    root_RCdev = dev;#ifdef MODULE    if (register_netdev(dev) != 0) /* linux kernel interface */    {        printk("rc: unable to register device \n");        free_irq(dev->irq, dev);        iounmap(vaddr);        kfree(dev);        return 1;    }#else    RCinit(dev);#endif    printk("%s: RedCreek Communications IPSEC VPN adapter\n",        dev->name);    return 0; /* success */}static intRCopen(struct device *dev){    int post_buffers = MAX_NMBR_RCV_BUFFERS;    PDPA pDpa = (PDPA) dev->priv;    int count = 0;    int requested = 0;#ifdef RCDEBUG    printk("rc: RCopen\n");#endif    RCEnableI2OInterrupts(pDpa->id);    if (pDpa->nexus)    {        /* This is not the first time RCopen is called.  Thus,         * the interface was previously opened and later closed         * by RCclose().  RCclose() does a Shutdown; to wake up         * the adapter, a reset is mandatory before we can post         * receive buffers.  However, if the adapter initiated          * a reboot while the interface was closed -- and interrupts         * were turned off -- we need will need to reinitialize         * the adapter, rather than simply waking it up.           */

⌨️ 快捷键说明

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