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

📄 lmc_main.c

📁 hdlc wan 驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 /*  * Copyright (c) 1997-2000 LAN Media Corporation (LMC)  * All rights reserved.  www.lanmedia.com  *  * This code is written by:  * Andrew Stanley-Jones (asj@cban.com)  * Rob Braun (bbraun@vix.com),  * Michael Graff (explorer@vix.com) and  * Matt Thomas (matt@3am-software.com).  *  * With Help By:  * David Boggs  * Ron Crane  * Alan Cox  *  * This software may be used and distributed according to the terms  * of the GNU General Public License version 2, incorporated herein by reference.  *  * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.  *  * To control link specific options lmcctl is required.  * It can be obtained from ftp.lanmedia.com.  *  * Linux driver notes:  * Linux uses the device struct lmc_private to pass private information  * arround.  *  * The initialization portion of this driver (the lmc_reset() and the  * lmc_dec_reset() functions, as well as the led controls and the  * lmc_initcsrs() functions.  *  * The watchdog function runs every second and checks to see if  * we still have link, and that the timing source is what we expected  * it to be.  If link is lost, the interface is marked down, and  * we no longer can transmit.  *  *//* $Id: lmc_main.c,v 1.36 2000/04/11 05:25:25 asj Exp $ */#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/in.h>#include <linux/if_arp.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/inet.h>#include <net/syncppp.h>#include <asm/processor.h>             /* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>//#include <asm/spinlock.h>#define DRIVER_MAJOR_VERSION     1#define DRIVER_MINOR_VERSION    34#define DRIVER_SUB_VERSION       0#define DRIVER_VERSION  ((DRIVER_MAJOR_VERSION << 8) + DRIVER_MINOR_VERSION)#include "lmc.h"#include "lmc_var.h"#include "lmc_ioctl.h"#include "lmc_debug.h"#include "lmc_proto.h"static int lmc_first_load = 0;static int LMC_PKT_BUF_SZ = 1542;static struct pci_device_id lmc_pci_tbl[] = {	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,	  PCI_VENDOR_ID_LMC, PCI_ANY_ID },	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,	  PCI_ANY_ID, PCI_VENDOR_ID_LMC },	{ 0 }};MODULE_DEVICE_TABLE(pci, lmc_pci_tbl);MODULE_LICENSE("GPL");static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev);static int lmc_rx (struct net_device *dev);static int lmc_open(struct net_device *dev);static int lmc_close(struct net_device *dev);static struct net_device_stats *lmc_get_stats(struct net_device *dev);static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int lmc_set_config(struct net_device *dev, struct ifmap *map);static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);static void lmc_softreset(lmc_softc_t * const);static void lmc_running_reset(struct net_device *dev);static int lmc_ifdown(struct net_device * const);static void lmc_watchdog(unsigned long data);static void lmc_reset(lmc_softc_t * const sc);static void lmc_dec_reset(lmc_softc_t * const sc);static void lmc_driver_timeout(struct net_device *dev);/* * linux reserves 16 device specific IOCTLs.  We call them * LMCIOC* to control various bits of our world. */int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/{    lmc_softc_t *sc;    lmc_ctl_t ctl;    int ret;    u_int16_t regVal;    unsigned long flags;    struct sppp *sp;    ret = -EOPNOTSUPP;    sc = dev->priv;    lmc_trace(dev, "lmc_ioctl in");    /*     * Most functions mess with the structure     * Disable interrupts while we do the polling     */    spin_lock_irqsave(&sc->lmc_lock, flags);    switch (cmd) {        /*         * Return current driver state.  Since we keep this up         * To date internally, just copy this out to the user.         */    case LMCIOCGINFO: /*fold01*/        if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t)))            return -EFAULT;        ret = 0;        break;    case LMCIOCSINFO: /*fold01*/        sp = &((struct ppp_device *) dev)->sppp;        if (!capable(CAP_NET_ADMIN)) {            ret = -EPERM;            break;        }        if(dev->flags & IFF_UP){            ret = -EBUSY;            break;        }        if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))            return -EFAULT;        sc->lmc_media->set_status (sc, &ctl);        if(ctl.crc_length != sc->ictl.crc_length) {            sc->lmc_media->set_crc_length(sc, ctl.crc_length);	    if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16)		sc->TxDescriptControlInit |=  LMC_TDES_ADD_CRC_DISABLE;	    else		sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE;        }        if (ctl.keepalive_onoff == LMC_CTL_OFF)            sp->pp_flags &= ~PP_KEEPALIVE;	/* Turn off */        else            sp->pp_flags |= PP_KEEPALIVE;	/* Turn on */        ret = 0;        break;    case LMCIOCIFTYPE: /*fold01*/        {            u_int16_t	old_type = sc->if_type;            u_int16_t	new_type;	    if (!capable(CAP_NET_ADMIN)) {		ret = -EPERM;		break;	    }	    if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t)))                return -EFAULT;            	    if (new_type == old_type)	    {		ret = 0 ;		break;				/* no change */            }                        lmc_proto_close(sc);            lmc_proto_detach(sc);            sc->if_type = new_type;//            lmc_proto_init(sc);            lmc_proto_attach(sc);            lmc_proto_open(sc);	    ret = 0 ;	    break ;	}    case LMCIOCGETXINFO: /*fold01*/        sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;        sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;        sc->lmc_xinfo.PciSlotNumber = 0;        sc->lmc_xinfo.DriverMajorVersion = DRIVER_MAJOR_VERSION;        sc->lmc_xinfo.DriverMinorVersion = DRIVER_MINOR_VERSION;        sc->lmc_xinfo.DriverSubVersion = DRIVER_SUB_VERSION;        sc->lmc_xinfo.XilinxRevisionNumber =            lmc_mii_readreg (sc, 0, 3) & 0xf;        sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ;        sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);        sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);        sc->lmc_xinfo.Magic1 = 0xDEADBEEF;        if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo,                         sizeof (struct lmc_xinfo)))            return -EFAULT;        ret = 0;        break;    case LMCIOCGETLMCSTATS: /*fold01*/        if (sc->lmc_cardtype == LMC_CARDTYPE_T1){            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB);            sc->stats.framingBitErrorCount +=                lmc_mii_readreg (sc, 0, 18) & 0xff;            lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_MSB);            sc->stats.framingBitErrorCount +=                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_LSB);            sc->stats.lineCodeViolationCount +=                lmc_mii_readreg (sc, 0, 18) & 0xff;            lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_MSB);            sc->stats.lineCodeViolationCount +=                (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8;            lmc_mii_writereg (sc, 0, 17, T1FRAMER_AERR);            regVal = lmc_mii_readreg (sc, 0, 18) & 0xff;            sc->stats.lossOfFrameCount +=                (regVal & T1FRAMER_LOF_MASK) >> 4;            sc->stats.changeOfFrameAlignmentCount +=                (regVal & T1FRAMER_COFA_MASK) >> 2;            sc->stats.severelyErroredFrameCount +=                regVal & T1FRAMER_SEF_MASK;        }        if (copy_to_user(ifr->ifr_data, &sc->stats,                         sizeof (struct lmc_statistics)))            return -EFAULT;        ret = 0;        break;    case LMCIOCCLEARLMCSTATS: /*fold01*/        if (!capable(CAP_NET_ADMIN)){            ret = -EPERM;            break;        }        memset (&sc->stats, 0, sizeof (struct lmc_statistics));        sc->stats.check = STATCHECK;        sc->stats.version_size = (DRIVER_VERSION << 16) +            sizeof (struct lmc_statistics);        sc->stats.lmc_cardtype = sc->lmc_cardtype;        ret = 0;        break;    case LMCIOCSETCIRCUIT: /*fold01*/        if (!capable(CAP_NET_ADMIN)){            ret = -EPERM;            break;        }        if(dev->flags & IFF_UP){            ret = -EBUSY;            break;        }        if (copy_from_user(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t)))            return -EFAULT;        sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);        sc->ictl.circuit_type = ctl.circuit_type;        ret = 0;        break;    case LMCIOCRESET: /*fold01*/        if (!capable(CAP_NET_ADMIN)){            ret = -EPERM;            break;        }        /* Reset driver and bring back to current state */        printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16));        lmc_running_reset (dev);        printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));        LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));        ret = 0;        break;#ifdef DEBUG    case LMCIOCDUMPEVENTLOG:        if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof (u32)))            return -EFAULT;        if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf)))            return -EFAULT;        ret = 0;        break;#endif /* end ifdef _DBG_EVENTLOG */    case LMCIOCT1CONTROL: /*fold01*/        if (sc->lmc_cardtype != LMC_CARDTYPE_T1){            ret = -EOPNOTSUPP;            break;        }        break;    case LMCIOCXILINX: /*fold01*/        {            struct lmc_xilinx_control xc; /*fold02*/            if (!capable(CAP_NET_ADMIN)){                ret = -EPERM;                break;            }            /*             * Stop the xwitter whlie we restart the hardware             */            netif_stop_queue(dev);            if (copy_from_user(&xc, ifr->ifr_data, sizeof (struct lmc_xilinx_control)))                return -EFAULT;            switch(xc.command){            case lmc_xilinx_reset: /*fold02*/                {                    u16 mii;                    mii = lmc_mii_readreg (sc, 0, 16);                    /*                     * Make all of them 0 and make input                     */                    lmc_gpio_mkinput(sc, 0xff);                    /*                     * make the reset output                     */                    lmc_gpio_mkoutput(sc, LMC_GEP_RESET);                    /*                     * RESET low to force configuration.  This also forces                     * the transmitter clock to be internal, but we expect to reset                     * that later anyway.                     */                    sc->lmc_gpio &= ~LMC_GEP_RESET;                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);                    /*                     * hold for more than 10 microseconds                     */                    udelay(50);                    sc->lmc_gpio |= LMC_GEP_RESET;                    LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio);                    /*                     * stop driving Xilinx-related signals                     */                    lmc_gpio_mkinput(sc, 0xff);                    /* Reset the frammer hardware */                    sc->lmc_media->set_link_status (sc, 1);                    sc->lmc_media->set_status (sc, NULL);//                    lmc_softreset(sc);                    {                        int i;                        for(i = 0; i < 5; i++){                            lmc_led_on(sc, LMC_DS3_LED0);                            mdelay(100);                            lmc_led_off(sc, LMC_DS3_LED0);                            lmc_led_on(sc, LMC_DS3_LED1);                            mdelay(100);                            lmc_led_off(sc, LMC_DS3_LED1);                            lmc_led_on(sc, LMC_DS3_LED3);                            mdelay(100);                            lmc_led_off(sc, LMC_DS3_LED3);                            lmc_led_on(sc, LMC_DS3_LED2);                            mdelay(100);                            lmc_led_off(sc, LMC_DS3_LED2);                        }                    }                                                            ret = 0x0;                }                break;            case lmc_xilinx_load_prom: /*fold02*/                {                    u16 mii;                    int timeout = 500000;                    mii = lmc_mii_readreg (sc, 0, 16);                    /*                     * Make all of them 0 and make input                     */                    lmc_gpio_mkinput(sc, 0xff);                    /*                     * make the reset output                     */                    lmc_gpio_mkoutput(sc,  LMC_GEP_DP | LMC_GEP_RESET);                    /*                     * RESET low to force configuration.  This also forces                     * the transmitter clock to be internal, but we expect to reset                     * that later anyway.                     */

⌨️ 快捷键说明

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