xref: /onnv-gate/usr/src/grub/grub-0.97/netboot/e1000.c (revision 8044:b3af80bbf173)
1*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
2*8044SWilliam.Kucharski@Sun.COM Etherboot -  BOOTP/TFTP Bootstrap Program
3*8044SWilliam.Kucharski@Sun.COM Inter Pro 1000 for Etherboot
4*8044SWilliam.Kucharski@Sun.COM Drivers are port from Intel's Linux driver e1000-4.3.15
5*8044SWilliam.Kucharski@Sun.COM 
6*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
7*8044SWilliam.Kucharski@Sun.COM /*******************************************************************************
8*8044SWilliam.Kucharski@Sun.COM 
9*8044SWilliam.Kucharski@Sun.COM 
10*8044SWilliam.Kucharski@Sun.COM   Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
11*8044SWilliam.Kucharski@Sun.COM 
12*8044SWilliam.Kucharski@Sun.COM   This program is free software; you can redistribute it and/or modify it
13*8044SWilliam.Kucharski@Sun.COM   under the terms of the GNU General Public License as published by the Free
14*8044SWilliam.Kucharski@Sun.COM   Software Foundation; either version 2 of the License, or (at your option)
15*8044SWilliam.Kucharski@Sun.COM   any later version.
16*8044SWilliam.Kucharski@Sun.COM 
17*8044SWilliam.Kucharski@Sun.COM   This program is distributed in the hope that it will be useful, but WITHOUT
18*8044SWilliam.Kucharski@Sun.COM   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*8044SWilliam.Kucharski@Sun.COM   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20*8044SWilliam.Kucharski@Sun.COM   more details.
21*8044SWilliam.Kucharski@Sun.COM 
22*8044SWilliam.Kucharski@Sun.COM   You should have received a copy of the GNU General Public License along with
23*8044SWilliam.Kucharski@Sun.COM   this program; if not, write to the Free Software Foundation, Inc., 59
24*8044SWilliam.Kucharski@Sun.COM   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25*8044SWilliam.Kucharski@Sun.COM 
26*8044SWilliam.Kucharski@Sun.COM   The full GNU General Public License is included in this distribution in the
27*8044SWilliam.Kucharski@Sun.COM   file called LICENSE.
28*8044SWilliam.Kucharski@Sun.COM 
29*8044SWilliam.Kucharski@Sun.COM   Contact Information:
30*8044SWilliam.Kucharski@Sun.COM   Linux NICS <linux.nics@intel.com>
31*8044SWilliam.Kucharski@Sun.COM   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32*8044SWilliam.Kucharski@Sun.COM 
33*8044SWilliam.Kucharski@Sun.COM *******************************************************************************/
34*8044SWilliam.Kucharski@Sun.COM /*
35*8044SWilliam.Kucharski@Sun.COM  *  Copyright (C) Archway Digital Solutions.
36*8044SWilliam.Kucharski@Sun.COM  *
37*8044SWilliam.Kucharski@Sun.COM  *  written by Chrsitopher Li <cli at arcyway dot com> or <chrisl at gnuchina dot org>
38*8044SWilliam.Kucharski@Sun.COM  *  2/9/2002
39*8044SWilliam.Kucharski@Sun.COM  *
40*8044SWilliam.Kucharski@Sun.COM  *  Copyright (C) Linux Networx.
41*8044SWilliam.Kucharski@Sun.COM  *  Massive upgrade to work with the new intel gigabit NICs.
42*8044SWilliam.Kucharski@Sun.COM  *  <ebiederman at lnxi dot com>
43*8044SWilliam.Kucharski@Sun.COM  *
44*8044SWilliam.Kucharski@Sun.COM  *  Support for 82541ei & 82547ei chips from Intel's Linux driver 5.1.13 added by
45*8044SWilliam.Kucharski@Sun.COM  *  Georg Baum <gbaum@users.sf.net>, sponsored by PetaMem GmbH and linkLINE Communications, Inc.
46*8044SWilliam.Kucharski@Sun.COM  *
47*8044SWilliam.Kucharski@Sun.COM  *  01/2004: Updated to Linux driver 5.2.22 by Georg Baum <gbaum@users.sf.net>
48*8044SWilliam.Kucharski@Sun.COM  */
49*8044SWilliam.Kucharski@Sun.COM 
50*8044SWilliam.Kucharski@Sun.COM /* to get some global routines like printf */
51*8044SWilliam.Kucharski@Sun.COM #include "etherboot.h"
52*8044SWilliam.Kucharski@Sun.COM /* to get the interface to the body of the program */
53*8044SWilliam.Kucharski@Sun.COM #include "nic.h"
54*8044SWilliam.Kucharski@Sun.COM /* to get the PCI support functions, if this is a PCI NIC */
55*8044SWilliam.Kucharski@Sun.COM #include "pci.h"
56*8044SWilliam.Kucharski@Sun.COM #include "timer.h"
57*8044SWilliam.Kucharski@Sun.COM 
58*8044SWilliam.Kucharski@Sun.COM typedef unsigned char *dma_addr_t;
59*8044SWilliam.Kucharski@Sun.COM 
60*8044SWilliam.Kucharski@Sun.COM typedef enum {
61*8044SWilliam.Kucharski@Sun.COM 	FALSE = 0,
62*8044SWilliam.Kucharski@Sun.COM 	TRUE = 1
63*8044SWilliam.Kucharski@Sun.COM } boolean_t;
64*8044SWilliam.Kucharski@Sun.COM 
65*8044SWilliam.Kucharski@Sun.COM #define DEBUG 0
66*8044SWilliam.Kucharski@Sun.COM 
67*8044SWilliam.Kucharski@Sun.COM 
68*8044SWilliam.Kucharski@Sun.COM /* Some pieces of code are disabled with #if 0 ... #endif.
69*8044SWilliam.Kucharski@Sun.COM  * They are not deleted to show where the etherboot driver differs
70*8044SWilliam.Kucharski@Sun.COM  * from the linux driver below the function level.
71*8044SWilliam.Kucharski@Sun.COM  * Some member variables of the hw struct have been eliminated
72*8044SWilliam.Kucharski@Sun.COM  * and the corresponding inplace checks inserted instead.
73*8044SWilliam.Kucharski@Sun.COM  * Pieces such as LED handling that we definitely don't need are deleted.
74*8044SWilliam.Kucharski@Sun.COM  *
75*8044SWilliam.Kucharski@Sun.COM  * The following defines should not be needed normally,
76*8044SWilliam.Kucharski@Sun.COM  * but may be helpful for debugging purposes. */
77*8044SWilliam.Kucharski@Sun.COM 
78*8044SWilliam.Kucharski@Sun.COM /* Define this if you want to program the transmission control register
79*8044SWilliam.Kucharski@Sun.COM  * the way the Linux driver does it. */
80*8044SWilliam.Kucharski@Sun.COM #undef LINUX_DRIVER_TCTL
81*8044SWilliam.Kucharski@Sun.COM 
82*8044SWilliam.Kucharski@Sun.COM /* Define this to behave more like the Linux driver. */
83*8044SWilliam.Kucharski@Sun.COM #undef LINUX_DRIVER
84*8044SWilliam.Kucharski@Sun.COM 
85*8044SWilliam.Kucharski@Sun.COM #include "e1000_hw.h"
86*8044SWilliam.Kucharski@Sun.COM 
87*8044SWilliam.Kucharski@Sun.COM /* NIC specific static variables go here */
88*8044SWilliam.Kucharski@Sun.COM static struct e1000_hw hw;
89*8044SWilliam.Kucharski@Sun.COM static char tx_pool[128 + 16];
90*8044SWilliam.Kucharski@Sun.COM static char rx_pool[128 + 16];
91*8044SWilliam.Kucharski@Sun.COM static char packet[2096];
92*8044SWilliam.Kucharski@Sun.COM 
93*8044SWilliam.Kucharski@Sun.COM static struct e1000_tx_desc *tx_base;
94*8044SWilliam.Kucharski@Sun.COM static struct e1000_rx_desc *rx_base;
95*8044SWilliam.Kucharski@Sun.COM 
96*8044SWilliam.Kucharski@Sun.COM static int tx_tail;
97*8044SWilliam.Kucharski@Sun.COM static int rx_tail, rx_last;
98*8044SWilliam.Kucharski@Sun.COM 
99*8044SWilliam.Kucharski@Sun.COM /* Function forward declarations */
100*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_link(struct e1000_hw *hw);
101*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
102*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_copper_link(struct e1000_hw *hw);
103*8044SWilliam.Kucharski@Sun.COM static int e1000_phy_setup_autoneg(struct e1000_hw *hw);
104*8044SWilliam.Kucharski@Sun.COM static void e1000_config_collision_dist(struct e1000_hw *hw);
105*8044SWilliam.Kucharski@Sun.COM static int e1000_config_mac_to_phy(struct e1000_hw *hw);
106*8044SWilliam.Kucharski@Sun.COM static int e1000_config_fc_after_link_up(struct e1000_hw *hw);
107*8044SWilliam.Kucharski@Sun.COM static int e1000_check_for_link(struct e1000_hw *hw);
108*8044SWilliam.Kucharski@Sun.COM static int e1000_wait_autoneg(struct e1000_hw *hw);
109*8044SWilliam.Kucharski@Sun.COM static void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex);
110*8044SWilliam.Kucharski@Sun.COM static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
111*8044SWilliam.Kucharski@Sun.COM static int e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
112*8044SWilliam.Kucharski@Sun.COM static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data);
113*8044SWilliam.Kucharski@Sun.COM static int e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data);
114*8044SWilliam.Kucharski@Sun.COM static void e1000_phy_hw_reset(struct e1000_hw *hw);
115*8044SWilliam.Kucharski@Sun.COM static int e1000_phy_reset(struct e1000_hw *hw);
116*8044SWilliam.Kucharski@Sun.COM static int e1000_detect_gig_phy(struct e1000_hw *hw);
117*8044SWilliam.Kucharski@Sun.COM 
118*8044SWilliam.Kucharski@Sun.COM /* Printing macros... */
119*8044SWilliam.Kucharski@Sun.COM 
120*8044SWilliam.Kucharski@Sun.COM #define E1000_ERR(args...) printf("e1000: " args)
121*8044SWilliam.Kucharski@Sun.COM 
122*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 3
123*8044SWilliam.Kucharski@Sun.COM #define E1000_DBG(args...) printf("e1000: " args)
124*8044SWilliam.Kucharski@Sun.COM #else
125*8044SWilliam.Kucharski@Sun.COM #define E1000_DBG(args...)
126*8044SWilliam.Kucharski@Sun.COM #endif
127*8044SWilliam.Kucharski@Sun.COM 
128*8044SWilliam.Kucharski@Sun.COM #define MSGOUT(S, A, B)     printk(S "\n", A, B)
129*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 2
130*8044SWilliam.Kucharski@Sun.COM #define DEBUGFUNC(F)        DEBUGOUT(F "\n");
131*8044SWilliam.Kucharski@Sun.COM #else
132*8044SWilliam.Kucharski@Sun.COM #define DEBUGFUNC(F)
133*8044SWilliam.Kucharski@Sun.COM #endif
134*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 1
135*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT(S) printf(S)
136*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT1(S,A) printf(S,A)
137*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT2(S,A,B) printf(S,A,B)
138*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT3(S,A,B,C) printf(S,A,B,C)
139*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT7(S,A,B,C,D,E,F,G) printf(S,A,B,C,D,E,F,G)
140*8044SWilliam.Kucharski@Sun.COM #else
141*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT(S)
142*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT1(S,A)
143*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT2(S,A,B)
144*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT3(S,A,B,C)
145*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT7(S,A,B,C,D,E,F,G)
146*8044SWilliam.Kucharski@Sun.COM #endif
147*8044SWilliam.Kucharski@Sun.COM 
148*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_REG(a, reg, value) ( \
149*8044SWilliam.Kucharski@Sun.COM     ((a)->mac_type >= e1000_82543) ? \
150*8044SWilliam.Kucharski@Sun.COM         (writel((value), ((a)->hw_addr + E1000_##reg))) : \
151*8044SWilliam.Kucharski@Sun.COM         (writel((value), ((a)->hw_addr + E1000_82542_##reg))))
152*8044SWilliam.Kucharski@Sun.COM 
153*8044SWilliam.Kucharski@Sun.COM #define E1000_READ_REG(a, reg) ( \
154*8044SWilliam.Kucharski@Sun.COM     ((a)->mac_type >= e1000_82543) ? \
155*8044SWilliam.Kucharski@Sun.COM         readl((a)->hw_addr + E1000_##reg) : \
156*8044SWilliam.Kucharski@Sun.COM         readl((a)->hw_addr + E1000_82542_##reg))
157*8044SWilliam.Kucharski@Sun.COM 
158*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
159*8044SWilliam.Kucharski@Sun.COM     ((a)->mac_type >= e1000_82543) ? \
160*8044SWilliam.Kucharski@Sun.COM         writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2))) : \
161*8044SWilliam.Kucharski@Sun.COM         writel((value), ((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))))
162*8044SWilliam.Kucharski@Sun.COM 
163*8044SWilliam.Kucharski@Sun.COM #define E1000_READ_REG_ARRAY(a, reg, offset) ( \
164*8044SWilliam.Kucharski@Sun.COM     ((a)->mac_type >= e1000_82543) ? \
165*8044SWilliam.Kucharski@Sun.COM         readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \
166*8044SWilliam.Kucharski@Sun.COM         readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))
167*8044SWilliam.Kucharski@Sun.COM 
168*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);}
169*8044SWilliam.Kucharski@Sun.COM 
170*8044SWilliam.Kucharski@Sun.COM uint32_t
e1000_io_read(struct e1000_hw * hw __unused,uint32_t port)171*8044SWilliam.Kucharski@Sun.COM e1000_io_read(struct e1000_hw *hw __unused, uint32_t port)
172*8044SWilliam.Kucharski@Sun.COM {
173*8044SWilliam.Kucharski@Sun.COM         return inl(port);
174*8044SWilliam.Kucharski@Sun.COM }
175*8044SWilliam.Kucharski@Sun.COM 
176*8044SWilliam.Kucharski@Sun.COM void
e1000_io_write(struct e1000_hw * hw __unused,uint32_t port,uint32_t value)177*8044SWilliam.Kucharski@Sun.COM e1000_io_write(struct e1000_hw *hw __unused, uint32_t port, uint32_t value)
178*8044SWilliam.Kucharski@Sun.COM {
179*8044SWilliam.Kucharski@Sun.COM         outl(value, port);
180*8044SWilliam.Kucharski@Sun.COM }
181*8044SWilliam.Kucharski@Sun.COM 
e1000_pci_set_mwi(struct e1000_hw * hw)182*8044SWilliam.Kucharski@Sun.COM static inline void e1000_pci_set_mwi(struct e1000_hw *hw)
183*8044SWilliam.Kucharski@Sun.COM {
184*8044SWilliam.Kucharski@Sun.COM 	pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
185*8044SWilliam.Kucharski@Sun.COM }
186*8044SWilliam.Kucharski@Sun.COM 
e1000_pci_clear_mwi(struct e1000_hw * hw)187*8044SWilliam.Kucharski@Sun.COM static inline void e1000_pci_clear_mwi(struct e1000_hw *hw)
188*8044SWilliam.Kucharski@Sun.COM {
189*8044SWilliam.Kucharski@Sun.COM 	pci_write_config_word(hw->pdev, PCI_COMMAND,
190*8044SWilliam.Kucharski@Sun.COM 			      hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
191*8044SWilliam.Kucharski@Sun.COM }
192*8044SWilliam.Kucharski@Sun.COM 
193*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
194*8044SWilliam.Kucharski@Sun.COM  * Raises the EEPROM's clock input.
195*8044SWilliam.Kucharski@Sun.COM  *
196*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
197*8044SWilliam.Kucharski@Sun.COM  * eecd - EECD's current value
198*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
199*8044SWilliam.Kucharski@Sun.COM static void
e1000_raise_ee_clk(struct e1000_hw * hw,uint32_t * eecd)200*8044SWilliam.Kucharski@Sun.COM e1000_raise_ee_clk(struct e1000_hw *hw,
201*8044SWilliam.Kucharski@Sun.COM                    uint32_t *eecd)
202*8044SWilliam.Kucharski@Sun.COM {
203*8044SWilliam.Kucharski@Sun.COM 	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
204*8044SWilliam.Kucharski@Sun.COM 	 * wait <delay> microseconds.
205*8044SWilliam.Kucharski@Sun.COM 	 */
206*8044SWilliam.Kucharski@Sun.COM 	*eecd = *eecd | E1000_EECD_SK;
207*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, EECD, *eecd);
208*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
209*8044SWilliam.Kucharski@Sun.COM 	udelay(hw->eeprom.delay_usec);
210*8044SWilliam.Kucharski@Sun.COM }
211*8044SWilliam.Kucharski@Sun.COM 
212*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
213*8044SWilliam.Kucharski@Sun.COM  * Lowers the EEPROM's clock input.
214*8044SWilliam.Kucharski@Sun.COM  *
215*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
216*8044SWilliam.Kucharski@Sun.COM  * eecd - EECD's current value
217*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
218*8044SWilliam.Kucharski@Sun.COM static void
e1000_lower_ee_clk(struct e1000_hw * hw,uint32_t * eecd)219*8044SWilliam.Kucharski@Sun.COM e1000_lower_ee_clk(struct e1000_hw *hw,
220*8044SWilliam.Kucharski@Sun.COM                    uint32_t *eecd)
221*8044SWilliam.Kucharski@Sun.COM {
222*8044SWilliam.Kucharski@Sun.COM 	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
223*8044SWilliam.Kucharski@Sun.COM 	 * wait 50 microseconds.
224*8044SWilliam.Kucharski@Sun.COM 	 */
225*8044SWilliam.Kucharski@Sun.COM 	*eecd = *eecd & ~E1000_EECD_SK;
226*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, EECD, *eecd);
227*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
228*8044SWilliam.Kucharski@Sun.COM 	udelay(hw->eeprom.delay_usec);
229*8044SWilliam.Kucharski@Sun.COM }
230*8044SWilliam.Kucharski@Sun.COM 
231*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
232*8044SWilliam.Kucharski@Sun.COM  * Shift data bits out to the EEPROM.
233*8044SWilliam.Kucharski@Sun.COM  *
234*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
235*8044SWilliam.Kucharski@Sun.COM  * data - data to send to the EEPROM
236*8044SWilliam.Kucharski@Sun.COM  * count - number of bits to shift out
237*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
238*8044SWilliam.Kucharski@Sun.COM static void
e1000_shift_out_ee_bits(struct e1000_hw * hw,uint16_t data,uint16_t count)239*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(struct e1000_hw *hw,
240*8044SWilliam.Kucharski@Sun.COM                         uint16_t data,
241*8044SWilliam.Kucharski@Sun.COM                         uint16_t count)
242*8044SWilliam.Kucharski@Sun.COM {
243*8044SWilliam.Kucharski@Sun.COM 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
244*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd;
245*8044SWilliam.Kucharski@Sun.COM 	uint32_t mask;
246*8044SWilliam.Kucharski@Sun.COM 
247*8044SWilliam.Kucharski@Sun.COM 	/* We need to shift "count" bits out to the EEPROM. So, value in the
248*8044SWilliam.Kucharski@Sun.COM 	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
249*8044SWilliam.Kucharski@Sun.COM 	 * In order to do this, "data" must be broken down into bits.
250*8044SWilliam.Kucharski@Sun.COM 	 */
251*8044SWilliam.Kucharski@Sun.COM 	mask = 0x01 << (count - 1);
252*8044SWilliam.Kucharski@Sun.COM 	eecd = E1000_READ_REG(hw, EECD);
253*8044SWilliam.Kucharski@Sun.COM 	if (eeprom->type == e1000_eeprom_microwire) {
254*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_DO;
255*8044SWilliam.Kucharski@Sun.COM 	} else if (eeprom->type == e1000_eeprom_spi) {
256*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_DO;
257*8044SWilliam.Kucharski@Sun.COM 	}
258*8044SWilliam.Kucharski@Sun.COM 	do {
259*8044SWilliam.Kucharski@Sun.COM 		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
260*8044SWilliam.Kucharski@Sun.COM 		 * and then raising and then lowering the clock (the SK bit controls
261*8044SWilliam.Kucharski@Sun.COM 		 * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
262*8044SWilliam.Kucharski@Sun.COM 		 * by setting "DI" to "0" and then raising and then lowering the clock.
263*8044SWilliam.Kucharski@Sun.COM 		 */
264*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_DI;
265*8044SWilliam.Kucharski@Sun.COM 
266*8044SWilliam.Kucharski@Sun.COM 		if(data & mask)
267*8044SWilliam.Kucharski@Sun.COM 			eecd |= E1000_EECD_DI;
268*8044SWilliam.Kucharski@Sun.COM 
269*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
270*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
271*8044SWilliam.Kucharski@Sun.COM 
272*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
273*8044SWilliam.Kucharski@Sun.COM 
274*8044SWilliam.Kucharski@Sun.COM 		e1000_raise_ee_clk(hw, &eecd);
275*8044SWilliam.Kucharski@Sun.COM 		e1000_lower_ee_clk(hw, &eecd);
276*8044SWilliam.Kucharski@Sun.COM 
277*8044SWilliam.Kucharski@Sun.COM 		mask = mask >> 1;
278*8044SWilliam.Kucharski@Sun.COM 
279*8044SWilliam.Kucharski@Sun.COM 	} while(mask);
280*8044SWilliam.Kucharski@Sun.COM 
281*8044SWilliam.Kucharski@Sun.COM 	/* We leave the "DI" bit set to "0" when we leave this routine. */
282*8044SWilliam.Kucharski@Sun.COM 	eecd &= ~E1000_EECD_DI;
283*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, EECD, eecd);
284*8044SWilliam.Kucharski@Sun.COM }
285*8044SWilliam.Kucharski@Sun.COM 
286*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
287*8044SWilliam.Kucharski@Sun.COM  * Shift data bits in from the EEPROM
288*8044SWilliam.Kucharski@Sun.COM  *
289*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
290*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
291*8044SWilliam.Kucharski@Sun.COM static uint16_t
e1000_shift_in_ee_bits(struct e1000_hw * hw,uint16_t count)292*8044SWilliam.Kucharski@Sun.COM e1000_shift_in_ee_bits(struct e1000_hw *hw,
293*8044SWilliam.Kucharski@Sun.COM                        uint16_t count)
294*8044SWilliam.Kucharski@Sun.COM {
295*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd;
296*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
297*8044SWilliam.Kucharski@Sun.COM 	uint16_t data;
298*8044SWilliam.Kucharski@Sun.COM 
299*8044SWilliam.Kucharski@Sun.COM 	/* In order to read a register from the EEPROM, we need to shift 'count'
300*8044SWilliam.Kucharski@Sun.COM 	 * bits in from the EEPROM. Bits are "shifted in" by raising the clock
301*8044SWilliam.Kucharski@Sun.COM 	 * input to the EEPROM (setting the SK bit), and then reading the value of
302*8044SWilliam.Kucharski@Sun.COM 	 * the "DO" bit.  During this "shifting in" process the "DI" bit should
303*8044SWilliam.Kucharski@Sun.COM 	 * always be clear.
304*8044SWilliam.Kucharski@Sun.COM 	 */
305*8044SWilliam.Kucharski@Sun.COM 
306*8044SWilliam.Kucharski@Sun.COM 	eecd = E1000_READ_REG(hw, EECD);
307*8044SWilliam.Kucharski@Sun.COM 
308*8044SWilliam.Kucharski@Sun.COM 	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
309*8044SWilliam.Kucharski@Sun.COM 	data = 0;
310*8044SWilliam.Kucharski@Sun.COM 
311*8044SWilliam.Kucharski@Sun.COM 	for(i = 0; i < count; i++) {
312*8044SWilliam.Kucharski@Sun.COM 		data = data << 1;
313*8044SWilliam.Kucharski@Sun.COM 		e1000_raise_ee_clk(hw, &eecd);
314*8044SWilliam.Kucharski@Sun.COM 
315*8044SWilliam.Kucharski@Sun.COM 		eecd = E1000_READ_REG(hw, EECD);
316*8044SWilliam.Kucharski@Sun.COM 
317*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~(E1000_EECD_DI);
318*8044SWilliam.Kucharski@Sun.COM 		if(eecd & E1000_EECD_DO)
319*8044SWilliam.Kucharski@Sun.COM 			data |= 1;
320*8044SWilliam.Kucharski@Sun.COM 
321*8044SWilliam.Kucharski@Sun.COM 		e1000_lower_ee_clk(hw, &eecd);
322*8044SWilliam.Kucharski@Sun.COM 	}
323*8044SWilliam.Kucharski@Sun.COM 
324*8044SWilliam.Kucharski@Sun.COM 	return data;
325*8044SWilliam.Kucharski@Sun.COM }
326*8044SWilliam.Kucharski@Sun.COM 
327*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
328*8044SWilliam.Kucharski@Sun.COM  * Prepares EEPROM for access
329*8044SWilliam.Kucharski@Sun.COM  *
330*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
331*8044SWilliam.Kucharski@Sun.COM  *
332*8044SWilliam.Kucharski@Sun.COM  * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
333*8044SWilliam.Kucharski@Sun.COM  * function should be called before issuing a command to the EEPROM.
334*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
335*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_acquire_eeprom(struct e1000_hw * hw)336*8044SWilliam.Kucharski@Sun.COM e1000_acquire_eeprom(struct e1000_hw *hw)
337*8044SWilliam.Kucharski@Sun.COM {
338*8044SWilliam.Kucharski@Sun.COM 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
339*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd, i=0;
340*8044SWilliam.Kucharski@Sun.COM 
341*8044SWilliam.Kucharski@Sun.COM 	eecd = E1000_READ_REG(hw, EECD);
342*8044SWilliam.Kucharski@Sun.COM 
343*8044SWilliam.Kucharski@Sun.COM 	/* Request EEPROM Access */
344*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82544) {
345*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_REQ;
346*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
347*8044SWilliam.Kucharski@Sun.COM 		eecd = E1000_READ_REG(hw, EECD);
348*8044SWilliam.Kucharski@Sun.COM 		while((!(eecd & E1000_EECD_GNT)) &&
349*8044SWilliam.Kucharski@Sun.COM 		      (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
350*8044SWilliam.Kucharski@Sun.COM 			i++;
351*8044SWilliam.Kucharski@Sun.COM 			udelay(5);
352*8044SWilliam.Kucharski@Sun.COM 			eecd = E1000_READ_REG(hw, EECD);
353*8044SWilliam.Kucharski@Sun.COM 		}
354*8044SWilliam.Kucharski@Sun.COM 		if(!(eecd & E1000_EECD_GNT)) {
355*8044SWilliam.Kucharski@Sun.COM 			eecd &= ~E1000_EECD_REQ;
356*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, EECD, eecd);
357*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Could not acquire EEPROM grant\n");
358*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_EEPROM;
359*8044SWilliam.Kucharski@Sun.COM 		}
360*8044SWilliam.Kucharski@Sun.COM 	}
361*8044SWilliam.Kucharski@Sun.COM 
362*8044SWilliam.Kucharski@Sun.COM 	/* Setup EEPROM for Read/Write */
363*8044SWilliam.Kucharski@Sun.COM 
364*8044SWilliam.Kucharski@Sun.COM 	if (eeprom->type == e1000_eeprom_microwire) {
365*8044SWilliam.Kucharski@Sun.COM 		/* Clear SK and DI */
366*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
367*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
368*8044SWilliam.Kucharski@Sun.COM 
369*8044SWilliam.Kucharski@Sun.COM 		/* Set CS */
370*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_CS;
371*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
372*8044SWilliam.Kucharski@Sun.COM 	} else if (eeprom->type == e1000_eeprom_spi) {
373*8044SWilliam.Kucharski@Sun.COM 		/* Clear SK and CS */
374*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
375*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
376*8044SWilliam.Kucharski@Sun.COM 		udelay(1);
377*8044SWilliam.Kucharski@Sun.COM 	}
378*8044SWilliam.Kucharski@Sun.COM 
379*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
380*8044SWilliam.Kucharski@Sun.COM }
381*8044SWilliam.Kucharski@Sun.COM 
382*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
383*8044SWilliam.Kucharski@Sun.COM  * Returns EEPROM to a "standby" state
384*8044SWilliam.Kucharski@Sun.COM  *
385*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
386*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
387*8044SWilliam.Kucharski@Sun.COM static void
e1000_standby_eeprom(struct e1000_hw * hw)388*8044SWilliam.Kucharski@Sun.COM e1000_standby_eeprom(struct e1000_hw *hw)
389*8044SWilliam.Kucharski@Sun.COM {
390*8044SWilliam.Kucharski@Sun.COM 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
391*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd;
392*8044SWilliam.Kucharski@Sun.COM 
393*8044SWilliam.Kucharski@Sun.COM 	eecd = E1000_READ_REG(hw, EECD);
394*8044SWilliam.Kucharski@Sun.COM 
395*8044SWilliam.Kucharski@Sun.COM 	if(eeprom->type == e1000_eeprom_microwire) {
396*8044SWilliam.Kucharski@Sun.COM 
397*8044SWilliam.Kucharski@Sun.COM 		/* Deselect EEPROM */
398*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
399*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
400*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
401*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
402*8044SWilliam.Kucharski@Sun.COM 
403*8044SWilliam.Kucharski@Sun.COM 		/* Clock high */
404*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_SK;
405*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
406*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
407*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
408*8044SWilliam.Kucharski@Sun.COM 
409*8044SWilliam.Kucharski@Sun.COM 		/* Select EEPROM */
410*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_CS;
411*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
412*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
413*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
414*8044SWilliam.Kucharski@Sun.COM 
415*8044SWilliam.Kucharski@Sun.COM 		/* Clock low */
416*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_SK;
417*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
418*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
419*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
420*8044SWilliam.Kucharski@Sun.COM 	} else if(eeprom->type == e1000_eeprom_spi) {
421*8044SWilliam.Kucharski@Sun.COM 		/* Toggle CS to flush commands */
422*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_CS;
423*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
424*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
425*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
426*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_CS;
427*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
428*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
429*8044SWilliam.Kucharski@Sun.COM 		udelay(eeprom->delay_usec);
430*8044SWilliam.Kucharski@Sun.COM 	}
431*8044SWilliam.Kucharski@Sun.COM }
432*8044SWilliam.Kucharski@Sun.COM 
433*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
434*8044SWilliam.Kucharski@Sun.COM  * Terminates a command by inverting the EEPROM's chip select pin
435*8044SWilliam.Kucharski@Sun.COM  *
436*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
437*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
438*8044SWilliam.Kucharski@Sun.COM static void
e1000_release_eeprom(struct e1000_hw * hw)439*8044SWilliam.Kucharski@Sun.COM e1000_release_eeprom(struct e1000_hw *hw)
440*8044SWilliam.Kucharski@Sun.COM {
441*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd;
442*8044SWilliam.Kucharski@Sun.COM 
443*8044SWilliam.Kucharski@Sun.COM 	eecd = E1000_READ_REG(hw, EECD);
444*8044SWilliam.Kucharski@Sun.COM 
445*8044SWilliam.Kucharski@Sun.COM 	if (hw->eeprom.type == e1000_eeprom_spi) {
446*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_CS;  /* Pull CS high */
447*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_SK; /* Lower SCK */
448*8044SWilliam.Kucharski@Sun.COM 
449*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
450*8044SWilliam.Kucharski@Sun.COM 
451*8044SWilliam.Kucharski@Sun.COM 		udelay(hw->eeprom.delay_usec);
452*8044SWilliam.Kucharski@Sun.COM 	} else if(hw->eeprom.type == e1000_eeprom_microwire) {
453*8044SWilliam.Kucharski@Sun.COM 		/* cleanup eeprom */
454*8044SWilliam.Kucharski@Sun.COM 
455*8044SWilliam.Kucharski@Sun.COM 		/* CS on Microwire is active-high */
456*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
457*8044SWilliam.Kucharski@Sun.COM 
458*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
459*8044SWilliam.Kucharski@Sun.COM 
460*8044SWilliam.Kucharski@Sun.COM 		/* Rising edge of clock */
461*8044SWilliam.Kucharski@Sun.COM 		eecd |= E1000_EECD_SK;
462*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
463*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
464*8044SWilliam.Kucharski@Sun.COM 		udelay(hw->eeprom.delay_usec);
465*8044SWilliam.Kucharski@Sun.COM 
466*8044SWilliam.Kucharski@Sun.COM 		/* Falling edge of clock */
467*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_SK;
468*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
469*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
470*8044SWilliam.Kucharski@Sun.COM 		udelay(hw->eeprom.delay_usec);
471*8044SWilliam.Kucharski@Sun.COM 	}
472*8044SWilliam.Kucharski@Sun.COM 
473*8044SWilliam.Kucharski@Sun.COM 	/* Stop requesting EEPROM access */
474*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82544) {
475*8044SWilliam.Kucharski@Sun.COM 		eecd &= ~E1000_EECD_REQ;
476*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, EECD, eecd);
477*8044SWilliam.Kucharski@Sun.COM 	}
478*8044SWilliam.Kucharski@Sun.COM }
479*8044SWilliam.Kucharski@Sun.COM 
480*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
481*8044SWilliam.Kucharski@Sun.COM  * Reads a 16 bit word from the EEPROM.
482*8044SWilliam.Kucharski@Sun.COM  *
483*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
484*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
485*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_spi_eeprom_ready(struct e1000_hw * hw)486*8044SWilliam.Kucharski@Sun.COM e1000_spi_eeprom_ready(struct e1000_hw *hw)
487*8044SWilliam.Kucharski@Sun.COM {
488*8044SWilliam.Kucharski@Sun.COM 	uint16_t retry_count = 0;
489*8044SWilliam.Kucharski@Sun.COM 	uint8_t spi_stat_reg;
490*8044SWilliam.Kucharski@Sun.COM 
491*8044SWilliam.Kucharski@Sun.COM 	/* Read "Status Register" repeatedly until the LSB is cleared.  The
492*8044SWilliam.Kucharski@Sun.COM 	 * EEPROM will signal that the command has been completed by clearing
493*8044SWilliam.Kucharski@Sun.COM 	 * bit 0 of the internal status register.  If it's not cleared within
494*8044SWilliam.Kucharski@Sun.COM 	 * 5 milliseconds, then error out.
495*8044SWilliam.Kucharski@Sun.COM 	 */
496*8044SWilliam.Kucharski@Sun.COM 	retry_count = 0;
497*8044SWilliam.Kucharski@Sun.COM 	do {
498*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
499*8044SWilliam.Kucharski@Sun.COM 		hw->eeprom.opcode_bits);
500*8044SWilliam.Kucharski@Sun.COM 		spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
501*8044SWilliam.Kucharski@Sun.COM 		if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
502*8044SWilliam.Kucharski@Sun.COM 			break;
503*8044SWilliam.Kucharski@Sun.COM 
504*8044SWilliam.Kucharski@Sun.COM 		udelay(5);
505*8044SWilliam.Kucharski@Sun.COM 		retry_count += 5;
506*8044SWilliam.Kucharski@Sun.COM 
507*8044SWilliam.Kucharski@Sun.COM 	} while(retry_count < EEPROM_MAX_RETRY_SPI);
508*8044SWilliam.Kucharski@Sun.COM 
509*8044SWilliam.Kucharski@Sun.COM 	/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
510*8044SWilliam.Kucharski@Sun.COM 	 * only 0-5mSec on 5V devices)
511*8044SWilliam.Kucharski@Sun.COM 	 */
512*8044SWilliam.Kucharski@Sun.COM 	if(retry_count >= EEPROM_MAX_RETRY_SPI) {
513*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("SPI EEPROM Status error\n");
514*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_EEPROM;
515*8044SWilliam.Kucharski@Sun.COM 	}
516*8044SWilliam.Kucharski@Sun.COM 
517*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
518*8044SWilliam.Kucharski@Sun.COM }
519*8044SWilliam.Kucharski@Sun.COM 
520*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
521*8044SWilliam.Kucharski@Sun.COM  * Reads a 16 bit word from the EEPROM.
522*8044SWilliam.Kucharski@Sun.COM  *
523*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
524*8044SWilliam.Kucharski@Sun.COM  * offset - offset of  word in the EEPROM to read
525*8044SWilliam.Kucharski@Sun.COM  * data - word read from the EEPROM
526*8044SWilliam.Kucharski@Sun.COM  * words - number of words to read
527*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
528*8044SWilliam.Kucharski@Sun.COM static int
e1000_read_eeprom(struct e1000_hw * hw,uint16_t offset,uint16_t words,uint16_t * data)529*8044SWilliam.Kucharski@Sun.COM e1000_read_eeprom(struct e1000_hw *hw,
530*8044SWilliam.Kucharski@Sun.COM                   uint16_t offset,
531*8044SWilliam.Kucharski@Sun.COM 		  uint16_t words,
532*8044SWilliam.Kucharski@Sun.COM                   uint16_t *data)
533*8044SWilliam.Kucharski@Sun.COM {
534*8044SWilliam.Kucharski@Sun.COM 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
535*8044SWilliam.Kucharski@Sun.COM 	uint32_t i = 0;
536*8044SWilliam.Kucharski@Sun.COM 
537*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_read_eeprom");
538*8044SWilliam.Kucharski@Sun.COM 
539*8044SWilliam.Kucharski@Sun.COM 	/* A check for invalid values:  offset too large, too many words, and not
540*8044SWilliam.Kucharski@Sun.COM 	 * enough words.
541*8044SWilliam.Kucharski@Sun.COM 	 */
542*8044SWilliam.Kucharski@Sun.COM 	if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
543*8044SWilliam.Kucharski@Sun.COM 	   (words == 0)) {
544*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("\"words\" parameter out of bounds\n");
545*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_EEPROM;
546*8044SWilliam.Kucharski@Sun.COM 	}
547*8044SWilliam.Kucharski@Sun.COM 
548*8044SWilliam.Kucharski@Sun.COM 	/*  Prepare the EEPROM for reading  */
549*8044SWilliam.Kucharski@Sun.COM 	if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
550*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_EEPROM;
551*8044SWilliam.Kucharski@Sun.COM 
552*8044SWilliam.Kucharski@Sun.COM 	if(eeprom->type == e1000_eeprom_spi) {
553*8044SWilliam.Kucharski@Sun.COM 		uint16_t word_in;
554*8044SWilliam.Kucharski@Sun.COM 		uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
555*8044SWilliam.Kucharski@Sun.COM 
556*8044SWilliam.Kucharski@Sun.COM 		if(e1000_spi_eeprom_ready(hw)) {
557*8044SWilliam.Kucharski@Sun.COM 			e1000_release_eeprom(hw);
558*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_EEPROM;
559*8044SWilliam.Kucharski@Sun.COM 		}
560*8044SWilliam.Kucharski@Sun.COM 
561*8044SWilliam.Kucharski@Sun.COM 		e1000_standby_eeprom(hw);
562*8044SWilliam.Kucharski@Sun.COM 
563*8044SWilliam.Kucharski@Sun.COM 		/* Some SPI eeproms use the 8th address bit embedded in the opcode */
564*8044SWilliam.Kucharski@Sun.COM 		if((eeprom->address_bits == 8) && (offset >= 128))
565*8044SWilliam.Kucharski@Sun.COM 			read_opcode |= EEPROM_A8_OPCODE_SPI;
566*8044SWilliam.Kucharski@Sun.COM 
567*8044SWilliam.Kucharski@Sun.COM 		/* Send the READ command (opcode + addr)  */
568*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
569*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
570*8044SWilliam.Kucharski@Sun.COM 
571*8044SWilliam.Kucharski@Sun.COM 		/* Read the data.  The address of the eeprom internally increments with
572*8044SWilliam.Kucharski@Sun.COM 		 * each byte (spi) being read, saving on the overhead of eeprom setup
573*8044SWilliam.Kucharski@Sun.COM 		 * and tear-down.  The address counter will roll over if reading beyond
574*8044SWilliam.Kucharski@Sun.COM 		 * the size of the eeprom, thus allowing the entire memory to be read
575*8044SWilliam.Kucharski@Sun.COM 		 * starting from any offset. */
576*8044SWilliam.Kucharski@Sun.COM 		for (i = 0; i < words; i++) {
577*8044SWilliam.Kucharski@Sun.COM 			word_in = e1000_shift_in_ee_bits(hw, 16);
578*8044SWilliam.Kucharski@Sun.COM 			data[i] = (word_in >> 8) | (word_in << 8);
579*8044SWilliam.Kucharski@Sun.COM 		}
580*8044SWilliam.Kucharski@Sun.COM 	} else if(eeprom->type == e1000_eeprom_microwire) {
581*8044SWilliam.Kucharski@Sun.COM 		for (i = 0; i < words; i++) {
582*8044SWilliam.Kucharski@Sun.COM 			/*  Send the READ command (opcode + addr)  */
583*8044SWilliam.Kucharski@Sun.COM 			e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
584*8044SWilliam.Kucharski@Sun.COM 						eeprom->opcode_bits);
585*8044SWilliam.Kucharski@Sun.COM 			e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i),
586*8044SWilliam.Kucharski@Sun.COM 			                        eeprom->address_bits);
587*8044SWilliam.Kucharski@Sun.COM 
588*8044SWilliam.Kucharski@Sun.COM 			/* Read the data.  For microwire, each word requires the overhead
589*8044SWilliam.Kucharski@Sun.COM 			 * of eeprom setup and tear-down. */
590*8044SWilliam.Kucharski@Sun.COM 			data[i] = e1000_shift_in_ee_bits(hw, 16);
591*8044SWilliam.Kucharski@Sun.COM 			e1000_standby_eeprom(hw);
592*8044SWilliam.Kucharski@Sun.COM 		}
593*8044SWilliam.Kucharski@Sun.COM 	}
594*8044SWilliam.Kucharski@Sun.COM 
595*8044SWilliam.Kucharski@Sun.COM 	/* End this read operation */
596*8044SWilliam.Kucharski@Sun.COM 	e1000_release_eeprom(hw);
597*8044SWilliam.Kucharski@Sun.COM 
598*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
599*8044SWilliam.Kucharski@Sun.COM }
600*8044SWilliam.Kucharski@Sun.COM 
601*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
602*8044SWilliam.Kucharski@Sun.COM  * Verifies that the EEPROM has a valid checksum
603*8044SWilliam.Kucharski@Sun.COM  *
604*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
605*8044SWilliam.Kucharski@Sun.COM  *
606*8044SWilliam.Kucharski@Sun.COM  * Reads the first 64 16 bit words of the EEPROM and sums the values read.
607*8044SWilliam.Kucharski@Sun.COM  * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
608*8044SWilliam.Kucharski@Sun.COM  * valid.
609*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
610*8044SWilliam.Kucharski@Sun.COM static int
e1000_validate_eeprom_checksum(struct e1000_hw * hw)611*8044SWilliam.Kucharski@Sun.COM e1000_validate_eeprom_checksum(struct e1000_hw *hw)
612*8044SWilliam.Kucharski@Sun.COM {
613*8044SWilliam.Kucharski@Sun.COM 	uint16_t checksum = 0;
614*8044SWilliam.Kucharski@Sun.COM 	uint16_t i, eeprom_data;
615*8044SWilliam.Kucharski@Sun.COM 
616*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_validate_eeprom_checksum");
617*8044SWilliam.Kucharski@Sun.COM 
618*8044SWilliam.Kucharski@Sun.COM 	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
619*8044SWilliam.Kucharski@Sun.COM 		if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
620*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("EEPROM Read Error\n");
621*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_EEPROM;
622*8044SWilliam.Kucharski@Sun.COM 		}
623*8044SWilliam.Kucharski@Sun.COM 		checksum += eeprom_data;
624*8044SWilliam.Kucharski@Sun.COM 	}
625*8044SWilliam.Kucharski@Sun.COM 
626*8044SWilliam.Kucharski@Sun.COM 	if(checksum == (uint16_t) EEPROM_SUM)
627*8044SWilliam.Kucharski@Sun.COM 		return E1000_SUCCESS;
628*8044SWilliam.Kucharski@Sun.COM 	else {
629*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("EEPROM Checksum Invalid\n");
630*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_EEPROM;
631*8044SWilliam.Kucharski@Sun.COM 	}
632*8044SWilliam.Kucharski@Sun.COM }
633*8044SWilliam.Kucharski@Sun.COM 
634*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
635*8044SWilliam.Kucharski@Sun.COM  * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
636*8044SWilliam.Kucharski@Sun.COM  * second function of dual function devices
637*8044SWilliam.Kucharski@Sun.COM  *
638*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
639*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
640*8044SWilliam.Kucharski@Sun.COM static int
e1000_read_mac_addr(struct e1000_hw * hw)641*8044SWilliam.Kucharski@Sun.COM e1000_read_mac_addr(struct e1000_hw *hw)
642*8044SWilliam.Kucharski@Sun.COM {
643*8044SWilliam.Kucharski@Sun.COM 	uint16_t offset;
644*8044SWilliam.Kucharski@Sun.COM 	uint16_t eeprom_data;
645*8044SWilliam.Kucharski@Sun.COM 	int i;
646*8044SWilliam.Kucharski@Sun.COM 
647*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_read_mac_addr");
648*8044SWilliam.Kucharski@Sun.COM 
649*8044SWilliam.Kucharski@Sun.COM 	for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
650*8044SWilliam.Kucharski@Sun.COM 		offset = i >> 1;
651*8044SWilliam.Kucharski@Sun.COM 		if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
652*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("EEPROM Read Error\n");
653*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_EEPROM;
654*8044SWilliam.Kucharski@Sun.COM 		}
655*8044SWilliam.Kucharski@Sun.COM 		hw->mac_addr[i] = eeprom_data & 0xff;
656*8044SWilliam.Kucharski@Sun.COM 		hw->mac_addr[i+1] = (eeprom_data >> 8) & 0xff;
657*8044SWilliam.Kucharski@Sun.COM 	}
658*8044SWilliam.Kucharski@Sun.COM 	if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
659*8044SWilliam.Kucharski@Sun.COM 		(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
660*8044SWilliam.Kucharski@Sun.COM 		/* Invert the last bit if this is the second device */
661*8044SWilliam.Kucharski@Sun.COM 		hw->mac_addr[5] ^= 1;
662*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
663*8044SWilliam.Kucharski@Sun.COM }
664*8044SWilliam.Kucharski@Sun.COM 
665*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
666*8044SWilliam.Kucharski@Sun.COM  * Initializes receive address filters.
667*8044SWilliam.Kucharski@Sun.COM  *
668*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
669*8044SWilliam.Kucharski@Sun.COM  *
670*8044SWilliam.Kucharski@Sun.COM  * Places the MAC address in receive address register 0 and clears the rest
671*8044SWilliam.Kucharski@Sun.COM  * of the receive addresss registers. Clears the multicast table. Assumes
672*8044SWilliam.Kucharski@Sun.COM  * the receiver is in reset when the routine is called.
673*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
674*8044SWilliam.Kucharski@Sun.COM static void
e1000_init_rx_addrs(struct e1000_hw * hw)675*8044SWilliam.Kucharski@Sun.COM e1000_init_rx_addrs(struct e1000_hw *hw)
676*8044SWilliam.Kucharski@Sun.COM {
677*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
678*8044SWilliam.Kucharski@Sun.COM 	uint32_t addr_low;
679*8044SWilliam.Kucharski@Sun.COM 	uint32_t addr_high;
680*8044SWilliam.Kucharski@Sun.COM 
681*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_init_rx_addrs");
682*8044SWilliam.Kucharski@Sun.COM 
683*8044SWilliam.Kucharski@Sun.COM 	/* Setup the receive address. */
684*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Programming MAC Address into RAR[0]\n");
685*8044SWilliam.Kucharski@Sun.COM 	addr_low = (hw->mac_addr[0] |
686*8044SWilliam.Kucharski@Sun.COM 		(hw->mac_addr[1] << 8) |
687*8044SWilliam.Kucharski@Sun.COM 		(hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24));
688*8044SWilliam.Kucharski@Sun.COM 
689*8044SWilliam.Kucharski@Sun.COM 	addr_high = (hw->mac_addr[4] |
690*8044SWilliam.Kucharski@Sun.COM 		(hw->mac_addr[5] << 8) | E1000_RAH_AV);
691*8044SWilliam.Kucharski@Sun.COM 
692*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
693*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
694*8044SWilliam.Kucharski@Sun.COM 
695*8044SWilliam.Kucharski@Sun.COM 	/* Zero out the other 15 receive addresses. */
696*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Clearing RAR[1-15]\n");
697*8044SWilliam.Kucharski@Sun.COM 	for(i = 1; i < E1000_RAR_ENTRIES; i++) {
698*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
699*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
700*8044SWilliam.Kucharski@Sun.COM 	}
701*8044SWilliam.Kucharski@Sun.COM }
702*8044SWilliam.Kucharski@Sun.COM 
703*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
704*8044SWilliam.Kucharski@Sun.COM  * Clears the VLAN filer table
705*8044SWilliam.Kucharski@Sun.COM  *
706*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
707*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
708*8044SWilliam.Kucharski@Sun.COM static void
e1000_clear_vfta(struct e1000_hw * hw)709*8044SWilliam.Kucharski@Sun.COM e1000_clear_vfta(struct e1000_hw *hw)
710*8044SWilliam.Kucharski@Sun.COM {
711*8044SWilliam.Kucharski@Sun.COM 	uint32_t offset;
712*8044SWilliam.Kucharski@Sun.COM 
713*8044SWilliam.Kucharski@Sun.COM 	for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
714*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
715*8044SWilliam.Kucharski@Sun.COM }
716*8044SWilliam.Kucharski@Sun.COM 
717*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
718*8044SWilliam.Kucharski@Sun.COM * Writes a value to one of the devices registers using port I/O (as opposed to
719*8044SWilliam.Kucharski@Sun.COM * memory mapped I/O). Only 82544 and newer devices support port I/O. *
720*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
721*8044SWilliam.Kucharski@Sun.COM * offset - offset to write to * value - value to write
722*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
e1000_write_reg_io(struct e1000_hw * hw,uint32_t offset,uint32_t value)723*8044SWilliam.Kucharski@Sun.COM void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value){
724*8044SWilliam.Kucharski@Sun.COM 	uint32_t io_addr = hw->io_base;
725*8044SWilliam.Kucharski@Sun.COM 	uint32_t io_data = hw->io_base + 4;
726*8044SWilliam.Kucharski@Sun.COM 	e1000_io_write(hw, io_addr, offset);
727*8044SWilliam.Kucharski@Sun.COM 	e1000_io_write(hw, io_data, value);
728*8044SWilliam.Kucharski@Sun.COM }
729*8044SWilliam.Kucharski@Sun.COM 
730*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
731*8044SWilliam.Kucharski@Sun.COM  * Set the phy type member in the hw struct.
732*8044SWilliam.Kucharski@Sun.COM  *
733*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
734*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
735*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_set_phy_type(struct e1000_hw * hw)736*8044SWilliam.Kucharski@Sun.COM e1000_set_phy_type(struct e1000_hw *hw)
737*8044SWilliam.Kucharski@Sun.COM {
738*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_set_phy_type");
739*8044SWilliam.Kucharski@Sun.COM 
740*8044SWilliam.Kucharski@Sun.COM 	switch(hw->phy_id) {
741*8044SWilliam.Kucharski@Sun.COM 	case M88E1000_E_PHY_ID:
742*8044SWilliam.Kucharski@Sun.COM 	case M88E1000_I_PHY_ID:
743*8044SWilliam.Kucharski@Sun.COM 	case M88E1011_I_PHY_ID:
744*8044SWilliam.Kucharski@Sun.COM 		hw->phy_type = e1000_phy_m88;
745*8044SWilliam.Kucharski@Sun.COM 		break;
746*8044SWilliam.Kucharski@Sun.COM 	case IGP01E1000_I_PHY_ID:
747*8044SWilliam.Kucharski@Sun.COM 		hw->phy_type = e1000_phy_igp;
748*8044SWilliam.Kucharski@Sun.COM 		break;
749*8044SWilliam.Kucharski@Sun.COM 	default:
750*8044SWilliam.Kucharski@Sun.COM 		/* Should never have loaded on this device */
751*8044SWilliam.Kucharski@Sun.COM 		hw->phy_type = e1000_phy_undefined;
752*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_PHY_TYPE;
753*8044SWilliam.Kucharski@Sun.COM 	}
754*8044SWilliam.Kucharski@Sun.COM 
755*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
756*8044SWilliam.Kucharski@Sun.COM }
757*8044SWilliam.Kucharski@Sun.COM 
758*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
759*8044SWilliam.Kucharski@Sun.COM  * IGP phy init script - initializes the GbE PHY
760*8044SWilliam.Kucharski@Sun.COM  *
761*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
762*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
763*8044SWilliam.Kucharski@Sun.COM static void
e1000_phy_init_script(struct e1000_hw * hw)764*8044SWilliam.Kucharski@Sun.COM e1000_phy_init_script(struct e1000_hw *hw)
765*8044SWilliam.Kucharski@Sun.COM {
766*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_phy_init_script");
767*8044SWilliam.Kucharski@Sun.COM 
768*8044SWilliam.Kucharski@Sun.COM #if 0
769*8044SWilliam.Kucharski@Sun.COM 	/* See e1000_sw_init() of the Linux driver */
770*8044SWilliam.Kucharski@Sun.COM 	if(hw->phy_init_script) {
771*8044SWilliam.Kucharski@Sun.COM #else
772*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type == e1000_82541) ||
773*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82547) ||
774*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82541_rev_2) ||
775*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82547_rev_2)) {
776*8044SWilliam.Kucharski@Sun.COM #endif
777*8044SWilliam.Kucharski@Sun.COM 		mdelay(20);
778*8044SWilliam.Kucharski@Sun.COM 
779*8044SWilliam.Kucharski@Sun.COM 		e1000_write_phy_reg(hw,0x0000,0x0140);
780*8044SWilliam.Kucharski@Sun.COM 
781*8044SWilliam.Kucharski@Sun.COM 		mdelay(5);
782*8044SWilliam.Kucharski@Sun.COM 
783*8044SWilliam.Kucharski@Sun.COM 		if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) {
784*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F95, 0x0001);
785*8044SWilliam.Kucharski@Sun.COM 
786*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
787*8044SWilliam.Kucharski@Sun.COM 
788*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F79, 0x0018);
789*8044SWilliam.Kucharski@Sun.COM 
790*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F30, 0x1600);
791*8044SWilliam.Kucharski@Sun.COM 
792*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F31, 0x0014);
793*8044SWilliam.Kucharski@Sun.COM 
794*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F32, 0x161C);
795*8044SWilliam.Kucharski@Sun.COM 
796*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F94, 0x0003);
797*8044SWilliam.Kucharski@Sun.COM 
798*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F96, 0x003F);
799*8044SWilliam.Kucharski@Sun.COM 
800*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x2010, 0x0008);
801*8044SWilliam.Kucharski@Sun.COM 		} else {
802*8044SWilliam.Kucharski@Sun.COM 			e1000_write_phy_reg(hw, 0x1F73, 0x0099);
803*8044SWilliam.Kucharski@Sun.COM 		}
804*8044SWilliam.Kucharski@Sun.COM 
805*8044SWilliam.Kucharski@Sun.COM 		e1000_write_phy_reg(hw, 0x0000, 0x3300);
806*8044SWilliam.Kucharski@Sun.COM 
807*8044SWilliam.Kucharski@Sun.COM 
808*8044SWilliam.Kucharski@Sun.COM 		if(hw->mac_type == e1000_82547) {
809*8044SWilliam.Kucharski@Sun.COM 			uint16_t fused, fine, coarse;
810*8044SWilliam.Kucharski@Sun.COM 
811*8044SWilliam.Kucharski@Sun.COM 			/* Move to analog registers page */
812*8044SWilliam.Kucharski@Sun.COM 			e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
813*8044SWilliam.Kucharski@Sun.COM 
814*8044SWilliam.Kucharski@Sun.COM 			if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
815*8044SWilliam.Kucharski@Sun.COM 				e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
816*8044SWilliam.Kucharski@Sun.COM 
817*8044SWilliam.Kucharski@Sun.COM 				fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
818*8044SWilliam.Kucharski@Sun.COM 				coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
819*8044SWilliam.Kucharski@Sun.COM 
820*8044SWilliam.Kucharski@Sun.COM 				if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
821*8044SWilliam.Kucharski@Sun.COM 					coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
822*8044SWilliam.Kucharski@Sun.COM 					fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
823*8044SWilliam.Kucharski@Sun.COM 				} else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
824*8044SWilliam.Kucharski@Sun.COM 					fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
825*8044SWilliam.Kucharski@Sun.COM 
826*8044SWilliam.Kucharski@Sun.COM 				fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
827*8044SWilliam.Kucharski@Sun.COM 					(fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
828*8044SWilliam.Kucharski@Sun.COM 					(coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
829*8044SWilliam.Kucharski@Sun.COM 
830*8044SWilliam.Kucharski@Sun.COM 				e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
831*8044SWilliam.Kucharski@Sun.COM 				e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS,
832*8044SWilliam.Kucharski@Sun.COM 						IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
833*8044SWilliam.Kucharski@Sun.COM 			}
834*8044SWilliam.Kucharski@Sun.COM 		}
835*8044SWilliam.Kucharski@Sun.COM 	}
836*8044SWilliam.Kucharski@Sun.COM }
837*8044SWilliam.Kucharski@Sun.COM 
838*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
839*8044SWilliam.Kucharski@Sun.COM  * Set the mac type member in the hw struct.
840*8044SWilliam.Kucharski@Sun.COM  *
841*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
842*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
843*8044SWilliam.Kucharski@Sun.COM static int
844*8044SWilliam.Kucharski@Sun.COM e1000_set_mac_type(struct e1000_hw *hw)
845*8044SWilliam.Kucharski@Sun.COM {
846*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_set_mac_type");
847*8044SWilliam.Kucharski@Sun.COM 
848*8044SWilliam.Kucharski@Sun.COM 	switch (hw->device_id) {
849*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82542:
850*8044SWilliam.Kucharski@Sun.COM 		switch (hw->revision_id) {
851*8044SWilliam.Kucharski@Sun.COM 		case E1000_82542_2_0_REV_ID:
852*8044SWilliam.Kucharski@Sun.COM 			hw->mac_type = e1000_82542_rev2_0;
853*8044SWilliam.Kucharski@Sun.COM 			break;
854*8044SWilliam.Kucharski@Sun.COM 		case E1000_82542_2_1_REV_ID:
855*8044SWilliam.Kucharski@Sun.COM 			hw->mac_type = e1000_82542_rev2_1;
856*8044SWilliam.Kucharski@Sun.COM 			break;
857*8044SWilliam.Kucharski@Sun.COM 		default:
858*8044SWilliam.Kucharski@Sun.COM 			/* Invalid 82542 revision ID */
859*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_MAC_TYPE;
860*8044SWilliam.Kucharski@Sun.COM 		}
861*8044SWilliam.Kucharski@Sun.COM 		break;
862*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82543GC_FIBER:
863*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82543GC_COPPER:
864*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82543;
865*8044SWilliam.Kucharski@Sun.COM 		break;
866*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82544EI_COPPER:
867*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82544EI_FIBER:
868*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82544GC_COPPER:
869*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82544GC_LOM:
870*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82544;
871*8044SWilliam.Kucharski@Sun.COM 		break;
872*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82540EM:
873*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82540EM_LOM:
874*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82540EP:
875*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82540EP_LOM:
876*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82540EP_LP:
877*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82540;
878*8044SWilliam.Kucharski@Sun.COM 		break;
879*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82545EM_COPPER:
880*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82545EM_FIBER:
881*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82545;
882*8044SWilliam.Kucharski@Sun.COM 		break;
883*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82545GM_COPPER:
884*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82545GM_FIBER:
885*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82545GM_SERDES:
886*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82545_rev_3;
887*8044SWilliam.Kucharski@Sun.COM 		break;
888*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546EB_COPPER:
889*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546EB_FIBER:
890*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546EB_QUAD_COPPER:
891*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82546;
892*8044SWilliam.Kucharski@Sun.COM 		break;
893*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546GB_COPPER:
894*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546GB_FIBER:
895*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82546GB_SERDES:
896*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82546_rev_3;
897*8044SWilliam.Kucharski@Sun.COM 		break;
898*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82541EI:
899*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82541EI_MOBILE:
900*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82541;
901*8044SWilliam.Kucharski@Sun.COM 		break;
902*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82541ER:
903*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82541GI:
904*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82541GI_MOBILE:
905*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82541_rev_2;
906*8044SWilliam.Kucharski@Sun.COM 		break;
907*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82547EI:
908*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82547;
909*8044SWilliam.Kucharski@Sun.COM 		break;
910*8044SWilliam.Kucharski@Sun.COM 	case E1000_DEV_ID_82547GI:
911*8044SWilliam.Kucharski@Sun.COM 		hw->mac_type = e1000_82547_rev_2;
912*8044SWilliam.Kucharski@Sun.COM 		break;
913*8044SWilliam.Kucharski@Sun.COM 	default:
914*8044SWilliam.Kucharski@Sun.COM 		/* Should never have loaded on this device */
915*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_MAC_TYPE;
916*8044SWilliam.Kucharski@Sun.COM 	}
917*8044SWilliam.Kucharski@Sun.COM 
918*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
919*8044SWilliam.Kucharski@Sun.COM }
920*8044SWilliam.Kucharski@Sun.COM 
921*8044SWilliam.Kucharski@Sun.COM /*****************************************************************************
922*8044SWilliam.Kucharski@Sun.COM  * Set media type and TBI compatibility.
923*8044SWilliam.Kucharski@Sun.COM  *
924*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
925*8044SWilliam.Kucharski@Sun.COM  * **************************************************************************/
926*8044SWilliam.Kucharski@Sun.COM static void
927*8044SWilliam.Kucharski@Sun.COM e1000_set_media_type(struct e1000_hw *hw)
928*8044SWilliam.Kucharski@Sun.COM {
929*8044SWilliam.Kucharski@Sun.COM 	uint32_t status;
930*8044SWilliam.Kucharski@Sun.COM 
931*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_set_media_type");
932*8044SWilliam.Kucharski@Sun.COM 
933*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type != e1000_82543) {
934*8044SWilliam.Kucharski@Sun.COM 		/* tbi_compatibility is only valid on 82543 */
935*8044SWilliam.Kucharski@Sun.COM 		hw->tbi_compatibility_en = FALSE;
936*8044SWilliam.Kucharski@Sun.COM 	}
937*8044SWilliam.Kucharski@Sun.COM 
938*8044SWilliam.Kucharski@Sun.COM 	switch (hw->device_id) {
939*8044SWilliam.Kucharski@Sun.COM 		case E1000_DEV_ID_82545GM_SERDES:
940*8044SWilliam.Kucharski@Sun.COM 		case E1000_DEV_ID_82546GB_SERDES:
941*8044SWilliam.Kucharski@Sun.COM 			hw->media_type = e1000_media_type_internal_serdes;
942*8044SWilliam.Kucharski@Sun.COM 			break;
943*8044SWilliam.Kucharski@Sun.COM 		default:
944*8044SWilliam.Kucharski@Sun.COM 			if(hw->mac_type >= e1000_82543) {
945*8044SWilliam.Kucharski@Sun.COM 				status = E1000_READ_REG(hw, STATUS);
946*8044SWilliam.Kucharski@Sun.COM 				if(status & E1000_STATUS_TBIMODE) {
947*8044SWilliam.Kucharski@Sun.COM 					hw->media_type = e1000_media_type_fiber;
948*8044SWilliam.Kucharski@Sun.COM 					/* tbi_compatibility not valid on fiber */
949*8044SWilliam.Kucharski@Sun.COM 					hw->tbi_compatibility_en = FALSE;
950*8044SWilliam.Kucharski@Sun.COM 				} else {
951*8044SWilliam.Kucharski@Sun.COM 					hw->media_type = e1000_media_type_copper;
952*8044SWilliam.Kucharski@Sun.COM 				}
953*8044SWilliam.Kucharski@Sun.COM 			} else {
954*8044SWilliam.Kucharski@Sun.COM 				/* This is an 82542 (fiber only) */
955*8044SWilliam.Kucharski@Sun.COM 				hw->media_type = e1000_media_type_fiber;
956*8044SWilliam.Kucharski@Sun.COM 			}
957*8044SWilliam.Kucharski@Sun.COM 	}
958*8044SWilliam.Kucharski@Sun.COM }
959*8044SWilliam.Kucharski@Sun.COM 
960*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
961*8044SWilliam.Kucharski@Sun.COM  * Reset the transmit and receive units; mask and clear all interrupts.
962*8044SWilliam.Kucharski@Sun.COM  *
963*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
964*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
965*8044SWilliam.Kucharski@Sun.COM static void
966*8044SWilliam.Kucharski@Sun.COM e1000_reset_hw(struct e1000_hw *hw)
967*8044SWilliam.Kucharski@Sun.COM {
968*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
969*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl_ext;
970*8044SWilliam.Kucharski@Sun.COM 	uint32_t icr;
971*8044SWilliam.Kucharski@Sun.COM 	uint32_t manc;
972*8044SWilliam.Kucharski@Sun.COM 
973*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_reset_hw");
974*8044SWilliam.Kucharski@Sun.COM 
975*8044SWilliam.Kucharski@Sun.COM 	/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
976*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0) {
977*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
978*8044SWilliam.Kucharski@Sun.COM 		e1000_pci_clear_mwi(hw);
979*8044SWilliam.Kucharski@Sun.COM 	}
980*8044SWilliam.Kucharski@Sun.COM 
981*8044SWilliam.Kucharski@Sun.COM 	/* Clear interrupt mask to stop board from generating interrupts */
982*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Masking off all interrupts\n");
983*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, IMC, 0xffffffff);
984*8044SWilliam.Kucharski@Sun.COM 
985*8044SWilliam.Kucharski@Sun.COM 	/* Disable the Transmit and Receive units.  Then delay to allow
986*8044SWilliam.Kucharski@Sun.COM 	 * any pending transactions to complete before we hit the MAC with
987*8044SWilliam.Kucharski@Sun.COM 	 * the global reset.
988*8044SWilliam.Kucharski@Sun.COM 	 */
989*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, RCTL, 0);
990*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
991*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
992*8044SWilliam.Kucharski@Sun.COM 
993*8044SWilliam.Kucharski@Sun.COM 	/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
994*8044SWilliam.Kucharski@Sun.COM 	hw->tbi_compatibility_on = FALSE;
995*8044SWilliam.Kucharski@Sun.COM 
996*8044SWilliam.Kucharski@Sun.COM 	/* Delay to allow any outstanding PCI transactions to complete before
997*8044SWilliam.Kucharski@Sun.COM 	 * resetting the device
998*8044SWilliam.Kucharski@Sun.COM 	 */
999*8044SWilliam.Kucharski@Sun.COM 	mdelay(10);
1000*8044SWilliam.Kucharski@Sun.COM 
1001*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
1002*8044SWilliam.Kucharski@Sun.COM 
1003*8044SWilliam.Kucharski@Sun.COM 	/* Must reset the PHY before resetting the MAC */
1004*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1005*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
1006*8044SWilliam.Kucharski@Sun.COM 		mdelay(5);
1007*8044SWilliam.Kucharski@Sun.COM 	}
1008*8044SWilliam.Kucharski@Sun.COM 
1009*8044SWilliam.Kucharski@Sun.COM 	/* Issue a global reset to the MAC.  This will reset the chip's
1010*8044SWilliam.Kucharski@Sun.COM 	 * transmit, receive, DMA, and link units.  It will not effect
1011*8044SWilliam.Kucharski@Sun.COM 	 * the current PCI configuration.  The global reset bit is self-
1012*8044SWilliam.Kucharski@Sun.COM 	 * clearing, and should clear within a microsecond.
1013*8044SWilliam.Kucharski@Sun.COM 	 */
1014*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Issuing a global reset to MAC\n");
1015*8044SWilliam.Kucharski@Sun.COM 
1016*8044SWilliam.Kucharski@Sun.COM 	switch(hw->mac_type) {
1017*8044SWilliam.Kucharski@Sun.COM 		case e1000_82544:
1018*8044SWilliam.Kucharski@Sun.COM 		case e1000_82540:
1019*8044SWilliam.Kucharski@Sun.COM 		case e1000_82545:
1020*8044SWilliam.Kucharski@Sun.COM 		case e1000_82546:
1021*8044SWilliam.Kucharski@Sun.COM 		case e1000_82541:
1022*8044SWilliam.Kucharski@Sun.COM 		case e1000_82541_rev_2:
1023*8044SWilliam.Kucharski@Sun.COM 			/* These controllers can't ack the 64-bit write when issuing the
1024*8044SWilliam.Kucharski@Sun.COM 			 * reset, so use IO-mapping as a workaround to issue the reset */
1025*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
1026*8044SWilliam.Kucharski@Sun.COM 			break;
1027*8044SWilliam.Kucharski@Sun.COM 		case e1000_82545_rev_3:
1028*8044SWilliam.Kucharski@Sun.COM 		case e1000_82546_rev_3:
1029*8044SWilliam.Kucharski@Sun.COM 			/* Reset is performed on a shadow of the control register */
1030*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
1031*8044SWilliam.Kucharski@Sun.COM 			break;
1032*8044SWilliam.Kucharski@Sun.COM 		default:
1033*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
1034*8044SWilliam.Kucharski@Sun.COM 			break;
1035*8044SWilliam.Kucharski@Sun.COM 	}
1036*8044SWilliam.Kucharski@Sun.COM 
1037*8044SWilliam.Kucharski@Sun.COM 	/* After MAC reset, force reload of EEPROM to restore power-on settings to
1038*8044SWilliam.Kucharski@Sun.COM 	 * device.  Later controllers reload the EEPROM automatically, so just wait
1039*8044SWilliam.Kucharski@Sun.COM 	 * for reload to complete.
1040*8044SWilliam.Kucharski@Sun.COM 	 */
1041*8044SWilliam.Kucharski@Sun.COM 	switch(hw->mac_type) {
1042*8044SWilliam.Kucharski@Sun.COM 		case e1000_82542_rev2_0:
1043*8044SWilliam.Kucharski@Sun.COM 		case e1000_82542_rev2_1:
1044*8044SWilliam.Kucharski@Sun.COM 		case e1000_82543:
1045*8044SWilliam.Kucharski@Sun.COM 		case e1000_82544:
1046*8044SWilliam.Kucharski@Sun.COM 			/* Wait for reset to complete */
1047*8044SWilliam.Kucharski@Sun.COM 			udelay(10);
1048*8044SWilliam.Kucharski@Sun.COM 			ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
1049*8044SWilliam.Kucharski@Sun.COM 			ctrl_ext |= E1000_CTRL_EXT_EE_RST;
1050*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
1051*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_FLUSH(hw);
1052*8044SWilliam.Kucharski@Sun.COM 			/* Wait for EEPROM reload */
1053*8044SWilliam.Kucharski@Sun.COM 			mdelay(2);
1054*8044SWilliam.Kucharski@Sun.COM 			break;
1055*8044SWilliam.Kucharski@Sun.COM 		case e1000_82541:
1056*8044SWilliam.Kucharski@Sun.COM 		case e1000_82541_rev_2:
1057*8044SWilliam.Kucharski@Sun.COM 		case e1000_82547:
1058*8044SWilliam.Kucharski@Sun.COM 		case e1000_82547_rev_2:
1059*8044SWilliam.Kucharski@Sun.COM 			/* Wait for EEPROM reload */
1060*8044SWilliam.Kucharski@Sun.COM 			mdelay(20);
1061*8044SWilliam.Kucharski@Sun.COM 			break;
1062*8044SWilliam.Kucharski@Sun.COM 		default:
1063*8044SWilliam.Kucharski@Sun.COM 			/* Wait for EEPROM reload (it happens automatically) */
1064*8044SWilliam.Kucharski@Sun.COM 			mdelay(5);
1065*8044SWilliam.Kucharski@Sun.COM 			break;
1066*8044SWilliam.Kucharski@Sun.COM 	}
1067*8044SWilliam.Kucharski@Sun.COM 
1068*8044SWilliam.Kucharski@Sun.COM 	/* Disable HW ARPs on ASF enabled adapters */
1069*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type >= e1000_82540) {
1070*8044SWilliam.Kucharski@Sun.COM 		manc = E1000_READ_REG(hw, MANC);
1071*8044SWilliam.Kucharski@Sun.COM 		manc &= ~(E1000_MANC_ARP_EN);
1072*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, MANC, manc);
1073*8044SWilliam.Kucharski@Sun.COM 	}
1074*8044SWilliam.Kucharski@Sun.COM 
1075*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1076*8044SWilliam.Kucharski@Sun.COM 		e1000_phy_init_script(hw);
1077*8044SWilliam.Kucharski@Sun.COM 	}
1078*8044SWilliam.Kucharski@Sun.COM 
1079*8044SWilliam.Kucharski@Sun.COM 	/* Clear interrupt mask to stop board from generating interrupts */
1080*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Masking off all interrupts\n");
1081*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, IMC, 0xffffffff);
1082*8044SWilliam.Kucharski@Sun.COM 
1083*8044SWilliam.Kucharski@Sun.COM 	/* Clear any pending interrupt events. */
1084*8044SWilliam.Kucharski@Sun.COM 	icr = E1000_READ_REG(hw, ICR);
1085*8044SWilliam.Kucharski@Sun.COM 
1086*8044SWilliam.Kucharski@Sun.COM 	/* If MWI was previously enabled, reenable it. */
1087*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0) {
1088*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1089*8044SWilliam.Kucharski@Sun.COM 		if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
1090*8044SWilliam.Kucharski@Sun.COM #endif
1091*8044SWilliam.Kucharski@Sun.COM 			e1000_pci_set_mwi(hw);
1092*8044SWilliam.Kucharski@Sun.COM 	}
1093*8044SWilliam.Kucharski@Sun.COM }
1094*8044SWilliam.Kucharski@Sun.COM 
1095*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1096*8044SWilliam.Kucharski@Sun.COM  * Performs basic configuration of the adapter.
1097*8044SWilliam.Kucharski@Sun.COM  *
1098*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
1099*8044SWilliam.Kucharski@Sun.COM  *
1100*8044SWilliam.Kucharski@Sun.COM  * Assumes that the controller has previously been reset and is in a
1101*8044SWilliam.Kucharski@Sun.COM  * post-reset uninitialized state. Initializes the receive address registers,
1102*8044SWilliam.Kucharski@Sun.COM  * multicast table, and VLAN filter table. Calls routines to setup link
1103*8044SWilliam.Kucharski@Sun.COM  * configuration and flow control settings. Clears all on-chip counters. Leaves
1104*8044SWilliam.Kucharski@Sun.COM  * the transmit and receive units disabled and uninitialized.
1105*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
1106*8044SWilliam.Kucharski@Sun.COM static int
1107*8044SWilliam.Kucharski@Sun.COM e1000_init_hw(struct e1000_hw *hw)
1108*8044SWilliam.Kucharski@Sun.COM {
1109*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl, status;
1110*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
1111*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
1112*8044SWilliam.Kucharski@Sun.COM 	uint16_t pcix_cmd_word;
1113*8044SWilliam.Kucharski@Sun.COM 	uint16_t pcix_stat_hi_word;
1114*8044SWilliam.Kucharski@Sun.COM 	uint16_t cmd_mmrbc;
1115*8044SWilliam.Kucharski@Sun.COM 	uint16_t stat_mmrbc;
1116*8044SWilliam.Kucharski@Sun.COM 	e1000_bus_type bus_type = e1000_bus_type_unknown;
1117*8044SWilliam.Kucharski@Sun.COM 
1118*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_init_hw");
1119*8044SWilliam.Kucharski@Sun.COM 
1120*8044SWilliam.Kucharski@Sun.COM 	/* Set the media type and TBI compatibility */
1121*8044SWilliam.Kucharski@Sun.COM 	e1000_set_media_type(hw);
1122*8044SWilliam.Kucharski@Sun.COM 
1123*8044SWilliam.Kucharski@Sun.COM 	/* Disabling VLAN filtering. */
1124*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Initializing the IEEE VLAN\n");
1125*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, VET, 0);
1126*8044SWilliam.Kucharski@Sun.COM 
1127*8044SWilliam.Kucharski@Sun.COM 	e1000_clear_vfta(hw);
1128*8044SWilliam.Kucharski@Sun.COM 
1129*8044SWilliam.Kucharski@Sun.COM 	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
1130*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0) {
1131*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
1132*8044SWilliam.Kucharski@Sun.COM 		e1000_pci_clear_mwi(hw);
1133*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
1134*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
1135*8044SWilliam.Kucharski@Sun.COM 		mdelay(5);
1136*8044SWilliam.Kucharski@Sun.COM 	}
1137*8044SWilliam.Kucharski@Sun.COM 
1138*8044SWilliam.Kucharski@Sun.COM 	/* Setup the receive address. This involves initializing all of the Receive
1139*8044SWilliam.Kucharski@Sun.COM 	 * Address Registers (RARs 0 - 15).
1140*8044SWilliam.Kucharski@Sun.COM 	 */
1141*8044SWilliam.Kucharski@Sun.COM 	e1000_init_rx_addrs(hw);
1142*8044SWilliam.Kucharski@Sun.COM 
1143*8044SWilliam.Kucharski@Sun.COM 	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
1144*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0) {
1145*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, RCTL, 0);
1146*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
1147*8044SWilliam.Kucharski@Sun.COM 		mdelay(1);
1148*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1149*8044SWilliam.Kucharski@Sun.COM 		if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
1150*8044SWilliam.Kucharski@Sun.COM #endif
1151*8044SWilliam.Kucharski@Sun.COM 			e1000_pci_set_mwi(hw);
1152*8044SWilliam.Kucharski@Sun.COM 	}
1153*8044SWilliam.Kucharski@Sun.COM 
1154*8044SWilliam.Kucharski@Sun.COM 	/* Zero out the Multicast HASH table */
1155*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Zeroing the MTA\n");
1156*8044SWilliam.Kucharski@Sun.COM 	for(i = 0; i < E1000_MC_TBL_SIZE; i++)
1157*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
1158*8044SWilliam.Kucharski@Sun.COM 
1159*8044SWilliam.Kucharski@Sun.COM #if 0
1160*8044SWilliam.Kucharski@Sun.COM 	/* Set the PCI priority bit correctly in the CTRL register.  This
1161*8044SWilliam.Kucharski@Sun.COM 	 * determines if the adapter gives priority to receives, or if it
1162*8044SWilliam.Kucharski@Sun.COM 	 * gives equal priority to transmits and receives.
1163*8044SWilliam.Kucharski@Sun.COM 	 */
1164*8044SWilliam.Kucharski@Sun.COM 	if(hw->dma_fairness) {
1165*8044SWilliam.Kucharski@Sun.COM 		ctrl = E1000_READ_REG(hw, CTRL);
1166*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
1167*8044SWilliam.Kucharski@Sun.COM 	}
1168*8044SWilliam.Kucharski@Sun.COM #endif
1169*8044SWilliam.Kucharski@Sun.COM 
1170*8044SWilliam.Kucharski@Sun.COM 	switch(hw->mac_type) {
1171*8044SWilliam.Kucharski@Sun.COM 		case e1000_82545_rev_3:
1172*8044SWilliam.Kucharski@Sun.COM 		case e1000_82546_rev_3:
1173*8044SWilliam.Kucharski@Sun.COM 			break;
1174*8044SWilliam.Kucharski@Sun.COM 		default:
1175*8044SWilliam.Kucharski@Sun.COM 			if (hw->mac_type >= e1000_82543) {
1176*8044SWilliam.Kucharski@Sun.COM 				/* See e1000_get_bus_info() of the Linux driver */
1177*8044SWilliam.Kucharski@Sun.COM 				status = E1000_READ_REG(hw, STATUS);
1178*8044SWilliam.Kucharski@Sun.COM 				bus_type = (status & E1000_STATUS_PCIX_MODE) ?
1179*8044SWilliam.Kucharski@Sun.COM 					e1000_bus_type_pcix : e1000_bus_type_pci;
1180*8044SWilliam.Kucharski@Sun.COM 			}
1181*8044SWilliam.Kucharski@Sun.COM 
1182*8044SWilliam.Kucharski@Sun.COM 			/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
1183*8044SWilliam.Kucharski@Sun.COM 			if(bus_type == e1000_bus_type_pcix) {
1184*8044SWilliam.Kucharski@Sun.COM 				pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
1185*8044SWilliam.Kucharski@Sun.COM 				pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
1186*8044SWilliam.Kucharski@Sun.COM 				cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
1187*8044SWilliam.Kucharski@Sun.COM 					PCIX_COMMAND_MMRBC_SHIFT;
1188*8044SWilliam.Kucharski@Sun.COM 				stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
1189*8044SWilliam.Kucharski@Sun.COM 					PCIX_STATUS_HI_MMRBC_SHIFT;
1190*8044SWilliam.Kucharski@Sun.COM 				if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
1191*8044SWilliam.Kucharski@Sun.COM 					stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
1192*8044SWilliam.Kucharski@Sun.COM 				if(cmd_mmrbc > stat_mmrbc) {
1193*8044SWilliam.Kucharski@Sun.COM 					pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
1194*8044SWilliam.Kucharski@Sun.COM 					pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
1195*8044SWilliam.Kucharski@Sun.COM 					pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, pcix_cmd_word);
1196*8044SWilliam.Kucharski@Sun.COM 				}
1197*8044SWilliam.Kucharski@Sun.COM 			}
1198*8044SWilliam.Kucharski@Sun.COM 			break;
1199*8044SWilliam.Kucharski@Sun.COM 	}
1200*8044SWilliam.Kucharski@Sun.COM 
1201*8044SWilliam.Kucharski@Sun.COM 	/* Call a subroutine to configure the link and setup flow control. */
1202*8044SWilliam.Kucharski@Sun.COM 	ret_val = e1000_setup_link(hw);
1203*8044SWilliam.Kucharski@Sun.COM 
1204*8044SWilliam.Kucharski@Sun.COM 	/* Set the transmit descriptor write-back policy */
1205*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82544) {
1206*8044SWilliam.Kucharski@Sun.COM 		ctrl = E1000_READ_REG(hw, TXDCTL);
1207*8044SWilliam.Kucharski@Sun.COM 		ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
1208*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, TXDCTL, ctrl);
1209*8044SWilliam.Kucharski@Sun.COM 	}
1210*8044SWilliam.Kucharski@Sun.COM 
1211*8044SWilliam.Kucharski@Sun.COM #if 0
1212*8044SWilliam.Kucharski@Sun.COM 	/* Clear all of the statistics registers (clear on read).  It is
1213*8044SWilliam.Kucharski@Sun.COM 	 * important that we do this after we have tried to establish link
1214*8044SWilliam.Kucharski@Sun.COM 	 * because the symbol error count will increment wildly if there
1215*8044SWilliam.Kucharski@Sun.COM 	 * is no link.
1216*8044SWilliam.Kucharski@Sun.COM 	 */
1217*8044SWilliam.Kucharski@Sun.COM 	e1000_clear_hw_cntrs(hw);
1218*8044SWilliam.Kucharski@Sun.COM #endif
1219*8044SWilliam.Kucharski@Sun.COM 
1220*8044SWilliam.Kucharski@Sun.COM 	return ret_val;
1221*8044SWilliam.Kucharski@Sun.COM }
1222*8044SWilliam.Kucharski@Sun.COM 
1223*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1224*8044SWilliam.Kucharski@Sun.COM  * Adjust SERDES output amplitude based on EEPROM setting.
1225*8044SWilliam.Kucharski@Sun.COM  *
1226*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code.
1227*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
1228*8044SWilliam.Kucharski@Sun.COM static int32_t
1229*8044SWilliam.Kucharski@Sun.COM e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
1230*8044SWilliam.Kucharski@Sun.COM {
1231*8044SWilliam.Kucharski@Sun.COM 	uint16_t eeprom_data;
1232*8044SWilliam.Kucharski@Sun.COM 	int32_t  ret_val;
1233*8044SWilliam.Kucharski@Sun.COM 
1234*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_adjust_serdes_amplitude");
1235*8044SWilliam.Kucharski@Sun.COM 
1236*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type != e1000_media_type_internal_serdes)
1237*8044SWilliam.Kucharski@Sun.COM 		return E1000_SUCCESS;
1238*8044SWilliam.Kucharski@Sun.COM 
1239*8044SWilliam.Kucharski@Sun.COM 	switch(hw->mac_type) {
1240*8044SWilliam.Kucharski@Sun.COM 		case e1000_82545_rev_3:
1241*8044SWilliam.Kucharski@Sun.COM 		case e1000_82546_rev_3:
1242*8044SWilliam.Kucharski@Sun.COM 			break;
1243*8044SWilliam.Kucharski@Sun.COM 		default:
1244*8044SWilliam.Kucharski@Sun.COM 			return E1000_SUCCESS;
1245*8044SWilliam.Kucharski@Sun.COM 	}
1246*8044SWilliam.Kucharski@Sun.COM 
1247*8044SWilliam.Kucharski@Sun.COM 	if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
1248*8044SWilliam.Kucharski@Sun.COM 					&eeprom_data))) {
1249*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1250*8044SWilliam.Kucharski@Sun.COM 	}
1251*8044SWilliam.Kucharski@Sun.COM 
1252*8044SWilliam.Kucharski@Sun.COM 	if(eeprom_data != EEPROM_RESERVED_WORD) {
1253*8044SWilliam.Kucharski@Sun.COM 		/* Adjust SERDES output amplitude only. */
1254*8044SWilliam.Kucharski@Sun.COM 		eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
1255*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL,
1256*8044SWilliam.Kucharski@Sun.COM 		                                  eeprom_data)))
1257*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1258*8044SWilliam.Kucharski@Sun.COM 	}
1259*8044SWilliam.Kucharski@Sun.COM 
1260*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
1261*8044SWilliam.Kucharski@Sun.COM }
1262*8044SWilliam.Kucharski@Sun.COM 
1263*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1264*8044SWilliam.Kucharski@Sun.COM  * Configures flow control and link settings.
1265*8044SWilliam.Kucharski@Sun.COM  *
1266*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
1267*8044SWilliam.Kucharski@Sun.COM  *
1268*8044SWilliam.Kucharski@Sun.COM  * Determines which flow control settings to use. Calls the apropriate media-
1269*8044SWilliam.Kucharski@Sun.COM  * specific link configuration function. Configures the flow control settings.
1270*8044SWilliam.Kucharski@Sun.COM  * Assuming the adapter has a valid link partner, a valid link should be
1271*8044SWilliam.Kucharski@Sun.COM  * established. Assumes the hardware has previously been reset and the
1272*8044SWilliam.Kucharski@Sun.COM  * transmitter and receiver are not enabled.
1273*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
1274*8044SWilliam.Kucharski@Sun.COM static int
1275*8044SWilliam.Kucharski@Sun.COM e1000_setup_link(struct e1000_hw *hw)
1276*8044SWilliam.Kucharski@Sun.COM {
1277*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl_ext;
1278*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
1279*8044SWilliam.Kucharski@Sun.COM 	uint16_t eeprom_data;
1280*8044SWilliam.Kucharski@Sun.COM 
1281*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_setup_link");
1282*8044SWilliam.Kucharski@Sun.COM 
1283*8044SWilliam.Kucharski@Sun.COM 	/* Read and store word 0x0F of the EEPROM. This word contains bits
1284*8044SWilliam.Kucharski@Sun.COM 	 * that determine the hardware's default PAUSE (flow control) mode,
1285*8044SWilliam.Kucharski@Sun.COM 	 * a bit that determines whether the HW defaults to enabling or
1286*8044SWilliam.Kucharski@Sun.COM 	 * disabling auto-negotiation, and the direction of the
1287*8044SWilliam.Kucharski@Sun.COM 	 * SW defined pins. If there is no SW over-ride of the flow
1288*8044SWilliam.Kucharski@Sun.COM 	 * control setting, then the variable hw->fc will
1289*8044SWilliam.Kucharski@Sun.COM 	 * be initialized based on a value in the EEPROM.
1290*8044SWilliam.Kucharski@Sun.COM 	 */
1291*8044SWilliam.Kucharski@Sun.COM 	if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
1292*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("EEPROM Read Error\n");
1293*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_EEPROM;
1294*8044SWilliam.Kucharski@Sun.COM 	}
1295*8044SWilliam.Kucharski@Sun.COM 
1296*8044SWilliam.Kucharski@Sun.COM 	if(hw->fc == e1000_fc_default) {
1297*8044SWilliam.Kucharski@Sun.COM 		if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
1298*8044SWilliam.Kucharski@Sun.COM 			hw->fc = e1000_fc_none;
1299*8044SWilliam.Kucharski@Sun.COM 		else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
1300*8044SWilliam.Kucharski@Sun.COM 			EEPROM_WORD0F_ASM_DIR)
1301*8044SWilliam.Kucharski@Sun.COM 			hw->fc = e1000_fc_tx_pause;
1302*8044SWilliam.Kucharski@Sun.COM 		else
1303*8044SWilliam.Kucharski@Sun.COM 			hw->fc = e1000_fc_full;
1304*8044SWilliam.Kucharski@Sun.COM 	}
1305*8044SWilliam.Kucharski@Sun.COM 
1306*8044SWilliam.Kucharski@Sun.COM 	/* We want to save off the original Flow Control configuration just
1307*8044SWilliam.Kucharski@Sun.COM 	 * in case we get disconnected and then reconnected into a different
1308*8044SWilliam.Kucharski@Sun.COM 	 * hub or switch with different Flow Control capabilities.
1309*8044SWilliam.Kucharski@Sun.COM 	 */
1310*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0)
1311*8044SWilliam.Kucharski@Sun.COM 		hw->fc &= (~e1000_fc_tx_pause);
1312*8044SWilliam.Kucharski@Sun.COM 
1313*8044SWilliam.Kucharski@Sun.COM #if 0
1314*8044SWilliam.Kucharski@Sun.COM 	/* See e1000_sw_init() of the Linux driver */
1315*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
1316*8044SWilliam.Kucharski@Sun.COM #else
1317*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type < e1000_82543) && (hw->mac_type >= e1000_82543))
1318*8044SWilliam.Kucharski@Sun.COM #endif
1319*8044SWilliam.Kucharski@Sun.COM 		hw->fc &= (~e1000_fc_rx_pause);
1320*8044SWilliam.Kucharski@Sun.COM 
1321*8044SWilliam.Kucharski@Sun.COM #if 0
1322*8044SWilliam.Kucharski@Sun.COM 	hw->original_fc = hw->fc;
1323*8044SWilliam.Kucharski@Sun.COM #endif
1324*8044SWilliam.Kucharski@Sun.COM 
1325*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc);
1326*8044SWilliam.Kucharski@Sun.COM 
1327*8044SWilliam.Kucharski@Sun.COM 	/* Take the 4 bits from EEPROM word 0x0F that determine the initial
1328*8044SWilliam.Kucharski@Sun.COM 	 * polarity value for the SW controlled pins, and setup the
1329*8044SWilliam.Kucharski@Sun.COM 	 * Extended Device Control reg with that info.
1330*8044SWilliam.Kucharski@Sun.COM 	 * This is needed because one of the SW controlled pins is used for
1331*8044SWilliam.Kucharski@Sun.COM 	 * signal detection.  So this should be done before e1000_setup_pcs_link()
1332*8044SWilliam.Kucharski@Sun.COM 	 * or e1000_phy_setup() is called.
1333*8044SWilliam.Kucharski@Sun.COM 	 */
1334*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82543) {
1335*8044SWilliam.Kucharski@Sun.COM 		ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
1336*8044SWilliam.Kucharski@Sun.COM 			SWDPIO__EXT_SHIFT);
1337*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
1338*8044SWilliam.Kucharski@Sun.COM 	}
1339*8044SWilliam.Kucharski@Sun.COM 
1340*8044SWilliam.Kucharski@Sun.COM 	/* Call the necessary subroutine to configure the link. */
1341*8044SWilliam.Kucharski@Sun.COM 	ret_val = (hw->media_type == e1000_media_type_copper) ?
1342*8044SWilliam.Kucharski@Sun.COM 		e1000_setup_copper_link(hw) :
1343*8044SWilliam.Kucharski@Sun.COM 		e1000_setup_fiber_serdes_link(hw);
1344*8044SWilliam.Kucharski@Sun.COM 	if (ret_val < 0) {
1345*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1346*8044SWilliam.Kucharski@Sun.COM 	}
1347*8044SWilliam.Kucharski@Sun.COM 
1348*8044SWilliam.Kucharski@Sun.COM 	/* Initialize the flow control address, type, and PAUSE timer
1349*8044SWilliam.Kucharski@Sun.COM 	 * registers to their default values.  This is done even if flow
1350*8044SWilliam.Kucharski@Sun.COM 	 * control is disabled, because it does not hurt anything to
1351*8044SWilliam.Kucharski@Sun.COM 	 * initialize these registers.
1352*8044SWilliam.Kucharski@Sun.COM 	 */
1353*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
1354*8044SWilliam.Kucharski@Sun.COM 
1355*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
1356*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
1357*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
1358*8044SWilliam.Kucharski@Sun.COM #if 0
1359*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
1360*8044SWilliam.Kucharski@Sun.COM #else
1361*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, FCTTV, FC_DEFAULT_TX_TIMER);
1362*8044SWilliam.Kucharski@Sun.COM #endif
1363*8044SWilliam.Kucharski@Sun.COM 
1364*8044SWilliam.Kucharski@Sun.COM 	/* Set the flow control receive threshold registers.  Normally,
1365*8044SWilliam.Kucharski@Sun.COM 	 * these registers will be set to a default threshold that may be
1366*8044SWilliam.Kucharski@Sun.COM 	 * adjusted later by the driver's runtime code.  However, if the
1367*8044SWilliam.Kucharski@Sun.COM 	 * ability to transmit pause frames in not enabled, then these
1368*8044SWilliam.Kucharski@Sun.COM 	 * registers will be set to 0.
1369*8044SWilliam.Kucharski@Sun.COM 	 */
1370*8044SWilliam.Kucharski@Sun.COM 	if(!(hw->fc & e1000_fc_tx_pause)) {
1371*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, FCRTL, 0);
1372*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, FCRTH, 0);
1373*8044SWilliam.Kucharski@Sun.COM 	} else {
1374*8044SWilliam.Kucharski@Sun.COM 		/* We need to set up the Receive Threshold high and low water marks
1375*8044SWilliam.Kucharski@Sun.COM 		 * as well as (optionally) enabling the transmission of XON frames.
1376*8044SWilliam.Kucharski@Sun.COM 		 */
1377*8044SWilliam.Kucharski@Sun.COM #if 0
1378*8044SWilliam.Kucharski@Sun.COM 		if(hw->fc_send_xon) {
1379*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
1380*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
1381*8044SWilliam.Kucharski@Sun.COM 		} else {
1382*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
1383*8044SWilliam.Kucharski@Sun.COM 			E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
1384*8044SWilliam.Kucharski@Sun.COM 		}
1385*8044SWilliam.Kucharski@Sun.COM #else
1386*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, FCRTL, (FC_DEFAULT_LO_THRESH | E1000_FCRTL_XONE));
1387*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, FCRTH, FC_DEFAULT_HI_THRESH);
1388*8044SWilliam.Kucharski@Sun.COM #endif
1389*8044SWilliam.Kucharski@Sun.COM 	}
1390*8044SWilliam.Kucharski@Sun.COM 	return ret_val;
1391*8044SWilliam.Kucharski@Sun.COM }
1392*8044SWilliam.Kucharski@Sun.COM 
1393*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1394*8044SWilliam.Kucharski@Sun.COM  * Sets up link for a fiber based or serdes based adapter
1395*8044SWilliam.Kucharski@Sun.COM  *
1396*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
1397*8044SWilliam.Kucharski@Sun.COM  *
1398*8044SWilliam.Kucharski@Sun.COM  * Manipulates Physical Coding Sublayer functions in order to configure
1399*8044SWilliam.Kucharski@Sun.COM  * link. Assumes the hardware has been previously reset and the transmitter
1400*8044SWilliam.Kucharski@Sun.COM  * and receiver are not enabled.
1401*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
1402*8044SWilliam.Kucharski@Sun.COM static int
1403*8044SWilliam.Kucharski@Sun.COM e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
1404*8044SWilliam.Kucharski@Sun.COM {
1405*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
1406*8044SWilliam.Kucharski@Sun.COM 	uint32_t status;
1407*8044SWilliam.Kucharski@Sun.COM 	uint32_t txcw = 0;
1408*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
1409*8044SWilliam.Kucharski@Sun.COM 	uint32_t signal = 0;
1410*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
1411*8044SWilliam.Kucharski@Sun.COM 
1412*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_setup_fiber_serdes_link");
1413*8044SWilliam.Kucharski@Sun.COM 
1414*8044SWilliam.Kucharski@Sun.COM 	/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
1415*8044SWilliam.Kucharski@Sun.COM 	 * set when the optics detect a signal. On older adapters, it will be
1416*8044SWilliam.Kucharski@Sun.COM 	 * cleared when there is a signal.  This applies to fiber media only.
1417*8044SWilliam.Kucharski@Sun.COM 	 * If we're on serdes media, adjust the output amplitude to value set in
1418*8044SWilliam.Kucharski@Sun.COM 	 * the EEPROM.
1419*8044SWilliam.Kucharski@Sun.COM 	 */
1420*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
1421*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_fiber)
1422*8044SWilliam.Kucharski@Sun.COM 		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
1423*8044SWilliam.Kucharski@Sun.COM 
1424*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_adjust_serdes_amplitude(hw)))
1425*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1426*8044SWilliam.Kucharski@Sun.COM 
1427*8044SWilliam.Kucharski@Sun.COM 	/* Take the link out of reset */
1428*8044SWilliam.Kucharski@Sun.COM 	ctrl &= ~(E1000_CTRL_LRST);
1429*8044SWilliam.Kucharski@Sun.COM 
1430*8044SWilliam.Kucharski@Sun.COM #if 0
1431*8044SWilliam.Kucharski@Sun.COM 	/* Adjust VCO speed to improve BER performance */
1432*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_set_vco_speed(hw)))
1433*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1434*8044SWilliam.Kucharski@Sun.COM #endif
1435*8044SWilliam.Kucharski@Sun.COM 
1436*8044SWilliam.Kucharski@Sun.COM 	e1000_config_collision_dist(hw);
1437*8044SWilliam.Kucharski@Sun.COM 
1438*8044SWilliam.Kucharski@Sun.COM 	/* Check for a software override of the flow control settings, and setup
1439*8044SWilliam.Kucharski@Sun.COM 	 * the device accordingly.  If auto-negotiation is enabled, then software
1440*8044SWilliam.Kucharski@Sun.COM 	 * will have to set the "PAUSE" bits to the correct value in the Tranmsit
1441*8044SWilliam.Kucharski@Sun.COM 	 * Config Word Register (TXCW) and re-start auto-negotiation.  However, if
1442*8044SWilliam.Kucharski@Sun.COM 	 * auto-negotiation is disabled, then software will have to manually
1443*8044SWilliam.Kucharski@Sun.COM 	 * configure the two flow control enable bits in the CTRL register.
1444*8044SWilliam.Kucharski@Sun.COM 	 *
1445*8044SWilliam.Kucharski@Sun.COM 	 * The possible values of the "fc" parameter are:
1446*8044SWilliam.Kucharski@Sun.COM 	 *      0:  Flow control is completely disabled
1447*8044SWilliam.Kucharski@Sun.COM 	 *      1:  Rx flow control is enabled (we can receive pause frames, but
1448*8044SWilliam.Kucharski@Sun.COM 	 *          not send pause frames).
1449*8044SWilliam.Kucharski@Sun.COM 	 *      2:  Tx flow control is enabled (we can send pause frames but we do
1450*8044SWilliam.Kucharski@Sun.COM 	 *          not support receiving pause frames).
1451*8044SWilliam.Kucharski@Sun.COM 	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
1452*8044SWilliam.Kucharski@Sun.COM 	 */
1453*8044SWilliam.Kucharski@Sun.COM 	switch (hw->fc) {
1454*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_none:
1455*8044SWilliam.Kucharski@Sun.COM 		/* Flow control is completely disabled by a software over-ride. */
1456*8044SWilliam.Kucharski@Sun.COM 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
1457*8044SWilliam.Kucharski@Sun.COM 		break;
1458*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_rx_pause:
1459*8044SWilliam.Kucharski@Sun.COM 		/* RX Flow control is enabled and TX Flow control is disabled by a
1460*8044SWilliam.Kucharski@Sun.COM 		 * software over-ride. Since there really isn't a way to advertise
1461*8044SWilliam.Kucharski@Sun.COM 		 * that we are capable of RX Pause ONLY, we will advertise that we
1462*8044SWilliam.Kucharski@Sun.COM 		 * support both symmetric and asymmetric RX PAUSE. Later, we will
1463*8044SWilliam.Kucharski@Sun.COM 		 *  disable the adapter's ability to send PAUSE frames.
1464*8044SWilliam.Kucharski@Sun.COM 		 */
1465*8044SWilliam.Kucharski@Sun.COM 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
1466*8044SWilliam.Kucharski@Sun.COM 		break;
1467*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_tx_pause:
1468*8044SWilliam.Kucharski@Sun.COM 		/* TX Flow control is enabled, and RX Flow control is disabled, by a
1469*8044SWilliam.Kucharski@Sun.COM 		 * software over-ride.
1470*8044SWilliam.Kucharski@Sun.COM 		 */
1471*8044SWilliam.Kucharski@Sun.COM 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
1472*8044SWilliam.Kucharski@Sun.COM 		break;
1473*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_full:
1474*8044SWilliam.Kucharski@Sun.COM 		/* Flow control (both RX and TX) is enabled by a software over-ride. */
1475*8044SWilliam.Kucharski@Sun.COM 		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
1476*8044SWilliam.Kucharski@Sun.COM 		break;
1477*8044SWilliam.Kucharski@Sun.COM 	default:
1478*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Flow control param set incorrectly\n");
1479*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_CONFIG;
1480*8044SWilliam.Kucharski@Sun.COM 		break;
1481*8044SWilliam.Kucharski@Sun.COM 	}
1482*8044SWilliam.Kucharski@Sun.COM 
1483*8044SWilliam.Kucharski@Sun.COM 	/* Since auto-negotiation is enabled, take the link out of reset (the link
1484*8044SWilliam.Kucharski@Sun.COM 	 * will be in reset, because we previously reset the chip). This will
1485*8044SWilliam.Kucharski@Sun.COM 	 * restart auto-negotiation.  If auto-neogtiation is successful then the
1486*8044SWilliam.Kucharski@Sun.COM 	 * link-up status bit will be set and the flow control enable bits (RFCE
1487*8044SWilliam.Kucharski@Sun.COM 	 * and TFCE) will be set according to their negotiated value.
1488*8044SWilliam.Kucharski@Sun.COM 	 */
1489*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Auto-negotiation enabled\n");
1490*8044SWilliam.Kucharski@Sun.COM 
1491*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, TXCW, txcw);
1492*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, ctrl);
1493*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
1494*8044SWilliam.Kucharski@Sun.COM 
1495*8044SWilliam.Kucharski@Sun.COM 	hw->txcw = txcw;
1496*8044SWilliam.Kucharski@Sun.COM 	mdelay(1);
1497*8044SWilliam.Kucharski@Sun.COM 
1498*8044SWilliam.Kucharski@Sun.COM 	/* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
1499*8044SWilliam.Kucharski@Sun.COM 	 * indication in the Device Status Register.  Time-out if a link isn't
1500*8044SWilliam.Kucharski@Sun.COM 	 * seen in 500 milliseconds seconds (Auto-negotiation should complete in
1501*8044SWilliam.Kucharski@Sun.COM 	 * less than 500 milliseconds even if the other end is doing it in SW).
1502*8044SWilliam.Kucharski@Sun.COM 	 * For internal serdes, we just assume a signal is present, then poll.
1503*8044SWilliam.Kucharski@Sun.COM 	 */
1504*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_internal_serdes ||
1505*8044SWilliam.Kucharski@Sun.COM 	   (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
1506*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Looking for Link\n");
1507*8044SWilliam.Kucharski@Sun.COM 		for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
1508*8044SWilliam.Kucharski@Sun.COM 			mdelay(10);
1509*8044SWilliam.Kucharski@Sun.COM 			status = E1000_READ_REG(hw, STATUS);
1510*8044SWilliam.Kucharski@Sun.COM 			if(status & E1000_STATUS_LU) break;
1511*8044SWilliam.Kucharski@Sun.COM 		}
1512*8044SWilliam.Kucharski@Sun.COM 		if(i == (LINK_UP_TIMEOUT / 10)) {
1513*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Never got a valid link from auto-neg!!!\n");
1514*8044SWilliam.Kucharski@Sun.COM 			hw->autoneg_failed = 1;
1515*8044SWilliam.Kucharski@Sun.COM 			/* AutoNeg failed to achieve a link, so we'll call
1516*8044SWilliam.Kucharski@Sun.COM 			 * e1000_check_for_link. This routine will force the link up if
1517*8044SWilliam.Kucharski@Sun.COM 			 * we detect a signal. This will allow us to communicate with
1518*8044SWilliam.Kucharski@Sun.COM 			 * non-autonegotiating link partners.
1519*8044SWilliam.Kucharski@Sun.COM 			 */
1520*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_check_for_link(hw))) {
1521*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Error while checking for link\n");
1522*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1523*8044SWilliam.Kucharski@Sun.COM 			}
1524*8044SWilliam.Kucharski@Sun.COM 			hw->autoneg_failed = 0;
1525*8044SWilliam.Kucharski@Sun.COM 		} else {
1526*8044SWilliam.Kucharski@Sun.COM 			hw->autoneg_failed = 0;
1527*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Valid Link Found\n");
1528*8044SWilliam.Kucharski@Sun.COM 		}
1529*8044SWilliam.Kucharski@Sun.COM 	} else {
1530*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("No Signal Detected\n");
1531*8044SWilliam.Kucharski@Sun.COM 	}
1532*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
1533*8044SWilliam.Kucharski@Sun.COM }
1534*8044SWilliam.Kucharski@Sun.COM 
1535*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1536*8044SWilliam.Kucharski@Sun.COM * Detects which PHY is present and the speed and duplex
1537*8044SWilliam.Kucharski@Sun.COM *
1538*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1539*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
1540*8044SWilliam.Kucharski@Sun.COM static int
1541*8044SWilliam.Kucharski@Sun.COM e1000_setup_copper_link(struct e1000_hw *hw)
1542*8044SWilliam.Kucharski@Sun.COM {
1543*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
1544*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
1545*8044SWilliam.Kucharski@Sun.COM 	uint16_t i;
1546*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_data;
1547*8044SWilliam.Kucharski@Sun.COM 
1548*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_setup_copper_link");
1549*8044SWilliam.Kucharski@Sun.COM 
1550*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
1551*8044SWilliam.Kucharski@Sun.COM 	/* With 82543, we need to force speed and duplex on the MAC equal to what
1552*8044SWilliam.Kucharski@Sun.COM 	 * the PHY speed and duplex configuration is. In addition, we need to
1553*8044SWilliam.Kucharski@Sun.COM 	 * perform a hardware reset on the PHY to take it out of reset.
1554*8044SWilliam.Kucharski@Sun.COM 	 */
1555*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82543) {
1556*8044SWilliam.Kucharski@Sun.COM 		ctrl |= E1000_CTRL_SLU;
1557*8044SWilliam.Kucharski@Sun.COM 		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
1558*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl);
1559*8044SWilliam.Kucharski@Sun.COM 	} else {
1560*8044SWilliam.Kucharski@Sun.COM 		ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
1561*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl);
1562*8044SWilliam.Kucharski@Sun.COM 		e1000_phy_hw_reset(hw);
1563*8044SWilliam.Kucharski@Sun.COM 	}
1564*8044SWilliam.Kucharski@Sun.COM 
1565*8044SWilliam.Kucharski@Sun.COM 	/* Make sure we have a valid PHY */
1566*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_detect_gig_phy(hw))) {
1567*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Error, did not detect valid phy.\n");
1568*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1569*8044SWilliam.Kucharski@Sun.COM 	}
1570*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
1571*8044SWilliam.Kucharski@Sun.COM 
1572*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type <= e1000_82543 ||
1573*8044SWilliam.Kucharski@Sun.COM 	   hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
1574*8044SWilliam.Kucharski@Sun.COM #if 0
1575*8044SWilliam.Kucharski@Sun.COM 	   hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
1576*8044SWilliam.Kucharski@Sun.COM 		hw->phy_reset_disable = FALSE;
1577*8044SWilliam.Kucharski@Sun.COM 
1578*8044SWilliam.Kucharski@Sun.COM 	if(!hw->phy_reset_disable) {
1579*8044SWilliam.Kucharski@Sun.COM #else
1580*8044SWilliam.Kucharski@Sun.COM 	   hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
1581*8044SWilliam.Kucharski@Sun.COM #endif
1582*8044SWilliam.Kucharski@Sun.COM 	if (hw->phy_type == e1000_phy_igp) {
1583*8044SWilliam.Kucharski@Sun.COM 
1584*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_phy_reset(hw))) {
1585*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error Resetting the PHY\n");
1586*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1587*8044SWilliam.Kucharski@Sun.COM 		}
1588*8044SWilliam.Kucharski@Sun.COM 
1589*8044SWilliam.Kucharski@Sun.COM 		/* Wait 10ms for MAC to configure PHY from eeprom settings */
1590*8044SWilliam.Kucharski@Sun.COM 		mdelay(15);
1591*8044SWilliam.Kucharski@Sun.COM 
1592*8044SWilliam.Kucharski@Sun.COM #if 0
1593*8044SWilliam.Kucharski@Sun.COM 		/* disable lplu d3 during driver init */
1594*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) {
1595*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error Disabling LPLU D3\n");
1596*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1597*8044SWilliam.Kucharski@Sun.COM 		}
1598*8044SWilliam.Kucharski@Sun.COM 
1599*8044SWilliam.Kucharski@Sun.COM 		/* Configure mdi-mdix settings */
1600*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
1601*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
1602*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1603*8044SWilliam.Kucharski@Sun.COM 
1604*8044SWilliam.Kucharski@Sun.COM 		if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1605*8044SWilliam.Kucharski@Sun.COM 			hw->dsp_config_state = e1000_dsp_config_disabled;
1606*8044SWilliam.Kucharski@Sun.COM 			/* Force MDI for IGP B-0 PHY */
1607*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
1608*8044SWilliam.Kucharski@Sun.COM 			              IGP01E1000_PSCR_FORCE_MDI_MDIX);
1609*8044SWilliam.Kucharski@Sun.COM 			hw->mdix = 1;
1610*8044SWilliam.Kucharski@Sun.COM 
1611*8044SWilliam.Kucharski@Sun.COM 		} else {
1612*8044SWilliam.Kucharski@Sun.COM 			hw->dsp_config_state = e1000_dsp_config_enabled;
1613*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
1614*8044SWilliam.Kucharski@Sun.COM 
1615*8044SWilliam.Kucharski@Sun.COM 			switch (hw->mdix) {
1616*8044SWilliam.Kucharski@Sun.COM 			case 1:
1617*8044SWilliam.Kucharski@Sun.COM 				phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
1618*8044SWilliam.Kucharski@Sun.COM 				break;
1619*8044SWilliam.Kucharski@Sun.COM 			case 2:
1620*8044SWilliam.Kucharski@Sun.COM 				phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
1621*8044SWilliam.Kucharski@Sun.COM 				break;
1622*8044SWilliam.Kucharski@Sun.COM 			case 0:
1623*8044SWilliam.Kucharski@Sun.COM 			default:
1624*8044SWilliam.Kucharski@Sun.COM 				phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
1625*8044SWilliam.Kucharski@Sun.COM 				break;
1626*8044SWilliam.Kucharski@Sun.COM 			}
1627*8044SWilliam.Kucharski@Sun.COM 		}
1628*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
1629*8044SWilliam.Kucharski@Sun.COM 		                                  phy_data)))
1630*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1631*8044SWilliam.Kucharski@Sun.COM 
1632*8044SWilliam.Kucharski@Sun.COM 		/* set auto-master slave resolution settings */
1633*8044SWilliam.Kucharski@Sun.COM 		e1000_ms_type phy_ms_setting = hw->master_slave;
1634*8044SWilliam.Kucharski@Sun.COM 
1635*8044SWilliam.Kucharski@Sun.COM 		if(hw->ffe_config_state == e1000_ffe_config_active)
1636*8044SWilliam.Kucharski@Sun.COM 			hw->ffe_config_state = e1000_ffe_config_enabled;
1637*8044SWilliam.Kucharski@Sun.COM 
1638*8044SWilliam.Kucharski@Sun.COM 		if(hw->dsp_config_state == e1000_dsp_config_activated)
1639*8044SWilliam.Kucharski@Sun.COM 			hw->dsp_config_state = e1000_dsp_config_enabled;
1640*8044SWilliam.Kucharski@Sun.COM #endif
1641*8044SWilliam.Kucharski@Sun.COM 
1642*8044SWilliam.Kucharski@Sun.COM 		/* when autonegotiation advertisment is only 1000Mbps then we
1643*8044SWilliam.Kucharski@Sun.COM 		 * should disable SmartSpeed and enable Auto MasterSlave
1644*8044SWilliam.Kucharski@Sun.COM 		 * resolution as hardware default. */
1645*8044SWilliam.Kucharski@Sun.COM 		if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
1646*8044SWilliam.Kucharski@Sun.COM 			/* Disable SmartSpeed */
1647*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_read_phy_reg(hw,
1648*8044SWilliam.Kucharski@Sun.COM 			                                 IGP01E1000_PHY_PORT_CONFIG,
1649*8044SWilliam.Kucharski@Sun.COM 			                                 &phy_data)))
1650*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1651*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1652*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_write_phy_reg(hw,
1653*8044SWilliam.Kucharski@Sun.COM 			                                  IGP01E1000_PHY_PORT_CONFIG,
1654*8044SWilliam.Kucharski@Sun.COM 			                                  phy_data)))
1655*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1656*8044SWilliam.Kucharski@Sun.COM 			/* Set auto Master/Slave resolution process */
1657*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
1658*8044SWilliam.Kucharski@Sun.COM 			                                 &phy_data)))
1659*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1660*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~CR_1000T_MS_ENABLE;
1661*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
1662*8044SWilliam.Kucharski@Sun.COM 			                                  phy_data)))
1663*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1664*8044SWilliam.Kucharski@Sun.COM 		}
1665*8044SWilliam.Kucharski@Sun.COM 
1666*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
1667*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
1668*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1669*8044SWilliam.Kucharski@Sun.COM 
1670*8044SWilliam.Kucharski@Sun.COM #if 0
1671*8044SWilliam.Kucharski@Sun.COM 		/* load defaults for future use */
1672*8044SWilliam.Kucharski@Sun.COM 		hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
1673*8044SWilliam.Kucharski@Sun.COM 		                            ((phy_data & CR_1000T_MS_VALUE) ?
1674*8044SWilliam.Kucharski@Sun.COM 		                             e1000_ms_force_master :
1675*8044SWilliam.Kucharski@Sun.COM 		                             e1000_ms_force_slave) :
1676*8044SWilliam.Kucharski@Sun.COM 		                             e1000_ms_auto;
1677*8044SWilliam.Kucharski@Sun.COM 
1678*8044SWilliam.Kucharski@Sun.COM 		switch (phy_ms_setting) {
1679*8044SWilliam.Kucharski@Sun.COM 		case e1000_ms_force_master:
1680*8044SWilliam.Kucharski@Sun.COM 			phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
1681*8044SWilliam.Kucharski@Sun.COM 			break;
1682*8044SWilliam.Kucharski@Sun.COM 		case e1000_ms_force_slave:
1683*8044SWilliam.Kucharski@Sun.COM 			phy_data |= CR_1000T_MS_ENABLE;
1684*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~(CR_1000T_MS_VALUE);
1685*8044SWilliam.Kucharski@Sun.COM 			break;
1686*8044SWilliam.Kucharski@Sun.COM 		case e1000_ms_auto:
1687*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~CR_1000T_MS_ENABLE;
1688*8044SWilliam.Kucharski@Sun.COM 		default:
1689*8044SWilliam.Kucharski@Sun.COM 			break;
1690*8044SWilliam.Kucharski@Sun.COM 		}
1691*8044SWilliam.Kucharski@Sun.COM #endif
1692*8044SWilliam.Kucharski@Sun.COM 
1693*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
1694*8044SWilliam.Kucharski@Sun.COM 		                                  phy_data)))
1695*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1696*8044SWilliam.Kucharski@Sun.COM 	} else {
1697*8044SWilliam.Kucharski@Sun.COM 		/* Enable CRS on TX. This must be set for half-duplex operation. */
1698*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
1699*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
1700*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1701*8044SWilliam.Kucharski@Sun.COM 
1702*8044SWilliam.Kucharski@Sun.COM 		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
1703*8044SWilliam.Kucharski@Sun.COM 
1704*8044SWilliam.Kucharski@Sun.COM 		/* Options:
1705*8044SWilliam.Kucharski@Sun.COM 		 *   MDI/MDI-X = 0 (default)
1706*8044SWilliam.Kucharski@Sun.COM 		 *   0 - Auto for all speeds
1707*8044SWilliam.Kucharski@Sun.COM 		 *   1 - MDI mode
1708*8044SWilliam.Kucharski@Sun.COM 		 *   2 - MDI-X mode
1709*8044SWilliam.Kucharski@Sun.COM 		 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
1710*8044SWilliam.Kucharski@Sun.COM 		 */
1711*8044SWilliam.Kucharski@Sun.COM #if 0
1712*8044SWilliam.Kucharski@Sun.COM 		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
1713*8044SWilliam.Kucharski@Sun.COM 
1714*8044SWilliam.Kucharski@Sun.COM 		switch (hw->mdix) {
1715*8044SWilliam.Kucharski@Sun.COM 		case 1:
1716*8044SWilliam.Kucharski@Sun.COM 			phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
1717*8044SWilliam.Kucharski@Sun.COM 			break;
1718*8044SWilliam.Kucharski@Sun.COM 		case 2:
1719*8044SWilliam.Kucharski@Sun.COM 			phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
1720*8044SWilliam.Kucharski@Sun.COM 			break;
1721*8044SWilliam.Kucharski@Sun.COM 		case 3:
1722*8044SWilliam.Kucharski@Sun.COM 			phy_data |= M88E1000_PSCR_AUTO_X_1000T;
1723*8044SWilliam.Kucharski@Sun.COM 			break;
1724*8044SWilliam.Kucharski@Sun.COM 		case 0:
1725*8044SWilliam.Kucharski@Sun.COM 		default:
1726*8044SWilliam.Kucharski@Sun.COM #endif
1727*8044SWilliam.Kucharski@Sun.COM 			phy_data |= M88E1000_PSCR_AUTO_X_MODE;
1728*8044SWilliam.Kucharski@Sun.COM #if 0
1729*8044SWilliam.Kucharski@Sun.COM 			break;
1730*8044SWilliam.Kucharski@Sun.COM 		}
1731*8044SWilliam.Kucharski@Sun.COM #endif
1732*8044SWilliam.Kucharski@Sun.COM 
1733*8044SWilliam.Kucharski@Sun.COM 		/* Options:
1734*8044SWilliam.Kucharski@Sun.COM 		 *   disable_polarity_correction = 0 (default)
1735*8044SWilliam.Kucharski@Sun.COM 		 *       Automatic Correction for Reversed Cable Polarity
1736*8044SWilliam.Kucharski@Sun.COM 		 *   0 - Disabled
1737*8044SWilliam.Kucharski@Sun.COM 		 *   1 - Enabled
1738*8044SWilliam.Kucharski@Sun.COM 		 */
1739*8044SWilliam.Kucharski@Sun.COM 		phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
1740*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
1741*8044SWilliam.Kucharski@Sun.COM 		                                  phy_data)))
1742*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1743*8044SWilliam.Kucharski@Sun.COM 
1744*8044SWilliam.Kucharski@Sun.COM 		/* Force TX_CLK in the Extended PHY Specific Control Register
1745*8044SWilliam.Kucharski@Sun.COM 		 * to 25MHz clock.
1746*8044SWilliam.Kucharski@Sun.COM 		 */
1747*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
1748*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
1749*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1750*8044SWilliam.Kucharski@Sun.COM 
1751*8044SWilliam.Kucharski@Sun.COM 		phy_data |= M88E1000_EPSCR_TX_CLK_25;
1752*8044SWilliam.Kucharski@Sun.COM 
1753*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1754*8044SWilliam.Kucharski@Sun.COM 		if (hw->phy_revision < M88E1011_I_REV_4) {
1755*8044SWilliam.Kucharski@Sun.COM #endif
1756*8044SWilliam.Kucharski@Sun.COM 			/* Configure Master and Slave downshift values */
1757*8044SWilliam.Kucharski@Sun.COM 			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
1758*8044SWilliam.Kucharski@Sun.COM 				M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
1759*8044SWilliam.Kucharski@Sun.COM 			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
1760*8044SWilliam.Kucharski@Sun.COM 				M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
1761*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_write_phy_reg(hw,
1762*8044SWilliam.Kucharski@Sun.COM 			                                  M88E1000_EXT_PHY_SPEC_CTRL,
1763*8044SWilliam.Kucharski@Sun.COM 			                                  phy_data)))
1764*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1765*8044SWilliam.Kucharski@Sun.COM 		}
1766*8044SWilliam.Kucharski@Sun.COM 
1767*8044SWilliam.Kucharski@Sun.COM 		/* SW Reset the PHY so all changes take effect */
1768*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_phy_reset(hw))) {
1769*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error Resetting the PHY\n");
1770*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1771*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1772*8044SWilliam.Kucharski@Sun.COM 		}
1773*8044SWilliam.Kucharski@Sun.COM #endif
1774*8044SWilliam.Kucharski@Sun.COM 	}
1775*8044SWilliam.Kucharski@Sun.COM 
1776*8044SWilliam.Kucharski@Sun.COM 	/* Options:
1777*8044SWilliam.Kucharski@Sun.COM 	 *   autoneg = 1 (default)
1778*8044SWilliam.Kucharski@Sun.COM 	 *      PHY will advertise value(s) parsed from
1779*8044SWilliam.Kucharski@Sun.COM 	 *      autoneg_advertised and fc
1780*8044SWilliam.Kucharski@Sun.COM 	 *   autoneg = 0
1781*8044SWilliam.Kucharski@Sun.COM 	 *      PHY will be set to 10H, 10F, 100H, or 100F
1782*8044SWilliam.Kucharski@Sun.COM 	 *      depending on value parsed from forced_speed_duplex.
1783*8044SWilliam.Kucharski@Sun.COM 	 */
1784*8044SWilliam.Kucharski@Sun.COM 
1785*8044SWilliam.Kucharski@Sun.COM 	/* Is autoneg enabled?  This is enabled by default or by software
1786*8044SWilliam.Kucharski@Sun.COM 	 * override.  If so, call e1000_phy_setup_autoneg routine to parse the
1787*8044SWilliam.Kucharski@Sun.COM 	 * autoneg_advertised and fc options. If autoneg is NOT enabled, then
1788*8044SWilliam.Kucharski@Sun.COM 	 * the user should have provided a speed/duplex override.  If so, then
1789*8044SWilliam.Kucharski@Sun.COM 	 * call e1000_phy_force_speed_duplex to parse and set this up.
1790*8044SWilliam.Kucharski@Sun.COM 	 */
1791*8044SWilliam.Kucharski@Sun.COM 	/* Perform some bounds checking on the hw->autoneg_advertised
1792*8044SWilliam.Kucharski@Sun.COM 	 * parameter.  If this variable is zero, then set it to the default.
1793*8044SWilliam.Kucharski@Sun.COM 	 */
1794*8044SWilliam.Kucharski@Sun.COM 	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1795*8044SWilliam.Kucharski@Sun.COM 
1796*8044SWilliam.Kucharski@Sun.COM 	/* If autoneg_advertised is zero, we assume it was not defaulted
1797*8044SWilliam.Kucharski@Sun.COM 	 * by the calling code so we set to advertise full capability.
1798*8044SWilliam.Kucharski@Sun.COM 	 */
1799*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised == 0)
1800*8044SWilliam.Kucharski@Sun.COM 		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1801*8044SWilliam.Kucharski@Sun.COM 
1802*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
1803*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_phy_setup_autoneg(hw))) {
1804*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Error Setting up Auto-Negotiation\n");
1805*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1806*8044SWilliam.Kucharski@Sun.COM 	}
1807*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Restarting Auto-Neg\n");
1808*8044SWilliam.Kucharski@Sun.COM 
1809*8044SWilliam.Kucharski@Sun.COM 	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
1810*8044SWilliam.Kucharski@Sun.COM 	 * the Auto Neg Restart bit in the PHY control register.
1811*8044SWilliam.Kucharski@Sun.COM 	 */
1812*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
1813*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1814*8044SWilliam.Kucharski@Sun.COM 
1815*8044SWilliam.Kucharski@Sun.COM 	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
1816*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
1817*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1818*8044SWilliam.Kucharski@Sun.COM 
1819*8044SWilliam.Kucharski@Sun.COM #if 0
1820*8044SWilliam.Kucharski@Sun.COM 	/* Does the user want to wait for Auto-Neg to complete here, or
1821*8044SWilliam.Kucharski@Sun.COM 	 * check at a later time (for example, callback routine).
1822*8044SWilliam.Kucharski@Sun.COM 	 */
1823*8044SWilliam.Kucharski@Sun.COM 	if(hw->wait_autoneg_complete) {
1824*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_wait_autoneg(hw))) {
1825*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error while waiting for autoneg to complete\n");
1826*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1827*8044SWilliam.Kucharski@Sun.COM 		}
1828*8044SWilliam.Kucharski@Sun.COM 	}
1829*8044SWilliam.Kucharski@Sun.COM #else
1830*8044SWilliam.Kucharski@Sun.COM 	/* If we do not wait for autonegotiation to complete I
1831*8044SWilliam.Kucharski@Sun.COM 	 * do not see a valid link status.
1832*8044SWilliam.Kucharski@Sun.COM 	 */
1833*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_wait_autoneg(hw))) {
1834*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Error while waiting for autoneg to complete\n");
1835*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1836*8044SWilliam.Kucharski@Sun.COM 	}
1837*8044SWilliam.Kucharski@Sun.COM #endif
1838*8044SWilliam.Kucharski@Sun.COM 	} /* !hw->phy_reset_disable */
1839*8044SWilliam.Kucharski@Sun.COM 
1840*8044SWilliam.Kucharski@Sun.COM 	/* Check link status. Wait up to 100 microseconds for link to become
1841*8044SWilliam.Kucharski@Sun.COM 	 * valid.
1842*8044SWilliam.Kucharski@Sun.COM 	 */
1843*8044SWilliam.Kucharski@Sun.COM 	for(i = 0; i < 10; i++) {
1844*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
1845*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1846*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
1847*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
1848*8044SWilliam.Kucharski@Sun.COM 
1849*8044SWilliam.Kucharski@Sun.COM 		if(phy_data & MII_SR_LINK_STATUS) {
1850*8044SWilliam.Kucharski@Sun.COM 			/* We have link, so we need to finish the config process:
1851*8044SWilliam.Kucharski@Sun.COM 			 *   1) Set up the MAC to the current PHY speed/duplex
1852*8044SWilliam.Kucharski@Sun.COM 			 *      if we are on 82543.  If we
1853*8044SWilliam.Kucharski@Sun.COM 			 *      are on newer silicon, we only need to configure
1854*8044SWilliam.Kucharski@Sun.COM 			 *      collision distance in the Transmit Control Register.
1855*8044SWilliam.Kucharski@Sun.COM 			 *   2) Set up flow control on the MAC to that established with
1856*8044SWilliam.Kucharski@Sun.COM 			 *      the link partner.
1857*8044SWilliam.Kucharski@Sun.COM 			 */
1858*8044SWilliam.Kucharski@Sun.COM 			if(hw->mac_type >= e1000_82544) {
1859*8044SWilliam.Kucharski@Sun.COM 				e1000_config_collision_dist(hw);
1860*8044SWilliam.Kucharski@Sun.COM 			} else {
1861*8044SWilliam.Kucharski@Sun.COM 				if((ret_val = e1000_config_mac_to_phy(hw))) {
1862*8044SWilliam.Kucharski@Sun.COM 					DEBUGOUT("Error configuring MAC to PHY settings\n");
1863*8044SWilliam.Kucharski@Sun.COM 					return ret_val;
1864*8044SWilliam.Kucharski@Sun.COM 				}
1865*8044SWilliam.Kucharski@Sun.COM 			}
1866*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_config_fc_after_link_up(hw))) {
1867*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Error Configuring Flow Control\n");
1868*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
1869*8044SWilliam.Kucharski@Sun.COM 			}
1870*8044SWilliam.Kucharski@Sun.COM #if 0
1871*8044SWilliam.Kucharski@Sun.COM 			if(hw->phy_type == e1000_phy_igp) {
1872*8044SWilliam.Kucharski@Sun.COM 				if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) {
1873*8044SWilliam.Kucharski@Sun.COM 					DEBUGOUT("Error Configuring DSP after link up\n");
1874*8044SWilliam.Kucharski@Sun.COM 					return ret_val;
1875*8044SWilliam.Kucharski@Sun.COM 				}
1876*8044SWilliam.Kucharski@Sun.COM 			}
1877*8044SWilliam.Kucharski@Sun.COM #endif
1878*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Valid link established!!!\n");
1879*8044SWilliam.Kucharski@Sun.COM 			return E1000_SUCCESS;
1880*8044SWilliam.Kucharski@Sun.COM 		}
1881*8044SWilliam.Kucharski@Sun.COM 		udelay(10);
1882*8044SWilliam.Kucharski@Sun.COM 	}
1883*8044SWilliam.Kucharski@Sun.COM 
1884*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Unable to establish link!!!\n");
1885*8044SWilliam.Kucharski@Sun.COM 	return -E1000_ERR_NOLINK;
1886*8044SWilliam.Kucharski@Sun.COM }
1887*8044SWilliam.Kucharski@Sun.COM 
1888*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1889*8044SWilliam.Kucharski@Sun.COM * Configures PHY autoneg and flow control advertisement settings
1890*8044SWilliam.Kucharski@Sun.COM *
1891*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1892*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
1893*8044SWilliam.Kucharski@Sun.COM static int
1894*8044SWilliam.Kucharski@Sun.COM e1000_phy_setup_autoneg(struct e1000_hw *hw)
1895*8044SWilliam.Kucharski@Sun.COM {
1896*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
1897*8044SWilliam.Kucharski@Sun.COM 	uint16_t mii_autoneg_adv_reg;
1898*8044SWilliam.Kucharski@Sun.COM 	uint16_t mii_1000t_ctrl_reg;
1899*8044SWilliam.Kucharski@Sun.COM 
1900*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_phy_setup_autoneg");
1901*8044SWilliam.Kucharski@Sun.COM 
1902*8044SWilliam.Kucharski@Sun.COM 	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
1903*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
1904*8044SWilliam.Kucharski@Sun.COM 	                                 &mii_autoneg_adv_reg)))
1905*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1906*8044SWilliam.Kucharski@Sun.COM 
1907*8044SWilliam.Kucharski@Sun.COM 	/* Read the MII 1000Base-T Control Register (Address 9). */
1908*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg)))
1909*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
1910*8044SWilliam.Kucharski@Sun.COM 
1911*8044SWilliam.Kucharski@Sun.COM 	/* Need to parse both autoneg_advertised and fc and set up
1912*8044SWilliam.Kucharski@Sun.COM 	 * the appropriate PHY registers.  First we will parse for
1913*8044SWilliam.Kucharski@Sun.COM 	 * autoneg_advertised software override.  Since we can advertise
1914*8044SWilliam.Kucharski@Sun.COM 	 * a plethora of combinations, we need to check each bit
1915*8044SWilliam.Kucharski@Sun.COM 	 * individually.
1916*8044SWilliam.Kucharski@Sun.COM 	 */
1917*8044SWilliam.Kucharski@Sun.COM 
1918*8044SWilliam.Kucharski@Sun.COM 	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
1919*8044SWilliam.Kucharski@Sun.COM 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
1920*8044SWilliam.Kucharski@Sun.COM 	 * the  1000Base-T Control Register (Address 9).
1921*8044SWilliam.Kucharski@Sun.COM 	 */
1922*8044SWilliam.Kucharski@Sun.COM 	mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
1923*8044SWilliam.Kucharski@Sun.COM 	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
1924*8044SWilliam.Kucharski@Sun.COM 
1925*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
1926*8044SWilliam.Kucharski@Sun.COM 
1927*8044SWilliam.Kucharski@Sun.COM 	/* Do we want to advertise 10 Mb Half Duplex? */
1928*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_10_HALF) {
1929*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 10mb Half duplex\n");
1930*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
1931*8044SWilliam.Kucharski@Sun.COM 	}
1932*8044SWilliam.Kucharski@Sun.COM 
1933*8044SWilliam.Kucharski@Sun.COM 	/* Do we want to advertise 10 Mb Full Duplex? */
1934*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_10_FULL) {
1935*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 10mb Full duplex\n");
1936*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
1937*8044SWilliam.Kucharski@Sun.COM 	}
1938*8044SWilliam.Kucharski@Sun.COM 
1939*8044SWilliam.Kucharski@Sun.COM 	/* Do we want to advertise 100 Mb Half Duplex? */
1940*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_100_HALF) {
1941*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 100mb Half duplex\n");
1942*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
1943*8044SWilliam.Kucharski@Sun.COM 	}
1944*8044SWilliam.Kucharski@Sun.COM 
1945*8044SWilliam.Kucharski@Sun.COM 	/* Do we want to advertise 100 Mb Full Duplex? */
1946*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_100_FULL) {
1947*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 100mb Full duplex\n");
1948*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
1949*8044SWilliam.Kucharski@Sun.COM 	}
1950*8044SWilliam.Kucharski@Sun.COM 
1951*8044SWilliam.Kucharski@Sun.COM 	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
1952*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_1000_HALF) {
1953*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
1954*8044SWilliam.Kucharski@Sun.COM 	}
1955*8044SWilliam.Kucharski@Sun.COM 
1956*8044SWilliam.Kucharski@Sun.COM 	/* Do we want to advertise 1000 Mb Full Duplex? */
1957*8044SWilliam.Kucharski@Sun.COM 	if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {
1958*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Advertise 1000mb Full duplex\n");
1959*8044SWilliam.Kucharski@Sun.COM 		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
1960*8044SWilliam.Kucharski@Sun.COM 	}
1961*8044SWilliam.Kucharski@Sun.COM 
1962*8044SWilliam.Kucharski@Sun.COM 	/* Check for a software override of the flow control settings, and
1963*8044SWilliam.Kucharski@Sun.COM 	 * setup the PHY advertisement registers accordingly.  If
1964*8044SWilliam.Kucharski@Sun.COM 	 * auto-negotiation is enabled, then software will have to set the
1965*8044SWilliam.Kucharski@Sun.COM 	 * "PAUSE" bits to the correct value in the Auto-Negotiation
1966*8044SWilliam.Kucharski@Sun.COM 	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
1967*8044SWilliam.Kucharski@Sun.COM 	 *
1968*8044SWilliam.Kucharski@Sun.COM 	 * The possible values of the "fc" parameter are:
1969*8044SWilliam.Kucharski@Sun.COM 	 *      0:  Flow control is completely disabled
1970*8044SWilliam.Kucharski@Sun.COM 	 *      1:  Rx flow control is enabled (we can receive pause frames
1971*8044SWilliam.Kucharski@Sun.COM 	 *          but not send pause frames).
1972*8044SWilliam.Kucharski@Sun.COM 	 *      2:  Tx flow control is enabled (we can send pause frames
1973*8044SWilliam.Kucharski@Sun.COM 	 *          but we do not support receiving pause frames).
1974*8044SWilliam.Kucharski@Sun.COM 	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
1975*8044SWilliam.Kucharski@Sun.COM 	 *  other:  No software override.  The flow control configuration
1976*8044SWilliam.Kucharski@Sun.COM 	 *          in the EEPROM is used.
1977*8044SWilliam.Kucharski@Sun.COM 	 */
1978*8044SWilliam.Kucharski@Sun.COM 	switch (hw->fc) {
1979*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_none: /* 0 */
1980*8044SWilliam.Kucharski@Sun.COM 		/* Flow control (RX & TX) is completely disabled by a
1981*8044SWilliam.Kucharski@Sun.COM 		 * software over-ride.
1982*8044SWilliam.Kucharski@Sun.COM 		 */
1983*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
1984*8044SWilliam.Kucharski@Sun.COM 		break;
1985*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_rx_pause: /* 1 */
1986*8044SWilliam.Kucharski@Sun.COM 		/* RX Flow control is enabled, and TX Flow control is
1987*8044SWilliam.Kucharski@Sun.COM 		 * disabled, by a software over-ride.
1988*8044SWilliam.Kucharski@Sun.COM 		 */
1989*8044SWilliam.Kucharski@Sun.COM 		/* Since there really isn't a way to advertise that we are
1990*8044SWilliam.Kucharski@Sun.COM 		 * capable of RX Pause ONLY, we will advertise that we
1991*8044SWilliam.Kucharski@Sun.COM 		 * support both symmetric and asymmetric RX PAUSE.  Later
1992*8044SWilliam.Kucharski@Sun.COM 		 * (in e1000_config_fc_after_link_up) we will disable the
1993*8044SWilliam.Kucharski@Sun.COM 		 *hw's ability to send PAUSE frames.
1994*8044SWilliam.Kucharski@Sun.COM 		 */
1995*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
1996*8044SWilliam.Kucharski@Sun.COM 		break;
1997*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_tx_pause: /* 2 */
1998*8044SWilliam.Kucharski@Sun.COM 		/* TX Flow control is enabled, and RX Flow control is
1999*8044SWilliam.Kucharski@Sun.COM 		 * disabled, by a software over-ride.
2000*8044SWilliam.Kucharski@Sun.COM 		 */
2001*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
2002*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
2003*8044SWilliam.Kucharski@Sun.COM 		break;
2004*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_full: /* 3 */
2005*8044SWilliam.Kucharski@Sun.COM 		/* Flow control (both RX and TX) is enabled by a software
2006*8044SWilliam.Kucharski@Sun.COM 		 * over-ride.
2007*8044SWilliam.Kucharski@Sun.COM 		 */
2008*8044SWilliam.Kucharski@Sun.COM 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
2009*8044SWilliam.Kucharski@Sun.COM 		break;
2010*8044SWilliam.Kucharski@Sun.COM 	default:
2011*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Flow control param set incorrectly\n");
2012*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_CONFIG;
2013*8044SWilliam.Kucharski@Sun.COM 	}
2014*8044SWilliam.Kucharski@Sun.COM 
2015*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV,
2016*8044SWilliam.Kucharski@Sun.COM 	                       mii_autoneg_adv_reg)))
2017*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
2018*8044SWilliam.Kucharski@Sun.COM 
2019*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
2020*8044SWilliam.Kucharski@Sun.COM 
2021*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg)))
2022*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
2023*8044SWilliam.Kucharski@Sun.COM 
2024*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2025*8044SWilliam.Kucharski@Sun.COM }
2026*8044SWilliam.Kucharski@Sun.COM 
2027*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2028*8044SWilliam.Kucharski@Sun.COM * Sets the collision distance in the Transmit Control register
2029*8044SWilliam.Kucharski@Sun.COM *
2030*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2031*8044SWilliam.Kucharski@Sun.COM *
2032*8044SWilliam.Kucharski@Sun.COM * Link should have been established previously. Reads the speed and duplex
2033*8044SWilliam.Kucharski@Sun.COM * information from the Device Status register.
2034*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2035*8044SWilliam.Kucharski@Sun.COM static void
2036*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(struct e1000_hw *hw)
2037*8044SWilliam.Kucharski@Sun.COM {
2038*8044SWilliam.Kucharski@Sun.COM 	uint32_t tctl;
2039*8044SWilliam.Kucharski@Sun.COM 
2040*8044SWilliam.Kucharski@Sun.COM 	tctl = E1000_READ_REG(hw, TCTL);
2041*8044SWilliam.Kucharski@Sun.COM 
2042*8044SWilliam.Kucharski@Sun.COM 	tctl &= ~E1000_TCTL_COLD;
2043*8044SWilliam.Kucharski@Sun.COM 	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
2044*8044SWilliam.Kucharski@Sun.COM 
2045*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, TCTL, tctl);
2046*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
2047*8044SWilliam.Kucharski@Sun.COM }
2048*8044SWilliam.Kucharski@Sun.COM 
2049*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2050*8044SWilliam.Kucharski@Sun.COM * Sets MAC speed and duplex settings to reflect the those in the PHY
2051*8044SWilliam.Kucharski@Sun.COM *
2052*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2053*8044SWilliam.Kucharski@Sun.COM * mii_reg - data to write to the MII control register
2054*8044SWilliam.Kucharski@Sun.COM *
2055*8044SWilliam.Kucharski@Sun.COM * The contents of the PHY register containing the needed information need to
2056*8044SWilliam.Kucharski@Sun.COM * be passed in.
2057*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2058*8044SWilliam.Kucharski@Sun.COM static int
2059*8044SWilliam.Kucharski@Sun.COM e1000_config_mac_to_phy(struct e1000_hw *hw)
2060*8044SWilliam.Kucharski@Sun.COM {
2061*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
2062*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
2063*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_data;
2064*8044SWilliam.Kucharski@Sun.COM 
2065*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_config_mac_to_phy");
2066*8044SWilliam.Kucharski@Sun.COM 
2067*8044SWilliam.Kucharski@Sun.COM 	/* Read the Device Control Register and set the bits to Force Speed
2068*8044SWilliam.Kucharski@Sun.COM 	 * and Duplex.
2069*8044SWilliam.Kucharski@Sun.COM 	 */
2070*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
2071*8044SWilliam.Kucharski@Sun.COM 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
2072*8044SWilliam.Kucharski@Sun.COM 	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
2073*8044SWilliam.Kucharski@Sun.COM 
2074*8044SWilliam.Kucharski@Sun.COM 	/* Set up duplex in the Device Control and Transmit Control
2075*8044SWilliam.Kucharski@Sun.COM 	 * registers depending on negotiated values.
2076*8044SWilliam.Kucharski@Sun.COM 	 */
2077*8044SWilliam.Kucharski@Sun.COM 	if (hw->phy_type == e1000_phy_igp) {
2078*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
2079*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
2080*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2081*8044SWilliam.Kucharski@Sun.COM 
2082*8044SWilliam.Kucharski@Sun.COM 		if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
2083*8044SWilliam.Kucharski@Sun.COM 		else ctrl &= ~E1000_CTRL_FD;
2084*8044SWilliam.Kucharski@Sun.COM 
2085*8044SWilliam.Kucharski@Sun.COM 		e1000_config_collision_dist(hw);
2086*8044SWilliam.Kucharski@Sun.COM 
2087*8044SWilliam.Kucharski@Sun.COM 		/* Set up speed in the Device Control register depending on
2088*8044SWilliam.Kucharski@Sun.COM 		 * negotiated values.
2089*8044SWilliam.Kucharski@Sun.COM 		 */
2090*8044SWilliam.Kucharski@Sun.COM 		if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
2091*8044SWilliam.Kucharski@Sun.COM 		   IGP01E1000_PSSR_SPEED_1000MBPS)
2092*8044SWilliam.Kucharski@Sun.COM 			ctrl |= E1000_CTRL_SPD_1000;
2093*8044SWilliam.Kucharski@Sun.COM 		else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
2094*8044SWilliam.Kucharski@Sun.COM 			IGP01E1000_PSSR_SPEED_100MBPS)
2095*8044SWilliam.Kucharski@Sun.COM 			ctrl |= E1000_CTRL_SPD_100;
2096*8044SWilliam.Kucharski@Sun.COM 	} else {
2097*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
2098*8044SWilliam.Kucharski@Sun.COM 		                                 &phy_data)))
2099*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2100*8044SWilliam.Kucharski@Sun.COM 
2101*8044SWilliam.Kucharski@Sun.COM 		if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
2102*8044SWilliam.Kucharski@Sun.COM 		else ctrl &= ~E1000_CTRL_FD;
2103*8044SWilliam.Kucharski@Sun.COM 
2104*8044SWilliam.Kucharski@Sun.COM 		e1000_config_collision_dist(hw);
2105*8044SWilliam.Kucharski@Sun.COM 
2106*8044SWilliam.Kucharski@Sun.COM 		/* Set up speed in the Device Control register depending on
2107*8044SWilliam.Kucharski@Sun.COM 		 * negotiated values.
2108*8044SWilliam.Kucharski@Sun.COM 		 */
2109*8044SWilliam.Kucharski@Sun.COM 		if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
2110*8044SWilliam.Kucharski@Sun.COM 			ctrl |= E1000_CTRL_SPD_1000;
2111*8044SWilliam.Kucharski@Sun.COM 		else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
2112*8044SWilliam.Kucharski@Sun.COM 			ctrl |= E1000_CTRL_SPD_100;
2113*8044SWilliam.Kucharski@Sun.COM 	}
2114*8044SWilliam.Kucharski@Sun.COM 	/* Write the configured values back to the Device Control Reg. */
2115*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, ctrl);
2116*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2117*8044SWilliam.Kucharski@Sun.COM }
2118*8044SWilliam.Kucharski@Sun.COM 
2119*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2120*8044SWilliam.Kucharski@Sun.COM  * Forces the MAC's flow control settings.
2121*8044SWilliam.Kucharski@Sun.COM  *
2122*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
2123*8044SWilliam.Kucharski@Sun.COM  *
2124*8044SWilliam.Kucharski@Sun.COM  * Sets the TFCE and RFCE bits in the device control register to reflect
2125*8044SWilliam.Kucharski@Sun.COM  * the adapter settings. TFCE and RFCE need to be explicitly set by
2126*8044SWilliam.Kucharski@Sun.COM  * software when a Copper PHY is used because autonegotiation is managed
2127*8044SWilliam.Kucharski@Sun.COM  * by the PHY rather than the MAC. Software must also configure these
2128*8044SWilliam.Kucharski@Sun.COM  * bits when link is forced on a fiber connection.
2129*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
2130*8044SWilliam.Kucharski@Sun.COM static int
2131*8044SWilliam.Kucharski@Sun.COM e1000_force_mac_fc(struct e1000_hw *hw)
2132*8044SWilliam.Kucharski@Sun.COM {
2133*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
2134*8044SWilliam.Kucharski@Sun.COM 
2135*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_force_mac_fc");
2136*8044SWilliam.Kucharski@Sun.COM 
2137*8044SWilliam.Kucharski@Sun.COM 	/* Get the current configuration of the Device Control Register */
2138*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
2139*8044SWilliam.Kucharski@Sun.COM 
2140*8044SWilliam.Kucharski@Sun.COM 	/* Because we didn't get link via the internal auto-negotiation
2141*8044SWilliam.Kucharski@Sun.COM 	 * mechanism (we either forced link or we got link via PHY
2142*8044SWilliam.Kucharski@Sun.COM 	 * auto-neg), we have to manually enable/disable transmit an
2143*8044SWilliam.Kucharski@Sun.COM 	 * receive flow control.
2144*8044SWilliam.Kucharski@Sun.COM 	 *
2145*8044SWilliam.Kucharski@Sun.COM 	 * The "Case" statement below enables/disable flow control
2146*8044SWilliam.Kucharski@Sun.COM 	 * according to the "hw->fc" parameter.
2147*8044SWilliam.Kucharski@Sun.COM 	 *
2148*8044SWilliam.Kucharski@Sun.COM 	 * The possible values of the "fc" parameter are:
2149*8044SWilliam.Kucharski@Sun.COM 	 *      0:  Flow control is completely disabled
2150*8044SWilliam.Kucharski@Sun.COM 	 *      1:  Rx flow control is enabled (we can receive pause
2151*8044SWilliam.Kucharski@Sun.COM 	 *          frames but not send pause frames).
2152*8044SWilliam.Kucharski@Sun.COM 	 *      2:  Tx flow control is enabled (we can send pause frames
2153*8044SWilliam.Kucharski@Sun.COM 	 *          frames but we do not receive pause frames).
2154*8044SWilliam.Kucharski@Sun.COM 	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
2155*8044SWilliam.Kucharski@Sun.COM 	 *  other:  No other values should be possible at this point.
2156*8044SWilliam.Kucharski@Sun.COM 	 */
2157*8044SWilliam.Kucharski@Sun.COM 
2158*8044SWilliam.Kucharski@Sun.COM 	switch (hw->fc) {
2159*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_none:
2160*8044SWilliam.Kucharski@Sun.COM 		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
2161*8044SWilliam.Kucharski@Sun.COM 		break;
2162*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_rx_pause:
2163*8044SWilliam.Kucharski@Sun.COM 		ctrl &= (~E1000_CTRL_TFCE);
2164*8044SWilliam.Kucharski@Sun.COM 		ctrl |= E1000_CTRL_RFCE;
2165*8044SWilliam.Kucharski@Sun.COM 		break;
2166*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_tx_pause:
2167*8044SWilliam.Kucharski@Sun.COM 		ctrl &= (~E1000_CTRL_RFCE);
2168*8044SWilliam.Kucharski@Sun.COM 		ctrl |= E1000_CTRL_TFCE;
2169*8044SWilliam.Kucharski@Sun.COM 		break;
2170*8044SWilliam.Kucharski@Sun.COM 	case e1000_fc_full:
2171*8044SWilliam.Kucharski@Sun.COM 		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
2172*8044SWilliam.Kucharski@Sun.COM 		break;
2173*8044SWilliam.Kucharski@Sun.COM 	default:
2174*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("Flow control param set incorrectly\n");
2175*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_CONFIG;
2176*8044SWilliam.Kucharski@Sun.COM 	}
2177*8044SWilliam.Kucharski@Sun.COM 
2178*8044SWilliam.Kucharski@Sun.COM 	/* Disable TX Flow Control for 82542 (rev 2.0) */
2179*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type == e1000_82542_rev2_0)
2180*8044SWilliam.Kucharski@Sun.COM 		ctrl &= (~E1000_CTRL_TFCE);
2181*8044SWilliam.Kucharski@Sun.COM 
2182*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, ctrl);
2183*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2184*8044SWilliam.Kucharski@Sun.COM }
2185*8044SWilliam.Kucharski@Sun.COM 
2186*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2187*8044SWilliam.Kucharski@Sun.COM  * Configures flow control settings after link is established
2188*8044SWilliam.Kucharski@Sun.COM  *
2189*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
2190*8044SWilliam.Kucharski@Sun.COM  *
2191*8044SWilliam.Kucharski@Sun.COM  * Should be called immediately after a valid link has been established.
2192*8044SWilliam.Kucharski@Sun.COM  * Forces MAC flow control settings if link was forced. When in MII/GMII mode
2193*8044SWilliam.Kucharski@Sun.COM  * and autonegotiation is enabled, the MAC flow control settings will be set
2194*8044SWilliam.Kucharski@Sun.COM  * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
2195*8044SWilliam.Kucharski@Sun.COM  * and RFCE bits will be automaticaly set to the negotiated flow control mode.
2196*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
2197*8044SWilliam.Kucharski@Sun.COM static int
2198*8044SWilliam.Kucharski@Sun.COM e1000_config_fc_after_link_up(struct e1000_hw *hw)
2199*8044SWilliam.Kucharski@Sun.COM {
2200*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
2201*8044SWilliam.Kucharski@Sun.COM 	uint16_t mii_status_reg;
2202*8044SWilliam.Kucharski@Sun.COM 	uint16_t mii_nway_adv_reg;
2203*8044SWilliam.Kucharski@Sun.COM 	uint16_t mii_nway_lp_ability_reg;
2204*8044SWilliam.Kucharski@Sun.COM 	uint16_t speed;
2205*8044SWilliam.Kucharski@Sun.COM 	uint16_t duplex;
2206*8044SWilliam.Kucharski@Sun.COM 
2207*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_config_fc_after_link_up");
2208*8044SWilliam.Kucharski@Sun.COM 
2209*8044SWilliam.Kucharski@Sun.COM 	/* Check for the case where we have fiber media and auto-neg failed
2210*8044SWilliam.Kucharski@Sun.COM 	 * so we had to force link.  In this case, we need to force the
2211*8044SWilliam.Kucharski@Sun.COM 	 * configuration of the MAC to match the "fc" parameter.
2212*8044SWilliam.Kucharski@Sun.COM 	 */
2213*8044SWilliam.Kucharski@Sun.COM 	if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
2214*8044SWilliam.Kucharski@Sun.COM 	   ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed))) {
2215*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_force_mac_fc(hw))) {
2216*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error forcing flow control settings\n");
2217*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2218*8044SWilliam.Kucharski@Sun.COM 		}
2219*8044SWilliam.Kucharski@Sun.COM 	}
2220*8044SWilliam.Kucharski@Sun.COM 
2221*8044SWilliam.Kucharski@Sun.COM 	/* Check for the case where we have copper media and auto-neg is
2222*8044SWilliam.Kucharski@Sun.COM 	 * enabled.  In this case, we need to check and see if Auto-Neg
2223*8044SWilliam.Kucharski@Sun.COM 	 * has completed, and if so, how the PHY and link partner has
2224*8044SWilliam.Kucharski@Sun.COM 	 * flow control configured.
2225*8044SWilliam.Kucharski@Sun.COM 	 */
2226*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_copper) {
2227*8044SWilliam.Kucharski@Sun.COM 		/* Read the MII Status Register and check to see if AutoNeg
2228*8044SWilliam.Kucharski@Sun.COM 		 * has completed.  We read this twice because this reg has
2229*8044SWilliam.Kucharski@Sun.COM 		 * some "sticky" (latched) bits.
2230*8044SWilliam.Kucharski@Sun.COM 		 */
2231*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
2232*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2233*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
2234*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2235*8044SWilliam.Kucharski@Sun.COM 
2236*8044SWilliam.Kucharski@Sun.COM 		if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
2237*8044SWilliam.Kucharski@Sun.COM 			/* The AutoNeg process has completed, so we now need to
2238*8044SWilliam.Kucharski@Sun.COM 			 * read both the Auto Negotiation Advertisement Register
2239*8044SWilliam.Kucharski@Sun.COM 			 * (Address 4) and the Auto_Negotiation Base Page Ability
2240*8044SWilliam.Kucharski@Sun.COM 			 * Register (Address 5) to determine how flow control was
2241*8044SWilliam.Kucharski@Sun.COM 			 * negotiated.
2242*8044SWilliam.Kucharski@Sun.COM 			 */
2243*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
2244*8044SWilliam.Kucharski@Sun.COM 			                                 &mii_nway_adv_reg)))
2245*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
2246*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
2247*8044SWilliam.Kucharski@Sun.COM 			                                 &mii_nway_lp_ability_reg)))
2248*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
2249*8044SWilliam.Kucharski@Sun.COM 
2250*8044SWilliam.Kucharski@Sun.COM 			/* Two bits in the Auto Negotiation Advertisement Register
2251*8044SWilliam.Kucharski@Sun.COM 			 * (Address 4) and two bits in the Auto Negotiation Base
2252*8044SWilliam.Kucharski@Sun.COM 			 * Page Ability Register (Address 5) determine flow control
2253*8044SWilliam.Kucharski@Sun.COM 			 * for both the PHY and the link partner.  The following
2254*8044SWilliam.Kucharski@Sun.COM 			 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
2255*8044SWilliam.Kucharski@Sun.COM 			 * 1999, describes these PAUSE resolution bits and how flow
2256*8044SWilliam.Kucharski@Sun.COM 			 * control is determined based upon these settings.
2257*8044SWilliam.Kucharski@Sun.COM 			 * NOTE:  DC = Don't Care
2258*8044SWilliam.Kucharski@Sun.COM 			 *
2259*8044SWilliam.Kucharski@Sun.COM 			 *   LOCAL DEVICE  |   LINK PARTNER
2260*8044SWilliam.Kucharski@Sun.COM 			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
2261*8044SWilliam.Kucharski@Sun.COM 			 *-------|---------|-------|---------|--------------------
2262*8044SWilliam.Kucharski@Sun.COM 			 *   0   |    0    |  DC   |   DC    | e1000_fc_none
2263*8044SWilliam.Kucharski@Sun.COM 			 *   0   |    1    |   0   |   DC    | e1000_fc_none
2264*8044SWilliam.Kucharski@Sun.COM 			 *   0   |    1    |   1   |    0    | e1000_fc_none
2265*8044SWilliam.Kucharski@Sun.COM 			 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
2266*8044SWilliam.Kucharski@Sun.COM 			 *   1   |    0    |   0   |   DC    | e1000_fc_none
2267*8044SWilliam.Kucharski@Sun.COM 			 *   1   |   DC    |   1   |   DC    | e1000_fc_full
2268*8044SWilliam.Kucharski@Sun.COM 			 *   1   |    1    |   0   |    0    | e1000_fc_none
2269*8044SWilliam.Kucharski@Sun.COM 			 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
2270*8044SWilliam.Kucharski@Sun.COM 			 *
2271*8044SWilliam.Kucharski@Sun.COM 			 */
2272*8044SWilliam.Kucharski@Sun.COM 			/* Are both PAUSE bits set to 1?  If so, this implies
2273*8044SWilliam.Kucharski@Sun.COM 			 * Symmetric Flow Control is enabled at both ends.  The
2274*8044SWilliam.Kucharski@Sun.COM 			 * ASM_DIR bits are irrelevant per the spec.
2275*8044SWilliam.Kucharski@Sun.COM 			 *
2276*8044SWilliam.Kucharski@Sun.COM 			 * For Symmetric Flow Control:
2277*8044SWilliam.Kucharski@Sun.COM 			 *
2278*8044SWilliam.Kucharski@Sun.COM 			 *   LOCAL DEVICE  |   LINK PARTNER
2279*8044SWilliam.Kucharski@Sun.COM 			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2280*8044SWilliam.Kucharski@Sun.COM 			 *-------|---------|-------|---------|--------------------
2281*8044SWilliam.Kucharski@Sun.COM 			 *   1   |   DC    |   1   |   DC    | e1000_fc_full
2282*8044SWilliam.Kucharski@Sun.COM 			 *
2283*8044SWilliam.Kucharski@Sun.COM 			 */
2284*8044SWilliam.Kucharski@Sun.COM 			if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2285*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
2286*8044SWilliam.Kucharski@Sun.COM 				/* Now we need to check if the user selected RX ONLY
2287*8044SWilliam.Kucharski@Sun.COM 				 * of pause frames.  In this case, we had to advertise
2288*8044SWilliam.Kucharski@Sun.COM 				 * FULL flow control because we could not advertise RX
2289*8044SWilliam.Kucharski@Sun.COM 				 * ONLY. Hence, we must now check to see if we need to
2290*8044SWilliam.Kucharski@Sun.COM 				 * turn OFF  the TRANSMISSION of PAUSE frames.
2291*8044SWilliam.Kucharski@Sun.COM 				 */
2292*8044SWilliam.Kucharski@Sun.COM #if 0
2293*8044SWilliam.Kucharski@Sun.COM 				if(hw->original_fc == e1000_fc_full) {
2294*8044SWilliam.Kucharski@Sun.COM 					hw->fc = e1000_fc_full;
2295*8044SWilliam.Kucharski@Sun.COM #else
2296*8044SWilliam.Kucharski@Sun.COM 				if(hw->fc == e1000_fc_full) {
2297*8044SWilliam.Kucharski@Sun.COM #endif
2298*8044SWilliam.Kucharski@Sun.COM 					DEBUGOUT("Flow Control = FULL.\r\n");
2299*8044SWilliam.Kucharski@Sun.COM 				} else {
2300*8044SWilliam.Kucharski@Sun.COM 					hw->fc = e1000_fc_rx_pause;
2301*8044SWilliam.Kucharski@Sun.COM 					DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2302*8044SWilliam.Kucharski@Sun.COM 				}
2303*8044SWilliam.Kucharski@Sun.COM 			}
2304*8044SWilliam.Kucharski@Sun.COM 			/* For receiving PAUSE frames ONLY.
2305*8044SWilliam.Kucharski@Sun.COM 			 *
2306*8044SWilliam.Kucharski@Sun.COM 			 *   LOCAL DEVICE  |   LINK PARTNER
2307*8044SWilliam.Kucharski@Sun.COM 			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2308*8044SWilliam.Kucharski@Sun.COM 			 *-------|---------|-------|---------|--------------------
2309*8044SWilliam.Kucharski@Sun.COM 			 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
2310*8044SWilliam.Kucharski@Sun.COM 			 *
2311*8044SWilliam.Kucharski@Sun.COM 			 */
2312*8044SWilliam.Kucharski@Sun.COM 			else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2313*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
2314*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
2315*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
2316*8044SWilliam.Kucharski@Sun.COM 				hw->fc = e1000_fc_tx_pause;
2317*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
2318*8044SWilliam.Kucharski@Sun.COM 			}
2319*8044SWilliam.Kucharski@Sun.COM 			/* For transmitting PAUSE frames ONLY.
2320*8044SWilliam.Kucharski@Sun.COM 			 *
2321*8044SWilliam.Kucharski@Sun.COM 			 *   LOCAL DEVICE  |   LINK PARTNER
2322*8044SWilliam.Kucharski@Sun.COM 			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2323*8044SWilliam.Kucharski@Sun.COM 			 *-------|---------|-------|---------|--------------------
2324*8044SWilliam.Kucharski@Sun.COM 			 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
2325*8044SWilliam.Kucharski@Sun.COM 			 *
2326*8044SWilliam.Kucharski@Sun.COM 			 */
2327*8044SWilliam.Kucharski@Sun.COM 			else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2328*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
2329*8044SWilliam.Kucharski@Sun.COM 				!(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
2330*8044SWilliam.Kucharski@Sun.COM 				(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
2331*8044SWilliam.Kucharski@Sun.COM 				hw->fc = e1000_fc_rx_pause;
2332*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2333*8044SWilliam.Kucharski@Sun.COM 			}
2334*8044SWilliam.Kucharski@Sun.COM 			/* Per the IEEE spec, at this point flow control should be
2335*8044SWilliam.Kucharski@Sun.COM 			 * disabled.  However, we want to consider that we could
2336*8044SWilliam.Kucharski@Sun.COM 			 * be connected to a legacy switch that doesn't advertise
2337*8044SWilliam.Kucharski@Sun.COM 			 * desired flow control, but can be forced on the link
2338*8044SWilliam.Kucharski@Sun.COM 			 * partner.  So if we advertised no flow control, that is
2339*8044SWilliam.Kucharski@Sun.COM 			 * what we will resolve to.  If we advertised some kind of
2340*8044SWilliam.Kucharski@Sun.COM 			 * receive capability (Rx Pause Only or Full Flow Control)
2341*8044SWilliam.Kucharski@Sun.COM 			 * and the link partner advertised none, we will configure
2342*8044SWilliam.Kucharski@Sun.COM 			 * ourselves to enable Rx Flow Control only.  We can do
2343*8044SWilliam.Kucharski@Sun.COM 			 * this safely for two reasons:  If the link partner really
2344*8044SWilliam.Kucharski@Sun.COM 			 * didn't want flow control enabled, and we enable Rx, no
2345*8044SWilliam.Kucharski@Sun.COM 			 * harm done since we won't be receiving any PAUSE frames
2346*8044SWilliam.Kucharski@Sun.COM 			 * anyway.  If the intent on the link partner was to have
2347*8044SWilliam.Kucharski@Sun.COM 			 * flow control enabled, then by us enabling RX only, we
2348*8044SWilliam.Kucharski@Sun.COM 			 * can at least receive pause frames and process them.
2349*8044SWilliam.Kucharski@Sun.COM 			 * This is a good idea because in most cases, since we are
2350*8044SWilliam.Kucharski@Sun.COM 			 * predominantly a server NIC, more times than not we will
2351*8044SWilliam.Kucharski@Sun.COM 			 * be asked to delay transmission of packets than asking
2352*8044SWilliam.Kucharski@Sun.COM 			 * our link partner to pause transmission of frames.
2353*8044SWilliam.Kucharski@Sun.COM 			 */
2354*8044SWilliam.Kucharski@Sun.COM #if 0
2355*8044SWilliam.Kucharski@Sun.COM 			else if(hw->original_fc == e1000_fc_none ||
2356*8044SWilliam.Kucharski@Sun.COM 				hw->original_fc == e1000_fc_tx_pause) {
2357*8044SWilliam.Kucharski@Sun.COM #else
2358*8044SWilliam.Kucharski@Sun.COM 			else if(hw->fc == e1000_fc_none)
2359*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Flow Control = NONE.\r\n");
2360*8044SWilliam.Kucharski@Sun.COM 			else if(hw->fc == e1000_fc_tx_pause) {
2361*8044SWilliam.Kucharski@Sun.COM #endif
2362*8044SWilliam.Kucharski@Sun.COM 				hw->fc = e1000_fc_none;
2363*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Flow Control = NONE.\r\n");
2364*8044SWilliam.Kucharski@Sun.COM 			} else {
2365*8044SWilliam.Kucharski@Sun.COM 				hw->fc = e1000_fc_rx_pause;
2366*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2367*8044SWilliam.Kucharski@Sun.COM 			}
2368*8044SWilliam.Kucharski@Sun.COM 
2369*8044SWilliam.Kucharski@Sun.COM 			/* Now we need to do one last check...  If we auto-
2370*8044SWilliam.Kucharski@Sun.COM 			 * negotiated to HALF DUPLEX, flow control should not be
2371*8044SWilliam.Kucharski@Sun.COM 			 * enabled per IEEE 802.3 spec.
2372*8044SWilliam.Kucharski@Sun.COM 			 */
2373*8044SWilliam.Kucharski@Sun.COM 			e1000_get_speed_and_duplex(hw, &speed, &duplex);
2374*8044SWilliam.Kucharski@Sun.COM 
2375*8044SWilliam.Kucharski@Sun.COM 			if(duplex == HALF_DUPLEX)
2376*8044SWilliam.Kucharski@Sun.COM 				hw->fc = e1000_fc_none;
2377*8044SWilliam.Kucharski@Sun.COM 
2378*8044SWilliam.Kucharski@Sun.COM 			/* Now we call a subroutine to actually force the MAC
2379*8044SWilliam.Kucharski@Sun.COM 			 * controller to use the correct flow control settings.
2380*8044SWilliam.Kucharski@Sun.COM 			 */
2381*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_force_mac_fc(hw))) {
2382*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Error forcing flow control settings\n");
2383*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
2384*8044SWilliam.Kucharski@Sun.COM 			}
2385*8044SWilliam.Kucharski@Sun.COM 		} else {
2386*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
2387*8044SWilliam.Kucharski@Sun.COM 		}
2388*8044SWilliam.Kucharski@Sun.COM 	}
2389*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2390*8044SWilliam.Kucharski@Sun.COM }
2391*8044SWilliam.Kucharski@Sun.COM 
2392*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2393*8044SWilliam.Kucharski@Sun.COM  * Checks to see if the link status of the hardware has changed.
2394*8044SWilliam.Kucharski@Sun.COM  *
2395*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
2396*8044SWilliam.Kucharski@Sun.COM  *
2397*8044SWilliam.Kucharski@Sun.COM  * Called by any function that needs to check the link status of the adapter.
2398*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
2399*8044SWilliam.Kucharski@Sun.COM static int
2400*8044SWilliam.Kucharski@Sun.COM e1000_check_for_link(struct e1000_hw *hw)
2401*8044SWilliam.Kucharski@Sun.COM {
2402*8044SWilliam.Kucharski@Sun.COM 	uint32_t rxcw;
2403*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
2404*8044SWilliam.Kucharski@Sun.COM 	uint32_t status;
2405*8044SWilliam.Kucharski@Sun.COM 	uint32_t rctl;
2406*8044SWilliam.Kucharski@Sun.COM 	uint32_t signal = 0;
2407*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
2408*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_data;
2409*8044SWilliam.Kucharski@Sun.COM 	uint16_t lp_capability;
2410*8044SWilliam.Kucharski@Sun.COM 
2411*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_check_for_link");
2412*8044SWilliam.Kucharski@Sun.COM 
2413*8044SWilliam.Kucharski@Sun.COM 	/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
2414*8044SWilliam.Kucharski@Sun.COM 	 * set when the optics detect a signal. On older adapters, it will be
2415*8044SWilliam.Kucharski@Sun.COM 	 * cleared when there is a signal.  This applies to fiber media only.
2416*8044SWilliam.Kucharski@Sun.COM 	 */
2417*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_fiber)
2418*8044SWilliam.Kucharski@Sun.COM 		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
2419*8044SWilliam.Kucharski@Sun.COM 
2420*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
2421*8044SWilliam.Kucharski@Sun.COM 	status = E1000_READ_REG(hw, STATUS);
2422*8044SWilliam.Kucharski@Sun.COM 	rxcw = E1000_READ_REG(hw, RXCW);
2423*8044SWilliam.Kucharski@Sun.COM 
2424*8044SWilliam.Kucharski@Sun.COM 	/* If we have a copper PHY then we only want to go out to the PHY
2425*8044SWilliam.Kucharski@Sun.COM 	 * registers to see if Auto-Neg has completed and/or if our link
2426*8044SWilliam.Kucharski@Sun.COM 	 * status has changed.  The get_link_status flag will be set if we
2427*8044SWilliam.Kucharski@Sun.COM 	 * receive a Link Status Change interrupt or we have Rx Sequence
2428*8044SWilliam.Kucharski@Sun.COM 	 * Errors.
2429*8044SWilliam.Kucharski@Sun.COM 	 */
2430*8044SWilliam.Kucharski@Sun.COM #if 0
2431*8044SWilliam.Kucharski@Sun.COM 	if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
2432*8044SWilliam.Kucharski@Sun.COM #else
2433*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_copper) {
2434*8044SWilliam.Kucharski@Sun.COM #endif
2435*8044SWilliam.Kucharski@Sun.COM 		/* First we want to see if the MII Status Register reports
2436*8044SWilliam.Kucharski@Sun.COM 		 * link.  If so, then we want to get the current speed/duplex
2437*8044SWilliam.Kucharski@Sun.COM 		 * of the PHY.
2438*8044SWilliam.Kucharski@Sun.COM 		 * Read the register twice since the link bit is sticky.
2439*8044SWilliam.Kucharski@Sun.COM 		 */
2440*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2441*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2442*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2443*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2444*8044SWilliam.Kucharski@Sun.COM 
2445*8044SWilliam.Kucharski@Sun.COM 		if(phy_data & MII_SR_LINK_STATUS) {
2446*8044SWilliam.Kucharski@Sun.COM #if 0
2447*8044SWilliam.Kucharski@Sun.COM 			hw->get_link_status = FALSE;
2448*8044SWilliam.Kucharski@Sun.COM #endif
2449*8044SWilliam.Kucharski@Sun.COM 		} else {
2450*8044SWilliam.Kucharski@Sun.COM 			/* No link detected */
2451*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_NOLINK;
2452*8044SWilliam.Kucharski@Sun.COM 		}
2453*8044SWilliam.Kucharski@Sun.COM 
2454*8044SWilliam.Kucharski@Sun.COM 		/* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
2455*8044SWilliam.Kucharski@Sun.COM 		 * have Si on board that is 82544 or newer, Auto
2456*8044SWilliam.Kucharski@Sun.COM 		 * Speed Detection takes care of MAC speed/duplex
2457*8044SWilliam.Kucharski@Sun.COM 		 * configuration.  So we only need to configure Collision
2458*8044SWilliam.Kucharski@Sun.COM 		 * Distance in the MAC.  Otherwise, we need to force
2459*8044SWilliam.Kucharski@Sun.COM 		 * speed/duplex on the MAC to the current PHY speed/duplex
2460*8044SWilliam.Kucharski@Sun.COM 		 * settings.
2461*8044SWilliam.Kucharski@Sun.COM 		 */
2462*8044SWilliam.Kucharski@Sun.COM 		if(hw->mac_type >= e1000_82544)
2463*8044SWilliam.Kucharski@Sun.COM 			e1000_config_collision_dist(hw);
2464*8044SWilliam.Kucharski@Sun.COM 		else {
2465*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_config_mac_to_phy(hw))) {
2466*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("Error configuring MAC to PHY settings\n");
2467*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
2468*8044SWilliam.Kucharski@Sun.COM 			}
2469*8044SWilliam.Kucharski@Sun.COM 		}
2470*8044SWilliam.Kucharski@Sun.COM 
2471*8044SWilliam.Kucharski@Sun.COM 		/* Configure Flow Control now that Auto-Neg has completed. First, we
2472*8044SWilliam.Kucharski@Sun.COM 		 * need to restore the desired flow control settings because we may
2473*8044SWilliam.Kucharski@Sun.COM 		 * have had to re-autoneg with a different link partner.
2474*8044SWilliam.Kucharski@Sun.COM 		 */
2475*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_config_fc_after_link_up(hw))) {
2476*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error configuring flow control\n");
2477*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2478*8044SWilliam.Kucharski@Sun.COM 		}
2479*8044SWilliam.Kucharski@Sun.COM 
2480*8044SWilliam.Kucharski@Sun.COM 		/* At this point we know that we are on copper and we have
2481*8044SWilliam.Kucharski@Sun.COM 		 * auto-negotiated link.  These are conditions for checking the link
2482*8044SWilliam.Kucharski@Sun.COM 		 * parter capability register.  We use the link partner capability to
2483*8044SWilliam.Kucharski@Sun.COM 		 * determine if TBI Compatibility needs to be turned on or off.  If
2484*8044SWilliam.Kucharski@Sun.COM 		 * the link partner advertises any speed in addition to Gigabit, then
2485*8044SWilliam.Kucharski@Sun.COM 		 * we assume that they are GMII-based, and TBI compatibility is not
2486*8044SWilliam.Kucharski@Sun.COM 		 * needed. If no other speeds are advertised, we assume the link
2487*8044SWilliam.Kucharski@Sun.COM 		 * partner is TBI-based, and we turn on TBI Compatibility.
2488*8044SWilliam.Kucharski@Sun.COM 		 */
2489*8044SWilliam.Kucharski@Sun.COM 		if(hw->tbi_compatibility_en) {
2490*8044SWilliam.Kucharski@Sun.COM 			if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
2491*8044SWilliam.Kucharski@Sun.COM 			                                 &lp_capability)))
2492*8044SWilliam.Kucharski@Sun.COM 				return ret_val;
2493*8044SWilliam.Kucharski@Sun.COM 			if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
2494*8044SWilliam.Kucharski@Sun.COM                                 NWAY_LPAR_10T_FD_CAPS |
2495*8044SWilliam.Kucharski@Sun.COM                                 NWAY_LPAR_100TX_HD_CAPS |
2496*8044SWilliam.Kucharski@Sun.COM                                 NWAY_LPAR_100TX_FD_CAPS |
2497*8044SWilliam.Kucharski@Sun.COM                                 NWAY_LPAR_100T4_CAPS)) {
2498*8044SWilliam.Kucharski@Sun.COM 				/* If our link partner advertises anything in addition to
2499*8044SWilliam.Kucharski@Sun.COM 				 * gigabit, we do not need to enable TBI compatibility.
2500*8044SWilliam.Kucharski@Sun.COM 				 */
2501*8044SWilliam.Kucharski@Sun.COM 				if(hw->tbi_compatibility_on) {
2502*8044SWilliam.Kucharski@Sun.COM 					/* If we previously were in the mode, turn it off. */
2503*8044SWilliam.Kucharski@Sun.COM 					rctl = E1000_READ_REG(hw, RCTL);
2504*8044SWilliam.Kucharski@Sun.COM 					rctl &= ~E1000_RCTL_SBP;
2505*8044SWilliam.Kucharski@Sun.COM 					E1000_WRITE_REG(hw, RCTL, rctl);
2506*8044SWilliam.Kucharski@Sun.COM 					hw->tbi_compatibility_on = FALSE;
2507*8044SWilliam.Kucharski@Sun.COM 				}
2508*8044SWilliam.Kucharski@Sun.COM 			} else {
2509*8044SWilliam.Kucharski@Sun.COM 				/* If TBI compatibility is was previously off, turn it on. For
2510*8044SWilliam.Kucharski@Sun.COM 				 * compatibility with a TBI link partner, we will store bad
2511*8044SWilliam.Kucharski@Sun.COM 				 * packets. Some frames have an additional byte on the end and
2512*8044SWilliam.Kucharski@Sun.COM 				 * will look like CRC errors to to the hardware.
2513*8044SWilliam.Kucharski@Sun.COM 				 */
2514*8044SWilliam.Kucharski@Sun.COM 				if(!hw->tbi_compatibility_on) {
2515*8044SWilliam.Kucharski@Sun.COM 					hw->tbi_compatibility_on = TRUE;
2516*8044SWilliam.Kucharski@Sun.COM 					rctl = E1000_READ_REG(hw, RCTL);
2517*8044SWilliam.Kucharski@Sun.COM 					rctl |= E1000_RCTL_SBP;
2518*8044SWilliam.Kucharski@Sun.COM 					E1000_WRITE_REG(hw, RCTL, rctl);
2519*8044SWilliam.Kucharski@Sun.COM 				}
2520*8044SWilliam.Kucharski@Sun.COM 			}
2521*8044SWilliam.Kucharski@Sun.COM 		}
2522*8044SWilliam.Kucharski@Sun.COM 	}
2523*8044SWilliam.Kucharski@Sun.COM 	/* If we don't have link (auto-negotiation failed or link partner cannot
2524*8044SWilliam.Kucharski@Sun.COM 	 * auto-negotiate), the cable is plugged in (we have signal), and our
2525*8044SWilliam.Kucharski@Sun.COM 	 * link partner is not trying to auto-negotiate with us (we are receiving
2526*8044SWilliam.Kucharski@Sun.COM 	 * idles or data), we need to force link up. We also need to give
2527*8044SWilliam.Kucharski@Sun.COM 	 * auto-negotiation time to complete, in case the cable was just plugged
2528*8044SWilliam.Kucharski@Sun.COM 	 * in. The autoneg_failed flag does this.
2529*8044SWilliam.Kucharski@Sun.COM 	 */
2530*8044SWilliam.Kucharski@Sun.COM 	else if((((hw->media_type == e1000_media_type_fiber) &&
2531*8044SWilliam.Kucharski@Sun.COM 	        ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
2532*8044SWilliam.Kucharski@Sun.COM 	        (hw->media_type == e1000_media_type_internal_serdes)) &&
2533*8044SWilliam.Kucharski@Sun.COM 		(!(status & E1000_STATUS_LU)) &&
2534*8044SWilliam.Kucharski@Sun.COM 		(!(rxcw & E1000_RXCW_C))) {
2535*8044SWilliam.Kucharski@Sun.COM 		if(hw->autoneg_failed == 0) {
2536*8044SWilliam.Kucharski@Sun.COM 			hw->autoneg_failed = 1;
2537*8044SWilliam.Kucharski@Sun.COM 			return 0;
2538*8044SWilliam.Kucharski@Sun.COM 		}
2539*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
2540*8044SWilliam.Kucharski@Sun.COM 
2541*8044SWilliam.Kucharski@Sun.COM 		/* Disable auto-negotiation in the TXCW register */
2542*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
2543*8044SWilliam.Kucharski@Sun.COM 
2544*8044SWilliam.Kucharski@Sun.COM 		/* Force link-up and also force full-duplex. */
2545*8044SWilliam.Kucharski@Sun.COM 		ctrl = E1000_READ_REG(hw, CTRL);
2546*8044SWilliam.Kucharski@Sun.COM 		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
2547*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl);
2548*8044SWilliam.Kucharski@Sun.COM 
2549*8044SWilliam.Kucharski@Sun.COM 		/* Configure Flow Control after forcing link up. */
2550*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_config_fc_after_link_up(hw))) {
2551*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Error configuring flow control\n");
2552*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2553*8044SWilliam.Kucharski@Sun.COM 		}
2554*8044SWilliam.Kucharski@Sun.COM 	}
2555*8044SWilliam.Kucharski@Sun.COM 	/* If we are forcing link and we are receiving /C/ ordered sets, re-enable
2556*8044SWilliam.Kucharski@Sun.COM 	 * auto-negotiation in the TXCW register and disable forced link in the
2557*8044SWilliam.Kucharski@Sun.COM 	 * Device Control register in an attempt to auto-negotiate with our link
2558*8044SWilliam.Kucharski@Sun.COM 	 * partner.
2559*8044SWilliam.Kucharski@Sun.COM 	 */
2560*8044SWilliam.Kucharski@Sun.COM 	else if(((hw->media_type == e1000_media_type_fiber)  ||
2561*8044SWilliam.Kucharski@Sun.COM 	         (hw->media_type == e1000_media_type_internal_serdes)) &&
2562*8044SWilliam.Kucharski@Sun.COM 		(ctrl & E1000_CTRL_SLU) &&
2563*8044SWilliam.Kucharski@Sun.COM 		(rxcw & E1000_RXCW_C)) {
2564*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
2565*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, TXCW, hw->txcw);
2566*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
2567*8044SWilliam.Kucharski@Sun.COM 	}
2568*8044SWilliam.Kucharski@Sun.COM #if 0
2569*8044SWilliam.Kucharski@Sun.COM 	/* If we force link for non-auto-negotiation switch, check link status
2570*8044SWilliam.Kucharski@Sun.COM 	 * based on MAC synchronization for internal serdes media type.
2571*8044SWilliam.Kucharski@Sun.COM 	 */
2572*8044SWilliam.Kucharski@Sun.COM 	else if((hw->media_type == e1000_media_type_internal_serdes) &&
2573*8044SWilliam.Kucharski@Sun.COM 			!(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
2574*8044SWilliam.Kucharski@Sun.COM 		/* SYNCH bit and IV bit are sticky. */
2575*8044SWilliam.Kucharski@Sun.COM 		udelay(10);
2576*8044SWilliam.Kucharski@Sun.COM 		if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
2577*8044SWilliam.Kucharski@Sun.COM 			if(!(rxcw & E1000_RXCW_IV)) {
2578*8044SWilliam.Kucharski@Sun.COM 				hw->serdes_link_down = FALSE;
2579*8044SWilliam.Kucharski@Sun.COM 				DEBUGOUT("SERDES: Link is up.\n");
2580*8044SWilliam.Kucharski@Sun.COM 			}
2581*8044SWilliam.Kucharski@Sun.COM 		} else {
2582*8044SWilliam.Kucharski@Sun.COM 			hw->serdes_link_down = TRUE;
2583*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("SERDES: Link is down.\n");
2584*8044SWilliam.Kucharski@Sun.COM 		}
2585*8044SWilliam.Kucharski@Sun.COM 	}
2586*8044SWilliam.Kucharski@Sun.COM #endif
2587*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2588*8044SWilliam.Kucharski@Sun.COM }
2589*8044SWilliam.Kucharski@Sun.COM 
2590*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2591*8044SWilliam.Kucharski@Sun.COM  * Detects the current speed and duplex settings of the hardware.
2592*8044SWilliam.Kucharski@Sun.COM  *
2593*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
2594*8044SWilliam.Kucharski@Sun.COM  * speed - Speed of the connection
2595*8044SWilliam.Kucharski@Sun.COM  * duplex - Duplex setting of the connection
2596*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
2597*8044SWilliam.Kucharski@Sun.COM static void
2598*8044SWilliam.Kucharski@Sun.COM e1000_get_speed_and_duplex(struct e1000_hw *hw,
2599*8044SWilliam.Kucharski@Sun.COM                            uint16_t *speed,
2600*8044SWilliam.Kucharski@Sun.COM                            uint16_t *duplex)
2601*8044SWilliam.Kucharski@Sun.COM {
2602*8044SWilliam.Kucharski@Sun.COM 	uint32_t status;
2603*8044SWilliam.Kucharski@Sun.COM 
2604*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_get_speed_and_duplex");
2605*8044SWilliam.Kucharski@Sun.COM 
2606*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type >= e1000_82543) {
2607*8044SWilliam.Kucharski@Sun.COM 		status = E1000_READ_REG(hw, STATUS);
2608*8044SWilliam.Kucharski@Sun.COM 		if(status & E1000_STATUS_SPEED_1000) {
2609*8044SWilliam.Kucharski@Sun.COM 			*speed = SPEED_1000;
2610*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("1000 Mbs, ");
2611*8044SWilliam.Kucharski@Sun.COM 		} else if(status & E1000_STATUS_SPEED_100) {
2612*8044SWilliam.Kucharski@Sun.COM 			*speed = SPEED_100;
2613*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("100 Mbs, ");
2614*8044SWilliam.Kucharski@Sun.COM 		} else {
2615*8044SWilliam.Kucharski@Sun.COM 			*speed = SPEED_10;
2616*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("10 Mbs, ");
2617*8044SWilliam.Kucharski@Sun.COM 		}
2618*8044SWilliam.Kucharski@Sun.COM 
2619*8044SWilliam.Kucharski@Sun.COM 		if(status & E1000_STATUS_FD) {
2620*8044SWilliam.Kucharski@Sun.COM 			*duplex = FULL_DUPLEX;
2621*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Full Duplex\r\n");
2622*8044SWilliam.Kucharski@Sun.COM 		} else {
2623*8044SWilliam.Kucharski@Sun.COM 			*duplex = HALF_DUPLEX;
2624*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT(" Half Duplex\r\n");
2625*8044SWilliam.Kucharski@Sun.COM 		}
2626*8044SWilliam.Kucharski@Sun.COM 	} else {
2627*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT("1000 Mbs, Full Duplex\r\n");
2628*8044SWilliam.Kucharski@Sun.COM 		*speed = SPEED_1000;
2629*8044SWilliam.Kucharski@Sun.COM 		*duplex = FULL_DUPLEX;
2630*8044SWilliam.Kucharski@Sun.COM 	}
2631*8044SWilliam.Kucharski@Sun.COM }
2632*8044SWilliam.Kucharski@Sun.COM 
2633*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2634*8044SWilliam.Kucharski@Sun.COM * Blocks until autoneg completes or times out (~4.5 seconds)
2635*8044SWilliam.Kucharski@Sun.COM *
2636*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2637*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2638*8044SWilliam.Kucharski@Sun.COM static int
2639*8044SWilliam.Kucharski@Sun.COM e1000_wait_autoneg(struct e1000_hw *hw)
2640*8044SWilliam.Kucharski@Sun.COM {
2641*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
2642*8044SWilliam.Kucharski@Sun.COM 	uint16_t i;
2643*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_data;
2644*8044SWilliam.Kucharski@Sun.COM 
2645*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_wait_autoneg");
2646*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Waiting for Auto-Neg to complete.\n");
2647*8044SWilliam.Kucharski@Sun.COM 
2648*8044SWilliam.Kucharski@Sun.COM 	/* We will wait for autoneg to complete or 4.5 seconds to expire. */
2649*8044SWilliam.Kucharski@Sun.COM 	for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
2650*8044SWilliam.Kucharski@Sun.COM 		/* Read the MII Status Register and wait for Auto-Neg
2651*8044SWilliam.Kucharski@Sun.COM 		 * Complete bit to be set.
2652*8044SWilliam.Kucharski@Sun.COM 		 */
2653*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2654*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2655*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2656*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2657*8044SWilliam.Kucharski@Sun.COM 		if(phy_data & MII_SR_AUTONEG_COMPLETE) {
2658*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("Auto-Neg complete.\n");
2659*8044SWilliam.Kucharski@Sun.COM 			return E1000_SUCCESS;
2660*8044SWilliam.Kucharski@Sun.COM 		}
2661*8044SWilliam.Kucharski@Sun.COM 		mdelay(100);
2662*8044SWilliam.Kucharski@Sun.COM 	}
2663*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Auto-Neg timedout.\n");
2664*8044SWilliam.Kucharski@Sun.COM 	return -E1000_ERR_TIMEOUT;
2665*8044SWilliam.Kucharski@Sun.COM }
2666*8044SWilliam.Kucharski@Sun.COM 
2667*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2668*8044SWilliam.Kucharski@Sun.COM * Raises the Management Data Clock
2669*8044SWilliam.Kucharski@Sun.COM *
2670*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2671*8044SWilliam.Kucharski@Sun.COM * ctrl - Device control register's current value
2672*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2673*8044SWilliam.Kucharski@Sun.COM static void
2674*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(struct e1000_hw *hw,
2675*8044SWilliam.Kucharski@Sun.COM                     uint32_t *ctrl)
2676*8044SWilliam.Kucharski@Sun.COM {
2677*8044SWilliam.Kucharski@Sun.COM 	/* Raise the clock input to the Management Data Clock (by setting the MDC
2678*8044SWilliam.Kucharski@Sun.COM 	 * bit), and then delay 10 microseconds.
2679*8044SWilliam.Kucharski@Sun.COM 	 */
2680*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
2681*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
2682*8044SWilliam.Kucharski@Sun.COM 	udelay(10);
2683*8044SWilliam.Kucharski@Sun.COM }
2684*8044SWilliam.Kucharski@Sun.COM 
2685*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2686*8044SWilliam.Kucharski@Sun.COM * Lowers the Management Data Clock
2687*8044SWilliam.Kucharski@Sun.COM *
2688*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2689*8044SWilliam.Kucharski@Sun.COM * ctrl - Device control register's current value
2690*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2691*8044SWilliam.Kucharski@Sun.COM static void
2692*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(struct e1000_hw *hw,
2693*8044SWilliam.Kucharski@Sun.COM                     uint32_t *ctrl)
2694*8044SWilliam.Kucharski@Sun.COM {
2695*8044SWilliam.Kucharski@Sun.COM 	/* Lower the clock input to the Management Data Clock (by clearing the MDC
2696*8044SWilliam.Kucharski@Sun.COM 	 * bit), and then delay 10 microseconds.
2697*8044SWilliam.Kucharski@Sun.COM 	 */
2698*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
2699*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
2700*8044SWilliam.Kucharski@Sun.COM 	udelay(10);
2701*8044SWilliam.Kucharski@Sun.COM }
2702*8044SWilliam.Kucharski@Sun.COM 
2703*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2704*8044SWilliam.Kucharski@Sun.COM * Shifts data bits out to the PHY
2705*8044SWilliam.Kucharski@Sun.COM *
2706*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2707*8044SWilliam.Kucharski@Sun.COM * data - Data to send out to the PHY
2708*8044SWilliam.Kucharski@Sun.COM * count - Number of bits to shift out
2709*8044SWilliam.Kucharski@Sun.COM *
2710*8044SWilliam.Kucharski@Sun.COM * Bits are shifted out in MSB to LSB order.
2711*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2712*8044SWilliam.Kucharski@Sun.COM static void
2713*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(struct e1000_hw *hw,
2714*8044SWilliam.Kucharski@Sun.COM                          uint32_t data,
2715*8044SWilliam.Kucharski@Sun.COM                          uint16_t count)
2716*8044SWilliam.Kucharski@Sun.COM {
2717*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
2718*8044SWilliam.Kucharski@Sun.COM 	uint32_t mask;
2719*8044SWilliam.Kucharski@Sun.COM 
2720*8044SWilliam.Kucharski@Sun.COM 	/* We need to shift "count" number of bits out to the PHY. So, the value
2721*8044SWilliam.Kucharski@Sun.COM 	 * in the "data" parameter will be shifted out to the PHY one bit at a
2722*8044SWilliam.Kucharski@Sun.COM 	 * time. In order to do this, "data" must be broken down into bits.
2723*8044SWilliam.Kucharski@Sun.COM 	 */
2724*8044SWilliam.Kucharski@Sun.COM 	mask = 0x01;
2725*8044SWilliam.Kucharski@Sun.COM 	mask <<= (count - 1);
2726*8044SWilliam.Kucharski@Sun.COM 
2727*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
2728*8044SWilliam.Kucharski@Sun.COM 
2729*8044SWilliam.Kucharski@Sun.COM 	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
2730*8044SWilliam.Kucharski@Sun.COM 	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
2731*8044SWilliam.Kucharski@Sun.COM 
2732*8044SWilliam.Kucharski@Sun.COM 	while(mask) {
2733*8044SWilliam.Kucharski@Sun.COM 		/* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
2734*8044SWilliam.Kucharski@Sun.COM 		 * then raising and lowering the Management Data Clock. A "0" is
2735*8044SWilliam.Kucharski@Sun.COM 		 * shifted out to the PHY by setting the MDIO bit to "0" and then
2736*8044SWilliam.Kucharski@Sun.COM 		 * raising and lowering the clock.
2737*8044SWilliam.Kucharski@Sun.COM 		 */
2738*8044SWilliam.Kucharski@Sun.COM 		if(data & mask) ctrl |= E1000_CTRL_MDIO;
2739*8044SWilliam.Kucharski@Sun.COM 		else ctrl &= ~E1000_CTRL_MDIO;
2740*8044SWilliam.Kucharski@Sun.COM 
2741*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl);
2742*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
2743*8044SWilliam.Kucharski@Sun.COM 
2744*8044SWilliam.Kucharski@Sun.COM 		udelay(10);
2745*8044SWilliam.Kucharski@Sun.COM 
2746*8044SWilliam.Kucharski@Sun.COM 		e1000_raise_mdi_clk(hw, &ctrl);
2747*8044SWilliam.Kucharski@Sun.COM 		e1000_lower_mdi_clk(hw, &ctrl);
2748*8044SWilliam.Kucharski@Sun.COM 
2749*8044SWilliam.Kucharski@Sun.COM 		mask = mask >> 1;
2750*8044SWilliam.Kucharski@Sun.COM 	}
2751*8044SWilliam.Kucharski@Sun.COM }
2752*8044SWilliam.Kucharski@Sun.COM 
2753*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2754*8044SWilliam.Kucharski@Sun.COM * Shifts data bits in from the PHY
2755*8044SWilliam.Kucharski@Sun.COM *
2756*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2757*8044SWilliam.Kucharski@Sun.COM *
2758*8044SWilliam.Kucharski@Sun.COM * Bits are shifted in in MSB to LSB order.
2759*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2760*8044SWilliam.Kucharski@Sun.COM static uint16_t
2761*8044SWilliam.Kucharski@Sun.COM e1000_shift_in_mdi_bits(struct e1000_hw *hw)
2762*8044SWilliam.Kucharski@Sun.COM {
2763*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl;
2764*8044SWilliam.Kucharski@Sun.COM 	uint16_t data = 0;
2765*8044SWilliam.Kucharski@Sun.COM 	uint8_t i;
2766*8044SWilliam.Kucharski@Sun.COM 
2767*8044SWilliam.Kucharski@Sun.COM 	/* In order to read a register from the PHY, we need to shift in a total
2768*8044SWilliam.Kucharski@Sun.COM 	 * of 18 bits from the PHY. The first two bit (turnaround) times are used
2769*8044SWilliam.Kucharski@Sun.COM 	 * to avoid contention on the MDIO pin when a read operation is performed.
2770*8044SWilliam.Kucharski@Sun.COM 	 * These two bits are ignored by us and thrown away. Bits are "shifted in"
2771*8044SWilliam.Kucharski@Sun.COM 	 * by raising the input to the Management Data Clock (setting the MDC bit),
2772*8044SWilliam.Kucharski@Sun.COM 	 * and then reading the value of the MDIO bit.
2773*8044SWilliam.Kucharski@Sun.COM 	 */
2774*8044SWilliam.Kucharski@Sun.COM 	ctrl = E1000_READ_REG(hw, CTRL);
2775*8044SWilliam.Kucharski@Sun.COM 
2776*8044SWilliam.Kucharski@Sun.COM 	/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
2777*8044SWilliam.Kucharski@Sun.COM 	ctrl &= ~E1000_CTRL_MDIO_DIR;
2778*8044SWilliam.Kucharski@Sun.COM 	ctrl &= ~E1000_CTRL_MDIO;
2779*8044SWilliam.Kucharski@Sun.COM 
2780*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, CTRL, ctrl);
2781*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_FLUSH(hw);
2782*8044SWilliam.Kucharski@Sun.COM 
2783*8044SWilliam.Kucharski@Sun.COM 	/* Raise and Lower the clock before reading in the data. This accounts for
2784*8044SWilliam.Kucharski@Sun.COM 	 * the turnaround bits. The first clock occurred when we clocked out the
2785*8044SWilliam.Kucharski@Sun.COM 	 * last bit of the Register Address.
2786*8044SWilliam.Kucharski@Sun.COM 	 */
2787*8044SWilliam.Kucharski@Sun.COM 	e1000_raise_mdi_clk(hw, &ctrl);
2788*8044SWilliam.Kucharski@Sun.COM 	e1000_lower_mdi_clk(hw, &ctrl);
2789*8044SWilliam.Kucharski@Sun.COM 
2790*8044SWilliam.Kucharski@Sun.COM 	for(data = 0, i = 0; i < 16; i++) {
2791*8044SWilliam.Kucharski@Sun.COM 		data = data << 1;
2792*8044SWilliam.Kucharski@Sun.COM 		e1000_raise_mdi_clk(hw, &ctrl);
2793*8044SWilliam.Kucharski@Sun.COM 		ctrl = E1000_READ_REG(hw, CTRL);
2794*8044SWilliam.Kucharski@Sun.COM 		/* Check to see if we shifted in a "1". */
2795*8044SWilliam.Kucharski@Sun.COM 		if(ctrl & E1000_CTRL_MDIO) data |= 1;
2796*8044SWilliam.Kucharski@Sun.COM 		e1000_lower_mdi_clk(hw, &ctrl);
2797*8044SWilliam.Kucharski@Sun.COM 	}
2798*8044SWilliam.Kucharski@Sun.COM 
2799*8044SWilliam.Kucharski@Sun.COM 	e1000_raise_mdi_clk(hw, &ctrl);
2800*8044SWilliam.Kucharski@Sun.COM 	e1000_lower_mdi_clk(hw, &ctrl);
2801*8044SWilliam.Kucharski@Sun.COM 
2802*8044SWilliam.Kucharski@Sun.COM 	return data;
2803*8044SWilliam.Kucharski@Sun.COM }
2804*8044SWilliam.Kucharski@Sun.COM 
2805*8044SWilliam.Kucharski@Sun.COM /*****************************************************************************
2806*8044SWilliam.Kucharski@Sun.COM * Reads the value from a PHY register, if the value is on a specific non zero
2807*8044SWilliam.Kucharski@Sun.COM * page, sets the page first.
2808*8044SWilliam.Kucharski@Sun.COM *
2809*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2810*8044SWilliam.Kucharski@Sun.COM * reg_addr - address of the PHY register to read
2811*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2812*8044SWilliam.Kucharski@Sun.COM static int
2813*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg(struct e1000_hw *hw,
2814*8044SWilliam.Kucharski@Sun.COM                    uint32_t reg_addr,
2815*8044SWilliam.Kucharski@Sun.COM                    uint16_t *phy_data)
2816*8044SWilliam.Kucharski@Sun.COM {
2817*8044SWilliam.Kucharski@Sun.COM 	uint32_t ret_val;
2818*8044SWilliam.Kucharski@Sun.COM 
2819*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_read_phy_reg");
2820*8044SWilliam.Kucharski@Sun.COM 
2821*8044SWilliam.Kucharski@Sun.COM 	if(hw->phy_type == e1000_phy_igp &&
2822*8044SWilliam.Kucharski@Sun.COM 	   (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
2823*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
2824*8044SWilliam.Kucharski@Sun.COM 		                                     (uint16_t)reg_addr)))
2825*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2826*8044SWilliam.Kucharski@Sun.COM 	}
2827*8044SWilliam.Kucharski@Sun.COM 
2828*8044SWilliam.Kucharski@Sun.COM 	ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
2829*8044SWilliam.Kucharski@Sun.COM 	                                phy_data);
2830*8044SWilliam.Kucharski@Sun.COM 
2831*8044SWilliam.Kucharski@Sun.COM 	return ret_val;
2832*8044SWilliam.Kucharski@Sun.COM }
2833*8044SWilliam.Kucharski@Sun.COM 
2834*8044SWilliam.Kucharski@Sun.COM static int
2835*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg_ex(struct e1000_hw *hw,
2836*8044SWilliam.Kucharski@Sun.COM                       uint32_t reg_addr,
2837*8044SWilliam.Kucharski@Sun.COM                       uint16_t *phy_data)
2838*8044SWilliam.Kucharski@Sun.COM {
2839*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
2840*8044SWilliam.Kucharski@Sun.COM 	uint32_t mdic = 0;
2841*8044SWilliam.Kucharski@Sun.COM 	const uint32_t phy_addr = 1;
2842*8044SWilliam.Kucharski@Sun.COM 
2843*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_read_phy_reg_ex");
2844*8044SWilliam.Kucharski@Sun.COM 
2845*8044SWilliam.Kucharski@Sun.COM 	if(reg_addr > MAX_PHY_REG_ADDRESS) {
2846*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
2847*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_PARAM;
2848*8044SWilliam.Kucharski@Sun.COM 	}
2849*8044SWilliam.Kucharski@Sun.COM 
2850*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82543) {
2851*8044SWilliam.Kucharski@Sun.COM 		/* Set up Op-code, Phy Address, and register address in the MDI
2852*8044SWilliam.Kucharski@Sun.COM 		 * Control register.  The MAC will take care of interfacing with the
2853*8044SWilliam.Kucharski@Sun.COM 		 * PHY to retrieve the desired data.
2854*8044SWilliam.Kucharski@Sun.COM 		 */
2855*8044SWilliam.Kucharski@Sun.COM 		mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
2856*8044SWilliam.Kucharski@Sun.COM 			(phy_addr << E1000_MDIC_PHY_SHIFT) |
2857*8044SWilliam.Kucharski@Sun.COM 			(E1000_MDIC_OP_READ));
2858*8044SWilliam.Kucharski@Sun.COM 
2859*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, MDIC, mdic);
2860*8044SWilliam.Kucharski@Sun.COM 
2861*8044SWilliam.Kucharski@Sun.COM 		/* Poll the ready bit to see if the MDI read completed */
2862*8044SWilliam.Kucharski@Sun.COM 		for(i = 0; i < 64; i++) {
2863*8044SWilliam.Kucharski@Sun.COM 			udelay(50);
2864*8044SWilliam.Kucharski@Sun.COM 			mdic = E1000_READ_REG(hw, MDIC);
2865*8044SWilliam.Kucharski@Sun.COM 			if(mdic & E1000_MDIC_READY) break;
2866*8044SWilliam.Kucharski@Sun.COM 		}
2867*8044SWilliam.Kucharski@Sun.COM 		if(!(mdic & E1000_MDIC_READY)) {
2868*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("MDI Read did not complete\n");
2869*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_PHY;
2870*8044SWilliam.Kucharski@Sun.COM 		}
2871*8044SWilliam.Kucharski@Sun.COM 		if(mdic & E1000_MDIC_ERROR) {
2872*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("MDI Error\n");
2873*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_PHY;
2874*8044SWilliam.Kucharski@Sun.COM 		}
2875*8044SWilliam.Kucharski@Sun.COM 		*phy_data = (uint16_t) mdic;
2876*8044SWilliam.Kucharski@Sun.COM 	} else {
2877*8044SWilliam.Kucharski@Sun.COM 		/* We must first send a preamble through the MDIO pin to signal the
2878*8044SWilliam.Kucharski@Sun.COM 		 * beginning of an MII instruction.  This is done by sending 32
2879*8044SWilliam.Kucharski@Sun.COM 		 * consecutive "1" bits.
2880*8044SWilliam.Kucharski@Sun.COM 		 */
2881*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
2882*8044SWilliam.Kucharski@Sun.COM 
2883*8044SWilliam.Kucharski@Sun.COM 		/* Now combine the next few fields that are required for a read
2884*8044SWilliam.Kucharski@Sun.COM 		 * operation.  We use this method instead of calling the
2885*8044SWilliam.Kucharski@Sun.COM 		 * e1000_shift_out_mdi_bits routine five different times. The format of
2886*8044SWilliam.Kucharski@Sun.COM 		 * a MII read instruction consists of a shift out of 14 bits and is
2887*8044SWilliam.Kucharski@Sun.COM 		 * defined as follows:
2888*8044SWilliam.Kucharski@Sun.COM 		 *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
2889*8044SWilliam.Kucharski@Sun.COM 		 * followed by a shift in of 18 bits.  This first two bits shifted in
2890*8044SWilliam.Kucharski@Sun.COM 		 * are TurnAround bits used to avoid contention on the MDIO pin when a
2891*8044SWilliam.Kucharski@Sun.COM 		 * READ operation is performed.  These two bits are thrown away
2892*8044SWilliam.Kucharski@Sun.COM 		 * followed by a shift in of 16 bits which contains the desired data.
2893*8044SWilliam.Kucharski@Sun.COM 		 */
2894*8044SWilliam.Kucharski@Sun.COM 		mdic = ((reg_addr) | (phy_addr << 5) |
2895*8044SWilliam.Kucharski@Sun.COM 			(PHY_OP_READ << 10) | (PHY_SOF << 12));
2896*8044SWilliam.Kucharski@Sun.COM 
2897*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_mdi_bits(hw, mdic, 14);
2898*8044SWilliam.Kucharski@Sun.COM 
2899*8044SWilliam.Kucharski@Sun.COM 		/* Now that we've shifted out the read command to the MII, we need to
2900*8044SWilliam.Kucharski@Sun.COM 		 * "shift in" the 16-bit value (18 total bits) of the requested PHY
2901*8044SWilliam.Kucharski@Sun.COM 		 * register address.
2902*8044SWilliam.Kucharski@Sun.COM 		 */
2903*8044SWilliam.Kucharski@Sun.COM 		*phy_data = e1000_shift_in_mdi_bits(hw);
2904*8044SWilliam.Kucharski@Sun.COM 	}
2905*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2906*8044SWilliam.Kucharski@Sun.COM }
2907*8044SWilliam.Kucharski@Sun.COM 
2908*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2909*8044SWilliam.Kucharski@Sun.COM * Writes a value to a PHY register
2910*8044SWilliam.Kucharski@Sun.COM *
2911*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2912*8044SWilliam.Kucharski@Sun.COM * reg_addr - address of the PHY register to write
2913*8044SWilliam.Kucharski@Sun.COM * data - data to write to the PHY
2914*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2915*8044SWilliam.Kucharski@Sun.COM static int
2916*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(struct e1000_hw *hw,
2917*8044SWilliam.Kucharski@Sun.COM                     uint32_t reg_addr,
2918*8044SWilliam.Kucharski@Sun.COM                     uint16_t phy_data)
2919*8044SWilliam.Kucharski@Sun.COM {
2920*8044SWilliam.Kucharski@Sun.COM 	uint32_t ret_val;
2921*8044SWilliam.Kucharski@Sun.COM 
2922*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_write_phy_reg");
2923*8044SWilliam.Kucharski@Sun.COM 
2924*8044SWilliam.Kucharski@Sun.COM 	if(hw->phy_type == e1000_phy_igp &&
2925*8044SWilliam.Kucharski@Sun.COM 	   (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
2926*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
2927*8044SWilliam.Kucharski@Sun.COM 		                                     (uint16_t)reg_addr)))
2928*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
2929*8044SWilliam.Kucharski@Sun.COM 	}
2930*8044SWilliam.Kucharski@Sun.COM 
2931*8044SWilliam.Kucharski@Sun.COM 	ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
2932*8044SWilliam.Kucharski@Sun.COM 	                                 phy_data);
2933*8044SWilliam.Kucharski@Sun.COM 
2934*8044SWilliam.Kucharski@Sun.COM 	return ret_val;
2935*8044SWilliam.Kucharski@Sun.COM }
2936*8044SWilliam.Kucharski@Sun.COM 
2937*8044SWilliam.Kucharski@Sun.COM static int
2938*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg_ex(struct e1000_hw *hw,
2939*8044SWilliam.Kucharski@Sun.COM                        uint32_t reg_addr,
2940*8044SWilliam.Kucharski@Sun.COM                        uint16_t phy_data)
2941*8044SWilliam.Kucharski@Sun.COM {
2942*8044SWilliam.Kucharski@Sun.COM 	uint32_t i;
2943*8044SWilliam.Kucharski@Sun.COM 	uint32_t mdic = 0;
2944*8044SWilliam.Kucharski@Sun.COM 	const uint32_t phy_addr = 1;
2945*8044SWilliam.Kucharski@Sun.COM 
2946*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_write_phy_reg_ex");
2947*8044SWilliam.Kucharski@Sun.COM 
2948*8044SWilliam.Kucharski@Sun.COM 	if(reg_addr > MAX_PHY_REG_ADDRESS) {
2949*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
2950*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_PARAM;
2951*8044SWilliam.Kucharski@Sun.COM 	}
2952*8044SWilliam.Kucharski@Sun.COM 
2953*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82543) {
2954*8044SWilliam.Kucharski@Sun.COM 		/* Set up Op-code, Phy Address, register address, and data intended
2955*8044SWilliam.Kucharski@Sun.COM 		 * for the PHY register in the MDI Control register.  The MAC will take
2956*8044SWilliam.Kucharski@Sun.COM 		 * care of interfacing with the PHY to send the desired data.
2957*8044SWilliam.Kucharski@Sun.COM 		 */
2958*8044SWilliam.Kucharski@Sun.COM 		mdic = (((uint32_t) phy_data) |
2959*8044SWilliam.Kucharski@Sun.COM 			(reg_addr << E1000_MDIC_REG_SHIFT) |
2960*8044SWilliam.Kucharski@Sun.COM 			(phy_addr << E1000_MDIC_PHY_SHIFT) |
2961*8044SWilliam.Kucharski@Sun.COM 			(E1000_MDIC_OP_WRITE));
2962*8044SWilliam.Kucharski@Sun.COM 
2963*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, MDIC, mdic);
2964*8044SWilliam.Kucharski@Sun.COM 
2965*8044SWilliam.Kucharski@Sun.COM 		/* Poll the ready bit to see if the MDI read completed */
2966*8044SWilliam.Kucharski@Sun.COM 		for(i = 0; i < 640; i++) {
2967*8044SWilliam.Kucharski@Sun.COM 			udelay(5);
2968*8044SWilliam.Kucharski@Sun.COM 			mdic = E1000_READ_REG(hw, MDIC);
2969*8044SWilliam.Kucharski@Sun.COM 			if(mdic & E1000_MDIC_READY) break;
2970*8044SWilliam.Kucharski@Sun.COM 		}
2971*8044SWilliam.Kucharski@Sun.COM 		if(!(mdic & E1000_MDIC_READY)) {
2972*8044SWilliam.Kucharski@Sun.COM 			DEBUGOUT("MDI Write did not complete\n");
2973*8044SWilliam.Kucharski@Sun.COM 			return -E1000_ERR_PHY;
2974*8044SWilliam.Kucharski@Sun.COM 		}
2975*8044SWilliam.Kucharski@Sun.COM 	} else {
2976*8044SWilliam.Kucharski@Sun.COM 		/* We'll need to use the SW defined pins to shift the write command
2977*8044SWilliam.Kucharski@Sun.COM 		 * out to the PHY. We first send a preamble to the PHY to signal the
2978*8044SWilliam.Kucharski@Sun.COM 		 * beginning of the MII instruction.  This is done by sending 32
2979*8044SWilliam.Kucharski@Sun.COM 		 * consecutive "1" bits.
2980*8044SWilliam.Kucharski@Sun.COM 		 */
2981*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
2982*8044SWilliam.Kucharski@Sun.COM 
2983*8044SWilliam.Kucharski@Sun.COM 		/* Now combine the remaining required fields that will indicate a
2984*8044SWilliam.Kucharski@Sun.COM 		 * write operation. We use this method instead of calling the
2985*8044SWilliam.Kucharski@Sun.COM 		 * e1000_shift_out_mdi_bits routine for each field in the command. The
2986*8044SWilliam.Kucharski@Sun.COM 		 * format of a MII write instruction is as follows:
2987*8044SWilliam.Kucharski@Sun.COM 		 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
2988*8044SWilliam.Kucharski@Sun.COM 		 */
2989*8044SWilliam.Kucharski@Sun.COM 		mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
2990*8044SWilliam.Kucharski@Sun.COM 			(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
2991*8044SWilliam.Kucharski@Sun.COM 		mdic <<= 16;
2992*8044SWilliam.Kucharski@Sun.COM 		mdic |= (uint32_t) phy_data;
2993*8044SWilliam.Kucharski@Sun.COM 
2994*8044SWilliam.Kucharski@Sun.COM 		e1000_shift_out_mdi_bits(hw, mdic, 32);
2995*8044SWilliam.Kucharski@Sun.COM 	}
2996*8044SWilliam.Kucharski@Sun.COM 
2997*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
2998*8044SWilliam.Kucharski@Sun.COM }
2999*8044SWilliam.Kucharski@Sun.COM 
3000*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3001*8044SWilliam.Kucharski@Sun.COM * Returns the PHY to the power-on reset state
3002*8044SWilliam.Kucharski@Sun.COM *
3003*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3004*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3005*8044SWilliam.Kucharski@Sun.COM static void
3006*8044SWilliam.Kucharski@Sun.COM e1000_phy_hw_reset(struct e1000_hw *hw)
3007*8044SWilliam.Kucharski@Sun.COM {
3008*8044SWilliam.Kucharski@Sun.COM 	uint32_t ctrl, ctrl_ext;
3009*8044SWilliam.Kucharski@Sun.COM 
3010*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_phy_hw_reset");
3011*8044SWilliam.Kucharski@Sun.COM 
3012*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT("Resetting Phy...\n");
3013*8044SWilliam.Kucharski@Sun.COM 
3014*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type > e1000_82543) {
3015*8044SWilliam.Kucharski@Sun.COM 		/* Read the device control register and assert the E1000_CTRL_PHY_RST
3016*8044SWilliam.Kucharski@Sun.COM 		 * bit. Then, take it out of reset.
3017*8044SWilliam.Kucharski@Sun.COM 		 */
3018*8044SWilliam.Kucharski@Sun.COM 		ctrl = E1000_READ_REG(hw, CTRL);
3019*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
3020*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
3021*8044SWilliam.Kucharski@Sun.COM 		mdelay(10);
3022*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL, ctrl);
3023*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
3024*8044SWilliam.Kucharski@Sun.COM 	} else {
3025*8044SWilliam.Kucharski@Sun.COM 		/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
3026*8044SWilliam.Kucharski@Sun.COM 		 * bit to put the PHY into reset. Then, take it out of reset.
3027*8044SWilliam.Kucharski@Sun.COM 		 */
3028*8044SWilliam.Kucharski@Sun.COM 		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
3029*8044SWilliam.Kucharski@Sun.COM 		ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
3030*8044SWilliam.Kucharski@Sun.COM 		ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
3031*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
3032*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
3033*8044SWilliam.Kucharski@Sun.COM 		mdelay(10);
3034*8044SWilliam.Kucharski@Sun.COM 		ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
3035*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
3036*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_FLUSH(hw);
3037*8044SWilliam.Kucharski@Sun.COM 	}
3038*8044SWilliam.Kucharski@Sun.COM 	udelay(150);
3039*8044SWilliam.Kucharski@Sun.COM }
3040*8044SWilliam.Kucharski@Sun.COM 
3041*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3042*8044SWilliam.Kucharski@Sun.COM * Resets the PHY
3043*8044SWilliam.Kucharski@Sun.COM *
3044*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3045*8044SWilliam.Kucharski@Sun.COM *
3046*8044SWilliam.Kucharski@Sun.COM * Sets bit 15 of the MII Control regiser
3047*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3048*8044SWilliam.Kucharski@Sun.COM static int
3049*8044SWilliam.Kucharski@Sun.COM e1000_phy_reset(struct e1000_hw *hw)
3050*8044SWilliam.Kucharski@Sun.COM {
3051*8044SWilliam.Kucharski@Sun.COM 	int32_t ret_val;
3052*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_data;
3053*8044SWilliam.Kucharski@Sun.COM 
3054*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_phy_reset");
3055*8044SWilliam.Kucharski@Sun.COM 
3056*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type != e1000_82541_rev_2) {
3057*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
3058*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
3059*8044SWilliam.Kucharski@Sun.COM 
3060*8044SWilliam.Kucharski@Sun.COM 		phy_data |= MII_CR_RESET;
3061*8044SWilliam.Kucharski@Sun.COM 		if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
3062*8044SWilliam.Kucharski@Sun.COM 			return ret_val;
3063*8044SWilliam.Kucharski@Sun.COM 
3064*8044SWilliam.Kucharski@Sun.COM 		udelay(1);
3065*8044SWilliam.Kucharski@Sun.COM 	} else e1000_phy_hw_reset(hw);
3066*8044SWilliam.Kucharski@Sun.COM 
3067*8044SWilliam.Kucharski@Sun.COM 	if(hw->phy_type == e1000_phy_igp)
3068*8044SWilliam.Kucharski@Sun.COM 		e1000_phy_init_script(hw);
3069*8044SWilliam.Kucharski@Sun.COM 
3070*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
3071*8044SWilliam.Kucharski@Sun.COM }
3072*8044SWilliam.Kucharski@Sun.COM 
3073*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3074*8044SWilliam.Kucharski@Sun.COM * Probes the expected PHY address for known PHY IDs
3075*8044SWilliam.Kucharski@Sun.COM *
3076*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3077*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3078*8044SWilliam.Kucharski@Sun.COM static int
3079*8044SWilliam.Kucharski@Sun.COM e1000_detect_gig_phy(struct e1000_hw *hw)
3080*8044SWilliam.Kucharski@Sun.COM {
3081*8044SWilliam.Kucharski@Sun.COM 	int32_t phy_init_status, ret_val;
3082*8044SWilliam.Kucharski@Sun.COM 	uint16_t phy_id_high, phy_id_low;
3083*8044SWilliam.Kucharski@Sun.COM 	boolean_t match = FALSE;
3084*8044SWilliam.Kucharski@Sun.COM 
3085*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_detect_gig_phy");
3086*8044SWilliam.Kucharski@Sun.COM 
3087*8044SWilliam.Kucharski@Sun.COM 	/* Read the PHY ID Registers to identify which PHY is onboard. */
3088*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high)))
3089*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
3090*8044SWilliam.Kucharski@Sun.COM 
3091*8044SWilliam.Kucharski@Sun.COM 	hw->phy_id = (uint32_t) (phy_id_high << 16);
3092*8044SWilliam.Kucharski@Sun.COM 	udelay(20);
3093*8044SWilliam.Kucharski@Sun.COM 	if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low)))
3094*8044SWilliam.Kucharski@Sun.COM 		return ret_val;
3095*8044SWilliam.Kucharski@Sun.COM 
3096*8044SWilliam.Kucharski@Sun.COM 	hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
3097*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
3098*8044SWilliam.Kucharski@Sun.COM 	hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
3099*8044SWilliam.Kucharski@Sun.COM #endif
3100*8044SWilliam.Kucharski@Sun.COM 
3101*8044SWilliam.Kucharski@Sun.COM 	switch(hw->mac_type) {
3102*8044SWilliam.Kucharski@Sun.COM 	case e1000_82543:
3103*8044SWilliam.Kucharski@Sun.COM 		if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
3104*8044SWilliam.Kucharski@Sun.COM 		break;
3105*8044SWilliam.Kucharski@Sun.COM 	case e1000_82544:
3106*8044SWilliam.Kucharski@Sun.COM 		if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
3107*8044SWilliam.Kucharski@Sun.COM 		break;
3108*8044SWilliam.Kucharski@Sun.COM 	case e1000_82540:
3109*8044SWilliam.Kucharski@Sun.COM 	case e1000_82545:
3110*8044SWilliam.Kucharski@Sun.COM 	case e1000_82545_rev_3:
3111*8044SWilliam.Kucharski@Sun.COM 	case e1000_82546:
3112*8044SWilliam.Kucharski@Sun.COM 	case e1000_82546_rev_3:
3113*8044SWilliam.Kucharski@Sun.COM 		if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
3114*8044SWilliam.Kucharski@Sun.COM 		break;
3115*8044SWilliam.Kucharski@Sun.COM 	case e1000_82541:
3116*8044SWilliam.Kucharski@Sun.COM 	case e1000_82541_rev_2:
3117*8044SWilliam.Kucharski@Sun.COM 	case e1000_82547:
3118*8044SWilliam.Kucharski@Sun.COM 	case e1000_82547_rev_2:
3119*8044SWilliam.Kucharski@Sun.COM 		if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
3120*8044SWilliam.Kucharski@Sun.COM 		break;
3121*8044SWilliam.Kucharski@Sun.COM 	default:
3122*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
3123*8044SWilliam.Kucharski@Sun.COM 		return -E1000_ERR_CONFIG;
3124*8044SWilliam.Kucharski@Sun.COM 	}
3125*8044SWilliam.Kucharski@Sun.COM 	phy_init_status = e1000_set_phy_type(hw);
3126*8044SWilliam.Kucharski@Sun.COM 
3127*8044SWilliam.Kucharski@Sun.COM 	if ((match) && (phy_init_status == E1000_SUCCESS)) {
3128*8044SWilliam.Kucharski@Sun.COM 		DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
3129*8044SWilliam.Kucharski@Sun.COM 		return E1000_SUCCESS;
3130*8044SWilliam.Kucharski@Sun.COM 	}
3131*8044SWilliam.Kucharski@Sun.COM 	DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
3132*8044SWilliam.Kucharski@Sun.COM 	return -E1000_ERR_PHY;
3133*8044SWilliam.Kucharski@Sun.COM }
3134*8044SWilliam.Kucharski@Sun.COM 
3135*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3136*8044SWilliam.Kucharski@Sun.COM  * Sets up eeprom variables in the hw struct.  Must be called after mac_type
3137*8044SWilliam.Kucharski@Sun.COM  * is configured.
3138*8044SWilliam.Kucharski@Sun.COM  *
3139*8044SWilliam.Kucharski@Sun.COM  * hw - Struct containing variables accessed by shared code
3140*8044SWilliam.Kucharski@Sun.COM  *****************************************************************************/
3141*8044SWilliam.Kucharski@Sun.COM static void
3142*8044SWilliam.Kucharski@Sun.COM e1000_init_eeprom_params(struct e1000_hw *hw)
3143*8044SWilliam.Kucharski@Sun.COM {
3144*8044SWilliam.Kucharski@Sun.COM 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
3145*8044SWilliam.Kucharski@Sun.COM 	uint32_t eecd = E1000_READ_REG(hw, EECD);
3146*8044SWilliam.Kucharski@Sun.COM 	uint16_t eeprom_size;
3147*8044SWilliam.Kucharski@Sun.COM 
3148*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("e1000_init_eeprom_params");
3149*8044SWilliam.Kucharski@Sun.COM 
3150*8044SWilliam.Kucharski@Sun.COM 	switch (hw->mac_type) {
3151*8044SWilliam.Kucharski@Sun.COM 	case e1000_82542_rev2_0:
3152*8044SWilliam.Kucharski@Sun.COM 	case e1000_82542_rev2_1:
3153*8044SWilliam.Kucharski@Sun.COM 	case e1000_82543:
3154*8044SWilliam.Kucharski@Sun.COM 	case e1000_82544:
3155*8044SWilliam.Kucharski@Sun.COM 		eeprom->type = e1000_eeprom_microwire;
3156*8044SWilliam.Kucharski@Sun.COM 		eeprom->word_size = 64;
3157*8044SWilliam.Kucharski@Sun.COM 		eeprom->opcode_bits = 3;
3158*8044SWilliam.Kucharski@Sun.COM 		eeprom->address_bits = 6;
3159*8044SWilliam.Kucharski@Sun.COM 		eeprom->delay_usec = 50;
3160*8044SWilliam.Kucharski@Sun.COM 		break;
3161*8044SWilliam.Kucharski@Sun.COM 	case e1000_82540:
3162*8044SWilliam.Kucharski@Sun.COM 	case e1000_82545:
3163*8044SWilliam.Kucharski@Sun.COM 	case e1000_82545_rev_3:
3164*8044SWilliam.Kucharski@Sun.COM 	case e1000_82546:
3165*8044SWilliam.Kucharski@Sun.COM 	case e1000_82546_rev_3:
3166*8044SWilliam.Kucharski@Sun.COM 		eeprom->type = e1000_eeprom_microwire;
3167*8044SWilliam.Kucharski@Sun.COM 		eeprom->opcode_bits = 3;
3168*8044SWilliam.Kucharski@Sun.COM 		eeprom->delay_usec = 50;
3169*8044SWilliam.Kucharski@Sun.COM 		if(eecd & E1000_EECD_SIZE) {
3170*8044SWilliam.Kucharski@Sun.COM 			eeprom->word_size = 256;
3171*8044SWilliam.Kucharski@Sun.COM 			eeprom->address_bits = 8;
3172*8044SWilliam.Kucharski@Sun.COM 		} else {
3173*8044SWilliam.Kucharski@Sun.COM 			eeprom->word_size = 64;
3174*8044SWilliam.Kucharski@Sun.COM 			eeprom->address_bits = 6;
3175*8044SWilliam.Kucharski@Sun.COM 		}
3176*8044SWilliam.Kucharski@Sun.COM 		break;
3177*8044SWilliam.Kucharski@Sun.COM 	case e1000_82541:
3178*8044SWilliam.Kucharski@Sun.COM 	case e1000_82541_rev_2:
3179*8044SWilliam.Kucharski@Sun.COM 	case e1000_82547:
3180*8044SWilliam.Kucharski@Sun.COM 	case e1000_82547_rev_2:
3181*8044SWilliam.Kucharski@Sun.COM 		if (eecd & E1000_EECD_TYPE) {
3182*8044SWilliam.Kucharski@Sun.COM 			eeprom->type = e1000_eeprom_spi;
3183*8044SWilliam.Kucharski@Sun.COM 			if (eecd & E1000_EECD_ADDR_BITS) {
3184*8044SWilliam.Kucharski@Sun.COM 				eeprom->page_size = 32;
3185*8044SWilliam.Kucharski@Sun.COM 				eeprom->address_bits = 16;
3186*8044SWilliam.Kucharski@Sun.COM 			} else {
3187*8044SWilliam.Kucharski@Sun.COM 				eeprom->page_size = 8;
3188*8044SWilliam.Kucharski@Sun.COM 				eeprom->address_bits = 8;
3189*8044SWilliam.Kucharski@Sun.COM 			}
3190*8044SWilliam.Kucharski@Sun.COM 		} else {
3191*8044SWilliam.Kucharski@Sun.COM 			eeprom->type = e1000_eeprom_microwire;
3192*8044SWilliam.Kucharski@Sun.COM 			eeprom->opcode_bits = 3;
3193*8044SWilliam.Kucharski@Sun.COM 			eeprom->delay_usec = 50;
3194*8044SWilliam.Kucharski@Sun.COM 			if (eecd & E1000_EECD_ADDR_BITS) {
3195*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 256;
3196*8044SWilliam.Kucharski@Sun.COM 				eeprom->address_bits = 8;
3197*8044SWilliam.Kucharski@Sun.COM 			} else {
3198*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 64;
3199*8044SWilliam.Kucharski@Sun.COM 				eeprom->address_bits = 6;
3200*8044SWilliam.Kucharski@Sun.COM 			}
3201*8044SWilliam.Kucharski@Sun.COM 		}
3202*8044SWilliam.Kucharski@Sun.COM 		break;
3203*8044SWilliam.Kucharski@Sun.COM 	default:
3204*8044SWilliam.Kucharski@Sun.COM 		eeprom->type = e1000_eeprom_spi;
3205*8044SWilliam.Kucharski@Sun.COM 		if (eecd & E1000_EECD_ADDR_BITS) {
3206*8044SWilliam.Kucharski@Sun.COM 			eeprom->page_size = 32;
3207*8044SWilliam.Kucharski@Sun.COM 			eeprom->address_bits = 16;
3208*8044SWilliam.Kucharski@Sun.COM 		} else {
3209*8044SWilliam.Kucharski@Sun.COM 			eeprom->page_size = 8;
3210*8044SWilliam.Kucharski@Sun.COM 			eeprom->address_bits = 8;
3211*8044SWilliam.Kucharski@Sun.COM 		}
3212*8044SWilliam.Kucharski@Sun.COM 		break;
3213*8044SWilliam.Kucharski@Sun.COM 	}
3214*8044SWilliam.Kucharski@Sun.COM 
3215*8044SWilliam.Kucharski@Sun.COM 	if (eeprom->type == e1000_eeprom_spi) {
3216*8044SWilliam.Kucharski@Sun.COM 		eeprom->opcode_bits = 8;
3217*8044SWilliam.Kucharski@Sun.COM 		eeprom->delay_usec = 1;
3218*8044SWilliam.Kucharski@Sun.COM 		eeprom->word_size = 64;
3219*8044SWilliam.Kucharski@Sun.COM 		if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) {
3220*8044SWilliam.Kucharski@Sun.COM 			eeprom_size &= EEPROM_SIZE_MASK;
3221*8044SWilliam.Kucharski@Sun.COM 
3222*8044SWilliam.Kucharski@Sun.COM 			switch (eeprom_size) {
3223*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_16KB:
3224*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 8192;
3225*8044SWilliam.Kucharski@Sun.COM 				break;
3226*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_8KB:
3227*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 4096;
3228*8044SWilliam.Kucharski@Sun.COM 				break;
3229*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_4KB:
3230*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 2048;
3231*8044SWilliam.Kucharski@Sun.COM 				break;
3232*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_2KB:
3233*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 1024;
3234*8044SWilliam.Kucharski@Sun.COM 				break;
3235*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_1KB:
3236*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 512;
3237*8044SWilliam.Kucharski@Sun.COM 				break;
3238*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_512B:
3239*8044SWilliam.Kucharski@Sun.COM 				eeprom->word_size = 256;
3240*8044SWilliam.Kucharski@Sun.COM 				break;
3241*8044SWilliam.Kucharski@Sun.COM 			case EEPROM_SIZE_128B:
3242*8044SWilliam.Kucharski@Sun.COM 			default:
3243*8044SWilliam.Kucharski@Sun.COM 				break;
3244*8044SWilliam.Kucharski@Sun.COM 			}
3245*8044SWilliam.Kucharski@Sun.COM 		}
3246*8044SWilliam.Kucharski@Sun.COM 	}
3247*8044SWilliam.Kucharski@Sun.COM }
3248*8044SWilliam.Kucharski@Sun.COM 
3249*8044SWilliam.Kucharski@Sun.COM /**
3250*8044SWilliam.Kucharski@Sun.COM  * e1000_reset - Reset the adapter
3251*8044SWilliam.Kucharski@Sun.COM  */
3252*8044SWilliam.Kucharski@Sun.COM 
3253*8044SWilliam.Kucharski@Sun.COM static int
3254*8044SWilliam.Kucharski@Sun.COM e1000_reset(struct e1000_hw *hw)
3255*8044SWilliam.Kucharski@Sun.COM {
3256*8044SWilliam.Kucharski@Sun.COM 	uint32_t pba;
3257*8044SWilliam.Kucharski@Sun.COM 	/* Repartition Pba for greater than 9k mtu
3258*8044SWilliam.Kucharski@Sun.COM 	 * To take effect CTRL.RST is required.
3259*8044SWilliam.Kucharski@Sun.COM 	 */
3260*8044SWilliam.Kucharski@Sun.COM 
3261*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type < e1000_82547) {
3262*8044SWilliam.Kucharski@Sun.COM 		pba = E1000_PBA_48K;
3263*8044SWilliam.Kucharski@Sun.COM 	} else {
3264*8044SWilliam.Kucharski@Sun.COM 		pba = E1000_PBA_30K;
3265*8044SWilliam.Kucharski@Sun.COM 	}
3266*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG(hw, PBA, pba);
3267*8044SWilliam.Kucharski@Sun.COM 
3268*8044SWilliam.Kucharski@Sun.COM 	/* flow control settings */
3269*8044SWilliam.Kucharski@Sun.COM #if 0
3270*8044SWilliam.Kucharski@Sun.COM 	hw->fc_high_water = FC_DEFAULT_HI_THRESH;
3271*8044SWilliam.Kucharski@Sun.COM 	hw->fc_low_water = FC_DEFAULT_LO_THRESH;
3272*8044SWilliam.Kucharski@Sun.COM 	hw->fc_pause_time = FC_DEFAULT_TX_TIMER;
3273*8044SWilliam.Kucharski@Sun.COM 	hw->fc_send_xon = 1;
3274*8044SWilliam.Kucharski@Sun.COM 	hw->fc = hw->original_fc;
3275*8044SWilliam.Kucharski@Sun.COM #endif
3276*8044SWilliam.Kucharski@Sun.COM 
3277*8044SWilliam.Kucharski@Sun.COM 	e1000_reset_hw(hw);
3278*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type >= e1000_82544)
3279*8044SWilliam.Kucharski@Sun.COM 		E1000_WRITE_REG(hw, WUC, 0);
3280*8044SWilliam.Kucharski@Sun.COM 	return e1000_init_hw(hw);
3281*8044SWilliam.Kucharski@Sun.COM }
3282*8044SWilliam.Kucharski@Sun.COM 
3283*8044SWilliam.Kucharski@Sun.COM /**
3284*8044SWilliam.Kucharski@Sun.COM  * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
3285*8044SWilliam.Kucharski@Sun.COM  * @adapter: board private structure to initialize
3286*8044SWilliam.Kucharski@Sun.COM  *
3287*8044SWilliam.Kucharski@Sun.COM  * e1000_sw_init initializes the Adapter private data structure.
3288*8044SWilliam.Kucharski@Sun.COM  * Fields are initialized based on PCI device information and
3289*8044SWilliam.Kucharski@Sun.COM  * OS network device settings (MTU size).
3290*8044SWilliam.Kucharski@Sun.COM  **/
3291*8044SWilliam.Kucharski@Sun.COM 
3292*8044SWilliam.Kucharski@Sun.COM static int
3293*8044SWilliam.Kucharski@Sun.COM e1000_sw_init(struct pci_device *pdev, struct e1000_hw *hw)
3294*8044SWilliam.Kucharski@Sun.COM {
3295*8044SWilliam.Kucharski@Sun.COM 	int result;
3296*8044SWilliam.Kucharski@Sun.COM 
3297*8044SWilliam.Kucharski@Sun.COM 	/* PCI config space info */
3298*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_word(pdev, PCI_VENDOR_ID, &hw->vendor_id);
3299*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_word(pdev, PCI_DEVICE_ID, &hw->device_id);
3300*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_byte(pdev, PCI_REVISION, &hw->revision_id);
3301*8044SWilliam.Kucharski@Sun.COM #if 0
3302*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID,
3303*8044SWilliam.Kucharski@Sun.COM                              &hw->subsystem_vendor_id);
3304*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id);
3305*8044SWilliam.Kucharski@Sun.COM #endif
3306*8044SWilliam.Kucharski@Sun.COM 
3307*8044SWilliam.Kucharski@Sun.COM 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
3308*8044SWilliam.Kucharski@Sun.COM 
3309*8044SWilliam.Kucharski@Sun.COM 	/* identify the MAC */
3310*8044SWilliam.Kucharski@Sun.COM 
3311*8044SWilliam.Kucharski@Sun.COM 	result = e1000_set_mac_type(hw);
3312*8044SWilliam.Kucharski@Sun.COM 	if (result) {
3313*8044SWilliam.Kucharski@Sun.COM 		E1000_ERR("Unknown MAC Type\n");
3314*8044SWilliam.Kucharski@Sun.COM 		return result;
3315*8044SWilliam.Kucharski@Sun.COM 	}
3316*8044SWilliam.Kucharski@Sun.COM 
3317*8044SWilliam.Kucharski@Sun.COM 	/* initialize eeprom parameters */
3318*8044SWilliam.Kucharski@Sun.COM 
3319*8044SWilliam.Kucharski@Sun.COM 	e1000_init_eeprom_params(hw);
3320*8044SWilliam.Kucharski@Sun.COM 
3321*8044SWilliam.Kucharski@Sun.COM #if 0
3322*8044SWilliam.Kucharski@Sun.COM 	if((hw->mac_type == e1000_82541) ||
3323*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82547) ||
3324*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82541_rev_2) ||
3325*8044SWilliam.Kucharski@Sun.COM 	   (hw->mac_type == e1000_82547_rev_2))
3326*8044SWilliam.Kucharski@Sun.COM 		hw->phy_init_script = 1;
3327*8044SWilliam.Kucharski@Sun.COM #endif
3328*8044SWilliam.Kucharski@Sun.COM 
3329*8044SWilliam.Kucharski@Sun.COM 	e1000_set_media_type(hw);
3330*8044SWilliam.Kucharski@Sun.COM 
3331*8044SWilliam.Kucharski@Sun.COM #if 0
3332*8044SWilliam.Kucharski@Sun.COM 	if(hw->mac_type < e1000_82543)
3333*8044SWilliam.Kucharski@Sun.COM 		hw->report_tx_early = 0;
3334*8044SWilliam.Kucharski@Sun.COM 	else
3335*8044SWilliam.Kucharski@Sun.COM 		hw->report_tx_early = 1;
3336*8044SWilliam.Kucharski@Sun.COM 
3337*8044SWilliam.Kucharski@Sun.COM 	hw->wait_autoneg_complete = FALSE;
3338*8044SWilliam.Kucharski@Sun.COM #endif
3339*8044SWilliam.Kucharski@Sun.COM 	hw->tbi_compatibility_en = TRUE;
3340*8044SWilliam.Kucharski@Sun.COM #if 0
3341*8044SWilliam.Kucharski@Sun.COM 	hw->adaptive_ifs = TRUE;
3342*8044SWilliam.Kucharski@Sun.COM 
3343*8044SWilliam.Kucharski@Sun.COM 	/* Copper options */
3344*8044SWilliam.Kucharski@Sun.COM 
3345*8044SWilliam.Kucharski@Sun.COM 	if(hw->media_type == e1000_media_type_copper) {
3346*8044SWilliam.Kucharski@Sun.COM 		hw->mdix = AUTO_ALL_MODES;
3347*8044SWilliam.Kucharski@Sun.COM 		hw->disable_polarity_correction = FALSE;
3348*8044SWilliam.Kucharski@Sun.COM 		hw->master_slave = E1000_MASTER_SLAVE;
3349*8044SWilliam.Kucharski@Sun.COM 	}
3350*8044SWilliam.Kucharski@Sun.COM #endif
3351*8044SWilliam.Kucharski@Sun.COM 	return E1000_SUCCESS;
3352*8044SWilliam.Kucharski@Sun.COM }
3353*8044SWilliam.Kucharski@Sun.COM 
3354*8044SWilliam.Kucharski@Sun.COM static void fill_rx (void)
3355*8044SWilliam.Kucharski@Sun.COM {
3356*8044SWilliam.Kucharski@Sun.COM 	struct e1000_rx_desc *rd;
3357*8044SWilliam.Kucharski@Sun.COM 	rx_last = rx_tail;
3358*8044SWilliam.Kucharski@Sun.COM 	rd = rx_base + rx_tail;
3359*8044SWilliam.Kucharski@Sun.COM 	rx_tail = (rx_tail + 1) % 8;
3360*8044SWilliam.Kucharski@Sun.COM 	memset (rd, 0, 16);
3361*8044SWilliam.Kucharski@Sun.COM 	rd->buffer_addr = virt_to_bus(&packet);
3362*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDT, rx_tail);
3363*8044SWilliam.Kucharski@Sun.COM }
3364*8044SWilliam.Kucharski@Sun.COM 
3365*8044SWilliam.Kucharski@Sun.COM static void init_descriptor (void)
3366*8044SWilliam.Kucharski@Sun.COM {
3367*8044SWilliam.Kucharski@Sun.COM 	unsigned long ptr;
3368*8044SWilliam.Kucharski@Sun.COM 	unsigned long tctl;
3369*8044SWilliam.Kucharski@Sun.COM 
3370*8044SWilliam.Kucharski@Sun.COM 	ptr = virt_to_phys(tx_pool);
3371*8044SWilliam.Kucharski@Sun.COM 	if (ptr & 0xf)
3372*8044SWilliam.Kucharski@Sun.COM 		ptr = (ptr + 0x10) & (~0xf);
3373*8044SWilliam.Kucharski@Sun.COM 
3374*8044SWilliam.Kucharski@Sun.COM 	tx_base = phys_to_virt(ptr);
3375*8044SWilliam.Kucharski@Sun.COM 
3376*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDBAL, virt_to_bus(tx_base));
3377*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDBAH, 0);
3378*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDLEN, 128);
3379*8044SWilliam.Kucharski@Sun.COM 
3380*8044SWilliam.Kucharski@Sun.COM 	/* Setup the HW Tx Head and Tail descriptor pointers */
3381*8044SWilliam.Kucharski@Sun.COM 
3382*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDH, 0);
3383*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDT, 0);
3384*8044SWilliam.Kucharski@Sun.COM 	tx_tail = 0;
3385*8044SWilliam.Kucharski@Sun.COM 
3386*8044SWilliam.Kucharski@Sun.COM 	/* Program the Transmit Control Register */
3387*8044SWilliam.Kucharski@Sun.COM 
3388*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER_TCTL
3389*8044SWilliam.Kucharski@Sun.COM 	tctl = E1000_READ_REG(&hw, TCTL);
3390*8044SWilliam.Kucharski@Sun.COM 
3391*8044SWilliam.Kucharski@Sun.COM 	tctl &= ~E1000_TCTL_CT;
3392*8044SWilliam.Kucharski@Sun.COM 	tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
3393*8044SWilliam.Kucharski@Sun.COM 		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
3394*8044SWilliam.Kucharski@Sun.COM #else
3395*8044SWilliam.Kucharski@Sun.COM 	tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
3396*8044SWilliam.Kucharski@Sun.COM 		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) |
3397*8044SWilliam.Kucharski@Sun.COM 		(E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
3398*8044SWilliam.Kucharski@Sun.COM #endif
3399*8044SWilliam.Kucharski@Sun.COM 
3400*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TCTL, tctl);
3401*8044SWilliam.Kucharski@Sun.COM 
3402*8044SWilliam.Kucharski@Sun.COM 	e1000_config_collision_dist(&hw);
3403*8044SWilliam.Kucharski@Sun.COM 
3404*8044SWilliam.Kucharski@Sun.COM 
3405*8044SWilliam.Kucharski@Sun.COM 	rx_tail = 0;
3406*8044SWilliam.Kucharski@Sun.COM 	/* disable receive */
3407*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RCTL, 0);
3408*8044SWilliam.Kucharski@Sun.COM 	ptr = virt_to_phys(rx_pool);
3409*8044SWilliam.Kucharski@Sun.COM 	if (ptr & 0xf)
3410*8044SWilliam.Kucharski@Sun.COM 		ptr = (ptr + 0x10) & (~0xf);
3411*8044SWilliam.Kucharski@Sun.COM 	rx_base = phys_to_virt(ptr);
3412*8044SWilliam.Kucharski@Sun.COM 
3413*8044SWilliam.Kucharski@Sun.COM 	/* Setup the Base and Length of the Rx Descriptor Ring */
3414*8044SWilliam.Kucharski@Sun.COM 
3415*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDBAL, virt_to_bus(rx_base));
3416*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDBAH, 0);
3417*8044SWilliam.Kucharski@Sun.COM 
3418*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDLEN, 128);
3419*8044SWilliam.Kucharski@Sun.COM 
3420*8044SWilliam.Kucharski@Sun.COM 	/* Setup the HW Rx Head and Tail Descriptor Pointers */
3421*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDH, 0);
3422*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDT, 0);
3423*8044SWilliam.Kucharski@Sun.COM 
3424*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RCTL,
3425*8044SWilliam.Kucharski@Sun.COM 		E1000_RCTL_EN |
3426*8044SWilliam.Kucharski@Sun.COM 		E1000_RCTL_BAM |
3427*8044SWilliam.Kucharski@Sun.COM 		E1000_RCTL_SZ_2048 |
3428*8044SWilliam.Kucharski@Sun.COM 		E1000_RCTL_MPE);
3429*8044SWilliam.Kucharski@Sun.COM 	fill_rx();
3430*8044SWilliam.Kucharski@Sun.COM }
3431*8044SWilliam.Kucharski@Sun.COM 
3432*8044SWilliam.Kucharski@Sun.COM 
3433*8044SWilliam.Kucharski@Sun.COM 
3434*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3435*8044SWilliam.Kucharski@Sun.COM POLL - Wait for a frame
3436*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3437*8044SWilliam.Kucharski@Sun.COM static int
3438*8044SWilliam.Kucharski@Sun.COM e1000_poll (struct nic *nic, int retrieve)
3439*8044SWilliam.Kucharski@Sun.COM {
3440*8044SWilliam.Kucharski@Sun.COM 	/* return true if there's an ethernet packet ready to read */
3441*8044SWilliam.Kucharski@Sun.COM 	/* nic->packet should contain data on return */
3442*8044SWilliam.Kucharski@Sun.COM 	/* nic->packetlen should contain length of data */
3443*8044SWilliam.Kucharski@Sun.COM 	struct e1000_rx_desc *rd;
3444*8044SWilliam.Kucharski@Sun.COM 
3445*8044SWilliam.Kucharski@Sun.COM 	rd = rx_base + rx_last;
3446*8044SWilliam.Kucharski@Sun.COM 	if (!rd->status & E1000_RXD_STAT_DD)
3447*8044SWilliam.Kucharski@Sun.COM 		return 0;
3448*8044SWilliam.Kucharski@Sun.COM 
3449*8044SWilliam.Kucharski@Sun.COM 	if ( ! retrieve ) return 1;
3450*8044SWilliam.Kucharski@Sun.COM 
3451*8044SWilliam.Kucharski@Sun.COM 	//      printf("recv: packet %! -> %! len=%d \n", packet+6, packet,rd->Length);
3452*8044SWilliam.Kucharski@Sun.COM 	memcpy (nic->packet, packet, rd->length);
3453*8044SWilliam.Kucharski@Sun.COM 	nic->packetlen = rd->length;
3454*8044SWilliam.Kucharski@Sun.COM 	fill_rx ();
3455*8044SWilliam.Kucharski@Sun.COM 	return 1;
3456*8044SWilliam.Kucharski@Sun.COM }
3457*8044SWilliam.Kucharski@Sun.COM 
3458*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3459*8044SWilliam.Kucharski@Sun.COM TRANSMIT - Transmit a frame
3460*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3461*8044SWilliam.Kucharski@Sun.COM static void
3462*8044SWilliam.Kucharski@Sun.COM e1000_transmit (struct nic *nic, const char *d,	/* Destination */
3463*8044SWilliam.Kucharski@Sun.COM 		    unsigned int type,	/* Type */
3464*8044SWilliam.Kucharski@Sun.COM 		    unsigned int size,	/* size */
3465*8044SWilliam.Kucharski@Sun.COM 		    const char *p)	/* Packet */
3466*8044SWilliam.Kucharski@Sun.COM {
3467*8044SWilliam.Kucharski@Sun.COM 	/* send the packet to destination */
3468*8044SWilliam.Kucharski@Sun.COM 	struct eth_hdr {
3469*8044SWilliam.Kucharski@Sun.COM 		unsigned char dst_addr[ETH_ALEN];
3470*8044SWilliam.Kucharski@Sun.COM 		unsigned char src_addr[ETH_ALEN];
3471*8044SWilliam.Kucharski@Sun.COM 		unsigned short type;
3472*8044SWilliam.Kucharski@Sun.COM 	} hdr;
3473*8044SWilliam.Kucharski@Sun.COM 	struct e1000_tx_desc *txhd;	/* header */
3474*8044SWilliam.Kucharski@Sun.COM 	struct e1000_tx_desc *txp;	/* payload */
3475*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("send");
3476*8044SWilliam.Kucharski@Sun.COM 
3477*8044SWilliam.Kucharski@Sun.COM 	memcpy (&hdr.dst_addr, d, ETH_ALEN);
3478*8044SWilliam.Kucharski@Sun.COM 	memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
3479*8044SWilliam.Kucharski@Sun.COM 
3480*8044SWilliam.Kucharski@Sun.COM 	hdr.type = htons (type);
3481*8044SWilliam.Kucharski@Sun.COM 	txhd = tx_base + tx_tail;
3482*8044SWilliam.Kucharski@Sun.COM 	tx_tail = (tx_tail + 1) % 8;
3483*8044SWilliam.Kucharski@Sun.COM 	txp = tx_base + tx_tail;
3484*8044SWilliam.Kucharski@Sun.COM 	tx_tail = (tx_tail + 1) % 8;
3485*8044SWilliam.Kucharski@Sun.COM 
3486*8044SWilliam.Kucharski@Sun.COM 	txhd->buffer_addr = virt_to_bus (&hdr);
3487*8044SWilliam.Kucharski@Sun.COM 	txhd->lower.data = sizeof (hdr);
3488*8044SWilliam.Kucharski@Sun.COM 	txhd->upper.data = 0;
3489*8044SWilliam.Kucharski@Sun.COM 
3490*8044SWilliam.Kucharski@Sun.COM 	txp->buffer_addr = virt_to_bus(p);
3491*8044SWilliam.Kucharski@Sun.COM 	txp->lower.data = E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS | size;
3492*8044SWilliam.Kucharski@Sun.COM 	txp->upper.data = 0;
3493*8044SWilliam.Kucharski@Sun.COM 
3494*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDT, tx_tail);
3495*8044SWilliam.Kucharski@Sun.COM 	while (!(txp->upper.data & E1000_TXD_STAT_DD)) {
3496*8044SWilliam.Kucharski@Sun.COM 		udelay(10);	/* give the nic a chance to write to the register */
3497*8044SWilliam.Kucharski@Sun.COM 		poll_interruptions();
3498*8044SWilliam.Kucharski@Sun.COM 	}
3499*8044SWilliam.Kucharski@Sun.COM 	DEBUGFUNC("send end");
3500*8044SWilliam.Kucharski@Sun.COM }
3501*8044SWilliam.Kucharski@Sun.COM 
3502*8044SWilliam.Kucharski@Sun.COM 
3503*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3504*8044SWilliam.Kucharski@Sun.COM DISABLE - Turn off ethernet interface
3505*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3506*8044SWilliam.Kucharski@Sun.COM static void e1000_disable (struct dev *dev __unused)
3507*8044SWilliam.Kucharski@Sun.COM {
3508*8044SWilliam.Kucharski@Sun.COM 	/* Clear the transmit ring */
3509*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDH, 0);
3510*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TDT, 0);
3511*8044SWilliam.Kucharski@Sun.COM 
3512*8044SWilliam.Kucharski@Sun.COM 	/* Clear the receive ring */
3513*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDH, 0);
3514*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RDT, 0);
3515*8044SWilliam.Kucharski@Sun.COM 
3516*8044SWilliam.Kucharski@Sun.COM 	/* put the card in its initial state */
3517*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, CTRL, E1000_CTRL_RST);
3518*8044SWilliam.Kucharski@Sun.COM 
3519*8044SWilliam.Kucharski@Sun.COM 	/* Turn off the ethernet interface */
3520*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, RCTL, 0);
3521*8044SWilliam.Kucharski@Sun.COM 	E1000_WRITE_REG (&hw, TCTL, 0);
3522*8044SWilliam.Kucharski@Sun.COM 	mdelay (10);
3523*8044SWilliam.Kucharski@Sun.COM 
3524*8044SWilliam.Kucharski@Sun.COM 	/* Unmap my window to the device */
3525*8044SWilliam.Kucharski@Sun.COM 	iounmap(hw.hw_addr);
3526*8044SWilliam.Kucharski@Sun.COM }
3527*8044SWilliam.Kucharski@Sun.COM 
3528*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3529*8044SWilliam.Kucharski@Sun.COM IRQ - Enable, Disable, or Force interrupts
3530*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3531*8044SWilliam.Kucharski@Sun.COM static void e1000_irq(struct nic *nic __unused, irq_action_t action __unused)
3532*8044SWilliam.Kucharski@Sun.COM {
3533*8044SWilliam.Kucharski@Sun.COM   switch ( action ) {
3534*8044SWilliam.Kucharski@Sun.COM   case DISABLE :
3535*8044SWilliam.Kucharski@Sun.COM     break;
3536*8044SWilliam.Kucharski@Sun.COM   case ENABLE :
3537*8044SWilliam.Kucharski@Sun.COM     break;
3538*8044SWilliam.Kucharski@Sun.COM   case FORCE :
3539*8044SWilliam.Kucharski@Sun.COM     break;
3540*8044SWilliam.Kucharski@Sun.COM   }
3541*8044SWilliam.Kucharski@Sun.COM }
3542*8044SWilliam.Kucharski@Sun.COM 
3543*8044SWilliam.Kucharski@Sun.COM #define IORESOURCE_IO	0x00000100     /* Resource type */
3544*8044SWilliam.Kucharski@Sun.COM #define BAR_0		0
3545*8044SWilliam.Kucharski@Sun.COM #define BAR_1		1
3546*8044SWilliam.Kucharski@Sun.COM #define BAR_5		5
3547*8044SWilliam.Kucharski@Sun.COM 
3548*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3549*8044SWilliam.Kucharski@Sun.COM PROBE - Look for an adapter, this routine's visible to the outside
3550*8044SWilliam.Kucharski@Sun.COM You should omit the last argument struct pci_device * for a non-PCI NIC
3551*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3552*8044SWilliam.Kucharski@Sun.COM static int e1000_probe(struct dev *dev, struct pci_device *p)
3553*8044SWilliam.Kucharski@Sun.COM {
3554*8044SWilliam.Kucharski@Sun.COM 	struct nic *nic = (struct nic *)dev;
3555*8044SWilliam.Kucharski@Sun.COM 	unsigned long mmio_start, mmio_len;
3556*8044SWilliam.Kucharski@Sun.COM 	int ret_val, i;
3557*8044SWilliam.Kucharski@Sun.COM 
3558*8044SWilliam.Kucharski@Sun.COM 	if (p == 0)
3559*8044SWilliam.Kucharski@Sun.COM 		return 0;
3560*8044SWilliam.Kucharski@Sun.COM 	/* Initialize hw with default values */
3561*8044SWilliam.Kucharski@Sun.COM 	memset(&hw, 0, sizeof(hw));
3562*8044SWilliam.Kucharski@Sun.COM 	hw.pdev = p;
3563*8044SWilliam.Kucharski@Sun.COM 
3564*8044SWilliam.Kucharski@Sun.COM #if 1
3565*8044SWilliam.Kucharski@Sun.COM 	/* Are these variables needed? */
3566*8044SWilliam.Kucharski@Sun.COM 	hw.fc                    = e1000_fc_none;
3567*8044SWilliam.Kucharski@Sun.COM #if 0
3568*8044SWilliam.Kucharski@Sun.COM 	hw.original_fc           = e1000_fc_none;
3569*8044SWilliam.Kucharski@Sun.COM #endif
3570*8044SWilliam.Kucharski@Sun.COM 	hw.autoneg_failed        = 0;
3571*8044SWilliam.Kucharski@Sun.COM #if 0
3572*8044SWilliam.Kucharski@Sun.COM 	hw.get_link_status       = TRUE;
3573*8044SWilliam.Kucharski@Sun.COM #endif
3574*8044SWilliam.Kucharski@Sun.COM #endif
3575*8044SWilliam.Kucharski@Sun.COM 
3576*8044SWilliam.Kucharski@Sun.COM 	mmio_start = pci_bar_start(p, PCI_BASE_ADDRESS_0);
3577*8044SWilliam.Kucharski@Sun.COM 	mmio_len   = pci_bar_size(p,  PCI_BASE_ADDRESS_0);
3578*8044SWilliam.Kucharski@Sun.COM 	hw.hw_addr = ioremap(mmio_start, mmio_len);
3579*8044SWilliam.Kucharski@Sun.COM 
3580*8044SWilliam.Kucharski@Sun.COM 	for(i = BAR_1; i <= BAR_5; i++) {
3581*8044SWilliam.Kucharski@Sun.COM 		if(pci_bar_size(p, i) == 0)
3582*8044SWilliam.Kucharski@Sun.COM 			continue;
3583*8044SWilliam.Kucharski@Sun.COM 		if(pci_find_capability(p, i) & IORESOURCE_IO) {
3584*8044SWilliam.Kucharski@Sun.COM 			hw.io_base = pci_bar_start(p, i);
3585*8044SWilliam.Kucharski@Sun.COM 			break;
3586*8044SWilliam.Kucharski@Sun.COM                 }
3587*8044SWilliam.Kucharski@Sun.COM 	}
3588*8044SWilliam.Kucharski@Sun.COM 
3589*8044SWilliam.Kucharski@Sun.COM 	adjust_pci_device(p);
3590*8044SWilliam.Kucharski@Sun.COM 
3591*8044SWilliam.Kucharski@Sun.COM 	nic->ioaddr   = p->ioaddr & ~3;
3592*8044SWilliam.Kucharski@Sun.COM 	nic->irqno    = 0;
3593*8044SWilliam.Kucharski@Sun.COM 
3594*8044SWilliam.Kucharski@Sun.COM 	/* From Matt Hortman <mbhortman@acpthinclient.com> */
3595*8044SWilliam.Kucharski@Sun.COM 	/* MAC and Phy settings */
3596*8044SWilliam.Kucharski@Sun.COM 
3597*8044SWilliam.Kucharski@Sun.COM 	/* setup the private structure */
3598*8044SWilliam.Kucharski@Sun.COM 	if (e1000_sw_init(p, &hw) < 0) {
3599*8044SWilliam.Kucharski@Sun.COM 		iounmap(hw.hw_addr);
3600*8044SWilliam.Kucharski@Sun.COM 		return 0;
3601*8044SWilliam.Kucharski@Sun.COM 	}
3602*8044SWilliam.Kucharski@Sun.COM 
3603*8044SWilliam.Kucharski@Sun.COM 	/* make sure the EEPROM is good */
3604*8044SWilliam.Kucharski@Sun.COM 
3605*8044SWilliam.Kucharski@Sun.COM 	if (e1000_validate_eeprom_checksum(&hw) < 0) {
3606*8044SWilliam.Kucharski@Sun.COM 		printf ("The EEPROM Checksum Is Not Valid\n");
3607*8044SWilliam.Kucharski@Sun.COM 		iounmap(hw.hw_addr);
3608*8044SWilliam.Kucharski@Sun.COM 		return 0;
3609*8044SWilliam.Kucharski@Sun.COM 	}
3610*8044SWilliam.Kucharski@Sun.COM 
3611*8044SWilliam.Kucharski@Sun.COM 	/* copy the MAC address out of the EEPROM */
3612*8044SWilliam.Kucharski@Sun.COM 
3613*8044SWilliam.Kucharski@Sun.COM 	e1000_read_mac_addr(&hw);
3614*8044SWilliam.Kucharski@Sun.COM 	memcpy (nic->node_addr, hw.mac_addr, ETH_ALEN);
3615*8044SWilliam.Kucharski@Sun.COM 
3616*8044SWilliam.Kucharski@Sun.COM 	printf("Ethernet addr: %!\n", nic->node_addr);
3617*8044SWilliam.Kucharski@Sun.COM 
3618*8044SWilliam.Kucharski@Sun.COM 	/* reset the hardware with the new settings */
3619*8044SWilliam.Kucharski@Sun.COM 
3620*8044SWilliam.Kucharski@Sun.COM 	ret_val = e1000_reset(&hw);
3621*8044SWilliam.Kucharski@Sun.COM 	if (ret_val < 0) {
3622*8044SWilliam.Kucharski@Sun.COM 		if ((ret_val == -E1000_ERR_NOLINK) ||
3623*8044SWilliam.Kucharski@Sun.COM 			(ret_val == -E1000_ERR_TIMEOUT)) {
3624*8044SWilliam.Kucharski@Sun.COM 			E1000_ERR("Valid Link not detected\n");
3625*8044SWilliam.Kucharski@Sun.COM 		} else {
3626*8044SWilliam.Kucharski@Sun.COM 			E1000_ERR("Hardware Initialization Failed\n");
3627*8044SWilliam.Kucharski@Sun.COM 		}
3628*8044SWilliam.Kucharski@Sun.COM 		iounmap(hw.hw_addr);
3629*8044SWilliam.Kucharski@Sun.COM 		return 0;
3630*8044SWilliam.Kucharski@Sun.COM 	}
3631*8044SWilliam.Kucharski@Sun.COM 	init_descriptor();
3632*8044SWilliam.Kucharski@Sun.COM 
3633*8044SWilliam.Kucharski@Sun.COM 	/* point to NIC specific routines */
3634*8044SWilliam.Kucharski@Sun.COM 	dev->disable  = e1000_disable;
3635*8044SWilliam.Kucharski@Sun.COM 	nic->poll     = e1000_poll;
3636*8044SWilliam.Kucharski@Sun.COM 	nic->transmit = e1000_transmit;
3637*8044SWilliam.Kucharski@Sun.COM 	nic->irq      = e1000_irq;
3638*8044SWilliam.Kucharski@Sun.COM 
3639*8044SWilliam.Kucharski@Sun.COM 	return 1;
3640*8044SWilliam.Kucharski@Sun.COM }
3641*8044SWilliam.Kucharski@Sun.COM 
3642*8044SWilliam.Kucharski@Sun.COM static struct pci_id e1000_nics[] = {
3643*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1000, "e1000-82542",               "Intel EtherExpressPro1000"),
3644*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1001, "e1000-82543gc-fiber",       "Intel EtherExpressPro1000 82543GC Fiber"),
3645*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1004, "e1000-82543gc-copper",	     "Intel EtherExpressPro1000 82543GC Copper"),
3646*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1008, "e1000-82544ei-copper",      "Intel EtherExpressPro1000 82544EI Copper"),
3647*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1009, "e1000-82544ei-fiber",       "Intel EtherExpressPro1000 82544EI Fiber"),
3648*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100C, "e1000-82544gc-copper",      "Intel EtherExpressPro1000 82544GC Copper"),
3649*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100D, "e1000-82544gc-lom",         "Intel EtherExpressPro1000 82544GC LOM"),
3650*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100E, "e1000-82540em",     	     "Intel EtherExpressPro1000 82540EM"),
3651*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100F, "e1000-82545em-copper",      "Intel EtherExpressPro1000 82545EM Copper"),
3652*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1010, "e1000-82546eb-copper",      "Intel EtherExpressPro1000 82546EB Copper"),
3653*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1011, "e1000-82545em-fiber",       "Intel EtherExpressPro1000 82545EM Fiber"),
3654*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1012, "e1000-82546eb-fiber", 	     "Intel EtherExpressPro1000 82546EB Copper"),
3655*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1013, "e1000-82541ei",	     "Intel EtherExpressPro1000 82541EI"),
3656*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1015, "e1000-82540em-lom",  	     "Intel EtherExpressPro1000 82540EM LOM"),
3657*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1016, "e1000-82540ep-lom",	     "Intel EtherExpressPro1000 82540EP LOM"),
3658*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1017, "e1000-82540ep",	     "Intel EtherExpressPro1000 82540EP"),
3659*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1018, "e1000-82541ep",	     "Intel EtherExpressPro1000 82541EP"),
3660*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1019, "e1000-82547ei",	     "Intel EtherExpressPro1000 82547EI"),
3661*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x101d, "e1000-82546eb-quad-copper", "Intel EtherExpressPro1000 82546EB Quad Copper"),
3662*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x101e, "e1000-82540ep-lp",	     "Intel EtherExpressPro1000 82540EP LP"),
3663*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1026, "e1000-82545gm-copper",	     "Intel EtherExpressPro1000 82545GM Copper"),
3664*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1027, "e1000-82545gm-fiber",	     "Intel EtherExpressPro1000 82545GM Fiber"),
3665*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1028, "e1000-82545gm-serdes",	     "Intel EtherExpressPro1000 82545GM SERDES"),
3666*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1075, "e1000-82547gi",	     "Intel EtherExpressPro1000 82547GI"),
3667*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1076, "e1000-82541gi",	     "Intel EtherExpressPro1000 82541GI"),
3668*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1077, "e1000-82541gi-mobile",	     "Intel EtherExpressPro1000 82541GI Mobile"),
3669*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1078, "e1000-82541er",	     "Intel EtherExpressPro1000 82541ER"),
3670*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1079, "e1000-82546gb-copper",	     "Intel EtherExpressPro1000 82546GB Copper"),
3671*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x107a, "e1000-82546gb-fiber",	     "Intel EtherExpressPro1000 82546GB Fiber"),
3672*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x107b, "e1000-82546gb-serdes",	     "Intel EtherExpressPro1000 82546GB SERDES"),
3673*8044SWilliam.Kucharski@Sun.COM };
3674*8044SWilliam.Kucharski@Sun.COM 
3675*8044SWilliam.Kucharski@Sun.COM struct pci_driver e1000_driver = {
3676*8044SWilliam.Kucharski@Sun.COM 	.type     = NIC_DRIVER,
3677*8044SWilliam.Kucharski@Sun.COM 	.name     = "E1000",
3678*8044SWilliam.Kucharski@Sun.COM 	.probe    = e1000_probe,
3679*8044SWilliam.Kucharski@Sun.COM 	.ids      = e1000_nics,
3680*8044SWilliam.Kucharski@Sun.COM 	.id_count = sizeof(e1000_nics)/sizeof(e1000_nics[0]),
3681*8044SWilliam.Kucharski@Sun.COM 	.class    = 0,
3682*8044SWilliam.Kucharski@Sun.COM };
3683