?? xirc2ps_cs.c
字號:
/* [xirc2ps_cs.c wk 03.11.99] (1.40 1999/11/18 00:06:03) * Xircom CreditCard Ethernet Adapter IIps driver * Xircom Realport 10/100 (RE-100) driver * * This driver supports various Xircom CreditCard Ethernet adapters * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56, * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100. * * 2000-09-24 <psheer@icon.co.za> The Xircom CE3B-100 may not * autodetect the media properly. In this case use the * if_port=1 (for 10BaseT) or if_port=4 (for 100BaseT) options * to force the media type. * * Written originally by Werner Koch based on David Hinds' skeleton of the * PCMCIA driver. * * Copyright (c) 1997,1998 Werner Koch (dd9jn) * * This driver 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. * * It 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * * ALTERNATIVELY, this driver may be distributed under the terms of * the following license, in which case the provisions of this license * are required INSTEAD OF the GNU General Public License. (This clause * is necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/in.h>#include <linux/delay.h>#include <linux/ethtool.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>#include <linux/bitops.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/cisreg.h>#include <pcmcia/ciscode.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#ifndef MANFID_COMPAQ #define MANFID_COMPAQ 0x0138 #define MANFID_COMPAQ2 0x0183 /* is this correct? */#endif#include <pcmcia/ds.h>/* Time in jiffies before concluding Tx hung */#define TX_TIMEOUT ((400*HZ)/1000)/**************** * Some constants used to access the hardware *//* Register offsets and value constans */#define XIRCREG_CR 0 /* Command register (wr) */enum xirc_cr { TransmitPacket = 0x01, SoftReset = 0x02, EnableIntr = 0x04, ForceIntr = 0x08, ClearTxFIFO = 0x10, ClearRxOvrun = 0x20, RestartTx = 0x40};#define XIRCREG_ESR 0 /* Ethernet status register (rd) */enum xirc_esr { FullPktRcvd = 0x01, /* full packet in receive buffer */ PktRejected = 0x04, /* a packet has been rejected */ TxPktPend = 0x08, /* TX Packet Pending */ IncorPolarity = 0x10, MediaSelect = 0x20 /* set if TP, clear if AUI */};#define XIRCREG_PR 1 /* Page Register select */#define XIRCREG_EDP 4 /* Ethernet Data Port Register */#define XIRCREG_ISR 6 /* Ethernet Interrupt Status Register */enum xirc_isr { TxBufOvr = 0x01, /* TX Buffer Overflow */ PktTxed = 0x02, /* Packet Transmitted */ MACIntr = 0x04, /* MAC Interrupt occurred */ TxResGrant = 0x08, /* Tx Reservation Granted */ RxFullPkt = 0x20, /* Rx Full Packet */ RxPktRej = 0x40, /* Rx Packet Rejected */ ForcedIntr= 0x80 /* Forced Interrupt */};#define XIRCREG1_IMR0 12 /* Ethernet Interrupt Mask Register (on page 1)*/#define XIRCREG1_IMR1 13#define XIRCREG0_TSO 8 /* Transmit Space Open Register (on page 0)*/#define XIRCREG0_TRS 10 /* Transmit reservation Size Register (page 0)*/#define XIRCREG0_DO 12 /* Data Offset Register (page 0) (wr) */#define XIRCREG0_RSR 12 /* Receive Status Register (page 0) (rd) */enum xirc_rsr { PhyPkt = 0x01, /* set:physical packet, clear: multicast packet */ BrdcstPkt = 0x02, /* set if it is a broadcast packet */ PktTooLong = 0x04, /* set if packet length > 1518 */ AlignErr = 0x10, /* incorrect CRC and last octet not complete */ CRCErr = 0x20, /* incorrect CRC and last octet is complete */ PktRxOk = 0x80 /* received ok */};#define XIRCREG0_PTR 13 /* packets transmitted register (rd) */#define XIRCREG0_RBC 14 /* receive byte count regsister (rd) */#define XIRCREG1_ECR 14 /* ethernet configurationn register */enum xirc_ecr { FullDuplex = 0x04, /* enable full duplex mode */ LongTPMode = 0x08, /* adjust for longer lengths of TP cable */ DisablePolCor = 0x10,/* disable auto polarity correction */ DisableLinkPulse = 0x20, /* disable link pulse generation */ DisableAutoTx = 0x40, /* disable auto-transmit */};#define XIRCREG2_RBS 8 /* receive buffer start register */#define XIRCREG2_LED 10 /* LED Configuration register *//* values for the leds: Bits 2-0 for led 1 * 0 disabled Bits 5-3 for led 2 * 1 collision * 2 noncollision * 3 link_detected * 4 incor_polarity * 5 jabber * 6 auto_assertion * 7 rx_tx_activity */#define XIRCREG2_MSR 12 /* Mohawk specific register */#define XIRCREG4_GPR0 8 /* General Purpose Register 0 */#define XIRCREG4_GPR1 9 /* General Purpose Register 1 */#define XIRCREG2_GPR2 13 /* General Purpose Register 2 (page2!)*/#define XIRCREG4_BOV 10 /* Bonding Version Register */#define XIRCREG4_LMA 12 /* Local Memory Address Register */#define XIRCREG4_LMD 14 /* Local Memory Data Port *//* MAC register can only by accessed with 8 bit operations */#define XIRCREG40_CMD0 8 /* Command Register (wr) */enum xirc_cmd { /* Commands */ Transmit = 0x01, EnableRecv = 0x04, DisableRecv = 0x08, Abort = 0x10, Online = 0x20, IntrAck = 0x40, Offline = 0x80};#define XIRCREG5_RHSA0 10 /* Rx Host Start Address */#define XIRCREG40_RXST0 9 /* Receive Status Register */#define XIRCREG40_TXST0 11 /* Transmit Status Register 0 */#define XIRCREG40_TXST1 12 /* Transmit Status Register 10 */#define XIRCREG40_RMASK0 13 /* Receive Mask Register */#define XIRCREG40_TMASK0 14 /* Transmit Mask Register 0 */#define XIRCREG40_TMASK1 15 /* Transmit Mask Register 0 */#define XIRCREG42_SWC0 8 /* Software Configuration 0 */#define XIRCREG42_SWC1 9 /* Software Configuration 1 */#define XIRCREG42_BOC 10 /* Back-Off Configuration */#define XIRCREG44_TDR0 8 /* Time Domain Reflectometry 0 */#define XIRCREG44_TDR1 9 /* Time Domain Reflectometry 1 */#define XIRCREG44_RXBC_LO 10 /* Rx Byte Count 0 (rd) */#define XIRCREG44_RXBC_HI 11 /* Rx Byte Count 1 (rd) */#define XIRCREG45_REV 15 /* Revision Register (rd) */#define XIRCREG50_IA 8 /* Individual Address (8-13) */static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" };/**************** * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If * you do not define PCMCIA_DEBUG at all, all the debug code will be * left out. If you compile with PCMCIA_DEBUG=0, the debug code will * be present but disabled -- but it can then be enabled for specific * modules at load time with a 'pc_debug=#' option to insmod. */#ifdef PCMCIA_DEBUGstatic int pc_debug = PCMCIA_DEBUG;module_param(pc_debug, int, 0);#define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args)#else#define DEBUG(n, args...)#endif#define KDBG_XIRC KERN_DEBUG "xirc2ps_cs: "#define KERR_XIRC KERN_ERR "xirc2ps_cs: "#define KWRN_XIRC KERN_WARNING "xirc2ps_cs: "#define KNOT_XIRC KERN_NOTICE "xirc2ps_cs: "#define KINF_XIRC KERN_INFO "xirc2ps_cs: "/* card types */#define XIR_UNKNOWN 0 /* unknown: not supported */#define XIR_CE 1 /* (prodid 1) different hardware: not supported */#define XIR_CE2 2 /* (prodid 2) */#define XIR_CE3 3 /* (prodid 3) */#define XIR_CEM 4 /* (prodid 1) different hardware: not supported */#define XIR_CEM2 5 /* (prodid 2) */#define XIR_CEM3 6 /* (prodid 3) */#define XIR_CEM33 7 /* (prodid 4) */#define XIR_CEM56M 8 /* (prodid 5) */#define XIR_CEM56 9 /* (prodid 6) */#define XIR_CM28 10 /* (prodid 3) modem only: not supported here */#define XIR_CM33 11 /* (prodid 4) modem only: not supported here */#define XIR_CM56 12 /* (prodid 5) modem only: not supported here */#define XIR_CG 13 /* (prodid 1) GSM modem only: not supported */#define XIR_CBE 14 /* (prodid 1) cardbus ethernet: not supported *//*====================================================================*//* Module parameters */MODULE_DESCRIPTION("Xircom PCMCIA ethernet driver");MODULE_LICENSE("Dual MPL/GPL");#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)INT_MODULE_PARM(if_port, 0);INT_MODULE_PARM(full_duplex, 0);INT_MODULE_PARM(do_sound, 1);INT_MODULE_PARM(lockup_hack, 0); /* anti lockup hack *//*====================================================================*//* We do not process more than these number of bytes during one * interrupt. (Of course we receive complete packets, so this is not * an exact value). * Something between 2000..22000; first value gives best interrupt latency, * the second enables the usage of the complete on-chip buffer. We use the * high value as the initial value. */static unsigned maxrx_bytes = 22000;/* MII management prototypes */static void mii_idle(kio_addr_t ioaddr);static void mii_putbit(kio_addr_t ioaddr, unsigned data);static int mii_getbit(kio_addr_t ioaddr);static void mii_wbits(kio_addr_t ioaddr, unsigned data, int len);static unsigned mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg);static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len);/* * The event() function is this driver's Card Services event handler. * It will be called by Card Services when an appropriate card status * event is received. The config() and release() entry points are * used to configure or release a socket, in response to card insertion * and ejection events. They are invoked from the event handler. */static int has_ce2_string(struct pcmcia_device * link);static int xirc2ps_config(struct pcmcia_device * link);static void xirc2ps_release(struct pcmcia_device * link);/**************** * The attach() and detach() entry points are used to create and destroy * "instances" of the driver, where each instance represents everything * needed to manage one actual PCMCIA card. */static void xirc2ps_detach(struct pcmcia_device *p_dev);/**************** * You'll also need to prototype all the functions that will actually * be used to talk to your device. See 'pcmem_cs' for a good example * of a fully self-sufficient driver; the other drivers rely more or * less on other parts of the kernel. */static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);/**************** * A linked list of "instances" of the device. Each actual * PCMCIA card corresponds to one device instance, and is described * by one struct pcmcia_device structure (defined in ds.h). * * You may not want to use a linked list for this -- for example, the * memory card driver uses an array of struct pcmcia_device pointers, where minor * device numbers are used to derive the corresponding array index. *//**************** * A driver needs to provide a dev_node_t structure for each device * on a card. In some cases, there is only one device per card (for * example, ethernet cards, modems). In other cases, there may be * many actual or logical devices (SCSI adapters, memory cards with * multiple partitions). The dev_node_t structures need to be kept * in a linked list starting at the 'dev' field of a struct pcmcia_device * structure. We allocate them in the card's private data structure, * because they generally can't be allocated dynamically. */typedef struct local_info_t { struct net_device *dev; struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; int card_type; int probe_port; int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */ int mohawk; /* a CE3 type card */ int dingo; /* a CEM56 type card */ int new_mii; /* has full 10baseT/100baseT MII */ int modem; /* is a multi function card (i.e with a modem) */ void __iomem *dingo_ccr; /* only used for CEM56 cards */ unsigned last_ptr_value; /* last packets transmitted value */ const char *manf_str; struct work_struct tx_timeout_task;} local_info_t;/**************** * Some more prototypes */static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);static void do_tx_timeout(struct net_device *dev);static void xirc2ps_tx_timeout_task(struct work_struct *work);static struct net_device_stats *do_get_stats(struct net_device *dev);static void set_addresses(struct net_device *dev);static void set_multicast_list(struct net_device *dev);static int set_card_type(struct pcmcia_device *link, const void *s);static int do_config(struct net_device *dev, struct ifmap *map);static int do_open(struct net_device *dev);static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static const struct ethtool_ops netdev_ethtool_ops;static void hardreset(struct net_device *dev);static void do_reset(struct net_device *dev, int full);static int init_mii(struct net_device *dev);static void do_powerdown(struct net_device *dev);static int do_stop(struct net_device *dev);/*=============== Helper functions =========================*/static intfirst_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse){ int err; if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 && (err = pcmcia_get_tuple_data(handle, tuple)) == 0) err = pcmcia_parse_tuple(handle, tuple, parse); return err;}static intnext_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse){ int err; if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 && (err = pcmcia_get_tuple_data(handle, tuple)) == 0) err = pcmcia_parse_tuple(handle, tuple, parse); return err;}#define SelectPage(pgnr) outb((pgnr), ioaddr + XIRCREG_PR)#define GetByte(reg) ((unsigned)inb(ioaddr + (reg)))#define GetWord(reg) ((unsigned)inw(ioaddr + (reg)))#define PutByte(reg,value) outb((value), ioaddr+(reg))#define PutWord(reg,value) outw((value), ioaddr+(reg))/*====== Functions used for debugging =================================*/#if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */static voidPrintRegisters(struct net_device *dev){ kio_addr_t ioaddr = dev->base_addr; if (pc_debug > 1) { int i, page; printk(KDBG_XIRC "Register common: "); for (i = 0; i < 8; i++) printk(" %2.2x", GetByte(i)); printk("\n"); for (page = 0; page <= 8; page++) { printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } for (page=0x40 ; page <= 0x5f; page++) { if (page == 0x43 || (page >= 0x46 && page <= 0x4f) || (page >= 0x51 && page <=0x5e)) continue; printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } }}#endif /* PCMCIA_DEBUG *//*============== MII Management functions ===============*//**************** * Turn around for read */static voidmii_idle(kio_addr_t ioaddr){ PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ udelay(1); PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */ udelay(1);}/**************** * Write a bit to MDI/O */static voidmii_putbit(kio_addr_t ioaddr, unsigned data){ #if 1 if (data) { PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */ udelay(1); PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */ udelay(1); } else { PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */ udelay(1); PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */ udelay(1); } #else if (data) { PutWord(XIRCREG2_GPR2-1, 0x0e0e); udelay(1); PutWord(XIRCREG2_GPR2-1, 0x0f0f); udelay(1); } else { PutWord(XIRCREG2_GPR2-1, 0x0c0c); udelay(1); PutWord(XIRCREG2_GPR2-1, 0x0d0d); udelay(1); } #endif}/**************** * Get a bit from MDI/O */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -