1b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 2b955f6caSJeff Kirsher Linux PCMCIA ethernet adapter driver for the New Media Ethernet LAN. 3b955f6caSJeff Kirsher nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao 4b955f6caSJeff Kirsher 5b955f6caSJeff Kirsher The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media 6b955f6caSJeff Kirsher Access Controller for Ethernet (MACE). It is essentially the Am2150 7b955f6caSJeff Kirsher PCMCIA Ethernet card contained in the Am2150 Demo Kit. 8b955f6caSJeff Kirsher 9b955f6caSJeff Kirsher Written by Roger C. Pao <rpao@paonet.org> 10b955f6caSJeff Kirsher Copyright 1995 Roger C. Pao 11b955f6caSJeff Kirsher Linux 2.5 cleanups Copyright Red Hat 2003 12b955f6caSJeff Kirsher 13b955f6caSJeff Kirsher This software may be used and distributed according to the terms of 14b955f6caSJeff Kirsher the GNU General Public License. 15b955f6caSJeff Kirsher 16b955f6caSJeff Kirsher Ported to Linux 1.3.* network driver environment by 17b955f6caSJeff Kirsher Matti Aarnio <mea@utu.fi> 18b955f6caSJeff Kirsher 19b955f6caSJeff Kirsher References 20b955f6caSJeff Kirsher 21b955f6caSJeff Kirsher Am2150 Technical Reference Manual, Revision 1.0, August 17, 1993 22b955f6caSJeff Kirsher Am79C940 (MACE) Data Sheet, 1994 23b955f6caSJeff Kirsher Am79C90 (C-LANCE) Data Sheet, 1994 24b955f6caSJeff Kirsher Linux PCMCIA Programmer's Guide v1.17 25b955f6caSJeff Kirsher /usr/src/linux/net/inet/dev.c, Linux kernel 1.2.8 26b955f6caSJeff Kirsher 27b955f6caSJeff Kirsher Eric Mears, New Media Corporation 28b955f6caSJeff Kirsher Tom Pollard, New Media Corporation 29b955f6caSJeff Kirsher Dean Siasoyco, New Media Corporation 30b955f6caSJeff Kirsher Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com> 31b955f6caSJeff Kirsher Donald Becker <becker@scyld.com> 32b955f6caSJeff Kirsher David Hinds <dahinds@users.sourceforge.net> 33b955f6caSJeff Kirsher 34b955f6caSJeff Kirsher The Linux client driver is based on the 3c589_cs.c client driver by 35b955f6caSJeff Kirsher David Hinds. 36b955f6caSJeff Kirsher 37b955f6caSJeff Kirsher The Linux network driver outline is based on the 3c589_cs.c driver, 38b955f6caSJeff Kirsher the 8390.c driver, and the example skeleton.c kernel code, which are 39b955f6caSJeff Kirsher by Donald Becker. 40b955f6caSJeff Kirsher 41b955f6caSJeff Kirsher The Am2150 network driver hardware interface code is based on the 42b955f6caSJeff Kirsher OS/9000 driver for the New Media Ethernet LAN by Eric Mears. 43b955f6caSJeff Kirsher 44b955f6caSJeff Kirsher Special thanks for testing and help in debugging this driver goes 45b955f6caSJeff Kirsher to Ken Lesniak. 46b955f6caSJeff Kirsher 47b955f6caSJeff Kirsher ------------------------------------------------------------------------------- 48b955f6caSJeff Kirsher Driver Notes and Issues 49b955f6caSJeff Kirsher ------------------------------------------------------------------------------- 50b955f6caSJeff Kirsher 51b955f6caSJeff Kirsher 1. Developed on a Dell 320SLi 52b955f6caSJeff Kirsher PCMCIA Card Services 2.6.2 53b955f6caSJeff Kirsher Linux dell 1.2.10 #1 Thu Jun 29 20:23:41 PDT 1995 i386 54b955f6caSJeff Kirsher 55b955f6caSJeff Kirsher 2. rc.pcmcia may require loading pcmcia_core with io_speed=300: 56b955f6caSJeff Kirsher 'insmod pcmcia_core.o io_speed=300'. 57b955f6caSJeff Kirsher This will avoid problems with fast systems which causes rx_framecnt 58b955f6caSJeff Kirsher to return random values. 59b955f6caSJeff Kirsher 60b955f6caSJeff Kirsher 3. If hot extraction does not work for you, use 'ifconfig eth0 down' 61b955f6caSJeff Kirsher before extraction. 62b955f6caSJeff Kirsher 63b955f6caSJeff Kirsher 4. There is a bad slow-down problem in this driver. 64b955f6caSJeff Kirsher 65b955f6caSJeff Kirsher 5. Future: Multicast processing. In the meantime, do _not_ compile your 66b955f6caSJeff Kirsher kernel with multicast ip enabled. 67b955f6caSJeff Kirsher 68b955f6caSJeff Kirsher ------------------------------------------------------------------------------- 69b955f6caSJeff Kirsher History 70b955f6caSJeff Kirsher ------------------------------------------------------------------------------- 71b955f6caSJeff Kirsher Log: nmclan_cs.c,v 72b955f6caSJeff Kirsher * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk> 73b955f6caSJeff Kirsher * Fixed hang on card eject as we probe it 74b955f6caSJeff Kirsher * Cleaned up to use new style locking. 75b955f6caSJeff Kirsher * 76b955f6caSJeff Kirsher * Revision 0.16 1995/07/01 06:42:17 rpao 77b955f6caSJeff Kirsher * Bug fix: nmclan_reset() called CardServices incorrectly. 78b955f6caSJeff Kirsher * 79b955f6caSJeff Kirsher * Revision 0.15 1995/05/24 08:09:47 rpao 80b955f6caSJeff Kirsher * Re-implement MULTI_TX dev->tbusy handling. 81b955f6caSJeff Kirsher * 82b955f6caSJeff Kirsher * Revision 0.14 1995/05/23 03:19:30 rpao 83b955f6caSJeff Kirsher * Added, in nmclan_config(), "tuple.Attributes = 0;". 84b955f6caSJeff Kirsher * Modified MACE ID check to ignore chip revision level. 85b955f6caSJeff Kirsher * Avoid tx_free_frames race condition between _start_xmit and _interrupt. 86b955f6caSJeff Kirsher * 87b955f6caSJeff Kirsher * Revision 0.13 1995/05/18 05:56:34 rpao 88b955f6caSJeff Kirsher * Statistics changes. 89b955f6caSJeff Kirsher * Bug fix: nmclan_reset did not enable TX and RX: call restore_multicast_list. 90b955f6caSJeff Kirsher * Bug fix: mace_interrupt checks ~MACE_IMR_DEFAULT. Fixes driver lockup. 91b955f6caSJeff Kirsher * 92b955f6caSJeff Kirsher * Revision 0.12 1995/05/14 00:12:23 rpao 93b955f6caSJeff Kirsher * Statistics overhaul. 94b955f6caSJeff Kirsher * 95b955f6caSJeff Kirsher 96b955f6caSJeff Kirsher 95/05/13 rpao V0.10a 97b955f6caSJeff Kirsher Bug fix: MACE statistics counters used wrong I/O ports. 98b955f6caSJeff Kirsher Bug fix: mace_interrupt() needed to allow statistics to be 99b955f6caSJeff Kirsher processed without RX or TX interrupts pending. 100b955f6caSJeff Kirsher 95/05/11 rpao V0.10 101b955f6caSJeff Kirsher Multiple transmit request processing. 102b955f6caSJeff Kirsher Modified statistics to use MACE counters where possible. 103b955f6caSJeff Kirsher 95/05/10 rpao V0.09 Bug fix: Must use IO_DATA_PATH_WIDTH_AUTO. 104b955f6caSJeff Kirsher *Released 105b955f6caSJeff Kirsher 95/05/10 rpao V0.08 106b955f6caSJeff Kirsher Bug fix: Make all non-exported functions private by using 107b955f6caSJeff Kirsher static keyword. 108b955f6caSJeff Kirsher Bug fix: Test IntrCnt _before_ reading MACE_IR. 109b955f6caSJeff Kirsher 95/05/10 rpao V0.07 Statistics. 110b955f6caSJeff Kirsher 95/05/09 rpao V0.06 Fix rx_framecnt problem by addition of PCIC wait states. 111b955f6caSJeff Kirsher 112b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 113b955f6caSJeff Kirsher 114b955f6caSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 115b955f6caSJeff Kirsher 116b955f6caSJeff Kirsher #define DRV_NAME "nmclan_cs" 117b955f6caSJeff Kirsher #define DRV_VERSION "0.16" 118b955f6caSJeff Kirsher 119b955f6caSJeff Kirsher 120b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 121b955f6caSJeff Kirsher Conditional Compilation Options 122b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 123b955f6caSJeff Kirsher 124b955f6caSJeff Kirsher #define MULTI_TX 0 125b955f6caSJeff Kirsher #define RESET_ON_TIMEOUT 1 126b955f6caSJeff Kirsher #define TX_INTERRUPTABLE 1 127b955f6caSJeff Kirsher #define RESET_XILINX 0 128b955f6caSJeff Kirsher 129b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 130b955f6caSJeff Kirsher Include Files 131b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 132b955f6caSJeff Kirsher 133b955f6caSJeff Kirsher #include <linux/module.h> 134b955f6caSJeff Kirsher #include <linux/kernel.h> 135b955f6caSJeff Kirsher #include <linux/ptrace.h> 136b955f6caSJeff Kirsher #include <linux/slab.h> 137b955f6caSJeff Kirsher #include <linux/string.h> 138b955f6caSJeff Kirsher #include <linux/timer.h> 139b955f6caSJeff Kirsher #include <linux/interrupt.h> 140b955f6caSJeff Kirsher #include <linux/in.h> 141b955f6caSJeff Kirsher #include <linux/delay.h> 142b955f6caSJeff Kirsher #include <linux/ethtool.h> 143b955f6caSJeff Kirsher #include <linux/netdevice.h> 144b955f6caSJeff Kirsher #include <linux/etherdevice.h> 145b955f6caSJeff Kirsher #include <linux/skbuff.h> 146b955f6caSJeff Kirsher #include <linux/if_arp.h> 147b955f6caSJeff Kirsher #include <linux/ioport.h> 148b955f6caSJeff Kirsher #include <linux/bitops.h> 149b955f6caSJeff Kirsher 150b955f6caSJeff Kirsher #include <pcmcia/cisreg.h> 151b955f6caSJeff Kirsher #include <pcmcia/cistpl.h> 152b955f6caSJeff Kirsher #include <pcmcia/ds.h> 153b955f6caSJeff Kirsher 154b955f6caSJeff Kirsher #include <asm/uaccess.h> 155b955f6caSJeff Kirsher #include <asm/io.h> 156b955f6caSJeff Kirsher 157b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 158b955f6caSJeff Kirsher Defines 159b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 160b955f6caSJeff Kirsher 161b955f6caSJeff Kirsher #define MACE_LADRF_LEN 8 162b955f6caSJeff Kirsher /* 8 bytes in Logical Address Filter */ 163b955f6caSJeff Kirsher 164b955f6caSJeff Kirsher /* Loop Control Defines */ 165b955f6caSJeff Kirsher #define MACE_MAX_IR_ITERATIONS 10 166b955f6caSJeff Kirsher #define MACE_MAX_RX_ITERATIONS 12 167b955f6caSJeff Kirsher /* 168b955f6caSJeff Kirsher TBD: Dean brought this up, and I assumed the hardware would 169b955f6caSJeff Kirsher handle it: 170b955f6caSJeff Kirsher 171b955f6caSJeff Kirsher If MACE_MAX_RX_ITERATIONS is > 1, rx_framecnt may still be 172b955f6caSJeff Kirsher non-zero when the isr exits. We may not get another interrupt 173b955f6caSJeff Kirsher to process the remaining packets for some time. 174b955f6caSJeff Kirsher */ 175b955f6caSJeff Kirsher 176b955f6caSJeff Kirsher /* 177b955f6caSJeff Kirsher The Am2150 has a Xilinx XC3042 field programmable gate array (FPGA) 178b955f6caSJeff Kirsher which manages the interface between the MACE and the PCMCIA bus. It 179b955f6caSJeff Kirsher also includes buffer management for the 32K x 8 SRAM to control up to 180b955f6caSJeff Kirsher four transmit and 12 receive frames at a time. 181b955f6caSJeff Kirsher */ 182b955f6caSJeff Kirsher #define AM2150_MAX_TX_FRAMES 4 183b955f6caSJeff Kirsher #define AM2150_MAX_RX_FRAMES 12 184b955f6caSJeff Kirsher 185b955f6caSJeff Kirsher /* Am2150 Ethernet Card I/O Mapping */ 186b955f6caSJeff Kirsher #define AM2150_RCV 0x00 187b955f6caSJeff Kirsher #define AM2150_XMT 0x04 188b955f6caSJeff Kirsher #define AM2150_XMT_SKIP 0x09 189b955f6caSJeff Kirsher #define AM2150_RCV_NEXT 0x0A 190b955f6caSJeff Kirsher #define AM2150_RCV_FRAME_COUNT 0x0B 191b955f6caSJeff Kirsher #define AM2150_MACE_BANK 0x0C 192b955f6caSJeff Kirsher #define AM2150_MACE_BASE 0x10 193b955f6caSJeff Kirsher 194b955f6caSJeff Kirsher /* MACE Registers */ 195b955f6caSJeff Kirsher #define MACE_RCVFIFO 0 196b955f6caSJeff Kirsher #define MACE_XMTFIFO 1 197b955f6caSJeff Kirsher #define MACE_XMTFC 2 198b955f6caSJeff Kirsher #define MACE_XMTFS 3 199b955f6caSJeff Kirsher #define MACE_XMTRC 4 200b955f6caSJeff Kirsher #define MACE_RCVFC 5 201b955f6caSJeff Kirsher #define MACE_RCVFS 6 202b955f6caSJeff Kirsher #define MACE_FIFOFC 7 203b955f6caSJeff Kirsher #define MACE_IR 8 204b955f6caSJeff Kirsher #define MACE_IMR 9 205b955f6caSJeff Kirsher #define MACE_PR 10 206b955f6caSJeff Kirsher #define MACE_BIUCC 11 207b955f6caSJeff Kirsher #define MACE_FIFOCC 12 208b955f6caSJeff Kirsher #define MACE_MACCC 13 209b955f6caSJeff Kirsher #define MACE_PLSCC 14 210b955f6caSJeff Kirsher #define MACE_PHYCC 15 211b955f6caSJeff Kirsher #define MACE_CHIPIDL 16 212b955f6caSJeff Kirsher #define MACE_CHIPIDH 17 213b955f6caSJeff Kirsher #define MACE_IAC 18 214b955f6caSJeff Kirsher /* Reserved */ 215b955f6caSJeff Kirsher #define MACE_LADRF 20 216b955f6caSJeff Kirsher #define MACE_PADR 21 217b955f6caSJeff Kirsher /* Reserved */ 218b955f6caSJeff Kirsher /* Reserved */ 219b955f6caSJeff Kirsher #define MACE_MPC 24 220b955f6caSJeff Kirsher /* Reserved */ 221b955f6caSJeff Kirsher #define MACE_RNTPC 26 222b955f6caSJeff Kirsher #define MACE_RCVCC 27 223b955f6caSJeff Kirsher /* Reserved */ 224b955f6caSJeff Kirsher #define MACE_UTR 29 225b955f6caSJeff Kirsher #define MACE_RTR1 30 226b955f6caSJeff Kirsher #define MACE_RTR2 31 227b955f6caSJeff Kirsher 228b955f6caSJeff Kirsher /* MACE Bit Masks */ 229b955f6caSJeff Kirsher #define MACE_XMTRC_EXDEF 0x80 230b955f6caSJeff Kirsher #define MACE_XMTRC_XMTRC 0x0F 231b955f6caSJeff Kirsher 232b955f6caSJeff Kirsher #define MACE_XMTFS_XMTSV 0x80 233b955f6caSJeff Kirsher #define MACE_XMTFS_UFLO 0x40 234b955f6caSJeff Kirsher #define MACE_XMTFS_LCOL 0x20 235b955f6caSJeff Kirsher #define MACE_XMTFS_MORE 0x10 236b955f6caSJeff Kirsher #define MACE_XMTFS_ONE 0x08 237b955f6caSJeff Kirsher #define MACE_XMTFS_DEFER 0x04 238b955f6caSJeff Kirsher #define MACE_XMTFS_LCAR 0x02 239b955f6caSJeff Kirsher #define MACE_XMTFS_RTRY 0x01 240b955f6caSJeff Kirsher 241b955f6caSJeff Kirsher #define MACE_RCVFS_RCVSTS 0xF000 242b955f6caSJeff Kirsher #define MACE_RCVFS_OFLO 0x8000 243b955f6caSJeff Kirsher #define MACE_RCVFS_CLSN 0x4000 244b955f6caSJeff Kirsher #define MACE_RCVFS_FRAM 0x2000 245b955f6caSJeff Kirsher #define MACE_RCVFS_FCS 0x1000 246b955f6caSJeff Kirsher 247b955f6caSJeff Kirsher #define MACE_FIFOFC_RCVFC 0xF0 248b955f6caSJeff Kirsher #define MACE_FIFOFC_XMTFC 0x0F 249b955f6caSJeff Kirsher 250b955f6caSJeff Kirsher #define MACE_IR_JAB 0x80 251b955f6caSJeff Kirsher #define MACE_IR_BABL 0x40 252b955f6caSJeff Kirsher #define MACE_IR_CERR 0x20 253b955f6caSJeff Kirsher #define MACE_IR_RCVCCO 0x10 254b955f6caSJeff Kirsher #define MACE_IR_RNTPCO 0x08 255b955f6caSJeff Kirsher #define MACE_IR_MPCO 0x04 256b955f6caSJeff Kirsher #define MACE_IR_RCVINT 0x02 257b955f6caSJeff Kirsher #define MACE_IR_XMTINT 0x01 258b955f6caSJeff Kirsher 259b955f6caSJeff Kirsher #define MACE_MACCC_PROM 0x80 260b955f6caSJeff Kirsher #define MACE_MACCC_DXMT2PD 0x40 261b955f6caSJeff Kirsher #define MACE_MACCC_EMBA 0x20 262b955f6caSJeff Kirsher #define MACE_MACCC_RESERVED 0x10 263b955f6caSJeff Kirsher #define MACE_MACCC_DRCVPA 0x08 264b955f6caSJeff Kirsher #define MACE_MACCC_DRCVBC 0x04 265b955f6caSJeff Kirsher #define MACE_MACCC_ENXMT 0x02 266b955f6caSJeff Kirsher #define MACE_MACCC_ENRCV 0x01 267b955f6caSJeff Kirsher 268b955f6caSJeff Kirsher #define MACE_PHYCC_LNKFL 0x80 269b955f6caSJeff Kirsher #define MACE_PHYCC_DLNKTST 0x40 270b955f6caSJeff Kirsher #define MACE_PHYCC_REVPOL 0x20 271b955f6caSJeff Kirsher #define MACE_PHYCC_DAPC 0x10 272b955f6caSJeff Kirsher #define MACE_PHYCC_LRT 0x08 273b955f6caSJeff Kirsher #define MACE_PHYCC_ASEL 0x04 274b955f6caSJeff Kirsher #define MACE_PHYCC_RWAKE 0x02 275b955f6caSJeff Kirsher #define MACE_PHYCC_AWAKE 0x01 276b955f6caSJeff Kirsher 277b955f6caSJeff Kirsher #define MACE_IAC_ADDRCHG 0x80 278b955f6caSJeff Kirsher #define MACE_IAC_PHYADDR 0x04 279b955f6caSJeff Kirsher #define MACE_IAC_LOGADDR 0x02 280b955f6caSJeff Kirsher 281b955f6caSJeff Kirsher #define MACE_UTR_RTRE 0x80 282b955f6caSJeff Kirsher #define MACE_UTR_RTRD 0x40 283b955f6caSJeff Kirsher #define MACE_UTR_RPA 0x20 284b955f6caSJeff Kirsher #define MACE_UTR_FCOLL 0x10 285b955f6caSJeff Kirsher #define MACE_UTR_RCVFCSE 0x08 286b955f6caSJeff Kirsher #define MACE_UTR_LOOP_INCL_MENDEC 0x06 287b955f6caSJeff Kirsher #define MACE_UTR_LOOP_NO_MENDEC 0x04 288b955f6caSJeff Kirsher #define MACE_UTR_LOOP_EXTERNAL 0x02 289b955f6caSJeff Kirsher #define MACE_UTR_LOOP_NONE 0x00 290b955f6caSJeff Kirsher #define MACE_UTR_RESERVED 0x01 291b955f6caSJeff Kirsher 292b955f6caSJeff Kirsher /* Switch MACE register bank (only 0 and 1 are valid) */ 293b955f6caSJeff Kirsher #define MACEBANK(win_num) outb((win_num), ioaddr + AM2150_MACE_BANK) 294b955f6caSJeff Kirsher 295b955f6caSJeff Kirsher #define MACE_IMR_DEFAULT \ 296b955f6caSJeff Kirsher (0xFF - \ 297b955f6caSJeff Kirsher ( \ 298b955f6caSJeff Kirsher MACE_IR_CERR | \ 299b955f6caSJeff Kirsher MACE_IR_RCVCCO | \ 300b955f6caSJeff Kirsher MACE_IR_RNTPCO | \ 301b955f6caSJeff Kirsher MACE_IR_MPCO | \ 302b955f6caSJeff Kirsher MACE_IR_RCVINT | \ 303b955f6caSJeff Kirsher MACE_IR_XMTINT \ 304b955f6caSJeff Kirsher ) \ 305b955f6caSJeff Kirsher ) 306b955f6caSJeff Kirsher #undef MACE_IMR_DEFAULT 307b955f6caSJeff Kirsher #define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */ 308b955f6caSJeff Kirsher 309b955f6caSJeff Kirsher #define TX_TIMEOUT ((400*HZ)/1000) 310b955f6caSJeff Kirsher 311b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 312b955f6caSJeff Kirsher Type Definitions 313b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 314b955f6caSJeff Kirsher 315b955f6caSJeff Kirsher typedef struct _mace_statistics { 316b955f6caSJeff Kirsher /* MACE_XMTFS */ 317b955f6caSJeff Kirsher int xmtsv; 318b955f6caSJeff Kirsher int uflo; 319b955f6caSJeff Kirsher int lcol; 320b955f6caSJeff Kirsher int more; 321b955f6caSJeff Kirsher int one; 322b955f6caSJeff Kirsher int defer; 323b955f6caSJeff Kirsher int lcar; 324b955f6caSJeff Kirsher int rtry; 325b955f6caSJeff Kirsher 326b955f6caSJeff Kirsher /* MACE_XMTRC */ 327b955f6caSJeff Kirsher int exdef; 328b955f6caSJeff Kirsher int xmtrc; 329b955f6caSJeff Kirsher 330b955f6caSJeff Kirsher /* RFS1--Receive Status (RCVSTS) */ 331b955f6caSJeff Kirsher int oflo; 332b955f6caSJeff Kirsher int clsn; 333b955f6caSJeff Kirsher int fram; 334b955f6caSJeff Kirsher int fcs; 335b955f6caSJeff Kirsher 336b955f6caSJeff Kirsher /* RFS2--Runt Packet Count (RNTPC) */ 337b955f6caSJeff Kirsher int rfs_rntpc; 338b955f6caSJeff Kirsher 339b955f6caSJeff Kirsher /* RFS3--Receive Collision Count (RCVCC) */ 340b955f6caSJeff Kirsher int rfs_rcvcc; 341b955f6caSJeff Kirsher 342b955f6caSJeff Kirsher /* MACE_IR */ 343b955f6caSJeff Kirsher int jab; 344b955f6caSJeff Kirsher int babl; 345b955f6caSJeff Kirsher int cerr; 346b955f6caSJeff Kirsher int rcvcco; 347b955f6caSJeff Kirsher int rntpco; 348b955f6caSJeff Kirsher int mpco; 349b955f6caSJeff Kirsher 350b955f6caSJeff Kirsher /* MACE_MPC */ 351b955f6caSJeff Kirsher int mpc; 352b955f6caSJeff Kirsher 353b955f6caSJeff Kirsher /* MACE_RNTPC */ 354b955f6caSJeff Kirsher int rntpc; 355b955f6caSJeff Kirsher 356b955f6caSJeff Kirsher /* MACE_RCVCC */ 357b955f6caSJeff Kirsher int rcvcc; 358b955f6caSJeff Kirsher } mace_statistics; 359b955f6caSJeff Kirsher 360b955f6caSJeff Kirsher typedef struct _mace_private { 361b955f6caSJeff Kirsher struct pcmcia_device *p_dev; 362b955f6caSJeff Kirsher struct net_device_stats linux_stats; /* Linux statistics counters */ 363b955f6caSJeff Kirsher mace_statistics mace_stats; /* MACE chip statistics counters */ 364b955f6caSJeff Kirsher 365b955f6caSJeff Kirsher /* restore_multicast_list() state variables */ 366b955f6caSJeff Kirsher int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */ 367b955f6caSJeff Kirsher int multicast_num_addrs; 368b955f6caSJeff Kirsher 369b955f6caSJeff Kirsher char tx_free_frames; /* Number of free transmit frame buffers */ 370b955f6caSJeff Kirsher char tx_irq_disabled; /* MACE TX interrupt disabled */ 371b955f6caSJeff Kirsher 372b955f6caSJeff Kirsher spinlock_t bank_lock; /* Must be held if you step off bank 0 */ 373b955f6caSJeff Kirsher } mace_private; 374b955f6caSJeff Kirsher 375b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 376b955f6caSJeff Kirsher Private Global Variables 377b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 378b955f6caSJeff Kirsher 379b955f6caSJeff Kirsher static const char *if_names[]={ 380b955f6caSJeff Kirsher "Auto", "10baseT", "BNC", 381b955f6caSJeff Kirsher }; 382b955f6caSJeff Kirsher 383b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 384b955f6caSJeff Kirsher Parameters 385b955f6caSJeff Kirsher These are the parameters that can be set during loading with 386b955f6caSJeff Kirsher 'insmod'. 387b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 388b955f6caSJeff Kirsher 389b955f6caSJeff Kirsher MODULE_DESCRIPTION("New Media PCMCIA ethernet driver"); 390b955f6caSJeff Kirsher MODULE_LICENSE("GPL"); 391b955f6caSJeff Kirsher 392b955f6caSJeff Kirsher #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) 393b955f6caSJeff Kirsher 394b955f6caSJeff Kirsher /* 0=auto, 1=10baseT, 2 = 10base2, default=auto */ 395b955f6caSJeff Kirsher INT_MODULE_PARM(if_port, 0); 396b955f6caSJeff Kirsher 397b955f6caSJeff Kirsher 398b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 399b955f6caSJeff Kirsher Function Prototypes 400b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 401b955f6caSJeff Kirsher 402b955f6caSJeff Kirsher static int nmclan_config(struct pcmcia_device *link); 403b955f6caSJeff Kirsher static void nmclan_release(struct pcmcia_device *link); 404b955f6caSJeff Kirsher 405b955f6caSJeff Kirsher static void nmclan_reset(struct net_device *dev); 406b955f6caSJeff Kirsher static int mace_config(struct net_device *dev, struct ifmap *map); 407b955f6caSJeff Kirsher static int mace_open(struct net_device *dev); 408b955f6caSJeff Kirsher static int mace_close(struct net_device *dev); 409b955f6caSJeff Kirsher static netdev_tx_t mace_start_xmit(struct sk_buff *skb, 410b955f6caSJeff Kirsher struct net_device *dev); 411b955f6caSJeff Kirsher static void mace_tx_timeout(struct net_device *dev); 412b955f6caSJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id); 413b955f6caSJeff Kirsher static struct net_device_stats *mace_get_stats(struct net_device *dev); 414b955f6caSJeff Kirsher static int mace_rx(struct net_device *dev, unsigned char RxCnt); 415b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev); 416b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev); 417b955f6caSJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops; 418b955f6caSJeff Kirsher 419b955f6caSJeff Kirsher 420b955f6caSJeff Kirsher static void nmclan_detach(struct pcmcia_device *p_dev); 421b955f6caSJeff Kirsher 422b955f6caSJeff Kirsher static const struct net_device_ops mace_netdev_ops = { 423b955f6caSJeff Kirsher .ndo_open = mace_open, 424b955f6caSJeff Kirsher .ndo_stop = mace_close, 425b955f6caSJeff Kirsher .ndo_start_xmit = mace_start_xmit, 426b955f6caSJeff Kirsher .ndo_tx_timeout = mace_tx_timeout, 427b955f6caSJeff Kirsher .ndo_set_config = mace_config, 428b955f6caSJeff Kirsher .ndo_get_stats = mace_get_stats, 429afc4b13dSJiri Pirko .ndo_set_rx_mode = set_multicast_list, 430b955f6caSJeff Kirsher .ndo_change_mtu = eth_change_mtu, 431b955f6caSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 432b955f6caSJeff Kirsher .ndo_validate_addr = eth_validate_addr, 433b955f6caSJeff Kirsher }; 434b955f6caSJeff Kirsher 435b955f6caSJeff Kirsher static int nmclan_probe(struct pcmcia_device *link) 436b955f6caSJeff Kirsher { 437b955f6caSJeff Kirsher mace_private *lp; 438b955f6caSJeff Kirsher struct net_device *dev; 439b955f6caSJeff Kirsher 440b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_attach()\n"); 441b955f6caSJeff Kirsher 442b955f6caSJeff Kirsher /* Create new ethernet device */ 443b955f6caSJeff Kirsher dev = alloc_etherdev(sizeof(mace_private)); 444b955f6caSJeff Kirsher if (!dev) 445b955f6caSJeff Kirsher return -ENOMEM; 446b955f6caSJeff Kirsher lp = netdev_priv(dev); 447b955f6caSJeff Kirsher lp->p_dev = link; 448b955f6caSJeff Kirsher link->priv = dev; 449b955f6caSJeff Kirsher 450b955f6caSJeff Kirsher spin_lock_init(&lp->bank_lock); 451b955f6caSJeff Kirsher link->resource[0]->end = 32; 452b955f6caSJeff Kirsher link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; 453b955f6caSJeff Kirsher link->config_flags |= CONF_ENABLE_IRQ; 454b955f6caSJeff Kirsher link->config_index = 1; 455b955f6caSJeff Kirsher link->config_regs = PRESENT_OPTION; 456b955f6caSJeff Kirsher 457b955f6caSJeff Kirsher lp->tx_free_frames=AM2150_MAX_TX_FRAMES; 458b955f6caSJeff Kirsher 459b955f6caSJeff Kirsher dev->netdev_ops = &mace_netdev_ops; 4607ad24ea4SWilfried Klaebe dev->ethtool_ops = &netdev_ethtool_ops; 461b955f6caSJeff Kirsher dev->watchdog_timeo = TX_TIMEOUT; 462b955f6caSJeff Kirsher 463b955f6caSJeff Kirsher return nmclan_config(link); 464b955f6caSJeff Kirsher } /* nmclan_attach */ 465b955f6caSJeff Kirsher 466b955f6caSJeff Kirsher static void nmclan_detach(struct pcmcia_device *link) 467b955f6caSJeff Kirsher { 468b955f6caSJeff Kirsher struct net_device *dev = link->priv; 469b955f6caSJeff Kirsher 470b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_detach\n"); 471b955f6caSJeff Kirsher 472b955f6caSJeff Kirsher unregister_netdev(dev); 473b955f6caSJeff Kirsher 474b955f6caSJeff Kirsher nmclan_release(link); 475b955f6caSJeff Kirsher 476b955f6caSJeff Kirsher free_netdev(dev); 477b955f6caSJeff Kirsher } /* nmclan_detach */ 478b955f6caSJeff Kirsher 479b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 480b955f6caSJeff Kirsher mace_read 481b955f6caSJeff Kirsher Reads a MACE register. This is bank independent; however, the 482b955f6caSJeff Kirsher caller must ensure that this call is not interruptable. We are 483b955f6caSJeff Kirsher assuming that during normal operation, the MACE is always in 484b955f6caSJeff Kirsher bank 0. 485b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 486b955f6caSJeff Kirsher static int mace_read(mace_private *lp, unsigned int ioaddr, int reg) 487b955f6caSJeff Kirsher { 488b955f6caSJeff Kirsher int data = 0xFF; 489b955f6caSJeff Kirsher unsigned long flags; 490b955f6caSJeff Kirsher 491b955f6caSJeff Kirsher switch (reg >> 4) { 492b955f6caSJeff Kirsher case 0: /* register 0-15 */ 493b955f6caSJeff Kirsher data = inb(ioaddr + AM2150_MACE_BASE + reg); 494b955f6caSJeff Kirsher break; 495b955f6caSJeff Kirsher case 1: /* register 16-31 */ 496b955f6caSJeff Kirsher spin_lock_irqsave(&lp->bank_lock, flags); 497b955f6caSJeff Kirsher MACEBANK(1); 498b955f6caSJeff Kirsher data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); 499b955f6caSJeff Kirsher MACEBANK(0); 500b955f6caSJeff Kirsher spin_unlock_irqrestore(&lp->bank_lock, flags); 501b955f6caSJeff Kirsher break; 502b955f6caSJeff Kirsher } 503b955f6caSJeff Kirsher return data & 0xFF; 504b955f6caSJeff Kirsher } /* mace_read */ 505b955f6caSJeff Kirsher 506b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 507b955f6caSJeff Kirsher mace_write 508b955f6caSJeff Kirsher Writes to a MACE register. This is bank independent; however, 509b955f6caSJeff Kirsher the caller must ensure that this call is not interruptable. We 510b955f6caSJeff Kirsher are assuming that during normal operation, the MACE is always in 511b955f6caSJeff Kirsher bank 0. 512b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 513b955f6caSJeff Kirsher static void mace_write(mace_private *lp, unsigned int ioaddr, int reg, 514b955f6caSJeff Kirsher int data) 515b955f6caSJeff Kirsher { 516b955f6caSJeff Kirsher unsigned long flags; 517b955f6caSJeff Kirsher 518b955f6caSJeff Kirsher switch (reg >> 4) { 519b955f6caSJeff Kirsher case 0: /* register 0-15 */ 520b955f6caSJeff Kirsher outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg); 521b955f6caSJeff Kirsher break; 522b955f6caSJeff Kirsher case 1: /* register 16-31 */ 523b955f6caSJeff Kirsher spin_lock_irqsave(&lp->bank_lock, flags); 524b955f6caSJeff Kirsher MACEBANK(1); 525b955f6caSJeff Kirsher outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); 526b955f6caSJeff Kirsher MACEBANK(0); 527b955f6caSJeff Kirsher spin_unlock_irqrestore(&lp->bank_lock, flags); 528b955f6caSJeff Kirsher break; 529b955f6caSJeff Kirsher } 530b955f6caSJeff Kirsher } /* mace_write */ 531b955f6caSJeff Kirsher 532b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 533b955f6caSJeff Kirsher mace_init 534b955f6caSJeff Kirsher Resets the MACE chip. 535b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 536b955f6caSJeff Kirsher static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) 537b955f6caSJeff Kirsher { 538b955f6caSJeff Kirsher int i; 539b955f6caSJeff Kirsher int ct = 0; 540b955f6caSJeff Kirsher 541b955f6caSJeff Kirsher /* MACE Software reset */ 542b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_BIUCC, 1); 543b955f6caSJeff Kirsher while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) { 544b955f6caSJeff Kirsher /* Wait for reset bit to be cleared automatically after <= 200ns */; 545b955f6caSJeff Kirsher if(++ct > 500) 546b955f6caSJeff Kirsher { 547b955f6caSJeff Kirsher pr_err("reset failed, card removed?\n"); 548b955f6caSJeff Kirsher return -1; 549b955f6caSJeff Kirsher } 550b955f6caSJeff Kirsher udelay(1); 551b955f6caSJeff Kirsher } 552b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_BIUCC, 0); 553b955f6caSJeff Kirsher 554b955f6caSJeff Kirsher /* The Am2150 requires that the MACE FIFOs operate in burst mode. */ 555b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F); 556b955f6caSJeff Kirsher 557b955f6caSJeff Kirsher mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */ 558b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */ 559b955f6caSJeff Kirsher 560b955f6caSJeff Kirsher /* 561b955f6caSJeff Kirsher * Bit 2-1 PORTSEL[1-0] Port Select. 562b955f6caSJeff Kirsher * 00 AUI/10Base-2 563b955f6caSJeff Kirsher * 01 10Base-T 564b955f6caSJeff Kirsher * 10 DAI Port (reserved in Am2150) 565b955f6caSJeff Kirsher * 11 GPSI 566b955f6caSJeff Kirsher * For this card, only the first two are valid. 567b955f6caSJeff Kirsher * So, PLSCC should be set to 568b955f6caSJeff Kirsher * 0x00 for 10Base-2 569b955f6caSJeff Kirsher * 0x02 for 10Base-T 570b955f6caSJeff Kirsher * Or just set ASEL in PHYCC below! 571b955f6caSJeff Kirsher */ 572b955f6caSJeff Kirsher switch (if_port) { 573b955f6caSJeff Kirsher case 1: 574b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_PLSCC, 0x02); 575b955f6caSJeff Kirsher break; 576b955f6caSJeff Kirsher case 2: 577b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_PLSCC, 0x00); 578b955f6caSJeff Kirsher break; 579b955f6caSJeff Kirsher default: 580b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4); 581b955f6caSJeff Kirsher /* ASEL Auto Select. When set, the PORTSEL[1-0] bits are overridden, 582b955f6caSJeff Kirsher and the MACE device will automatically select the operating media 583b955f6caSJeff Kirsher interface port. */ 584b955f6caSJeff Kirsher break; 585b955f6caSJeff Kirsher } 586b955f6caSJeff Kirsher 587b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR); 588b955f6caSJeff Kirsher /* Poll ADDRCHG bit */ 589b955f6caSJeff Kirsher ct = 0; 590b955f6caSJeff Kirsher while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) 591b955f6caSJeff Kirsher { 592b955f6caSJeff Kirsher if(++ ct > 500) 593b955f6caSJeff Kirsher { 594b955f6caSJeff Kirsher pr_err("ADDRCHG timeout, card removed?\n"); 595b955f6caSJeff Kirsher return -1; 596b955f6caSJeff Kirsher } 597b955f6caSJeff Kirsher } 598b955f6caSJeff Kirsher /* Set PADR register */ 599104bf3fbSJoe Perches for (i = 0; i < ETH_ALEN; i++) 600b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]); 601b955f6caSJeff Kirsher 602b955f6caSJeff Kirsher /* MAC Configuration Control Register should be written last */ 603b955f6caSJeff Kirsher /* Let set_multicast_list set this. */ 604b955f6caSJeff Kirsher /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */ 605b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, 0x00); 606b955f6caSJeff Kirsher return 0; 607b955f6caSJeff Kirsher } /* mace_init */ 608b955f6caSJeff Kirsher 609b955f6caSJeff Kirsher static int nmclan_config(struct pcmcia_device *link) 610b955f6caSJeff Kirsher { 611b955f6caSJeff Kirsher struct net_device *dev = link->priv; 612b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 613b955f6caSJeff Kirsher u8 *buf; 614b955f6caSJeff Kirsher size_t len; 615b955f6caSJeff Kirsher int i, ret; 616b955f6caSJeff Kirsher unsigned int ioaddr; 617b955f6caSJeff Kirsher 618b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_config\n"); 619b955f6caSJeff Kirsher 620b955f6caSJeff Kirsher link->io_lines = 5; 621b955f6caSJeff Kirsher ret = pcmcia_request_io(link); 622b955f6caSJeff Kirsher if (ret) 623b955f6caSJeff Kirsher goto failed; 6245f5316fcSJeff Kirsher ret = pcmcia_request_irq(link, mace_interrupt); 625b955f6caSJeff Kirsher if (ret) 626b955f6caSJeff Kirsher goto failed; 627b955f6caSJeff Kirsher ret = pcmcia_enable_device(link); 628b955f6caSJeff Kirsher if (ret) 629b955f6caSJeff Kirsher goto failed; 630b955f6caSJeff Kirsher 631b955f6caSJeff Kirsher dev->irq = link->irq; 632b955f6caSJeff Kirsher dev->base_addr = link->resource[0]->start; 633b955f6caSJeff Kirsher 634b955f6caSJeff Kirsher ioaddr = dev->base_addr; 635b955f6caSJeff Kirsher 636b955f6caSJeff Kirsher /* Read the ethernet address from the CIS. */ 637b955f6caSJeff Kirsher len = pcmcia_get_tuple(link, 0x80, &buf); 638104bf3fbSJoe Perches if (!buf || len < ETH_ALEN) { 639b955f6caSJeff Kirsher kfree(buf); 640b955f6caSJeff Kirsher goto failed; 641b955f6caSJeff Kirsher } 642104bf3fbSJoe Perches memcpy(dev->dev_addr, buf, ETH_ALEN); 643b955f6caSJeff Kirsher kfree(buf); 644b955f6caSJeff Kirsher 645b955f6caSJeff Kirsher /* Verify configuration by reading the MACE ID. */ 646b955f6caSJeff Kirsher { 647b955f6caSJeff Kirsher char sig[2]; 648b955f6caSJeff Kirsher 649b955f6caSJeff Kirsher sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL); 650b955f6caSJeff Kirsher sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH); 651b955f6caSJeff Kirsher if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) { 652b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n", 653b955f6caSJeff Kirsher sig[0], sig[1]); 654b955f6caSJeff Kirsher } else { 655b955f6caSJeff Kirsher pr_notice("mace id not found: %x %x should be 0x40 0x?9\n", 656b955f6caSJeff Kirsher sig[0], sig[1]); 657b955f6caSJeff Kirsher return -ENODEV; 658b955f6caSJeff Kirsher } 659b955f6caSJeff Kirsher } 660b955f6caSJeff Kirsher 661b955f6caSJeff Kirsher if(mace_init(lp, ioaddr, dev->dev_addr) == -1) 662b955f6caSJeff Kirsher goto failed; 663b955f6caSJeff Kirsher 664b955f6caSJeff Kirsher /* The if_port symbol can be set when the module is loaded */ 665b955f6caSJeff Kirsher if (if_port <= 2) 666b955f6caSJeff Kirsher dev->if_port = if_port; 667b955f6caSJeff Kirsher else 668b955f6caSJeff Kirsher pr_notice("invalid if_port requested\n"); 669b955f6caSJeff Kirsher 670b955f6caSJeff Kirsher SET_NETDEV_DEV(dev, &link->dev); 671b955f6caSJeff Kirsher 672b955f6caSJeff Kirsher i = register_netdev(dev); 673b955f6caSJeff Kirsher if (i != 0) { 674b955f6caSJeff Kirsher pr_notice("register_netdev() failed\n"); 675b955f6caSJeff Kirsher goto failed; 676b955f6caSJeff Kirsher } 677b955f6caSJeff Kirsher 678b955f6caSJeff Kirsher netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n", 679b955f6caSJeff Kirsher dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr); 680b955f6caSJeff Kirsher return 0; 681b955f6caSJeff Kirsher 682b955f6caSJeff Kirsher failed: 683b955f6caSJeff Kirsher nmclan_release(link); 684b955f6caSJeff Kirsher return -ENODEV; 685b955f6caSJeff Kirsher } /* nmclan_config */ 686b955f6caSJeff Kirsher 687b955f6caSJeff Kirsher static void nmclan_release(struct pcmcia_device *link) 688b955f6caSJeff Kirsher { 689b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_release\n"); 690b955f6caSJeff Kirsher pcmcia_disable_device(link); 691b955f6caSJeff Kirsher } 692b955f6caSJeff Kirsher 693b955f6caSJeff Kirsher static int nmclan_suspend(struct pcmcia_device *link) 694b955f6caSJeff Kirsher { 695b955f6caSJeff Kirsher struct net_device *dev = link->priv; 696b955f6caSJeff Kirsher 697b955f6caSJeff Kirsher if (link->open) 698b955f6caSJeff Kirsher netif_device_detach(dev); 699b955f6caSJeff Kirsher 700b955f6caSJeff Kirsher return 0; 701b955f6caSJeff Kirsher } 702b955f6caSJeff Kirsher 703b955f6caSJeff Kirsher static int nmclan_resume(struct pcmcia_device *link) 704b955f6caSJeff Kirsher { 705b955f6caSJeff Kirsher struct net_device *dev = link->priv; 706b955f6caSJeff Kirsher 707b955f6caSJeff Kirsher if (link->open) { 708b955f6caSJeff Kirsher nmclan_reset(dev); 709b955f6caSJeff Kirsher netif_device_attach(dev); 710b955f6caSJeff Kirsher } 711b955f6caSJeff Kirsher 712b955f6caSJeff Kirsher return 0; 713b955f6caSJeff Kirsher } 714b955f6caSJeff Kirsher 715b955f6caSJeff Kirsher 716b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 717b955f6caSJeff Kirsher nmclan_reset 718b955f6caSJeff Kirsher Reset and restore all of the Xilinx and MACE registers. 719b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 720b955f6caSJeff Kirsher static void nmclan_reset(struct net_device *dev) 721b955f6caSJeff Kirsher { 722b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 723b955f6caSJeff Kirsher 724b955f6caSJeff Kirsher #if RESET_XILINX 725b955f6caSJeff Kirsher struct pcmcia_device *link = &lp->link; 726b955f6caSJeff Kirsher u8 OrigCorValue; 727b955f6caSJeff Kirsher 728b955f6caSJeff Kirsher /* Save original COR value */ 729b955f6caSJeff Kirsher pcmcia_read_config_byte(link, CISREG_COR, &OrigCorValue); 730b955f6caSJeff Kirsher 731b955f6caSJeff Kirsher /* Reset Xilinx */ 732b955f6caSJeff Kirsher dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%x, resetting...\n", 733b955f6caSJeff Kirsher OrigCorValue); 734b955f6caSJeff Kirsher pcmcia_write_config_byte(link, CISREG_COR, COR_SOFT_RESET); 735b955f6caSJeff Kirsher /* Need to wait for 20 ms for PCMCIA to finish reset. */ 736b955f6caSJeff Kirsher 737b955f6caSJeff Kirsher /* Restore original COR configuration index */ 738b955f6caSJeff Kirsher pcmcia_write_config_byte(link, CISREG_COR, 739b955f6caSJeff Kirsher (COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK))); 740b955f6caSJeff Kirsher /* Xilinx is now completely reset along with the MACE chip. */ 741b955f6caSJeff Kirsher lp->tx_free_frames=AM2150_MAX_TX_FRAMES; 742b955f6caSJeff Kirsher 743b955f6caSJeff Kirsher #endif /* #if RESET_XILINX */ 744b955f6caSJeff Kirsher 745b955f6caSJeff Kirsher /* Xilinx is now completely reset along with the MACE chip. */ 746b955f6caSJeff Kirsher lp->tx_free_frames=AM2150_MAX_TX_FRAMES; 747b955f6caSJeff Kirsher 748b955f6caSJeff Kirsher /* Reinitialize the MACE chip for operation. */ 749b955f6caSJeff Kirsher mace_init(lp, dev->base_addr, dev->dev_addr); 750b955f6caSJeff Kirsher mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT); 751b955f6caSJeff Kirsher 752b955f6caSJeff Kirsher /* Restore the multicast list and enable TX and RX. */ 753b955f6caSJeff Kirsher restore_multicast_list(dev); 754b955f6caSJeff Kirsher } /* nmclan_reset */ 755b955f6caSJeff Kirsher 756b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 757b955f6caSJeff Kirsher mace_config 758b955f6caSJeff Kirsher [Someone tell me what this is supposed to do? Is if_port a defined 759b955f6caSJeff Kirsher standard? If so, there should be defines to indicate 1=10Base-T, 760b955f6caSJeff Kirsher 2=10Base-2, etc. including limited automatic detection.] 761b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 762b955f6caSJeff Kirsher static int mace_config(struct net_device *dev, struct ifmap *map) 763b955f6caSJeff Kirsher { 764b955f6caSJeff Kirsher if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { 765b955f6caSJeff Kirsher if (map->port <= 2) { 766b955f6caSJeff Kirsher dev->if_port = map->port; 767b955f6caSJeff Kirsher netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); 768b955f6caSJeff Kirsher } else 769b955f6caSJeff Kirsher return -EINVAL; 770b955f6caSJeff Kirsher } 771b955f6caSJeff Kirsher return 0; 772b955f6caSJeff Kirsher } /* mace_config */ 773b955f6caSJeff Kirsher 774b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 775b955f6caSJeff Kirsher mace_open 776b955f6caSJeff Kirsher Open device driver. 777b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 778b955f6caSJeff Kirsher static int mace_open(struct net_device *dev) 779b955f6caSJeff Kirsher { 780b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 781b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 782b955f6caSJeff Kirsher struct pcmcia_device *link = lp->p_dev; 783b955f6caSJeff Kirsher 784b955f6caSJeff Kirsher if (!pcmcia_dev_present(link)) 785b955f6caSJeff Kirsher return -ENODEV; 786b955f6caSJeff Kirsher 787b955f6caSJeff Kirsher link->open++; 788b955f6caSJeff Kirsher 789b955f6caSJeff Kirsher MACEBANK(0); 790b955f6caSJeff Kirsher 791b955f6caSJeff Kirsher netif_start_queue(dev); 792b955f6caSJeff Kirsher nmclan_reset(dev); 793b955f6caSJeff Kirsher 794b955f6caSJeff Kirsher return 0; /* Always succeed */ 795b955f6caSJeff Kirsher } /* mace_open */ 796b955f6caSJeff Kirsher 797b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 798b955f6caSJeff Kirsher mace_close 799b955f6caSJeff Kirsher Closes device driver. 800b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 801b955f6caSJeff Kirsher static int mace_close(struct net_device *dev) 802b955f6caSJeff Kirsher { 803b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 804b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 805b955f6caSJeff Kirsher struct pcmcia_device *link = lp->p_dev; 806b955f6caSJeff Kirsher 807b955f6caSJeff Kirsher dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name); 808b955f6caSJeff Kirsher 809b955f6caSJeff Kirsher /* Mask off all interrupts from the MACE chip. */ 810b955f6caSJeff Kirsher outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR); 811b955f6caSJeff Kirsher 812b955f6caSJeff Kirsher link->open--; 813b955f6caSJeff Kirsher netif_stop_queue(dev); 814b955f6caSJeff Kirsher 815b955f6caSJeff Kirsher return 0; 816b955f6caSJeff Kirsher } /* mace_close */ 817b955f6caSJeff Kirsher 818b955f6caSJeff Kirsher static void netdev_get_drvinfo(struct net_device *dev, 819b955f6caSJeff Kirsher struct ethtool_drvinfo *info) 820b955f6caSJeff Kirsher { 82133a5ba14SRick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 82233a5ba14SRick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 82333a5ba14SRick Jones snprintf(info->bus_info, sizeof(info->bus_info), 82433a5ba14SRick Jones "PCMCIA 0x%lx", dev->base_addr); 825b955f6caSJeff Kirsher } 826b955f6caSJeff Kirsher 827b955f6caSJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops = { 828b955f6caSJeff Kirsher .get_drvinfo = netdev_get_drvinfo, 829b955f6caSJeff Kirsher }; 830b955f6caSJeff Kirsher 831b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 832b955f6caSJeff Kirsher mace_start_xmit 833b955f6caSJeff Kirsher This routine begins the packet transmit function. When completed, 834b955f6caSJeff Kirsher it will generate a transmit interrupt. 835b955f6caSJeff Kirsher 836b955f6caSJeff Kirsher According to /usr/src/linux/net/inet/dev.c, if _start_xmit 837b955f6caSJeff Kirsher returns 0, the "packet is now solely the responsibility of the 838b955f6caSJeff Kirsher driver." If _start_xmit returns non-zero, the "transmission 839b955f6caSJeff Kirsher failed, put skb back into a list." 840b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 841b955f6caSJeff Kirsher 842b955f6caSJeff Kirsher static void mace_tx_timeout(struct net_device *dev) 843b955f6caSJeff Kirsher { 844b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 845b955f6caSJeff Kirsher struct pcmcia_device *link = lp->p_dev; 846b955f6caSJeff Kirsher 847b955f6caSJeff Kirsher netdev_notice(dev, "transmit timed out -- "); 848b955f6caSJeff Kirsher #if RESET_ON_TIMEOUT 849b955f6caSJeff Kirsher pr_cont("resetting card\n"); 850b955f6caSJeff Kirsher pcmcia_reset_card(link->socket); 851b955f6caSJeff Kirsher #else /* #if RESET_ON_TIMEOUT */ 852b955f6caSJeff Kirsher pr_cont("NOT resetting card\n"); 853b955f6caSJeff Kirsher #endif /* #if RESET_ON_TIMEOUT */ 854b955f6caSJeff Kirsher dev->trans_start = jiffies; /* prevent tx timeout */ 855b955f6caSJeff Kirsher netif_wake_queue(dev); 856b955f6caSJeff Kirsher } 857b955f6caSJeff Kirsher 858b955f6caSJeff Kirsher static netdev_tx_t mace_start_xmit(struct sk_buff *skb, 859b955f6caSJeff Kirsher struct net_device *dev) 860b955f6caSJeff Kirsher { 861b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 862b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 863b955f6caSJeff Kirsher 864b955f6caSJeff Kirsher netif_stop_queue(dev); 865b955f6caSJeff Kirsher 866b955f6caSJeff Kirsher pr_debug("%s: mace_start_xmit(length = %ld) called.\n", 867b955f6caSJeff Kirsher dev->name, (long)skb->len); 868b955f6caSJeff Kirsher 869b955f6caSJeff Kirsher #if (!TX_INTERRUPTABLE) 870b955f6caSJeff Kirsher /* Disable MACE TX interrupts. */ 871b955f6caSJeff Kirsher outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT, 872b955f6caSJeff Kirsher ioaddr + AM2150_MACE_BASE + MACE_IMR); 873b955f6caSJeff Kirsher lp->tx_irq_disabled=1; 874b955f6caSJeff Kirsher #endif /* #if (!TX_INTERRUPTABLE) */ 875b955f6caSJeff Kirsher 876b955f6caSJeff Kirsher { 877b955f6caSJeff Kirsher /* This block must not be interrupted by another transmit request! 878b955f6caSJeff Kirsher mace_tx_timeout will take care of timer-based retransmissions from 879b955f6caSJeff Kirsher the upper layers. The interrupt handler is guaranteed never to 880b955f6caSJeff Kirsher service a transmit interrupt while we are in here. 881b955f6caSJeff Kirsher */ 882b955f6caSJeff Kirsher 883b955f6caSJeff Kirsher lp->linux_stats.tx_bytes += skb->len; 884b955f6caSJeff Kirsher lp->tx_free_frames--; 885b955f6caSJeff Kirsher 886b955f6caSJeff Kirsher /* WARNING: Write the _exact_ number of bytes written in the header! */ 887b955f6caSJeff Kirsher /* Put out the word header [must be an outw()] . . . */ 888b955f6caSJeff Kirsher outw(skb->len, ioaddr + AM2150_XMT); 889b955f6caSJeff Kirsher /* . . . and the packet [may be any combination of outw() and outb()] */ 890b955f6caSJeff Kirsher outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1); 891b955f6caSJeff Kirsher if (skb->len & 1) { 892b955f6caSJeff Kirsher /* Odd byte transfer */ 893b955f6caSJeff Kirsher outb(skb->data[skb->len-1], ioaddr + AM2150_XMT); 894b955f6caSJeff Kirsher } 895b955f6caSJeff Kirsher 896b955f6caSJeff Kirsher #if MULTI_TX 897b955f6caSJeff Kirsher if (lp->tx_free_frames > 0) 898b955f6caSJeff Kirsher netif_start_queue(dev); 899b955f6caSJeff Kirsher #endif /* #if MULTI_TX */ 900b955f6caSJeff Kirsher } 901b955f6caSJeff Kirsher 902b955f6caSJeff Kirsher #if (!TX_INTERRUPTABLE) 903b955f6caSJeff Kirsher /* Re-enable MACE TX interrupts. */ 904b955f6caSJeff Kirsher lp->tx_irq_disabled=0; 905b955f6caSJeff Kirsher outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR); 906b955f6caSJeff Kirsher #endif /* #if (!TX_INTERRUPTABLE) */ 907b955f6caSJeff Kirsher 908b955f6caSJeff Kirsher dev_kfree_skb(skb); 909b955f6caSJeff Kirsher 910b955f6caSJeff Kirsher return NETDEV_TX_OK; 911b955f6caSJeff Kirsher } /* mace_start_xmit */ 912b955f6caSJeff Kirsher 913b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 914b955f6caSJeff Kirsher mace_interrupt 915b955f6caSJeff Kirsher The interrupt handler. 916b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 917b955f6caSJeff Kirsher static irqreturn_t mace_interrupt(int irq, void *dev_id) 918b955f6caSJeff Kirsher { 919b955f6caSJeff Kirsher struct net_device *dev = (struct net_device *) dev_id; 920b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 921b955f6caSJeff Kirsher unsigned int ioaddr; 922b955f6caSJeff Kirsher int status; 923b955f6caSJeff Kirsher int IntrCnt = MACE_MAX_IR_ITERATIONS; 924b955f6caSJeff Kirsher 925b955f6caSJeff Kirsher if (dev == NULL) { 926b955f6caSJeff Kirsher pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n", 927b955f6caSJeff Kirsher irq); 928b955f6caSJeff Kirsher return IRQ_NONE; 929b955f6caSJeff Kirsher } 930b955f6caSJeff Kirsher 931b955f6caSJeff Kirsher ioaddr = dev->base_addr; 932b955f6caSJeff Kirsher 933b955f6caSJeff Kirsher if (lp->tx_irq_disabled) { 934b955f6caSJeff Kirsher const char *msg; 935b955f6caSJeff Kirsher if (lp->tx_irq_disabled) 936b955f6caSJeff Kirsher msg = "Interrupt with tx_irq_disabled"; 937b955f6caSJeff Kirsher else 938b955f6caSJeff Kirsher msg = "Re-entering the interrupt handler"; 939b955f6caSJeff Kirsher netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n", 940b955f6caSJeff Kirsher msg, 941b955f6caSJeff Kirsher inb(ioaddr + AM2150_MACE_BASE + MACE_IR), 942b955f6caSJeff Kirsher inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)); 943b955f6caSJeff Kirsher /* WARNING: MACE_IR has been read! */ 944b955f6caSJeff Kirsher return IRQ_NONE; 945b955f6caSJeff Kirsher } 946b955f6caSJeff Kirsher 947b955f6caSJeff Kirsher if (!netif_device_present(dev)) { 948b955f6caSJeff Kirsher netdev_dbg(dev, "interrupt from dead card\n"); 949b955f6caSJeff Kirsher return IRQ_NONE; 950b955f6caSJeff Kirsher } 951b955f6caSJeff Kirsher 952b955f6caSJeff Kirsher do { 953b955f6caSJeff Kirsher /* WARNING: MACE_IR is a READ/CLEAR port! */ 954b955f6caSJeff Kirsher status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR); 955*96a30175SArnd Bergmann if (!(status & ~MACE_IMR_DEFAULT) && IntrCnt == MACE_MAX_IR_ITERATIONS) 956*96a30175SArnd Bergmann return IRQ_NONE; 957b955f6caSJeff Kirsher 958b955f6caSJeff Kirsher pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status); 959b955f6caSJeff Kirsher 960b955f6caSJeff Kirsher if (status & MACE_IR_RCVINT) { 961b955f6caSJeff Kirsher mace_rx(dev, MACE_MAX_RX_ITERATIONS); 962b955f6caSJeff Kirsher } 963b955f6caSJeff Kirsher 964b955f6caSJeff Kirsher if (status & MACE_IR_XMTINT) { 965b955f6caSJeff Kirsher unsigned char fifofc; 966b955f6caSJeff Kirsher unsigned char xmtrc; 967b955f6caSJeff Kirsher unsigned char xmtfs; 968b955f6caSJeff Kirsher 969b955f6caSJeff Kirsher fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC); 970b955f6caSJeff Kirsher if ((fifofc & MACE_FIFOFC_XMTFC)==0) { 971b955f6caSJeff Kirsher lp->linux_stats.tx_errors++; 972b955f6caSJeff Kirsher outb(0xFF, ioaddr + AM2150_XMT_SKIP); 973b955f6caSJeff Kirsher } 974b955f6caSJeff Kirsher 975b955f6caSJeff Kirsher /* Transmit Retry Count (XMTRC, reg 4) */ 976b955f6caSJeff Kirsher xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC); 977b955f6caSJeff Kirsher if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++; 978b955f6caSJeff Kirsher lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC); 979b955f6caSJeff Kirsher 980b955f6caSJeff Kirsher if ( 981b955f6caSJeff Kirsher (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) & 982b955f6caSJeff Kirsher MACE_XMTFS_XMTSV /* Transmit Status Valid */ 983b955f6caSJeff Kirsher ) { 984b955f6caSJeff Kirsher lp->mace_stats.xmtsv++; 985b955f6caSJeff Kirsher 986b955f6caSJeff Kirsher if (xmtfs & ~MACE_XMTFS_XMTSV) { 987b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_UFLO) { 988b955f6caSJeff Kirsher /* Underflow. Indicates that the Transmit FIFO emptied before 989b955f6caSJeff Kirsher the end of frame was reached. */ 990b955f6caSJeff Kirsher lp->mace_stats.uflo++; 991b955f6caSJeff Kirsher } 992b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_LCOL) { 993b955f6caSJeff Kirsher /* Late Collision */ 994b955f6caSJeff Kirsher lp->mace_stats.lcol++; 995b955f6caSJeff Kirsher } 996b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_MORE) { 997b955f6caSJeff Kirsher /* MORE than one retry was needed */ 998b955f6caSJeff Kirsher lp->mace_stats.more++; 999b955f6caSJeff Kirsher } 1000b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_ONE) { 1001b955f6caSJeff Kirsher /* Exactly ONE retry occurred */ 1002b955f6caSJeff Kirsher lp->mace_stats.one++; 1003b955f6caSJeff Kirsher } 1004b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_DEFER) { 1005b955f6caSJeff Kirsher /* Transmission was defered */ 1006b955f6caSJeff Kirsher lp->mace_stats.defer++; 1007b955f6caSJeff Kirsher } 1008b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_LCAR) { 1009b955f6caSJeff Kirsher /* Loss of carrier */ 1010b955f6caSJeff Kirsher lp->mace_stats.lcar++; 1011b955f6caSJeff Kirsher } 1012b955f6caSJeff Kirsher if (xmtfs & MACE_XMTFS_RTRY) { 1013b955f6caSJeff Kirsher /* Retry error: transmit aborted after 16 attempts */ 1014b955f6caSJeff Kirsher lp->mace_stats.rtry++; 1015b955f6caSJeff Kirsher } 1016b955f6caSJeff Kirsher } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */ 1017b955f6caSJeff Kirsher 1018b955f6caSJeff Kirsher } /* if (xmtfs & MACE_XMTFS_XMTSV) */ 1019b955f6caSJeff Kirsher 1020b955f6caSJeff Kirsher lp->linux_stats.tx_packets++; 1021b955f6caSJeff Kirsher lp->tx_free_frames++; 1022b955f6caSJeff Kirsher netif_wake_queue(dev); 1023b955f6caSJeff Kirsher } /* if (status & MACE_IR_XMTINT) */ 1024b955f6caSJeff Kirsher 1025b955f6caSJeff Kirsher if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) { 1026b955f6caSJeff Kirsher if (status & MACE_IR_JAB) { 1027b955f6caSJeff Kirsher /* Jabber Error. Excessive transmit duration (20-150ms). */ 1028b955f6caSJeff Kirsher lp->mace_stats.jab++; 1029b955f6caSJeff Kirsher } 1030b955f6caSJeff Kirsher if (status & MACE_IR_BABL) { 1031b955f6caSJeff Kirsher /* Babble Error. >1518 bytes transmitted. */ 1032b955f6caSJeff Kirsher lp->mace_stats.babl++; 1033b955f6caSJeff Kirsher } 1034b955f6caSJeff Kirsher if (status & MACE_IR_CERR) { 1035b955f6caSJeff Kirsher /* Collision Error. CERR indicates the absence of the 1036b955f6caSJeff Kirsher Signal Quality Error Test message after a packet 1037b955f6caSJeff Kirsher transmission. */ 1038b955f6caSJeff Kirsher lp->mace_stats.cerr++; 1039b955f6caSJeff Kirsher } 1040b955f6caSJeff Kirsher if (status & MACE_IR_RCVCCO) { 1041b955f6caSJeff Kirsher /* Receive Collision Count Overflow; */ 1042b955f6caSJeff Kirsher lp->mace_stats.rcvcco++; 1043b955f6caSJeff Kirsher } 1044b955f6caSJeff Kirsher if (status & MACE_IR_RNTPCO) { 1045b955f6caSJeff Kirsher /* Runt Packet Count Overflow */ 1046b955f6caSJeff Kirsher lp->mace_stats.rntpco++; 1047b955f6caSJeff Kirsher } 1048b955f6caSJeff Kirsher if (status & MACE_IR_MPCO) { 1049b955f6caSJeff Kirsher /* Missed Packet Count Overflow */ 1050b955f6caSJeff Kirsher lp->mace_stats.mpco++; 1051b955f6caSJeff Kirsher } 1052b955f6caSJeff Kirsher } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */ 1053b955f6caSJeff Kirsher 1054b955f6caSJeff Kirsher } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); 1055b955f6caSJeff Kirsher 1056b955f6caSJeff Kirsher return IRQ_HANDLED; 1057b955f6caSJeff Kirsher } /* mace_interrupt */ 1058b955f6caSJeff Kirsher 1059b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1060b955f6caSJeff Kirsher mace_rx 1061b955f6caSJeff Kirsher Receives packets. 1062b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1063b955f6caSJeff Kirsher static int mace_rx(struct net_device *dev, unsigned char RxCnt) 1064b955f6caSJeff Kirsher { 1065b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1066b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 1067b955f6caSJeff Kirsher unsigned char rx_framecnt; 1068b955f6caSJeff Kirsher unsigned short rx_status; 1069b955f6caSJeff Kirsher 1070b955f6caSJeff Kirsher while ( 1071b955f6caSJeff Kirsher ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) && 1072b955f6caSJeff Kirsher (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */ 1073b955f6caSJeff Kirsher (RxCnt--) 1074b955f6caSJeff Kirsher ) { 1075b955f6caSJeff Kirsher rx_status = inw(ioaddr + AM2150_RCV); 1076b955f6caSJeff Kirsher 1077b955f6caSJeff Kirsher pr_debug("%s: in mace_rx(), framecnt 0x%X, rx_status" 1078b955f6caSJeff Kirsher " 0x%X.\n", dev->name, rx_framecnt, rx_status); 1079b955f6caSJeff Kirsher 1080b955f6caSJeff Kirsher if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */ 1081b955f6caSJeff Kirsher lp->linux_stats.rx_errors++; 1082b955f6caSJeff Kirsher if (rx_status & MACE_RCVFS_OFLO) { 1083b955f6caSJeff Kirsher lp->mace_stats.oflo++; 1084b955f6caSJeff Kirsher } 1085b955f6caSJeff Kirsher if (rx_status & MACE_RCVFS_CLSN) { 1086b955f6caSJeff Kirsher lp->mace_stats.clsn++; 1087b955f6caSJeff Kirsher } 1088b955f6caSJeff Kirsher if (rx_status & MACE_RCVFS_FRAM) { 1089b955f6caSJeff Kirsher lp->mace_stats.fram++; 1090b955f6caSJeff Kirsher } 1091b955f6caSJeff Kirsher if (rx_status & MACE_RCVFS_FCS) { 1092b955f6caSJeff Kirsher lp->mace_stats.fcs++; 1093b955f6caSJeff Kirsher } 1094b955f6caSJeff Kirsher } else { 1095b955f6caSJeff Kirsher short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4; 1096b955f6caSJeff Kirsher /* Auto Strip is off, always subtract 4 */ 1097b955f6caSJeff Kirsher struct sk_buff *skb; 1098b955f6caSJeff Kirsher 1099b955f6caSJeff Kirsher lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV); 1100b955f6caSJeff Kirsher /* runt packet count */ 1101b955f6caSJeff Kirsher lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV); 1102b955f6caSJeff Kirsher /* rcv collision count */ 1103b955f6caSJeff Kirsher 1104b955f6caSJeff Kirsher pr_debug(" receiving packet size 0x%X rx_status" 1105b955f6caSJeff Kirsher " 0x%X.\n", pkt_len, rx_status); 1106b955f6caSJeff Kirsher 11071d266430SPradeep A Dalvi skb = netdev_alloc_skb(dev, pkt_len + 2); 1108b955f6caSJeff Kirsher 1109b955f6caSJeff Kirsher if (skb != NULL) { 1110b955f6caSJeff Kirsher skb_reserve(skb, 2); 1111b955f6caSJeff Kirsher insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1); 1112b955f6caSJeff Kirsher if (pkt_len & 1) 1113b955f6caSJeff Kirsher *(skb_tail_pointer(skb) - 1) = inb(ioaddr + AM2150_RCV); 1114b955f6caSJeff Kirsher skb->protocol = eth_type_trans(skb, dev); 1115b955f6caSJeff Kirsher 1116b955f6caSJeff Kirsher netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ 1117b955f6caSJeff Kirsher 1118b955f6caSJeff Kirsher lp->linux_stats.rx_packets++; 1119b955f6caSJeff Kirsher lp->linux_stats.rx_bytes += pkt_len; 1120b955f6caSJeff Kirsher outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ 1121b955f6caSJeff Kirsher continue; 1122b955f6caSJeff Kirsher } else { 1123b955f6caSJeff Kirsher pr_debug("%s: couldn't allocate a sk_buff of size" 1124b955f6caSJeff Kirsher " %d.\n", dev->name, pkt_len); 1125b955f6caSJeff Kirsher lp->linux_stats.rx_dropped++; 1126b955f6caSJeff Kirsher } 1127b955f6caSJeff Kirsher } 1128b955f6caSJeff Kirsher outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ 1129b955f6caSJeff Kirsher } /* while */ 1130b955f6caSJeff Kirsher 1131b955f6caSJeff Kirsher return 0; 1132b955f6caSJeff Kirsher } /* mace_rx */ 1133b955f6caSJeff Kirsher 1134b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1135b955f6caSJeff Kirsher pr_linux_stats 1136b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1137b955f6caSJeff Kirsher static void pr_linux_stats(struct net_device_stats *pstats) 1138b955f6caSJeff Kirsher { 1139b955f6caSJeff Kirsher pr_debug("pr_linux_stats\n"); 1140b955f6caSJeff Kirsher pr_debug(" rx_packets=%-7ld tx_packets=%ld\n", 1141b955f6caSJeff Kirsher (long)pstats->rx_packets, (long)pstats->tx_packets); 1142b955f6caSJeff Kirsher pr_debug(" rx_errors=%-7ld tx_errors=%ld\n", 1143b955f6caSJeff Kirsher (long)pstats->rx_errors, (long)pstats->tx_errors); 1144b955f6caSJeff Kirsher pr_debug(" rx_dropped=%-7ld tx_dropped=%ld\n", 1145b955f6caSJeff Kirsher (long)pstats->rx_dropped, (long)pstats->tx_dropped); 1146b955f6caSJeff Kirsher pr_debug(" multicast=%-7ld collisions=%ld\n", 1147b955f6caSJeff Kirsher (long)pstats->multicast, (long)pstats->collisions); 1148b955f6caSJeff Kirsher 1149b955f6caSJeff Kirsher pr_debug(" rx_length_errors=%-7ld rx_over_errors=%ld\n", 1150b955f6caSJeff Kirsher (long)pstats->rx_length_errors, (long)pstats->rx_over_errors); 1151b955f6caSJeff Kirsher pr_debug(" rx_crc_errors=%-7ld rx_frame_errors=%ld\n", 1152b955f6caSJeff Kirsher (long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors); 1153b955f6caSJeff Kirsher pr_debug(" rx_fifo_errors=%-7ld rx_missed_errors=%ld\n", 1154b955f6caSJeff Kirsher (long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors); 1155b955f6caSJeff Kirsher 1156b955f6caSJeff Kirsher pr_debug(" tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n", 1157b955f6caSJeff Kirsher (long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors); 1158b955f6caSJeff Kirsher pr_debug(" tx_fifo_errors=%-7ld tx_heartbeat_errors=%ld\n", 1159b955f6caSJeff Kirsher (long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors); 1160b955f6caSJeff Kirsher pr_debug(" tx_window_errors=%ld\n", 1161b955f6caSJeff Kirsher (long)pstats->tx_window_errors); 1162b955f6caSJeff Kirsher } /* pr_linux_stats */ 1163b955f6caSJeff Kirsher 1164b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1165b955f6caSJeff Kirsher pr_mace_stats 1166b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1167b955f6caSJeff Kirsher static void pr_mace_stats(mace_statistics *pstats) 1168b955f6caSJeff Kirsher { 1169b955f6caSJeff Kirsher pr_debug("pr_mace_stats\n"); 1170b955f6caSJeff Kirsher 1171b955f6caSJeff Kirsher pr_debug(" xmtsv=%-7d uflo=%d\n", 1172b955f6caSJeff Kirsher pstats->xmtsv, pstats->uflo); 1173b955f6caSJeff Kirsher pr_debug(" lcol=%-7d more=%d\n", 1174b955f6caSJeff Kirsher pstats->lcol, pstats->more); 1175b955f6caSJeff Kirsher pr_debug(" one=%-7d defer=%d\n", 1176b955f6caSJeff Kirsher pstats->one, pstats->defer); 1177b955f6caSJeff Kirsher pr_debug(" lcar=%-7d rtry=%d\n", 1178b955f6caSJeff Kirsher pstats->lcar, pstats->rtry); 1179b955f6caSJeff Kirsher 1180b955f6caSJeff Kirsher /* MACE_XMTRC */ 1181b955f6caSJeff Kirsher pr_debug(" exdef=%-7d xmtrc=%d\n", 1182b955f6caSJeff Kirsher pstats->exdef, pstats->xmtrc); 1183b955f6caSJeff Kirsher 1184b955f6caSJeff Kirsher /* RFS1--Receive Status (RCVSTS) */ 1185b955f6caSJeff Kirsher pr_debug(" oflo=%-7d clsn=%d\n", 1186b955f6caSJeff Kirsher pstats->oflo, pstats->clsn); 1187b955f6caSJeff Kirsher pr_debug(" fram=%-7d fcs=%d\n", 1188b955f6caSJeff Kirsher pstats->fram, pstats->fcs); 1189b955f6caSJeff Kirsher 1190b955f6caSJeff Kirsher /* RFS2--Runt Packet Count (RNTPC) */ 1191b955f6caSJeff Kirsher /* RFS3--Receive Collision Count (RCVCC) */ 1192b955f6caSJeff Kirsher pr_debug(" rfs_rntpc=%-7d rfs_rcvcc=%d\n", 1193b955f6caSJeff Kirsher pstats->rfs_rntpc, pstats->rfs_rcvcc); 1194b955f6caSJeff Kirsher 1195b955f6caSJeff Kirsher /* MACE_IR */ 1196b955f6caSJeff Kirsher pr_debug(" jab=%-7d babl=%d\n", 1197b955f6caSJeff Kirsher pstats->jab, pstats->babl); 1198b955f6caSJeff Kirsher pr_debug(" cerr=%-7d rcvcco=%d\n", 1199b955f6caSJeff Kirsher pstats->cerr, pstats->rcvcco); 1200b955f6caSJeff Kirsher pr_debug(" rntpco=%-7d mpco=%d\n", 1201b955f6caSJeff Kirsher pstats->rntpco, pstats->mpco); 1202b955f6caSJeff Kirsher 1203b955f6caSJeff Kirsher /* MACE_MPC */ 1204b955f6caSJeff Kirsher pr_debug(" mpc=%d\n", pstats->mpc); 1205b955f6caSJeff Kirsher 1206b955f6caSJeff Kirsher /* MACE_RNTPC */ 1207b955f6caSJeff Kirsher pr_debug(" rntpc=%d\n", pstats->rntpc); 1208b955f6caSJeff Kirsher 1209b955f6caSJeff Kirsher /* MACE_RCVCC */ 1210b955f6caSJeff Kirsher pr_debug(" rcvcc=%d\n", pstats->rcvcc); 1211b955f6caSJeff Kirsher 1212b955f6caSJeff Kirsher } /* pr_mace_stats */ 1213b955f6caSJeff Kirsher 1214b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1215b955f6caSJeff Kirsher update_stats 1216b955f6caSJeff Kirsher Update statistics. We change to register window 1, so this 1217b955f6caSJeff Kirsher should be run single-threaded if the device is active. This is 1218b955f6caSJeff Kirsher expected to be a rare operation, and it's simpler for the rest 1219b955f6caSJeff Kirsher of the driver to assume that window 0 is always valid rather 1220b955f6caSJeff Kirsher than use a special window-state variable. 1221b955f6caSJeff Kirsher 1222b955f6caSJeff Kirsher oflo & uflo should _never_ occur since it would mean the Xilinx 1223b955f6caSJeff Kirsher was not able to transfer data between the MACE FIFO and the 1224b955f6caSJeff Kirsher card's SRAM fast enough. If this happens, something is 1225b955f6caSJeff Kirsher seriously wrong with the hardware. 1226b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1227b955f6caSJeff Kirsher static void update_stats(unsigned int ioaddr, struct net_device *dev) 1228b955f6caSJeff Kirsher { 1229b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1230b955f6caSJeff Kirsher 1231b955f6caSJeff Kirsher lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC); 1232b955f6caSJeff Kirsher lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC); 1233b955f6caSJeff Kirsher lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC); 1234b955f6caSJeff Kirsher /* At this point, mace_stats is fully updated for this call. 1235b955f6caSJeff Kirsher We may now update the linux_stats. */ 1236b955f6caSJeff Kirsher 1237b955f6caSJeff Kirsher /* The MACE has no equivalent for linux_stats field which are commented 1238b955f6caSJeff Kirsher out. */ 1239b955f6caSJeff Kirsher 1240b955f6caSJeff Kirsher /* lp->linux_stats.multicast; */ 1241b955f6caSJeff Kirsher lp->linux_stats.collisions = 1242b955f6caSJeff Kirsher lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc; 1243b955f6caSJeff Kirsher /* Collision: The MACE may retry sending a packet 15 times 1244b955f6caSJeff Kirsher before giving up. The retry count is in XMTRC. 1245b955f6caSJeff Kirsher Does each retry constitute a collision? 1246b955f6caSJeff Kirsher If so, why doesn't the RCVCC record these collisions? */ 1247b955f6caSJeff Kirsher 1248b955f6caSJeff Kirsher /* detailed rx_errors: */ 1249b955f6caSJeff Kirsher lp->linux_stats.rx_length_errors = 1250b955f6caSJeff Kirsher lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc; 1251b955f6caSJeff Kirsher /* lp->linux_stats.rx_over_errors */ 1252b955f6caSJeff Kirsher lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs; 1253b955f6caSJeff Kirsher lp->linux_stats.rx_frame_errors = lp->mace_stats.fram; 1254b955f6caSJeff Kirsher lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo; 1255b955f6caSJeff Kirsher lp->linux_stats.rx_missed_errors = 1256b955f6caSJeff Kirsher lp->mace_stats.mpco * 256 + lp->mace_stats.mpc; 1257b955f6caSJeff Kirsher 1258b955f6caSJeff Kirsher /* detailed tx_errors */ 1259b955f6caSJeff Kirsher lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry; 1260b955f6caSJeff Kirsher lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar; 1261b955f6caSJeff Kirsher /* LCAR usually results from bad cabling. */ 1262b955f6caSJeff Kirsher lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo; 1263b955f6caSJeff Kirsher lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr; 1264b955f6caSJeff Kirsher /* lp->linux_stats.tx_window_errors; */ 1265b955f6caSJeff Kirsher } /* update_stats */ 1266b955f6caSJeff Kirsher 1267b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1268b955f6caSJeff Kirsher mace_get_stats 1269b955f6caSJeff Kirsher Gathers ethernet statistics from the MACE chip. 1270b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1271b955f6caSJeff Kirsher static struct net_device_stats *mace_get_stats(struct net_device *dev) 1272b955f6caSJeff Kirsher { 1273b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1274b955f6caSJeff Kirsher 1275b955f6caSJeff Kirsher update_stats(dev->base_addr, dev); 1276b955f6caSJeff Kirsher 1277b955f6caSJeff Kirsher pr_debug("%s: updating the statistics.\n", dev->name); 1278b955f6caSJeff Kirsher pr_linux_stats(&lp->linux_stats); 1279b955f6caSJeff Kirsher pr_mace_stats(&lp->mace_stats); 1280b955f6caSJeff Kirsher 1281b955f6caSJeff Kirsher return &lp->linux_stats; 1282b955f6caSJeff Kirsher } /* net_device_stats */ 1283b955f6caSJeff Kirsher 1284b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1285b955f6caSJeff Kirsher updateCRC 1286b955f6caSJeff Kirsher Modified from Am79C90 data sheet. 1287b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1288b955f6caSJeff Kirsher 1289b955f6caSJeff Kirsher #ifdef BROKEN_MULTICAST 1290b955f6caSJeff Kirsher 1291b955f6caSJeff Kirsher static void updateCRC(int *CRC, int bit) 1292b955f6caSJeff Kirsher { 1293b955f6caSJeff Kirsher static const int poly[]={ 1294b955f6caSJeff Kirsher 1,1,1,0, 1,1,0,1, 1295b955f6caSJeff Kirsher 1,0,1,1, 1,0,0,0, 1296b955f6caSJeff Kirsher 1,0,0,0, 0,0,1,1, 1297b955f6caSJeff Kirsher 0,0,1,0, 0,0,0,0 1298b955f6caSJeff Kirsher }; /* CRC polynomial. poly[n] = coefficient of the x**n term of the 1299b955f6caSJeff Kirsher CRC generator polynomial. */ 1300b955f6caSJeff Kirsher 1301b955f6caSJeff Kirsher int j; 1302b955f6caSJeff Kirsher 1303b955f6caSJeff Kirsher /* shift CRC and control bit (CRC[32]) */ 1304b955f6caSJeff Kirsher for (j = 32; j > 0; j--) 1305b955f6caSJeff Kirsher CRC[j] = CRC[j-1]; 1306b955f6caSJeff Kirsher CRC[0] = 0; 1307b955f6caSJeff Kirsher 1308b955f6caSJeff Kirsher /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */ 1309b955f6caSJeff Kirsher if (bit ^ CRC[32]) 1310b955f6caSJeff Kirsher for (j = 0; j < 32; j++) 1311b955f6caSJeff Kirsher CRC[j] ^= poly[j]; 1312b955f6caSJeff Kirsher } /* updateCRC */ 1313b955f6caSJeff Kirsher 1314b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1315b955f6caSJeff Kirsher BuildLAF 1316b955f6caSJeff Kirsher Build logical address filter. 1317b955f6caSJeff Kirsher Modified from Am79C90 data sheet. 1318b955f6caSJeff Kirsher 1319b955f6caSJeff Kirsher Input 1320b955f6caSJeff Kirsher ladrf: logical address filter (contents initialized to 0) 1321b955f6caSJeff Kirsher adr: ethernet address 1322b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1323b955f6caSJeff Kirsher static void BuildLAF(int *ladrf, int *adr) 1324b955f6caSJeff Kirsher { 1325b955f6caSJeff Kirsher int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */ 1326b955f6caSJeff Kirsher 1327b955f6caSJeff Kirsher int i, byte; /* temporary array indices */ 1328b955f6caSJeff Kirsher int hashcode; /* the output object */ 1329b955f6caSJeff Kirsher 1330b955f6caSJeff Kirsher CRC[32]=0; 1331b955f6caSJeff Kirsher 1332b955f6caSJeff Kirsher for (byte = 0; byte < 6; byte++) 1333b955f6caSJeff Kirsher for (i = 0; i < 8; i++) 1334b955f6caSJeff Kirsher updateCRC(CRC, (adr[byte] >> i) & 1); 1335b955f6caSJeff Kirsher 1336b955f6caSJeff Kirsher hashcode = 0; 1337b955f6caSJeff Kirsher for (i = 0; i < 6; i++) 1338b955f6caSJeff Kirsher hashcode = (hashcode << 1) + CRC[i]; 1339b955f6caSJeff Kirsher 1340b955f6caSJeff Kirsher byte = hashcode >> 3; 1341b955f6caSJeff Kirsher ladrf[byte] |= (1 << (hashcode & 7)); 1342b955f6caSJeff Kirsher 1343b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG 1344b955f6caSJeff Kirsher if (0) 1345b955f6caSJeff Kirsher printk(KERN_DEBUG " adr =%pM\n", adr); 1346b955f6caSJeff Kirsher printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode); 1347b955f6caSJeff Kirsher for (i = 0; i < 8; i++) 1348b955f6caSJeff Kirsher pr_cont(" %02X", ladrf[i]); 1349b955f6caSJeff Kirsher pr_cont("\n"); 1350b955f6caSJeff Kirsher #endif 1351b955f6caSJeff Kirsher } /* BuildLAF */ 1352b955f6caSJeff Kirsher 1353b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1354b955f6caSJeff Kirsher restore_multicast_list 1355b955f6caSJeff Kirsher Restores the multicast filter for MACE chip to the last 1356b955f6caSJeff Kirsher set_multicast_list() call. 1357b955f6caSJeff Kirsher 1358b955f6caSJeff Kirsher Input 1359b955f6caSJeff Kirsher multicast_num_addrs 1360b955f6caSJeff Kirsher multicast_ladrf[] 1361b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1362b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev) 1363b955f6caSJeff Kirsher { 1364b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1365b955f6caSJeff Kirsher int num_addrs = lp->multicast_num_addrs; 1366b955f6caSJeff Kirsher int *ladrf = lp->multicast_ladrf; 1367b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 1368b955f6caSJeff Kirsher int i; 1369b955f6caSJeff Kirsher 1370b955f6caSJeff Kirsher pr_debug("%s: restoring Rx mode to %d addresses.\n", 1371b955f6caSJeff Kirsher dev->name, num_addrs); 1372b955f6caSJeff Kirsher 1373b955f6caSJeff Kirsher if (num_addrs > 0) { 1374b955f6caSJeff Kirsher 1375b955f6caSJeff Kirsher pr_debug("Attempt to restore multicast list detected.\n"); 1376b955f6caSJeff Kirsher 1377b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR); 1378b955f6caSJeff Kirsher /* Poll ADDRCHG bit */ 1379b955f6caSJeff Kirsher while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) 1380b955f6caSJeff Kirsher ; 1381b955f6caSJeff Kirsher /* Set LADRF register */ 1382b955f6caSJeff Kirsher for (i = 0; i < MACE_LADRF_LEN; i++) 1383b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]); 1384b955f6caSJeff Kirsher 1385b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL); 1386b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); 1387b955f6caSJeff Kirsher 1388b955f6caSJeff Kirsher } else if (num_addrs < 0) { 1389b955f6caSJeff Kirsher 1390b955f6caSJeff Kirsher /* Promiscuous mode: receive all packets */ 1391b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); 1392b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, 1393b955f6caSJeff Kirsher MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV 1394b955f6caSJeff Kirsher ); 1395b955f6caSJeff Kirsher 1396b955f6caSJeff Kirsher } else { 1397b955f6caSJeff Kirsher 1398b955f6caSJeff Kirsher /* Normal mode */ 1399b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); 1400b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); 1401b955f6caSJeff Kirsher 1402b955f6caSJeff Kirsher } 1403b955f6caSJeff Kirsher } /* restore_multicast_list */ 1404b955f6caSJeff Kirsher 1405b955f6caSJeff Kirsher /* ---------------------------------------------------------------------------- 1406b955f6caSJeff Kirsher set_multicast_list 1407b955f6caSJeff Kirsher Set or clear the multicast filter for this adaptor. 1408b955f6caSJeff Kirsher 1409b955f6caSJeff Kirsher Input 1410b955f6caSJeff Kirsher num_addrs == -1 Promiscuous mode, receive all packets 1411b955f6caSJeff Kirsher num_addrs == 0 Normal mode, clear multicast list 1412b955f6caSJeff Kirsher num_addrs > 0 Multicast mode, receive normal and MC packets, and do 1413b955f6caSJeff Kirsher best-effort filtering. 1414b955f6caSJeff Kirsher Output 1415b955f6caSJeff Kirsher multicast_num_addrs 1416b955f6caSJeff Kirsher multicast_ladrf[] 1417b955f6caSJeff Kirsher ---------------------------------------------------------------------------- */ 1418b955f6caSJeff Kirsher 1419b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev) 1420b955f6caSJeff Kirsher { 1421b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1422104bf3fbSJoe Perches int adr[ETH_ALEN] = {0}; /* Ethernet address */ 1423b955f6caSJeff Kirsher struct netdev_hw_addr *ha; 1424b955f6caSJeff Kirsher 1425b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG 1426b955f6caSJeff Kirsher { 1427b955f6caSJeff Kirsher static int old; 1428b955f6caSJeff Kirsher if (netdev_mc_count(dev) != old) { 1429b955f6caSJeff Kirsher old = netdev_mc_count(dev); 1430b955f6caSJeff Kirsher pr_debug("%s: setting Rx mode to %d addresses.\n", 1431b955f6caSJeff Kirsher dev->name, old); 1432b955f6caSJeff Kirsher } 1433b955f6caSJeff Kirsher } 1434b955f6caSJeff Kirsher #endif 1435b955f6caSJeff Kirsher 1436b955f6caSJeff Kirsher /* Set multicast_num_addrs. */ 1437b955f6caSJeff Kirsher lp->multicast_num_addrs = netdev_mc_count(dev); 1438b955f6caSJeff Kirsher 1439b955f6caSJeff Kirsher /* Set multicast_ladrf. */ 1440b955f6caSJeff Kirsher if (num_addrs > 0) { 1441b955f6caSJeff Kirsher /* Calculate multicast logical address filter */ 1442b955f6caSJeff Kirsher memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); 1443b955f6caSJeff Kirsher netdev_for_each_mc_addr(ha, dev) { 1444104bf3fbSJoe Perches memcpy(adr, ha->addr, ETH_ALEN); 1445b955f6caSJeff Kirsher BuildLAF(lp->multicast_ladrf, adr); 1446b955f6caSJeff Kirsher } 1447b955f6caSJeff Kirsher } 1448b955f6caSJeff Kirsher 1449b955f6caSJeff Kirsher restore_multicast_list(dev); 1450b955f6caSJeff Kirsher 1451b955f6caSJeff Kirsher } /* set_multicast_list */ 1452b955f6caSJeff Kirsher 1453b955f6caSJeff Kirsher #endif /* BROKEN_MULTICAST */ 1454b955f6caSJeff Kirsher 1455b955f6caSJeff Kirsher static void restore_multicast_list(struct net_device *dev) 1456b955f6caSJeff Kirsher { 1457b955f6caSJeff Kirsher unsigned int ioaddr = dev->base_addr; 1458b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1459b955f6caSJeff Kirsher 1460b955f6caSJeff Kirsher pr_debug("%s: restoring Rx mode to %d addresses.\n", dev->name, 1461b955f6caSJeff Kirsher lp->multicast_num_addrs); 1462b955f6caSJeff Kirsher 1463b955f6caSJeff Kirsher if (dev->flags & IFF_PROMISC) { 1464b955f6caSJeff Kirsher /* Promiscuous mode: receive all packets */ 1465b955f6caSJeff Kirsher mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); 1466b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, 1467b955f6caSJeff Kirsher MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV 1468b955f6caSJeff Kirsher ); 1469b955f6caSJeff Kirsher } else { 1470b955f6caSJeff Kirsher /* Normal mode */ 1471b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); 1472b955f6caSJeff Kirsher mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); 1473b955f6caSJeff Kirsher } 1474b955f6caSJeff Kirsher } /* restore_multicast_list */ 1475b955f6caSJeff Kirsher 1476b955f6caSJeff Kirsher static void set_multicast_list(struct net_device *dev) 1477b955f6caSJeff Kirsher { 1478b955f6caSJeff Kirsher mace_private *lp = netdev_priv(dev); 1479b955f6caSJeff Kirsher 1480b955f6caSJeff Kirsher #ifdef PCMCIA_DEBUG 1481b955f6caSJeff Kirsher { 1482b955f6caSJeff Kirsher static int old; 1483b955f6caSJeff Kirsher if (netdev_mc_count(dev) != old) { 1484b955f6caSJeff Kirsher old = netdev_mc_count(dev); 1485b955f6caSJeff Kirsher pr_debug("%s: setting Rx mode to %d addresses.\n", 1486b955f6caSJeff Kirsher dev->name, old); 1487b955f6caSJeff Kirsher } 1488b955f6caSJeff Kirsher } 1489b955f6caSJeff Kirsher #endif 1490b955f6caSJeff Kirsher 1491b955f6caSJeff Kirsher lp->multicast_num_addrs = netdev_mc_count(dev); 1492b955f6caSJeff Kirsher restore_multicast_list(dev); 1493b955f6caSJeff Kirsher 1494b955f6caSJeff Kirsher } /* set_multicast_list */ 1495b955f6caSJeff Kirsher 1496b955f6caSJeff Kirsher static const struct pcmcia_device_id nmclan_ids[] = { 1497b955f6caSJeff Kirsher PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), 1498b955f6caSJeff Kirsher PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf), 1499b955f6caSJeff Kirsher PCMCIA_DEVICE_NULL, 1500b955f6caSJeff Kirsher }; 1501b955f6caSJeff Kirsher MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); 1502b955f6caSJeff Kirsher 1503b955f6caSJeff Kirsher static struct pcmcia_driver nmclan_cs_driver = { 1504b955f6caSJeff Kirsher .owner = THIS_MODULE, 1505b955f6caSJeff Kirsher .name = "nmclan_cs", 1506b955f6caSJeff Kirsher .probe = nmclan_probe, 1507b955f6caSJeff Kirsher .remove = nmclan_detach, 1508b955f6caSJeff Kirsher .id_table = nmclan_ids, 1509b955f6caSJeff Kirsher .suspend = nmclan_suspend, 1510b955f6caSJeff Kirsher .resume = nmclan_resume, 1511b955f6caSJeff Kirsher }; 1512fdd3f29eSH Hartley Sweeten module_pcmcia_driver(nmclan_cs_driver); 1513