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