xref: /illumos-gate/usr/src/uts/common/io/sfe/sfe.c (revision d67944fb)
1f8919bdaSduboff /*
2f8919bdaSduboff  *  sfe.c : DP83815/DP83816/SiS900 Fast Ethernet MAC driver for Solaris
3f8919bdaSduboff  *
423d366e3Sduboff  * Copyright (c) 2002-2008 Masayuki Murayama.  All rights reserved.
5f8919bdaSduboff  *
6f8919bdaSduboff  * Redistribution and use in source and binary forms, with or without
7f8919bdaSduboff  * modification, are permitted provided that the following conditions are met:
8f8919bdaSduboff  *
9f8919bdaSduboff  * 1. Redistributions of source code must retain the above copyright notice,
10f8919bdaSduboff  *    this list of conditions and the following disclaimer.
11f8919bdaSduboff  *
12f8919bdaSduboff  * 2. Redistributions in binary form must reproduce the above copyright notice,
13f8919bdaSduboff  *    this list of conditions and the following disclaimer in the documentation
14f8919bdaSduboff  *    and/or other materials provided with the distribution.
15f8919bdaSduboff  *
16f8919bdaSduboff  * 3. Neither the name of the author nor the names of its contributors may be
17f8919bdaSduboff  *    used to endorse or promote products derived from this software without
18f8919bdaSduboff  *    specific prior written permission.
19f8919bdaSduboff  *
20f8919bdaSduboff  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21f8919bdaSduboff  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22f8919bdaSduboff  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23f8919bdaSduboff  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24f8919bdaSduboff  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25f8919bdaSduboff  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26f8919bdaSduboff  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27f8919bdaSduboff  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28f8919bdaSduboff  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29f8919bdaSduboff  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30f8919bdaSduboff  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31f8919bdaSduboff  * DAMAGE.
32f8919bdaSduboff  */
33f8919bdaSduboff 
34*d67944fbSScott Rotondo /* Avoid undefined symbol for non IA architectures */
35*d67944fbSScott Rotondo #pragma weak	inb
36*d67944fbSScott Rotondo #pragma weak	outb
37*d67944fbSScott Rotondo 
3819397407SSherry Moore /*
3953560dfaSSherry Moore  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
4019397407SSherry Moore  * Use is subject to license terms.
4119397407SSherry Moore  */
42f8919bdaSduboff 
43f8919bdaSduboff /*
44f8919bdaSduboff  * System Header files.
45f8919bdaSduboff  */
46f8919bdaSduboff #include <sys/types.h>
47f8919bdaSduboff #include <sys/conf.h>
48f8919bdaSduboff #include <sys/debug.h>
49f8919bdaSduboff #include <sys/kmem.h>
50f8919bdaSduboff #include <sys/modctl.h>
51f8919bdaSduboff #include <sys/errno.h>
52f8919bdaSduboff #include <sys/ddi.h>
53f8919bdaSduboff #include <sys/sunddi.h>
54f8919bdaSduboff #include <sys/byteorder.h>
55f8919bdaSduboff #include <sys/ethernet.h>
56f8919bdaSduboff #include <sys/pci.h>
57f8919bdaSduboff 
58f8919bdaSduboff #include "sfe_mii.h"
59f8919bdaSduboff #include "sfe_util.h"
60f8919bdaSduboff #include "sfereg.h"
61f8919bdaSduboff 
6253560dfaSSherry Moore char	ident[] = "sis900/dp83815 driver v" "2.6.1t30os";
63f8919bdaSduboff 
64f8919bdaSduboff /* Debugging support */
65f8919bdaSduboff #ifdef DEBUG_LEVEL
66f8919bdaSduboff static int sfe_debug = DEBUG_LEVEL;
67f8919bdaSduboff #if DEBUG_LEVEL > 4
68f8919bdaSduboff #define	CONS	"^"
69f8919bdaSduboff #else
70f8919bdaSduboff #define	CONS	"!"
71f8919bdaSduboff #endif
72f8919bdaSduboff #define	DPRINTF(n, args)	if (sfe_debug > (n)) cmn_err args
73f8919bdaSduboff #else
74f8919bdaSduboff #define	CONS	"!"
75f8919bdaSduboff #define	DPRINTF(n, args)
76f8919bdaSduboff #endif
77f8919bdaSduboff 
78f8919bdaSduboff /*
79f8919bdaSduboff  * Useful macros and typedefs
80f8919bdaSduboff  */
81f8919bdaSduboff #define	ONESEC		(drv_usectohz(1*1000000))
82f8919bdaSduboff #define	ROUNDUP2(x, a)	(((x) + (a) - 1) & ~((a) - 1))
83f8919bdaSduboff 
84f8919bdaSduboff /*
85f8919bdaSduboff  * Our configuration
86f8919bdaSduboff  */
87f8919bdaSduboff #define	MAXTXFRAGS	1
88f8919bdaSduboff #define	MAXRXFRAGS	1
89f8919bdaSduboff 
90f8919bdaSduboff #ifndef	TX_BUF_SIZE
91f8919bdaSduboff #define	TX_BUF_SIZE	64
92f8919bdaSduboff #endif
93f8919bdaSduboff #ifndef	TX_RING_SIZE
94f8919bdaSduboff #if MAXTXFRAGS == 1
95f8919bdaSduboff #define	TX_RING_SIZE	TX_BUF_SIZE
96f8919bdaSduboff #else
97f8919bdaSduboff #define	TX_RING_SIZE	(TX_BUF_SIZE * 4)
98f8919bdaSduboff #endif
99f8919bdaSduboff #endif
100f8919bdaSduboff 
101f8919bdaSduboff #ifndef	RX_BUF_SIZE
102f8919bdaSduboff #define	RX_BUF_SIZE	256
103f8919bdaSduboff #endif
104f8919bdaSduboff #ifndef	RX_RING_SIZE
105f8919bdaSduboff #define	RX_RING_SIZE	RX_BUF_SIZE
106f8919bdaSduboff #endif
107f8919bdaSduboff 
108f8919bdaSduboff #define	OUR_INTR_BITS	\
109f8919bdaSduboff 	(ISR_DPERR | ISR_SSERR | ISR_RMABT | ISR_RTABT | ISR_RXSOVR |	\
110f8919bdaSduboff 	ISR_TXURN | ISR_TXDESC | ISR_TXERR |	\
111f8919bdaSduboff 	ISR_RXORN | ISR_RXIDLE | ISR_RXOK | ISR_RXERR)
112f8919bdaSduboff 
113f8919bdaSduboff #define	USE_MULTICAST_HASHTBL
114f8919bdaSduboff 
115f8919bdaSduboff static int	sfe_tx_copy_thresh = 256;
116f8919bdaSduboff static int	sfe_rx_copy_thresh = 256;
117f8919bdaSduboff 
118f8919bdaSduboff /* special PHY registers for SIS900 */
119f8919bdaSduboff #define	MII_CONFIG1	0x0010
120f8919bdaSduboff #define	MII_CONFIG2	0x0011
121f8919bdaSduboff #define	MII_MASK	0x0013
122f8919bdaSduboff #define	MII_RESV	0x0014
123f8919bdaSduboff 
124f8919bdaSduboff #define	PHY_MASK		0xfffffff0
125f8919bdaSduboff #define	PHY_SIS900_INTERNAL	0x001d8000
126f8919bdaSduboff #define	PHY_ICS1893		0x0015f440
127f8919bdaSduboff 
128f8919bdaSduboff 
129f8919bdaSduboff #define	SFE_DESC_SIZE	16	/* including pads rounding up to power of 2 */
130f8919bdaSduboff 
131f8919bdaSduboff /*
132f8919bdaSduboff  * Supported chips
133f8919bdaSduboff  */
134f8919bdaSduboff struct chip_info {
135f8919bdaSduboff 	uint16_t	venid;
136f8919bdaSduboff 	uint16_t	devid;
137f8919bdaSduboff 	char		*chip_name;
138f8919bdaSduboff 	int		chip_type;
139f8919bdaSduboff #define	CHIPTYPE_DP83815	0
140f8919bdaSduboff #define	CHIPTYPE_SIS900		1
141f8919bdaSduboff };
142f8919bdaSduboff 
143f8919bdaSduboff /*
144f8919bdaSduboff  * Chip dependent MAC state
145f8919bdaSduboff  */
146f8919bdaSduboff struct sfe_dev {
147f8919bdaSduboff 	/* misc HW information */
148f8919bdaSduboff 	struct chip_info	*chip;
149f8919bdaSduboff 	uint32_t		our_intr_bits;
15023d366e3Sduboff 	uint32_t		isr_pended;
151f8919bdaSduboff 	uint32_t		cr;
152f8919bdaSduboff 	uint_t			tx_drain_threshold;
153f8919bdaSduboff 	uint_t			tx_fill_threshold;
154f8919bdaSduboff 	uint_t			rx_drain_threshold;
155f8919bdaSduboff 	uint_t			rx_fill_threshold;
156f8919bdaSduboff 	uint8_t			revid;	/* revision from PCI configuration */
157f8919bdaSduboff 	boolean_t		(*get_mac_addr)(struct gem_dev *);
158f8919bdaSduboff 	uint8_t			mac_addr[ETHERADDRL];
159f8919bdaSduboff 	uint8_t			bridge_revid;
160f8919bdaSduboff };
161f8919bdaSduboff 
162f8919bdaSduboff /*
163f8919bdaSduboff  * Hardware information
164f8919bdaSduboff  */
165f8919bdaSduboff struct chip_info sfe_chiptbl[] = {
166f8919bdaSduboff 	{ 0x1039, 0x0900, "SiS900", CHIPTYPE_SIS900, },
167f8919bdaSduboff 	{ 0x100b, 0x0020, "DP83815/83816", CHIPTYPE_DP83815, },
168f8919bdaSduboff 	{ 0x1039, 0x7016, "SiS7016", CHIPTYPE_SIS900, },
169f8919bdaSduboff };
170f8919bdaSduboff #define	CHIPTABLESIZE (sizeof (sfe_chiptbl)/sizeof (struct chip_info))
171f8919bdaSduboff 
172f8919bdaSduboff /* ======================================================== */
173f8919bdaSduboff 
174f8919bdaSduboff /* mii operations */
175f8919bdaSduboff static void  sfe_mii_sync_dp83815(struct gem_dev *);
176f8919bdaSduboff static void  sfe_mii_sync_sis900(struct gem_dev *);
177f8919bdaSduboff static uint16_t  sfe_mii_read_dp83815(struct gem_dev *, uint_t);
178f8919bdaSduboff static uint16_t  sfe_mii_read_sis900(struct gem_dev *, uint_t);
179f8919bdaSduboff static void sfe_mii_write_dp83815(struct gem_dev *, uint_t, uint16_t);
180f8919bdaSduboff static void sfe_mii_write_sis900(struct gem_dev *, uint_t, uint16_t);
181f8919bdaSduboff static void sfe_set_eq_sis630(struct gem_dev *dp);
182f8919bdaSduboff /* nic operations */
183f8919bdaSduboff static int sfe_reset_chip_sis900(struct gem_dev *);
184f8919bdaSduboff static int sfe_reset_chip_dp83815(struct gem_dev *);
185f8919bdaSduboff static int sfe_init_chip(struct gem_dev *);
186f8919bdaSduboff static int sfe_start_chip(struct gem_dev *);
187f8919bdaSduboff static int sfe_stop_chip(struct gem_dev *);
188f8919bdaSduboff static int sfe_set_media(struct gem_dev *);
189f8919bdaSduboff static int sfe_set_rx_filter_dp83815(struct gem_dev *);
190f8919bdaSduboff static int sfe_set_rx_filter_sis900(struct gem_dev *);
191f8919bdaSduboff static int sfe_get_stats(struct gem_dev *);
192f8919bdaSduboff static int sfe_attach_chip(struct gem_dev *);
193f8919bdaSduboff 
194f8919bdaSduboff /* descriptor operations */
195f8919bdaSduboff static int sfe_tx_desc_write(struct gem_dev *dp, int slot,
196f8919bdaSduboff 		    ddi_dma_cookie_t *dmacookie, int frags, uint64_t flags);
197f8919bdaSduboff static void sfe_tx_start(struct gem_dev *dp, int startslot, int nslot);
198f8919bdaSduboff static void sfe_rx_desc_write(struct gem_dev *dp, int slot,
199f8919bdaSduboff 		    ddi_dma_cookie_t *dmacookie, int frags);
200f8919bdaSduboff static uint_t sfe_tx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
201f8919bdaSduboff static uint64_t sfe_rx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
202f8919bdaSduboff 
203f8919bdaSduboff static void sfe_tx_desc_init(struct gem_dev *dp, int slot);
204f8919bdaSduboff static void sfe_rx_desc_init(struct gem_dev *dp, int slot);
205f8919bdaSduboff static void sfe_tx_desc_clean(struct gem_dev *dp, int slot);
206f8919bdaSduboff static void sfe_rx_desc_clean(struct gem_dev *dp, int slot);
207f8919bdaSduboff 
208f8919bdaSduboff /* interrupt handler */
209f8919bdaSduboff static uint_t sfe_interrupt(struct gem_dev *dp);
210f8919bdaSduboff 
211f8919bdaSduboff /* ======================================================== */
212f8919bdaSduboff 
213f8919bdaSduboff /* mapping attributes */
214f8919bdaSduboff /* Data access requirements. */
215f8919bdaSduboff static struct ddi_device_acc_attr sfe_dev_attr = {
216f8919bdaSduboff 	DDI_DEVICE_ATTR_V0,
217f8919bdaSduboff 	DDI_STRUCTURE_LE_ACC,
218f8919bdaSduboff 	DDI_STRICTORDER_ACC
219f8919bdaSduboff };
220f8919bdaSduboff 
221f8919bdaSduboff /* On sparc, Buffers should be native endian for speed */
222f8919bdaSduboff static struct ddi_device_acc_attr sfe_buf_attr = {
223f8919bdaSduboff 	DDI_DEVICE_ATTR_V0,
224f8919bdaSduboff 	DDI_NEVERSWAP_ACC,	/* native endianness */
225f8919bdaSduboff 	DDI_STRICTORDER_ACC
226f8919bdaSduboff };
227f8919bdaSduboff 
228f8919bdaSduboff static ddi_dma_attr_t sfe_dma_attr_buf = {
229f8919bdaSduboff 	DMA_ATTR_V0,		/* dma_attr_version */
230f8919bdaSduboff 	0,			/* dma_attr_addr_lo */
231f8919bdaSduboff 	0xffffffffull,		/* dma_attr_addr_hi */
232f8919bdaSduboff 	0x00000fffull,		/* dma_attr_count_max */
233f8919bdaSduboff 	0, /* patched later */	/* dma_attr_align */
234f8919bdaSduboff 	0x000003fc,		/* dma_attr_burstsizes */
235f8919bdaSduboff 	1,			/* dma_attr_minxfer */
236f8919bdaSduboff 	0x00000fffull,		/* dma_attr_maxxfer */
237f8919bdaSduboff 	0xffffffffull,		/* dma_attr_seg */
238f8919bdaSduboff 	0, /* patched later */	/* dma_attr_sgllen */
239f8919bdaSduboff 	1,			/* dma_attr_granular */
240f8919bdaSduboff 	0			/* dma_attr_flags */
241f8919bdaSduboff };
242f8919bdaSduboff 
243f8919bdaSduboff static ddi_dma_attr_t sfe_dma_attr_desc = {
244f8919bdaSduboff 	DMA_ATTR_V0,		/* dma_attr_version */
245f8919bdaSduboff 	16,			/* dma_attr_addr_lo */
246f8919bdaSduboff 	0xffffffffull,		/* dma_attr_addr_hi */
247f8919bdaSduboff 	0xffffffffull,		/* dma_attr_count_max */
248f8919bdaSduboff 	16,			/* dma_attr_align */
249f8919bdaSduboff 	0x000003fc,		/* dma_attr_burstsizes */
250f8919bdaSduboff 	1,			/* dma_attr_minxfer */
251f8919bdaSduboff 	0xffffffffull,		/* dma_attr_maxxfer */
252f8919bdaSduboff 	0xffffffffull,		/* dma_attr_seg */
253f8919bdaSduboff 	1,			/* dma_attr_sgllen */
254f8919bdaSduboff 	1,			/* dma_attr_granular */
255f8919bdaSduboff 	0			/* dma_attr_flags */
256f8919bdaSduboff };
257f8919bdaSduboff 
258f8919bdaSduboff uint32_t sfe_use_pcimemspace = 0;
259f8919bdaSduboff 
260f8919bdaSduboff /* ======================================================== */
261f8919bdaSduboff /*
262f8919bdaSduboff  * HW manipulation routines
263f8919bdaSduboff  */
264f8919bdaSduboff /* ======================================================== */
265f8919bdaSduboff 
266f8919bdaSduboff #define	SFE_EEPROM_DELAY(dp)	\
267f8919bdaSduboff 	{ (void) INL(dp, EROMAR); (void) INL(dp, EROMAR); }
268f8919bdaSduboff #define	EE_CMD_READ	6
269f8919bdaSduboff #define	EE_CMD_SHIFT	6
270f8919bdaSduboff 
271f8919bdaSduboff static uint16_t
sfe_read_eeprom(struct gem_dev * dp,uint_t offset)272f8919bdaSduboff sfe_read_eeprom(struct gem_dev *dp, uint_t offset)
273f8919bdaSduboff {
274f8919bdaSduboff 	int		eedi;
275f8919bdaSduboff 	int		i;
276f8919bdaSduboff 	uint16_t	ret;
277f8919bdaSduboff 
278f8919bdaSduboff 	/* ensure de-assert chip select */
279f8919bdaSduboff 	OUTL(dp, EROMAR, 0);
280f8919bdaSduboff 	SFE_EEPROM_DELAY(dp);
281f8919bdaSduboff 	OUTL(dp, EROMAR, EROMAR_EESK);
282f8919bdaSduboff 	SFE_EEPROM_DELAY(dp);
283f8919bdaSduboff 
284f8919bdaSduboff 	/* assert chip select */
285f8919bdaSduboff 	offset |= EE_CMD_READ << EE_CMD_SHIFT;
286f8919bdaSduboff 
287f8919bdaSduboff 	for (i = 8; i >= 0; i--) {
288f8919bdaSduboff 		/* make command */
289f8919bdaSduboff 		eedi = ((offset >> i) & 1) << EROMAR_EEDI_SHIFT;
290f8919bdaSduboff 
291f8919bdaSduboff 		/* send 1 bit */
292f8919bdaSduboff 		OUTL(dp, EROMAR, EROMAR_EECS | eedi);
293f8919bdaSduboff 		SFE_EEPROM_DELAY(dp);
294f8919bdaSduboff 		OUTL(dp, EROMAR, EROMAR_EECS | eedi | EROMAR_EESK);
295f8919bdaSduboff 		SFE_EEPROM_DELAY(dp);
296f8919bdaSduboff 	}
297f8919bdaSduboff 
298f8919bdaSduboff 	OUTL(dp, EROMAR, EROMAR_EECS);
299f8919bdaSduboff 
300f8919bdaSduboff 	ret = 0;
301f8919bdaSduboff 	for (i = 0; i < 16; i++) {
302f8919bdaSduboff 		/* Get 1 bit */
303f8919bdaSduboff 		OUTL(dp, EROMAR, EROMAR_EECS);
304f8919bdaSduboff 		SFE_EEPROM_DELAY(dp);
305f8919bdaSduboff 		OUTL(dp, EROMAR, EROMAR_EECS | EROMAR_EESK);
306f8919bdaSduboff 		SFE_EEPROM_DELAY(dp);
307f8919bdaSduboff 
308f8919bdaSduboff 		ret = (ret << 1) | ((INL(dp, EROMAR) >> EROMAR_EEDO_SHIFT) & 1);
309f8919bdaSduboff 	}
310f8919bdaSduboff 
311f8919bdaSduboff 	OUTL(dp, EROMAR, 0);
312f8919bdaSduboff 	SFE_EEPROM_DELAY(dp);
313f8919bdaSduboff 
314f8919bdaSduboff 	return (ret);
315f8919bdaSduboff }
316f8919bdaSduboff #undef SFE_EEPROM_DELAY
317f8919bdaSduboff 
318f8919bdaSduboff static boolean_t
sfe_get_mac_addr_dp83815(struct gem_dev * dp)319f8919bdaSduboff sfe_get_mac_addr_dp83815(struct gem_dev *dp)
320f8919bdaSduboff {
321f8919bdaSduboff 	uint8_t		*mac;
322f8919bdaSduboff 	uint_t		val;
323f8919bdaSduboff 	int		i;
324f8919bdaSduboff 
325f8919bdaSduboff #define	BITSET(p, ix, v)	(p)[(ix)/8] |= ((v) ? 1 : 0) << ((ix) & 0x7)
326f8919bdaSduboff 
327f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
328f8919bdaSduboff 
329f8919bdaSduboff 	mac = dp->dev_addr.ether_addr_octet;
330f8919bdaSduboff 
331f8919bdaSduboff 	/* first of all, clear MAC address buffer */
332f8919bdaSduboff 	bzero(mac, ETHERADDRL);
333f8919bdaSduboff 
334f8919bdaSduboff 	/* get bit 0 */
335f8919bdaSduboff 	val = sfe_read_eeprom(dp, 0x6);
336f8919bdaSduboff 	BITSET(mac, 0, val & 1);
337f8919bdaSduboff 
338f8919bdaSduboff 	/* get bit 1 - 16 */
339f8919bdaSduboff 	val = sfe_read_eeprom(dp, 0x7);
340f8919bdaSduboff 	for (i = 0; i < 16; i++) {
341f8919bdaSduboff 		BITSET(mac, 1 + i, val & (1 << (15 - i)));
342f8919bdaSduboff 	}
343f8919bdaSduboff 
344f8919bdaSduboff 	/* get bit 17 -  32 */
345f8919bdaSduboff 	val = sfe_read_eeprom(dp, 0x8);
346f8919bdaSduboff 	for (i = 0; i < 16; i++) {
347f8919bdaSduboff 		BITSET(mac, 17 + i, val & (1 << (15 - i)));
348f8919bdaSduboff 	}
349f8919bdaSduboff 
350f8919bdaSduboff 	/* get bit 33 -  47 */
351f8919bdaSduboff 	val = sfe_read_eeprom(dp, 0x9);
352f8919bdaSduboff 	for (i = 0; i < 15; i++) {
353f8919bdaSduboff 		BITSET(mac, 33 + i, val & (1 << (15 - i)));
354f8919bdaSduboff 	}
355f8919bdaSduboff 
356f8919bdaSduboff 	return (B_TRUE);
357f8919bdaSduboff #undef BITSET
358f8919bdaSduboff }
359f8919bdaSduboff 
360f8919bdaSduboff static boolean_t
sfe_get_mac_addr_sis900(struct gem_dev * dp)361f8919bdaSduboff sfe_get_mac_addr_sis900(struct gem_dev *dp)
362f8919bdaSduboff {
363f8919bdaSduboff 	uint_t		val;
364f8919bdaSduboff 	int		i;
365f8919bdaSduboff 	uint8_t		*mac;
366f8919bdaSduboff 
367f8919bdaSduboff 	mac = dp->dev_addr.ether_addr_octet;
368f8919bdaSduboff 
369f8919bdaSduboff 	for (i = 0; i < ETHERADDRL/2; i++) {
370f8919bdaSduboff 		val = sfe_read_eeprom(dp, 0x8 + i);
371f8919bdaSduboff 		*mac++ = (uint8_t)val;
372f8919bdaSduboff 		*mac++ = (uint8_t)(val >> 8);
373f8919bdaSduboff 	}
374f8919bdaSduboff 
375f8919bdaSduboff 	return (B_TRUE);
376f8919bdaSduboff }
377f8919bdaSduboff 
378f8919bdaSduboff static dev_info_t *
sfe_search_pci_dev_subr(dev_info_t * cur_node,int vendor_id,int device_id)379f8919bdaSduboff sfe_search_pci_dev_subr(dev_info_t *cur_node, int vendor_id, int device_id)
380f8919bdaSduboff {
381f8919bdaSduboff 	dev_info_t	*child_id;
382f8919bdaSduboff 	dev_info_t	*ret;
383f8919bdaSduboff 	int		vid, did;
384f8919bdaSduboff 
385f8919bdaSduboff 	if (cur_node == NULL) {
386f8919bdaSduboff 		return (NULL);
387f8919bdaSduboff 	}
388f8919bdaSduboff 
389f8919bdaSduboff 	/* check brothers */
390f8919bdaSduboff 	do {
391f8919bdaSduboff 		vid = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
392f8919bdaSduboff 		    DDI_PROP_DONTPASS, "vendor-id", -1);
393f8919bdaSduboff 		did = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
394f8919bdaSduboff 		    DDI_PROP_DONTPASS, "device-id", -1);
395f8919bdaSduboff 
396f8919bdaSduboff 		if (vid == vendor_id && did == device_id) {
397f8919bdaSduboff 			/* found */
398f8919bdaSduboff 			return (cur_node);
399f8919bdaSduboff 		}
400f8919bdaSduboff 
401f8919bdaSduboff 		/* check children */
402f8919bdaSduboff 		if ((child_id = ddi_get_child(cur_node)) != NULL) {
403f8919bdaSduboff 			if ((ret = sfe_search_pci_dev_subr(child_id,
404f8919bdaSduboff 			    vendor_id, device_id)) != NULL) {
405f8919bdaSduboff 				return (ret);
406f8919bdaSduboff 			}
407f8919bdaSduboff 		}
408f8919bdaSduboff 
409f8919bdaSduboff 	} while ((cur_node = ddi_get_next_sibling(cur_node)) != NULL);
410f8919bdaSduboff 
411f8919bdaSduboff 	/* not found */
412f8919bdaSduboff 	return (NULL);
413f8919bdaSduboff }
414f8919bdaSduboff 
415f8919bdaSduboff static dev_info_t *
sfe_search_pci_dev(int vendor_id,int device_id)416f8919bdaSduboff sfe_search_pci_dev(int vendor_id, int device_id)
417f8919bdaSduboff {
418f8919bdaSduboff 	return (sfe_search_pci_dev_subr(ddi_root_node(), vendor_id, device_id));
419f8919bdaSduboff }
420f8919bdaSduboff 
421f8919bdaSduboff static boolean_t
sfe_get_mac_addr_sis630e(struct gem_dev * dp)422f8919bdaSduboff sfe_get_mac_addr_sis630e(struct gem_dev *dp)
423f8919bdaSduboff {
424f8919bdaSduboff 	int		i;
425f8919bdaSduboff 	dev_info_t	*isa_bridge;
426f8919bdaSduboff 	ddi_acc_handle_t isa_handle;
427f8919bdaSduboff 	int		reg;
428f8919bdaSduboff 
429f8919bdaSduboff 	if (inb == NULL || outb == NULL) {
430f8919bdaSduboff 		/* this is not IA architecture */
431f8919bdaSduboff 		return (B_FALSE);
432f8919bdaSduboff 	}
433f8919bdaSduboff 
434f8919bdaSduboff 	if ((isa_bridge = sfe_search_pci_dev(0x1039, 0x8)) == NULL) {
435f8919bdaSduboff 		cmn_err(CE_WARN, "%s: failed to find isa-bridge pci1039,8",
436f8919bdaSduboff 		    dp->name);
437f8919bdaSduboff 		return (B_FALSE);
438f8919bdaSduboff 	}
439f8919bdaSduboff 
440f8919bdaSduboff 	if (pci_config_setup(isa_bridge, &isa_handle) != DDI_SUCCESS) {
441f8919bdaSduboff 		cmn_err(CE_WARN, "%s: ddi_regs_map_setup failed",
442f8919bdaSduboff 		    dp->name);
443f8919bdaSduboff 		return (B_FALSE);
444f8919bdaSduboff 	}
445f8919bdaSduboff 
446f8919bdaSduboff 	/* enable to access CMOS RAM */
447f8919bdaSduboff 	reg = pci_config_get8(isa_handle, 0x48);
448f8919bdaSduboff 	pci_config_put8(isa_handle, 0x48, reg | 0x40);
449f8919bdaSduboff 
450f8919bdaSduboff 	for (i = 0; i < ETHERADDRL; i++) {
451f8919bdaSduboff 		outb(0x70, 0x09 + i);
452f8919bdaSduboff 		dp->dev_addr.ether_addr_octet[i] = inb(0x71);
453f8919bdaSduboff 	}
454f8919bdaSduboff 
455f8919bdaSduboff 	/* disable to access CMOS RAM */
456f8919bdaSduboff 	pci_config_put8(isa_handle, 0x48, reg);
457f8919bdaSduboff 	pci_config_teardown(&isa_handle);
458f8919bdaSduboff 
459f8919bdaSduboff 	return (B_TRUE);
460f8919bdaSduboff }
461f8919bdaSduboff 
462f8919bdaSduboff static boolean_t
sfe_get_mac_addr_sis635(struct gem_dev * dp)463f8919bdaSduboff sfe_get_mac_addr_sis635(struct gem_dev *dp)
464f8919bdaSduboff {
465f8919bdaSduboff 	int		i;
466f8919bdaSduboff 	uint32_t	rfcr;
467f8919bdaSduboff 	uint16_t	v;
468f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
469f8919bdaSduboff 
470f8919bdaSduboff 	DPRINTF(2, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
471f8919bdaSduboff 	rfcr = INL(dp, RFCR);
472f8919bdaSduboff 
473f8919bdaSduboff 	OUTL(dp, CR, lp->cr | CR_RELOAD);
474f8919bdaSduboff 	OUTL(dp, CR, lp->cr);
475f8919bdaSduboff 
476f8919bdaSduboff 	/* disable packet filtering before reading filter */
477f8919bdaSduboff 	OUTL(dp, RFCR, rfcr & ~RFCR_RFEN);
478f8919bdaSduboff 
479f8919bdaSduboff 	/* load MAC addr from filter data register */
480f8919bdaSduboff 	for (i = 0; i < ETHERADDRL; i += 2) {
481f8919bdaSduboff 		OUTL(dp, RFCR,
482f8919bdaSduboff 		    (RFADDR_MAC_SIS900 + (i/2)) << RFCR_RFADDR_SHIFT_SIS900);
483f8919bdaSduboff 		v = INL(dp, RFDR);
484f8919bdaSduboff 		dp->dev_addr.ether_addr_octet[i] = (uint8_t)v;
485f8919bdaSduboff 		dp->dev_addr.ether_addr_octet[i+1] = (uint8_t)(v >> 8);
486f8919bdaSduboff 	}
487f8919bdaSduboff 
488f8919bdaSduboff 	/* re-enable packet filtering */
489f8919bdaSduboff 	OUTL(dp, RFCR, rfcr | RFCR_RFEN);
490f8919bdaSduboff 
491f8919bdaSduboff 	return (B_TRUE);
492f8919bdaSduboff }
493f8919bdaSduboff 
494f8919bdaSduboff static boolean_t
sfe_get_mac_addr_sis962(struct gem_dev * dp)495f8919bdaSduboff sfe_get_mac_addr_sis962(struct gem_dev *dp)
496f8919bdaSduboff {
497f8919bdaSduboff 	boolean_t	ret;
498f8919bdaSduboff 	int		i;
499f8919bdaSduboff 
500f8919bdaSduboff 	ret = B_FALSE;
501f8919bdaSduboff 
502f8919bdaSduboff 	/* rise request signal to access EEPROM */
503f8919bdaSduboff 	OUTL(dp, MEAR, EROMAR_EEREQ);
504f8919bdaSduboff 	for (i = 0; (INL(dp, MEAR) & EROMAR_EEGNT) == 0; i++) {
505f8919bdaSduboff 		if (i > 200) {
506f8919bdaSduboff 			/* failed to acquire eeprom */
507f8919bdaSduboff 			cmn_err(CE_NOTE,
508f8919bdaSduboff 			    CONS "%s: failed to access eeprom", dp->name);
509f8919bdaSduboff 			goto x;
510f8919bdaSduboff 		}
511f8919bdaSduboff 		drv_usecwait(10);
512f8919bdaSduboff 	}
513f8919bdaSduboff 	ret = sfe_get_mac_addr_sis900(dp);
514f8919bdaSduboff x:
515f8919bdaSduboff 	/* release EEPROM */
516f8919bdaSduboff 	OUTL(dp, MEAR, EROMAR_EEDONE);
517f8919bdaSduboff 
518f8919bdaSduboff 	return (ret);
519f8919bdaSduboff }
520f8919bdaSduboff 
521f8919bdaSduboff static int
sfe_reset_chip_sis900(struct gem_dev * dp)522f8919bdaSduboff sfe_reset_chip_sis900(struct gem_dev *dp)
523f8919bdaSduboff {
524f8919bdaSduboff 	int		i;
525f8919bdaSduboff 	uint32_t	done;
526f8919bdaSduboff 	uint32_t	val;
527f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
528f8919bdaSduboff 
529f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
530f8919bdaSduboff 
531f8919bdaSduboff 	/* invalidate mac addr cache */
532f8919bdaSduboff 	bzero(lp->mac_addr, sizeof (lp->mac_addr));
533f8919bdaSduboff 
534f8919bdaSduboff 	lp->cr = 0;
535f8919bdaSduboff 
536f8919bdaSduboff 	/* inhibit interrupt */
537f8919bdaSduboff 	OUTL(dp, IMR, 0);
53823d366e3Sduboff 	lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
539f8919bdaSduboff 
540915ebf8dSAlan Duboff 	OUTLINL(dp, RFCR, 0);
541f8919bdaSduboff 
542f8919bdaSduboff 	OUTL(dp, CR, CR_RST | CR_TXR | CR_RXR);
543f8919bdaSduboff 	drv_usecwait(10);
544f8919bdaSduboff 
545f8919bdaSduboff 	done = 0;
546f8919bdaSduboff 	for (i = 0; done != (ISR_TXRCMP | ISR_RXRCMP); i++) {
547f8919bdaSduboff 		if (i > 1000) {
548f8919bdaSduboff 			cmn_err(CE_WARN, "%s: chip reset timeout", dp->name);
549f8919bdaSduboff 			return (GEM_FAILURE);
550f8919bdaSduboff 		}
551f8919bdaSduboff 		done |= INL(dp, ISR) & (ISR_TXRCMP | ISR_RXRCMP);
552f8919bdaSduboff 		drv_usecwait(10);
553f8919bdaSduboff 	}
554f8919bdaSduboff 
555f8919bdaSduboff 	if (lp->revid == SIS630ET_900_REV) {
556f8919bdaSduboff 		lp->cr |= CR_ACCESSMODE;
557f8919bdaSduboff 		OUTL(dp, CR, lp->cr | INL(dp, CR));
558f8919bdaSduboff 	}
559f8919bdaSduboff 
560f8919bdaSduboff 	/* Configuration register: enable PCI parity */
561f8919bdaSduboff 	DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
562f8919bdaSduboff 	    dp->name, INL(dp, CFG), CFG_BITS_SIS900));
56323d366e3Sduboff 	val = 0;
564f8919bdaSduboff 	if (lp->revid >= SIS635A_900_REV ||
565f8919bdaSduboff 	    lp->revid == SIS900B_900_REV) {
566f8919bdaSduboff 		/* what is this ? */
567f8919bdaSduboff 		val |= CFG_RND_CNT;
568f8919bdaSduboff 	}
569f8919bdaSduboff 	OUTL(dp, CFG, val);
570f8919bdaSduboff 	DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
571f8919bdaSduboff 	    INL(dp, CFG), CFG_BITS_SIS900));
572f8919bdaSduboff 
573f8919bdaSduboff 	return (GEM_SUCCESS);
574f8919bdaSduboff }
575f8919bdaSduboff 
576f8919bdaSduboff static int
sfe_reset_chip_dp83815(struct gem_dev * dp)577f8919bdaSduboff sfe_reset_chip_dp83815(struct gem_dev *dp)
578f8919bdaSduboff {
579f8919bdaSduboff 	int		i;
58023d366e3Sduboff 	uint32_t	val;
581f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
582f8919bdaSduboff 
583f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
584f8919bdaSduboff 
585f8919bdaSduboff 	/* invalidate mac addr cache */
586f8919bdaSduboff 	bzero(lp->mac_addr, sizeof (lp->mac_addr));
587f8919bdaSduboff 
588f8919bdaSduboff 	lp->cr = 0;
589f8919bdaSduboff 
590f8919bdaSduboff 	/* inhibit interrupts */
591f8919bdaSduboff 	OUTL(dp, IMR, 0);
59223d366e3Sduboff 	lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
593f8919bdaSduboff 
594f8919bdaSduboff 	OUTL(dp, RFCR, 0);
595f8919bdaSduboff 
596f8919bdaSduboff 	OUTL(dp, CR, CR_RST);
597f8919bdaSduboff 	drv_usecwait(10);
598f8919bdaSduboff 
599f8919bdaSduboff 	for (i = 0; INL(dp, CR) & CR_RST; i++) {
600f8919bdaSduboff 		if (i > 100) {
601f8919bdaSduboff 			cmn_err(CE_WARN, "!%s: chip reset timeout", dp->name);
602f8919bdaSduboff 			return (GEM_FAILURE);
603f8919bdaSduboff 		}
604f8919bdaSduboff 		drv_usecwait(10);
605f8919bdaSduboff 	}
606f8919bdaSduboff 	DPRINTF(0, (CE_CONT, "!%s: chip reset in %duS", dp->name, i*10));
607f8919bdaSduboff 
608f8919bdaSduboff 	OUTL(dp, CCSR, CCSR_PMESTS);
609f8919bdaSduboff 	OUTL(dp, CCSR, 0);
610f8919bdaSduboff 
611f8919bdaSduboff 	/* Configuration register: enable PCI parity */
612f8919bdaSduboff 	DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
613f8919bdaSduboff 	    dp->name, INL(dp, CFG), CFG_BITS_DP83815));
61423d366e3Sduboff 	val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
61523d366e3Sduboff 	OUTL(dp, CFG, val | CFG_PAUSE_ADV);
616f8919bdaSduboff 	DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
617f8919bdaSduboff 	    INL(dp, CFG), CFG_BITS_DP83815));
618f8919bdaSduboff 
619f8919bdaSduboff 	return (GEM_SUCCESS);
620f8919bdaSduboff }
621f8919bdaSduboff 
622f8919bdaSduboff static int
sfe_init_chip(struct gem_dev * dp)623f8919bdaSduboff sfe_init_chip(struct gem_dev *dp)
624f8919bdaSduboff {
625f8919bdaSduboff 	/* Configuration register: have been set up in sfe_chip_reset */
626f8919bdaSduboff 
627f8919bdaSduboff 	/* PCI test control register: do nothing */
628f8919bdaSduboff 
629f8919bdaSduboff 	/* Interrupt status register : do nothing */
630f8919bdaSduboff 
631f8919bdaSduboff 	/* Interrupt mask register: clear, but leave lp->our_intr_bits */
632f8919bdaSduboff 	OUTL(dp, IMR, 0);
633f8919bdaSduboff 
634f8919bdaSduboff 	/* Enhanced PHY Access register (sis900): do nothing */
635f8919bdaSduboff 
636f8919bdaSduboff 	/* Transmit Descriptor Pointer register: base addr of TX ring */
637f8919bdaSduboff 	OUTL(dp, TXDP, dp->tx_ring_dma);
638f8919bdaSduboff 
639f8919bdaSduboff 	/* Receive descriptor pointer register: base addr of RX ring */
640f8919bdaSduboff 	OUTL(dp, RXDP, dp->rx_ring_dma);
641f8919bdaSduboff 
642f8919bdaSduboff 	return (GEM_SUCCESS);
643f8919bdaSduboff }
644f8919bdaSduboff 
645f8919bdaSduboff static uint_t
sfe_mcast_hash(struct gem_dev * dp,uint8_t * addr)646f8919bdaSduboff sfe_mcast_hash(struct gem_dev *dp, uint8_t *addr)
647f8919bdaSduboff {
648f8919bdaSduboff 	return (gem_ether_crc_be(addr, ETHERADDRL));
649f8919bdaSduboff }
650f8919bdaSduboff 
651f8919bdaSduboff #ifdef DEBUG_LEVEL
652f8919bdaSduboff static void
sfe_rxfilter_dump(struct gem_dev * dp,int start,int end)653f8919bdaSduboff sfe_rxfilter_dump(struct gem_dev *dp, int start, int end)
654f8919bdaSduboff {
655f8919bdaSduboff 	int		i;
656f8919bdaSduboff 	int		j;
657f8919bdaSduboff 	uint16_t	ram[0x10];
658f8919bdaSduboff 
659f8919bdaSduboff 	cmn_err(CE_CONT, "!%s: rx filter ram dump:", dp->name);
660f8919bdaSduboff #define	WORDS_PER_LINE	4
661f8919bdaSduboff 	for (i = start; i < end; i += WORDS_PER_LINE*2) {
662f8919bdaSduboff 		for (j = 0; j < WORDS_PER_LINE; j++) {
663f8919bdaSduboff 			OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i + j*2);
664f8919bdaSduboff 			ram[j] = INL(dp, RFDR);
665f8919bdaSduboff 		}
666f8919bdaSduboff 
667f8919bdaSduboff 		cmn_err(CE_CONT, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
668f8919bdaSduboff 		    i, ram[0], ram[1], ram[2], ram[3]);
669f8919bdaSduboff 		}
670f8919bdaSduboff 
671f8919bdaSduboff #undef	WORDS_PER_LINE
672f8919bdaSduboff }
673f8919bdaSduboff #endif
674f8919bdaSduboff 
675f8919bdaSduboff static uint_t	sfe_rf_perfect_base_dp83815[] = {
676f8919bdaSduboff 	RFADDR_PMATCH0_DP83815,
677f8919bdaSduboff 	RFADDR_PMATCH1_DP83815,
678f8919bdaSduboff 	RFADDR_PMATCH2_DP83815,
679f8919bdaSduboff 	RFADDR_PMATCH3_DP83815,
680f8919bdaSduboff };
681f8919bdaSduboff 
682f8919bdaSduboff static int
sfe_set_rx_filter_dp83815(struct gem_dev * dp)683f8919bdaSduboff sfe_set_rx_filter_dp83815(struct gem_dev *dp)
684f8919bdaSduboff {
685f8919bdaSduboff 	int		i;
686f8919bdaSduboff 	int		j;
687f8919bdaSduboff 	uint32_t	mode;
688f8919bdaSduboff 	uint8_t		*mac = dp->cur_addr.ether_addr_octet;
689f8919bdaSduboff 	uint16_t	hash_tbl[32];
690f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
691f8919bdaSduboff 
692f8919bdaSduboff 	DPRINTF(1, (CE_CONT, CONS "%s: %s: called, mc_count:%d, mode:0x%b",
693f8919bdaSduboff 	    dp->name, __func__, dp->mc_count, dp->rxmode, RXMODE_BITS));
694f8919bdaSduboff 
695f8919bdaSduboff #if DEBUG_LEVEL > 0
696f8919bdaSduboff 	for (i = 0; i < dp->mc_count; i++) {
697f8919bdaSduboff 		cmn_err(CE_CONT,
698f8919bdaSduboff 		"!%s: adding mcast(%d) %02x:%02x:%02x:%02x:%02x:%02x",
699f8919bdaSduboff 		    dp->name, i,
700f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[0],
701f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[1],
702f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[2],
703f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[3],
704f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[4],
705f8919bdaSduboff 		    dp->mc_list[i].addr.ether_addr_octet[5]);
706f8919bdaSduboff 	}
707f8919bdaSduboff #endif
708f8919bdaSduboff 	if ((dp->rxmode & RXMODE_ENABLE) == 0) {
709f8919bdaSduboff 		/* disable rx filter */
710f8919bdaSduboff 		OUTL(dp, RFCR, 0);
711f8919bdaSduboff 		return (GEM_SUCCESS);
712f8919bdaSduboff 	}
713f8919bdaSduboff 
714f8919bdaSduboff 	/*
715f8919bdaSduboff 	 * Set Receive filter control register
716f8919bdaSduboff 	 */
717f8919bdaSduboff 	if (dp->rxmode & RXMODE_PROMISC) {
718f8919bdaSduboff 		/* all broadcast, all multicast, all physical */
719f8919bdaSduboff 		mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
720f8919bdaSduboff 	} else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 16*32/2) {
721f8919bdaSduboff 		/* all broadcast, all multicast, physical for the chip */
722f8919bdaSduboff 		mode = RFCR_AAB | RFCR_AAM | RFCR_APM_DP83815;
723f8919bdaSduboff 	} else if (dp->mc_count > 4) {
724f8919bdaSduboff 		/*
725f8919bdaSduboff 		 * Use multicast hash table,
726f8919bdaSduboff 		 * accept all broadcast and physical for the chip.
727f8919bdaSduboff 		 */
728f8919bdaSduboff 		mode = RFCR_AAB | RFCR_MHEN_DP83815 | RFCR_APM_DP83815;
729f8919bdaSduboff 
730f8919bdaSduboff 		bzero(hash_tbl, sizeof (hash_tbl));
731f8919bdaSduboff 		for (i = 0; i < dp->mc_count; i++) {
732f8919bdaSduboff 			j = dp->mc_list[i].hash >> (32 - 9);
733f8919bdaSduboff 			hash_tbl[j / 16] |= 1 << (j % 16);
734f8919bdaSduboff 		}
735f8919bdaSduboff 	} else {
736f8919bdaSduboff 		/*
737f8919bdaSduboff 		 * Use pattern mach filter for multicast address,
738f8919bdaSduboff 		 * accept all broadcast and physical for the chip
739f8919bdaSduboff 		 */
740f8919bdaSduboff 		/* need to enable corresponding pattern registers */
741f8919bdaSduboff 		mode = RFCR_AAB | RFCR_APM_DP83815 |
742f8919bdaSduboff 		    (((1 << dp->mc_count) - 1) << RFCR_APAT_SHIFT);
743f8919bdaSduboff 	}
744f8919bdaSduboff 
745f8919bdaSduboff #if DEBUG_LEVEL > 1
746f8919bdaSduboff 	cmn_err(CE_CONT,
747f8919bdaSduboff 	    "!%s: mac %02x:%02x:%02x:%02x:%02x:%02x"
748f8919bdaSduboff 	    "  cache %02x:%02x:%02x:%02x:%02x:%02x",
749f8919bdaSduboff 	    dp->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
750f8919bdaSduboff 	    lp->mac_addr[0], lp->mac_addr[1],
751f8919bdaSduboff 	    lp->mac_addr[2], lp->mac_addr[3],
752f8919bdaSduboff 	    lp->mac_addr[4], lp->mac_addr[5]);
753f8919bdaSduboff #endif
754f8919bdaSduboff 	if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
755f8919bdaSduboff 		/*
756f8919bdaSduboff 		 * XXX - need to *disable* rx filter to load mac address for
757f8919bdaSduboff 		 * the chip. otherwise, we cannot setup rxfilter correctly.
758f8919bdaSduboff 		 */
759f8919bdaSduboff 		/* setup perfect match register for my station address */
760f8919bdaSduboff 		for (i = 0; i < ETHERADDRL; i += 2) {
761f8919bdaSduboff 			OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i);
762f8919bdaSduboff 			OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
763f8919bdaSduboff 		}
764f8919bdaSduboff 
765f8919bdaSduboff 		bcopy(mac, lp->mac_addr, ETHERADDRL);
766f8919bdaSduboff 	}
767f8919bdaSduboff 
768f8919bdaSduboff #if DEBUG_LEVEL > 3
769f8919bdaSduboff 	/* clear pattern ram */
770f8919bdaSduboff 	for (j = 0x200; j < 0x380; j += 2) {
771f8919bdaSduboff 		OUTL(dp, RFCR, j);
772f8919bdaSduboff 		OUTL(dp, RFDR, 0);
773f8919bdaSduboff 	}
774f8919bdaSduboff #endif
775f8919bdaSduboff 	if (mode & RFCR_APAT_DP83815) {
776f8919bdaSduboff 		/* setup multicast address into pattern match registers */
777f8919bdaSduboff 		for (j = 0; j < dp->mc_count; j++) {
778f8919bdaSduboff 			mac = &dp->mc_list[j].addr.ether_addr_octet[0];
779f8919bdaSduboff 			for (i = 0; i < ETHERADDRL; i += 2) {
780f8919bdaSduboff 				OUTL(dp, RFCR,
781f8919bdaSduboff 				    sfe_rf_perfect_base_dp83815[j] + i*2);
782f8919bdaSduboff 				OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
783f8919bdaSduboff 			}
784f8919bdaSduboff 		}
785f8919bdaSduboff 
786f8919bdaSduboff 		/* setup pattern count registers */
787f8919bdaSduboff 		OUTL(dp, RFCR, RFADDR_PCOUNT01_DP83815);
788f8919bdaSduboff 		OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
789f8919bdaSduboff 		OUTL(dp, RFCR, RFADDR_PCOUNT23_DP83815);
790f8919bdaSduboff 		OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
791f8919bdaSduboff 	}
792f8919bdaSduboff 
793f8919bdaSduboff 	if (mode & RFCR_MHEN_DP83815) {
794f8919bdaSduboff 		/* Load Multicast hash table */
795f8919bdaSduboff 		for (i = 0; i < 32; i++) {
796f8919bdaSduboff 			/* for DP83815, index is in byte */
797f8919bdaSduboff 			OUTL(dp, RFCR, RFADDR_MULTICAST_DP83815 + i*2);
798f8919bdaSduboff 			OUTL(dp, RFDR, hash_tbl[i]);
799f8919bdaSduboff 		}
800f8919bdaSduboff 	}
801f8919bdaSduboff #if DEBUG_LEVEL > 2
802f8919bdaSduboff 	sfe_rxfilter_dump(dp, 0, 0x10);
803f8919bdaSduboff 	sfe_rxfilter_dump(dp, 0x200, 0x380);
804f8919bdaSduboff #endif
805f8919bdaSduboff 	/* Set rx filter mode and enable rx filter */
806f8919bdaSduboff 	OUTL(dp, RFCR, RFCR_RFEN | mode);
807f8919bdaSduboff 
808f8919bdaSduboff 	return (GEM_SUCCESS);
809f8919bdaSduboff }
810f8919bdaSduboff 
811f8919bdaSduboff static int
sfe_set_rx_filter_sis900(struct gem_dev * dp)812f8919bdaSduboff sfe_set_rx_filter_sis900(struct gem_dev *dp)
813f8919bdaSduboff {
814f8919bdaSduboff 	int		i;
815f8919bdaSduboff 	uint32_t	mode;
816f8919bdaSduboff 	uint16_t	hash_tbl[16];
817f8919bdaSduboff 	uint8_t		*mac = dp->cur_addr.ether_addr_octet;
818f8919bdaSduboff 	int		hash_size;
819f8919bdaSduboff 	int		hash_shift;
820f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
821f8919bdaSduboff 
822f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
823f8919bdaSduboff 
824f8919bdaSduboff 	if ((dp->rxmode & RXMODE_ENABLE) == 0) {
825915ebf8dSAlan Duboff 		/* disable rx filter */
826915ebf8dSAlan Duboff 		OUTLINL(dp, RFCR, 0);
827f8919bdaSduboff 		return (GEM_SUCCESS);
828f8919bdaSduboff 	}
829f8919bdaSduboff 
830f8919bdaSduboff 	/*
831f8919bdaSduboff 	 * determine hardware hash table size in word.
832f8919bdaSduboff 	 */
833f8919bdaSduboff 	hash_shift = 25;
834f8919bdaSduboff 	if (lp->revid >= SIS635A_900_REV || lp->revid == SIS900B_900_REV) {
835f8919bdaSduboff 		hash_shift = 24;
836f8919bdaSduboff 	}
837f8919bdaSduboff 	hash_size = (1 << (32 - hash_shift)) / 16;
838f8919bdaSduboff 	bzero(hash_tbl, sizeof (hash_tbl));
839f8919bdaSduboff 
840f8919bdaSduboff 	/* Set Receive filter control register */
841f8919bdaSduboff 
842f8919bdaSduboff 	if (dp->rxmode & RXMODE_PROMISC) {
843f8919bdaSduboff 		/* all broadcast, all multicast, all physical */
844f8919bdaSduboff 		mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
845f8919bdaSduboff 	} else if ((dp->rxmode & RXMODE_ALLMULTI) ||
846f8919bdaSduboff 	    dp->mc_count > hash_size*16/2) {
847f8919bdaSduboff 		/* all broadcast, all multicast, physical for the chip */
848f8919bdaSduboff 		mode = RFCR_AAB | RFCR_AAM;
849f8919bdaSduboff 	} else {
850f8919bdaSduboff 		/* all broadcast, physical for the chip */
851f8919bdaSduboff 		mode = RFCR_AAB;
852f8919bdaSduboff 	}
853f8919bdaSduboff 
854f8919bdaSduboff 	/* make hash table */
855f8919bdaSduboff 	for (i = 0; i < dp->mc_count; i++) {
856f8919bdaSduboff 		uint_t	h;
857f8919bdaSduboff 		h = dp->mc_list[i].hash >> hash_shift;
858f8919bdaSduboff 		hash_tbl[h / 16] |= 1 << (h % 16);
859f8919bdaSduboff 	}
860f8919bdaSduboff 
861f8919bdaSduboff 	if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
862f8919bdaSduboff 		/* Disable Rx filter and load mac address */
863f8919bdaSduboff 		for (i = 0; i < ETHERADDRL/2; i++) {
864f8919bdaSduboff 			/* For sis900, index is in word */
865915ebf8dSAlan Duboff 			OUTLINL(dp, RFCR,
866f8919bdaSduboff 			    (RFADDR_MAC_SIS900+i) << RFCR_RFADDR_SHIFT_SIS900);
867915ebf8dSAlan Duboff 			OUTLINL(dp, RFDR, (mac[i*2+1] << 8) | mac[i*2]);
868f8919bdaSduboff 		}
869f8919bdaSduboff 
870f8919bdaSduboff 		bcopy(mac, lp->mac_addr, ETHERADDRL);
871f8919bdaSduboff 	}
872f8919bdaSduboff 
873f8919bdaSduboff 	/* Load Multicast hash table */
874f8919bdaSduboff 	for (i = 0; i < hash_size; i++) {
875f8919bdaSduboff 		/* For sis900, index is in word */
876915ebf8dSAlan Duboff 		OUTLINL(dp, RFCR,
877f8919bdaSduboff 		    (RFADDR_MULTICAST_SIS900 + i) << RFCR_RFADDR_SHIFT_SIS900);
878915ebf8dSAlan Duboff 		OUTLINL(dp, RFDR, hash_tbl[i]);
879f8919bdaSduboff 	}
880f8919bdaSduboff 
881f8919bdaSduboff 	/* Load rx filter mode and enable rx filter */
882915ebf8dSAlan Duboff 	OUTLINL(dp, RFCR, RFCR_RFEN | mode);
883f8919bdaSduboff 
884f8919bdaSduboff 	return (GEM_SUCCESS);
885f8919bdaSduboff }
886f8919bdaSduboff 
887f8919bdaSduboff static int
sfe_start_chip(struct gem_dev * dp)888f8919bdaSduboff sfe_start_chip(struct gem_dev *dp)
889f8919bdaSduboff {
890f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
891f8919bdaSduboff 
892f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
893f8919bdaSduboff 
894f8919bdaSduboff 	/*
895f8919bdaSduboff 	 * setup interrupt mask, which shouldn't include ISR_TOK
896f8919bdaSduboff 	 * to improve performance.
897f8919bdaSduboff 	 */
898f8919bdaSduboff 	lp->our_intr_bits = OUR_INTR_BITS;
899f8919bdaSduboff 
900f8919bdaSduboff 	/* enable interrupt */
901f8919bdaSduboff 	if ((dp->misc_flag & GEM_NOINTR) == 0) {
902f8919bdaSduboff 		OUTL(dp, IER, 1);
903f8919bdaSduboff 		OUTL(dp, IMR, lp->our_intr_bits);
904f8919bdaSduboff 	}
905f8919bdaSduboff 
906f8919bdaSduboff 	/* Kick RX */
907f8919bdaSduboff 	OUTL(dp, CR, lp->cr | CR_RXE);
908f8919bdaSduboff 
909f8919bdaSduboff 	return (GEM_SUCCESS);
910f8919bdaSduboff }
911f8919bdaSduboff 
912f8919bdaSduboff /*
913f8919bdaSduboff  * Stop nic core gracefully.
914f8919bdaSduboff  */
915f8919bdaSduboff static int
sfe_stop_chip(struct gem_dev * dp)916f8919bdaSduboff sfe_stop_chip(struct gem_dev *dp)
917f8919bdaSduboff {
918f8919bdaSduboff 	struct sfe_dev	*lp = dp->private;
919f8919bdaSduboff 	uint32_t	done;
920f8919bdaSduboff 	int		i;
92123d366e3Sduboff 	uint32_t	val;
922f8919bdaSduboff 
923f8919bdaSduboff 	DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
924f8919bdaSduboff 
925f8919bdaSduboff 	/*
926f8919bdaSduboff 	 * Although we inhibit interrupt here, we don't clear soft copy of
927f8919bdaSduboff 	 * interrupt mask to avoid bogus interrupts.
928f8919bdaSduboff 	 */
929f8919bdaSduboff 	OUTL(dp, IMR, 0);
930f8919bdaSduboff 
931f8919bdaSduboff 	/* stop TX and RX immediately */
932f8919bdaSduboff 	OUTL(dp, CR, lp->cr | CR_TXR | CR_RXR);
933f8919bdaSduboff 
934f8919bdaSduboff 	done = 0;
935f8919bdaSduboff 	for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
936f8919bdaSduboff 		if (i > 1000) {
937f8919bdaSduboff 			/*
938f8919bdaSduboff 			 * As gem layer will call sfe_reset_chip(),
939f8919bdaSduboff 			 * we don't neet to reset futher
940f8919bdaSduboff 			 */
941f8919bdaSduboff 			cmn_err(CE_NOTE, "!%s: %s: Tx/Rx reset timeout",
942f8919bdaSduboff 			    dp->name, __func__);
943f8919bdaSduboff 
944f8919bdaSduboff 			return (GEM_FAILURE);
945f8919bdaSduboff 		}
94623d366e3Sduboff 		val = INL(dp, ISR);
94723d366e3Sduboff 		done |= val & (ISR_RXRCMP | ISR_TXRCMP);
94823d366e3Sduboff 		lp->isr_pended |= val & lp->our_intr_bits;
949f8919bdaSduboff 		drv_usecwait(10);
950f8919bdaSduboff 	}
951f8919bdaSduboff 
952f8919bdaSduboff 	return (GEM_SUCCESS);
953f8919bdaSduboff }
954f8919bdaSduboff 
95553560dfaSSherry Moore #ifndef	__sparc
95653560dfaSSherry Moore /*
95753560dfaSSherry Moore  * Stop nic core gracefully for quiesce
95853560dfaSSherry Moore  */
95953560dfaSSherry Moore static int
sfe_stop_chip_quiesce(struct gem_dev * dp)96053560dfaSSherry Moore sfe_stop_chip_quiesce(struct gem_dev *dp)
96153560dfaSSherry Moore {
96253560dfaSSherry Moore 	struct sfe_dev	*lp = dp->private;
96353560dfaSSherry Moore 	uint32_t	done;
96453560dfaSSherry Moore 	int		i;
96553560dfaSSherry Moore 	uint32_t	val;
96653560dfaSSherry Moore 
96753560dfaSSherry Moore 	/*
96853560dfaSSherry Moore 	 * Although we inhibit interrupt here, we don't clear soft copy of
96953560dfaSSherry Moore 	 * interrupt mask to avoid bogus interrupts.
97053560dfaSSherry Moore 	 */
97153560dfaSSherry Moore 	OUTL(dp, IMR, 0);
97253560dfaSSherry Moore 
97353560dfaSSherry Moore 	/* stop TX and RX immediately */
97453560dfaSSherry Moore 	OUTL(dp, CR, CR_TXR | CR_RXR);
97553560dfaSSherry Moore 
97653560dfaSSherry Moore 	done = 0;
97753560dfaSSherry Moore 	for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
97853560dfaSSherry Moore 		if (i > 1000) {
97953560dfaSSherry Moore 			/*
98053560dfaSSherry Moore 			 * As gem layer will call sfe_reset_chip(),
98153560dfaSSherry Moore 			 * we don't neet to reset futher
98253560dfaSSherry Moore 			 */
98353560dfaSSherry Moore 
98453560dfaSSherry Moore 			return (DDI_FAILURE);
98553560dfaSSherry Moore 		}
98653560dfaSSherry Moore 		val = INL(dp, ISR);
98753560dfaSSherry Moore 		done |= val & (ISR_RXRCMP | ISR_TXRCMP);
98853560dfaSSherry Moore 		lp->isr_pended |= val & lp->our_intr_bits;
98953560dfaSSherry Moore 		drv_usecwait(10);
99053560dfaSSherry Moore 	}
99153560dfaSSherry Moore 	return (DDI_SUCCESS);
99253560dfaSSherry Moore }
99353560dfaSSherry Moore #endif
99453560dfaSSherry Moore 
995f8919bdaSduboff /*
996f8919bdaSduboff  * Setup media mode
997f8919bdaSduboff  */
998f8919bdaSduboff static uint_t
999f8919bdaSduboff sfe_mxdma_value[] = { 512, 4, 8, 16, 32, 64, 128, 256, };
1000f8919bdaSduboff 
1001f8919bdaSduboff static uint_t
sfe_encode_mxdma(uint_t burstsize)1002f8919bdaSduboff sfe_encode_mxdma(uint_t burstsize)
1003f8919bdaSduboff {
1004f8919bdaSduboff 	int	i;
1005f8919bdaSduboff 
1006f8919bdaSduboff 	if (burstsize > 256) {
1007f8919bdaSduboff 		/* choose 512 */
1008