17c478bd9Sstevel@tonic-gate #define EB51
27c478bd9Sstevel@tonic-gate 
37c478bd9Sstevel@tonic-gate #ifdef EB50
47c478bd9Sstevel@tonic-gate #define __unused __attribute__((unused))
57c478bd9Sstevel@tonic-gate #endif
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /**************************************************************************
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate *    tlan.c -- Etherboot device driver for the Texas Instruments ThunderLAN
107c478bd9Sstevel@tonic-gate *    Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate *    This program is free software; you can redistribute it and/or modify
137c478bd9Sstevel@tonic-gate *    it under the terms of the GNU General Public License as published by
147c478bd9Sstevel@tonic-gate *    the Free Software Foundation; either version 2 of the License, or
157c478bd9Sstevel@tonic-gate *    (at your option) any later version.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate *    This program is distributed in the hope that it will be useful,
187c478bd9Sstevel@tonic-gate *    but WITHOUT ANY WARRANTY; without even the implied warranty of
197c478bd9Sstevel@tonic-gate *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
207c478bd9Sstevel@tonic-gate *    GNU General Public License for more details.
217c478bd9Sstevel@tonic-gate *
227c478bd9Sstevel@tonic-gate *    You should have received a copy of the GNU General Public License
237c478bd9Sstevel@tonic-gate *    along with this program; if not, write to the Free Software
247c478bd9Sstevel@tonic-gate *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate *    Portions of this code based on:
277c478bd9Sstevel@tonic-gate *	lan.c: Linux ThunderLan Driver:
287c478bd9Sstevel@tonic-gate *
297c478bd9Sstevel@tonic-gate *	by James Banks
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate *  	(C) 1997-1998 Caldera, Inc.
327c478bd9Sstevel@tonic-gate *	(C) 1998 James Banks
337c478bd9Sstevel@tonic-gate *	(C) 1999-2001 Torben Mathiasen
347c478bd9Sstevel@tonic-gate *	(C) 2002 Samuel Chessman
357c478bd9Sstevel@tonic-gate *
367c478bd9Sstevel@tonic-gate *    REVISION HISTORY:
377c478bd9Sstevel@tonic-gate *    ================
387c478bd9Sstevel@tonic-gate *    v1.0	07-08-2003	timlegge	Initial not quite working version
397c478bd9Sstevel@tonic-gate *    v1.1	07-27-2003	timlegge	Sync 5.0 and 5.1 versions
407c478bd9Sstevel@tonic-gate *    v1.2	08-19-2003	timlegge	Implement Multicast Support
417c478bd9Sstevel@tonic-gate *    v1.3	08-23-2003	timlegge	Fix the transmit Function
427c478bd9Sstevel@tonic-gate *    v1.4	01-17-2004	timlegge	Initial driver output cleanup
437c478bd9Sstevel@tonic-gate *
447c478bd9Sstevel@tonic-gate *    Indent Options: indent -kr -i8
457c478bd9Sstevel@tonic-gate ***************************************************************************/
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /* to get some global routines like printf */
487c478bd9Sstevel@tonic-gate #include "etherboot.h"
497c478bd9Sstevel@tonic-gate /* to get the interface to the body of the program */
507c478bd9Sstevel@tonic-gate #include "nic.h"
517c478bd9Sstevel@tonic-gate /* to get the PCI support functions, if this is a PCI NIC */
527c478bd9Sstevel@tonic-gate #include "pci.h"
537c478bd9Sstevel@tonic-gate #include "timer.h"
547c478bd9Sstevel@tonic-gate #include "tlan.h"
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define drv_version "v1.4"
577c478bd9Sstevel@tonic-gate #define drv_date "01-17-2004"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /* NIC specific static variables go here */
607c478bd9Sstevel@tonic-gate #define HZ 100
617c478bd9Sstevel@tonic-gate #define TX_TIME_OUT	  (6*HZ)
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #ifdef EB50
647c478bd9Sstevel@tonic-gate #define	cpu_to_le32(val) (val)
657c478bd9Sstevel@tonic-gate #define	le32_to_cpu(val) (val)
667c478bd9Sstevel@tonic-gate #define	virt_to_bus(x) ((unsigned long) x)
677c478bd9Sstevel@tonic-gate #define	bus_to_virt(x) ((unsigned long) x)
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /* Condensed operations for readability. */
717c478bd9Sstevel@tonic-gate #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
727c478bd9Sstevel@tonic-gate #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static void TLan_ResetLists(struct nic *nic __unused);
767c478bd9Sstevel@tonic-gate static void TLan_ResetAdapter(struct nic *nic __unused);
777c478bd9Sstevel@tonic-gate static void TLan_FinishReset(struct nic *nic __unused);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static void TLan_EeSendStart(u16);
807c478bd9Sstevel@tonic-gate static int TLan_EeSendByte(u16, u8, int);
817c478bd9Sstevel@tonic-gate static void TLan_EeReceiveByte(u16, u8 *, int);
827c478bd9Sstevel@tonic-gate static int TLan_EeReadByte(u16 io_base, u8, u8 *);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate static void TLan_PhyDetect(struct nic *nic);
857c478bd9Sstevel@tonic-gate static void TLan_PhyPowerDown(struct nic *nic);
867c478bd9Sstevel@tonic-gate static void TLan_PhyPowerUp(struct nic *nic);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static void TLan_SetMac(struct nic *nic __unused, int areg, char *mac);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate static void TLan_PhyReset(struct nic *nic);
927c478bd9Sstevel@tonic-gate static void TLan_PhyStartLink(struct nic *nic);
937c478bd9Sstevel@tonic-gate static void TLan_PhyFinishAutoNeg(struct nic *nic);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #ifdef MONITOR
967c478bd9Sstevel@tonic-gate static void TLan_PhyMonitor(struct nic *nic);
977c478bd9Sstevel@tonic-gate #endif
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate static void refill_rx(struct nic *nic __unused);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static int TLan_MiiReadReg(struct nic *nic __unused, u16, u16, u16 *);
1037c478bd9Sstevel@tonic-gate static void TLan_MiiSendData(u16, u32, unsigned);
1047c478bd9Sstevel@tonic-gate static void TLan_MiiSync(u16);
1057c478bd9Sstevel@tonic-gate static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate const char *media[] = {
1097c478bd9Sstevel@tonic-gate 	"10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ",
1107c478bd9Sstevel@tonic-gate 	"100baseTx-FD", "100baseT4", 0
1117c478bd9Sstevel@tonic-gate };
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate /* This much match tlan_pci_tbl[]!  */
1147c478bd9Sstevel@tonic-gate enum tlan_nics {
1157c478bd9Sstevel@tonic-gate 	NETEL10 = 0, NETEL100 = 1, NETFLEX3I = 2, THUNDER = 3, NETFLEX3B =
1167c478bd9Sstevel@tonic-gate 	    4, NETEL100PI = 5,
1177c478bd9Sstevel@tonic-gate 	NETEL100D = 6, NETEL100I = 7, OC2183 = 8, OC2325 = 9, OC2326 =
1187c478bd9Sstevel@tonic-gate 	    10, NETELLIGENT_10_100_WS_5100 = 11,
1197c478bd9Sstevel@tonic-gate 	NETELLIGENT_10_T2 = 12
1207c478bd9Sstevel@tonic-gate };
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate struct pci_id_info {
1237c478bd9Sstevel@tonic-gate 	const char *name;
1247c478bd9Sstevel@tonic-gate 	int nic_id;
1257c478bd9Sstevel@tonic-gate 	struct match_info {
1267c478bd9Sstevel@tonic-gate 		u32 pci, pci_mask, subsystem, subsystem_mask;
1277c478bd9Sstevel@tonic-gate 		u32 revision, revision_mask;	/* Only 8 bits. */
1287c478bd9Sstevel@tonic-gate 	} id;
1297c478bd9Sstevel@tonic-gate 	u32 flags;
1307c478bd9Sstevel@tonic-gate 	u16 addrOfs;		/* Address Offset */
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate static struct pci_id_info tlan_pci_tbl[] = {
1347c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent 10 T PCI UTP", NETEL10,
1357c478bd9Sstevel@tonic-gate 	 {0xae340e11, 0xffffffff, 0, 0, 0, 0},
1367c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},
1377c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent 10/100 TX PCI UTP", NETEL100,
1387c478bd9Sstevel@tonic-gate 	 {0xae320e11, 0xffffffff, 0, 0, 0, 0},
1397c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},
1407c478bd9Sstevel@tonic-gate 	{"Compaq Integrated NetFlex-3/P", NETFLEX3I,
1417c478bd9Sstevel@tonic-gate 	 {0xae350e11, 0xffffffff, 0, 0, 0, 0},
1427c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_NONE, 0x83},
1437c478bd9Sstevel@tonic-gate 	{"Compaq NetFlex-3/P", THUNDER,
1447c478bd9Sstevel@tonic-gate 	 {0xf1300e11, 0xffffffff, 0, 0, 0, 0},
1457c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
1467c478bd9Sstevel@tonic-gate 	{"Compaq NetFlex-3/P", NETFLEX3B,
1477c478bd9Sstevel@tonic-gate 	 {0xf1500e11, 0xffffffff, 0, 0, 0, 0},
1487c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_NONE, 0x83},
1497c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent Integrated 10/100 TX UTP", NETEL100PI,
1507c478bd9Sstevel@tonic-gate 	 {0xae430e11, 0xffffffff, 0, 0, 0, 0},
1517c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},
1527c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent Dual 10/100 TX PCI UTP", NETEL100D,
1537c478bd9Sstevel@tonic-gate 	 {0xae400e11, 0xffffffff, 0, 0, 0, 0},
1547c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_NONE, 0x83},
1557c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent 10/100 TX Embedded UTP", NETEL100I,
1567c478bd9Sstevel@tonic-gate 	 {0xb0110e11, 0xffffffff, 0, 0, 0, 0},
1577c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_NONE, 0x83},
1587c478bd9Sstevel@tonic-gate 	{"Olicom OC-2183/2185", OC2183,
1597c478bd9Sstevel@tonic-gate 	 {0x0013108d, 0xffffffff, 0, 0, 0, 0},
1607c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_USE_INTERN_10, 0x83},
1617c478bd9Sstevel@tonic-gate 	{"Olicom OC-2325", OC2325,
1627c478bd9Sstevel@tonic-gate 	 {0x0012108d, 0xffffffff, 0, 0, 0, 0},
1637c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_UNMANAGED_PHY, 0xF8},
1647c478bd9Sstevel@tonic-gate 	{"Olicom OC-2326", OC2326,
1657c478bd9Sstevel@tonic-gate 	 {0x0014108d, 0xffffffff, 0, 0, 0, 0},
1667c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_USE_INTERN_10, 0xF8},
1677c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent 10/100 TX UTP", NETELLIGENT_10_100_WS_5100,
1687c478bd9Sstevel@tonic-gate 	 {0xb0300e11, 0xffffffff, 0, 0, 0, 0},
1697c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},
1707c478bd9Sstevel@tonic-gate 	{"Compaq Netelligent 10 T/2 PCI UTP/Coax", NETELLIGENT_10_T2,
1717c478bd9Sstevel@tonic-gate 	 {0xb0120e11, 0xffffffff, 0, 0, 0, 0},
1727c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_NONE, 0x83},
1737c478bd9Sstevel@tonic-gate 	{"Compaq NetFlex-3/E", 0,	/* EISA card */
1747c478bd9Sstevel@tonic-gate 	 {0, 0, 0, 0, 0, 0},
1757c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED | TLAN_ADAPTER_UNMANAGED_PHY |
1767c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_BIT_RATE_PHY, 0x83},
1777c478bd9Sstevel@tonic-gate 	{"Compaq NetFlex-3/E", 0,	/* EISA card */
1787c478bd9Sstevel@tonic-gate 	 {0, 0, 0, 0, 0, 0},
1797c478bd9Sstevel@tonic-gate 	 TLAN_ADAPTER_ACTIVITY_LED, 0x83},
1807c478bd9Sstevel@tonic-gate 	{0, 0,
1817c478bd9Sstevel@tonic-gate 	 {0, 0, 0, 0, 0, 0},
1827c478bd9Sstevel@tonic-gate 	 0, 0},
1837c478bd9Sstevel@tonic-gate };
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate struct TLanList {
1877c478bd9Sstevel@tonic-gate 	u32 forward;
1887c478bd9Sstevel@tonic-gate 	u16 cStat;
1897c478bd9Sstevel@tonic-gate 	u16 frameSize;
1907c478bd9Sstevel@tonic-gate 	struct {
1917c478bd9Sstevel@tonic-gate 		u32 count;
1927c478bd9Sstevel@tonic-gate 		u32 address;
1937c478bd9Sstevel@tonic-gate 	} buffer[TLAN_BUFFERS_PER_LIST];
1947c478bd9Sstevel@tonic-gate };
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate struct TLanList tx_ring[TLAN_NUM_TX_LISTS];
1997c478bd9Sstevel@tonic-gate static unsigned char txb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_TX_LISTS];
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate struct TLanList rx_ring[TLAN_NUM_RX_LISTS];
2027c478bd9Sstevel@tonic-gate static unsigned char rxb[TLAN_MAX_FRAME_SIZE * TLAN_NUM_RX_LISTS];
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate int chip_idx;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /*****************************************************************
2117c478bd9Sstevel@tonic-gate * TLAN Private Information Structure
2127c478bd9Sstevel@tonic-gate *
2137c478bd9Sstevel@tonic-gate ****************************************************************/
2147c478bd9Sstevel@tonic-gate struct tlan_private {
2157c478bd9Sstevel@tonic-gate 	unsigned short vendor_id;	/* PCI Vendor code */
2167c478bd9Sstevel@tonic-gate 	unsigned short dev_id;	/* PCI Device code */
2177c478bd9Sstevel@tonic-gate 	const char *nic_name;
2187c478bd9Sstevel@tonic-gate 	u8 *padBuffer;
2197c478bd9Sstevel@tonic-gate 	u8 *rxBuffer;
2207c478bd9Sstevel@tonic-gate 	struct TLanList *rx_head_desc;
2217c478bd9Sstevel@tonic-gate 	u32 rxHead;
2227c478bd9Sstevel@tonic-gate 	u32 rxTail;
2237c478bd9Sstevel@tonic-gate 	u32 rxEocCount;
2247c478bd9Sstevel@tonic-gate 	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indicies */
2257c478bd9Sstevel@tonic-gate 	unsigned int cur_tx, dirty_tx;
2267c478bd9Sstevel@tonic-gate 	unsigned rx_buf_sz;	/* Based on mtu + Slack */
2277c478bd9Sstevel@tonic-gate 	struct TLanList *txList;
2287c478bd9Sstevel@tonic-gate 	struct TLanList *rxList;
2297c478bd9Sstevel@tonic-gate 	u8 *txBuffer;
2307c478bd9Sstevel@tonic-gate 	u32 txHead;
2317c478bd9Sstevel@tonic-gate 	u32 txInProgress;
2327c478bd9Sstevel@tonic-gate 	u32 txTail;
2337c478bd9Sstevel@tonic-gate 	int eoc;
2347c478bd9Sstevel@tonic-gate 	u32 txBusyCount;
2357c478bd9Sstevel@tonic-gate 	u32 phyOnline;
2367c478bd9Sstevel@tonic-gate 	u32 timerSetAt;
2377c478bd9Sstevel@tonic-gate 	u32 timerType;
2387c478bd9Sstevel@tonic-gate 	u32 adapterRev;
2397c478bd9Sstevel@tonic-gate 	u32 aui;
2407c478bd9Sstevel@tonic-gate 	u32 debug;
2417c478bd9Sstevel@tonic-gate 	u32 duplex;
2427c478bd9Sstevel@tonic-gate 	u32 phy[2];
2437c478bd9Sstevel@tonic-gate 	u32 phyNum;
2447c478bd9Sstevel@tonic-gate 	u32 speed;
2457c478bd9Sstevel@tonic-gate 	u8 tlanRev;
2467c478bd9Sstevel@tonic-gate 	u8 tlanFullDuplex;
2477c478bd9Sstevel@tonic-gate 	char devName[8];
2487c478bd9Sstevel@tonic-gate 	u8 link;
2497c478bd9Sstevel@tonic-gate 	u8 is_eisa;
2507c478bd9Sstevel@tonic-gate 	u8 neg_be_verbose;
2517c478bd9Sstevel@tonic-gate } TLanPrivateInfo;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate static struct tlan_private *priv;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate u32 BASE;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate /***************************************************************
2607c478bd9Sstevel@tonic-gate *	TLan_ResetLists
2617c478bd9Sstevel@tonic-gate *
2627c478bd9Sstevel@tonic-gate *	Returns:
2637c478bd9Sstevel@tonic-gate *		Nothing
2647c478bd9Sstevel@tonic-gate *	Parms:
2657c478bd9Sstevel@tonic-gate *		dev	The device structure with the list
2667c478bd9Sstevel@tonic-gate *			stuctures to be reset.
2677c478bd9Sstevel@tonic-gate *
2687c478bd9Sstevel@tonic-gate *	This routine sets the variables associated with managing
2697c478bd9Sstevel@tonic-gate *	the TLAN lists to their initial values.
2707c478bd9Sstevel@tonic-gate *
2717c478bd9Sstevel@tonic-gate **************************************************************/
2727c478bd9Sstevel@tonic-gate 
TLan_ResetLists(struct nic * nic __unused)2737c478bd9Sstevel@tonic-gate void TLan_ResetLists(struct nic *nic __unused)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	int i;
2777c478bd9Sstevel@tonic-gate 	struct TLanList *list;
2787c478bd9Sstevel@tonic-gate 	priv->txHead = 0;
2797c478bd9Sstevel@tonic-gate 	priv->txTail = 0;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
2827c478bd9Sstevel@tonic-gate 		list = &tx_ring[i];
2837c478bd9Sstevel@tonic-gate 		list->cStat = TLAN_CSTAT_UNUSED;
2847c478bd9Sstevel@tonic-gate /*		list->buffer[0].address = 0; */
2857c478bd9Sstevel@tonic-gate 		list->buffer[0].address = virt_to_bus(txb +
2867c478bd9Sstevel@tonic-gate 				(i * TLAN_MAX_FRAME_SIZE));
2877c478bd9Sstevel@tonic-gate 		list->buffer[2].count = 0;
2887c478bd9Sstevel@tonic-gate 		list->buffer[2].address = 0;
2897c478bd9Sstevel@tonic-gate 		list->buffer[9].address = 0;
2907c478bd9Sstevel@tonic-gate /*		list->forward = 0; */
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	priv->cur_rx = 0;
2947c478bd9Sstevel@tonic-gate 	priv->rx_buf_sz = (TLAN_MAX_FRAME_SIZE);
2957c478bd9Sstevel@tonic-gate 	priv->rx_head_desc = &rx_ring[0];
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/* Initialize all the Rx descriptors */
2987c478bd9Sstevel@tonic-gate 	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
2997c478bd9Sstevel@tonic-gate 		rx_ring[i].forward = virt_to_le32desc(&rx_ring[i + 1]);
3007c478bd9Sstevel@tonic-gate 		rx_ring[i].cStat = TLAN_CSTAT_READY;
3017c478bd9Sstevel@tonic-gate 		rx_ring[i].frameSize = TLAN_MAX_FRAME_SIZE;
3027c478bd9Sstevel@tonic-gate 		rx_ring[i].buffer[0].count =
3037c478bd9Sstevel@tonic-gate 		    TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
3047c478bd9Sstevel@tonic-gate 		rx_ring[i].buffer[0].address =
3057c478bd9Sstevel@tonic-gate 		    virt_to_le32desc(&rxb[i * TLAN_MAX_FRAME_SIZE]);
3067c478bd9Sstevel@tonic-gate 		rx_ring[i].buffer[1].count = 0;
3077c478bd9Sstevel@tonic-gate 		rx_ring[i].buffer[1].address = 0;
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/* Mark the last entry as wrapping the ring */
3117c478bd9Sstevel@tonic-gate 	rx_ring[i - 1].forward = virt_to_le32desc(&rx_ring[0]);
3127c478bd9Sstevel@tonic-gate 	priv->dirty_rx = (unsigned int) (i - TLAN_NUM_RX_LISTS);
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate } /* TLan_ResetLists */
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate /***************************************************************
3177c478bd9Sstevel@tonic-gate *	TLan_Reset
3187c478bd9Sstevel@tonic-gate *
3197c478bd9Sstevel@tonic-gate *	Returns:
3207c478bd9Sstevel@tonic-gate *		0
3217c478bd9Sstevel@tonic-gate *	Parms:
3227c478bd9Sstevel@tonic-gate *		dev	Pointer to device structure of adapter
3237c478bd9Sstevel@tonic-gate *			to be reset.
3247c478bd9Sstevel@tonic-gate *
3257c478bd9Sstevel@tonic-gate *	This function resets the adapter and it's physical
3267c478bd9Sstevel@tonic-gate *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN
3277c478bd9Sstevel@tonic-gate *	Programmer's Guide" for details.  The routine tries to
3287c478bd9Sstevel@tonic-gate *	implement what is detailed there, though adjustments
3297c478bd9Sstevel@tonic-gate *	have been made.
3307c478bd9Sstevel@tonic-gate *
3317c478bd9Sstevel@tonic-gate **************************************************************/
3327c478bd9Sstevel@tonic-gate 
TLan_ResetAdapter(struct nic * nic __unused)3337c478bd9Sstevel@tonic-gate void TLan_ResetAdapter(struct nic *nic __unused)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate 	int i;
3367c478bd9Sstevel@tonic-gate 	u32 addr;
3377c478bd9Sstevel@tonic-gate 	u32 data;
3387c478bd9Sstevel@tonic-gate 	u8 data8;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	priv->tlanFullDuplex = FALSE;
3417c478bd9Sstevel@tonic-gate 	priv->phyOnline = 0;
3427c478bd9Sstevel@tonic-gate /*  1.	Assert reset bit. */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	data = inl(BASE + TLAN_HOST_CMD);
3457c478bd9Sstevel@tonic-gate 	data |= TLAN_HC_AD_RST;
3467c478bd9Sstevel@tonic-gate 	outl(data, BASE + TLAN_HOST_CMD);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	udelay(1000);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /*  2.	Turn off interrupts. ( Probably isn't necessary ) */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	data = inl(BASE + TLAN_HOST_CMD);
3537c478bd9Sstevel@tonic-gate 	data |= TLAN_HC_INT_OFF;
3547c478bd9Sstevel@tonic-gate 	outl(data, BASE + TLAN_HOST_CMD);
3557c478bd9Sstevel@tonic-gate /*  3.	Clear AREGs and HASHs. */
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4) {
3587c478bd9Sstevel@tonic-gate 		TLan_DioWrite32(BASE, (u16) i, 0);
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /*  4.	Setup NetConfig register. */
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	data =
3647c478bd9Sstevel@tonic-gate 	    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
3657c478bd9Sstevel@tonic-gate 	TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*  5.	Load Ld_Tmr and Ld_Thr in HOST_CMD. */
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	outl(TLAN_HC_LD_TMR | 0x3f, BASE + TLAN_HOST_CMD);
3707c478bd9Sstevel@tonic-gate 	outl(TLAN_HC_LD_THR | 0x0, BASE + TLAN_HOST_CMD);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*  6.	Unreset the MII by setting NMRST (in NetSio) to 1. */
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
3757c478bd9Sstevel@tonic-gate 	addr = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
3767c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_NMRST, addr);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate /*  7.	Setup the remaining registers. */
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	if (priv->tlanRev >= 0x30) {
3817c478bd9Sstevel@tonic-gate 		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
3827c478bd9Sstevel@tonic-gate 		TLan_DioWrite8(BASE, TLAN_INT_DIS, data8);
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 	TLan_PhyDetect(nic);
3857c478bd9Sstevel@tonic-gate 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_BIT_RATE_PHY) {
3887c478bd9Sstevel@tonic-gate 		data |= TLAN_NET_CFG_BIT;
3897c478bd9Sstevel@tonic-gate 		if (priv->aui == 1) {
3907c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x0a);
3917c478bd9Sstevel@tonic-gate 		} else if (priv->duplex == TLAN_DUPLEX_FULL) {
3927c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x00);
3937c478bd9Sstevel@tonic-gate 			priv->tlanFullDuplex = TRUE;
3947c478bd9Sstevel@tonic-gate 		} else {
3957c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_ACOMMIT, 0x08);
3967c478bd9Sstevel@tonic-gate 		}
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (priv->phyNum == 0) {
4007c478bd9Sstevel@tonic-gate 		data |= TLAN_NET_CFG_PHY_EN;
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 	TLan_DioWrite16(BASE, TLAN_NET_CONFIG, (u16) data);
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
4057c478bd9Sstevel@tonic-gate 		TLan_FinishReset(nic);
4067c478bd9Sstevel@tonic-gate 	} else {
4077c478bd9Sstevel@tonic-gate 		TLan_PhyPowerDown(nic);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate }	/* TLan_ResetAdapter */
4117c478bd9Sstevel@tonic-gate 
TLan_FinishReset(struct nic * nic)4127c478bd9Sstevel@tonic-gate void TLan_FinishReset(struct nic *nic)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	u8 data;
4167c478bd9Sstevel@tonic-gate 	u32 phy;
4177c478bd9Sstevel@tonic-gate 	u8 sio;
4187c478bd9Sstevel@tonic-gate 	u16 status;
4197c478bd9Sstevel@tonic-gate 	u16 partner;
4207c478bd9Sstevel@tonic-gate 	u16 tlphy_ctl;
4217c478bd9Sstevel@tonic-gate 	u16 tlphy_par;
4227c478bd9Sstevel@tonic-gate 	u16 tlphy_id1, tlphy_id2;
4237c478bd9Sstevel@tonic-gate 	int i;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	phy = priv->phy[priv->phyNum];
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
4287c478bd9Sstevel@tonic-gate 	if (priv->tlanFullDuplex) {
4297c478bd9Sstevel@tonic-gate 		data |= TLAN_NET_CMD_DUPLEX;
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 	TLan_DioWrite8(BASE, TLAN_NET_CMD, data);
4327c478bd9Sstevel@tonic-gate 	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
4337c478bd9Sstevel@tonic-gate 	if (priv->phyNum == 0) {
4347c478bd9Sstevel@tonic-gate 		data |= TLAN_NET_MASK_MASK7;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	TLan_DioWrite8(BASE, TLAN_NET_MASK, data);
4377c478bd9Sstevel@tonic-gate 	TLan_DioWrite16(BASE, TLAN_MAX_RX, ((1536) + 7) & ~7);
4387c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_ID_HI, &tlphy_id1);
4397c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_ID_LO, &tlphy_id2);
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if ((tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY)
4427c478bd9Sstevel@tonic-gate 	    || (priv->aui)) {
4437c478bd9Sstevel@tonic-gate 		status = MII_GS_LINK;
4447c478bd9Sstevel@tonic-gate 		printf("TLAN:  %s: Link forced.\n", priv->nic_name);
4457c478bd9Sstevel@tonic-gate 	} else {
4467c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);
4477c478bd9Sstevel@tonic-gate 		udelay(1000);
4487c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);
4497c478bd9Sstevel@tonic-gate 		if ((status & MII_GS_LINK) &&	/* We only support link info on Nat.Sem. PHY's */
4507c478bd9Sstevel@tonic-gate 		    (tlphy_id1 == NAT_SEM_ID1)
4517c478bd9Sstevel@tonic-gate 		    && (tlphy_id2 == NAT_SEM_ID2)) {
4527c478bd9Sstevel@tonic-gate 			TLan_MiiReadReg(nic, phy, MII_AN_LPA, &partner);
4537c478bd9Sstevel@tonic-gate 			TLan_MiiReadReg(nic, phy, TLAN_TLPHY_PAR,
4547c478bd9Sstevel@tonic-gate 					&tlphy_par);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 			printf("TLAN: %s: Link active with ",
4577c478bd9Sstevel@tonic-gate 			       priv->nic_name);
4587c478bd9Sstevel@tonic-gate 			if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
4597c478bd9Sstevel@tonic-gate 				printf("forced 10%sMbps %s-Duplex\n",
4607c478bd9Sstevel@tonic-gate 				       tlphy_par & TLAN_PHY_SPEED_100 ? ""
4617c478bd9Sstevel@tonic-gate 				       : "0",
4627c478bd9Sstevel@tonic-gate 				       tlphy_par & TLAN_PHY_DUPLEX_FULL ?
4637c478bd9Sstevel@tonic-gate 				       "Full" : "Half");
4647c478bd9Sstevel@tonic-gate 			} else {
4657c478bd9Sstevel@tonic-gate 				printf
4667c478bd9Sstevel@tonic-gate 				    ("AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
4677c478bd9Sstevel@tonic-gate 				     tlphy_par & TLAN_PHY_SPEED_100 ? "" :
4687c478bd9Sstevel@tonic-gate 				     "0",
4697c478bd9Sstevel@tonic-gate 				     tlphy_par & TLAN_PHY_DUPLEX_FULL ?
4707c478bd9Sstevel@tonic-gate 				     "Full" : "Half");
4717c478bd9Sstevel@tonic-gate 				printf("TLAN: Partner capability: ");
4727c478bd9Sstevel@tonic-gate 				for (i = 5; i <= 10; i++)
4737c478bd9Sstevel@tonic-gate 					if (partner & (1 << i))
4747c478bd9Sstevel@tonic-gate 						printf("%s", media[i - 5]);
4757c478bd9Sstevel@tonic-gate 				printf("\n");
4767c478bd9Sstevel@tonic-gate 			}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
4797c478bd9Sstevel@tonic-gate #ifdef MONITOR
4807c478bd9Sstevel@tonic-gate 			/* We have link beat..for now anyway */
4817c478bd9Sstevel@tonic-gate 			priv->link = 1;
4827c478bd9Sstevel@tonic-gate 			/*Enabling link beat monitoring */
4837c478bd9Sstevel@tonic-gate 			/* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_LINK_BEAT ); */
4847c478bd9Sstevel@tonic-gate 			mdelay(10000);
4857c478bd9Sstevel@tonic-gate 			TLan_PhyMonitor(nic);
4867c478bd9Sstevel@tonic-gate #endif
4877c478bd9Sstevel@tonic-gate 		} else if (status & MII_GS_LINK) {
4887c478bd9Sstevel@tonic-gate 			printf("TLAN: %s: Link active\n", priv->nic_name);
4897c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_LED_REG, TLAN_LED_LINK);
4907c478bd9Sstevel@tonic-gate 		}
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	if (priv->phyNum == 0) {
4947c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
4957c478bd9Sstevel@tonic-gate 		tlphy_ctl |= TLAN_TC_INTEN;
4967c478bd9Sstevel@tonic-gate 		TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tlphy_ctl);
4977c478bd9Sstevel@tonic-gate 		sio = TLan_DioRead8(BASE, TLAN_NET_SIO);
4987c478bd9Sstevel@tonic-gate 		sio |= TLAN_NET_SIO_MINTEN;
4997c478bd9Sstevel@tonic-gate 		TLan_DioWrite8(BASE, TLAN_NET_SIO, sio);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	if (status & MII_GS_LINK) {
5037c478bd9Sstevel@tonic-gate 		TLan_SetMac(nic, 0, nic->node_addr);
5047c478bd9Sstevel@tonic-gate 		priv->phyOnline = 1;
5057c478bd9Sstevel@tonic-gate 		outb((TLAN_HC_INT_ON >> 8), BASE + TLAN_HOST_CMD + 1);
5067c478bd9Sstevel@tonic-gate /*		if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) {
5077c478bd9Sstevel@tonic-gate 			outb( ( TLAN_HC_REQ_INT >> 8 ), BASE + TLAN_HOST_CMD + 1 );
5087c478bd9Sstevel@tonic-gate 		}
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		*/
5117c478bd9Sstevel@tonic-gate 		outl(virt_to_bus(&rx_ring), BASE + TLAN_CH_PARM);
5127c478bd9Sstevel@tonic-gate 		outl(TLAN_HC_GO | TLAN_HC_RT, BASE + TLAN_HOST_CMD);
5137c478bd9Sstevel@tonic-gate 	} else {
5147c478bd9Sstevel@tonic-gate 		printf
5157c478bd9Sstevel@tonic-gate 		    ("TLAN: %s: Link inactive, will retry in 10 secs...\n",
5167c478bd9Sstevel@tonic-gate 		     priv->nic_name);
5177c478bd9Sstevel@tonic-gate 		/* TLan_SetTimer( nic, (10*HZ), TLAN_TIMER_FINISH_RESET ); */
5187c478bd9Sstevel@tonic-gate 		mdelay(10000);
5197c478bd9Sstevel@tonic-gate 		TLan_FinishReset(nic);
5207c478bd9Sstevel@tonic-gate 		return;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate }	/* TLan_FinishReset */
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate /**************************************************************************
5277c478bd9Sstevel@tonic-gate POLL - Wait for a frame
5287c478bd9Sstevel@tonic-gate ***************************************************************************/
tlan_poll(struct nic * nic,int retrieve)5297c478bd9Sstevel@tonic-gate static int tlan_poll(struct nic *nic, int retrieve)
5307c478bd9Sstevel@tonic-gate {
5317c478bd9Sstevel@tonic-gate 	/* return true if there's an ethernet packet ready to read */
5327c478bd9Sstevel@tonic-gate 	/* nic->packet should contain data on return */
5337c478bd9Sstevel@tonic-gate 	/* nic->packetlen should contain length of data */
5347c478bd9Sstevel@tonic-gate 	u32 framesize;
5357c478bd9Sstevel@tonic-gate 	u32 host_cmd = 0;
5367c478bd9Sstevel@tonic-gate 	u32 ack = 1;
5377c478bd9Sstevel@tonic-gate 	int eoc = 0;
5387c478bd9Sstevel@tonic-gate 	int entry = priv->cur_rx % TLAN_NUM_RX_LISTS;
5397c478bd9Sstevel@tonic-gate 	u16 tmpCStat = le32_to_cpu(rx_ring[entry].cStat);
5407c478bd9Sstevel@tonic-gate 	u16 host_int = inw(BASE + TLAN_HOST_INT);
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	if ((tmpCStat & TLAN_CSTAT_FRM_CMP) && !retrieve)
5437c478bd9Sstevel@tonic-gate 	  return 1;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	outw(host_int, BASE + TLAN_HOST_INT);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	if (!(tmpCStat & TLAN_CSTAT_FRM_CMP))
5487c478bd9Sstevel@tonic-gate 		return 0;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/* printf("PI-1: 0x%hX\n", host_int); */
5517c478bd9Sstevel@tonic-gate 	if (tmpCStat & TLAN_CSTAT_EOC)
5527c478bd9Sstevel@tonic-gate 		eoc = 1;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	framesize = rx_ring[entry].frameSize;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	nic->packetlen = framesize;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
5597c478bd9Sstevel@tonic-gate      printf(".%d.", framesize);
5607c478bd9Sstevel@tonic-gate #endif
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	memcpy(nic->packet, rxb +
5637c478bd9Sstevel@tonic-gate 	       (priv->cur_rx * TLAN_MAX_FRAME_SIZE), nic->packetlen);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	rx_ring[entry].cStat = 0;
5667c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
5677c478bd9Sstevel@tonic-gate 	hex_dump(nic->packet, nic->packetlen);
5687c478bd9Sstevel@tonic-gate 	printf("%d", entry);
5697c478bd9Sstevel@tonic-gate #endif
5707c478bd9Sstevel@tonic-gate 	entry = (entry + 1) % TLAN_NUM_RX_LISTS;
5717c478bd9Sstevel@tonic-gate 	priv->cur_rx = entry;
5727c478bd9Sstevel@tonic-gate 	if (eoc) {
5737c478bd9Sstevel@tonic-gate 		if ((rx_ring[entry].cStat & TLAN_CSTAT_READY) ==
5747c478bd9Sstevel@tonic-gate 		    TLAN_CSTAT_READY) {
5757c478bd9Sstevel@tonic-gate 			ack |= TLAN_HC_GO | TLAN_HC_RT;
5767c478bd9Sstevel@tonic-gate 			host_cmd = TLAN_HC_ACK | ack | 0x001C0000;
5777c478bd9Sstevel@tonic-gate 			outl(host_cmd, BASE + TLAN_HOST_CMD);
5787c478bd9Sstevel@tonic-gate 		}
5797c478bd9Sstevel@tonic-gate 	} else {
5807c478bd9Sstevel@tonic-gate 		host_cmd = TLAN_HC_ACK | ack | (0x000C0000);
5817c478bd9Sstevel@tonic-gate 		outl(host_cmd, BASE + TLAN_HOST_CMD);
5827c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
5837c478bd9Sstevel@tonic-gate 		printf("AC: 0x%hX\n", inw(BASE + TLAN_CH_PARM));
5847c478bd9Sstevel@tonic-gate 		host_int = inw(BASE + TLAN_HOST_INT);
5857c478bd9Sstevel@tonic-gate 		printf("PI-2: 0x%hX\n", host_int);
5867c478bd9Sstevel@tonic-gate #endif
5877c478bd9Sstevel@tonic-gate 	}
5887c478bd9Sstevel@tonic-gate 	refill_rx(nic);
5897c478bd9Sstevel@tonic-gate 	return (1);		/* initially as this is called to flush the input */
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
refill_rx(struct nic * nic __unused)5927c478bd9Sstevel@tonic-gate static void refill_rx(struct nic *nic __unused)
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate 	int entry = 0;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	for (;
5977c478bd9Sstevel@tonic-gate 	     (priv->cur_rx - priv->dirty_rx +
5987c478bd9Sstevel@tonic-gate 	      TLAN_NUM_RX_LISTS) % TLAN_NUM_RX_LISTS > 0;
5997c478bd9Sstevel@tonic-gate 	     priv->dirty_rx = (priv->dirty_rx + 1) % TLAN_NUM_RX_LISTS) {
6007c478bd9Sstevel@tonic-gate 		entry = priv->dirty_rx % TLAN_NUM_TX_LISTS;
6017c478bd9Sstevel@tonic-gate 		rx_ring[entry].frameSize = TLAN_MAX_FRAME_SIZE;
6027c478bd9Sstevel@tonic-gate 		rx_ring[entry].cStat = TLAN_CSTAT_READY;
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate /* #define EBDEBUG */
6087c478bd9Sstevel@tonic-gate /**************************************************************************
6097c478bd9Sstevel@tonic-gate TRANSMIT - Transmit a frame
6107c478bd9Sstevel@tonic-gate ***************************************************************************/
tlan_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)6117c478bd9Sstevel@tonic-gate static void tlan_transmit(struct nic *nic, const char *d,	/* Destination */
6127c478bd9Sstevel@tonic-gate 			  unsigned int t,	/* Type */
6137c478bd9Sstevel@tonic-gate 			  unsigned int s,	/* size */
6147c478bd9Sstevel@tonic-gate 			  const char *p)
6157c478bd9Sstevel@tonic-gate {				/* Packet */
6167c478bd9Sstevel@tonic-gate 	u16 nstype;
6177c478bd9Sstevel@tonic-gate 	u32 to;
6187c478bd9Sstevel@tonic-gate 	struct TLanList *tail_list;
6197c478bd9Sstevel@tonic-gate 	struct TLanList *head_list;
6207c478bd9Sstevel@tonic-gate 	u8 *tail_buffer;
6217c478bd9Sstevel@tonic-gate 	u32 ack = 0;
6227c478bd9Sstevel@tonic-gate 	u32 host_cmd;
6237c478bd9Sstevel@tonic-gate 	int eoc = 0;
6247c478bd9Sstevel@tonic-gate 	u16 tmpCStat;
6257c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
6267c478bd9Sstevel@tonic-gate 	u16 host_int = inw(BASE + TLAN_HOST_INT);
6277c478bd9Sstevel@tonic-gate #endif
6287c478bd9Sstevel@tonic-gate 	int entry = 0;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
6317c478bd9Sstevel@tonic-gate 	printf("INT0-0x%hX\n", host_int);
6327c478bd9Sstevel@tonic-gate #endif
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	if (!priv->phyOnline) {
6357c478bd9Sstevel@tonic-gate 		printf("TRANSMIT:  %s PHY is not ready\n", priv->nic_name);
6367c478bd9Sstevel@tonic-gate 		return;
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	tail_list = priv->txList + priv->txTail;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (tail_list->cStat != TLAN_CSTAT_UNUSED) {
6427c478bd9Sstevel@tonic-gate 		printf("TRANSMIT: %s is busy (Head=%d Tail=%d)\n",
6437c478bd9Sstevel@tonic-gate 		       priv->nic_name, priv->txList, priv->txTail);
6447c478bd9Sstevel@tonic-gate 		tx_ring[entry].cStat = TLAN_CSTAT_UNUSED;
6457c478bd9Sstevel@tonic-gate 		priv->txBusyCount++;
6467c478bd9Sstevel@tonic-gate 		return;
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	tail_list->forward = 0;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	tail_buffer = txb + (priv->txTail * TLAN_MAX_FRAME_SIZE);
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	/* send the packet to destination */
6547c478bd9Sstevel@tonic-gate 	memcpy(tail_buffer, d, ETH_ALEN);
6557c478bd9Sstevel@tonic-gate 	memcpy(tail_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);
6567c478bd9Sstevel@tonic-gate 	nstype = htons((u16) t);
6577c478bd9Sstevel@tonic-gate 	memcpy(tail_buffer + 2 * ETH_ALEN, (u8 *) & nstype, 2);
6587c478bd9Sstevel@tonic-gate 	memcpy(tail_buffer + ETH_HLEN, p, s);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	s += ETH_HLEN;
6617c478bd9Sstevel@tonic-gate 	s &= 0x0FFF;
6627c478bd9Sstevel@tonic-gate 	while (s < ETH_ZLEN)
6637c478bd9Sstevel@tonic-gate 		tail_buffer[s++] = '\0';
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	/*=====================================================*/
6667c478bd9Sstevel@tonic-gate 	/* Receive
6677c478bd9Sstevel@tonic-gate 	 * 0000 0000 0001 1100
6687c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 1100
6697c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0011 = 0x0003
6707c478bd9Sstevel@tonic-gate 	 *
6717c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0000 0000 0000 0000 0011
6727c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 1100 0000 0000 0000 0000 = 0x000C0000
6737c478bd9Sstevel@tonic-gate 	 *
6747c478bd9Sstevel@tonic-gate 	 * Transmit
6757c478bd9Sstevel@tonic-gate 	 * 0000 0000 0001 1100
6767c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0100
6777c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0001 = 0x0001
6787c478bd9Sstevel@tonic-gate 	 *
6797c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0000 0000 0000 0000 0001
6807c478bd9Sstevel@tonic-gate 	 * 0000 0000 0000 0100 0000 0000 0000 0000 = 0x00040000
6817c478bd9Sstevel@tonic-gate 	 * */
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	/* Setup the transmit descriptor */
6847c478bd9Sstevel@tonic-gate 	tail_list->frameSize = (u16) s;
6857c478bd9Sstevel@tonic-gate 	tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) s;
6867c478bd9Sstevel@tonic-gate 	tail_list->buffer[1].count = 0;
6877c478bd9Sstevel@tonic-gate 	tail_list->buffer[1].address = 0;
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	tail_list->cStat = TLAN_CSTAT_READY;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
6927c478bd9Sstevel@tonic-gate 	host_int = inw(BASE + TLAN_HOST_INT);
6937c478bd9Sstevel@tonic-gate 	printf("INT1-0x%hX\n", host_int);
6947c478bd9Sstevel@tonic-gate #endif
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	if (!priv->txInProgress) {
6977c478bd9Sstevel@tonic-gate 		priv->txInProgress = 1;
6987c478bd9Sstevel@tonic-gate 		outl(virt_to_le32desc(tail_list), BASE + TLAN_CH_PARM);
6997c478bd9Sstevel@tonic-gate 		outl(TLAN_HC_GO, BASE + TLAN_HOST_CMD);
7007c478bd9Sstevel@tonic-gate 	} else {
7017c478bd9Sstevel@tonic-gate 		if (priv->txTail == 0) {
7027c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
7037c478bd9Sstevel@tonic-gate 			printf("Out buffer\n");
7047c478bd9Sstevel@tonic-gate #endif
7057c478bd9Sstevel@tonic-gate 			(priv->txList + (TLAN_NUM_TX_LISTS - 1))->forward =
7067c478bd9Sstevel@tonic-gate 			    virt_to_le32desc(tail_list);
7077c478bd9Sstevel@tonic-gate 		} else {
7087c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
7097c478bd9Sstevel@tonic-gate 			printf("Fix this \n");
7107c478bd9Sstevel@tonic-gate #endif
7117c478bd9Sstevel@tonic-gate 			(priv->txList + (priv->txTail - 1))->forward =
7127c478bd9Sstevel@tonic-gate 			    virt_to_le32desc(tail_list);
7137c478bd9Sstevel@tonic-gate 		}
7147c478bd9Sstevel@tonic-gate 	}
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	CIRC_INC(priv->txTail, TLAN_NUM_TX_LISTS);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate #ifdef EBDEBUG
7197c478bd9Sstevel@tonic-gate 	host_int = inw(BASE + TLAN_HOST_INT);
7207c478bd9Sstevel@tonic-gate 	printf("INT2-0x%hX\n", host_int);
7217c478bd9Sstevel@tonic-gate #endif
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	to = currticks() + TX_TIME_OUT;
7247c478bd9Sstevel@tonic-gate 	while ((tail_list->cStat == TLAN_CSTAT_READY) && currticks() < to);
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	head_list = priv->txList + priv->txHead;
7277c478bd9Sstevel@tonic-gate 	while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP)
7287c478bd9Sstevel@tonic-gate 			&& (ack < 255)) {
7297c478bd9Sstevel@tonic-gate 		ack++;
7307c478bd9Sstevel@tonic-gate 		if(tmpCStat & TLAN_CSTAT_EOC)
7317c478bd9Sstevel@tonic-gate 			eoc =1;
7327c478bd9Sstevel@tonic-gate 		head_list->cStat = TLAN_CSTAT_UNUSED;
7337c478bd9Sstevel@tonic-gate 		CIRC_INC(priv->txHead, TLAN_NUM_TX_LISTS);
7347c478bd9Sstevel@tonic-gate 		head_list = priv->txList + priv->txHead;
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	}
7377c478bd9Sstevel@tonic-gate 	if(!ack)
7387c478bd9Sstevel@tonic-gate 		printf("Incomplete TX Frame\n");
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	if(eoc) {
7417c478bd9Sstevel@tonic-gate 		head_list = priv->txList + priv->txHead;
7427c478bd9Sstevel@tonic-gate 		if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
7437c478bd9Sstevel@tonic-gate 			outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
7447c478bd9Sstevel@tonic-gate 			ack |= TLAN_HC_GO;
7457c478bd9Sstevel@tonic-gate 		} else {
7467c478bd9Sstevel@tonic-gate 			priv->txInProgress = 0;
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 	if(ack) {
7507c478bd9Sstevel@tonic-gate 		host_cmd = TLAN_HC_ACK | ack;
7517c478bd9Sstevel@tonic-gate 		outl(host_cmd, BASE + TLAN_HOST_CMD);
7527c478bd9Sstevel@tonic-gate 	}
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	if(priv->tlanRev < 0x30 ) {
7557c478bd9Sstevel@tonic-gate 		ack = 1;
7567c478bd9Sstevel@tonic-gate 		head_list = priv->txList + priv->txHead;
7577c478bd9Sstevel@tonic-gate 		if ((head_list->cStat & TLAN_CSTAT_READY) == TLAN_CSTAT_READY) {
7587c478bd9Sstevel@tonic-gate 			outl(virt_to_le32desc(head_list), BASE + TLAN_CH_PARM);
7597c478bd9Sstevel@tonic-gate 			ack |= TLAN_HC_GO;
7607c478bd9Sstevel@tonic-gate 		} else {
7617c478bd9Sstevel@tonic-gate 			priv->txInProgress = 0;
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 		host_cmd = TLAN_HC_ACK | ack | 0x00140000;
7647c478bd9Sstevel@tonic-gate 		outl(host_cmd, BASE + TLAN_HOST_CMD);
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (currticks() >= to) {
7697c478bd9Sstevel@tonic-gate 		printf("TX Time Out");
7707c478bd9Sstevel@tonic-gate 	}
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate /**************************************************************************
7747c478bd9Sstevel@tonic-gate DISABLE - Turn off ethernet interface
7757c478bd9Sstevel@tonic-gate ***************************************************************************/
7767c478bd9Sstevel@tonic-gate #ifdef EB51
tlan_disable(struct dev * dev __unused)7777c478bd9Sstevel@tonic-gate static void tlan_disable(struct dev *dev __unused)
7787c478bd9Sstevel@tonic-gate #else
7797c478bd9Sstevel@tonic-gate static void tlan_disable(struct nic *nic __unused)
7807c478bd9Sstevel@tonic-gate #endif
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate 	/* put the card in its initial state */
7837c478bd9Sstevel@tonic-gate 	/* This function serves 3 purposes.
7847c478bd9Sstevel@tonic-gate 	 * This disables DMA and interrupts so we don't receive
7857c478bd9Sstevel@tonic-gate 	 *  unexpected packets or interrupts from the card after
7867c478bd9Sstevel@tonic-gate 	 *  etherboot has finished.
7877c478bd9Sstevel@tonic-gate 	 * This frees resources so etherboot may use
7887c478bd9Sstevel@tonic-gate 	 *  this driver on another interface
7897c478bd9Sstevel@tonic-gate 	 * This allows etherboot to reinitialize the interface
7907c478bd9Sstevel@tonic-gate 	 *  if something is something goes wrong.
7917c478bd9Sstevel@tonic-gate 	 *
7927c478bd9Sstevel@tonic-gate 	 */
7937c478bd9Sstevel@tonic-gate 	outl(TLAN_HC_AD_RST, BASE + TLAN_HOST_CMD);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate /**************************************************************************
7977c478bd9Sstevel@tonic-gate IRQ - Enable, Disable, or Force interrupts
7987c478bd9Sstevel@tonic-gate ***************************************************************************/
tlan_irq(struct nic * nic __unused,irq_action_t action __unused)7997c478bd9Sstevel@tonic-gate static void tlan_irq(struct nic *nic __unused, irq_action_t action __unused)
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate   switch ( action ) {
8027c478bd9Sstevel@tonic-gate   case DISABLE :
8037c478bd9Sstevel@tonic-gate     break;
8047c478bd9Sstevel@tonic-gate   case ENABLE :
8057c478bd9Sstevel@tonic-gate     break;
8067c478bd9Sstevel@tonic-gate   case FORCE :
8077c478bd9Sstevel@tonic-gate     break;
8087c478bd9Sstevel@tonic-gate   }
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate 
TLan_SetMulticastList(struct nic * nic)8117c478bd9Sstevel@tonic-gate static void TLan_SetMulticastList(struct nic *nic) {
8127c478bd9Sstevel@tonic-gate 	int i;
8137c478bd9Sstevel@tonic-gate 	u8 tmp;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	/* !IFF_PROMISC */
8167c478bd9Sstevel@tonic-gate 	tmp = TLan_DioRead8(BASE, TLAN_NET_CMD);
8177c478bd9Sstevel@tonic-gate 	TLan_DioWrite8(BASE, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 	/* IFF_ALLMULTI */
8207c478bd9Sstevel@tonic-gate 	for(i = 0; i< 3; i++)
8217c478bd9Sstevel@tonic-gate 		TLan_SetMac(nic, i + 1, NULL);
8227c478bd9Sstevel@tonic-gate 	TLan_DioWrite32(BASE, TLAN_HASH_1, 0xFFFFFFFF);
8237c478bd9Sstevel@tonic-gate 	TLan_DioWrite32(BASE, TLAN_HASH_2, 0xFFFFFFFF);
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate /**************************************************************************
8287c478bd9Sstevel@tonic-gate PROBE - Look for an adapter, this routine's visible to the outside
8297c478bd9Sstevel@tonic-gate ***************************************************************************/
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate #define board_found 1
8327c478bd9Sstevel@tonic-gate #define valid_link 0
8337c478bd9Sstevel@tonic-gate #ifdef EB51
tlan_probe(struct dev * dev,struct pci_device * pci)8347c478bd9Sstevel@tonic-gate static int tlan_probe(struct dev *dev, struct pci_device *pci)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate 	struct nic *nic = (struct nic *) dev;
8377c478bd9Sstevel@tonic-gate #else
8387c478bd9Sstevel@tonic-gate struct nic *tlan_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate #endif
8417c478bd9Sstevel@tonic-gate 		u16 data = 0;
8427c478bd9Sstevel@tonic-gate 	int err;
8437c478bd9Sstevel@tonic-gate 	int i;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	if (pci->ioaddr == 0)
8467c478bd9Sstevel@tonic-gate 		return 0;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	nic->irqno  = 0;
8497c478bd9Sstevel@tonic-gate 	nic->ioaddr = pci->ioaddr & ~3;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	BASE = pci->ioaddr;
8527c478bd9Sstevel@tonic-gate 	printf("\n");
8537c478bd9Sstevel@tonic-gate 	printf("tlan.c: %s, %s\n", drv_version, drv_date);
8547c478bd9Sstevel@tonic-gate 	printf("%s: Probing for Vendor 0x%hX, Device 0x%hX",
8557c478bd9Sstevel@tonic-gate 	       pci->name, pci->vendor, pci->dev_id);
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	/* I really must find out what this does */
8597c478bd9Sstevel@tonic-gate 	adjust_pci_device(pci);
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	/* Point to private storage */
8627c478bd9Sstevel@tonic-gate 	priv = &TLanPrivateInfo;
8637c478bd9Sstevel@tonic-gate 	/* Figure out which chip we're dealing with */
8647c478bd9Sstevel@tonic-gate 	i = 0;
8657c478bd9Sstevel@tonic-gate 	chip_idx = -1;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	while (tlan_pci_tbl[i].name) {
8687c478bd9Sstevel@tonic-gate 		if ((((u32) pci->dev_id << 16) | pci->vendor) ==
8697c478bd9Sstevel@tonic-gate 		    (tlan_pci_tbl[i].id.pci & 0xffffffff)) {
8707c478bd9Sstevel@tonic-gate 			chip_idx = i;
8717c478bd9Sstevel@tonic-gate 			break;
8727c478bd9Sstevel@tonic-gate 		}
8737c478bd9Sstevel@tonic-gate 		i++;
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	priv->vendor_id = pci->vendor;
8777c478bd9Sstevel@tonic-gate 	priv->dev_id = pci->dev_id;
8787c478bd9Sstevel@tonic-gate 	priv->nic_name = pci->name;
8797c478bd9Sstevel@tonic-gate 	priv->eoc = 0;
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	err = 0;
8827c478bd9Sstevel@tonic-gate 	for (i = 0; i < 6; i++)
8837c478bd9Sstevel@tonic-gate 		err |= TLan_EeReadByte(BASE,
8847c478bd9Sstevel@tonic-gate 				       (u8) tlan_pci_tbl[chip_idx].
8857c478bd9Sstevel@tonic-gate 				       addrOfs + i,
8867c478bd9Sstevel@tonic-gate 				       (u8 *) & nic->node_addr[i]);
8877c478bd9Sstevel@tonic-gate 	if (err) {
8887c478bd9Sstevel@tonic-gate 		printf("TLAN: %s: Error reading MAC from eeprom: %d\n",
8897c478bd9Sstevel@tonic-gate 		       pci->name, err);
8907c478bd9Sstevel@tonic-gate 	} else
8917c478bd9Sstevel@tonic-gate 		printf("\nAddress: %!\n", nic->node_addr);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION);
8947c478bd9Sstevel@tonic-gate 	printf("\nRevision = 0x%hX\n", priv->tlanRev);
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	TLan_ResetLists(nic);
8977c478bd9Sstevel@tonic-gate 	TLan_ResetAdapter(nic);
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate 	data = inl(BASE + TLAN_HOST_CMD);
9007c478bd9Sstevel@tonic-gate 	data |= TLAN_HC_EOC;
9017c478bd9Sstevel@tonic-gate 	outw(data, BASE + TLAN_HOST_CMD);
9027c478bd9Sstevel@tonic-gate */
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	data = inl(BASE + TLAN_HOST_CMD);
9057c478bd9Sstevel@tonic-gate 	data |= TLAN_HC_INT_OFF;
9067c478bd9Sstevel@tonic-gate 	outw(data, BASE + TLAN_HOST_CMD);
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	TLan_SetMulticastList(nic);
9097c478bd9Sstevel@tonic-gate 	udelay(100);
9107c478bd9Sstevel@tonic-gate 	priv->txList = tx_ring;
9117c478bd9Sstevel@tonic-gate 	priv->rxList = rx_ring;
9127c478bd9Sstevel@tonic-gate /*	if (board_found && valid_link)
9137c478bd9Sstevel@tonic-gate 	{*/
9147c478bd9Sstevel@tonic-gate 	/* point to NIC specific routines */
9157c478bd9Sstevel@tonic-gate #ifdef EB51
9167c478bd9Sstevel@tonic-gate 	dev->disable = tlan_disable;
9177c478bd9Sstevel@tonic-gate 	nic->poll = tlan_poll;
9187c478bd9Sstevel@tonic-gate 	nic->transmit = tlan_transmit;
9197c478bd9Sstevel@tonic-gate 	nic->irq    = tlan_irq;
9207c478bd9Sstevel@tonic-gate 	return 1;
9217c478bd9Sstevel@tonic-gate #else
9227c478bd9Sstevel@tonic-gate 	nic->disable = tlan_disable;
9237c478bd9Sstevel@tonic-gate 	nic->poll = tlan_poll;
9247c478bd9Sstevel@tonic-gate 	nic->transmit = tlan_transmit;
9257c478bd9Sstevel@tonic-gate 	nic->irq    = tlan_irq;
9267c478bd9Sstevel@tonic-gate 	return nic;
9277c478bd9Sstevel@tonic-gate #endif
9287c478bd9Sstevel@tonic-gate }
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate /*****************************************************************************
9327c478bd9Sstevel@tonic-gate ******************************************************************************
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	ThunderLAN Driver Eeprom routines
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
9377c478bd9Sstevel@tonic-gate 	EEPROM.  These functions are based on information in Microchip's
9387c478bd9Sstevel@tonic-gate 	data sheet.  I don't know how well this functions will work with
9397c478bd9Sstevel@tonic-gate 	other EEPROMs.
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate ******************************************************************************
9427c478bd9Sstevel@tonic-gate *****************************************************************************/
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/***************************************************************
9467c478bd9Sstevel@tonic-gate 	 *	TLan_EeSendStart
9477c478bd9Sstevel@tonic-gate 	 *
9487c478bd9Sstevel@tonic-gate 	 *	Returns:
9497c478bd9Sstevel@tonic-gate 	 *		Nothing
9507c478bd9Sstevel@tonic-gate 	 *	Parms:
9517c478bd9Sstevel@tonic-gate 	 *		io_base		The IO port base address for the
9527c478bd9Sstevel@tonic-gate 	 *				TLAN device with the EEPROM to
9537c478bd9Sstevel@tonic-gate 	 *				use.
9547c478bd9Sstevel@tonic-gate 	 *
9557c478bd9Sstevel@tonic-gate 	 *	This function sends a start cycle to an EEPROM attached
9567c478bd9Sstevel@tonic-gate 	 *	to a TLAN chip.
9577c478bd9Sstevel@tonic-gate 	 *
9587c478bd9Sstevel@tonic-gate 	 **************************************************************/
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate void TLan_EeSendStart(u16 io_base)
9617c478bd9Sstevel@tonic-gate {
9627c478bd9Sstevel@tonic-gate 	u16 sio;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
9657c478bd9Sstevel@tonic-gate 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
9687c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
9697c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
9707c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
9717c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate }				/* TLan_EeSendStart */
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	/***************************************************************
9797c478bd9Sstevel@tonic-gate 	 *	TLan_EeSendByte
9807c478bd9Sstevel@tonic-gate 	 *
9817c478bd9Sstevel@tonic-gate 	 *	Returns:
9827c478bd9Sstevel@tonic-gate 	 *		If the correct ack was received, 0, otherwise 1
9837c478bd9Sstevel@tonic-gate 	 *	Parms:	io_base		The IO port base address for the
9847c478bd9Sstevel@tonic-gate 	 *				TLAN device with the EEPROM to
9857c478bd9Sstevel@tonic-gate 	 *				use.
9867c478bd9Sstevel@tonic-gate 	 *		data		The 8 bits of information to
9877c478bd9Sstevel@tonic-gate 	 *				send to the EEPROM.
9887c478bd9Sstevel@tonic-gate 	 *		stop		If TLAN_EEPROM_STOP is passed, a
9897c478bd9Sstevel@tonic-gate 	 *				stop cycle is sent after the
9907c478bd9Sstevel@tonic-gate 	 *				byte is sent after the ack is
9917c478bd9Sstevel@tonic-gate 	 *				read.
9927c478bd9Sstevel@tonic-gate 	 *
9937c478bd9Sstevel@tonic-gate 	 *	This function sends a byte on the serial EEPROM line,
9947c478bd9Sstevel@tonic-gate 	 *	driving the clock to send each bit. The function then
9957c478bd9Sstevel@tonic-gate 	 *	reverses transmission direction and reads an acknowledge
9967c478bd9Sstevel@tonic-gate 	 *	bit.
9977c478bd9Sstevel@tonic-gate 	 *
9987c478bd9Sstevel@tonic-gate 	 **************************************************************/
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate int TLan_EeSendByte(u16 io_base, u8 data, int stop)
10017c478bd9Sstevel@tonic-gate {
10027c478bd9Sstevel@tonic-gate 	int err;
10037c478bd9Sstevel@tonic-gate 	u8 place;
10047c478bd9Sstevel@tonic-gate 	u16 sio;
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
10077c478bd9Sstevel@tonic-gate 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	/* Assume clock is low, tx is enabled; */
10107c478bd9Sstevel@tonic-gate 	for (place = 0x80; place != 0; place >>= 1) {
10117c478bd9Sstevel@tonic-gate 		if (place & data)
10127c478bd9Sstevel@tonic-gate 			TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
10137c478bd9Sstevel@tonic-gate 		else
10147c478bd9Sstevel@tonic-gate 			TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);
10157c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10167c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
10197c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10207c478bd9Sstevel@tonic-gate 	err = TLan_GetBit(TLAN_NET_SIO_EDATA, sio);
10217c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
10227c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	if ((!err) && stop) {
10257c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);	/* STOP, raise data while clock is high */
10267c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10277c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
10287c478bd9Sstevel@tonic-gate 	}
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	return (err);
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate }				/* TLan_EeSendByte */
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	/***************************************************************
10387c478bd9Sstevel@tonic-gate 	 *	TLan_EeReceiveByte
10397c478bd9Sstevel@tonic-gate 	 *
10407c478bd9Sstevel@tonic-gate 	 *	Returns:
10417c478bd9Sstevel@tonic-gate 	 *		Nothing
10427c478bd9Sstevel@tonic-gate 	 *	Parms:
10437c478bd9Sstevel@tonic-gate 	 *		io_base		The IO port base address for the
10447c478bd9Sstevel@tonic-gate 	 *				TLAN device with the EEPROM to
10457c478bd9Sstevel@tonic-gate 	 *				use.
10467c478bd9Sstevel@tonic-gate 	 *		data		An address to a char to hold the
10477c478bd9Sstevel@tonic-gate 	 *				data sent from the EEPROM.
10487c478bd9Sstevel@tonic-gate 	 *		stop		If TLAN_EEPROM_STOP is passed, a
10497c478bd9Sstevel@tonic-gate 	 *				stop cycle is sent after the
10507c478bd9Sstevel@tonic-gate 	 *				byte is received, and no ack is
10517c478bd9Sstevel@tonic-gate 	 *				sent.
10527c478bd9Sstevel@tonic-gate 	 *
10537c478bd9Sstevel@tonic-gate 	 *	This function receives 8 bits of data from the EEPROM
10547c478bd9Sstevel@tonic-gate 	 *	over the serial link.  It then sends and ack bit, or no
10557c478bd9Sstevel@tonic-gate 	 *	ack and a stop bit.  This function is used to retrieve
10567c478bd9Sstevel@tonic-gate 	 *	data after the address of a byte in the EEPROM has been
10577c478bd9Sstevel@tonic-gate 	 *	sent.
10587c478bd9Sstevel@tonic-gate 	 *
10597c478bd9Sstevel@tonic-gate 	 **************************************************************/
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate void TLan_EeReceiveByte(u16 io_base, u8 * data, int stop)
10627c478bd9Sstevel@tonic-gate {
10637c478bd9Sstevel@tonic-gate 	u8 place;
10647c478bd9Sstevel@tonic-gate 	u16 sio;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
10677c478bd9Sstevel@tonic-gate 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
10687c478bd9Sstevel@tonic-gate 	*data = 0;
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	/* Assume clock is low, tx is enabled; */
10717c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio);
10727c478bd9Sstevel@tonic-gate 	for (place = 0x80; place; place >>= 1) {
10737c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10747c478bd9Sstevel@tonic-gate 		if (TLan_GetBit(TLAN_NET_SIO_EDATA, sio))
10757c478bd9Sstevel@tonic-gate 			*data |= place;
10767c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
10777c478bd9Sstevel@tonic-gate 	}
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_ETXEN, sio);
10807c478bd9Sstevel@tonic-gate 	if (!stop) {
10817c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);	/* Ack = 0 */
10827c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10837c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
10847c478bd9Sstevel@tonic-gate 	} else {
10857c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_EDATA, sio);	/* No ack = 1 (?) */
10867c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10877c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);
10887c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_EDATA, sio);	/* STOP, raise data while clock is high */
10897c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_ECLOK, sio);
10907c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_EDATA, sio);
10917c478bd9Sstevel@tonic-gate 	}
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate }				/* TLan_EeReceiveByte */
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 	/***************************************************************
10987c478bd9Sstevel@tonic-gate 	 *	TLan_EeReadByte
10997c478bd9Sstevel@tonic-gate 	 *
11007c478bd9Sstevel@tonic-gate 	 *	Returns:
11017c478bd9Sstevel@tonic-gate 	 *		No error = 0, else, the stage at which the error
11027c478bd9Sstevel@tonic-gate 	 *		occurred.
11037c478bd9Sstevel@tonic-gate 	 *	Parms:
11047c478bd9Sstevel@tonic-gate 	 *		io_base		The IO port base address for the
11057c478bd9Sstevel@tonic-gate 	 *				TLAN device with the EEPROM to
11067c478bd9Sstevel@tonic-gate 	 *				use.
11077c478bd9Sstevel@tonic-gate 	 *		ee_addr		The address of the byte in the
11087c478bd9Sstevel@tonic-gate 	 *				EEPROM whose contents are to be
11097c478bd9Sstevel@tonic-gate 	 *				retrieved.
11107c478bd9Sstevel@tonic-gate 	 *		data		An address to a char to hold the
11117c478bd9Sstevel@tonic-gate 	 *				data obtained from the EEPROM.
11127c478bd9Sstevel@tonic-gate 	 *
11137c478bd9Sstevel@tonic-gate 	 *	This function reads a byte of information from an byte
11147c478bd9Sstevel@tonic-gate 	 *	cell in the EEPROM.
11157c478bd9Sstevel@tonic-gate 	 *
11167c478bd9Sstevel@tonic-gate 	 **************************************************************/
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate int TLan_EeReadByte(u16 io_base, u8 ee_addr, u8 * data)
11197c478bd9Sstevel@tonic-gate {
11207c478bd9Sstevel@tonic-gate 	int err;
11217c478bd9Sstevel@tonic-gate 	int ret = 0;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	TLan_EeSendStart(io_base);
11257c478bd9Sstevel@tonic-gate 	err = TLan_EeSendByte(io_base, 0xA0, TLAN_EEPROM_ACK);
11267c478bd9Sstevel@tonic-gate 	if (err) {
11277c478bd9Sstevel@tonic-gate 		ret = 1;
11287c478bd9Sstevel@tonic-gate 		goto fail;
11297c478bd9Sstevel@tonic-gate 	}
11307c478bd9Sstevel@tonic-gate 	err = TLan_EeSendByte(io_base, ee_addr, TLAN_EEPROM_ACK);
11317c478bd9Sstevel@tonic-gate 	if (err) {
11327c478bd9Sstevel@tonic-gate 		ret = 2;
11337c478bd9Sstevel@tonic-gate 		goto fail;
11347c478bd9Sstevel@tonic-gate 	}
11357c478bd9Sstevel@tonic-gate 	TLan_EeSendStart(io_base);
11367c478bd9Sstevel@tonic-gate 	err = TLan_EeSendByte(io_base, 0xA1, TLAN_EEPROM_ACK);
11377c478bd9Sstevel@tonic-gate 	if (err) {
11387c478bd9Sstevel@tonic-gate 		ret = 3;
11397c478bd9Sstevel@tonic-gate 		goto fail;
11407c478bd9Sstevel@tonic-gate 	}
11417c478bd9Sstevel@tonic-gate 	TLan_EeReceiveByte(io_base, data, TLAN_EEPROM_STOP);
11427c478bd9Sstevel@tonic-gate       fail:
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	return ret;
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate }				/* TLan_EeReadByte */
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate /*****************************************************************************
11507c478bd9Sstevel@tonic-gate ******************************************************************************
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	ThunderLAN Driver MII Routines
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	These routines are based on the information in Chap. 2 of the
11557c478bd9Sstevel@tonic-gate 	"ThunderLAN Programmer's Guide", pp. 15-24.
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate ******************************************************************************
11587c478bd9Sstevel@tonic-gate *****************************************************************************/
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	/***************************************************************
11627c478bd9Sstevel@tonic-gate 	 *	TLan_MiiReadReg
11637c478bd9Sstevel@tonic-gate 	 *
11647c478bd9Sstevel@tonic-gate 	 *	Returns:
11657c478bd9Sstevel@tonic-gate 	 *		0	if ack received ok
11667c478bd9Sstevel@tonic-gate 	 *		1	otherwise.
11677c478bd9Sstevel@tonic-gate 	 *
11687c478bd9Sstevel@tonic-gate 	 *	Parms:
11697c478bd9Sstevel@tonic-gate 	 *		dev		The device structure containing
11707c478bd9Sstevel@tonic-gate 	 *				The io address and interrupt count
11717c478bd9Sstevel@tonic-gate 	 *				for this device.
11727c478bd9Sstevel@tonic-gate 	 *		phy		The address of the PHY to be queried.
11737c478bd9Sstevel@tonic-gate 	 *		reg		The register whose contents are to be
11747c478bd9Sstevel@tonic-gate 	 *				retreived.
11757c478bd9Sstevel@tonic-gate 	 *		val		A pointer to a variable to store the
11767c478bd9Sstevel@tonic-gate 	 *				retrieved value.
11777c478bd9Sstevel@tonic-gate 	 *
11787c478bd9Sstevel@tonic-gate 	 *	This function uses the TLAN's MII bus to retreive the contents
11797c478bd9Sstevel@tonic-gate 	 *	of a given register on a PHY.  It sends the appropriate info
11807c478bd9Sstevel@tonic-gate 	 *	and then reads the 16-bit register value from the MII bus via
11817c478bd9Sstevel@tonic-gate 	 *	the TLAN SIO register.
11827c478bd9Sstevel@tonic-gate 	 *
11837c478bd9Sstevel@tonic-gate 	 **************************************************************/
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate int TLan_MiiReadReg(struct nic *nic __unused, u16 phy, u16 reg, u16 * val)
11867c478bd9Sstevel@tonic-gate {
11877c478bd9Sstevel@tonic-gate 	u8 nack;
11887c478bd9Sstevel@tonic-gate 	u16 sio, tmp;
11897c478bd9Sstevel@tonic-gate 	u32 i;
11907c478bd9Sstevel@tonic-gate 	int err;
11917c478bd9Sstevel@tonic-gate 	int minten;
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 	err = FALSE;
11947c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
11957c478bd9Sstevel@tonic-gate 	sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 	minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
12007c478bd9Sstevel@tonic-gate 	if (minten)
12017c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, 0x1, 2);	/* Start ( 01b ) */
12047c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, 0x2, 2);	/* Read  ( 10b ) */
12057c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, phy, 5);	/* Device #      */
12067c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, reg, 5);	/* Register #    */
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);	/* Change direction */
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);	/* Clock Idle bit */
12127c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
12137c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);	/* Wait 300ns */
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio);	/* Check for ACK */
12167c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);	/* Finish ACK */
12177c478bd9Sstevel@tonic-gate 	if (nack) {		/* No ACK, so fake it */
12187c478bd9Sstevel@tonic-gate 		for (i = 0; i < 16; i++) {
12197c478bd9Sstevel@tonic-gate 			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
12207c478bd9Sstevel@tonic-gate 			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
12217c478bd9Sstevel@tonic-gate 		}
12227c478bd9Sstevel@tonic-gate 		tmp = 0xffff;
12237c478bd9Sstevel@tonic-gate 		err = TRUE;
12247c478bd9Sstevel@tonic-gate 	} else {		/* ACK, so read data */
12257c478bd9Sstevel@tonic-gate 		for (tmp = 0, i = 0x8000; i; i >>= 1) {
12267c478bd9Sstevel@tonic-gate 			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
12277c478bd9Sstevel@tonic-gate 			if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
12287c478bd9Sstevel@tonic-gate 				tmp |= i;
12297c478bd9Sstevel@tonic-gate 			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
12307c478bd9Sstevel@tonic-gate 		}
12317c478bd9Sstevel@tonic-gate 	}
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);	/* Idle cycle */
12357c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 	if (minten)
12387c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	*val = tmp;
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	return err;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate }				/* TLan_MiiReadReg */
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 	/***************************************************************
12477c478bd9Sstevel@tonic-gate 	 *	TLan_MiiSendData
12487c478bd9Sstevel@tonic-gate 	 *
12497c478bd9Sstevel@tonic-gate 	 *	Returns:
12507c478bd9Sstevel@tonic-gate 	 *		Nothing
12517c478bd9Sstevel@tonic-gate 	 *	Parms:
12527c478bd9Sstevel@tonic-gate 	 *		base_port	The base IO port of the adapter	in
12537c478bd9Sstevel@tonic-gate 	 *				question.
12547c478bd9Sstevel@tonic-gate 	 *		dev		The address of the PHY to be queried.
12557c478bd9Sstevel@tonic-gate 	 *		data		The value to be placed on the MII bus.
12567c478bd9Sstevel@tonic-gate 	 *		num_bits	The number of bits in data that are to
12577c478bd9Sstevel@tonic-gate 	 *				be placed on the MII bus.
12587c478bd9Sstevel@tonic-gate 	 *
12597c478bd9Sstevel@tonic-gate 	 *	This function sends on sequence of bits on the MII
12607c478bd9Sstevel@tonic-gate 	 *	configuration bus.
12617c478bd9Sstevel@tonic-gate 	 *
12627c478bd9Sstevel@tonic-gate 	 **************************************************************/
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate void TLan_MiiSendData(u16 base_port, u32 data, unsigned num_bits)
12657c478bd9Sstevel@tonic-gate {
12667c478bd9Sstevel@tonic-gate 	u16 sio;
12677c478bd9Sstevel@tonic-gate 	u32 i;
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	if (num_bits == 0)
12707c478bd9Sstevel@tonic-gate 		return;
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
12737c478bd9Sstevel@tonic-gate 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
12747c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_MTXEN, sio);
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
12777c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
12787c478bd9Sstevel@tonic-gate 		(void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
12797c478bd9Sstevel@tonic-gate 		if (data & i)
12807c478bd9Sstevel@tonic-gate 			TLan_SetBit(TLAN_NET_SIO_MDATA, sio);
12817c478bd9Sstevel@tonic-gate 		else
12827c478bd9Sstevel@tonic-gate 			TLan_ClearBit(TLAN_NET_SIO_MDATA, sio);
12837c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
12847c478bd9Sstevel@tonic-gate 		(void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio);
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate }				/* TLan_MiiSendData */
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	/***************************************************************
12937c478bd9Sstevel@tonic-gate 	 *	TLan_MiiSync
12947c478bd9Sstevel@tonic-gate 	 *
12957c478bd9Sstevel@tonic-gate 	 *	Returns:
12967c478bd9Sstevel@tonic-gate 	 *		Nothing
12977c478bd9Sstevel@tonic-gate 	 *	Parms:
12987c478bd9Sstevel@tonic-gate 	 *		base_port	The base IO port of the adapter in
12997c478bd9Sstevel@tonic-gate 	 *				question.
13007c478bd9Sstevel@tonic-gate 	 *
13017c478bd9Sstevel@tonic-gate 	 *	This functions syncs all PHYs in terms of the MII configuration
13027c478bd9Sstevel@tonic-gate 	 *	bus.
13037c478bd9Sstevel@tonic-gate 	 *
13047c478bd9Sstevel@tonic-gate 	 **************************************************************/
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate void TLan_MiiSync(u16 base_port)
13077c478bd9Sstevel@tonic-gate {
13087c478bd9Sstevel@tonic-gate 	int i;
13097c478bd9Sstevel@tonic-gate 	u16 sio;
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
13127c478bd9Sstevel@tonic-gate 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);
13157c478bd9Sstevel@tonic-gate 	for (i = 0; i < 32; i++) {
13167c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
13177c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
13187c478bd9Sstevel@tonic-gate 	}
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate }				/* TLan_MiiSync */
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 	/***************************************************************
13267c478bd9Sstevel@tonic-gate 	 *	TLan_MiiWriteReg
13277c478bd9Sstevel@tonic-gate 	 *
13287c478bd9Sstevel@tonic-gate 	 *	Returns:
13297c478bd9Sstevel@tonic-gate 	 *		Nothing
13307c478bd9Sstevel@tonic-gate 	 *	Parms:
13317c478bd9Sstevel@tonic-gate 	 *		dev		The device structure for the device
13327c478bd9Sstevel@tonic-gate 	 *				to write to.
13337c478bd9Sstevel@tonic-gate 	 *		phy		The address of the PHY to be written to.
13347c478bd9Sstevel@tonic-gate 	 *		reg		The register whose contents are to be
13357c478bd9Sstevel@tonic-gate 	 *				written.
13367c478bd9Sstevel@tonic-gate 	 *		val		The value to be written to the register.
13377c478bd9Sstevel@tonic-gate 	 *
13387c478bd9Sstevel@tonic-gate 	 *	This function uses the TLAN's MII bus to write the contents of a
13397c478bd9Sstevel@tonic-gate 	 *	given register on a PHY.  It sends the appropriate info and then
13407c478bd9Sstevel@tonic-gate 	 *	writes the 16-bit register value from the MII configuration bus
13417c478bd9Sstevel@tonic-gate 	 *	via the TLAN SIO register.
13427c478bd9Sstevel@tonic-gate 	 *
13437c478bd9Sstevel@tonic-gate 	 **************************************************************/
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate void TLan_MiiWriteReg(struct nic *nic __unused, u16 phy, u16 reg, u16 val)
13467c478bd9Sstevel@tonic-gate {
13477c478bd9Sstevel@tonic-gate 	u16 sio;
13487c478bd9Sstevel@tonic-gate 	int minten;
13497c478bd9Sstevel@tonic-gate 
13507c478bd9Sstevel@tonic-gate 	outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR);
13517c478bd9Sstevel@tonic-gate 	sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO;
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio);
13567c478bd9Sstevel@tonic-gate 	if (minten)
13577c478bd9Sstevel@tonic-gate 		TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, 0x1, 2);	/* Start ( 01b ) */
13607c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, 0x1, 2);	/* Write ( 01b ) */
13617c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, phy, 5);	/* Device #      */
13627c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, reg, 5);	/* Register #    */
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, 0x2, 2);	/* Send ACK */
13657c478bd9Sstevel@tonic-gate 	TLan_MiiSendData(BASE, val, 16);	/* Send Data */
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);	/* Idle cycle */
13687c478bd9Sstevel@tonic-gate 	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	if (minten)
13717c478bd9Sstevel@tonic-gate 		TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate }				/* TLan_MiiWriteReg */
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 	/***************************************************************
13777c478bd9Sstevel@tonic-gate 	 *	TLan_SetMac
13787c478bd9Sstevel@tonic-gate 	 *
13797c478bd9Sstevel@tonic-gate 	 *	Returns:
13807c478bd9Sstevel@tonic-gate 	 *		Nothing
13817c478bd9Sstevel@tonic-gate 	 *	Parms:
13827c478bd9Sstevel@tonic-gate 	 *		dev	Pointer to device structure of adapter
13837c478bd9Sstevel@tonic-gate 	 *			on which to change the AREG.
13847c478bd9Sstevel@tonic-gate 	 *		areg	The AREG to set the address in (0 - 3).
13857c478bd9Sstevel@tonic-gate 	 *		mac	A pointer to an array of chars.  Each
13867c478bd9Sstevel@tonic-gate 	 *			element stores one byte of the address.
13877c478bd9Sstevel@tonic-gate 	 *			IE, it isn't in ascii.
13887c478bd9Sstevel@tonic-gate 	 *
13897c478bd9Sstevel@tonic-gate 	 *	This function transfers a MAC address to one of the
13907c478bd9Sstevel@tonic-gate 	 *	TLAN AREGs (address registers).  The TLAN chip locks
13917c478bd9Sstevel@tonic-gate 	 *	the register on writing to offset 0 and unlocks the
13927c478bd9Sstevel@tonic-gate 	 *	register after writing to offset 5.  If NULL is passed
13937c478bd9Sstevel@tonic-gate 	 *	in mac, then the AREG is filled with 0's.
13947c478bd9Sstevel@tonic-gate 	 *
13957c478bd9Sstevel@tonic-gate 	 **************************************************************/
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate void TLan_SetMac(struct nic *nic __unused, int areg, char *mac)
13987c478bd9Sstevel@tonic-gate {
13997c478bd9Sstevel@tonic-gate 	int i;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 	areg *= 6;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	if (mac != NULL) {
14047c478bd9Sstevel@tonic-gate 		for (i = 0; i < 6; i++)
14057c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i,
14067c478bd9Sstevel@tonic-gate 				       mac[i]);
14077c478bd9Sstevel@tonic-gate 	} else {
14087c478bd9Sstevel@tonic-gate 		for (i = 0; i < 6; i++)
14097c478bd9Sstevel@tonic-gate 			TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0);
14107c478bd9Sstevel@tonic-gate 	}
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate }				/* TLan_SetMac */
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	/*********************************************************************
14157c478bd9Sstevel@tonic-gate 	 *	TLan_PhyDetect
14167c478bd9Sstevel@tonic-gate 	 *
14177c478bd9Sstevel@tonic-gate 	 *	Returns:
14187c478bd9Sstevel@tonic-gate 	 *		Nothing
14197c478bd9Sstevel@tonic-gate 	 *	Parms:
14207c478bd9Sstevel@tonic-gate 	 *		dev	A pointer to the device structure of the adapter
14217c478bd9Sstevel@tonic-gate 	 *			for which the PHY needs determined.
14227c478bd9Sstevel@tonic-gate 	 *
14237c478bd9Sstevel@tonic-gate 	 *	So far I've found that adapters which have external PHYs
14247c478bd9Sstevel@tonic-gate 	 *	may also use the internal PHY for part of the functionality.
14257c478bd9Sstevel@tonic-gate 	 *	(eg, AUI/Thinnet).  This function finds out if this TLAN
14267c478bd9Sstevel@tonic-gate 	 *	chip has an internal PHY, and then finds the first external
14277c478bd9Sstevel@tonic-gate 	 *	PHY (starting from address 0) if it exists).
14287c478bd9Sstevel@tonic-gate 	 *
14297c478bd9Sstevel@tonic-gate 	 ********************************************************************/
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate void TLan_PhyDetect(struct nic *nic)
14327c478bd9Sstevel@tonic-gate {
14337c478bd9Sstevel@tonic-gate 	u16 control;
14347c478bd9Sstevel@tonic-gate 	u16 hi;
14357c478bd9Sstevel@tonic-gate 	u16 lo;
14367c478bd9Sstevel@tonic-gate 	u32 phy;
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate 	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {
14397c478bd9Sstevel@tonic-gate 		priv->phyNum = 0xFFFF;
14407c478bd9Sstevel@tonic-gate 		return;
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi);
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	if (hi != 0xFFFF) {
14467c478bd9Sstevel@tonic-gate 		priv->phy[0] = TLAN_PHY_MAX_ADDR;
14477c478bd9Sstevel@tonic-gate 	} else {
14487c478bd9Sstevel@tonic-gate 		priv->phy[0] = TLAN_PHY_NONE;
14497c478bd9Sstevel@tonic-gate 	}
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	priv->phy[1] = TLAN_PHY_NONE;
14527c478bd9Sstevel@tonic-gate 	for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
14537c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &control);
14547c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_ID_HI, &hi);
14557c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_ID_LO, &lo);
14567c478bd9Sstevel@tonic-gate 		if ((control != 0xFFFF) || (hi != 0xFFFF)
14577c478bd9Sstevel@tonic-gate 		    || (lo != 0xFFFF)) {
14587c478bd9Sstevel@tonic-gate 			printf("PHY found at %hX %hX %hX %hX\n", phy,
14597c478bd9Sstevel@tonic-gate 			       control, hi, lo);
14607c478bd9Sstevel@tonic-gate 			if ((priv->phy[1] == TLAN_PHY_NONE)
14617c478bd9Sstevel@tonic-gate 			    && (phy != TLAN_PHY_MAX_ADDR)) {
14627c478bd9Sstevel@tonic-gate 				priv->phy[1] = phy;
14637c478bd9Sstevel@tonic-gate 			}
14647c478bd9Sstevel@tonic-gate 		}
14657c478bd9Sstevel@tonic-gate 	}
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	if (priv->phy[1] != TLAN_PHY_NONE) {
14687c478bd9Sstevel@tonic-gate 		priv->phyNum = 1;
14697c478bd9Sstevel@tonic-gate 	} else if (priv->phy[0] != TLAN_PHY_NONE) {
14707c478bd9Sstevel@tonic-gate 		priv->phyNum = 0;
14717c478bd9Sstevel@tonic-gate 	} else {
14727c478bd9Sstevel@tonic-gate 		printf
14737c478bd9Sstevel@tonic-gate 		    ("TLAN:  Cannot initialize device, no PHY was found!\n");
14747c478bd9Sstevel@tonic-gate 	}
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate }				/* TLan_PhyDetect */
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate void TLan_PhyPowerDown(struct nic *nic)
14797c478bd9Sstevel@tonic-gate {
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	u16 value;
14827c478bd9Sstevel@tonic-gate 	printf("%s: Powering down PHY(s).\n", priv->nic_name);
14837c478bd9Sstevel@tonic-gate 	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
14847c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
14857c478bd9Sstevel@tonic-gate 	TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value);
14867c478bd9Sstevel@tonic-gate 	if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE)
14877c478bd9Sstevel@tonic-gate 	    &&
14887c478bd9Sstevel@tonic-gate 	    (!(tlan_pci_tbl[chip_idx].
14897c478bd9Sstevel@tonic-gate 	       flags & TLAN_ADAPTER_USE_INTERN_10))) {
14907c478bd9Sstevel@tonic-gate 		TLan_MiiSync(BASE);
14917c478bd9Sstevel@tonic-gate 		TLan_MiiWriteReg(nic, priv->phy[1], MII_GEN_CTL, value);
14927c478bd9Sstevel@tonic-gate 	}
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	/* Wait for 50 ms and powerup
14957c478bd9Sstevel@tonic-gate 	 * This is abitrary.  It is intended to make sure the
14967c478bd9Sstevel@tonic-gate 	 * tranceiver settles.
14977c478bd9Sstevel@tonic-gate 	 */
14987c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */
14997c478bd9Sstevel@tonic-gate 	mdelay(50);
15007c478bd9Sstevel@tonic-gate 	TLan_PhyPowerUp(nic);
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate }				/* TLan_PhyPowerDown */
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate void TLan_PhyPowerUp(struct nic *nic)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate 	u16 value;
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 	printf("%s: Powering up PHY.\n", priv->nic_name);
15107c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
15117c478bd9Sstevel@tonic-gate 	value = MII_GC_LOOPBK;
15127c478bd9Sstevel@tonic-gate 	TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value);
15137c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
15147c478bd9Sstevel@tonic-gate 	/* Wait for 500 ms and reset the
15157c478bd9Sstevel@tonic-gate 	 * tranceiver.  The TLAN docs say both 50 ms and
15167c478bd9Sstevel@tonic-gate 	 * 500 ms, so do the longer, just in case.
15177c478bd9Sstevel@tonic-gate 	 */
15187c478bd9Sstevel@tonic-gate 	mdelay(500);
15197c478bd9Sstevel@tonic-gate 	TLan_PhyReset(nic);
15207c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate }				/* TLan_PhyPowerUp */
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate void TLan_PhyReset(struct nic *nic)
15257c478bd9Sstevel@tonic-gate {
15267c478bd9Sstevel@tonic-gate 	u16 phy;
15277c478bd9Sstevel@tonic-gate 	u16 value;
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 	phy = priv->phy[priv->phyNum];
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate 	printf("%s: Reseting PHY.\n", priv->nic_name);
15327c478bd9Sstevel@tonic-gate 	TLan_MiiSync(BASE);
15337c478bd9Sstevel@tonic-gate 	value = MII_GC_LOOPBK | MII_GC_RESET;
15347c478bd9Sstevel@tonic-gate 	TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, value);
15357c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value);
15367c478bd9Sstevel@tonic-gate 	while (value & MII_GC_RESET) {
15377c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value);
15387c478bd9Sstevel@tonic-gate 	}
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 	/* Wait for 500 ms and initialize.
15417c478bd9Sstevel@tonic-gate 	 * I don't remember why I wait this long.
15427c478bd9Sstevel@tonic-gate 	 * I've changed this to 50ms, as it seems long enough.
15437c478bd9Sstevel@tonic-gate 	 */
15447c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */
15457c478bd9Sstevel@tonic-gate 	mdelay(50);
15467c478bd9Sstevel@tonic-gate 	TLan_PhyStartLink(nic);
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate }				/* TLan_PhyReset */
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate void TLan_PhyStartLink(struct nic *nic)
15527c478bd9Sstevel@tonic-gate {
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 	u16 ability;
15557c478bd9Sstevel@tonic-gate 	u16 control;
15567c478bd9Sstevel@tonic-gate 	u16 data;
15577c478bd9Sstevel@tonic-gate 	u16 phy;
15587c478bd9Sstevel@tonic-gate 	u16 status;
15597c478bd9Sstevel@tonic-gate 	u16 tctl;
15607c478bd9Sstevel@tonic-gate 
15617c478bd9Sstevel@tonic-gate 	phy = priv->phy[priv->phyNum];
15627c478bd9Sstevel@tonic-gate 	printf("%s: Trying to activate link.\n", priv->nic_name);
15637c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);
15647c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &ability);
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	if ((status & MII_GS_AUTONEG) && (!priv->aui)) {
15677c478bd9Sstevel@tonic-gate 		ability = status >> 11;
15687c478bd9Sstevel@tonic-gate 		if (priv->speed == TLAN_SPEED_10 &&
15697c478bd9Sstevel@tonic-gate 		    priv->duplex == TLAN_DUPLEX_HALF) {
15707c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0000);
15717c478bd9Sstevel@tonic-gate 		} else if (priv->speed == TLAN_SPEED_10 &&
15727c478bd9Sstevel@tonic-gate 			   priv->duplex == TLAN_DUPLEX_FULL) {
15737c478bd9Sstevel@tonic-gate 			priv->tlanFullDuplex = TRUE;
15747c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0100);
15757c478bd9Sstevel@tonic-gate 		} else if (priv->speed == TLAN_SPEED_100 &&
15767c478bd9Sstevel@tonic-gate 			   priv->duplex == TLAN_DUPLEX_HALF) {
15777c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2000);
15787c478bd9Sstevel@tonic-gate 		} else if (priv->speed == TLAN_SPEED_100 &&
15797c478bd9Sstevel@tonic-gate 			   priv->duplex == TLAN_DUPLEX_FULL) {
15807c478bd9Sstevel@tonic-gate 			priv->tlanFullDuplex = TRUE;
15817c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2100);
15827c478bd9Sstevel@tonic-gate 		} else {
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 			/* Set Auto-Neg advertisement */
15857c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_AN_ADV,
15867c478bd9Sstevel@tonic-gate 					 (ability << 5) | 1);
15877c478bd9Sstevel@tonic-gate 			/* Enablee Auto-Neg */
15887c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1000);
15897c478bd9Sstevel@tonic-gate 			/* Restart Auto-Neg */
15907c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1200);
15917c478bd9Sstevel@tonic-gate 			/* Wait for 4 sec for autonegotiation
15927c478bd9Sstevel@tonic-gate 			 * to complete.  The max spec time is less than this
15937c478bd9Sstevel@tonic-gate 			 * but the card need additional time to start AN.
15947c478bd9Sstevel@tonic-gate 			 * .5 sec should be plenty extra.
15957c478bd9Sstevel@tonic-gate 			 */
15967c478bd9Sstevel@tonic-gate 			printf("TLAN: %s: Starting autonegotiation.\n",
15977c478bd9Sstevel@tonic-gate 			       priv->nic_name);
15987c478bd9Sstevel@tonic-gate 			mdelay(4000);
15997c478bd9Sstevel@tonic-gate 			TLan_PhyFinishAutoNeg(nic);
16007c478bd9Sstevel@tonic-gate 			/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
16017c478bd9Sstevel@tonic-gate 			return;
16027c478bd9Sstevel@tonic-gate 		}
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	}
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	if ((priv->aui) && (priv->phyNum != 0)) {
16077c478bd9Sstevel@tonic-gate 		priv->phyNum = 0;
16087c478bd9Sstevel@tonic-gate 		data =
16097c478bd9Sstevel@tonic-gate 		    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
16107c478bd9Sstevel@tonic-gate 		    TLAN_NET_CFG_PHY_EN;
16117c478bd9Sstevel@tonic-gate 		TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
16127c478bd9Sstevel@tonic-gate 		mdelay(50);
16137c478bd9Sstevel@tonic-gate 		/* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
16147c478bd9Sstevel@tonic-gate 		TLan_PhyPowerDown(nic);
16157c478bd9Sstevel@tonic-gate 		return;
16167c478bd9Sstevel@tonic-gate 	} else if (priv->phyNum == 0) {
16177c478bd9Sstevel@tonic-gate 		control = 0;
16187c478bd9Sstevel@tonic-gate 		TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl);
16197c478bd9Sstevel@tonic-gate 		if (priv->aui) {
16207c478bd9Sstevel@tonic-gate 			tctl |= TLAN_TC_AUISEL;
16217c478bd9Sstevel@tonic-gate 		} else {
16227c478bd9Sstevel@tonic-gate 			tctl &= ~TLAN_TC_AUISEL;
16237c478bd9Sstevel@tonic-gate 			if (priv->duplex == TLAN_DUPLEX_FULL) {
16247c478bd9Sstevel@tonic-gate 				control |= MII_GC_DUPLEX;
16257c478bd9Sstevel@tonic-gate 				priv->tlanFullDuplex = TRUE;
16267c478bd9Sstevel@tonic-gate 			}
16277c478bd9Sstevel@tonic-gate 			if (priv->speed == TLAN_SPEED_100) {
16287c478bd9Sstevel@tonic-gate 				control |= MII_GC_SPEEDSEL;
16297c478bd9Sstevel@tonic-gate 			}
16307c478bd9Sstevel@tonic-gate 		}
16317c478bd9Sstevel@tonic-gate 		TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, control);
16327c478bd9Sstevel@tonic-gate 		TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl);
16337c478bd9Sstevel@tonic-gate 	}
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	/* Wait for 2 sec to give the tranceiver time
16367c478bd9Sstevel@tonic-gate 	 * to establish link.
16377c478bd9Sstevel@tonic-gate 	 */
16387c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */
16397c478bd9Sstevel@tonic-gate 	mdelay(2000);
16407c478bd9Sstevel@tonic-gate 	TLan_FinishReset(nic);
16417c478bd9Sstevel@tonic-gate 
16427c478bd9Sstevel@tonic-gate }				/* TLan_PhyStartLink */
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate void TLan_PhyFinishAutoNeg(struct nic *nic)
16457c478bd9Sstevel@tonic-gate {
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 	u16 an_adv;
16487c478bd9Sstevel@tonic-gate 	u16 an_lpa;
16497c478bd9Sstevel@tonic-gate 	u16 data;
16507c478bd9Sstevel@tonic-gate 	u16 mode;
16517c478bd9Sstevel@tonic-gate 	u16 phy;
16527c478bd9Sstevel@tonic-gate 	u16 status;
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 	phy = priv->phy[priv->phyNum];
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);
16577c478bd9Sstevel@tonic-gate 	udelay(1000);
16587c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);
16597c478bd9Sstevel@tonic-gate 
16607c478bd9Sstevel@tonic-gate 	if (!(status & MII_GS_AUTOCMPLT)) {
16617c478bd9Sstevel@tonic-gate 		/* Wait for 8 sec to give the process
16627c478bd9Sstevel@tonic-gate 		 * more time.  Perhaps we should fail after a while.
16637c478bd9Sstevel@tonic-gate 		 */
16647c478bd9Sstevel@tonic-gate 		if (!priv->neg_be_verbose++) {
16657c478bd9Sstevel@tonic-gate 			printf
16667c478bd9Sstevel@tonic-gate 			    ("TLAN:  Giving autonegotiation more time.\n");
16677c478bd9Sstevel@tonic-gate 			printf
16687c478bd9Sstevel@tonic-gate 			    ("TLAN:  Please check that your adapter has\n");
16697c478bd9Sstevel@tonic-gate 			printf
16707c478bd9Sstevel@tonic-gate 			    ("TLAN:  been properly connected to a HUB or Switch.\n");
16717c478bd9Sstevel@tonic-gate 			printf
16727c478bd9Sstevel@tonic-gate 			    ("TLAN:  Trying to establish link in the background...\n");
16737c478bd9Sstevel@tonic-gate 		}
16747c478bd9Sstevel@tonic-gate 		mdelay(8000);
16757c478bd9Sstevel@tonic-gate 		TLan_PhyFinishAutoNeg(nic);
16767c478bd9Sstevel@tonic-gate 		/* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */
16777c478bd9Sstevel@tonic-gate 		return;
16787c478bd9Sstevel@tonic-gate 	}
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	printf("TLAN: %s: Autonegotiation complete.\n", priv->nic_name);
16817c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_AN_ADV, &an_adv);
16827c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_AN_LPA, &an_lpa);
16837c478bd9Sstevel@tonic-gate 	mode = an_adv & an_lpa & 0x03E0;
16847c478bd9Sstevel@tonic-gate 	if (mode & 0x0100) {
16857c478bd9Sstevel@tonic-gate 		printf("Full Duplex\n");
16867c478bd9Sstevel@tonic-gate 		priv->tlanFullDuplex = TRUE;
16877c478bd9Sstevel@tonic-gate 	} else if (!(mode & 0x0080) && (mode & 0x0040)) {
16887c478bd9Sstevel@tonic-gate 		priv->tlanFullDuplex = TRUE;
16897c478bd9Sstevel@tonic-gate 		printf("Full Duplex\n");
16907c478bd9Sstevel@tonic-gate 	}
16917c478bd9Sstevel@tonic-gate 
16927c478bd9Sstevel@tonic-gate 	if ((!(mode & 0x0180))
16937c478bd9Sstevel@tonic-gate 	    && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10)
16947c478bd9Sstevel@tonic-gate 	    && (priv->phyNum != 0)) {
16957c478bd9Sstevel@tonic-gate 		priv->phyNum = 0;
16967c478bd9Sstevel@tonic-gate 		data =
16977c478bd9Sstevel@tonic-gate 		    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |
16987c478bd9Sstevel@tonic-gate 		    TLAN_NET_CFG_PHY_EN;
16997c478bd9Sstevel@tonic-gate 		TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);
17007c478bd9Sstevel@tonic-gate 		/* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */
17017c478bd9Sstevel@tonic-gate 		mdelay(400);
17027c478bd9Sstevel@tonic-gate 		TLan_PhyPowerDown(nic);
17037c478bd9Sstevel@tonic-gate 		return;
17047c478bd9Sstevel@tonic-gate 	}
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 	if (priv->phyNum == 0) {
17077c478bd9Sstevel@tonic-gate 		if ((priv->duplex == TLAN_DUPLEX_FULL)
17087c478bd9Sstevel@tonic-gate 		    || (an_adv & an_lpa & 0x0040)) {
17097c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL,
17107c478bd9Sstevel@tonic-gate 					 MII_GC_AUTOENB | MII_GC_DUPLEX);
17117c478bd9Sstevel@tonic-gate 			printf
17127c478bd9Sstevel@tonic-gate 			    ("TLAN:  Starting internal PHY with FULL-DUPLEX\n");
17137c478bd9Sstevel@tonic-gate 		} else {
17147c478bd9Sstevel@tonic-gate 			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL,
17157c478bd9Sstevel@tonic-gate 					 MII_GC_AUTOENB);
17167c478bd9Sstevel@tonic-gate 			printf
17177c478bd9Sstevel@tonic-gate 			    ("TLAN:  Starting internal PHY with HALF-DUPLEX\n");
17187c478bd9Sstevel@tonic-gate 		}
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	/* Wait for 100 ms.  No reason in partiticular.
17227c478bd9Sstevel@tonic-gate 	 */
17237c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */
17247c478bd9Sstevel@tonic-gate 	mdelay(100);
17257c478bd9Sstevel@tonic-gate 	TLan_FinishReset(nic);
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate }				/* TLan_PhyFinishAutoNeg */
17287c478bd9Sstevel@tonic-gate 
17297c478bd9Sstevel@tonic-gate #ifdef MONITOR
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	/*********************************************************************
17327c478bd9Sstevel@tonic-gate         *
17337c478bd9Sstevel@tonic-gate         *      TLan_phyMonitor
17347c478bd9Sstevel@tonic-gate         *
17357c478bd9Sstevel@tonic-gate         *      Returns:
17367c478bd9Sstevel@tonic-gate         *              None
17377c478bd9Sstevel@tonic-gate         *
17387c478bd9Sstevel@tonic-gate         *      Params:
17397c478bd9Sstevel@tonic-gate         *              dev             The device structure of this device.
17407c478bd9Sstevel@tonic-gate         *
17417c478bd9Sstevel@tonic-gate         *
17427c478bd9Sstevel@tonic-gate         *      This function monitors PHY condition by reading the status
17437c478bd9Sstevel@tonic-gate         *      register via the MII bus. This can be used to give info
17447c478bd9Sstevel@tonic-gate         *      about link changes (up/down), and possible switch to alternate
17457c478bd9Sstevel@tonic-gate         *      media.
17467c478bd9Sstevel@tonic-gate         *
17477c478bd9Sstevel@tonic-gate         * ******************************************************************/
17487c478bd9Sstevel@tonic-gate 
17497c478bd9Sstevel@tonic-gate void TLan_PhyMonitor(struct net_device *dev)
17507c478bd9Sstevel@tonic-gate {
17517c478bd9Sstevel@tonic-gate 	TLanPrivateInfo *priv = dev->priv;
17527c478bd9Sstevel@tonic-gate 	u16 phy;
17537c478bd9Sstevel@tonic-gate 	u16 phy_status;
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate 	phy = priv->phy[priv->phyNum];
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 	/* Get PHY status register */
17587c478bd9Sstevel@tonic-gate 	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &phy_status);
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 	/* Check if link has been lost */
17617c478bd9Sstevel@tonic-gate 	if (!(phy_status & MII_GS_LINK)) {
17627c478bd9Sstevel@tonic-gate 		if (priv->link) {
17637c478bd9Sstevel@tonic-gate 			priv->link = 0;
17647c478bd9Sstevel@tonic-gate 			printf("TLAN: %s has lost link\n", priv->nic_name);
17657c478bd9Sstevel@tonic-gate 			priv->flags &= ~IFF_RUNNING;
17667c478bd9Sstevel@tonic-gate 			mdelay(2000);
17677c478bd9Sstevel@tonic-gate 			TLan_PhyMonitor(nic);
17687c478bd9Sstevel@tonic-gate 			/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
17697c478bd9Sstevel@tonic-gate 			return;
17707c478bd9Sstevel@tonic-gate 		}
17717c478bd9Sstevel@tonic-gate 	}
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 	/* Link restablished? */
17747c478bd9Sstevel@tonic-gate 	if ((phy_status & MII_GS_LINK) && !priv->link) {
17757c478bd9Sstevel@tonic-gate 		priv->link = 1;
17767c478bd9Sstevel@tonic-gate 		printf("TLAN: %s has reestablished link\n",
17777c478bd9Sstevel@tonic-gate 		       priv->nic_name);
17787c478bd9Sstevel@tonic-gate 		priv->flags |= IFF_RUNNING;
17797c478bd9Sstevel@tonic-gate 	}
17807c478bd9Sstevel@tonic-gate 
17817c478bd9Sstevel@tonic-gate 	/* Setup a new monitor */
17827c478bd9Sstevel@tonic-gate 	/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */
17837c478bd9Sstevel@tonic-gate 	mdelay(2000);
17847c478bd9Sstevel@tonic-gate 	TLan_PhyMonitor(nic);
17857c478bd9Sstevel@tonic-gate }
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate #endif				/* MONITOR */
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate #ifdef EB51
17907c478bd9Sstevel@tonic-gate static struct pci_id tlan_nics[] = {
17917c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP"),
17927c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP"),
17937c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P"),
17947c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P"),
17957c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P"),
17967c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP"),
17977c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP"),
17987c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP"),
17997c478bd9Sstevel@tonic-gate 	PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185"),
18007c478bd9Sstevel@tonic-gate 	PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325"),
18017c478bd9Sstevel@tonic-gate 	PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326"),
18027c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP"),
18037c478bd9Sstevel@tonic-gate 	PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax"),
18047c478bd9Sstevel@tonic-gate };
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate struct pci_driver tlan_driver = {
18077c478bd9Sstevel@tonic-gate 	.type = NIC_DRIVER,
18087c478bd9Sstevel@tonic-gate 	.name = "TLAN/PCI",
18097c478bd9Sstevel@tonic-gate 	.probe = tlan_probe,
18107c478bd9Sstevel@tonic-gate 	.ids = tlan_nics,
18117c478bd9Sstevel@tonic-gate 	.id_count = sizeof(tlan_nics) / sizeof(tlan_nics[0]),
18127c478bd9Sstevel@tonic-gate 	.class = 0,
18137c478bd9Sstevel@tonic-gate };
18147c478bd9Sstevel@tonic-gate #endif
1815