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 /*
2211618SLi-Zhen.You@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23744Sgs150176 * Use is subject to license terms.
24744Sgs150176 */
25744Sgs150176
26744Sgs150176 #include "rge.h"
27744Sgs150176
28744Sgs150176 /*
29744Sgs150176 * This is the string displayed by modinfo, etc.
30744Sgs150176 * Make sure you keep the version ID up to date!
31744Sgs150176 */
327656SSherry.Moore@Sun.COM static char rge_ident[] = "Realtek 1Gb Ethernet";
33744Sgs150176
34744Sgs150176 /*
35744Sgs150176 * Used for buffers allocated by ddi_dma_mem_alloc()
36744Sgs150176 */
37744Sgs150176 static ddi_dma_attr_t dma_attr_buf = {
38744Sgs150176 DMA_ATTR_V0, /* dma_attr version */
39744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */
40744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */
41744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */
42744Sgs150176 (uint32_t)16, /* dma_attr_align */
43744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */
44744Sgs150176 1, /* dma_attr_minxfer */
45744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */
46744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */
47744Sgs150176 1, /* dma_attr_sgllen */
48744Sgs150176 1, /* dma_attr_granular */
49744Sgs150176 0, /* dma_attr_flags */
50744Sgs150176 };
51744Sgs150176
52744Sgs150176 /*
53744Sgs150176 * Used for BDs allocated by ddi_dma_mem_alloc()
54744Sgs150176 */
55744Sgs150176 static ddi_dma_attr_t dma_attr_desc = {
56744Sgs150176 DMA_ATTR_V0, /* dma_attr version */
57744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */
58744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */
59744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */
60744Sgs150176 (uint32_t)256, /* dma_attr_align */
61744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */
62744Sgs150176 1, /* dma_attr_minxfer */
63744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */
64744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */
65744Sgs150176 1, /* dma_attr_sgllen */
66744Sgs150176 1, /* dma_attr_granular */
67744Sgs150176 0, /* dma_attr_flags */
68744Sgs150176 };
69744Sgs150176
70744Sgs150176 /*
71744Sgs150176 * PIO access attributes for registers
72744Sgs150176 */
73744Sgs150176 static ddi_device_acc_attr_t rge_reg_accattr = {
74744Sgs150176 DDI_DEVICE_ATTR_V0,
75744Sgs150176 DDI_STRUCTURE_LE_ACC,
76744Sgs150176 DDI_STRICTORDER_ACC,
77744Sgs150176 DDI_DEFAULT_ACC
78744Sgs150176 };
79744Sgs150176
80744Sgs150176 /*
81744Sgs150176 * DMA access attributes for descriptors
82744Sgs150176 */
83744Sgs150176 static ddi_device_acc_attr_t rge_desc_accattr = {
84744Sgs150176 DDI_DEVICE_ATTR_V0,
85744Sgs150176 DDI_NEVERSWAP_ACC,
86744Sgs150176 DDI_STRICTORDER_ACC,
87744Sgs150176 DDI_DEFAULT_ACC
88744Sgs150176 };
89744Sgs150176
90744Sgs150176 /*
91744Sgs150176 * DMA access attributes for data
92744Sgs150176 */
93744Sgs150176 static ddi_device_acc_attr_t rge_buf_accattr = {
94744Sgs150176 DDI_DEVICE_ATTR_V0,
95744Sgs150176 DDI_NEVERSWAP_ACC,
96744Sgs150176 DDI_STRICTORDER_ACC,
97744Sgs150176 DDI_DEFAULT_ACC
98744Sgs150176 };
99744Sgs150176
100744Sgs150176 /*
101744Sgs150176 * Property names
102744Sgs150176 */
1032544Sgs150176 static char debug_propname[] = "rge_debug_flags";
1042544Sgs150176 static char mtu_propname[] = "default_mtu";
1052544Sgs150176 static char msi_propname[] = "msi_enable";
106744Sgs150176
1072311Sseb static int rge_m_start(void *);
1082311Sseb static void rge_m_stop(void *);
1092311Sseb static int rge_m_promisc(void *, boolean_t);
1102311Sseb static int rge_m_multicst(void *, boolean_t, const uint8_t *);
1112311Sseb static int rge_m_unicst(void *, const uint8_t *);
1122311Sseb static void rge_m_ioctl(void *, queue_t *, mblk_t *);
1132311Sseb static boolean_t rge_m_getcapab(void *, mac_capab_t, void *);
1142311Sseb
1158275SEric Cheng #define RGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
1162311Sseb
1172311Sseb static mac_callbacks_t rge_m_callbacks = {
1182311Sseb RGE_M_CALLBACK_FLAGS,
1192311Sseb rge_m_stat,
1202311Sseb rge_m_start,
1212311Sseb rge_m_stop,
1222311Sseb rge_m_promisc,
1232311Sseb rge_m_multicst,
1242311Sseb rge_m_unicst,
1252311Sseb rge_m_tx,
126*11878SVenu.Iyer@Sun.COM NULL,
1272311Sseb rge_m_ioctl,
1282311Sseb rge_m_getcapab
1292311Sseb };
130744Sgs150176
131744Sgs150176 /*
132744Sgs150176 * Allocate an area of memory and a DMA handle for accessing it
133744Sgs150176 */
134744Sgs150176 static int
rge_alloc_dma_mem(rge_t * rgep,size_t memsize,ddi_dma_attr_t * dma_attr_p,ddi_device_acc_attr_t * acc_attr_p,uint_t dma_flags,dma_area_t * dma_p)135744Sgs150176 rge_alloc_dma_mem(rge_t *rgep, size_t memsize, ddi_dma_attr_t *dma_attr_p,
136744Sgs150176 ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, dma_area_t *dma_p)
137744Sgs150176 {
138744Sgs150176 caddr_t vaddr;
139744Sgs150176 int err;
140744Sgs150176
141744Sgs150176 /*
142744Sgs150176 * Allocate handle
143744Sgs150176 */
144744Sgs150176 err = ddi_dma_alloc_handle(rgep->devinfo, dma_attr_p,
1455107Seota DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
146744Sgs150176 if (err != DDI_SUCCESS) {
147744Sgs150176 dma_p->dma_hdl = NULL;
148744Sgs150176 return (DDI_FAILURE);
149744Sgs150176 }
150744Sgs150176
151744Sgs150176 /*
152744Sgs150176 * Allocate memory
153744Sgs150176 */
154744Sgs150176 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
155744Sgs150176 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
156744Sgs150176 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
157744Sgs150176 if (err != DDI_SUCCESS) {
158744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl);
159744Sgs150176 dma_p->dma_hdl = NULL;
160744Sgs150176 dma_p->acc_hdl = NULL;
161744Sgs150176 return (DDI_FAILURE);
162744Sgs150176 }
163744Sgs150176
164744Sgs150176 /*
165744Sgs150176 * Bind the two together
166744Sgs150176 */
167744Sgs150176 dma_p->mem_va = vaddr;
168744Sgs150176 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
169744Sgs150176 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
170744Sgs150176 &dma_p->cookie, &dma_p->ncookies);
171744Sgs150176 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) {
172744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl);
173744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl);
174744Sgs150176 dma_p->acc_hdl = NULL;
175744Sgs150176 dma_p->dma_hdl = NULL;
176744Sgs150176 return (DDI_FAILURE);
177744Sgs150176 }
178744Sgs150176
179744Sgs150176 dma_p->nslots = ~0U;
180744Sgs150176 dma_p->size = ~0U;
181744Sgs150176 dma_p->token = ~0U;
182744Sgs150176 dma_p->offset = 0;
183744Sgs150176 return (DDI_SUCCESS);
184744Sgs150176 }
185744Sgs150176
186744Sgs150176 /*
187744Sgs150176 * Free one allocated area of DMAable memory
188744Sgs150176 */
189744Sgs150176 static void
rge_free_dma_mem(dma_area_t * dma_p)190744Sgs150176 rge_free_dma_mem(dma_area_t *dma_p)
191744Sgs150176 {
192744Sgs150176 if (dma_p->dma_hdl != NULL) {
193744Sgs150176 if (dma_p->ncookies) {
194744Sgs150176 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
195744Sgs150176 dma_p->ncookies = 0;
196744Sgs150176 }
197744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl);
198744Sgs150176 dma_p->dma_hdl = NULL;
199744Sgs150176 }
200744Sgs150176
201744Sgs150176 if (dma_p->acc_hdl != NULL) {
202744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl);
203744Sgs150176 dma_p->acc_hdl = NULL;
204744Sgs150176 }
205744Sgs150176 }
206744Sgs150176
207744Sgs150176 /*
208744Sgs150176 * Utility routine to carve a slice off a chunk of allocated memory,
209744Sgs150176 * updating the chunk descriptor accordingly. The size of the slice
210744Sgs150176 * is given by the product of the <qty> and <size> parameters.
211744Sgs150176 */
212744Sgs150176 static void
rge_slice_chunk(dma_area_t * slice,dma_area_t * chunk,uint32_t qty,uint32_t size)213744Sgs150176 rge_slice_chunk(dma_area_t *slice, dma_area_t *chunk,
214744Sgs150176 uint32_t qty, uint32_t size)
215744Sgs150176 {
216744Sgs150176 static uint32_t sequence = 0xbcd5704a;
217744Sgs150176 size_t totsize;
218744Sgs150176
219744Sgs150176 totsize = qty*size;
220744Sgs150176 ASSERT(totsize <= chunk->alength);
221744Sgs150176
222744Sgs150176 *slice = *chunk;
223744Sgs150176 slice->nslots = qty;
224744Sgs150176 slice->size = size;
225744Sgs150176 slice->alength = totsize;
226744Sgs150176 slice->token = ++sequence;
227744Sgs150176
228744Sgs150176 chunk->mem_va = (caddr_t)chunk->mem_va + totsize;
229744Sgs150176 chunk->alength -= totsize;
230744Sgs150176 chunk->offset += totsize;
231744Sgs150176 chunk->cookie.dmac_laddress += totsize;
232744Sgs150176 chunk->cookie.dmac_size -= totsize;
233744Sgs150176 }
234744Sgs150176
235744Sgs150176 static int
rge_alloc_bufs(rge_t * rgep)236744Sgs150176 rge_alloc_bufs(rge_t *rgep)
237744Sgs150176 {
238744Sgs150176 size_t txdescsize;
239744Sgs150176 size_t rxdescsize;
240744Sgs150176 int err;
241744Sgs150176
242744Sgs150176 /*
243744Sgs150176 * Allocate memory & handle for packet statistics
244744Sgs150176 */
245744Sgs150176 err = rge_alloc_dma_mem(rgep,
246744Sgs150176 RGE_STATS_DUMP_SIZE,
247744Sgs150176 &dma_attr_desc,
248744Sgs150176 &rge_desc_accattr,
249744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
250744Sgs150176 &rgep->dma_area_stats);
251744Sgs150176 if (err != DDI_SUCCESS)
252744Sgs150176 return (DDI_FAILURE);
253744Sgs150176 rgep->hw_stats = DMA_VPTR(rgep->dma_area_stats);
254744Sgs150176
255744Sgs150176 /*
256744Sgs150176 * Allocate memory & handle for Tx descriptor ring
257744Sgs150176 */
258744Sgs150176 txdescsize = RGE_SEND_SLOTS * sizeof (rge_bd_t);
259744Sgs150176 err = rge_alloc_dma_mem(rgep,
260744Sgs150176 txdescsize,
261744Sgs150176 &dma_attr_desc,
262744Sgs150176 &rge_desc_accattr,
263744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
264744Sgs150176 &rgep->dma_area_txdesc);
265744Sgs150176 if (err != DDI_SUCCESS)
266744Sgs150176 return (DDI_FAILURE);
267744Sgs150176
268744Sgs150176 /*
269744Sgs150176 * Allocate memory & handle for Rx descriptor ring
270744Sgs150176 */
271744Sgs150176 rxdescsize = RGE_RECV_SLOTS * sizeof (rge_bd_t);
272744Sgs150176 err = rge_alloc_dma_mem(rgep,
273744Sgs150176 rxdescsize,
274744Sgs150176 &dma_attr_desc,
275744Sgs150176 &rge_desc_accattr,
276744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
277744Sgs150176 &rgep->dma_area_rxdesc);
278744Sgs150176 if (err != DDI_SUCCESS)
279744Sgs150176 return (DDI_FAILURE);
280744Sgs150176
281744Sgs150176 return (DDI_SUCCESS);
282744Sgs150176 }
283744Sgs150176
284744Sgs150176 /*
285744Sgs150176 * rge_free_bufs() -- free descriptors/buffers allocated for this
286744Sgs150176 * device instance.
287744Sgs150176 */
288744Sgs150176 static void
rge_free_bufs(rge_t * rgep)289744Sgs150176 rge_free_bufs(rge_t *rgep)
290744Sgs150176 {
291744Sgs150176 rge_free_dma_mem(&rgep->dma_area_stats);
292744Sgs150176 rge_free_dma_mem(&rgep->dma_area_txdesc);
293744Sgs150176 rge_free_dma_mem(&rgep->dma_area_rxdesc);
294744Sgs150176 }
295744Sgs150176
296744Sgs150176 /*
297744Sgs150176 * ========== Transmit and receive ring reinitialisation ==========
298744Sgs150176 */
299744Sgs150176
300744Sgs150176 /*
301744Sgs150176 * These <reinit> routines each reset the rx/tx rings to an initial
302744Sgs150176 * state, assuming that the corresponding <init> routine has already
303744Sgs150176 * been called exactly once.
304744Sgs150176 */
305744Sgs150176 static void
rge_reinit_send_ring(rge_t * rgep)306744Sgs150176 rge_reinit_send_ring(rge_t *rgep)
307744Sgs150176 {
308744Sgs150176 sw_sbd_t *ssbdp;
309744Sgs150176 rge_bd_t *bdp;
310744Sgs150176 uint32_t slot;
311744Sgs150176
312744Sgs150176 /*
313744Sgs150176 * re-init send ring
314744Sgs150176 */
315744Sgs150176 DMA_ZERO(rgep->tx_desc);
316744Sgs150176 ssbdp = rgep->sw_sbds;
317744Sgs150176 bdp = rgep->tx_ring;
318744Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
319744Sgs150176 bdp->host_buf_addr =
320744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress);
321744Sgs150176 bdp->host_buf_addr_hi =
322744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress >> 32);
323744Sgs150176 /* last BD in Tx ring */
324744Sgs150176 if (slot == (RGE_SEND_SLOTS - 1))
325744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_EOR);
326744Sgs150176 ssbdp++;
327744Sgs150176 bdp++;
328744Sgs150176 }
329744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
330744Sgs150176 rgep->tx_next = 0;
331744Sgs150176 rgep->tc_next = 0;
332744Sgs150176 rgep->tc_tail = 0;
333744Sgs150176 rgep->tx_flow = 0;
334744Sgs150176 rgep->tx_free = RGE_SEND_SLOTS;
335744Sgs150176 }
336744Sgs150176
337744Sgs150176 static void
rge_reinit_recv_ring(rge_t * rgep)338744Sgs150176 rge_reinit_recv_ring(rge_t *rgep)
339744Sgs150176 {
340744Sgs150176 rge_bd_t *bdp;
341744Sgs150176 sw_rbd_t *srbdp;
342744Sgs150176 dma_area_t *pbuf;
343744Sgs150176 uint32_t slot;
344744Sgs150176
345744Sgs150176 /*
346744Sgs150176 * re-init receive ring
347744Sgs150176 */
348744Sgs150176 DMA_ZERO(rgep->rx_desc);
349744Sgs150176 srbdp = rgep->sw_rbds;
350744Sgs150176 bdp = rgep->rx_ring;
351744Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
352744Sgs150176 pbuf = &srbdp->rx_buf->pbuf;
353744Sgs150176 bdp->host_buf_addr =
3542544Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress + rgep->head_room);
355744Sgs150176 bdp->host_buf_addr_hi =
356744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32);
357744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN |
3582544Sgs150176 (rgep->rxbuf_size - rgep->head_room));
359744Sgs150176 /* last BD in Tx ring */
360744Sgs150176 if (slot == (RGE_RECV_SLOTS - 1))
361744Sgs150176 bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR);
362744Sgs150176 srbdp++;
363744Sgs150176 bdp++;
364744Sgs150176 }
365744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
366744Sgs150176 rgep->watchdog = 0;
367744Sgs150176 rgep->rx_next = 0;
368744Sgs150176 }
369744Sgs150176
370744Sgs150176 static void
rge_reinit_buf_ring(rge_t * rgep)371744Sgs150176 rge_reinit_buf_ring(rge_t *rgep)
372744Sgs150176 {
3732544Sgs150176
3742544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
3752544Sgs150176 return;
3762544Sgs150176
377744Sgs150176 /*
3782544Sgs150176 * If all the up-sending buffers haven't been returned to driver,
3792544Sgs150176 * use bcopy() only in rx process.
380744Sgs150176 */
381744Sgs150176 if (rgep->rx_free != RGE_BUF_SLOTS)
382744Sgs150176 rgep->rx_bcopy = B_TRUE;
383744Sgs150176 }
384744Sgs150176
385744Sgs150176 static void
rge_reinit_rings(rge_t * rgep)386744Sgs150176 rge_reinit_rings(rge_t *rgep)
387744Sgs150176 {
388744Sgs150176 rge_reinit_send_ring(rgep);
389744Sgs150176 rge_reinit_recv_ring(rgep);
390744Sgs150176 rge_reinit_buf_ring(rgep);
391744Sgs150176 }
392744Sgs150176
393744Sgs150176 static void
rge_fini_send_ring(rge_t * rgep)3942544Sgs150176 rge_fini_send_ring(rge_t *rgep)
3952544Sgs150176 {
3962544Sgs150176 sw_sbd_t *ssbdp;
3972544Sgs150176 uint32_t slot;
3982544Sgs150176
3992544Sgs150176 ssbdp = rgep->sw_sbds;
4002544Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; ++slot) {
4012544Sgs150176 rge_free_dma_mem(&ssbdp->pbuf);
4022544Sgs150176 ssbdp++;
4032544Sgs150176 }
4042544Sgs150176
4052544Sgs150176 kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t));
4062544Sgs150176 rgep->sw_sbds = NULL;
4072544Sgs150176 }
4082544Sgs150176
4092544Sgs150176 static void
rge_fini_recv_ring(rge_t * rgep)4102544Sgs150176 rge_fini_recv_ring(rge_t *rgep)
4112544Sgs150176 {
4122544Sgs150176 sw_rbd_t *srbdp;
4132544Sgs150176 uint32_t slot;
4142544Sgs150176
4152544Sgs150176 srbdp = rgep->sw_rbds;
4162544Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; ++srbdp, ++slot) {
4172544Sgs150176 if (srbdp->rx_buf) {
4182544Sgs150176 if (srbdp->rx_buf->mp != NULL) {
4192544Sgs150176 freemsg(srbdp->rx_buf->mp);
4202544Sgs150176 srbdp->rx_buf->mp = NULL;
4212544Sgs150176 }
4222544Sgs150176 rge_free_dma_mem(&srbdp->rx_buf->pbuf);
4232544Sgs150176 kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
4242544Sgs150176 srbdp->rx_buf = NULL;
4252544Sgs150176 }
4262544Sgs150176 }
4272544Sgs150176
4282544Sgs150176 kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t));
4292544Sgs150176 rgep->sw_rbds = NULL;
4302544Sgs150176 }
4312544Sgs150176
4322544Sgs150176 static void
rge_fini_buf_ring(rge_t * rgep)4332544Sgs150176 rge_fini_buf_ring(rge_t *rgep)
4342544Sgs150176 {
4352544Sgs150176 sw_rbd_t *srbdp;
4362544Sgs150176 uint32_t slot;
4372544Sgs150176
4382544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)
4392544Sgs150176 return;
4402544Sgs150176
4412544Sgs150176 ASSERT(rgep->rx_free == RGE_BUF_SLOTS);
4422544Sgs150176
4432544Sgs150176 srbdp = rgep->free_srbds;
4442544Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS; ++srbdp, ++slot) {
4452544Sgs150176 if (srbdp->rx_buf != NULL) {
4462544Sgs150176 if (srbdp->rx_buf->mp != NULL) {
4472544Sgs150176 freemsg(srbdp->rx_buf->mp);
4482544Sgs150176 srbdp->rx_buf->mp = NULL;
4492544Sgs150176 }
4502544Sgs150176 rge_free_dma_mem(&srbdp->rx_buf->pbuf);
4512544Sgs150176 kmem_free(srbdp->rx_buf, sizeof (dma_buf_t));
4522544Sgs150176 srbdp->rx_buf = NULL;
4532544Sgs150176 }
4542544Sgs150176 }
4552544Sgs150176
4562544Sgs150176 kmem_free(rgep->free_srbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t));
4572544Sgs150176 rgep->free_srbds = NULL;
4582544Sgs150176 }
4592544Sgs150176
4602544Sgs150176 static void
rge_fini_rings(rge_t * rgep)4612544Sgs150176 rge_fini_rings(rge_t *rgep)
4622544Sgs150176 {
4632544Sgs150176 rge_fini_send_ring(rgep);
4642544Sgs150176 rge_fini_recv_ring(rgep);
4652544Sgs150176 rge_fini_buf_ring(rgep);
4662544Sgs150176 }
4672544Sgs150176
4682544Sgs150176 static int
rge_init_send_ring(rge_t * rgep)469744Sgs150176 rge_init_send_ring(rge_t *rgep)
470744Sgs150176 {
471744Sgs150176 uint32_t slot;
472744Sgs150176 sw_sbd_t *ssbdp;
473744Sgs150176 dma_area_t *pbuf;
4742544Sgs150176 dma_area_t desc;
4752544Sgs150176 int err;
476744Sgs150176
477744Sgs150176 /*
478744Sgs150176 * Allocate the array of s/w Tx Buffer Descriptors
479744Sgs150176 */
480744Sgs150176 ssbdp = kmem_zalloc(RGE_SEND_SLOTS*sizeof (*ssbdp), KM_SLEEP);
481744Sgs150176 rgep->sw_sbds = ssbdp;
482744Sgs150176
483744Sgs150176 /*
484744Sgs150176 * Init send ring
485744Sgs150176 */
486744Sgs150176 rgep->tx_desc = rgep->dma_area_txdesc;
487744Sgs150176 DMA_ZERO(rgep->tx_desc);
4882544Sgs150176 rgep->tx_ring = rgep->tx_desc.mem_va;
4892544Sgs150176
4902544Sgs150176 desc = rgep->tx_desc;
4912544Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; slot++) {
4922544Sgs150176 rge_slice_chunk(&ssbdp->desc, &desc, 1, sizeof (rge_bd_t));
4932544Sgs150176
4942544Sgs150176 /*
4952544Sgs150176 * Allocate memory & handle for Tx buffers
4962544Sgs150176 */
4972544Sgs150176 pbuf = &ssbdp->pbuf;
4982544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->txbuf_size,
4992544Sgs150176 &dma_attr_buf, &rge_buf_accattr,
5002544Sgs150176 DDI_DMA_WRITE | DDI_DMA_STREAMING, pbuf);
5012544Sgs150176 if (err != DDI_SUCCESS) {
5022544Sgs150176 rge_error(rgep,
5032544Sgs150176 "rge_init_send_ring: alloc tx buffer failed");
5042544Sgs150176 rge_fini_send_ring(rgep);
5052544Sgs150176 return (DDI_FAILURE);
506744Sgs150176 }
5072544Sgs150176 ssbdp++;
508744Sgs150176 }
5092544Sgs150176 ASSERT(desc.alength == 0);
5102544Sgs150176
511744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV);
5122544Sgs150176 return (DDI_SUCCESS);
513744Sgs150176 }
514744Sgs150176
515744Sgs150176 static int
rge_init_recv_ring(rge_t * rgep)516744Sgs150176 rge_init_recv_ring(rge_t *rgep)
517744Sgs150176 {
518744Sgs150176 uint32_t slot;
519744Sgs150176 sw_rbd_t *srbdp;
520744Sgs150176 dma_buf_t *rx_buf;
521744Sgs150176 dma_area_t *pbuf;
5222544Sgs150176 int err;
523744Sgs150176
524744Sgs150176 /*
525744Sgs150176 * Allocate the array of s/w Rx Buffer Descriptors
526744Sgs150176 */
527744Sgs150176 srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP);
528744Sgs150176 rgep->sw_rbds = srbdp;
529744Sgs150176
530744Sgs150176 /*
531744Sgs150176 * Init receive ring
532744Sgs150176 */
533744Sgs150176 rgep->rx_next = 0;
534744Sgs150176 rgep->rx_desc = rgep->dma_area_rxdesc;
535744Sgs150176 DMA_ZERO(rgep->rx_desc);
5362544Sgs150176 rgep->rx_ring = rgep->rx_desc.mem_va;
5372544Sgs150176
5382544Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++) {
5392544Sgs150176 srbdp->rx_buf = rx_buf =
5402544Sgs150176 kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
5412544Sgs150176
5422544Sgs150176 /*
5432544Sgs150176 * Allocate memory & handle for Rx buffers
5442544Sgs150176 */
5452544Sgs150176 pbuf = &rx_buf->pbuf;
5462544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
5472544Sgs150176 &dma_attr_buf, &rge_buf_accattr,
5482544Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
5492544Sgs150176 if (err != DDI_SUCCESS) {
5502544Sgs150176 rge_fini_recv_ring(rgep);
5512544Sgs150176 rge_error(rgep,
5522544Sgs150176 "rge_init_recv_ring: alloc rx buffer failed");
5532544Sgs150176 return (DDI_FAILURE);
5542544Sgs150176 }
5552544Sgs150176
5562544Sgs150176 pbuf->alength -= rgep->head_room;
5572544Sgs150176 pbuf->offset += rgep->head_room;
5582544Sgs150176 if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)) {
559744Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle;
560744Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
561744Sgs150176 rx_buf->private = (caddr_t)rgep;
562744Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
563744Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
564744Sgs150176 if (rx_buf->mp == NULL) {
5652544Sgs150176 rge_fini_recv_ring(rgep);
566744Sgs150176 rge_problem(rgep,
567744Sgs150176 "rge_init_recv_ring: desballoc() failed");
568744Sgs150176 return (DDI_FAILURE);
569744Sgs150176 }
570744Sgs150176 }
5712544Sgs150176 srbdp++;
572744Sgs150176 }
573744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV);
574744Sgs150176 return (DDI_SUCCESS);
575744Sgs150176 }
576744Sgs150176
577744Sgs150176 static int
rge_init_buf_ring(rge_t * rgep)578744Sgs150176 rge_init_buf_ring(rge_t *rgep)
579744Sgs150176 {
580744Sgs150176 uint32_t slot;
5812544Sgs150176 sw_rbd_t *free_srbdp;
582744Sgs150176 dma_buf_t *rx_buf;
583744Sgs150176 dma_area_t *pbuf;
5842544Sgs150176 int err;
5852544Sgs150176
5862544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) {
5872544Sgs150176 rgep->rx_bcopy = B_TRUE;
5882544Sgs150176 return (DDI_SUCCESS);
5892544Sgs150176 }
590744Sgs150176
591744Sgs150176 /*
592744Sgs150176 * Allocate the array of s/w free Buffer Descriptors
593744Sgs150176 */
5942544Sgs150176 free_srbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_srbdp), KM_SLEEP);
5952544Sgs150176 rgep->free_srbds = free_srbdp;
596744Sgs150176
597744Sgs150176 /*
598744Sgs150176 * Init free buffer ring
599744Sgs150176 */
600744Sgs150176 rgep->rc_next = 0;
601744Sgs150176 rgep->rf_next = 0;
602744Sgs150176 rgep->rx_bcopy = B_FALSE;
603744Sgs150176 rgep->rx_free = RGE_BUF_SLOTS;
6042544Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS; slot++) {
6052544Sgs150176 free_srbdp->rx_buf = rx_buf =
6062544Sgs150176 kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP);
6072544Sgs150176
6082544Sgs150176 /*
6092544Sgs150176 * Allocate memory & handle for free Rx buffers
6102544Sgs150176 */
6112544Sgs150176 pbuf = &rx_buf->pbuf;
6122544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size,
6132544Sgs150176 &dma_attr_buf, &rge_buf_accattr,
6142544Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, pbuf);
6152544Sgs150176 if (err != DDI_SUCCESS) {
6162544Sgs150176 rge_fini_buf_ring(rgep);
6172544Sgs150176 rge_error(rgep,
6182544Sgs150176 "rge_init_buf_ring: alloc rx free buffer failed");
6192544Sgs150176 return (DDI_FAILURE);
620744Sgs150176 }
6212544Sgs150176 pbuf->alength -= rgep->head_room;
6222544Sgs150176 pbuf->offset += rgep->head_room;
6232544Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle;
6242544Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf;
6252544Sgs150176 rx_buf->private = (caddr_t)rgep;
6262544Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf),
6272544Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle);
6282544Sgs150176 if (rx_buf->mp == NULL) {
6292544Sgs150176 rge_fini_buf_ring(rgep);
6302544Sgs150176 rge_problem(rgep,
6312544Sgs150176 "rge_init_buf_ring: desballoc() failed");
6322544Sgs150176 return (DDI_FAILURE);
6332544Sgs150176 }
6342544Sgs150176 free_srbdp++;
635744Sgs150176 }
636744Sgs150176 return (DDI_SUCCESS);
637744Sgs150176 }
638744Sgs150176
639744Sgs150176 static int
rge_init_rings(rge_t * rgep)640744Sgs150176 rge_init_rings(rge_t *rgep)
641744Sgs150176 {
642744Sgs150176 int err;
643744Sgs150176
6442544Sgs150176 err = rge_init_send_ring(rgep);
6452544Sgs150176 if (err != DDI_SUCCESS)
6462544Sgs150176 return (DDI_FAILURE);
647744Sgs150176
6482544Sgs150176 err = rge_init_recv_ring(rgep);
6492544Sgs150176 if (err != DDI_SUCCESS) {
6502544Sgs150176 rge_fini_send_ring(rgep);
6512544Sgs150176 return (DDI_FAILURE);
6522544Sgs150176 }
653744Sgs150176
6542544Sgs150176 err = rge_init_buf_ring(rgep);
6552544Sgs150176 if (err != DDI_SUCCESS) {
6562544Sgs150176 rge_fini_send_ring(rgep);
6572544Sgs150176 rge_fini_recv_ring(rgep);
6582544Sgs150176 return (DDI_FAILURE);
6592544Sgs150176 }
660744Sgs150176
6612544Sgs150176 return (DDI_SUCCESS);
662744Sgs150176 }
663744Sgs150176
664744Sgs150176 /*
665744Sgs150176 * ========== Internal state management entry points ==========
666744Sgs150176 */
667744Sgs150176
668744Sgs150176 #undef RGE_DBG
669744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */
670744Sgs150176
671744Sgs150176 /*
672744Sgs150176 * These routines provide all the functionality required by the
673744Sgs150176 * corresponding MAC layer entry points, but don't update the
674744Sgs150176 * MAC state so they can be called internally without disturbing
675744Sgs150176 * our record of what NEMO thinks we should be doing ...
676744Sgs150176 */
677744Sgs150176
678744Sgs150176 /*
679744Sgs150176 * rge_reset() -- reset h/w & rings to initial state
680744Sgs150176 */
681744Sgs150176 static void
rge_reset(rge_t * rgep)682744Sgs150176 rge_reset(rge_t *rgep)
683744Sgs150176 {
684744Sgs150176 ASSERT(mutex_owned(rgep->genlock));
685744Sgs150176
686744Sgs150176 /*
687744Sgs150176 * Grab all the other mutexes in the world (this should
688744Sgs150176 * ensure no other threads are manipulating driver state)
689744Sgs150176 */
690744Sgs150176 mutex_enter(rgep->rx_lock);
691744Sgs150176 mutex_enter(rgep->rc_lock);
692744Sgs150176 rw_enter(rgep->errlock, RW_WRITER);
693744Sgs150176
694744Sgs150176 (void) rge_chip_reset(rgep);
695744Sgs150176 rge_reinit_rings(rgep);
696744Sgs150176 rge_chip_init(rgep);
697744Sgs150176
698744Sgs150176 /*
699744Sgs150176 * Free the world ...
700744Sgs150176 */
701744Sgs150176 rw_exit(rgep->errlock);
702744Sgs150176 mutex_exit(rgep->rc_lock);
703744Sgs150176 mutex_exit(rgep->rx_lock);
704744Sgs150176
7056410Smx205022 rgep->stats.rpackets = 0;
7066410Smx205022 rgep->stats.rbytes = 0;
7076410Smx205022 rgep->stats.opackets = 0;
7086410Smx205022 rgep->stats.obytes = 0;
7096410Smx205022 rgep->stats.tx_pre_ismax = B_FALSE;
7106410Smx205022 rgep->stats.tx_cur_ismax = B_FALSE;
7116410Smx205022
712744Sgs150176 RGE_DEBUG(("rge_reset($%p) done", (void *)rgep));
713744Sgs150176 }
714744Sgs150176
715744Sgs150176 /*
716744Sgs150176 * rge_stop() -- stop processing, don't reset h/w or rings
717744Sgs150176 */
718744Sgs150176 static void
rge_stop(rge_t * rgep)719744Sgs150176 rge_stop(rge_t *rgep)
720744Sgs150176 {
721744Sgs150176 ASSERT(mutex_owned(rgep->genlock));
722744Sgs150176
723744Sgs150176 rge_chip_stop(rgep, B_FALSE);
724744Sgs150176
725744Sgs150176 RGE_DEBUG(("rge_stop($%p) done", (void *)rgep));
726744Sgs150176 }
727744Sgs150176
728744Sgs150176 /*
729744Sgs150176 * rge_start() -- start transmitting/receiving
730744Sgs150176 */
731744Sgs150176 static void
rge_start(rge_t * rgep)732744Sgs150176 rge_start(rge_t *rgep)
733744Sgs150176 {
734744Sgs150176 ASSERT(mutex_owned(rgep->genlock));
735744Sgs150176
736744Sgs150176 /*
737744Sgs150176 * Start chip processing, including enabling interrupts
738744Sgs150176 */
739744Sgs150176 rge_chip_start(rgep);
740744Sgs150176 rgep->watchdog = 0;
741744Sgs150176 }
742744Sgs150176
743744Sgs150176 /*
744744Sgs150176 * rge_restart - restart transmitting/receiving after error or suspend
745744Sgs150176 */
746744Sgs150176 void
rge_restart(rge_t * rgep)747744Sgs150176 rge_restart(rge_t *rgep)
748744Sgs150176 {
749744Sgs150176 uint32_t i;
750744Sgs150176
751744Sgs150176 ASSERT(mutex_owned(rgep->genlock));
752744Sgs150176 /*
753744Sgs150176 * Wait for posted buffer to be freed...
754744Sgs150176 */
755744Sgs150176 if (!rgep->rx_bcopy) {
756744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
757744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS)
758744Sgs150176 break;
759744Sgs150176 drv_usecwait(1000);
760744Sgs150176 RGE_DEBUG(("rge_restart: waiting for rx buf free..."));
761744Sgs150176 }
762744Sgs150176 }
763744Sgs150176 rge_reset(rgep);
764744Sgs150176 rgep->stats.chip_reset++;
765744Sgs150176 if (rgep->rge_mac_state == RGE_MAC_STARTED) {
766744Sgs150176 rge_start(rgep);
7672544Sgs150176 rgep->resched_needed = B_TRUE;
7682544Sgs150176 (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL);
769744Sgs150176 }
770744Sgs150176 }
771744Sgs150176
772744Sgs150176
773744Sgs150176 /*
774744Sgs150176 * ========== Nemo-required management entry points ==========
775744Sgs150176 */
776744Sgs150176
777744Sgs150176 #undef RGE_DBG
778744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */
779744Sgs150176
780744Sgs150176 /*
781744Sgs150176 * rge_m_stop() -- stop transmitting/receiving
782744Sgs150176 */
783744Sgs150176 static void
rge_m_stop(void * arg)784744Sgs150176 rge_m_stop(void *arg)
785744Sgs150176 {
786744Sgs150176 rge_t *rgep = arg; /* private device info */
787744Sgs150176 uint32_t i;
788744Sgs150176
789744Sgs150176 /*
790744Sgs150176 * Just stop processing, then record new MAC state
791744Sgs150176 */
792744Sgs150176 mutex_enter(rgep->genlock);
7936764Smx205022 if (rgep->suspended) {
7946764Smx205022 ASSERT(rgep->rge_mac_state == RGE_MAC_STOPPED);
7956764Smx205022 mutex_exit(rgep->genlock);
7966764Smx205022 return;
7976764Smx205022 }
798744Sgs150176 rge_stop(rgep);
799744Sgs150176 /*
800744Sgs150176 * Wait for posted buffer to be freed...
801744Sgs150176 */
802744Sgs150176 if (!rgep->rx_bcopy) {
803744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) {
804744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS)
805744Sgs150176 break;
806744Sgs150176 drv_usecwait(1000);
807744Sgs150176 RGE_DEBUG(("rge_m_stop: waiting for rx buf free..."));
808744Sgs150176 }
809744Sgs150176 }
810744Sgs150176 rgep->rge_mac_state = RGE_MAC_STOPPED;
811744Sgs150176 RGE_DEBUG(("rge_m_stop($%p) done", arg));
812744Sgs150176 mutex_exit(rgep->genlock);
813744Sgs150176 }
814744Sgs150176
815744Sgs150176 /*
816744Sgs150176 * rge_m_start() -- start transmitting/receiving
817744Sgs150176 */
818744Sgs150176 static int
rge_m_start(void * arg)819744Sgs150176 rge_m_start(void *arg)
820744Sgs150176 {
821744Sgs150176 rge_t *rgep = arg; /* private device info */
822744Sgs150176
823744Sgs150176 mutex_enter(rgep->genlock);
8246764Smx205022 if (rgep->suspended) {
8256764Smx205022 mutex_exit(rgep->genlock);
8266764Smx205022 return (DDI_FAILURE);
8276764Smx205022 }
828744Sgs150176 /*
829744Sgs150176 * Clear hw/sw statistics
830744Sgs150176 */
831744Sgs150176 DMA_ZERO(rgep->dma_area_stats);
832744Sgs150176 bzero(&rgep->stats, sizeof (rge_stats_t));
833744Sgs150176
834744Sgs150176 /*
835744Sgs150176 * Start processing and record new MAC state
836744Sgs150176 */
837744Sgs150176 rge_reset(rgep);
838744Sgs150176 rge_start(rgep);
839744Sgs150176 rgep->rge_mac_state = RGE_MAC_STARTED;
840744Sgs150176 RGE_DEBUG(("rge_m_start($%p) done", arg));
841744Sgs150176
842744Sgs150176 mutex_exit(rgep->genlock);
843744Sgs150176
844744Sgs150176 return (0);
845744Sgs150176 }
846744Sgs150176
847744Sgs150176 /*
848744Sgs150176 * rge_m_unicst_set() -- set the physical network address
849744Sgs150176 */
850744Sgs150176 static int
rge_m_unicst(void * arg,const uint8_t * macaddr)851744Sgs150176 rge_m_unicst(void *arg, const uint8_t *macaddr)
852744Sgs150176 {
853744Sgs150176 rge_t *rgep = arg; /* private device info */
854744Sgs150176
855744Sgs150176 /*
856744Sgs150176 * Remember the new current address in the driver state
857744Sgs150176 * Sync the chip's idea of the address too ...
858744Sgs150176 */
859744Sgs150176 mutex_enter(rgep->genlock);
860744Sgs150176 bcopy(macaddr, rgep->netaddr, ETHERADDRL);
8616764Smx205022
8626764Smx205022 if (rgep->suspended) {
8636764Smx205022 mutex_exit(rgep->genlock);
8646764Smx205022 return (DDI_SUCCESS);
8656764Smx205022 }
8666764Smx205022
867744Sgs150176 rge_chip_sync(rgep, RGE_SET_MAC);
868744Sgs150176 mutex_exit(rgep->genlock);
869744Sgs150176
870744Sgs150176 return (0);
871744Sgs150176 }
872744Sgs150176
873744Sgs150176 /*
874744Sgs150176 * Compute the index of the required bit in the multicast hash map.
875744Sgs150176 * This must mirror the way the hardware actually does it!
876744Sgs150176 */
877744Sgs150176 static uint32_t
rge_hash_index(const uint8_t * mca)878744Sgs150176 rge_hash_index(const uint8_t *mca)
879744Sgs150176 {
8802544Sgs150176 uint32_t crc = (uint32_t)RGE_HASH_CRC;
881744Sgs150176 uint32_t const POLY = RGE_HASH_POLY;
882744Sgs150176 uint32_t msb;
883744Sgs150176 int bytes;
884744Sgs150176 uchar_t currentbyte;
885744Sgs150176 uint32_t index;
886744Sgs150176 int bit;
887744Sgs150176
888744Sgs150176 for (bytes = 0; bytes < ETHERADDRL; bytes++) {
889744Sgs150176 currentbyte = mca[bytes];
890744Sgs150176 for (bit = 0; bit < 8; bit++) {
891744Sgs150176 msb = crc >> 31;
892744Sgs150176 crc <<= 1;
8932544Sgs150176 if (msb ^ (currentbyte & 1))
894744Sgs150176 crc ^= POLY;
895744Sgs150176 currentbyte >>= 1;
896744Sgs150176 }
897744Sgs150176 }
898744Sgs150176 index = crc >> 26;
8992544Sgs150176 /* the index value is between 0 and 63(0x3f) */
900744Sgs150176
901744Sgs150176 return (index);
902744Sgs150176 }
903744Sgs150176
904744Sgs150176 /*
905744Sgs150176 * rge_m_multicst_add() -- enable/disable a multicast address
906744Sgs150176 */
907744Sgs150176 static int
rge_m_multicst(void * arg,boolean_t add,const uint8_t * mca)908744Sgs150176 rge_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
909744Sgs150176 {
910744Sgs150176 rge_t *rgep = arg; /* private device info */
911744Sgs150176 struct ether_addr *addr;
912744Sgs150176 uint32_t index;
9132544Sgs150176 uint32_t reg;
9142544Sgs150176 uint8_t *hashp;
915744Sgs150176
916744Sgs150176 mutex_enter(rgep->genlock);
917744Sgs150176 hashp = rgep->mcast_hash;
918744Sgs150176 addr = (struct ether_addr *)mca;
9192544Sgs150176 /*
9202544Sgs150176 * Calculate the Multicast address hash index value
9212544Sgs150176 * Normally, the position of MAR0-MAR7 is
9222544Sgs150176 * MAR0: offset 0x08, ..., MAR7: offset 0x0F.
9232544Sgs150176 *
9242544Sgs150176 * For pcie chipset, the position of MAR0-MAR7 is
9252544Sgs150176 * different from others:
9262544Sgs150176 * MAR0: offset 0x0F, ..., MAR7: offset 0x08.
9272544Sgs150176 */
928744Sgs150176 index = rge_hash_index(addr->ether_addr_octet);
9292544Sgs150176 if (rgep->chipid.is_pcie)
9302544Sgs150176 reg = (~(index / RGE_MCAST_NUM)) & 0x7;
9312544Sgs150176 else
9322544Sgs150176 reg = index / RGE_MCAST_NUM;
933744Sgs150176
934744Sgs150176 if (add) {
935744Sgs150176 if (rgep->mcast_refs[index]++) {
936744Sgs150176 mutex_exit(rgep->genlock);
937744Sgs150176 return (0);
938744Sgs150176 }
9392544Sgs150176 hashp[reg] |= 1 << (index % RGE_MCAST_NUM);
940744Sgs150176 } else {
941744Sgs150176 if (--rgep->mcast_refs[index]) {
942744Sgs150176 mutex_exit(rgep->genlock);
943744Sgs150176 return (0);
944744Sgs150176 }
9452544Sgs150176 hashp[reg] &= ~ (1 << (index % RGE_MCAST_NUM));
946744Sgs150176 }
947744Sgs150176
9486764Smx205022 if (rgep->suspended) {
9496764Smx205022 mutex_exit(rgep->genlock);
9506764Smx205022 return (DDI_SUCCESS);
9516764Smx205022 }
9526764Smx205022
953744Sgs150176 /*
954744Sgs150176 * Set multicast register
955744Sgs150176 */
956744Sgs150176 rge_chip_sync(rgep, RGE_SET_MUL);
957744Sgs150176
958744Sgs150176 mutex_exit(rgep->genlock);
959744Sgs150176 return (0);
960744Sgs150176 }
961744Sgs150176
962744Sgs150176 /*
963744Sgs150176 * rge_m_promisc() -- set or reset promiscuous mode on the board
964744Sgs150176 *
965744Sgs150176 * Program the hardware to enable/disable promiscuous and/or
966744Sgs150176 * receive-all-multicast modes.
967744Sgs150176 */
968744Sgs150176 static int
rge_m_promisc(void * arg,boolean_t on)969744Sgs150176 rge_m_promisc(void *arg, boolean_t on)
970744Sgs150176 {
971744Sgs150176 rge_t *rgep = arg;
972744Sgs150176
973744Sgs150176 /*
974744Sgs150176 * Store MAC layer specified mode and pass to chip layer to update h/w
975744Sgs150176 */
976744Sgs150176 mutex_enter(rgep->genlock);
977744Sgs150176
978744Sgs150176 if (rgep->promisc == on) {
979744Sgs150176 mutex_exit(rgep->genlock);
980744Sgs150176 return (0);
981744Sgs150176 }
982744Sgs150176 rgep->promisc = on;
9836764Smx205022
9846764Smx205022 if (rgep->suspended) {
9856764Smx205022 mutex_exit(rgep->genlock);
9866764Smx205022 return (DDI_SUCCESS);
9876764Smx205022 }
9886764Smx205022
989744Sgs150176 rge_chip_sync(rgep, RGE_SET_PROMISC);
990744Sgs150176 RGE_DEBUG(("rge_m_promisc_set($%p) done", arg));
991744Sgs150176 mutex_exit(rgep->genlock);
992744Sgs150176 return (0);
993744Sgs150176 }
994744Sgs150176
995744Sgs150176 /*
996744Sgs150176 * Loopback ioctl code
997744Sgs150176 */
998744Sgs150176
999744Sgs150176 static lb_property_t loopmodes[] = {
1000744Sgs150176 { normal, "normal", RGE_LOOP_NONE },
1001744Sgs150176 { internal, "PHY", RGE_LOOP_INTERNAL_PHY },
1002744Sgs150176 { internal, "MAC", RGE_LOOP_INTERNAL_MAC }
1003744Sgs150176 };
1004744Sgs150176
1005744Sgs150176 static enum ioc_reply
rge_set_loop_mode(rge_t * rgep,uint32_t mode)1006744Sgs150176 rge_set_loop_mode(rge_t *rgep, uint32_t mode)
1007744Sgs150176 {
1008744Sgs150176 /*
1009744Sgs150176 * If the mode isn't being changed, there's nothing to do ...
1010744Sgs150176 */
1011744Sgs150176 if (mode == rgep->param_loop_mode)
1012744Sgs150176 return (IOC_ACK);
1013744Sgs150176
1014744Sgs150176 /*
1015744Sgs150176 * Validate the requested mode and prepare a suitable message
1016744Sgs150176 * to explain the link down/up cycle that the change will
1017744Sgs150176 * probably induce ...
1018744Sgs150176 */
1019744Sgs150176 switch (mode) {
1020744Sgs150176 default:
1021744Sgs150176 return (IOC_INVAL);
1022744Sgs150176
1023744Sgs150176 case RGE_LOOP_NONE:
1024744Sgs150176 case RGE_LOOP_INTERNAL_PHY:
1025744Sgs150176 case RGE_LOOP_INTERNAL_MAC:
1026744Sgs150176 break;
1027744Sgs150176 }
1028744Sgs150176
1029744Sgs150176 /*
1030744Sgs150176 * All OK; tell the caller to reprogram
1031744Sgs150176 * the PHY and/or MAC for the new mode ...
1032744Sgs150176 */
1033744Sgs150176 rgep->param_loop_mode = mode;
1034744Sgs150176 return (IOC_RESTART_ACK);
1035744Sgs150176 }
1036744Sgs150176
1037744Sgs150176 static enum ioc_reply
rge_loop_ioctl(rge_t * rgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)1038744Sgs150176 rge_loop_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
1039744Sgs150176 {
1040744Sgs150176 lb_info_sz_t *lbsp;
1041744Sgs150176 lb_property_t *lbpp;
1042744Sgs150176 uint32_t *lbmp;
1043744Sgs150176 int cmd;
1044744Sgs150176
1045744Sgs150176 _NOTE(ARGUNUSED(wq))
1046744Sgs150176
1047744Sgs150176 /*
1048744Sgs150176 * Validate format of ioctl
1049744Sgs150176 */
1050744Sgs150176 if (mp->b_cont == NULL)
1051744Sgs150176 return (IOC_INVAL);
1052744Sgs150176
1053744Sgs150176 cmd = iocp->ioc_cmd;
1054744Sgs150176 switch (cmd) {
1055744Sgs150176 default:
1056744Sgs150176 /* NOTREACHED */
1057744Sgs150176 rge_error(rgep, "rge_loop_ioctl: invalid cmd 0x%x", cmd);
1058744Sgs150176 return (IOC_INVAL);
1059744Sgs150176
1060744Sgs150176 case LB_GET_INFO_SIZE:
1061744Sgs150176 if (iocp->ioc_count != sizeof (lb_info_sz_t))
1062744Sgs150176 return (IOC_INVAL);
1063744Sgs150176 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr;
1064744Sgs150176 *lbsp = sizeof (loopmodes);
1065744Sgs150176 return (IOC_REPLY);
1066744Sgs150176
1067744Sgs150176 case LB_GET_INFO:
1068744Sgs150176 if (iocp->ioc_count != sizeof (loopmodes))
1069744Sgs150176 return (IOC_INVAL);
1070744Sgs150176 lbpp = (lb_property_t *)mp->b_cont->b_rptr;
1071744Sgs150176 bcopy(loopmodes, lbpp, sizeof (loopmodes));
1072744Sgs150176 return (IOC_REPLY);
1073744Sgs150176
1074744Sgs150176 case LB_GET_MODE:
1075744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t))
1076744Sgs150176 return (IOC_INVAL);
1077744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr;
1078744Sgs150176 *lbmp = rgep->param_loop_mode;
1079744Sgs150176 return (IOC_REPLY);
1080744Sgs150176
1081744Sgs150176 case LB_SET_MODE:
1082744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t))
1083744Sgs150176 return (IOC_INVAL);
1084744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr;
1085744Sgs150176 return (rge_set_loop_mode(rgep, *lbmp));
1086744Sgs150176 }
1087744Sgs150176 }
1088744Sgs150176
1089744Sgs150176 /*
1090744Sgs150176 * Specific rge IOCTLs, the MAC layer handles the generic ones.
1091744Sgs150176 */
1092744Sgs150176 static void
rge_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)1093744Sgs150176 rge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1094744Sgs150176 {
1095744Sgs150176 rge_t *rgep = arg;
1096744Sgs150176 struct iocblk *iocp;
1097744Sgs150176 enum ioc_reply status;
1098744Sgs150176 boolean_t need_privilege;
1099744Sgs150176 int err;
1100744Sgs150176 int cmd;
1101744Sgs150176
1102744Sgs150176 /*
11036764Smx205022 * If suspended, we might actually be able to do some of
11046764Smx205022 * these ioctls, but it is harder to make sure they occur
11056764Smx205022 * without actually putting the hardware in an undesireable
11066764Smx205022 * state. So just NAK it.
11076764Smx205022 */
11086764Smx205022 mutex_enter(rgep->genlock);
11096764Smx205022 if (rgep->suspended) {
11106764Smx205022 miocnak(wq, mp, 0, EINVAL);
11116764Smx205022 mutex_exit(rgep->genlock);
11126764Smx205022 return;
11136764Smx205022 }
11146764Smx205022 mutex_exit(rgep->genlock);
11156764Smx205022
11166764Smx205022 /*
1117744Sgs150176 * Validate the command before bothering with the mutex ...
1118744Sgs150176 */
1119744Sgs150176 iocp = (struct iocblk *)mp->b_rptr;
1120744Sgs150176 iocp->ioc_error = 0;
1121744Sgs150176 need_privilege = B_TRUE;
1122744Sgs150176 cmd = iocp->ioc_cmd;
1123744Sgs150176 switch (cmd) {
1124744Sgs150176 default:
1125744Sgs150176 miocnak(wq, mp, 0, EINVAL);
1126744Sgs150176 return;
1127744Sgs150176
1128744Sgs150176 case RGE_MII_READ:
1129744Sgs150176 case RGE_MII_WRITE:
1130744Sgs150176 case RGE_DIAG:
1131744Sgs150176 case RGE_PEEK:
1132744Sgs150176 case RGE_POKE:
1133744Sgs150176 case RGE_PHY_RESET:
1134744Sgs150176 case RGE_SOFT_RESET:
1135744Sgs150176 case RGE_HARD_RESET:
1136744Sgs150176 break;
1137744Sgs150176
1138744Sgs150176 case LB_GET_INFO_SIZE:
1139744Sgs150176 case LB_GET_INFO:
1140744Sgs150176 case LB_GET_MODE:
1141744Sgs150176 need_privilege = B_FALSE;
1142744Sgs150176 /* FALLTHRU */
1143744Sgs150176 case LB_SET_MODE:
1144744Sgs150176 break;
1145744Sgs150176
1146744Sgs150176 case ND_GET:
1147744Sgs150176 need_privilege = B_FALSE;
1148744Sgs150176 /* FALLTHRU */
1149744Sgs150176 case ND_SET:
1150744Sgs150176 break;
1151744Sgs150176 }
1152744Sgs150176
1153744Sgs150176 if (need_privilege) {
1154744Sgs150176 /*
11552544Sgs150176 * Check for specific net_config privilege
1156744Sgs150176 */
11572544Sgs150176 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1158744Sgs150176 if (err != 0) {
1159744Sgs150176 miocnak(wq, mp, 0, err);
1160744Sgs150176 return;
1161744Sgs150176 }
1162744Sgs150176 }
1163744Sgs150176
1164744Sgs150176 mutex_enter(rgep->genlock);
1165744Sgs150176
1166744Sgs150176 switch (cmd) {
1167744Sgs150176 default:
1168744Sgs150176 _NOTE(NOTREACHED)
1169744Sgs150176 status = IOC_INVAL;
1170744Sgs150176 break;
1171744Sgs150176
1172744Sgs150176 case RGE_MII_READ:
1173744Sgs150176 case RGE_MII_WRITE:
1174744Sgs150176 case RGE_DIAG:
1175744Sgs150176 case RGE_PEEK:
1176744Sgs150176 case RGE_POKE:
1177744Sgs150176 case RGE_PHY_RESET:
1178744Sgs150176 case RGE_SOFT_RESET:
1179744Sgs150176 case RGE_HARD_RESET:
1180744Sgs150176 status = rge_chip_ioctl(rgep, wq, mp, iocp);
1181744Sgs150176 break;
1182744Sgs150176
1183744Sgs150176 case LB_GET_INFO_SIZE:
1184744Sgs150176 case LB_GET_INFO:
1185744Sgs150176 case LB_GET_MODE:
1186744Sgs150176 case LB_SET_MODE:
1187744Sgs150176 status = rge_loop_ioctl(rgep, wq, mp, iocp);
1188744Sgs150176 break;
1189744Sgs150176
1190744Sgs150176 case ND_GET:
1191744Sgs150176 case ND_SET:
1192744Sgs150176 status = rge_nd_ioctl(rgep, wq, mp, iocp);
1193744Sgs150176 break;
1194744Sgs150176 }
1195744Sgs150176
1196744Sgs150176 /*
1197744Sgs150176 * Do we need to reprogram the PHY and/or the MAC?
1198744Sgs150176 * Do it now, while we still have the mutex.
1199744Sgs150176 *
1200744Sgs150176 * Note: update the PHY first, 'cos it controls the
1201744Sgs150176 * speed/duplex parameters that the MAC code uses.
1202744Sgs150176 */
1203744Sgs150176 switch (status) {
1204744Sgs150176 case IOC_RESTART_REPLY:
1205744Sgs150176 case IOC_RESTART_ACK:
1206744Sgs150176 rge_phy_update(rgep);
1207744Sgs150176 break;
1208744Sgs150176 }
1209744Sgs150176
1210744Sgs150176 mutex_exit(rgep->genlock);
1211744Sgs150176
1212744Sgs150176 /*
1213744Sgs150176 * Finally, decide how to reply
1214744Sgs150176 */
1215744Sgs150176 switch (status) {
1216744Sgs150176 default:
1217744Sgs150176 case IOC_INVAL:
1218744Sgs150176 /*
1219744Sgs150176 * Error, reply with a NAK and EINVAL or the specified error
1220744Sgs150176 */
1221744Sgs150176 miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
12225107Seota EINVAL : iocp->ioc_error);
1223744Sgs150176 break;
1224744Sgs150176
1225744Sgs150176 case IOC_DONE:
1226744Sgs150176 /*
1227744Sgs150176 * OK, reply already sent
1228744Sgs150176 */
1229744Sgs150176 break;
1230744Sgs150176
1231744Sgs150176 case IOC_RESTART_ACK:
1232744Sgs150176 case IOC_ACK:
1233744Sgs150176 /*
1234744Sgs150176 * OK, reply with an ACK
1235744Sgs150176 */
1236744Sgs150176 miocack(wq, mp, 0, 0);
1237744Sgs150176 break;
1238744Sgs150176
1239744Sgs150176 case IOC_RESTART_REPLY:
1240744Sgs150176 case IOC_REPLY:
1241744Sgs150176 /*
1242744Sgs150176 * OK, send prepared reply as ACK or NAK
1243744Sgs150176 */
1244744Sgs150176 mp->b_datap->db_type = iocp->ioc_error == 0 ?
12455107Seota M_IOCACK : M_IOCNAK;
1246744Sgs150176 qreply(wq, mp);
1247744Sgs150176 break;
1248744Sgs150176 }
1249744Sgs150176 }
1250744Sgs150176
12512311Sseb /* ARGSUSED */
12522311Sseb static boolean_t
rge_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)12532311Sseb rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
12542311Sseb {
12557516SYong.Tan@Sun.COM rge_t *rgep = arg;
12567516SYong.Tan@Sun.COM
12572311Sseb switch (cap) {
12582311Sseb case MAC_CAPAB_HCKSUM: {
12592311Sseb uint32_t *hcksum_txflags = cap_data;
12607516SYong.Tan@Sun.COM switch (rgep->chipid.mac_ver) {
12617516SYong.Tan@Sun.COM case MAC_VER_8169:
12627516SYong.Tan@Sun.COM case MAC_VER_8169S_D:
12637516SYong.Tan@Sun.COM case MAC_VER_8169S_E:
12647516SYong.Tan@Sun.COM case MAC_VER_8169SB:
12657516SYong.Tan@Sun.COM case MAC_VER_8169SC:
12667516SYong.Tan@Sun.COM case MAC_VER_8168:
12677516SYong.Tan@Sun.COM case MAC_VER_8168B_B:
12687516SYong.Tan@Sun.COM case MAC_VER_8168B_C:
12697516SYong.Tan@Sun.COM case MAC_VER_8101E:
12707516SYong.Tan@Sun.COM *hcksum_txflags = HCKSUM_INET_FULL_V4 |
12717516SYong.Tan@Sun.COM HCKSUM_IPHDRCKSUM;
12727516SYong.Tan@Sun.COM break;
127310814SKHF04453@nifty.ne.jp case MAC_VER_8168C:
12747516SYong.Tan@Sun.COM case MAC_VER_8101E_B:
12757516SYong.Tan@Sun.COM case MAC_VER_8101E_C:
12767516SYong.Tan@Sun.COM default:
12777516SYong.Tan@Sun.COM *hcksum_txflags = 0;
12787516SYong.Tan@Sun.COM break;
12797516SYong.Tan@Sun.COM }
12802311Sseb break;
12812311Sseb }
12822311Sseb default:
12832311Sseb return (B_FALSE);
12842311Sseb }
12852311Sseb return (B_TRUE);
12862311Sseb }
12872311Sseb
1288744Sgs150176 /*
12892544Sgs150176 * ============ Init MSI/Fixed Interrupt routines ==============
12902544Sgs150176 */
12912544Sgs150176
12922544Sgs150176 /*
12932544Sgs150176 * rge_add_intrs:
12942544Sgs150176 *
12952544Sgs150176 * Register FIXED or MSI interrupts.
12962544Sgs150176 */
12972544Sgs150176 static int
rge_add_intrs(rge_t * rgep,int intr_type)12982544Sgs150176 rge_add_intrs(rge_t *rgep, int intr_type)
12992544Sgs150176 {
13002544Sgs150176 dev_info_t *dip = rgep->devinfo;
13012544Sgs150176 int avail;
13022544Sgs150176 int actual;
13032544Sgs150176 int intr_size;
13042544Sgs150176 int count;
13052544Sgs150176 int i, j;
13062544Sgs150176 int ret;
13072544Sgs150176
13082544Sgs150176 /* Get number of interrupts */
13092544Sgs150176 ret = ddi_intr_get_nintrs(dip, intr_type, &count);
13102544Sgs150176 if ((ret != DDI_SUCCESS) || (count == 0)) {
13112544Sgs150176 rge_error(rgep, "ddi_intr_get_nintrs() failure, ret: %d, "
13122544Sgs150176 "count: %d", ret, count);
13132544Sgs150176 return (DDI_FAILURE);
13142544Sgs150176 }
13152544Sgs150176
13162544Sgs150176 /* Get number of available interrupts */
13172544Sgs150176 ret = ddi_intr_get_navail(dip, intr_type, &avail);
13182544Sgs150176 if ((ret != DDI_SUCCESS) || (avail == 0)) {
13192544Sgs150176 rge_error(rgep, "ddi_intr_get_navail() failure, "
13202544Sgs150176 "ret: %d, avail: %d\n", ret, avail);
13212544Sgs150176 return (DDI_FAILURE);
13222544Sgs150176 }
13232544Sgs150176
13242544Sgs150176 /* Allocate an array of interrupt handles */
13252544Sgs150176 intr_size = count * sizeof (ddi_intr_handle_t);
13262544Sgs150176 rgep->htable = kmem_alloc(intr_size, KM_SLEEP);
13272544Sgs150176 rgep->intr_rqst = count;
13282544Sgs150176
13292544Sgs150176 /* Call ddi_intr_alloc() */
13302544Sgs150176 ret = ddi_intr_alloc(dip, rgep->htable, intr_type, 0,
13312544Sgs150176 count, &actual, DDI_INTR_ALLOC_NORMAL);
13322544Sgs150176 if (ret != DDI_SUCCESS || actual == 0) {
13332544Sgs150176 rge_error(rgep, "ddi_intr_alloc() failed %d\n", ret);
13342544Sgs150176 kmem_free(rgep->htable, intr_size);
13352544Sgs150176 return (DDI_FAILURE);
13362544Sgs150176 }
13372544Sgs150176 if (actual < count) {
13382544Sgs150176 rge_log(rgep, "ddi_intr_alloc() Requested: %d, Received: %d\n",
13392544Sgs150176 count, actual);
13402544Sgs150176 }
13412544Sgs150176 rgep->intr_cnt = actual;
13422544Sgs150176
13432544Sgs150176 /*
13442544Sgs150176 * Get priority for first msi, assume remaining are all the same
13452544Sgs150176 */
13462544Sgs150176 if ((ret = ddi_intr_get_pri(rgep->htable[0], &rgep->intr_pri)) !=
13472544Sgs150176 DDI_SUCCESS) {
13482544Sgs150176 rge_error(rgep, "ddi_intr_get_pri() failed %d\n", ret);
13492544Sgs150176 /* Free already allocated intr */
13502544Sgs150176 for (i = 0; i < actual; i++) {
13512544Sgs150176 (void) ddi_intr_free(rgep->htable[i]);
13522544Sgs150176 }
13532544Sgs150176 kmem_free(rgep->htable, intr_size);
13542544Sgs150176 return (DDI_FAILURE);
13552544Sgs150176 }
13562544Sgs150176
13572544Sgs150176 /* Test for high level mutex */
13582544Sgs150176 if (rgep->intr_pri >= ddi_intr_get_hilevel_pri()) {
13592544Sgs150176 rge_error(rgep, "rge_add_intrs:"
13602544Sgs150176 "Hi level interrupt not supported");
13612544Sgs150176 for (i = 0; i < actual; i++)
13622544Sgs150176 (void) ddi_intr_free(rgep->htable[i]);
13632544Sgs150176 kmem_free(rgep->htable, intr_size);
13642544Sgs150176 return (DDI_FAILURE);
13652544Sgs150176 }
13662544Sgs150176
13672544Sgs150176 /* Call ddi_intr_add_handler() */
13682544Sgs150176 for (i = 0; i < actual; i++) {
13692544Sgs150176 if ((ret = ddi_intr_add_handler(rgep->htable[i], rge_intr,
13702544Sgs150176 (caddr_t)rgep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
13712544Sgs150176 rge_error(rgep, "ddi_intr_add_handler() "
13722544Sgs150176 "failed %d\n", ret);
13732544Sgs150176 /* Remove already added intr */
13742544Sgs150176 for (j = 0; j < i; j++)
13752544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[j]);
13762544Sgs150176 /* Free already allocated intr */
13772544Sgs150176 for (i = 0; i < actual; i++) {
13782544Sgs150176 (void) ddi_intr_free(rgep->htable[i]);
13792544Sgs150176 }
13802544Sgs150176 kmem_free(rgep->htable, intr_size);
13812544Sgs150176 return (DDI_FAILURE);
13822544Sgs150176 }
13832544Sgs150176 }
13842544Sgs150176
13852544Sgs150176 if ((ret = ddi_intr_get_cap(rgep->htable[0], &rgep->intr_cap))
13862544Sgs150176 != DDI_SUCCESS) {
13872544Sgs150176 rge_error(rgep, "ddi_intr_get_cap() failed %d\n", ret);
13882544Sgs150176 for (i = 0; i < actual; i++) {
13892544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[i]);
13902544Sgs150176 (void) ddi_intr_free(rgep->htable[i]);
13912544Sgs150176 }
13922544Sgs150176 kmem_free(rgep->htable, intr_size);
13932544Sgs150176 return (DDI_FAILURE);
13942544Sgs150176 }
13952544Sgs150176
13962544Sgs150176 return (DDI_SUCCESS);
13972544Sgs150176 }
13982544Sgs150176
13992544Sgs150176 /*
14002544Sgs150176 * rge_rem_intrs:
14012544Sgs150176 *
14022544Sgs150176 * Unregister FIXED or MSI interrupts
14032544Sgs150176 */
14042544Sgs150176 static void
rge_rem_intrs(rge_t * rgep)14052544Sgs150176 rge_rem_intrs(rge_t *rgep)
14062544Sgs150176 {
14072544Sgs150176 int i;
14082544Sgs150176
14092544Sgs150176 /* Disable all interrupts */
14102544Sgs150176 if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
14112544Sgs150176 /* Call ddi_intr_block_disable() */
14122544Sgs150176 (void) ddi_intr_block_disable(rgep->htable, rgep->intr_cnt);
14132544Sgs150176 } else {
14142544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) {
14152544Sgs150176 (void) ddi_intr_disable(rgep->htable[i]);
14162544Sgs150176 }
14172544Sgs150176 }
14182544Sgs150176
14192544Sgs150176 /* Call ddi_intr_remove_handler() */
14202544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) {
14212544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[i]);
14222544Sgs150176 (void) ddi_intr_free(rgep->htable[i]);
14232544Sgs150176 }
14242544Sgs150176
14252544Sgs150176 kmem_free(rgep->htable, rgep->intr_rqst * sizeof (ddi_intr_handle_t));
14262544Sgs150176 }
14272544Sgs150176
14282544Sgs150176 /*
1429744Sgs150176 * ========== Per-instance setup/teardown code ==========
1430744Sgs150176 */
1431744Sgs150176
1432744Sgs150176 #undef RGE_DBG
1433744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */
1434744Sgs150176
1435744Sgs150176 static void
rge_unattach(rge_t * rgep)1436744Sgs150176 rge_unattach(rge_t *rgep)
1437744Sgs150176 {
1438744Sgs150176 /*
1439744Sgs150176 * Flag that no more activity may be initiated
1440744Sgs150176 */
1441744Sgs150176 rgep->progress &= ~PROGRESS_READY;
1442744Sgs150176 rgep->rge_mac_state = RGE_MAC_UNATTACH;
1443744Sgs150176
1444744Sgs150176 /*
1445744Sgs150176 * Quiesce the PHY and MAC (leave it reset but still powered).
1446744Sgs150176 * Clean up and free all RGE data structures
1447744Sgs150176 */
14485107Seota if (rgep->periodic_id != NULL) {
14495107Seota ddi_periodic_delete(rgep->periodic_id);
14505107Seota rgep->periodic_id = NULL;
1451744Sgs150176 }
1452744Sgs150176
1453744Sgs150176 if (rgep->progress & PROGRESS_KSTATS)
1454744Sgs150176 rge_fini_kstats(rgep);
1455744Sgs150176
1456744Sgs150176 if (rgep->progress & PROGRESS_PHY)
1457744Sgs150176 (void) rge_phy_reset(rgep);
1458744Sgs150176
14592544Sgs150176 if (rgep->progress & PROGRESS_INIT) {
1460744Sgs150176 mutex_enter(rgep->genlock);
1461744Sgs150176 (void) rge_chip_reset(rgep);
1462744Sgs150176 mutex_exit(rgep->genlock);
1463744Sgs150176 rge_fini_rings(rgep);
14642544Sgs150176 }
14652544Sgs150176
14662544Sgs150176 if (rgep->progress & PROGRESS_INTR) {
14672544Sgs150176 rge_rem_intrs(rgep);
1468744Sgs150176 mutex_destroy(rgep->rc_lock);
1469744Sgs150176 mutex_destroy(rgep->rx_lock);
1470744Sgs150176 mutex_destroy(rgep->tc_lock);
1471744Sgs150176 mutex_destroy(rgep->tx_lock);
1472744Sgs150176 rw_destroy(rgep->errlock);
1473744Sgs150176 mutex_destroy(rgep->genlock);
1474744Sgs150176 }
1475744Sgs150176
1476744Sgs150176 if (rgep->progress & PROGRESS_FACTOTUM)
14772544Sgs150176 (void) ddi_intr_remove_softint(rgep->factotum_hdl);
1478744Sgs150176
1479744Sgs150176 if (rgep->progress & PROGRESS_RESCHED)
14802544Sgs150176 (void) ddi_intr_remove_softint(rgep->resched_hdl);
1481744Sgs150176
1482744Sgs150176 if (rgep->progress & PROGRESS_NDD)
1483744Sgs150176 rge_nd_cleanup(rgep);
1484744Sgs150176
14855735Smx205022 rge_free_bufs(rgep);
14865735Smx205022
1487744Sgs150176 if (rgep->progress & PROGRESS_REGS)
1488744Sgs150176 ddi_regs_map_free(&rgep->io_handle);
1489744Sgs150176
1490744Sgs150176 if (rgep->progress & PROGRESS_CFG)
1491744Sgs150176 pci_config_teardown(&rgep->cfg_handle);
1492744Sgs150176
1493744Sgs150176 ddi_remove_minor_node(rgep->devinfo, NULL);
1494744Sgs150176 kmem_free(rgep, sizeof (*rgep));
1495744Sgs150176 }
1496744Sgs150176
1497744Sgs150176 static int
rge_resume(dev_info_t * devinfo)1498744Sgs150176 rge_resume(dev_info_t *devinfo)
1499744Sgs150176 {
1500744Sgs150176 rge_t *rgep; /* Our private data */
1501744Sgs150176 chip_id_t *cidp;
1502744Sgs150176 chip_id_t chipid;
1503744Sgs150176
1504744Sgs150176 rgep = ddi_get_driver_private(devinfo);
15056764Smx205022
15066764Smx205022 /*
15076764Smx205022 * If there are state inconsistancies, this is bad. Returning
15086764Smx205022 * DDI_FAILURE here will eventually cause the machine to panic,
15096764Smx205022 * so it is best done here so that there is a possibility of
15106764Smx205022 * debugging the problem.
15116764Smx205022 */
1512744Sgs150176 if (rgep == NULL)
15136764Smx205022 cmn_err(CE_PANIC,
15146764Smx205022 "rge: ngep returned from ddi_get_driver_private was NULL");
1515744Sgs150176
1516744Sgs150176 /*
1517744Sgs150176 * Refuse to resume if the data structures aren't consistent
1518744Sgs150176 */
1519744Sgs150176 if (rgep->devinfo != devinfo)
15206764Smx205022 cmn_err(CE_PANIC,
15216764Smx205022 "rge: passed devinfo not the same as saved devinfo");
1522744Sgs150176
1523744Sgs150176 /*
1524744Sgs150176 * Read chip ID & set up config space command register(s)
1525744Sgs150176 * Refuse to resume if the chip has changed its identity!
1526744Sgs150176 */
1527744Sgs150176 cidp = &rgep->chipid;
1528744Sgs150176 rge_chip_cfg_init(rgep, &chipid);
1529744Sgs150176 if (chipid.vendor != cidp->vendor)
1530744Sgs150176 return (DDI_FAILURE);
1531744Sgs150176 if (chipid.device != cidp->device)
1532744Sgs150176 return (DDI_FAILURE);
1533744Sgs150176 if (chipid.revision != cidp->revision)
1534744Sgs150176 return (DDI_FAILURE);
1535744Sgs150176
15366764Smx205022 mutex_enter(rgep->genlock);
15376764Smx205022
15386764Smx205022 /*
15396764Smx205022 * Only in one case, this conditional branch can be executed: the port
15406764Smx205022 * hasn't been plumbed.
15416764Smx205022 */
15426764Smx205022 if (rgep->suspended == B_FALSE) {
15436764Smx205022 mutex_exit(rgep->genlock);
15446764Smx205022 return (DDI_SUCCESS);
15456764Smx205022 }
15466764Smx205022 rgep->rge_mac_state = RGE_MAC_STARTED;
1547744Sgs150176 /*
1548744Sgs150176 * All OK, reinitialise h/w & kick off NEMO scheduling
1549744Sgs150176 */
1550744Sgs150176 rge_restart(rgep);
15516764Smx205022 rgep->suspended = B_FALSE;
15526764Smx205022
1553744Sgs150176 mutex_exit(rgep->genlock);
15546764Smx205022
1555744Sgs150176 return (DDI_SUCCESS);
1556744Sgs150176 }
1557744Sgs150176
1558744Sgs150176
1559744Sgs150176 /*
1560744Sgs150176 * attach(9E) -- Attach a device to the system
1561744Sgs150176 *
1562744Sgs150176 * Called once for each board successfully probed.
1563744Sgs150176 */
1564744Sgs150176 static int
rge_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)1565744Sgs150176 rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1566744Sgs150176 {
1567744Sgs150176 rge_t *rgep; /* Our private data */
15682311Sseb mac_register_t *macp;
1569744Sgs150176 chip_id_t *cidp;
15702544Sgs150176 int intr_types;
1571744Sgs150176 caddr_t regs;
1572744Sgs150176 int instance;
15732544Sgs150176 int i;
1574744Sgs150176 int err;
1575744Sgs150176
1576744Sgs150176 /*
1577744Sgs150176 * we don't support high level interrupts in the driver
1578744Sgs150176 */
1579744Sgs150176 if (ddi_intr_hilevel(devinfo, 0) != 0) {
1580744Sgs150176 cmn_err(CE_WARN,
1581744Sgs150176 "rge_attach -- unsupported high level interrupt");
1582744Sgs150176 return (DDI_FAILURE);
1583744Sgs150176 }
1584744Sgs150176
1585744Sgs150176 instance = ddi_get_instance(devinfo);
1586744Sgs150176 RGE_GTRACE(("rge_attach($%p, %d) instance %d",
15875107Seota (void *)devinfo, cmd, instance));
1588744Sgs150176 RGE_BRKPT(NULL, "rge_attach");
1589744Sgs150176
1590744Sgs150176 switch (cmd) {
1591744Sgs150176 default:
1592744Sgs150176 return (DDI_FAILURE);
1593744Sgs150176
1594744Sgs150176 case DDI_RESUME:
1595744Sgs150176 return (rge_resume(devinfo));
1596744Sgs150176
1597744Sgs150176 case DDI_ATTACH:
1598744Sgs150176 break;
1599744Sgs150176 }
1600744Sgs150176
1601744Sgs150176 rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP);
1602744Sgs150176 ddi_set_driver_private(devinfo, rgep);
1603744Sgs150176 rgep->devinfo = devinfo;
1604744Sgs150176
1605744Sgs150176 /*
1606744Sgs150176 * Initialize more fields in RGE private data
1607744Sgs150176 */
16082544Sgs150176 rgep->rge_mac_state = RGE_MAC_ATTACH;
1609744Sgs150176 rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16105107Seota DDI_PROP_DONTPASS, debug_propname, rge_debug);
16112544Sgs150176 rgep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16125107Seota DDI_PROP_DONTPASS, mtu_propname, ETHERMTU);
16132544Sgs150176 rgep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
16145107Seota DDI_PROP_DONTPASS, msi_propname, B_TRUE);
1615744Sgs150176 (void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d",
16165107Seota RGE_DRIVER_NAME, instance);
1617744Sgs150176
1618744Sgs150176 /*
1619744Sgs150176 * Map config space registers
1620744Sgs150176 * Read chip ID & set up config space command register(s)
1621744Sgs150176 *
1622744Sgs150176 * Note: this leaves the chip accessible by Memory Space
1623744Sgs150176 * accesses, but with interrupts and Bus Mastering off.
1624744Sgs150176 * This should ensure that nothing untoward will happen
1625744Sgs150176 * if it has been left active by the (net-)bootloader.
1626744Sgs150176 * We'll re-enable Bus Mastering once we've reset the chip,
1627744Sgs150176 * and allow interrupts only when everything else is set up.
1628744Sgs150176 */
1629744Sgs150176 err = pci_config_setup(devinfo, &rgep->cfg_handle);
1630744Sgs150176 if (err != DDI_SUCCESS) {
1631744Sgs150176 rge_problem(rgep, "pci_config_setup() failed");
1632744Sgs150176 goto attach_fail;
1633744Sgs150176 }
1634744Sgs150176 rgep->progress |= PROGRESS_CFG;
1635744Sgs150176 cidp = &rgep->chipid;
1636744Sgs150176 bzero(cidp, sizeof (*cidp));
1637744Sgs150176 rge_chip_cfg_init(rgep, cidp);
1638744Sgs150176
1639744Sgs150176 /*
1640744Sgs150176 * Map operating registers
1641744Sgs150176 */
164211365SZhen.W@Sun.COM err = ddi_regs_map_setup(devinfo, 2, ®s,
1643744Sgs150176 0, 0, &rge_reg_accattr, &rgep->io_handle);
164411618SLi-Zhen.You@Sun.COM
164511618SLi-Zhen.You@Sun.COM /*
164611618SLi-Zhen.You@Sun.COM * MMIO map will fail if the assigned address is bigger than 4G
164711618SLi-Zhen.You@Sun.COM * then choose I/O map
164811618SLi-Zhen.You@Sun.COM */
164911618SLi-Zhen.You@Sun.COM if (err != DDI_SUCCESS) {
165011618SLi-Zhen.You@Sun.COM err = ddi_regs_map_setup(devinfo, 1, ®s,
165111618SLi-Zhen.You@Sun.COM 0, 0, &rge_reg_accattr, &rgep->io_handle);
165211618SLi-Zhen.You@Sun.COM }
1653744Sgs150176 if (err != DDI_SUCCESS) {
1654744Sgs150176 rge_problem(rgep, "ddi_regs_map_setup() failed");
1655744Sgs150176 goto attach_fail;
1656744Sgs150176 }
1657744Sgs150176 rgep->io_regs = regs;
1658744Sgs150176 rgep->progress |= PROGRESS_REGS;
1659744Sgs150176
1660744Sgs150176 /*
1661744Sgs150176 * Characterise the device, so we know its requirements.
1662744Sgs150176 * Then allocate the appropriate TX and RX descriptors & buffers.
1663744Sgs150176 */
1664744Sgs150176 rge_chip_ident(rgep);
1665744Sgs150176 err = rge_alloc_bufs(rgep);
1666744Sgs150176 if (err != DDI_SUCCESS) {
1667744Sgs150176 rge_problem(rgep, "DMA buffer allocation failed");
1668744Sgs150176 goto attach_fail;
1669744Sgs150176 }
1670744Sgs150176
1671744Sgs150176 /*
16725735Smx205022 * Register NDD-tweakable parameters
16735735Smx205022 */
16745735Smx205022 if (rge_nd_init(rgep)) {
16755735Smx205022 rge_problem(rgep, "rge_nd_init() failed");
16765735Smx205022 goto attach_fail;
16775735Smx205022 }
16785735Smx205022 rgep->progress |= PROGRESS_NDD;
16795735Smx205022
16805735Smx205022 /*
1681744Sgs150176 * Add the softint handlers:
1682744Sgs150176 *
1683744Sgs150176 * Both of these handlers are used to avoid restrictions on the
1684744Sgs150176 * context and/or mutexes required for some operations. In
1685744Sgs150176 * particular, the hardware interrupt handler and its subfunctions
1686744Sgs150176 * can detect a number of conditions that we don't want to handle
1687744Sgs150176 * in that context or with that set of mutexes held. So, these
1688744Sgs150176 * softints are triggered instead:
1689744Sgs150176 *
1690744Sgs150176 * the <resched> softint is triggered if if we have previously
1691744Sgs150176 * had to refuse to send a packet because of resource shortage
1692744Sgs150176 * (we've run out of transmit buffers), but the send completion
1693744Sgs150176 * interrupt handler has now detected that more buffers have
1694744Sgs150176 * become available.
1695744Sgs150176 *
1696744Sgs150176 * the <factotum> is triggered if the h/w interrupt handler
1697744Sgs150176 * sees the <link state changed> or <error> bits in the status
1698744Sgs150176 * block. It's also triggered periodically to poll the link
1699744Sgs150176 * state, just in case we aren't getting link status change
1700744Sgs150176 * interrupts ...
1701744Sgs150176 */
17022544Sgs150176 err = ddi_intr_add_softint(devinfo, &rgep->resched_hdl,
17035107Seota DDI_INTR_SOFTPRI_MIN, rge_reschedule, (caddr_t)rgep);
1704744Sgs150176 if (err != DDI_SUCCESS) {
17052544Sgs150176 rge_problem(rgep, "ddi_intr_add_softint() failed");
1706744Sgs150176 goto attach_fail;
1707744Sgs150176 }
1708744Sgs150176 rgep->progress |= PROGRESS_RESCHED;
17092544Sgs150176 err = ddi_intr_add_softint(devinfo, &rgep->factotum_hdl,
17105107Seota DDI_INTR_SOFTPRI_MIN, rge_chip_factotum, (caddr_t)rgep);
1711744Sgs150176 if (err != DDI_SUCCESS) {
17122544Sgs150176 rge_problem(rgep, "ddi_intr_add_softint() failed");
1713744Sgs150176 goto attach_fail;
1714744Sgs150176 }
1715744Sgs150176 rgep->progress |= PROGRESS_FACTOTUM;
1716744Sgs150176
1717744Sgs150176 /*
17182544Sgs150176 * Get supported interrupt types
1719744Sgs150176 */
17202544Sgs150176 if (ddi_intr_get_supported_types(devinfo, &intr_types)
17212544Sgs150176 != DDI_SUCCESS) {
17222544Sgs150176 rge_error(rgep, "ddi_intr_get_supported_types failed\n");
1723744Sgs150176 goto attach_fail;
1724744Sgs150176 }
17252544Sgs150176
17262544Sgs150176 /*
17272544Sgs150176 * Add the h/w interrupt handler and initialise mutexes
17286764Smx205022 * RTL8101E is observed to have MSI invalidation issue after S/R.
17296764Smx205022 * So the FIXED interrupt is used instead.
17302544Sgs150176 */
17316764Smx205022 if (rgep->chipid.mac_ver == MAC_VER_8101E)
17326764Smx205022 rgep->msi_enable = B_FALSE;
17332544Sgs150176 if ((intr_types & DDI_INTR_TYPE_MSI) && rgep->msi_enable) {
17342544Sgs150176 if (rge_add_intrs(rgep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) {
17352544Sgs150176 rge_error(rgep, "MSI registration failed, "
17362544Sgs150176 "trying FIXED interrupt type\n");
17372544Sgs150176 } else {
17382544Sgs150176 rge_log(rgep, "Using MSI interrupt type\n");
17392544Sgs150176 rgep->intr_type = DDI_INTR_TYPE_MSI;
17402544Sgs150176 rgep->progress |= PROGRESS_INTR;
17412544Sgs150176 }
17422544Sgs150176 }
17432544Sgs150176 if (!(rgep->progress & PROGRESS_INTR) &&
17442544Sgs150176 (intr_types & DDI_INTR_TYPE_FIXED)) {
17452544Sgs150176 if (rge_add_intrs(rgep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) {
17462544Sgs150176 rge_error(rgep, "FIXED interrupt "
17472544Sgs150176 "registration failed\n");
17482544Sgs150176 goto attach_fail;
17492544Sgs150176 }
17502544Sgs150176 rge_log(rgep, "Using FIXED interrupt type\n");
17512544Sgs150176 rgep->intr_type = DDI_INTR_TYPE_FIXED;
17522544Sgs150176 rgep->progress |= PROGRESS_INTR;
17532544Sgs150176 }
17542544Sgs150176 if (!(rgep->progress & PROGRESS_INTR)) {
17552544Sgs150176 rge_error(rgep, "No interrupts registered\n");
17562544Sgs150176 goto attach_fail;
17572544Sgs150176 }
17582544Sgs150176 mutex_init(rgep->genlock, NULL, MUTEX_DRIVER,
17592544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
17602544Sgs150176 rw_init(rgep->errlock, NULL, RW_DRIVER,
17612544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
17622544Sgs150176 mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER,
17632544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
17642544Sgs150176 mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER,
17652544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
17662544Sgs150176 mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER,
17672544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
17682544Sgs150176 mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER,
17692544Sgs150176 DDI_INTR_PRI(rgep->intr_pri));
1770744Sgs150176
1771744Sgs150176 /*
1772744Sgs150176 * Initialize rings
1773744Sgs150176 */
1774744Sgs150176 err = rge_init_rings(rgep);
1775744Sgs150176 if (err != DDI_SUCCESS) {
1776744Sgs150176 rge_problem(rgep, "rge_init_rings() failed");
1777744Sgs150176 goto attach_fail;
1778744Sgs150176 }
17792544Sgs150176 rgep->progress |= PROGRESS_INIT;
17802544Sgs150176
17812544Sgs150176 /*
17822544Sgs150176 * Now that mutex locks are initialized, enable interrupts.
17832544Sgs150176 */
17842544Sgs150176 if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) {
17852544Sgs150176 /* Call ddi_intr_block_enable() for MSI interrupts */
17862544Sgs150176 (void) ddi_intr_block_enable(rgep->htable, rgep->intr_cnt);
17872544Sgs150176 } else {
17882544Sgs150176 /* Call ddi_intr_enable for MSI or FIXED interrupts */
17892544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) {
17902544Sgs150176 (void) ddi_intr_enable(rgep->htable[i]);
17912544Sgs150176 }
17922544Sgs150176 }
1793744Sgs150176
1794744Sgs150176 /*
1795744Sgs150176 * Initialise link state variables
1796744Sgs150176 * Stop, reset & reinitialise the chip.
1797744Sgs150176 * Initialise the (internal) PHY.
1798744Sgs150176 */
1799744Sgs150176 rgep->param_link_up = LINK_STATE_UNKNOWN;
1800744Sgs150176
1801744Sgs150176 /*
1802744Sgs150176 * Reset chip & rings to initial state; also reset address
1803744Sgs150176 * filtering, promiscuity, loopback mode.
1804744Sgs150176 */
1805744Sgs150176 mutex_enter(rgep->genlock);
1806744Sgs150176 (void) rge_chip_reset(rgep);
1807744Sgs150176 rge_chip_sync(rgep, RGE_GET_MAC);
1808744Sgs150176 bzero(rgep->mcast_hash, sizeof (rgep->mcast_hash));
1809744Sgs150176 bzero(rgep->mcast_refs, sizeof (rgep->mcast_refs));
1810744Sgs150176 rgep->promisc = B_FALSE;
1811744Sgs150176 rgep->param_loop_mode = RGE_LOOP_NONE;
1812744Sgs150176 mutex_exit(rgep->genlock);
1813744Sgs150176 rge_phy_init(rgep);
1814744Sgs150176 rgep->progress |= PROGRESS_PHY;
1815744Sgs150176
1816744Sgs150176 /*
1817744Sgs150176 * Create & initialise named kstats
1818744Sgs150176 */
1819744Sgs150176 rge_init_kstats(rgep, instance);
1820744Sgs150176 rgep->progress |= PROGRESS_KSTATS;
1821744Sgs150176
18222311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL)
18232311Sseb goto attach_fail;
18242311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
18252311Sseb macp->m_driver = rgep;
1826744Sgs150176 macp->m_dip = devinfo;
18272311Sseb macp->m_src_addr = rgep->netaddr;
18282311Sseb macp->m_callbacks = &rge_m_callbacks;
18292311Sseb macp->m_min_sdu = 0;
18302544Sgs150176 macp->m_max_sdu = rgep->default_mtu;
18315895Syz147064 macp->m_margin = VLAN_TAGSZ;
1832744Sgs150176
1833744Sgs150176 /*
1834744Sgs150176 * Finally, we're ready to register ourselves with the MAC layer
1835744Sgs150176 * interface; if this succeeds, we're all ready to start()
1836744Sgs150176 */
18372311Sseb err = mac_register(macp, &rgep->mh);
18382311Sseb mac_free(macp);
18392311Sseb if (err != 0)
1840744Sgs150176 goto attach_fail;
1841744Sgs150176
18425107Seota /*
18435107Seota * Register a periodical handler.
18445107Seota * reg_chip_cyclic() is invoked in kernel context.
18455107Seota */
18465107Seota rgep->periodic_id = ddi_periodic_add(rge_chip_cyclic, rgep,
18475107Seota RGE_CYCLIC_PERIOD, DDI_IPL_0);
1848744Sgs150176
1849744Sgs150176 rgep->progress |= PROGRESS_READY;
1850744Sgs150176 return (DDI_SUCCESS);
1851744Sgs150176
1852744Sgs150176 attach_fail:
1853744Sgs150176 rge_unattach(rgep);
1854744Sgs150176 return (DDI_FAILURE);
1855744Sgs150176 }
1856744Sgs150176
1857744Sgs150176 /*
1858744Sgs150176 * rge_suspend() -- suspend transmit/receive for powerdown
1859744Sgs150176 */
1860744Sgs150176 static int
rge_suspend(rge_t * rgep)1861744Sgs150176 rge_suspend(rge_t *rgep)
1862744Sgs150176 {
1863744Sgs150176 /*
1864744Sgs150176 * Stop processing and idle (powerdown) the PHY ...
1865744Sgs150176 */
1866744Sgs150176 mutex_enter(rgep->genlock);
18677825SMin.Xu@Sun.COM rw_enter(rgep->errlock, RW_WRITER);
18686764Smx205022
18696764Smx205022 if (rgep->rge_mac_state != RGE_MAC_STARTED) {
18707825SMin.Xu@Sun.COM rw_exit(rgep->errlock);
18716764Smx205022 mutex_exit(rgep->genlock);
18726764Smx205022 return (DDI_SUCCESS);
18736764Smx205022 }
18746764Smx205022
18756764Smx205022 rgep->suspended = B_TRUE;
1876744Sgs150176 rge_stop(rgep);
18776764Smx205022 rgep->rge_mac_state = RGE_MAC_STOPPED;
18786764Smx205022
18796764Smx205022 rw_exit(rgep->errlock);
1880744Sgs150176 mutex_exit(rgep->genlock);
1881744Sgs150176
1882744Sgs150176 return (DDI_SUCCESS);
1883744Sgs150176 }
1884744Sgs150176
1885744Sgs150176 /*
18867656SSherry.Moore@Sun.COM * quiesce(9E) entry point.
18877656SSherry.Moore@Sun.COM *
18887656SSherry.Moore@Sun.COM * This function is called when the system is single-threaded at high
18897656SSherry.Moore@Sun.COM * PIL with preemption disabled. Therefore, this function must not be
18907656SSherry.Moore@Sun.COM * blocked.
18917656SSherry.Moore@Sun.COM *
18927656SSherry.Moore@Sun.COM * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
18937656SSherry.Moore@Sun.COM * DDI_FAILURE indicates an error condition and should almost never happen.
18947656SSherry.Moore@Sun.COM */
18957656SSherry.Moore@Sun.COM static int
rge_quiesce(dev_info_t * devinfo)18967656SSherry.Moore@Sun.COM rge_quiesce(dev_info_t *devinfo)
18977656SSherry.Moore@Sun.COM {
18987656SSherry.Moore@Sun.COM rge_t *rgep = ddi_get_driver_private(devinfo);
18997656SSherry.Moore@Sun.COM
19007656SSherry.Moore@Sun.COM if (rgep == NULL)
19017656SSherry.Moore@Sun.COM return (DDI_FAILURE);
19027656SSherry.Moore@Sun.COM
19037656SSherry.Moore@Sun.COM /*
19047656SSherry.Moore@Sun.COM * Turn off debugging
19057656SSherry.Moore@Sun.COM */
19067656SSherry.Moore@Sun.COM rge_debug = 0;
19077656SSherry.Moore@Sun.COM rgep->debug = 0;
19087656SSherry.Moore@Sun.COM
19097656SSherry.Moore@Sun.COM /* Stop the chip */
19107656SSherry.Moore@Sun.COM rge_chip_stop(rgep, B_FALSE);
19117656SSherry.Moore@Sun.COM
19127656SSherry.Moore@Sun.COM return (DDI_SUCCESS);
19137656SSherry.Moore@Sun.COM }
19147656SSherry.Moore@Sun.COM
19157656SSherry.Moore@Sun.COM /*
1916744Sgs150176 * detach(9E) -- Detach a device from the system
1917744Sgs150176 */
1918744Sgs150176 static int
rge_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)1919744Sgs150176 rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1920744Sgs150176 {
1921744Sgs150176 rge_t *rgep;
1922744Sgs150176
1923744Sgs150176 RGE_GTRACE(("rge_detach($%p, %d)", (void *)devinfo, cmd));
1924744Sgs150176
1925744Sgs150176 rgep = ddi_get_driver_private(devinfo);
1926744Sgs150176
1927744Sgs150176 switch (cmd) {
1928744Sgs150176 default:
1929744Sgs150176 return (DDI_FAILURE);
1930744Sgs150176
1931744Sgs150176 case DDI_SUSPEND:
1932744Sgs150176 return (rge_suspend(rgep));
1933744Sgs150176
1934744Sgs150176 case DDI_DETACH:
1935744Sgs150176 break;
1936744Sgs150176 }
1937744Sgs150176
1938744Sgs150176 /*
1939744Sgs150176 * If there is any posted buffer, the driver should reject to be
1940744Sgs150176 * detached. Need notice upper layer to release them.
1941744Sgs150176 */
19422544Sgs150176 if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) &&
19432544Sgs150176 rgep->rx_free != RGE_BUF_SLOTS)
1944744Sgs150176 return (DDI_FAILURE);
1945744Sgs150176
1946744Sgs150176 /*
1947744Sgs150176 * Unregister from the MAC layer subsystem. This can fail, in
1948744Sgs150176 * particular if there are DLPI style-2 streams still open -
1949744Sgs150176 * in which case we just return failure without shutting
1950744Sgs150176 * down chip operations.
1951744Sgs150176 */
19522311Sseb if (mac_unregister(rgep->mh) != 0)
1953744Sgs150176 return (DDI_FAILURE);
1954744Sgs150176
1955744Sgs150176 /*
1956744Sgs150176 * All activity stopped, so we can clean up & exit
1957744Sgs150176 */
1958744Sgs150176 rge_unattach(rgep);
1959744Sgs150176 return (DDI_SUCCESS);
1960744Sgs150176 }
1961744Sgs150176
1962744Sgs150176
1963744Sgs150176 /*
1964744Sgs150176 * ========== Module Loading Data & Entry Points ==========
1965744Sgs150176 */
1966744Sgs150176
1967744Sgs150176 #undef RGE_DBG
1968744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */
1969744Sgs150176 DDI_DEFINE_STREAM_OPS(rge_dev_ops, nulldev, nulldev, rge_attach, rge_detach,
19707656SSherry.Moore@Sun.COM nodev, NULL, D_MP, NULL, rge_quiesce);
1971744Sgs150176
1972744Sgs150176 static struct modldrv rge_modldrv = {
1973744Sgs150176 &mod_driverops, /* Type of module. This one is a driver */
1974744Sgs150176 rge_ident, /* short description */
1975744Sgs150176 &rge_dev_ops /* driver specific ops */
1976744Sgs150176 };
1977744Sgs150176
1978744Sgs150176 static struct modlinkage modlinkage = {
1979744Sgs150176 MODREV_1, (void *)&rge_modldrv, NULL
1980744Sgs150176 };
1981744Sgs150176
1982744Sgs150176
1983744Sgs150176 int
_info(struct modinfo * modinfop)1984744Sgs150176 _info(struct modinfo *modinfop)
1985744Sgs150176 {
1986744Sgs150176 return (mod_info(&modlinkage, modinfop));
1987744Sgs150176 }
1988744Sgs150176
1989744Sgs150176 int
_init(void)1990744Sgs150176 _init(void)
1991744Sgs150176 {
1992744Sgs150176 int status;
1993744Sgs150176
1994744Sgs150176 mac_init_ops(&rge_dev_ops, "rge");
1995744Sgs150176 status = mod_install(&modlinkage);
1996744Sgs150176 if (status == DDI_SUCCESS)
1997744Sgs150176 mutex_init(rge_log_mutex, NULL, MUTEX_DRIVER, NULL);
1998744Sgs150176 else
1999744Sgs150176 mac_fini_ops(&rge_dev_ops);
2000744Sgs150176
2001744Sgs150176 return (status);
2002744Sgs150176 }
2003744Sgs150176
2004744Sgs150176 int
_fini(void)2005744Sgs150176 _fini(void)
2006744Sgs150176 {
2007744Sgs150176 int status;
2008744Sgs150176
2009744Sgs150176 status = mod_remove(&modlinkage);
2010744Sgs150176 if (status == DDI_SUCCESS) {
2011744Sgs150176 mac_fini_ops(&rge_dev_ops);
2012744Sgs150176 mutex_destroy(rge_log_mutex);
2013744Sgs150176 }
2014744Sgs150176 return (status);
2015744Sgs150176 }
2016