176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* sundance.c -- Etherboot device driver for the Sundance ST201 "Alta". 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Written 2002-2002 by Timothy Legge <tlegge@rogers.com> 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* This program is free software; you can redistribute it and/or modify 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* it under the terms of the GNU General Public License as published by 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* the Free Software Foundation; either version 2 of the License, or 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* (at your option) any later version. 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* This program is distributed in the hope that it will be useful, 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* but WITHOUT ANY WARRANTY; without even the implied warranty of 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* GNU General Public License for more details. 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* You should have received a copy of the GNU General Public License 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* along with this program; if not, write to the Free Software 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Portions of this code based on: 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* sundance.c: A Linux device driver for the Sundance ST201 "Alta" 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Written 1999-2002 by Donald Becker 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* tulip.c: Tulip and Clone Etherboot Driver 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* By Marty Conner 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Copyright (C) 2001 Entity Cyber, Inc. 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Linux Driver Version LK1.09a, 10-Jul-2003 (2.4.25) 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* REVISION HISTORY: 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* ================ 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.1 01-01-2003 timlegge Initial implementation 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.7 04-10-2003 timlegge Transfers Linux Kernel (30 sec) 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.8 04-13-2003 timlegge Fix multiple transmission bug 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.9 08-19-2003 timlegge Support Multicast 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.10 01-17-2004 timlegge Initial driver output cleanup 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.11 03-21-2004 timlegge Remove unused variables 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.12 03-21-2004 timlegge Remove excess MII defines 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* v1.13 03-24-2004 timlegge Update to Linux 2.4.25 driver 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman****************************************************************************/ 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get some global routines like printf */ 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "etherboot.h" 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get the interface to the body of the program */ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "nic.h" 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get the PCI support functions, if this is a PCI NIC */ 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/pci.h> 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "mii.h" 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define drv_version "v1.12" 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define drv_date "2004-03-21" 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HZ 100 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Condensed operations for readability. */ 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Set the mtu */ 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mtu = 1514; 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Maximum number of multicast addresses to filter (vs. rx-all-multicast). 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman The sundance uses a 64 element hash table based on the Ethernet CRC. */ 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// static int multicast_filter_limit = 32; 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Set the copy breakpoint for the copy-only-tiny-frames scheme. 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Setting to > 1518 effectively disables this feature. 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman This chip can receive into any byte alignment buffers, so word-oriented 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman archs do not need a copy-align of the IP header. */ 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int rx_copybreak = 0; 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int flowctrl = 1; 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Allow forcing the media type */ 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* media[] specifies the media type the NIC operates at. 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman autosense Autosensing active media. 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10mbps_hd 10Mbps half duplex. 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10mbps_fd 10Mbps full duplex. 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 100mbps_hd 100Mbps half duplex. 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 100mbps_fd 100Mbps full duplex. 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic char media[] = "autosense"; 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Operational parameters that are set at compile time. */ 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* As Etherboot uses a Polling driver we can keep the number of rings 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanto the minimum number required. In general that is 1 transmit and 4 receive receive rings. However some cards require that 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanthere be a minimum of 2 rings */ 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_RING_SIZE 2 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define RX_RING_SIZE 4 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Operational parameters that usually are not changed. */ 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Time in jiffies before concluding the transmitter is hung. */ 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_TIME_OUT (4*HZ) 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PKT_BUF_SZ 1536 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Offsets to the device registers. 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Unlike software-only systems, device drivers interact with complex hardware. 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman It's not useful to define symbolic names for every register bit in the 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman device. The name can only partially document the semantics and make 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman the driver longer and more difficult to read. 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman In general, only the important configuration values or bits changed 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman multiple times should be defined symbolically. 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum alta_offsets { 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DMACtrl = 0x00, 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxListPtr = 0x04, 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxDMABurstThresh = 0x08, 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxDMAUrgentThresh = 0x09, 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxDMAPollPeriod = 0x0a, 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxDMAStatus = 0x0c, 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxListPtr = 0x10, 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DebugCtrl0 = 0x1a, 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DebugCtrl1 = 0x1c, 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxDMABurstThresh = 0x14, 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxDMAUrgentThresh = 0x15, 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxDMAPollPeriod = 0x16, 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LEDCtrl = 0x1a, 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ASICCtrl = 0x30, 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EEData = 0x34, 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EECtrl = 0x36, 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxStartThresh = 0x3c, 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxEarlyThresh = 0x3e, 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FlashAddr = 0x40, 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FlashData = 0x44, 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxStatus = 0x46, 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxFrameId = 0x47, 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DownCounter = 0x18, 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrClear = 0x4a, 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrEnable = 0x4c, 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrStatus = 0x4e, 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MACCtrl0 = 0x50, 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MACCtrl1 = 0x52, 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StationAddr = 0x54, 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MaxFrameSize = 0x5A, 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxMode = 0x5c, 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MIICtrl = 0x5e, 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MulticastFilter0 = 0x60, 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MulticastFilter1 = 0x64, 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxOctetsLow = 0x68, 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxOctetsHigh = 0x6a, 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxOctetsLow = 0x6c, 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxOctetsHigh = 0x6e, 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxFramesOK = 0x70, 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxFramesOK = 0x72, 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsCarrierError = 0x74, 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsLateColl = 0x75, 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsMultiColl = 0x76, 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsOneColl = 0x77, 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsTxDefer = 0x78, 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxMissed = 0x79, 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsTxXSDefer = 0x7a, 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsTxAbort = 0x7b, 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsBcastTx = 0x7c, 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsBcastRx = 0x7d, 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsMcastTx = 0x7e, 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsMcastRx = 0x7f, 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Aliased and bogus values! */ 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxStatus = 0x0c, 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum ASICCtrl_HiWord_bit { 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GlobalReset = 0x0001, 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxReset = 0x0002, 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxReset = 0x0004, 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DMAReset = 0x0008, 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FIFOReset = 0x0010, 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NetworkReset = 0x0020, 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman HostReset = 0x0040, 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ResetBusy = 0x0400, 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in the interrupt status/mask registers. */ 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum intr_status_bits { 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008, 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020, 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrDrvRqst = 0x0040, 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsMax = 0x0080, LinkChange = 0x0100, 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400, 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in the RxMode register. */ 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum rx_mode_bits { 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08, 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys = 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 0x01, 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in MACCtrl. */ 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum mac_ctrl0_bits { 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40, 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200, 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum mac_ctrl1_bits { 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080, 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400, 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000, 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The Rx and Tx buffer descriptors. 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Using only 32 bit fields simplifies software endian correction. 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman This structure must be aligned, and should avoid spanning cache lines. 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct netdev_desc { 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 next_desc; 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status; 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 addr; 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 length; 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in netdev_desc.status */ 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum desc_status_bits { 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DescOwn = 0x8000, 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DescEndPacket = 0x4000, 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DescEndRing = 0x2000, 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LastFrag = 0x80000000, 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DescIntrOnTx = 0x8000, 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DescIntrOnDMADone = 0x80000000, 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DisableAlign = 0x00000001, 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/********************************************** 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman* Descriptor Ring and Buffer defination 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***********************************************/ 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Define the TX Descriptor */ 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct netdev_desc tx_ring[TX_RING_SIZE]; 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Define the RX Descriptor */ 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct netdev_desc rx_ring[RX_RING_SIZE]; 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor. 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman All descriptors point to a part of this buffer */ 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct { 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE]; 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ]; 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} rx_tx_buf __shared; 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rxb rx_tx_buf.rxb 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define txb rx_tx_buf.txb 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* FIXME: Move BASE to the private structure */ 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u32 BASE; 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EEPROM_SIZE 128 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum pci_id_flags_bits { 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4, 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 = 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2 << 4, PCI_ADDR3 = 3 << 4, 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, }; 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0) 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MII_CNT 4 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct sundance_private { 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *nic_name; 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Frequently used values */ 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int cur_rx; /* Producer/consumer ring indicies */ 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int mtu; 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* These values keep track of the tranceiver/media in use */ 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int flowctrl:1; 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int an_enable:1; 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int speed; 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* MII tranceiver section */ 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct mii_if_info mii_if; 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_preamble_required; 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char phys[MII_CNT]; 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char pci_rev_id; 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} sdx; 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct sundance_private *sdc; 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Station Address location within the EEPROM */ 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EEPROM_SA_OFFSET 0x10 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \ 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman IntrDrvRqst | IntrTxDone | StatsMax | \ 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LinkChange) 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int eeprom_read(long ioaddr, int location); 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mdio_read(struct nic *nic, int phy_id, unsigned int location); 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mdio_write(struct nic *nic, int phy_id, unsigned int location, 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int value); 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void set_rx_mode(struct nic *nic); 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void check_duplex(struct nic *nic) 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA); 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int negotiated = mii_lpa & sdc->mii_if.advertising; 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int duplex; 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Force media */ 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!sdc->an_enable || mii_lpa == 0xffff) { 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mii_if.full_duplex) 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(inw(BASE + MACCtrl0) | EnbFullDuplex, 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BASE + MACCtrl0); 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Autonegotiation */ 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mii_if.full_duplex != duplex) { 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = duplex; 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ("%s: Setting %s-duplex based on MII #%d " 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "negotiated capability %4.4x.\n", sdc->nic_name, 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman duplex ? "full" : "half", sdc->phys[0], 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman negotiated ); 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0, 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BASE + MACCtrl0); 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * init_ring - setup the tx and rx descriptors 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *************************************************************************/ 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void init_ring(struct nic *nic __unused) 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->cur_rx = 0; 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Initialize all the Rx descriptors */ 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < RX_RING_SIZE; i++) { 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]); 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].status = 0; 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].length = 0; 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].addr = 0; 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Mark the last entry as wrapping the ring */ 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]); 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < RX_RING_SIZE; i++) { 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]); 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag); 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* We only use one transmit buffer, but two 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * descriptors so transmit engines have somewhere 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to point should they feel the need */ 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[0].status = 0x00000000; 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[0].addr = virt_to_bus(&txb[0]); 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[0].next_desc = 0; /* virt_to_bus(&tx_ring[1]); */ 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* This descriptor is never used */ 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[1].status = 0x00000000; 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[1].addr = 0; /*virt_to_bus(&txb[0]); */ 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[1].next_desc = 0; 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Mark the last entry as wrapping the ring, 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * though this should never happen */ 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ); 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * RESET - Reset Adapter 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ***********************************************************************/ 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sundance_reset(struct nic *nic) 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman init_ring(nic); 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr); 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* The Tx List Pointer is written as packets are queued */ 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Initialize other registers. */ 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* __set_mac_addr(dev); */ 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 addr16; 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8)); 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(addr16, BASE + StationAddr); 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8)); 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(addr16, BASE + StationAddr + 2); 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8)); 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(addr16, BASE + StationAddr + 4); 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(sdc->mtu + 14, BASE + MaxFrameSize); 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mtu > 2047) /* this will never happen with default options */ 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl); 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman set_rx_mode(nic); 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0, BASE + DownCounter); 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Set the chip to poll every N*30nsec */ 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(100, BASE + RxDMAPollPeriod); 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Fix DFE-580TX packet drop issue */ 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->pci_rev_id >= 0x14) 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman writeb(0x01, BASE + DebugCtrl1); 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(RxEnable | TxEnable, BASE + MACCtrl1); 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Construct a perfect filter frame with the mac address as first match 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and broadcast for all others */ 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 192; i++) 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[i] = 0xFF; 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[0] = nic->node_addr[0]; 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[1] = nic->node_addr[1]; 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[2] = nic->node_addr[2]; 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[3] = nic->node_addr[3]; 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[4] = nic->node_addr[4]; 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[5] = nic->node_addr[5]; 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX " 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "MAC Control %hX, %hX %hX\n", 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->nic_name, (int) inl(BASE + RxStatus), 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0), 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) ); 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 42176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanIRQ - Wait for a frame 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/ 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sundance_irq ( struct nic *nic, irq_action_t action ) { 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int intr_status; 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch ( action ) { 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DISABLE : 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case ENABLE : 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman intr_status = inw(nic->ioaddr + IntrStatus); 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman intr_status = intr_status & ~DEFAULT_INTR; 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( action == ENABLE ) 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman intr_status = intr_status | DEFAULT_INTR; 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(intr_status, nic->ioaddr + IntrEnable); 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case FORCE : 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0x0200, BASE + ASICCtrl); 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 44176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPOLL - Wait for a frame 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/ 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sundance_poll(struct nic *nic, int retreive) 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* return true if there's an ethernet packet ready to read */ 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* nic->packet should contain data on return */ 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* nic->packetlen should contain length of data */ 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int entry = sdc->cur_rx % RX_RING_SIZE; 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 frame_status = le32_to_cpu(rx_ring[entry].status); 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int intr_status; 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int pkt_len = 0; 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(frame_status & DescOwn)) 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* There is a packet ready */ 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if(!retreive) 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman intr_status = inw(nic->ioaddr + IntrStatus); 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(intr_status, nic->ioaddr + IntrStatus); 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pkt_len = frame_status & 0x1fff; 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (frame_status & 0x001f4000) { 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Polling frame_status error\n" ); /* Do we really care about this */ 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pkt_len < rx_copybreak) { 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* FIXME: What should happen Will this ever occur */ 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Poll Error: pkt_len < rx_copybreak"); 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->packetlen = pkt_len; 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(nic->packet, rxb + 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen); 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag); 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_ring[entry].status = 0; 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry++; 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->cur_rx = entry % RX_RING_SIZE; 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->ioaddr + IntrStatus); 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 48876d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanTRANSMIT - Transmit a frame 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/ 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sundance_transmit(struct nic *nic, const char *d, /* Destination */ 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int t, /* Type */ 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int s, /* size */ 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *p) 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ /* Packet */ 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 nstype; 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 to; 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Disable the Tx */ 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(TxDisable, BASE + MACCtrl1); 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb, d, ETH_ALEN); 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nstype = htons((u16) t); 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2); 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + ETH_HLEN, p, s); 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s += ETH_HLEN; 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s &= 0x0FFF; 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (s < ETH_ZLEN) 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[s++] = '\0'; 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Setup the transmit descriptor */ 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[0].length = cpu_to_le32(s | LastFrag); 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_ring[0].status = cpu_to_le32(0x00000001); 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Point to transmit descriptor */ 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr); 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Enable Tx */ 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(TxEnable, BASE + MACCtrl1); 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Trigger an immediate send */ 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0, BASE + TxStatus); 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to = currticks() + TX_TIME_OUT; 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!(tx_ring[0].status & 0x00010000) && (currticks() < to)); /* wait */ 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (currticks() >= to) { 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("TX Time Out"); 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Disable Tx */ 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(TxDisable, BASE + MACCtrl1); 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 53676d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanDISABLE - Turn off ethernet interface 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/ 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sundance_disable ( struct nic *nic __unused ) { 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* put the card in its initial state */ 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* This function serves 3 purposes. 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This disables DMA and interrupts so we don't receive 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * unexpected packets or interrupts from the card after 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * etherboot has finished. 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This frees resources so etherboot may use 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * this driver on another interface 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This allows etherboot to reinitialize the interface 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * if something is something goes wrong. 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0x0000, BASE + IntrEnable); 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Stop the Chipchips Tx and Rx Status */ 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1); 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct nic_operations sundance_operations = { 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .connect = dummy_connect, 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .poll = sundance_poll, 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .transmit = sundance_transmit, 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .irq = sundance_irq, 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/************************************************************************** 56376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPROBE - Look for an adapter, this routine's visible to the outside 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/ 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sundance_probe ( struct nic *nic, struct pci_device *pci ) { 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 ee_data[EEPROM_SIZE]; 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 mii_ctl; 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int speed; 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pci->ioaddr == 0) 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* BASE is used throughout to address the card */ 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BASE = pci->ioaddr; 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n", 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci->driver_name, pci->vendor, pci->device); 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Get the MAC Address by reading the EEPROM */ 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 3; i++) { 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((u16 *) ee_data)[i] = 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET)); 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Update the nic structure with the MAC Address */ 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < ETH_ALEN; i++) { 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->node_addr[i] = ee_data[i]; 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Set the card as PCI Bus Master */ 59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman adjust_pci_device(pci); 59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// sdc->mii_if.dev = pci; 59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// sdc->mii_if.phy_id_mask = 0x1f; 59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// sdc->mii_if.reg_num_mask = 0x1f; 59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* point to private storage */ 59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc = &sdx; 59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->nic_name = pci->driver_name; 60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mtu = mtu; 60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_read_config_byte(pci, PCI_REVISION_ID, &sdc->pci_rev_id); 60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Device revision id: %hx\n", sdc->pci_rev_id ); 60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Print out some hardware info */ 60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "%s: %s at ioaddr %hX, ", pci->driver_name, nic->node_addr, (unsigned int) BASE); 60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_preamble_required = 0; 61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (1) { 61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int phy, phy_idx = 0; 61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->phys[0] = 1; /* Default Setting */ 61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_preamble_required++; 61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) { 61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_status = mdio_read(nic, phy, MII_BMSR); 61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (mii_status != 0xffff && mii_status != 0x0000) { 61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->phys[phy_idx++] = phy; 61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.advertising = 62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_read(nic, phy, MII_ADVERTISE); 62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((mii_status & 0x0040) == 0) 62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_preamble_required++; 62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG 62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising ); 62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_preamble_required--; 62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (phy_idx == 0) 62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("%s: No MII transceiver found!\n", 63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->nic_name); 63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.phy_id = sdc->phys[0]; 63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Parse override configuration */ 63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->an_enable = 1; 63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (strcasecmp(media, "autosense") != 0) { 63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->an_enable = 0; 63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (strcasecmp(media, "100mbps_fd") == 0 || 63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman strcasecmp(media, "4") == 0) { 64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 100; 64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = 1; 64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (strcasecmp(media, "100mbps_hd") == 0 64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || strcasecmp(media, "3") == 0) { 64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 100; 64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = 0; 64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (strcasecmp(media, "10mbps_fd") == 0 || 64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman strcasecmp(media, "2") == 0) { 64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 10; 64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = 1; 65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (strcasecmp(media, "10mbps_hd") == 0 || 65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman strcasecmp(media, "1") == 0) { 65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 10; 65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = 0; 65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->an_enable = 1; 65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (flowctrl == 1) 65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->flowctrl = 1; 66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Fibre PHY? */ 66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (inl(BASE + ASICCtrl) & 0x80) { 66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Default 100Mbps Full */ 66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->an_enable) { 66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 100; 66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex = 1; 66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->an_enable = 0; 66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* The Linux driver uses flow control and resets the link here. This means the 67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii section from above would need to be re done I believe. Since it serves 67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman no real purpose leave it out. */ 67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Force media type */ 67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!sdc->an_enable) { 67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_ctl = 0; 67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0; 67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0; 68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl); 68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Override speed=%d, %s duplex\n", 68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed, 68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex ? "Full" : "Half"); 68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Reset the chip to erase previous misconfiguration */ 68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) ); 68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0x007f, BASE + ASICCtrl + 2); 68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * wait for reset to complete 69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * this is heavily inspired by the linux sundance driver 69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * according to the linux driver it can take up to 1ms for the reset 69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to complete 69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i = 0; 69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) { 69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if(i++ >= 10) { 69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG("sundance: NIC reset did not complete.\n"); 70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman udelay(100); 70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) ); 70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sundance_reset(nic); 70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->an_enable) { 70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 mii_advertise, mii_lpa; 71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_advertise = 71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_read(nic, sdc->phys[0], MII_ADVERTISE); 71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA); 71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_advertise &= mii_lpa; 71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (mii_advertise & ADVERTISE_100FULL) 71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 100; 71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (mii_advertise & ADVERTISE_100HALF) 71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 100; 71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (mii_advertise & ADVERTISE_10FULL) 71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 10; 72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (mii_advertise & ADVERTISE_10HALF) 72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = 10; 72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR); 72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; 72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->speed = speed; 72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed); 72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ? 72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman check_duplex(nic); 73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->flowctrl && sdc->mii_if.full_duplex) { 73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(inw(BASE + MulticastFilter1 + 2) | 0x0200, 73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BASE + MulticastFilter1 + 2); 73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0); 73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("%dMbps, %s-Duplex\n", sdc->speed, 73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sdc->mii_if.full_duplex ? "Full" : "Half"); 73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* point to NIC specific routines */ 74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->nic_op = &sundance_operations; 74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->irqno = pci->irq; 74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->ioaddr = BASE; 74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */ 75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int eeprom_read(long ioaddr, int location) 75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int boguscnt = 10000; /* Typical 1900 ticks */ 75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(0x0200 | (location & 0xff), ioaddr + EECtrl); 75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman do { 75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(inw(ioaddr + EECtrl) & 0x8000)) { 75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return inw(ioaddr + EEData); 75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (--boguscnt > 0); 76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* MII transceiver control section. 76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Read and write the MII registers using software-generated serial 76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MDIO protocol. See the MII specifications or DP83840A data sheet 76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for details. 76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman The maximum data clock rate is 2.5 Mhz. 76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman The timing is decoupled from the processor clock by flushing the write 77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman from the CPU write buffer with a following read, and using PCI 77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman transaction time. */ 77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define mdio_in(mdio_addr) inb(mdio_addr) 77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define mdio_out(value, mdio_addr) outb(value, mdio_addr) 77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define mdio_delay(mdio_addr) inb(mdio_addr) 77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum mii_reg_bits { 77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput = 77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 0x0004, 78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MDIO_EnbIn (0) 78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MDIO_WRITE0 (MDIO_EnbOutput) 78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput) 78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Generate the preamble required for initial synchronization and 78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman a few older transceivers. */ 78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mdio_sync(long mdio_addr) 78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int bits = 32; 79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Establish sync by sending at least 32 logic ones. */ 79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (--bits >= 0) { 79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_WRITE1, mdio_addr); 79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); 79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int 80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanmdio_read(struct nic *nic __unused, int phy_id, unsigned int location) 80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long mdio_addr = BASE + MIICtrl; 80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; 80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i, retval = 0; 80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mii_preamble_required) 80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_sync(mdio_addr); 80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Shift the read command bits out. */ 81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 15; i >= 0; i--) { 81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dataval = 81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; 81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(dataval, mdio_addr); 81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(dataval | MDIO_ShiftClk, mdio_addr); 81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Read the two transition, 16 data, and wire-idle bits. */ 82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 19; i > 0; i--) { 82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_EnbIn, mdio_addr); 82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data) 82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ? 1 : 0); 82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); 82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (retval >> 1) & 0xffff; 83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanmdio_write(struct nic *nic __unused, int phy_id, 83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int location, int value) 83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long mdio_addr = BASE + MIICtrl; 83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_cmd = 83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; 83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mii_preamble_required) 84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_sync(mdio_addr); 84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Shift the command bits out. */ 84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 31; i >= 0; i--) { 84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dataval = 84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; 84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(dataval, mdio_addr); 84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(dataval | MDIO_ShiftClk, mdio_addr); 85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear out extra bits. */ 85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 2; i > 0; i--) { 85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_EnbIn, mdio_addr); 85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); 85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mdio_delay(mdio_addr); 85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void set_rx_mode(struct nic *nic __unused) 86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 mc_filter[4]; /* Multicast hash filter */ 86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 rx_mode; 86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(mc_filter, 0xff, sizeof(mc_filter)); 87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; 87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sdc->mii_if.full_duplex && sdc->flowctrl) 87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mc_filter[3] |= 0x0200; 87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 4; i++) 87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outw(mc_filter[i], BASE + MulticastFilter0 + i * 2); 87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(rx_mode, BASE + RxMode); 87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct pci_device_id sundance_nics[] = { 88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0), 88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0), 88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0), 88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88676d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS ); 88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88876d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanDRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver, 88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sundance_probe, sundance_disable ); 89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Local variables: 89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * c-basic-offset: 8 89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * c-indent-level: 8 89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * tab-width: 8 89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * End: 89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 898