xref: /onnv-gate/usr/src/uts/common/io/rge/rge_main.c (revision 6764:726db199045b)
1744Sgs150176 /*
2744Sgs150176  * CDDL HEADER START
3744Sgs150176  *
4744Sgs150176  * The contents of this file are subject to the terms of the
52311Sseb  * Common Development and Distribution License (the "License").
62311Sseb  * You may not use this file except in compliance with the License.
7744Sgs150176  *
8744Sgs150176  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9744Sgs150176  * or http://www.opensolaris.org/os/licensing.
10744Sgs150176  * See the License for the specific language governing permissions
11744Sgs150176  * and limitations under the License.
12744Sgs150176  *
13744Sgs150176  * When distributing Covered Code, include this CDDL HEADER in each
14744Sgs150176  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15744Sgs150176  * If applicable, add the following below this CDDL HEADER, with the
16744Sgs150176  * fields enclosed by brackets "[]" replaced with your own identifying
17744Sgs150176  * information: Portions Copyright [yyyy] [name of copyright owner]
18744Sgs150176  *
19744Sgs150176  * CDDL HEADER END
20744Sgs150176  */
21744Sgs150176 /*
225895Syz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23744Sgs150176  * Use is subject to license terms.
24744Sgs150176  */
25744Sgs150176 
26744Sgs150176 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27744Sgs150176 
28744Sgs150176 #include "rge.h"
29744Sgs150176 
30744Sgs150176 /*
31744Sgs150176  * This is the string displayed by modinfo, etc.
32744Sgs150176  * Make sure you keep the version ID up to date!
33744Sgs150176  */
342544Sgs150176 static char rge_ident[] = "Realtek 1Gb Ethernet v%I%";
35744Sgs150176 
36744Sgs150176 /*
37744Sgs150176  * Used for buffers allocated by ddi_dma_mem_alloc()
38744Sgs150176  */
39744Sgs150176 static ddi_dma_attr_t dma_attr_buf = {
40744Sgs150176 	DMA_ATTR_V0,		/* dma_attr version */
41744Sgs150176 	(uint32_t)0,		/* dma_attr_addr_lo */
42744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_addr_hi */
43744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_count_max */
44744Sgs150176 	(uint32_t)16,		/* dma_attr_align */
45744Sgs150176 	0xFFFFFFFF,		/* dma_attr_burstsizes */
46744Sgs150176 	1,			/* dma_attr_minxfer */
47744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_maxxfer */
48744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_seg */
49744Sgs150176 	1,			/* dma_attr_sgllen */
50744Sgs150176 	1,			/* dma_attr_granular */
51744Sgs150176 	0,			/* dma_attr_flags */
52744Sgs150176 };
53744Sgs150176 
54744Sgs150176 /*
55744Sgs150176  * Used for BDs allocated by ddi_dma_mem_alloc()
56744Sgs150176  */
57744Sgs150176 static ddi_dma_attr_t dma_attr_desc = {
58744Sgs150176 	DMA_ATTR_V0,		/* dma_attr version */
59744Sgs150176 	(uint32_t)0,		/* dma_attr_addr_lo */
60744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_addr_hi */
61744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_count_max */
62744Sgs150176 	(uint32_t)256,		/* dma_attr_align */
63744Sgs150176 	0xFFFFFFFF,		/* dma_attr_burstsizes */
64744Sgs150176 	1,			/* dma_attr_minxfer */
65744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_maxxfer */
66744Sgs150176 	(uint32_t)0xFFFFFFFF,	/* dma_attr_seg */
67744Sgs150176 	1,			/* dma_attr_sgllen */
68744Sgs150176 	1,			/* dma_attr_granular */
69744Sgs150176 	0,			/* dma_attr_flags */
70744Sgs150176 };
71744Sgs150176 
72744Sgs150176 /*
73744Sgs150176  * PIO access attributes for registers
74744Sgs150176  */
75744Sgs150176 static ddi_device_acc_attr_t rge_reg_accattr = {
76744Sgs150176 	DDI_DEVICE_ATTR_V0,
77744Sgs150176 	DDI_STRUCTURE_LE_ACC,
78744Sgs150176 	DDI_STRICTORDER_ACC,
79744Sgs150176 	DDI_DEFAULT_ACC
80744Sgs150176 };
81744Sgs150176 
82744Sgs150176 /*
83744Sgs150176  * DMA access attributes for descriptors
84744Sgs150176  */
85744Sgs150176 static ddi_device_acc_attr_t rge_desc_accattr = {
86744Sgs150176 	DDI_DEVICE_ATTR_V0,
87744Sgs150176 	DDI_NEVERSWAP_ACC,
88744Sgs150176 	DDI_STRICTORDER_ACC,
89744Sgs150176 	DDI_DEFAULT_ACC
90744Sgs150176 };
91744Sgs150176 
92744Sgs150176 /*
93744Sgs150176  * DMA access attributes for data
94744Sgs150176  */
95744Sgs150176 static ddi_device_acc_attr_t rge_buf_accattr = {
96744Sgs150176 	DDI_DEVICE_ATTR_V0,
97744Sgs150176 	DDI_NEVERSWAP_ACC,
98744Sgs150176 	DDI_STRICTORDER_ACC,
99744Sgs150176 	DDI_DEFAULT_ACC
100744Sgs150176 };
101744Sgs150176 
102744Sgs150176 /*
103744Sgs150176  * Property names
104744Sgs150176  */
1052544Sgs150176 static char debug_propname[] = "rge_debug_flags";
1062544Sgs150176 static char mtu_propname[] = "default_mtu";
1072544Sgs150176 static char msi_propname[] = "msi_enable";
108744Sgs150176 
1092311Sseb static int		rge_m_start(void *);
1102311Sseb static void		rge_m_stop(void *);
1112311Sseb static int		rge_m_promisc(void *, boolean_t);
1122311Sseb static int		rge_m_multicst(void *, boolean_t, const uint8_t *);
1132311Sseb static int		rge_m_unicst(void *, const uint8_t *);
1142311Sseb static void		rge_m_resources(void *);
1152311Sseb static void		rge_m_ioctl(void *, queue_t *, mblk_t *);
1162311Sseb static boolean_t	rge_m_getcapab(void *, mac_capab_t, void *);
1172311Sseb 
1182311Sseb #define	RGE_M_CALLBACK_FLAGS	(MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
1192311Sseb 
1202311Sseb static mac_callbacks_t rge_m_callbacks = {
1212311Sseb 	RGE_M_CALLBACK_FLAGS,
1222311Sseb 	rge_m_stat,
1232311Sseb 	rge_m_start,
1242311Sseb 	rge_m_stop,
1252311Sseb 	rge_m_promisc,
1262311Sseb 	rge_m_multicst,
1272311Sseb 	rge_m_unicst,
1282311Sseb 	rge_m_tx,
1292311Sseb 	rge_m_resources,
1302311Sseb 	rge_m_ioctl,
1312311Sseb 	rge_m_getcapab
1322311Sseb };
133744Sgs150176 
134744Sgs150176 /*
135744Sgs150176  * Allocate an area of memory and a DMA handle for accessing it
136744Sgs150176  */
137744Sgs150176 static int
138744Sgs150176 rge_alloc_dma_mem(rge_t *rgep, size_t memsize, ddi_dma_attr_t *dma_attr_p,
139744Sgs150176 	ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, dma_area_t *dma_p)
140744Sgs150176 {
141744Sgs150176 	caddr_t vaddr;
142744Sgs150176 	int err;
143744Sgs150176 
144744Sgs150176 	/*
145744Sgs150176 	 * Allocate handle
146744Sgs150176 	 */
147744Sgs150176 	err = ddi_dma_alloc_handle(rgep->devinfo, dma_attr_p,
1485107Seota 	    DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
149744Sgs150176 	if (err != DDI_SUCCESS) {
150744Sgs150176 		dma_p->dma_hdl = NULL;
151744Sgs150176 		return (DDI_FAILURE);
152744Sgs150176 	}
153744Sgs150176 
154744Sgs150176 	/*
155744Sgs150176 	 * Allocate memory
156744Sgs150176 	 */
157744Sgs150176 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
158744Sgs150176 	    dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
159744Sgs150176 	    DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
160744Sgs150176 	if (err != DDI_SUCCESS) {
161744Sgs150176 		ddi_dma_free_handle(&dma_p->dma_hdl);
162744Sgs150176 		dma_p->dma_hdl = NULL;
163744Sgs150176 		dma_p->acc_hdl = NULL;
164744Sgs150176 		return (DDI_FAILURE);
165744Sgs150176 	}
166744Sgs150176 
167744Sgs150176 	/*
168744Sgs150176 	 * Bind the two together
169744Sgs150176 	 */
170744Sgs150176 	dma_p->mem_va = vaddr;
171744Sgs150176 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
172744Sgs150176 	    vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
173744Sgs150176 	    &dma_p->cookie, &dma_p->ncookies);
174744Sgs150176 	if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
175744Sgs150176 		ddi_dma_mem_free(&dma_p->acc_hdl);
176744Sgs150176 		ddi_dma_free_handle(&dma_p->dma_hdl);
177744Sgs150176 		dma_p->acc_hdl = NULL;
178744Sgs150176 		dma_p->dma_hdl = NULL;
179744Sgs150176 		return (DDI_FAILURE);
180744Sgs150176 	}
181744Sgs150176 
182744Sgs150176 	dma_p->nslots = ~0U;
183744Sgs150176 	dma_p->size = ~0U;
184744Sgs150176 	dma_p->token = ~0U;
185744Sgs150176 	dma_p->offset = 0;
186744Sgs150176 	return (DDI_SUCCESS);
187744Sgs150176 }
188744Sgs150176 
189744Sgs150176 /*
190744Sgs150176  * Free one allocated area of DMAable memory
191744Sgs150176  */
192744Sgs150176 static void
193744Sgs150176 rge_free_dma_mem(dma_area_t *dma_p)
194744Sgs150176 {
195744Sgs150176 	if (dma_p->dma_hdl != NULL) {
196744Sgs150176 		if (dma_p->ncookies) {
197744Sgs150176 			(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
198744Sgs150176 			dma_p->ncookies = 0;
199744Sgs150176 		}
200744Sgs150176 		ddi_dma_free_handle(&dma_p->dma_hdl);
201744Sgs150176 		dma_p->dma_hdl = NULL;
202744Sgs150176 	}
203744Sgs150176 
204744Sgs150176 	if (dma_p->acc_hdl != NULL) {
205744Sgs150176 		ddi_dma_mem_free(&dma_p->acc_hdl);
206744Sgs150176 		dma_p->acc_hdl = NULL;
207744Sgs150176 	}
208744Sgs150176 }
209744Sgs150176 
210744Sgs150176 /*
211744Sgs150176  * Utility routine to carve a slice off a chunk of allocated memory,
212744Sgs150176  * updating the chunk descriptor accordingly.  The size of the slice
213744Sgs150176  * is given by the product of the <qty> and <size> parameters.
214744Sgs150176  */
215744Sgs150176 static void
216744Sgs150176 rge_slice_chunk(dma_area_t *slice, dma_area_t *chunk,
217744Sgs150176 	uint32_t qty, uint32_t size)
218744Sgs150176 {
219744Sgs150176 	static uint32_t sequence = 0xbcd5704a;
220744Sgs150176 	size_t totsize;
221744Sgs150176 
222744Sgs150176 	totsize = qty*size;
223744Sgs150176 	ASSERT(size >= 0);
224744Sgs150176 	ASSERT(totsize <= chunk->alength);
225744Sgs150176 
226744Sgs150176 	*slice = *chunk;
227744Sgs150176 	slice->nslots = qty;
228744Sgs150176 	slice->size = size;
229744Sgs150176 	slice->alength = totsize;
230744Sgs150176 	slice->token = ++sequence;
231744Sgs150176 
232744Sgs150176 	chunk->mem_va = (caddr_t)chunk->mem_va + totsize;
233744Sgs150176 	chunk->alength -= totsize;
234744Sgs150176 	chunk->offset += totsize;
235744Sgs150176 	chunk->cookie.dmac_laddress += totsize;
236744Sgs150176 	chunk->cookie.dmac_size -= totsize;
237744Sgs150176 }
238744Sgs150176 
239744Sgs150176 static int
240744Sgs150176 rge_alloc_bufs(rge_t *rgep)
241744Sgs150176 {
242744Sgs150176 	size_t txdescsize;
243744Sgs150176 	size_t rxdescsize;
244744Sgs150176 	int err;
245744Sgs150176 
246744Sgs150176 	/*
247744Sgs150176 	 * Allocate memory & handle for packet statistics
248744Sgs150176 	 */
249744Sgs150176 	err = rge_alloc_dma_mem(rgep,
250744Sgs150176 	    RGE_STATS_DUMP_SIZE,
251744Sgs150176 	    &dma_attr_desc,
252744Sgs150176 	    &rge_desc_accattr,
253744Sgs150176 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
254744Sgs150176 	    &rgep->dma_area_stats);
255744Sgs150176 	if (err != DDI_SUCCESS)
256744Sgs150176 		return (DDI_FAILURE);
257744Sgs150176 	rgep->hw_stats = DMA_VPTR(rgep->dma_area_stats);
258744Sgs150176 
259744Sgs150176 	/*
260744Sgs150176 	 * Allocate memory & handle for Tx descriptor ring
261744Sgs150176 	 */
262744Sgs150176 	txdescsize = RGE_SEND_SLOTS * sizeof (rge_bd_t);
263744Sgs150176 	err = rge_alloc_dma_mem(rgep,
264744Sgs150176 	    txdescsize,
265744Sgs150176 	    &dma_attr_desc,
266744Sgs150176 	    &rge_desc_accattr,
267744Sgs150176 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
268744Sgs150176 	    &rgep->dma_area_txdesc);
269744Sgs150176 	if (err != DDI_SUCCESS)
270744Sgs150176 		return (DDI_FAILURE);
271744Sgs150176 
272744Sgs150176 	/*
273744Sgs150176 	 * Allocate memory & handle for Rx descriptor ring
274744Sgs150176 	 */
275744Sgs150176 	rxdescsize = RGE_RECV_SLOTS * sizeof (rge_bd_t);
276744Sgs150176 	err = rge_alloc_dma_mem(rgep,
277744Sgs150176 	    rxdescsize,
278744Sgs150176 	    &dma_attr_desc,
279744Sgs150176 	    &rge_desc_accattr,
280744Sgs150176 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
281744Sgs150176 	    &rgep->dma_area_rxdesc);
282744Sgs150176 	if (err != DDI_SUCCESS)
283744Sgs150176 		return (DDI_FAILURE);
284744Sgs150176 
285744Sgs150176 	return (DDI_SUCCESS);
286744Sgs150176 }
287744Sgs150176 
288744Sgs150176 /*
289744Sgs150176  * rge_free_bufs() -- free descriptors/buffers allocated for this
290744Sgs150176  * device instance.
291744Sgs150176  */
292744Sgs150176 static void
293744Sgs150176 rge_free_bufs(rge_t *rgep)
294744Sgs150176 {
295744Sgs150176 	rge_free_dma_mem(&rgep->dma_area_stats);
296744Sgs150176 	rge_free_dma_mem(&rgep->dma_area_txdesc);
297744Sgs150176 	rge_free_dma_mem(&rgep->dma_area_rxdesc);
298744Sgs150176 }
299744Sgs150176 
300744Sgs150176 /*
301744Sgs150176  * ========== Transmit and receive ring reinitialisation ==========
302744Sgs150176  */
303744Sgs150176 
304744Sgs150176 /*
305744Sgs150176  * These <reinit> routines each reset the rx/tx rings to an initial
306744Sgs150176  * state, assuming that the corresponding <init> routine has already
307744Sgs150176  * been called exactly once.
308744Sgs150176  */
309744Sgs150176 static void
310744Sgs150176 rge_reinit_send_ring(rge_t *rgep)
311744Sgs150176 {
312744Sgs150176 	sw_sbd_t *ssbdp;
313744Sgs150176 	rge_bd_t *bdp;
314744Sgs150176 	uint32_t slot;
315744Sgs150176 
316744Sgs150176 	/*
317744Sgs150176 	 * re-init send ring
318744Sgs150176 	 */
319744Sgs150176 	DMA_ZERO(rgep->tx_desc);
320744Sgs150176 	ssbdp = rgep->sw_sbds;
321744Sgs150176 	bdp = rgep->tx_ring;
322744Sgs150176 	for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
323744Sgs150176 		bdp->host_buf_addr =
324744Sgs150176 		    RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress);
325744Sgs150176 		bdp->host_buf_addr_hi =
326744Sgs150176 		    RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress >> 32);
327744Sgs150176 		/* last BD in Tx ring */
328744Sgs150176 		if (slot == (RGE_SEND_SLOTS - 1))
329744Sgs150176 			bdp->flags_len = RGE_BSWAP_32(BD_FLAG_EOR);
330744Sgs150176 		ssbdp++;
331744Sgs150176 		bdp++;
332744Sgs150176 	}
333744Sgs150176 	DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
334744Sgs150176 	rgep->tx_next = 0;
335744Sgs150176 	rgep->tc_next = 0;
336744Sgs150176 	rgep->tc_tail = 0;
337744Sgs150176 	rgep->tx_flow = 0;
338744Sgs150176 	rgep->tx_free = RGE_SEND_SLOTS;
339744Sgs150176 }
340744Sgs150176 
341744Sgs150176 static void
342744Sgs150176 rge_reinit_recv_ring(rge_t *rgep)
343744Sgs150176 {
344744Sgs150176 	rge_bd_t *bdp;
345744Sgs150176 	sw_rbd_t *srbdp;
346744Sgs150176 	dma_area_t *pbuf;
347744Sgs150176 	uint32_t slot;
348744Sgs150176 
349744Sgs150176 	/*
350744Sgs150176 	 * re-init receive ring
351744Sgs150176 	 */
352744Sgs150176 	DMA_ZERO(rgep->rx_desc);
353744Sgs150176 	srbdp = rgep->sw_rbds;
354744Sgs150176 	bdp = rgep->rx_ring;
355744Sgs150176 	for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
356744Sgs150176 		pbuf = &srbdp->rx_buf->pbuf;
357744Sgs150176 		bdp->host_buf_addr =
3582544Sgs150176 		    RGE_BSWAP_32(pbuf->cookie.dmac_laddress + rgep->head_room);
359744Sgs150176 		bdp->host_buf_addr_hi =
360744Sgs150176 		    RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32);
361744Sgs150176 		bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN |
3622544Sgs150176 		    (rgep->rxbuf_size - rgep->head_room));
363744Sgs150176 		/* last BD in Tx ring */
364744Sgs150176 		if (slot == (RGE_RECV_SLOTS - 1))
365744Sgs150176 			bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR);
366744Sgs150176 		srbdp++;
367744Sgs150176 		bdp++;
368744Sgs150176 	}
369744Sgs150176 	DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
370744Sgs150176 	rgep->watchdog = 0;
371744Sgs150176 	rgep->rx_next = 0;
372744Sgs150176 }
373744Sgs150176 
374744Sgs150176 static void
375744Sgs150176 rge_reinit_buf_ring(rge_t *rgep)
376744Sgs150176 {
3772544Sgs150176 
3782544Sgs150176 	if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
3792544Sgs150176 		return;
3802544Sgs150176 
381744Sgs150176 	/*
3822544Sgs150176 	 * If all the up-sending buffers haven't been returned to driver,
3832544Sgs150176 	 * use bcopy() only in rx process.
384744Sgs150176 	 */
385744Sgs150176 	if (rgep->rx_free != RGE_BUF_SLOTS)
386744Sgs150176 		rgep->rx_bcopy = B_TRUE;
387744Sgs150176 }
388744Sgs150176 
389744Sgs150176 static void
390744Sgs150176 rge_reinit_rings(rge_t *rgep)
391744Sgs150176 {
392744Sgs150176 	rge_reinit_send_ring(rgep);
393744Sgs150176 	rge_reinit_recv_ring(rgep);
394744Sgs150176 	rge_reinit_buf_ring(rgep);
395744Sgs150176 }
396744Sgs150176 
397744Sgs150176 static void
3982544Sgs150176 rge_fini_send_ring(rge_t *rgep)
3992544Sgs150176 {
4002544Sgs150176 	sw_sbd_t *ssbdp;
4012544Sgs150176 	uint32_t slot;
4022544Sgs150176 
4032544Sgs150176 	ssbdp = rgep->sw_sbds;
4042544Sgs150176 	for (slot = 0; slot < RGE_SEND_SLOTS; ++slot) {
4052544Sgs150176 		rge_free_dma_mem(&ssbdp->pbuf);
4062544Sgs150176 		ssbdp++;
4072544Sgs150176 	}
4082544Sgs150176 
4092544Sgs150176 	kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t));
4102544Sgs150176 	rgep->sw_sbds = NULL;
4112544Sgs150176 }
4122544Sgs150176 
4132544Sgs150176 static void
4142544Sgs150176 rge_fini_recv_ring(rge_t *rgep)
4152544Sgs150176 {
4162544Sgs150176 	sw_rbd_t *srbdp;
4172544Sgs150176 	uint32_t slot;
4182544Sgs150176 
4192544Sgs150176 	srbdp = rgep->sw_rbds;
4202544Sgs150176 	for (slot = 0; slot < RGE_RECV_SLOTS; ++srbdp, ++slot) {
4212544Sgs150176 		if (srbdp->rx_buf) {
4222544Sgs150176 			if (srbdp->rx_buf->mp != NULL) {
4232544Sgs150176 				freemsg(srbdp->rx_buf->mp);
4242544Sgs150176 				srbdp->rx_buf->mp = NULL;
4252544Sgs150176 			}
4262544Sgs150176 			rge_free_dma_mem(&srbdp->rx_buf->pbuf);
4272544Sgs150176 			kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
4282544Sgs150176 			srbdp->rx_buf = NULL;
4292544Sgs150176 		}
4302544Sgs150176 	}
4312544Sgs150176 
4322544Sgs150176 	kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t));
4332544Sgs150176 	rgep->sw_rbds = NULL;
4342544Sgs150176 }
4352544Sgs150176 
4362544Sgs150176 static void
4372544Sgs150176 rge_fini_buf_ring(rge_t *rgep)
4382544Sgs150176 {
4392544Sgs150176 	sw_rbd_t *srbdp;
4402544Sgs150176 	uint32_t slot;
4412544Sgs150176 
4422544Sgs150176 	if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
4432544Sgs150176 		return;
4442544Sgs150176 
4452544Sgs150176 	ASSERT(rgep->rx_free == RGE_BUF_SLOTS);
4462544Sgs150176 
4472544Sgs150176 	srbdp = rgep->free_srbds;
4482544Sgs150176 	for (slot = 0; slot < RGE_BUF_SLOTS; ++srbdp, ++slot) {
4492544Sgs150176 		if (srbdp->rx_buf != NULL) {
4502544Sgs150176 			if (srbdp->rx_buf->mp != NULL) {
4512544Sgs150176 				freemsg(srbdp->rx_buf->mp);
4522544Sgs150176 				srbdp->rx_buf->mp = NULL;
4532544Sgs150176 			}
4542544Sgs150176 			rge_free_dma_mem(&srbdp->rx_buf->pbuf);
4552544Sgs150176 			kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
4562544Sgs150176 			srbdp->rx_buf = NULL;
4572544Sgs150176 		}
4582544Sgs150176 	}
4592544Sgs150176 
4602544Sgs150176 	kmem_free(rgep->free_srbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t));
4612544Sgs150176 	rgep->free_srbds = NULL;
4622544Sgs150176 }
4632544Sgs150176 
4642544Sgs150176 static void
4652544Sgs150176 rge_fini_rings(rge_t *rgep)
4662544Sgs150176 {
4672544Sgs150176 	rge_fini_send_ring(rgep);
4682544Sgs150176 	rge_fini_recv_ring(rgep);
4692544Sgs150176 	rge_fini_buf_ring(rgep);
4702544Sgs150176 }
4712544Sgs150176 
4722544Sgs150176 static int
473744Sgs150176 rge_init_send_ring(rge_t *rgep)
474744Sgs150176 {
475744Sgs150176 	uint32_t slot;
476744Sgs150176 	sw_sbd_t *ssbdp;
477744Sgs150176 	dma_area_t *pbuf;
4782544Sgs150176 	dma_area_t desc;
4792544Sgs150176 	int err;
480744Sgs150176 
481744Sgs150176 	/*
482744Sgs150176 	 * Allocate the array of s/w Tx Buffer Descriptors
483744Sgs150176 	 */
484744Sgs150176 	ssbdp = kmem_zalloc(RGE_SEND_SLOTS*sizeof (*ssbdp), KM_SLEEP);
485744Sgs150176 	rgep->sw_sbds = ssbdp;
486744Sgs150176 
487744Sgs150176 	/*
488744Sgs150176 	 * Init send ring
489744Sgs150176 	 */
490744Sgs150176 	rgep->tx_desc = rgep->dma_area_txdesc;
491744Sgs150176 	DMA_ZERO(rgep->tx_desc);
4922544Sgs150176 	rgep->tx_ring = rgep->tx_desc.mem_va;
4932544Sgs150176 
4942544Sgs150176 	desc = rgep->tx_desc;
4952544Sgs150176 	for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
4962544Sgs150176 		rge_slice_chunk(&ssbdp->desc, &desc, 1, sizeof (rge_bd_t));
4972544Sgs150176 
4982544Sgs150176 		/*
4992544Sgs150176 		 * Allocate memory & handle for Tx buffers
5002544Sgs150176 		 */
5012544Sgs150176 		pbuf = &ssbdp->pbuf;
5022544Sgs150176 		err = rge_alloc_dma_mem(rgep, rgep->txbuf_size,
5032544Sgs150176 		    &dma_attr_buf, &rge_buf_accattr,
5042544Sgs150176 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, pbuf);
5052544Sgs150176 		if (err != DDI_SUCCESS) {
5062544Sgs150176 			rge_error(rgep,
5072544Sgs150176 			    "rge_init_send_ring: alloc tx buffer failed");
5082544Sgs150176 			rge_fini_send_ring(rgep);
5092544Sgs150176 			return (DDI_FAILURE);
510744Sgs150176 		}
5112544Sgs150176 		ssbdp++;
512744Sgs150176 	}
5132544Sgs150176 	ASSERT(desc.alength == 0);
5142544Sgs150176 
515744Sgs150176 	DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
5162544Sgs150176 	return (DDI_SUCCESS);
517744Sgs150176 }
518744Sgs150176 
519744Sgs150176 static int
520744Sgs150176 rge_init_recv_ring(rge_t *rgep)
521744Sgs150176 {
522744Sgs150176 	uint32_t slot;
523744Sgs150176 	sw_rbd_t *srbdp;
524744Sgs150176 	dma_buf_t *rx_buf;
525744Sgs150176 	dma_area_t *pbuf;
5262544Sgs150176 	int err;
527744Sgs150176 
528744Sgs150176 	/*
529744Sgs150176 	 * Allocate the array of s/w Rx Buffer Descriptors
530744Sgs150176 	 */
531744Sgs150176 	srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP);
532744Sgs150176 	rgep->sw_rbds = srbdp;
533744Sgs150176 
534744Sgs150176 	/*
535744Sgs150176 	 * Init receive ring
536744Sgs150176 	 */
537744Sgs150176 	rgep->rx_next = 0;
538744Sgs150176 	rgep->rx_desc = rgep->dma_area_rxdesc;
539744Sgs150176 	DMA_ZERO(rgep->rx_desc);
5402544Sgs150176 	rgep->rx_ring = rgep->rx_desc.mem_va;
5412544Sgs150176 
5422544Sgs150176 	for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
5432544Sgs150176 		srbdp->rx_buf = rx_buf =
5442544Sgs150176 		    kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
5452544Sgs150176 
5462544Sgs150176 		/*
5472544Sgs150176 		 * Allocate memory & handle for Rx buffers
5482544Sgs150176 		 */
5492544Sgs150176 		pbuf = &rx_buf->pbuf;
5502544Sgs150176 		err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
5512544Sgs150176 		    &dma_attr_buf, &rge_buf_accattr,
5522544Sgs150176 		    DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
5532544Sgs150176 		if (err != DDI_SUCCESS) {
5542544Sgs150176 			rge_fini_recv_ring(rgep);
5552544Sgs150176 			rge_error(rgep,
5562544Sgs150176 			    "rge_init_recv_ring: alloc rx buffer failed");
5572544Sgs150176 			return (DDI_FAILURE);
5582544Sgs150176 		}
5592544Sgs150176 
5602544Sgs150176 		pbuf->alength -= rgep->head_room;
5612544Sgs150176 		pbuf->offset += rgep->head_room;
5622544Sgs150176 		if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)) {
563744Sgs150176 			rx_buf->rx_recycle.free_func = rge_rx_recycle;
564744Sgs150176 			rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
565744Sgs150176 			rx_buf->private = (caddr_t)rgep;
566744Sgs150176 			rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
567744Sgs150176 			    rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
568744Sgs150176 			if (rx_buf->mp == NULL) {
5692544Sgs150176 				rge_fini_recv_ring(rgep);
570744Sgs150176 				rge_problem(rgep,
571744Sgs150176 				    "rge_init_recv_ring: desballoc() failed");
572744Sgs150176 				return (DDI_FAILURE);
573744Sgs150176 			}
574744Sgs150176 		}
5752544Sgs150176 		srbdp++;
576744Sgs150176 	}
577744Sgs150176 	DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
578744Sgs150176 	return (DDI_SUCCESS);
579744Sgs150176 }
580744Sgs150176 
581744Sgs150176 static int
582744Sgs150176 rge_init_buf_ring(rge_t *rgep)
583744Sgs150176 {
584744Sgs150176 	uint32_t slot;
5852544Sgs150176 	sw_rbd_t *free_srbdp;
586744Sgs150176 	dma_buf_t *rx_buf;
587744Sgs150176 	dma_area_t *pbuf;
5882544Sgs150176 	int err;
5892544Sgs150176 
5902544Sgs150176 	if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) {
5912544Sgs150176 		rgep->rx_bcopy = B_TRUE;
5922544Sgs150176 		return (DDI_SUCCESS);
5932544Sgs150176 	}
594744Sgs150176 
595744Sgs150176 	/*
596744Sgs150176 	 * Allocate the array of s/w free Buffer Descriptors
597744Sgs150176 	 */
5982544Sgs150176 	free_srbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_srbdp), KM_SLEEP);
5992544Sgs150176 	rgep->free_srbds = free_srbdp;
600744Sgs150176 
601744Sgs150176 	/*
602744Sgs150176 	 * Init free buffer ring
603744Sgs150176 	 */
604744Sgs150176 	rgep->rc_next = 0;
605744Sgs150176 	rgep->rf_next = 0;
606744Sgs150176 	rgep->rx_bcopy = B_FALSE;
607744Sgs150176 	rgep->rx_free = RGE_BUF_SLOTS;
6082544Sgs150176 	for (slot = 0; slot < RGE_BUF_SLOTS; slot++) {
6092544Sgs150176 		free_srbdp->rx_buf = rx_buf =
6102544Sgs150176 		    kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
6112544Sgs150176 
6122544Sgs150176 		/*
6132544Sgs150176 		 * Allocate memory & handle for free Rx buffers
6142544Sgs150176 		 */
6152544Sgs150176 		pbuf = &rx_buf->pbuf;
6162544Sgs150176 		err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
6172544Sgs150176 		    &dma_attr_buf, &rge_buf_accattr,
6182544Sgs150176 		    DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
6192544Sgs150176 		if (err != DDI_SUCCESS) {
6202544Sgs150176 			rge_fini_buf_ring(rgep);
6212544Sgs150176 			rge_error(rgep,
6222544Sgs150176 			    "rge_init_buf_ring: alloc rx free buffer failed");
6232544Sgs150176 			return (DDI_FAILURE);
624744Sgs150176 		}
6252544Sgs150176 		pbuf->alength -= rgep->head_room;
6262544Sgs150176 		pbuf->offset += rgep->head_room;
6272544Sgs150176 		rx_buf->rx_recycle.free_func = rge_rx_recycle;
6282544Sgs150176 		rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
6292544Sgs150176 		rx_buf->private = (caddr_t)rgep;
6302544Sgs150176 		rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
6312544Sgs150176 		    rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
6322544Sgs150176 		if (rx_buf->mp == NULL) {
6332544Sgs150176 			rge_fini_buf_ring(rgep);
6342544Sgs150176 			rge_problem(rgep,
6352544Sgs150176 			    "rge_init_buf_ring: desballoc() failed");
6362544Sgs150176 			return (DDI_FAILURE);
6372544Sgs150176 		}
6382544Sgs150176 		free_srbdp++;
639744Sgs150176 	}
640744Sgs150176 	return (DDI_SUCCESS);
641744Sgs150176 }
642744Sgs150176 
643744Sgs150176 static int
644744Sgs150176 rge_init_rings(rge_t *rgep)
645744Sgs150176 {
646744Sgs150176 	int err;
647744Sgs150176 
6482544Sgs150176 	err = rge_init_send_ring(rgep);
6492544Sgs150176 	if (err != DDI_SUCCESS)
6502544Sgs150176 		return (DDI_FAILURE);
651744Sgs150176 
6522544Sgs150176 	err = rge_init_recv_ring(rgep);
6532544Sgs150176 	if (err != DDI_SUCCESS) {
6542544Sgs150176 		rge_fini_send_ring(rgep);
6552544Sgs150176 		return (DDI_FAILURE);
6562544Sgs150176 	}
657744Sgs150176 
6582544Sgs150176 	err = rge_init_buf_ring(rgep);
6592544Sgs150176 	if (err != DDI_SUCCESS) {
6602544Sgs150176 		rge_fini_send_ring(rgep);
6612544Sgs150176 		rge_fini_recv_ring(rgep);
6622544Sgs150176 		return (DDI_FAILURE);
6632544Sgs150176 	}
664744Sgs150176 
6652544Sgs150176 	return (DDI_SUCCESS);
666744Sgs150176 }
667744Sgs150176 
668744Sgs150176 /*
669744Sgs150176  * ========== Internal state management entry points ==========
670744Sgs150176  */
671744Sgs150176 
672744Sgs150176 #undef	RGE_DBG
673744Sgs150176 #define	RGE_DBG		RGE_DBG_NEMO	/* debug flag for this code	*/
674744Sgs150176 
675744Sgs150176 /*
676744Sgs150176  * These routines provide all the functionality required by the
677744Sgs150176  * corresponding MAC layer entry points, but don't update the
678744Sgs150176  * MAC state so they can be called internally without disturbing
679744Sgs150176  * our record of what NEMO thinks we should be doing ...
680744Sgs150176  */
681744Sgs150176 
682744Sgs150176 /*
683744Sgs150176  *	rge_reset() -- reset h/w & rings to initial state
684744Sgs150176  */
685744Sgs150176 static void
686744Sgs150176 rge_reset(rge_t *rgep)
687744Sgs150176 {
688744Sgs150176 	ASSERT(mutex_owned(rgep->genlock));
689744Sgs150176 
690744Sgs150176 	/*
691744Sgs150176 	 * Grab all the other mutexes in the world (this should
692744Sgs150176 	 * ensure no other threads are manipulating driver state)
693744Sgs150176 	 */
694744Sgs150176 	mutex_enter(rgep->rx_lock);
695744Sgs150176 	mutex_enter(rgep->rc_lock);
696744Sgs150176 	rw_enter(rgep->errlock, RW_WRITER);
697744Sgs150176 
698744Sgs150176 	(void) rge_chip_reset(rgep);
699744Sgs150176 	rge_reinit_rings(rgep);
700744Sgs150176 	rge_chip_init(rgep);
701744Sgs150176 
702744Sgs150176 	/*
703744Sgs150176 	 * Free the world ...
704744Sgs150176 	 */
705744Sgs150176 	rw_exit(rgep->errlock);
706744Sgs150176 	mutex_exit(rgep->rc_lock);
707744Sgs150176 	mutex_exit(rgep->rx_lock);
708744Sgs150176 
7096410Smx205022 	rgep->stats.rpackets = 0;
7106410Smx205022 	rgep->stats.rbytes = 0;
7116410Smx205022 	rgep->stats.opackets = 0;
7126410Smx205022 	rgep->stats.obytes = 0;
7136410Smx205022 	rgep->stats.tx_pre_ismax = B_FALSE;
7146410Smx205022 	rgep->stats.tx_cur_ismax = B_FALSE;
7156410Smx205022 
716744Sgs150176 	RGE_DEBUG(("rge_reset($%p) done", (void *)rgep));
717744Sgs150176 }
718744Sgs150176 
719744Sgs150176 /*
720744Sgs150176  *	rge_stop() -- stop processing, don't reset h/w or rings
721744Sgs150176  */
722744Sgs150176 static void
723744Sgs150176 rge_stop(rge_t *rgep)
724744Sgs150176 {
725744Sgs150176 	ASSERT(mutex_owned(rgep->genlock));
726744Sgs150176 
727744Sgs150176 	rge_chip_stop(rgep, B_FALSE);
728744Sgs150176 
729744Sgs150176 	RGE_DEBUG(("rge_stop($%p) done", (void *)rgep));
730744Sgs150176 }
731744Sgs150176 
732744Sgs150176 /*
733744Sgs150176  *	rge_start() -- start transmitting/receiving
734744Sgs150176  */
735744Sgs150176 static void
736744Sgs150176 rge_start(rge_t *rgep)
737744Sgs150176 {
738744Sgs150176 	ASSERT(mutex_owned(rgep->genlock));
739744Sgs150176 
740744Sgs150176 	/*
741744Sgs150176 	 * Start chip processing, including enabling interrupts
742744Sgs150176 	 */
743744Sgs150176 	rge_chip_start(rgep);
744744Sgs150176 	rgep->watchdog = 0;
745744Sgs150176 }
746744Sgs150176 
747744Sgs150176 /*
748744Sgs150176  * rge_restart - restart transmitting/receiving after error or suspend
749744Sgs150176  */
750744Sgs150176 void
751744Sgs150176 rge_restart(rge_t *rgep)
752744Sgs150176 {
753744Sgs150176 	uint32_t i;
754744Sgs150176 
755744Sgs150176 	ASSERT(mutex_owned(rgep->genlock));
756744Sgs150176 	/*
757744Sgs150176 	 * Wait for posted buffer to be freed...
758744Sgs150176 	 */
759744Sgs150176 	if (!rgep->rx_bcopy) {
760744Sgs150176 		for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
761744Sgs150176 			if (rgep->rx_free == RGE_BUF_SLOTS)
762744Sgs150176 				break;
763744Sgs150176 			drv_usecwait(1000);
764744Sgs150176 			RGE_DEBUG(("rge_restart: waiting for rx buf free..."));
765744Sgs150176 		}
766744Sgs150176 	}
767744Sgs150176 	rge_reset(rgep);
768744Sgs150176 	rgep->stats.chip_reset++;
769744Sgs150176 	if (rgep->rge_mac_state == RGE_MAC_STARTED) {
770744Sgs150176 		rge_start(rgep);
7712544Sgs150176 		rgep->resched_needed = B_TRUE;
7722544Sgs150176 		(void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL);
773744Sgs150176 	}
774744Sgs150176 }
775744Sgs150176 
776744Sgs150176 
777744Sgs150176 /*
778744Sgs150176  * ========== Nemo-required management entry points ==========
779744Sgs150176  */
780744Sgs150176 
781744Sgs150176 #undef	RGE_DBG
782744Sgs150176 #define	RGE_DBG		RGE_DBG_NEMO	/* debug flag for this code	*/
783744Sgs150176 
784744Sgs150176 /*
785744Sgs150176  *	rge_m_stop() -- stop transmitting/receiving
786744Sgs150176  */
787744Sgs150176 static void
788744Sgs150176 rge_m_stop(void *arg)
789744Sgs150176 {
790744Sgs150176 	rge_t *rgep = arg;		/* private device info	*/
791744Sgs150176 	uint32_t i;
792744Sgs150176 
793744Sgs150176 	/*
794744Sgs150176 	 * Just stop processing, then record new MAC state
795744Sgs150176 	 */
796744Sgs150176 	mutex_enter(rgep->genlock);
797*6764Smx205022 	if (rgep->suspended) {
798*6764Smx205022 		ASSERT(rgep->rge_mac_state == RGE_MAC_STOPPED);
799*6764Smx205022 		mutex_exit(rgep->genlock);
800*6764Smx205022 		return;
801*6764Smx205022 	}
802744Sgs150176 	rge_stop(rgep);
803744Sgs150176 	/*
804744Sgs150176 	 * Wait for posted buffer to be freed...
805744Sgs150176 	 */
806744Sgs150176 	if (!rgep->rx_bcopy) {
807744Sgs150176 		for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
808744Sgs150176 			if (rgep->rx_free == RGE_BUF_SLOTS)
809744Sgs150176 				break;
810744Sgs150176 			drv_usecwait(1000);
811744Sgs150176 			RGE_DEBUG(("rge_m_stop: waiting for rx buf free..."));
812744Sgs150176 		}
813744Sgs150176 	}
814744Sgs150176 	rgep->rge_mac_state = RGE_MAC_STOPPED;
815744Sgs150176 	RGE_DEBUG(("rge_m_stop($%p) done", arg));
816744Sgs150176 	mutex_exit(rgep->genlock);
817744Sgs150176 }
818744Sgs150176 
819744Sgs150176 /*
820744Sgs150176  *	rge_m_start() -- start transmitting/receiving
821744Sgs150176  */
822744Sgs150176 static int
823744Sgs150176 rge_m_start(void *arg)
824744Sgs150176 {
825744Sgs150176 	rge_t *rgep = arg;		/* private device info	*/
826744Sgs150176 
827744Sgs150176 	mutex_enter(rgep->genlock);
828*6764Smx205022 	if (rgep->suspended) {
829*6764Smx205022 		mutex_exit(rgep->genlock);
830*6764Smx205022 		return (DDI_FAILURE);
831*6764Smx205022 	}
832744Sgs150176 	/*
833744Sgs150176 	 * Clear hw/sw statistics
834744Sgs150176 	 */
835744Sgs150176 	DMA_ZERO(rgep->dma_area_stats);
836744Sgs150176 	bzero(&rgep->stats, sizeof (rge_stats_t));
837744Sgs150176 
838744Sgs150176 	/*
839744Sgs150176 	 * Start processing and record new MAC state
840744Sgs150176 	 */
841744Sgs150176 	rge_reset(rgep);
842744Sgs150176 	rge_start(rgep);
843744Sgs150176 	rgep->rge_mac_state = RGE_MAC_STARTED;
844744Sgs150176 	RGE_DEBUG(("rge_m_start($%p) done", arg));
845744Sgs150176 
846744Sgs150176 	mutex_exit(rgep->genlock);
847744Sgs150176 
848744Sgs150176 	return (0);
849744Sgs150176 }
850744Sgs150176 
851744Sgs150176 /*
852744Sgs150176  *	rge_m_unicst_set() -- set the physical network address
853744Sgs150176  */
854744Sgs150176 static int
855744Sgs150176 rge_m_unicst(void *arg, const uint8_t *macaddr)
856744Sgs150176 {
857744Sgs150176 	rge_t *rgep = arg;		/* private device info	*/
858744Sgs150176 
859744Sgs150176 	/*
860744Sgs150176 	 * Remember the new current address in the driver state
861744Sgs150176 	 * Sync the chip's idea of the address too ...
862744Sgs150176 	 */
863744Sgs150176 	mutex_enter(rgep->genlock);
864744Sgs150176 	bcopy(macaddr, rgep->netaddr, ETHERADDRL);
865*6764Smx205022 
866*6764Smx205022 	if (rgep->suspended) {
867*6764Smx205022 		mutex_exit(rgep->genlock);
868*6764Smx205022 		return (DDI_SUCCESS);
869*6764Smx205022 	}
870*6764Smx205022 
871744Sgs150176 	rge_chip_sync(rgep, RGE_SET_MAC);
872744Sgs150176 	mutex_exit(rgep->genlock);
873744Sgs150176 
874744Sgs150176 	return (0);
875744Sgs150176 }
876744Sgs150176 
877744Sgs150176 /*
878744Sgs150176  * Compute the index of the required bit in the multicast hash map.
879744Sgs150176  * This must mirror the way the hardware actually does it!
880744Sgs150176  */
881744Sgs150176 static uint32_t
882744Sgs150176 rge_hash_index(const uint8_t *mca)
883744Sgs150176 {
8842544Sgs150176 	uint32_t crc = (uint32_t)RGE_HASH_CRC;
885744Sgs150176 	uint32_t const POLY = RGE_HASH_POLY;
886744Sgs150176 	uint32_t msb;
887744Sgs150176 	int bytes;
888744Sgs150176 	uchar_t currentbyte;
889744Sgs150176 	uint32_t index;
890744Sgs150176 	int bit;
891744Sgs150176 
892744Sgs150176 	for (bytes = 0; bytes < ETHERADDRL; bytes++) {
893744Sgs150176 		currentbyte = mca[bytes];
894744Sgs150176 		for (bit = 0; bit < 8; bit++) {
895744Sgs150176 			msb = crc >> 31;
896744Sgs150176 			crc <<= 1;
8972544Sgs150176 			if (msb ^ (currentbyte & 1))
898744Sgs150176 				crc ^= POLY;
899744Sgs150176 			currentbyte >>= 1;
900744Sgs150176 		}
901744Sgs150176 	}
902744Sgs150176 	index = crc >> 26;
9032544Sgs150176 		/* the index value is between 0 and 63(0x3f) */
904744Sgs150176 
905744Sgs150176 	return (index);
906744Sgs150176 }
907744Sgs150176 
908744Sgs150176 /*
909744Sgs150176  *	rge_m_multicst_add() -- enable/disable a multicast address
910744Sgs150176  */
911744Sgs150176 static int
912744Sgs150176 rge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
913744Sgs150176 {
914744Sgs150176 	rge_t *rgep = arg;		/* private device info	*/
915744Sgs150176 	struct ether_addr *addr;
916744Sgs150176 	uint32_t index;
9172544Sgs150176 	uint32_t reg;
9182544Sgs150176 	uint8_t *hashp;
919744Sgs150176 
920744Sgs150176 	mutex_enter(rgep->genlock);
921744Sgs150176 	hashp = rgep->mcast_hash;
922744Sgs150176 	addr = (struct ether_addr *)mca;
9232544Sgs150176 	/*
9242544Sgs150176 	 * Calculate the Multicast address hash index value
9252544Sgs150176 	 *	Normally, the position of MAR0-MAR7 is
9262544Sgs150176 	 *	MAR0: offset 0x08, ..., MAR7: offset 0x0F.
9272544Sgs150176 	 *
9282544Sgs150176 	 *	For pcie chipset, the position of MAR0-MAR7 is
9292544Sgs150176 	 *	different from others:
9302544Sgs150176 	 *	MAR0: offset 0x0F, ..., MAR7: offset 0x08.
9312544Sgs150176 	 */
932744Sgs150176 	index = rge_hash_index(addr->ether_addr_octet);
9332544Sgs150176 	if (rgep->chipid.is_pcie)
9342544Sgs150176 		reg = (~(index / RGE_MCAST_NUM)) & 0x7;
9352544Sgs150176 	else
9362544Sgs150176 		reg = index / RGE_MCAST_NUM;
937744Sgs150176 
938744Sgs150176 	if (add) {
939744Sgs150176 		if (rgep->mcast_refs[index]++) {
940744Sgs150176 			mutex_exit(rgep->genlock);
941744Sgs150176 			return (0);
942744Sgs150176 		}
9432544Sgs150176 		hashp[reg] |= 1 << (index % RGE_MCAST_NUM);
944744Sgs150176 	} else {
945744Sgs150176 		if (--rgep->mcast_refs[index]) {
946744Sgs150176 			mutex_exit(rgep->genlock);
947744Sgs150176 			return (0);
948744Sgs150176 		}
9492544Sgs150176 		hashp[reg] &= ~ (1 << (index % RGE_MCAST_NUM));
950744Sgs150176 	}
951744Sgs150176 
952*6764Smx205022 	if (rgep->suspended) {
953*6764Smx205022 		mutex_exit(rgep->genlock);
954*6764Smx205022 		return (DDI_SUCCESS);
955*6764Smx205022 	}
956*6764Smx205022 
957744Sgs150176 	/*
958744Sgs150176 	 * Set multicast register
959744Sgs150176 	 */
960744Sgs150176 	rge_chip_sync(rgep, RGE_SET_MUL);
961744Sgs150176 
962744Sgs150176 	mutex_exit(rgep->genlock);
963744Sgs150176 	return (0);
964744Sgs150176 }
965744Sgs150176 
966744Sgs150176 /*
967744Sgs150176  * rge_m_promisc() -- set or reset promiscuous mode on the board
968744Sgs150176  *
969744Sgs150176  *	Program the hardware to enable/disable promiscuous and/or
970744Sgs150176  *	receive-all-multicast modes.
971744Sgs150176  */
972744Sgs150176 static int
973744Sgs150176 rge_m_promisc(void *arg, boolean_t on)
974744Sgs150176 {
975744Sgs150176 	rge_t *rgep = arg;
976744Sgs150176 
977744Sgs150176 	/*
978744Sgs150176 	 * Store MAC layer specified mode and pass to chip layer to update h/w
979744Sgs150176 	 */
980744Sgs150176 	mutex_enter(rgep->genlock);
981744Sgs150176 
982744Sgs150176 	if (rgep->promisc == on) {
983744Sgs150176 		mutex_exit(rgep->genlock);
984744Sgs150176 		return (0);
985744Sgs150176 	}
986744Sgs150176 	rgep->promisc = on;
987*6764Smx205022 
988*6764Smx205022 	if (rgep->suspended) {
989*6764Smx205022 		mutex_exit(rgep->genlock);
990*6764Smx205022 		return (DDI_SUCCESS);
991*6764Smx205022 	}
992*6764Smx205022 
993744Sgs150176 	rge_chip_sync(rgep, RGE_SET_PROMISC);
994744Sgs150176 	RGE_DEBUG(("rge_m_promisc_set($%p) done", arg));
995744Sgs150176 	mutex_exit(rgep->genlock);
996744Sgs150176 	return (0);
997744Sgs150176 }
998744Sgs150176 
999744Sgs150176 /*
1000744Sgs150176  * Loopback ioctl code
1001744Sgs150176  */
1002744Sgs150176 
1003744Sgs150176 static lb_property_t loopmodes[] = {
1004744Sgs150176 	{ normal,	"normal",	RGE_LOOP_NONE		},
1005744Sgs150176 	{ internal,	"PHY",		RGE_LOOP_INTERNAL_PHY	},
1006744Sgs150176 	{ internal,	"MAC",		RGE_LOOP_INTERNAL_MAC	}
1007744Sgs150176 };
1008744Sgs150176 
1009744Sgs150176 static enum ioc_reply
1010744Sgs150176 rge_set_loop_mode(rge_t *rgep, uint32_t mode)
1011744Sgs150176 {
1012744Sgs150176 	/*
1013744Sgs150176 	 * If the mode isn't being changed, there's nothing to do ...
1014744Sgs150176 	 */
1015744Sgs150176 	if (mode == rgep->param_loop_mode)
1016744Sgs150176 		return (IOC_ACK);
1017744Sgs150176 
1018744Sgs150176 	/*
1019744Sgs150176 	 * Validate the requested mode and prepare a suitable message
1020744Sgs150176 	 * to explain the link down/up cycle that the change will
1021744Sgs150176 	 * probably induce ...
1022744Sgs150176 	 */
1023744Sgs150176 	switch (mode) {
1024744Sgs150176 	default:
1025744Sgs150176 		return (IOC_INVAL);
1026744Sgs150176 
1027744Sgs150176 	case RGE_LOOP_NONE:
1028744Sgs150176 	case RGE_LOOP_INTERNAL_PHY:
1029744Sgs150176 	case RGE_LOOP_INTERNAL_MAC:
1030744Sgs150176 		break;
1031744Sgs150176 	}
1032744Sgs150176 
1033744Sgs150176 	/*
1034744Sgs150176 	 * All OK; tell the caller to reprogram
1035744Sgs150176 	 * the PHY and/or MAC for the new mode ...
1036744Sgs150176 	 */
1037744Sgs150176 	rgep->param_loop_mode = mode;
1038744Sgs150176 	return (IOC_RESTART_ACK);
1039744Sgs150176 }
1040744Sgs150176 
1041744Sgs150176 static enum ioc_reply
1042744Sgs150176 rge_loop_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
1043744Sgs150176 {
1044744Sgs150176 	lb_info_sz_t *lbsp;
1045744Sgs150176 	lb_property_t *lbpp;
1046744Sgs150176 	uint32_t *lbmp;
1047744Sgs150176 	int cmd;
1048744Sgs150176 
1049744Sgs150176 	_NOTE(ARGUNUSED(wq))
1050744Sgs150176 
1051744Sgs150176 	/*
1052744Sgs150176 	 * Validate format of ioctl
1053744Sgs150176 	 */
1054744Sgs150176 	if (mp->b_cont == NULL)
1055744Sgs150176 		return (IOC_INVAL);
1056744Sgs150176 
1057744Sgs150176 	cmd = iocp->ioc_cmd;
1058744Sgs150176 	switch (cmd) {
1059744Sgs150176 	default:
1060744Sgs150176 		/* NOTREACHED */
1061744Sgs150176 		rge_error(rgep, "rge_loop_ioctl: invalid cmd 0x%x", cmd);
1062744Sgs150176 		return (IOC_INVAL);
1063744Sgs150176 
1064744Sgs150176 	case LB_GET_INFO_SIZE:
1065744Sgs150176 		if (iocp->ioc_count != sizeof (lb_info_sz_t))
1066744Sgs150176 			return (IOC_INVAL);
1067744Sgs150176 		lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr;
1068744Sgs150176 		*lbsp = sizeof (loopmodes);
1069744Sgs150176 		return (IOC_REPLY);
1070744Sgs150176 
1071744Sgs150176 	case LB_GET_INFO:
1072744Sgs150176 		if (iocp->ioc_count != sizeof (loopmodes))
1073744Sgs150176 			return (IOC_INVAL);
1074744Sgs150176 		lbpp = (lb_property_t *)mp->b_cont->b_rptr;
1075744Sgs150176 		bcopy(loopmodes, lbpp, sizeof (loopmodes));
1076744Sgs150176 		return (IOC_REPLY);
1077744Sgs150176 
1078744Sgs150176 	case LB_GET_MODE:
1079744Sgs150176 		if (iocp->ioc_count != sizeof (uint32_t))
1080744Sgs150176 			return (IOC_INVAL);
1081744Sgs150176 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
1082744Sgs150176 		*lbmp = rgep->param_loop_mode;
1083744Sgs150176 		return (IOC_REPLY);
1084744Sgs150176 
1085744Sgs150176 	case LB_SET_MODE:
1086744Sgs150176 		if (iocp->ioc_count != sizeof (uint32_t))
1087744Sgs150176 			return (IOC_INVAL);
1088744Sgs150176 		lbmp = (uint32_t *)mp->b_cont->b_rptr;
1089744Sgs150176 		return (rge_set_loop_mode(rgep, *lbmp));
1090744Sgs150176 	}
1091744Sgs150176 }
1092744Sgs150176 
1093744Sgs150176 /*
1094744Sgs150176  * Specific rge IOCTLs, the MAC layer handles the generic ones.
1095744Sgs150176  */
1096744Sgs150176 static void
1097744Sgs150176 rge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1098744Sgs150176 {
1099744Sgs150176 	rge_t *rgep = arg;
1100744Sgs150176 	struct iocblk *iocp;
1101744Sgs150176 	enum ioc_reply status;
1102744Sgs150176 	boolean_t need_privilege;
1103744Sgs150176 	int err;
1104744Sgs150176 	int cmd;
1105744Sgs150176 
1106744Sgs150176 	/*
1107*6764Smx205022 	 * If suspended, we might actually be able to do some of
1108*6764Smx205022 	 * these ioctls, but it is harder to make sure they occur
1109*6764Smx205022 	 * without actually putting the hardware in an undesireable
1110*6764Smx205022 	 * state.  So just NAK it.
1111*6764Smx205022 	 */
1112*6764Smx205022 	mutex_enter(rgep->genlock);
1113*6764Smx205022 	if (rgep->suspended) {
1114*6764Smx205022 		miocnak(wq, mp, 0, EINVAL);
1115*6764Smx205022 		mutex_exit(rgep->genlock);
1116*6764Smx205022 		return;
1117*6764Smx205022 	}
1118*6764Smx205022 	mutex_exit(rgep->genlock);
1119*6764Smx205022 
1120*6764Smx205022 	/*
1121744Sgs150176 	 * Validate the command before bothering with the mutex ...
1122744Sgs150176 	 */
1123744Sgs150176 	iocp = (struct iocblk *)mp->b_rptr;
1124744Sgs150176 	iocp->ioc_error = 0;
1125744Sgs150176 	need_privilege = B_TRUE;
1126744Sgs150176 	cmd = iocp->ioc_cmd;
1127744Sgs150176 	switch (cmd) {
1128744Sgs150176 	default:
1129744Sgs150176 		miocnak(wq, mp, 0, EINVAL);
1130744Sgs150176 		return;
1131744Sgs150176 
1132744Sgs150176 	case RGE_MII_READ:
1133744Sgs150176 	case RGE_MII_WRITE:
1134744Sgs150176 	case RGE_DIAG:
1135744Sgs150176 	case RGE_PEEK:
1136744Sgs150176 	case RGE_POKE:
1137744Sgs150176 	case RGE_PHY_RESET:
1138744Sgs150176 	case RGE_SOFT_RESET:
1139744Sgs150176 	case RGE_HARD_RESET:
1140744Sgs150176 		break;
1141744Sgs150176 
1142744Sgs150176 	case LB_GET_INFO_SIZE:
1143744Sgs150176 	case LB_GET_INFO:
1144744Sgs150176 	case LB_GET_MODE:
1145744Sgs150176 		need_privilege = B_FALSE;
1146744Sgs150176 		/* FALLTHRU */
1147744Sgs150176 	case LB_SET_MODE:
1148744Sgs150176 		break;
1149744Sgs150176 
1150744Sgs150176 	case ND_GET:
1151744Sgs150176 		need_privilege = B_FALSE;
1152744Sgs150176 		/* FALLTHRU */
1153744Sgs150176 	case ND_SET:
1154744Sgs150176 		break;
1155744Sgs150176 	}
1156744Sgs150176 
1157744Sgs150176 	if (need_privilege) {
1158744Sgs150176 		/*
11592544Sgs150176 		 * Check for specific net_config privilege
1160744Sgs150176 		 */
11612544Sgs150176 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1162744Sgs150176 		if (err != 0) {
1163744Sgs150176 			miocnak(wq, mp, 0, err);
1164744Sgs150176 			return;
1165744Sgs150176 		}
1166744Sgs150176 	}
1167744Sgs150176 
1168744Sgs150176 	mutex_enter(rgep->genlock);
1169744Sgs150176 
1170744Sgs150176 	switch (cmd) {
1171744Sgs150176 	default:
1172744Sgs150176 		_NOTE(NOTREACHED)
1173744Sgs150176 		status = IOC_INVAL;
1174744Sgs150176 		break;
1175744Sgs150176 
1176744Sgs150176 	case RGE_MII_READ:
1177744Sgs150176 	case RGE_MII_WRITE:
1178744Sgs150176 	case RGE_DIAG:
1179744Sgs150176 	case RGE_PEEK:
1180744Sgs150176 	case RGE_POKE:
1181744Sgs150176 	case RGE_PHY_RESET:
1182744Sgs150176 	case RGE_SOFT_RESET:
1183744Sgs150176 	case RGE_HARD_RESET:
1184744Sgs150176 		status = rge_chip_ioctl(rgep, wq, mp, iocp);
1185744Sgs150176 		break;
1186744Sgs150176 
1187744Sgs150176 	case LB_GET_INFO_SIZE:
1188744Sgs150176 	case LB_GET_INFO:
1189744Sgs150176 	case LB_GET_MODE:
1190744Sgs150176 	case LB_SET_MODE:
1191744Sgs150176 		status = rge_loop_ioctl(rgep, wq, mp, iocp);
1192744Sgs150176 		break;
1193744Sgs150176 
1194744Sgs150176 	case ND_GET:
1195744Sgs150176 	case ND_SET:
1196744Sgs150176 		status = rge_nd_ioctl(rgep, wq, mp, iocp);
1197744Sgs150176 		break;
1198744Sgs150176 	}
1199744Sgs150176 
1200744Sgs150176 	/*
1201744Sgs150176 	 * Do we need to reprogram the PHY and/or the MAC?
1202744Sgs150176 	 * Do it now, while we still have the mutex.
1203744Sgs150176 	 *
1204744Sgs150176 	 * Note: update the PHY first, 'cos it controls the
1205744Sgs150176 	 * speed/duplex parameters that the MAC code uses.
1206744Sgs150176 	 */
1207744Sgs150176 	switch (status) {
1208744Sgs150176 	case IOC_RESTART_REPLY:
1209744Sgs150176 	case IOC_RESTART_ACK:
1210744Sgs150176 		rge_phy_update(rgep);
1211744Sgs150176 		break;
1212744Sgs150176 	}
1213744Sgs150176 
1214744Sgs150176 	mutex_exit(rgep->genlock);
1215744Sgs150176 
1216744Sgs150176 	/*
1217744Sgs150176 	 * Finally, decide how to reply
1218744Sgs150176 	 */
1219744Sgs150176 	switch (status) {
1220744Sgs150176 	default:
1221744Sgs150176 	case IOC_INVAL:
1222744Sgs150176 		/*
1223744Sgs150176 		 * Error, reply with a NAK and EINVAL or the specified error
1224744Sgs150176 		 */
1225744Sgs150176 		miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
12265107Seota 		    EINVAL : iocp->ioc_error);
1227744Sgs150176 		break;
1228744Sgs150176 
1229744Sgs150176 	case IOC_DONE:
1230744Sgs150176 		/*
1231744Sgs150176 		 * OK, reply already sent
1232744Sgs150176 		 */
1233744Sgs150176 		break;
1234744Sgs150176 
1235744Sgs150176 	case IOC_RESTART_ACK:
1236744Sgs150176 	case IOC_ACK:
1237744Sgs150176 		/*
1238744Sgs150176 		 * OK, reply with an ACK
1239744Sgs150176 		 */
1240744Sgs150176 		miocack(wq, mp, 0, 0);
1241744Sgs150176 		break;
1242744Sgs150176 
1243744Sgs150176 	case IOC_RESTART_REPLY:
1244744Sgs150176 	case IOC_REPLY:
1245744Sgs150176 		/*
1246744Sgs150176 		 * OK, send prepared reply as ACK or NAK
1247744Sgs150176 		 */
1248744Sgs150176 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
12495107Seota 		    M_IOCACK : M_IOCNAK;
1250744Sgs150176 		qreply(wq, mp);
1251744Sgs150176 		break;
1252744Sgs150176 	}
1253744Sgs150176 }
1254744Sgs150176 
1255744Sgs150176 static void
1256744Sgs150176 rge_m_resources(void *arg)
1257744Sgs150176 {
1258744Sgs150176 	rge_t *rgep = arg;
1259744Sgs150176 	mac_rx_fifo_t mrf;
1260744Sgs150176 
1261744Sgs150176 	mutex_enter(rgep->genlock);
1262744Sgs150176 
1263744Sgs150176 	/*
1264744Sgs150176 	 * Register Rx rings as resources and save mac
1265744Sgs150176 	 * resource id for future reference
1266744Sgs150176 	 */
1267744Sgs150176 	mrf.mrf_type = MAC_RX_FIFO;
1268744Sgs150176 	mrf.mrf_blank = rge_chip_blank;
1269744Sgs150176 	mrf.mrf_arg = (void *)rgep;
1270744Sgs150176 	mrf.mrf_normal_blank_time = RGE_RX_INT_TIME;
1271744Sgs150176 	mrf.mrf_normal_pkt_count = RGE_RX_INT_PKTS;
12722311Sseb 	rgep->handle = mac_resource_add(rgep->mh, (mac_resource_t *)&mrf);
1273744Sgs150176 
1274744Sgs150176 	mutex_exit(rgep->genlock);
1275744Sgs150176 }
1276744Sgs150176 
12772311Sseb /* ARGSUSED */
12782311Sseb static boolean_t
12792311Sseb rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
12802311Sseb {
12812311Sseb 	switch (cap) {
12822311Sseb 	case MAC_CAPAB_HCKSUM: {
12832311Sseb 		uint32_t *hcksum_txflags = cap_data;
12842311Sseb 		*hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
12852311Sseb 		break;
12862311Sseb 	}
12872311Sseb 	case MAC_CAPAB_POLL:
12882311Sseb 		/*
12892311Sseb 		 * There's nothing for us to fill in, simply returning
12902311Sseb 		 * B_TRUE stating that we support polling is sufficient.
12912311Sseb 		 */
12922311Sseb 		break;
12932311Sseb 	default:
12942311Sseb 		return (B_FALSE);
12952311Sseb 	}
12962311Sseb 	return (B_TRUE);
12972311Sseb }
12982311Sseb 
1299744Sgs150176 /*
13002544Sgs150176  * ============ Init MSI/Fixed Interrupt routines ==============
13012544Sgs150176  */
13022544Sgs150176 
13032544Sgs150176 /*
13042544Sgs150176  * rge_add_intrs:
13052544Sgs150176  *
13062544Sgs150176  * Register FIXED or MSI interrupts.
13072544Sgs150176  */
13082544Sgs150176 static int
13092544Sgs150176 rge_add_intrs(rge_t *rgep, int intr_type)
13102544Sgs150176 {
13112544Sgs150176 	dev_info_t *dip = rgep->devinfo;
13122544Sgs150176 	int avail;
13132544Sgs150176 	int actual;
13142544Sgs150176 	int intr_size;
13152544Sgs150176 	int count;
13162544Sgs150176 	int i, j;
13172544Sgs150176 	int ret;
13182544Sgs150176 
13192544Sgs150176 	/* Get number of interrupts */
13202544Sgs150176 	ret = ddi_intr_get_nintrs(dip, intr_type, &count);
13212544Sgs150176 	if ((ret != DDI_SUCCESS) || (count == 0)) {
13222544Sgs150176 		rge_error(rgep, "ddi_intr_get_nintrs() failure, ret: %d, "
13232544Sgs150176 		    "count: %d", ret, count);
13242544Sgs150176 		return (DDI_FAILURE);
13252544Sgs150176 	}
13262544Sgs150176 
13272544Sgs150176 	/* Get number of available interrupts */
13282544Sgs150176 	ret = ddi_intr_get_navail(dip, intr_type, &avail);
13292544Sgs150176 	if ((ret != DDI_SUCCESS) || (avail == 0)) {
13302544Sgs150176 		rge_error(rgep, "ddi_intr_get_navail() failure, "
13312544Sgs150176 		    "ret: %d, avail: %d\n", ret, avail);
13322544Sgs150176 		return (DDI_FAILURE);
13332544Sgs150176 	}
13342544Sgs150176 
13352544Sgs150176 	/* Allocate an array of interrupt handles */
13362544Sgs150176 	intr_size = count * sizeof (ddi_intr_handle_t);
13372544Sgs150176 	rgep->htable = kmem_alloc(intr_size, KM_SLEEP);
13382544Sgs150176 	rgep->intr_rqst = count;
13392544Sgs150176 
13402544Sgs150176 	/* Call ddi_intr_alloc() */
13412544Sgs150176 	ret = ddi_intr_alloc(dip, rgep->htable, intr_type, 0,
13422544Sgs150176 	    count, &actual, DDI_INTR_ALLOC_NORMAL);
13432544Sgs150176 	if (ret != DDI_SUCCESS || actual == 0) {
13442544Sgs150176 		rge_error(rgep, "ddi_intr_alloc() failed %d\n", ret);
13452544Sgs150176 		kmem_free(rgep->htable, intr_size);
13462544Sgs150176 		return (DDI_FAILURE);
13472544Sgs150176 	}
13482544Sgs150176 	if (actual < count) {
13492544Sgs150176 		rge_log(rgep, "ddi_intr_alloc() Requested: %d, Received: %d\n",
13502544Sgs150176 		    count, actual);
13512544Sgs150176 	}
13522544Sgs150176 	rgep->intr_cnt = actual;
13532544Sgs150176 
13542544Sgs150176 	/*
13552544Sgs150176 	 * Get priority for first msi, assume remaining are all the same
13562544Sgs150176 	 */
13572544Sgs150176 	if ((ret = ddi_intr_get_pri(rgep->htable[0], &rgep->intr_pri)) !=
13582544Sgs150176 	    DDI_SUCCESS) {
13592544Sgs150176 		rge_error(rgep, "ddi_intr_get_pri() failed %d\n", ret);
13602544Sgs150176 		/* Free already allocated intr */
13612544Sgs150176 		for (i = 0; i < actual; i++) {
13622544Sgs150176 			(void) ddi_intr_free(rgep->htable[i]);
13632544Sgs150176 		}
13642544Sgs150176 		kmem_free(rgep->htable, intr_size);
13652544Sgs150176 		return (DDI_FAILURE);
13662544Sgs150176 	}
13672544Sgs150176 
13682544Sgs150176 	/* Test for high level mutex */
13692544Sgs150176 	if (rgep->intr_pri >= ddi_intr_get_hilevel_pri()) {
13702544Sgs150176 		rge_error(rgep, "rge_add_intrs:"
13712544Sgs150176 		    "Hi level interrupt not supported");
13722544Sgs150176 		for (i = 0; i < actual; i++)
13732544Sgs150176 			(void) ddi_intr_free(rgep->htable[i]);
13742544Sgs150176 		kmem_free(rgep->htable, intr_size);
13752544Sgs150176 		return (DDI_FAILURE);
13762544Sgs150176 	}
13772544Sgs150176 
13782544Sgs150176 	/* Call ddi_intr_add_handler() */
13792544Sgs150176 	for (i = 0; i < actual; i++) {
13802544Sgs150176 		if ((ret = ddi_intr_add_handler(rgep->htable[i], rge_intr,
13812544Sgs150176 		    (caddr_t)rgep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
13822544Sgs150176 			rge_error(rgep, "ddi_intr_add_handler() "
13832544Sgs150176 			    "failed %d\n", ret);
13842544Sgs150176 			/* Remove already added intr */
13852544Sgs150176 			for (j = 0; j < i; j++)
13862544Sgs150176 				(void) ddi_intr_remove_handler(rgep->htable[j]);
13872544Sgs150176 			/* Free already allocated intr */
13882544Sgs150176 			for (i = 0; i < actual; i++) {
13892544Sgs150176 				(void) ddi_intr_free(rgep->htable[i]);
13902544Sgs150176 			}
13912544Sgs150176 			kmem_free(rgep->htable, intr_size);
13922544Sgs150176 			return (DDI_FAILURE);
13932544Sgs150176 		}
13942544Sgs150176 	}
13952544Sgs150176 
13962544Sgs150176 	if ((ret = ddi_intr_get_cap(rgep->htable[0], &rgep->intr_cap))
13972544Sgs150176 	    != DDI_SUCCESS) {
13982544Sgs150176 		rge_error(rgep, "ddi_intr_get_cap() failed %d\n", ret);
13992544Sgs150176 		for (i = 0; i < actual; i++) {
14002544Sgs150176 			(void) ddi_intr_remove_handler(rgep->htable[i]);
14012544Sgs150176 			(void) ddi_intr_free(rgep->htable[i]);
14022544Sgs150176 		}
14032544Sgs150176 		kmem_free(rgep->htable, intr_size);
14042544Sgs150176 		return (DDI_FAILURE);
14052544Sgs150176 	}
14062544Sgs150176 
14072544Sgs150176 	return (DDI_SUCCESS);
14082544Sgs150176 }
14092544Sgs150176 
14102544Sgs150176 /*
14112544Sgs150176  * rge_rem_intrs:
14122544Sgs150176  *
14132544Sgs150176  * Unregister FIXED or MSI interrupts
14142544Sgs150176  */
14152544Sgs150176 static void
14162544Sgs150176 rge_rem_intrs(rge_t *rgep)
14172544Sgs150176 {
14182544Sgs150176 	int i;
14192544Sgs150176 
14202544Sgs150176 	/* Disable all interrupts */
14212544Sgs150176 	if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
14222544Sgs150176 		/* Call ddi_intr_block_disable() */
14232544Sgs150176 		(void) ddi_intr_block_disable(rgep->htable, rgep->intr_cnt);
14242544Sgs150176 	} else {
14252544Sgs150176 		for (i = 0; i < rgep->intr_cnt; i++) {
14262544Sgs150176 			(void) ddi_intr_disable(rgep->htable[i]);
14272544Sgs150176 		}
14282544Sgs150176 	}
14292544Sgs150176 
14302544Sgs150176 	/* Call ddi_intr_remove_handler() */
14312544Sgs150176 	for (i = 0; i < rgep->intr_cnt; i++) {
14322544Sgs150176 		(void) ddi_intr_remove_handler(rgep->htable[i]);
14332544Sgs150176 		(void) ddi_intr_free(rgep->htable[i]);
14342544Sgs150176 	}
14352544Sgs150176 
14362544Sgs150176 	kmem_free(rgep->htable, rgep->intr_rqst * sizeof (ddi_intr_handle_t));
14372544Sgs150176 }
14382544Sgs150176 
14392544Sgs150176 /*
1440744Sgs150176  * ========== Per-instance setup/teardown code ==========
1441744Sgs150176  */
1442744Sgs150176 
1443744Sgs150176 #undef	RGE_DBG
1444744Sgs150176 #define	RGE_DBG		RGE_DBG_INIT	/* debug flag for this code	*/
1445744Sgs150176 
1446744Sgs150176 static void
1447744Sgs150176 rge_unattach(rge_t *rgep)
1448744Sgs150176 {
1449744Sgs150176 	/*
1450744Sgs150176 	 * Flag that no more activity may be initiated
1451744Sgs150176 	 */
1452744Sgs150176 	rgep->progress &= ~PROGRESS_READY;
1453744Sgs150176 	rgep->rge_mac_state = RGE_MAC_UNATTACH;
1454744Sgs150176 
1455744Sgs150176 	/*
1456744Sgs150176 	 * Quiesce the PHY and MAC (leave it reset but still powered).
1457744Sgs150176 	 * Clean up and free all RGE data structures
1458744Sgs150176 	 */
14595107Seota 	if (rgep->periodic_id != NULL) {
14605107Seota 		ddi_periodic_delete(rgep->periodic_id);
14615107Seota 		rgep->periodic_id = NULL;
1462744Sgs150176 	}
1463744Sgs150176 
1464744Sgs150176 	if (rgep->progress & PROGRESS_KSTATS)
1465744Sgs150176 		rge_fini_kstats(rgep);
1466744Sgs150176 
1467744Sgs150176 	if (rgep->progress & PROGRESS_PHY)
1468744Sgs150176 		(void) rge_phy_reset(rgep);
1469744Sgs150176 
14702544Sgs150176 	if (rgep->progress & PROGRESS_INIT) {
1471744Sgs150176 		mutex_enter(rgep->genlock);
1472744Sgs150176 		(void) rge_chip_reset(rgep);
1473744Sgs150176 		mutex_exit(rgep->genlock);
1474744Sgs150176 		rge_fini_rings(rgep);
14752544Sgs150176 	}
14762544Sgs150176 
14772544Sgs150176 	if (rgep->progress & PROGRESS_INTR) {
14782544Sgs150176 		rge_rem_intrs(rgep);
1479744Sgs150176 		mutex_destroy(rgep->rc_lock);
1480744Sgs150176 		mutex_destroy(rgep->rx_lock);
1481744Sgs150176 		mutex_destroy(rgep->tc_lock);
1482744Sgs150176 		mutex_destroy(rgep->tx_lock);
1483744Sgs150176 		rw_destroy(rgep->errlock);
1484744Sgs150176 		mutex_destroy(rgep->genlock);
1485744Sgs150176 	}
1486744Sgs150176 
1487744Sgs150176 	if (rgep->progress & PROGRESS_FACTOTUM)
14882544Sgs150176 		(void) ddi_intr_remove_softint(rgep->factotum_hdl);
1489744Sgs150176 
1490744Sgs150176 	if (rgep->progress & PROGRESS_RESCHED)
14912544Sgs150176 		(void) ddi_intr_remove_softint(rgep->resched_hdl);
1492744Sgs150176 
1493744Sgs150176 	if (rgep->progress & PROGRESS_NDD)
1494744Sgs150176 		rge_nd_cleanup(rgep);
1495744Sgs150176 
14965735Smx205022 	rge_free_bufs(rgep);
14975735Smx205022 
1498744Sgs150176 	if (rgep->progress & PROGRESS_REGS)
1499744Sgs150176 		ddi_regs_map_free(&rgep->io_handle);
1500744Sgs150176 
1501744Sgs150176 	if (rgep->progress & PROGRESS_CFG)
1502744Sgs150176 		pci_config_teardown(&rgep->cfg_handle);
1503744Sgs150176 
1504744Sgs150176 	ddi_remove_minor_node(rgep->devinfo, NULL);
1505744Sgs150176 	kmem_free(rgep, sizeof (*rgep));
1506744Sgs150176 }
1507744Sgs150176 
1508744Sgs150176 static int
1509744Sgs150176 rge_resume(dev_info_t *devinfo)
1510744Sgs150176 {
1511744Sgs150176 	rge_t *rgep;			/* Our private data	*/
1512744Sgs150176 	chip_id_t *cidp;
1513744Sgs150176 	chip_id_t chipid;
1514744Sgs150176 
1515744Sgs150176 	rgep = ddi_get_driver_private(devinfo);
1516*6764Smx205022 
1517*6764Smx205022 	/*
1518*6764Smx205022 	 * If there are state inconsistancies, this is bad.  Returning
1519*6764Smx205022 	 * DDI_FAILURE here will eventually cause the machine to panic,
1520*6764Smx205022 	 * so it is best done here so that there is a possibility of
1521*6764Smx205022 	 * debugging the problem.
1522*6764Smx205022 	 */
1523744Sgs150176 	if (rgep == NULL)
1524*6764Smx205022 		cmn_err(CE_PANIC,
1525*6764Smx205022 		    "rge: ngep returned from ddi_get_driver_private was NULL");
1526744Sgs150176 
1527744Sgs150176 	/*
1528744Sgs150176 	 * Refuse to resume if the data structures aren't consistent
1529744Sgs150176 	 */
1530744Sgs150176 	if (rgep->devinfo != devinfo)
1531*6764Smx205022 		cmn_err(CE_PANIC,
1532*6764Smx205022 		    "rge: passed devinfo not the same as saved devinfo");
1533744Sgs150176 
1534744Sgs150176 	/*
1535744Sgs150176 	 * Read chip ID & set up config space command register(s)
1536744Sgs150176 	 * Refuse to resume if the chip has changed its identity!
1537744Sgs150176 	 */
1538744Sgs150176 	cidp = &rgep->chipid;
1539744Sgs150176 	rge_chip_cfg_init(rgep, &chipid);
1540744Sgs150176 	if (chipid.vendor != cidp->vendor)
1541744Sgs150176 		return (DDI_FAILURE);
1542744Sgs150176 	if (chipid.device != cidp->device)
1543744Sgs150176 		return (DDI_FAILURE);
1544744Sgs150176 	if (chipid.revision != cidp->revision)
1545744Sgs150176 		return (DDI_FAILURE);
1546744Sgs150176 
1547*6764Smx205022 	mutex_enter(rgep->genlock);
1548*6764Smx205022 
1549*6764Smx205022 	/*
1550*6764Smx205022 	 * Only in one case, this conditional branch can be executed: the port
1551*6764Smx205022 	 * hasn't been plumbed.
1552*6764Smx205022 	 */
1553*6764Smx205022 	if (rgep->suspended == B_FALSE) {
1554*6764Smx205022 		mutex_exit(rgep->genlock);
1555*6764Smx205022 		return (DDI_SUCCESS);
1556*6764Smx205022 	}
1557*6764Smx205022 	rgep->rge_mac_state = RGE_MAC_STARTED;
1558744Sgs150176 	/*
1559744Sgs150176 	 * All OK, reinitialise h/w & kick off NEMO scheduling
1560744Sgs150176 	 */
1561744Sgs150176 	rge_restart(rgep);
1562*6764Smx205022 	rgep->suspended = B_FALSE;
1563*6764Smx205022 
1564744Sgs150176 	mutex_exit(rgep->genlock);
1565*6764Smx205022 
1566744Sgs150176 	return (DDI_SUCCESS);
1567744Sgs150176 }
1568744Sgs150176 
1569744Sgs150176 
1570744Sgs150176 /*
1571744Sgs150176  * attach(9E) -- Attach a device to the system
1572744Sgs150176  *
1573744Sgs150176  * Called once for each board successfully probed.
1574744Sgs150176  */
1575744Sgs150176 static int
1576744Sgs150176 rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1577744Sgs150176 {
1578744Sgs150176 	rge_t *rgep;			/* Our private data	*/
15792311Sseb 	mac_register_t *macp;
1580744Sgs150176 	chip_id_t *cidp;
15812544Sgs150176 	int intr_types;
1582744Sgs150176 	caddr_t regs;
1583744Sgs150176 	int instance;
15842544Sgs150176 	int i;
1585744Sgs150176 	int err;
1586744Sgs150176 
1587744Sgs150176 	/*
1588744Sgs150176 	 * we don't support high level interrupts in the driver
1589744Sgs150176 	 */
1590744Sgs150176 	if (ddi_intr_hilevel(devinfo, 0) != 0) {
1591744Sgs150176 		cmn_err(CE_WARN,
1592744Sgs150176 		    "rge_attach -- unsupported high level interrupt");
1593744Sgs150176 		return (DDI_FAILURE);
1594744Sgs150176 	}
1595744Sgs150176 
1596744Sgs150176 	instance = ddi_get_instance(devinfo);
1597744Sgs150176 	RGE_GTRACE(("rge_attach($%p, %d) instance %d",
15985107Seota 	    (void *)devinfo, cmd, instance));
1599744Sgs150176 	RGE_BRKPT(NULL, "rge_attach");
1600744Sgs150176 
1601744Sgs150176 	switch (cmd) {
1602744Sgs150176 	default:
1603744Sgs150176 		return (DDI_FAILURE);
1604744Sgs150176 
1605744Sgs150176 	case DDI_RESUME:
1606744Sgs150176 		return (rge_resume(devinfo));
1607744Sgs150176 
1608744Sgs150176 	case DDI_ATTACH:
1609744Sgs150176 		break;
1610744Sgs150176 	}
1611744Sgs150176 
1612744Sgs150176 	rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP);
1613744Sgs150176 	ddi_set_driver_private(devinfo, rgep);
1614744Sgs150176 	rgep->devinfo = devinfo;
1615744Sgs150176 
1616744Sgs150176 	/*
1617744Sgs150176 	 * Initialize more fields in RGE private data
1618744Sgs150176 	 */
16192544Sgs150176 	rgep->rge_mac_state = RGE_MAC_ATTACH;
1620744Sgs150176 	rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16215107Seota 	    DDI_PROP_DONTPASS, debug_propname, rge_debug);
16222544Sgs150176 	rgep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16235107Seota 	    DDI_PROP_DONTPASS, mtu_propname, ETHERMTU);
16242544Sgs150176 	rgep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16255107Seota 	    DDI_PROP_DONTPASS, msi_propname, B_TRUE);
1626744Sgs150176 	(void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d",
16275107Seota 	    RGE_DRIVER_NAME, instance);
1628744Sgs150176 
1629744Sgs150176 	/*
1630744Sgs150176 	 * Map config space registers
1631744Sgs150176 	 * Read chip ID & set up config space command register(s)
1632744Sgs150176 	 *
1633744Sgs150176 	 * Note: this leaves the chip accessible by Memory Space
1634744Sgs150176 	 * accesses, but with interrupts and Bus Mastering off.
1635744Sgs150176 	 * This should ensure that nothing untoward will happen
1636744Sgs150176 	 * if it has been left active by the (net-)bootloader.
1637744Sgs150176 	 * We'll re-enable Bus Mastering once we've reset the chip,
1638744Sgs150176 	 * and allow interrupts only when everything else is set up.
1639744Sgs150176 	 */
1640744Sgs150176 	err = pci_config_setup(devinfo, &rgep->cfg_handle);
1641744Sgs150176 	if (err != DDI_SUCCESS) {
1642744Sgs150176 		rge_problem(rgep, "pci_config_setup() failed");
1643744Sgs150176 		goto attach_fail;
1644744Sgs150176 	}
1645744Sgs150176 	rgep->progress |= PROGRESS_CFG;
1646744Sgs150176 	cidp = &rgep->chipid;
1647744Sgs150176 	bzero(cidp, sizeof (*cidp));
1648744Sgs150176 	rge_chip_cfg_init(rgep, cidp);
1649744Sgs150176 
1650744Sgs150176 	/*
1651744Sgs150176 	 * Map operating registers
1652744Sgs150176 	 */
1653744Sgs150176 	err = ddi_regs_map_setup(devinfo, 1, &regs,
1654744Sgs150176 	    0, 0, &rge_reg_accattr, &rgep->io_handle);
1655744Sgs150176 	if (err != DDI_SUCCESS) {
1656744Sgs150176 		rge_problem(rgep, "ddi_regs_map_setup() failed");
1657744Sgs150176 		goto attach_fail;
1658744Sgs150176 	}
1659744Sgs150176 	rgep->io_regs = regs;
1660744Sgs150176 	rgep->progress |= PROGRESS_REGS;
1661744Sgs150176 
1662744Sgs150176 	/*
1663744Sgs150176 	 * Characterise the device, so we know its requirements.
1664744Sgs150176 	 * Then allocate the appropriate TX and RX descriptors & buffers.
1665744Sgs150176 	 */
1666744Sgs150176 	rge_chip_ident(rgep);
1667744Sgs150176 	err = rge_alloc_bufs(rgep);
1668744Sgs150176 	if (err != DDI_SUCCESS) {
1669744Sgs150176 		rge_problem(rgep, "DMA buffer allocation failed");
1670744Sgs150176 		goto attach_fail;
1671744Sgs150176 	}
1672744Sgs150176 
1673744Sgs150176 	/*
16745735Smx205022 	 * Register NDD-tweakable parameters
16755735Smx205022 	 */
16765735Smx205022 	if (rge_nd_init(rgep)) {
16775735Smx205022 		rge_problem(rgep, "rge_nd_init() failed");
16785735Smx205022 		goto attach_fail;
16795735Smx205022 	}
16805735Smx205022 	rgep->progress |= PROGRESS_NDD;
16815735Smx205022 
16825735Smx205022 	/*
1683744Sgs150176 	 * Add the softint handlers:
1684744Sgs150176 	 *
1685744Sgs150176 	 * Both of these handlers are used to avoid restrictions on the
1686744Sgs150176 	 * context and/or mutexes required for some operations.  In
1687744Sgs150176 	 * particular, the hardware interrupt handler and its subfunctions
1688744Sgs150176 	 * can detect a number of conditions that we don't want to handle
1689744Sgs150176 	 * in that context or with that set of mutexes held.  So, these
1690744Sgs150176 	 * softints are triggered instead:
1691744Sgs150176 	 *
1692744Sgs150176 	 * the <resched> softint is triggered if if we have previously
1693744Sgs150176 	 * had to refuse to send a packet because of resource shortage
1694744Sgs150176 	 * (we've run out of transmit buffers), but the send completion
1695744Sgs150176 	 * interrupt handler has now detected that more buffers have
1696744Sgs150176 	 * become available.
1697744Sgs150176 	 *
1698744Sgs150176 	 * the <factotum> is triggered if the h/w interrupt handler
1699744Sgs150176 	 * sees the <link state changed> or <error> bits in the status
1700744Sgs150176 	 * block.  It's also triggered periodically to poll the link
1701744Sgs150176 	 * state, just in case we aren't getting link status change
1702744Sgs150176 	 * interrupts ...
1703744Sgs150176 	 */
17042544Sgs150176 	err = ddi_intr_add_softint(devinfo, &rgep->resched_hdl,
17055107Seota 	    DDI_INTR_SOFTPRI_MIN, rge_reschedule, (caddr_t)rgep);
1706744Sgs150176 	if (err != DDI_SUCCESS) {
17072544Sgs150176 		rge_problem(rgep, "ddi_intr_add_softint() failed");
1708744Sgs150176 		goto attach_fail;
1709744Sgs150176 	}
1710744Sgs150176 	rgep->progress |= PROGRESS_RESCHED;
17112544Sgs150176 	err = ddi_intr_add_softint(devinfo, &rgep->factotum_hdl,
17125107Seota 	    DDI_INTR_SOFTPRI_MIN, rge_chip_factotum, (caddr_t)rgep);
1713744Sgs150176 	if (err != DDI_SUCCESS) {
17142544Sgs150176 		rge_problem(rgep, "ddi_intr_add_softint() failed");
1715744Sgs150176 		goto attach_fail;
1716744Sgs150176 	}
1717744Sgs150176 	rgep->progress |= PROGRESS_FACTOTUM;
1718744Sgs150176 
1719744Sgs150176 	/*
17202544Sgs150176 	 * Get supported interrupt types
1721744Sgs150176 	 */
17222544Sgs150176 	if (ddi_intr_get_supported_types(devinfo, &intr_types)
17232544Sgs150176 	    != DDI_SUCCESS) {
17242544Sgs150176 		rge_error(rgep, "ddi_intr_get_supported_types failed\n");
1725744Sgs150176 		goto attach_fail;
1726744Sgs150176 	}
17272544Sgs150176 
17282544Sgs150176 	/*
17292544Sgs150176 	 * Add the h/w interrupt handler and initialise mutexes
1730*6764Smx205022 	 * RTL8101E is observed to have MSI invalidation issue after S/R.
1731*6764Smx205022 	 * So the FIXED interrupt is used instead.
17322544Sgs150176 	 */
1733*6764Smx205022 	if (rgep->chipid.mac_ver == MAC_VER_8101E)
1734*6764Smx205022 		rgep->msi_enable = B_FALSE;
17352544Sgs150176 	if ((intr_types & DDI_INTR_TYPE_MSI) && rgep->msi_enable) {
17362544Sgs150176 		if (rge_add_intrs(rgep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) {
17372544Sgs150176 			rge_error(rgep, "MSI registration failed, "
17382544Sgs150176 			    "trying FIXED interrupt type\n");
17392544Sgs150176 		} else {
17402544Sgs150176 			rge_log(rgep, "Using MSI interrupt type\n");
17412544Sgs150176 			rgep->intr_type = DDI_INTR_TYPE_MSI;
17422544Sgs150176 			rgep->progress |= PROGRESS_INTR;
17432544Sgs150176 		}
17442544Sgs150176 	}
17452544Sgs150176 	if (!(rgep->progress & PROGRESS_INTR) &&
17462544Sgs150176 	    (intr_types & DDI_INTR_TYPE_FIXED)) {
17472544Sgs150176 		if (rge_add_intrs(rgep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) {
17482544Sgs150176 			rge_error(rgep, "FIXED interrupt "
17492544Sgs150176 			    "registration failed\n");
17502544Sgs150176 			goto attach_fail;
17512544Sgs150176 		}
17522544Sgs150176 		rge_log(rgep, "Using FIXED interrupt type\n");
17532544Sgs150176 		rgep->intr_type = DDI_INTR_TYPE_FIXED;
17542544Sgs150176 		rgep->progress |= PROGRESS_INTR;
17552544Sgs150176 	}
17562544Sgs150176 	if (!(rgep->progress & PROGRESS_INTR)) {
17572544Sgs150176 		rge_error(rgep, "No interrupts registered\n");
17582544Sgs150176 		goto attach_fail;
17592544Sgs150176 	}
17602544Sgs150176 	mutex_init(rgep->genlock, NULL, MUTEX_DRIVER,
17612544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
17622544Sgs150176 	rw_init(rgep->errlock, NULL, RW_DRIVER,
17632544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
17642544Sgs150176 	mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER,
17652544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
17662544Sgs150176 	mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER,
17672544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
17682544Sgs150176 	mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER,
17692544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
17702544Sgs150176 	mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER,
17712544Sgs150176 	    DDI_INTR_PRI(rgep->intr_pri));
1772744Sgs150176 
1773744Sgs150176 	/*
1774744Sgs150176 	 * Initialize rings
1775744Sgs150176 	 */
1776744Sgs150176 	err = rge_init_rings(rgep);
1777744Sgs150176 	if (err != DDI_SUCCESS) {
1778744Sgs150176 		rge_problem(rgep, "rge_init_rings() failed");
1779744Sgs150176 		goto attach_fail;
1780744Sgs150176 	}
17812544Sgs150176 	rgep->progress |= PROGRESS_INIT;
17822544Sgs150176 
17832544Sgs150176 	/*
17842544Sgs150176 	 * Now that mutex locks are initialized, enable interrupts.
17852544Sgs150176 	 */
17862544Sgs150176 	if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
17872544Sgs150176 		/* Call ddi_intr_block_enable() for MSI interrupts */
17882544Sgs150176 		(void) ddi_intr_block_enable(rgep->htable, rgep->intr_cnt);
17892544Sgs150176 	} else {
17902544Sgs150176 		/* Call ddi_intr_enable for MSI or FIXED interrupts */
17912544Sgs150176 		for (i = 0; i < rgep->intr_cnt; i++) {
17922544Sgs150176 			(void) ddi_intr_enable(rgep->htable[i]);
17932544Sgs150176 		}
17942544Sgs150176 	}
1795744Sgs150176 
1796744Sgs150176 	/*
1797744Sgs150176 	 * Initialise link state variables
1798744Sgs150176 	 * Stop, reset & reinitialise the chip.
1799744Sgs150176 	 * Initialise the (internal) PHY.
1800744Sgs150176 	 */
1801744Sgs150176 	rgep->param_link_up = LINK_STATE_UNKNOWN;
1802744Sgs150176 
1803744Sgs150176 	/*
1804744Sgs150176 	 * Reset chip & rings to initial state; also reset address
1805744Sgs150176 	 * filtering, promiscuity, loopback mode.
1806744Sgs150176 	 */
1807744Sgs150176 	mutex_enter(rgep->genlock);
1808744Sgs150176 	(void) rge_chip_reset(rgep);
1809744Sgs150176 	rge_chip_sync(rgep, RGE_GET_MAC);
1810744Sgs150176 	bzero(rgep->mcast_hash, sizeof (rgep->mcast_hash));
1811744Sgs150176 	bzero(rgep->mcast_refs, sizeof (rgep->mcast_refs));
1812744Sgs150176 	rgep->promisc = B_FALSE;
1813744Sgs150176 	rgep->param_loop_mode = RGE_LOOP_NONE;
1814744Sgs150176 	mutex_exit(rgep->genlock);
1815744Sgs150176 	rge_phy_init(rgep);
1816744Sgs150176 	rgep->progress |= PROGRESS_PHY;
1817744Sgs150176 
1818744Sgs150176 	/*
1819744Sgs150176 	 * Create & initialise named kstats
1820744Sgs150176 	 */
1821744Sgs150176 	rge_init_kstats(rgep, instance);
1822744Sgs150176 	rgep->progress |= PROGRESS_KSTATS;
1823744Sgs150176 
18242311Sseb 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
18252311Sseb 		goto attach_fail;
18262311Sseb 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
18272311Sseb 	macp->m_driver = rgep;
1828744Sgs150176 	macp->m_dip = devinfo;
18292311Sseb 	macp->m_src_addr = rgep->netaddr;
18302311Sseb 	macp->m_callbacks = &rge_m_callbacks;
18312311Sseb 	macp->m_min_sdu = 0;
18322544Sgs150176 	macp->m_max_sdu = rgep->default_mtu;
18335895Syz147064 	macp->m_margin = VLAN_TAGSZ;
1834744Sgs150176 
1835744Sgs150176 	/*
1836744Sgs150176 	 * Finally, we're ready to register ourselves with the MAC layer
1837744Sgs150176 	 * interface; if this succeeds, we're all ready to start()
1838744Sgs150176 	 */
18392311Sseb 	err = mac_register(macp, &rgep->mh);
18402311Sseb 	mac_free(macp);
18412311Sseb 	if (err != 0)
1842744Sgs150176 		goto attach_fail;
1843744Sgs150176 
18445107Seota 	/*
18455107Seota 	 * Register a periodical handler.
18465107Seota 	 * reg_chip_cyclic() is invoked in kernel context.
18475107Seota 	 */
18485107Seota 	rgep->periodic_id = ddi_periodic_add(rge_chip_cyclic, rgep,
18495107Seota 	    RGE_CYCLIC_PERIOD, DDI_IPL_0);
1850744Sgs150176 
1851744Sgs150176 	rgep->progress |= PROGRESS_READY;
1852744Sgs150176 	return (DDI_SUCCESS);
1853744Sgs150176 
1854744Sgs150176 attach_fail:
1855744Sgs150176 	rge_unattach(rgep);
1856744Sgs150176 	return (DDI_FAILURE);
1857744Sgs150176 }
1858744Sgs150176 
1859744Sgs150176 /*
1860744Sgs150176  *	rge_suspend() -- suspend transmit/receive for powerdown
1861744Sgs150176  */
1862744Sgs150176 static int
1863744Sgs150176 rge_suspend(rge_t *rgep)
1864744Sgs150176 {
1865744Sgs150176 	/*
1866744Sgs150176 	 * Stop processing and idle (powerdown) the PHY ...
1867744Sgs150176 	 */
1868744Sgs150176 	mutex_enter(rgep->genlock);
1869*6764Smx205022 	rw_enter(rgep->errlock, RW_READER);
1870*6764Smx205022 
1871*6764Smx205022 	if (rgep->rge_mac_state != RGE_MAC_STARTED) {
1872*6764Smx205022 		mutex_exit(rgep->genlock);
1873*6764Smx205022 		return (DDI_SUCCESS);
1874*6764Smx205022 	}
1875*6764Smx205022 
1876*6764Smx205022 	rgep->suspended = B_TRUE;
1877744Sgs150176 	rge_stop(rgep);
1878*6764Smx205022 	rgep->rge_mac_state = RGE_MAC_STOPPED;
1879*6764Smx205022 
1880*6764Smx205022 	rw_exit(rgep->errlock);
1881744Sgs150176 	mutex_exit(rgep->genlock);
1882744Sgs150176 
1883744Sgs150176 	return (DDI_SUCCESS);
1884744Sgs150176 }
1885744Sgs150176 
1886744Sgs150176 /*
1887744Sgs150176  * detach(9E) -- Detach a device from the system
1888744Sgs150176  */
1889744Sgs150176 static int
1890744Sgs150176 rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1891744Sgs150176 {
1892744Sgs150176 	rge_t *rgep;
1893744Sgs150176 
1894744Sgs150176 	RGE_GTRACE(("rge_detach($%p, %d)", (void *)devinfo, cmd));
1895744Sgs150176 
1896744Sgs150176 	rgep = ddi_get_driver_private(devinfo);
1897744Sgs150176 
1898744Sgs150176 	switch (cmd) {
1899744Sgs150176 	default:
1900744Sgs150176 		return (DDI_FAILURE);
1901744Sgs150176 
1902744Sgs150176 	case DDI_SUSPEND:
1903744Sgs150176 		return (rge_suspend(rgep));
1904744Sgs150176 
1905744Sgs150176 	case DDI_DETACH:
1906744Sgs150176 		break;
1907744Sgs150176 	}
1908744Sgs150176 
1909744Sgs150176 	/*
1910744Sgs150176 	 * If there is any posted buffer, the driver should reject to be
1911744Sgs150176 	 * detached. Need notice upper layer to release them.
1912744Sgs150176 	 */
19132544Sgs150176 	if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) &&
19142544Sgs150176 	    rgep->rx_free != RGE_BUF_SLOTS)
1915744Sgs150176 		return (DDI_FAILURE);
1916744Sgs150176 
1917744Sgs150176 	/*
1918744Sgs150176 	 * Unregister from the MAC layer subsystem.  This can fail, in
1919744Sgs150176 	 * particular if there are DLPI style-2 streams still open -
1920744Sgs150176 	 * in which case we just return failure without shutting
1921744Sgs150176 	 * down chip operations.
1922744Sgs150176 	 */
19232311Sseb 	if (mac_unregister(rgep->mh) != 0)
1924744Sgs150176 		return (DDI_FAILURE);
1925744Sgs150176 
1926744Sgs150176 	/*
1927744Sgs150176 	 * All activity stopped, so we can clean up & exit
1928744Sgs150176 	 */
1929744Sgs150176 	rge_unattach(rgep);
1930744Sgs150176 	return (DDI_SUCCESS);
1931744Sgs150176 }
1932744Sgs150176 
1933744Sgs150176 
1934744Sgs150176 /*
1935744Sgs150176  * ========== Module Loading Data & Entry Points ==========
1936744Sgs150176  */
1937744Sgs150176 
1938744Sgs150176 #undef	RGE_DBG
1939744Sgs150176 #define	RGE_DBG		RGE_DBG_INIT	/* debug flag for this code	*/
1940744Sgs150176 DDI_DEFINE_STREAM_OPS(rge_dev_ops, nulldev, nulldev, rge_attach, rge_detach,
1941744Sgs150176     nodev, NULL, D_MP, NULL);
1942744Sgs150176 
1943744Sgs150176 static struct modldrv rge_modldrv = {
1944744Sgs150176 	&mod_driverops,		/* Type of module.  This one is a driver */
1945744Sgs150176 	rge_ident,		/* short description */
1946744Sgs150176 	&rge_dev_ops		/* driver specific ops */
1947744Sgs150176 };
1948744Sgs150176 
1949744Sgs150176 static struct modlinkage modlinkage = {
1950744Sgs150176 	MODREV_1, (void *)&rge_modldrv, NULL
1951744Sgs150176 };
1952744Sgs150176 
1953744Sgs150176 
1954744Sgs150176 int
1955744Sgs150176 _info(struct modinfo *modinfop)
1956744Sgs150176 {
1957744Sgs150176 	return (mod_info(&modlinkage, modinfop));
1958744Sgs150176 }
1959744Sgs150176 
1960744Sgs150176 int
1961744Sgs150176 _init(void)
1962744Sgs150176 {
1963744Sgs150176 	int status;
1964744Sgs150176 
1965744Sgs150176 	mac_init_ops(&rge_dev_ops, "rge");
1966744Sgs150176 	status = mod_install(&modlinkage);
1967744Sgs150176 	if (status == DDI_SUCCESS)
1968744Sgs150176 		mutex_init(rge_log_mutex, NULL, MUTEX_DRIVER, NULL);
1969744Sgs150176 	else
1970744Sgs150176 		mac_fini_ops(&rge_dev_ops);
1971744Sgs150176 
1972744Sgs150176 	return (status);
1973744Sgs150176 }
1974744Sgs150176 
1975744Sgs150176 int
1976744Sgs150176 _fini(void)
1977744Sgs150176 {
1978744Sgs150176 	int status;
1979744Sgs150176 
1980744Sgs150176 	status = mod_remove(&modlinkage);
1981744Sgs150176 	if (status == DDI_SUCCESS) {
1982744Sgs150176 		mac_fini_ops(&rge_dev_ops);
1983744Sgs150176 		mutex_destroy(rge_log_mutex);
1984744Sgs150176 	}
1985744Sgs150176 	return (status);
1986744Sgs150176 }
1987