1bafec742SSukumar Swaminathan /*
2bafec742SSukumar Swaminathan  * CDDL HEADER START
3bafec742SSukumar Swaminathan  *
4bafec742SSukumar Swaminathan  * The contents of this file are subject to the terms of the
5bafec742SSukumar Swaminathan  * Common Development and Distribution License (the "License").
6bafec742SSukumar Swaminathan  * You may not use this file except in compliance with the License.
7bafec742SSukumar Swaminathan  *
8bafec742SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9bafec742SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
10bafec742SSukumar Swaminathan  * See the License for the specific language governing permissions
11bafec742SSukumar Swaminathan  * and limitations under the License.
12bafec742SSukumar Swaminathan  *
13bafec742SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
14bafec742SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15bafec742SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
16bafec742SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
17bafec742SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
18bafec742SSukumar Swaminathan  *
19bafec742SSukumar Swaminathan  * CDDL HEADER END
20bafec742SSukumar Swaminathan  */
21bafec742SSukumar Swaminathan 
22bafec742SSukumar Swaminathan /*
23*accf27a5SSukumar Swaminathan  * Copyright 2010 QLogic Corporation. All rights reserved.
24bafec742SSukumar Swaminathan  */
25bafec742SSukumar Swaminathan 
260dc2366fSVenugopal Iyer #include <sys/note.h>
27bafec742SSukumar Swaminathan #include <qlge.h>
28bafec742SSukumar Swaminathan #include <sys/strsubr.h>
29bafec742SSukumar Swaminathan #include <netinet/in.h>
30bafec742SSukumar Swaminathan #include <netinet/ip.h>
31bafec742SSukumar Swaminathan #include <netinet/ip6.h>
32bafec742SSukumar Swaminathan #include <inet/ip.h>
33bafec742SSukumar Swaminathan 
34bafec742SSukumar Swaminathan /*
35bafec742SSukumar Swaminathan  * GLDv3 functions prototypes
36bafec742SSukumar Swaminathan  */
37bafec742SSukumar Swaminathan static int	ql_m_getstat(void *, uint_t, uint64_t *);
38bafec742SSukumar Swaminathan static int	ql_m_start(void *);
39bafec742SSukumar Swaminathan static void	ql_m_stop(void *);
40bafec742SSukumar Swaminathan static int	ql_m_setpromiscuous(void *, boolean_t);
41bafec742SSukumar Swaminathan static int	ql_m_multicst(void *, boolean_t, const uint8_t *);
42bafec742SSukumar Swaminathan static int	ql_m_unicst(void *, const uint8_t *);
43bafec742SSukumar Swaminathan static mblk_t	*ql_m_tx(void *, mblk_t *);
44bafec742SSukumar Swaminathan static void	ql_m_ioctl(void *, queue_t *, mblk_t *);
45bafec742SSukumar Swaminathan static boolean_t ql_m_getcapab(void *, mac_capab_t, void *);
46bafec742SSukumar Swaminathan 
47bafec742SSukumar Swaminathan static int ql_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
48bafec742SSukumar Swaminathan     const void *);
490dc2366fSVenugopal Iyer static int ql_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
500dc2366fSVenugopal Iyer static void ql_m_propinfo(void *, const char *, mac_prop_id_t,
510dc2366fSVenugopal Iyer     mac_prop_info_handle_t);
520dc2366fSVenugopal Iyer 
530dc2366fSVenugopal Iyer #define	QL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \
540dc2366fSVenugopal Iyer     MC_GETPROP | MC_PROPINFO)
55bafec742SSukumar Swaminathan static mac_callbacks_t ql_m_callbacks = {
56bafec742SSukumar Swaminathan 	QL_M_CALLBACK_FLAGS,
57bafec742SSukumar Swaminathan 	ql_m_getstat,
58bafec742SSukumar Swaminathan 	ql_m_start,
59bafec742SSukumar Swaminathan 	ql_m_stop,
60bafec742SSukumar Swaminathan 	ql_m_setpromiscuous,
61bafec742SSukumar Swaminathan 	ql_m_multicst,
62bafec742SSukumar Swaminathan 	NULL,
63bafec742SSukumar Swaminathan 	NULL,
640dc2366fSVenugopal Iyer 	NULL,
65bafec742SSukumar Swaminathan 	ql_m_ioctl,
66bafec742SSukumar Swaminathan 	ql_m_getcapab,
67bafec742SSukumar Swaminathan 	NULL,
68bafec742SSukumar Swaminathan 	NULL,
69bafec742SSukumar Swaminathan 	ql_m_setprop,
700dc2366fSVenugopal Iyer 	ql_m_getprop,
710dc2366fSVenugopal Iyer 	ql_m_propinfo
72bafec742SSukumar Swaminathan };
73bafec742SSukumar Swaminathan 
740dc2366fSVenugopal Iyer char *qlge_priv_prop[] = {
750dc2366fSVenugopal Iyer 	"_adv_pause_mode",
76*accf27a5SSukumar Swaminathan 	"_fm_enable",
770dc2366fSVenugopal Iyer 	NULL
780dc2366fSVenugopal Iyer };
79bafec742SSukumar Swaminathan 
80bafec742SSukumar Swaminathan /*
81bafec742SSukumar Swaminathan  * This function starts the driver
82bafec742SSukumar Swaminathan  */
83bafec742SSukumar Swaminathan static int
ql_m_start(void * arg)84bafec742SSukumar Swaminathan ql_m_start(void *arg)
85bafec742SSukumar Swaminathan {
86bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
87bafec742SSukumar Swaminathan 
88bafec742SSukumar Swaminathan 	/*
89bafec742SSukumar Swaminathan 	 * reset chip, re-initialize everything but do not
90bafec742SSukumar Swaminathan 	 * re-allocate memory
91bafec742SSukumar Swaminathan 	 */
92bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
93bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
94bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
95bafec742SSukumar Swaminathan 		return (ECANCELED);
96bafec742SSukumar Swaminathan 	}
97bafec742SSukumar Swaminathan 	mutex_enter(&qlge->hw_mutex);
98bafec742SSukumar Swaminathan 	qlge->mac_flags = QL_MAC_INIT;
99bafec742SSukumar Swaminathan 	/*
100bafec742SSukumar Swaminathan 	 * Write default ethernet address to chip register Mac
101bafec742SSukumar Swaminathan 	 * Address slot 0 and Enable Primary Mac Function.
102bafec742SSukumar Swaminathan 	 */
1030662fbf4SSukumar Swaminathan 	(void) ql_unicst_set(qlge,
104bafec742SSukumar Swaminathan 	    (uint8_t *)qlge->unicst_addr[0].addr.ether_addr_octet, 0);
105bafec742SSukumar Swaminathan 	qlge->stats.rpackets = 0;
106bafec742SSukumar Swaminathan 	qlge->stats.rbytes = 0;
107bafec742SSukumar Swaminathan 	qlge->stats.opackets = 0;
108bafec742SSukumar Swaminathan 	qlge->stats.obytes = 0;
109bafec742SSukumar Swaminathan 	mutex_exit(&qlge->hw_mutex);
110bafec742SSukumar Swaminathan 
1110662fbf4SSukumar Swaminathan 	(void) ql_do_start(qlge);
112bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
113bafec742SSukumar Swaminathan 
114bafec742SSukumar Swaminathan 	mutex_enter(&qlge->mbx_mutex);
1154aa4baabSSukumar Swaminathan 	(void) ql_get_firmware_version(qlge, NULL);
116bafec742SSukumar Swaminathan 	mutex_exit(&qlge->mbx_mutex);
117bafec742SSukumar Swaminathan 
118bafec742SSukumar Swaminathan 	return (0);
119bafec742SSukumar Swaminathan }
120bafec742SSukumar Swaminathan 
121bafec742SSukumar Swaminathan /*
122bafec742SSukumar Swaminathan  * This function stops the driver
123bafec742SSukumar Swaminathan  */
124bafec742SSukumar Swaminathan static void
ql_m_stop(void * arg)125bafec742SSukumar Swaminathan ql_m_stop(void *arg)
126bafec742SSukumar Swaminathan {
127bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
128bafec742SSukumar Swaminathan 
129bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
130bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
131bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
132bafec742SSukumar Swaminathan 		return;
133bafec742SSukumar Swaminathan 	}
1340662fbf4SSukumar Swaminathan 	(void) ql_do_stop(qlge);
135bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
136bafec742SSukumar Swaminathan 	qlge->mac_flags = QL_MAC_STOPPED;
137bafec742SSukumar Swaminathan }
138bafec742SSukumar Swaminathan 
139bafec742SSukumar Swaminathan /*
140bafec742SSukumar Swaminathan  * Add or remove a multicast address
141bafec742SSukumar Swaminathan  */
142bafec742SSukumar Swaminathan static int
ql_m_multicst(void * arg,boolean_t add,const uint8_t * ep)143bafec742SSukumar Swaminathan ql_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
144bafec742SSukumar Swaminathan {
145bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
146bafec742SSukumar Swaminathan 	int ret = DDI_SUCCESS;
147bafec742SSukumar Swaminathan 
148bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
149bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
150bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
151bafec742SSukumar Swaminathan 		return (ECANCELED);
152bafec742SSukumar Swaminathan 	}
153bafec742SSukumar Swaminathan 
154bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_DETACH) {
155bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
156bafec742SSukumar Swaminathan 		return (ECANCELED);
157bafec742SSukumar Swaminathan 	}
158bafec742SSukumar Swaminathan 	if (add) {
159bafec742SSukumar Swaminathan 		QL_DUMP(DBG_GLD, "add to multicast list:\n",
160bafec742SSukumar Swaminathan 		    (uint8_t *)ep, 8, ETHERADDRL);
161bafec742SSukumar Swaminathan 		ret = ql_add_to_multicast_list(qlge, (uint8_t *)ep);
162bafec742SSukumar Swaminathan 	} else {
163bafec742SSukumar Swaminathan 		QL_DUMP(DBG_GLD, "remove from multicast list:\n",
164bafec742SSukumar Swaminathan 		    (uint8_t *)ep, 8, ETHERADDRL);
165bafec742SSukumar Swaminathan 		ret = ql_remove_from_multicast_list(qlge, (uint8_t *)ep);
166bafec742SSukumar Swaminathan 	}
167bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
168bafec742SSukumar Swaminathan 
169*accf27a5SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
170*accf27a5SSukumar Swaminathan 		ret = EIO;
171*accf27a5SSukumar Swaminathan 		if (qlge->fm_enable) {
172*accf27a5SSukumar Swaminathan 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
173*accf27a5SSukumar Swaminathan 		}
174*accf27a5SSukumar Swaminathan 	} else {
175*accf27a5SSukumar Swaminathan 		ret = 0;
176*accf27a5SSukumar Swaminathan 	}
177*accf27a5SSukumar Swaminathan 	return (ret);
178bafec742SSukumar Swaminathan }
179bafec742SSukumar Swaminathan 
180bafec742SSukumar Swaminathan /*
181bafec742SSukumar Swaminathan  * Enable or disable promiscuous mode
182bafec742SSukumar Swaminathan  */
183bafec742SSukumar Swaminathan static int
ql_m_setpromiscuous(void * arg,boolean_t on)184bafec742SSukumar Swaminathan ql_m_setpromiscuous(void* arg, boolean_t on)
185bafec742SSukumar Swaminathan {
186bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
187bafec742SSukumar Swaminathan 	int mode;
188bafec742SSukumar Swaminathan 
189bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
190bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
191bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
192bafec742SSukumar Swaminathan 		return (ECANCELED);
193bafec742SSukumar Swaminathan 	}
194bafec742SSukumar Swaminathan 
195bafec742SSukumar Swaminathan 	/* enable reception of all packets on the medium, */
196bafec742SSukumar Swaminathan 	if (on) {
197bafec742SSukumar Swaminathan 		mode = 1;
198bafec742SSukumar Swaminathan 		QL_PRINT(DBG_GLD, ("%s(%d) enable promiscuous mode\n",
199bafec742SSukumar Swaminathan 		    __func__, qlge->instance));
200bafec742SSukumar Swaminathan 	} else {
201bafec742SSukumar Swaminathan 		mode = 0;
202bafec742SSukumar Swaminathan 		QL_PRINT(DBG_GLD, ("%s(%d) disable promiscuous mode\n",
203bafec742SSukumar Swaminathan 		    __func__, qlge->instance));
204bafec742SSukumar Swaminathan 	}
205bafec742SSukumar Swaminathan 
206bafec742SSukumar Swaminathan 	mutex_enter(&qlge->hw_mutex);
207bafec742SSukumar Swaminathan 	ql_set_promiscuous(qlge, mode);
208bafec742SSukumar Swaminathan 	mutex_exit(&qlge->hw_mutex);
209bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
210bafec742SSukumar Swaminathan 	return (DDI_SUCCESS);
211bafec742SSukumar Swaminathan }
212bafec742SSukumar Swaminathan 
213bafec742SSukumar Swaminathan 
214bafec742SSukumar Swaminathan static int
ql_m_getstat(void * arg,uint_t stat,uint64_t * valp)215bafec742SSukumar Swaminathan ql_m_getstat(void *arg, uint_t stat, uint64_t *valp)
216bafec742SSukumar Swaminathan {
217bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
218bafec742SSukumar Swaminathan 	struct ql_stats *cur_stats;
219bafec742SSukumar Swaminathan 	uint64_t val = 0;
220bafec742SSukumar Swaminathan 	int i;
221bafec742SSukumar Swaminathan 	uint32_t val32;
222bafec742SSukumar Swaminathan 	struct rx_ring *rx_ring;
223bafec742SSukumar Swaminathan 	struct tx_ring *tx_ring;
224bafec742SSukumar Swaminathan 
225bafec742SSukumar Swaminathan 	ASSERT(qlge != NULL);
226bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
227bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
228bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
229bafec742SSukumar Swaminathan 		return (ECANCELED);
230bafec742SSukumar Swaminathan 	}
231bafec742SSukumar Swaminathan 
232bafec742SSukumar Swaminathan 	cur_stats = &qlge->stats;
233bafec742SSukumar Swaminathan 	/* these stats are maintained in software */
234bafec742SSukumar Swaminathan 	switch (stat) {
235bafec742SSukumar Swaminathan 
236bafec742SSukumar Swaminathan 	case MAC_STAT_IFSPEED /* 1000 */ :
237bafec742SSukumar Swaminathan 		if (CFG_IST(qlge, CFG_CHIP_8100) != 0) {
238bafec742SSukumar Swaminathan 			qlge->speed = SPEED_10G;
239bafec742SSukumar Swaminathan 		}
240bafec742SSukumar Swaminathan 		val = qlge->speed * 1000000ull;
241bafec742SSukumar Swaminathan 		break;
242bafec742SSukumar Swaminathan 
243bafec742SSukumar Swaminathan 	case MAC_STAT_MULTIRCV:
244bafec742SSukumar Swaminathan 		val = cur_stats->multircv;
245bafec742SSukumar Swaminathan 		break;
246bafec742SSukumar Swaminathan 
247bafec742SSukumar Swaminathan 	case MAC_STAT_BRDCSTRCV:
248bafec742SSukumar Swaminathan 		val = cur_stats->brdcstrcv;
249bafec742SSukumar Swaminathan 		break;
250bafec742SSukumar Swaminathan 
251bafec742SSukumar Swaminathan 	case MAC_STAT_MULTIXMT:
252bafec742SSukumar Swaminathan 		cur_stats->multixmt = 0;
253bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
254bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
255bafec742SSukumar Swaminathan 			cur_stats->multixmt += tx_ring->multixmt;
256bafec742SSukumar Swaminathan 		}
257bafec742SSukumar Swaminathan 		val = cur_stats->multixmt;
258bafec742SSukumar Swaminathan 		break;
259bafec742SSukumar Swaminathan 
260bafec742SSukumar Swaminathan 	case MAC_STAT_BRDCSTXMT:
261bafec742SSukumar Swaminathan 		cur_stats->brdcstxmt = 0;
262bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
263bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
264bafec742SSukumar Swaminathan 			cur_stats->brdcstxmt += tx_ring->brdcstxmt;
265bafec742SSukumar Swaminathan 		}
266bafec742SSukumar Swaminathan 		val = cur_stats->brdcstxmt;
267bafec742SSukumar Swaminathan 		break;
268bafec742SSukumar Swaminathan 
269bafec742SSukumar Swaminathan 	case MAC_STAT_NORCVBUF:
270bafec742SSukumar Swaminathan 		val = cur_stats->norcvbuf;
271bafec742SSukumar Swaminathan 		break;
272bafec742SSukumar Swaminathan 
273bafec742SSukumar Swaminathan 	case MAC_STAT_IERRORS:
274bafec742SSukumar Swaminathan 		val = cur_stats->errrcv;
275bafec742SSukumar Swaminathan 		break;
276bafec742SSukumar Swaminathan 
277bafec742SSukumar Swaminathan 	case MAC_STAT_OBYTES:
278bafec742SSukumar Swaminathan 		cur_stats->obytes = 0;
279bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
280bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
281bafec742SSukumar Swaminathan 			cur_stats->obytes += tx_ring->obytes;
282bafec742SSukumar Swaminathan 		}
283bafec742SSukumar Swaminathan 		val = cur_stats->obytes;
284bafec742SSukumar Swaminathan 		break;
285bafec742SSukumar Swaminathan 
286bafec742SSukumar Swaminathan 	case MAC_STAT_OPACKETS:
287bafec742SSukumar Swaminathan 		cur_stats->opackets = 0;
288bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
289bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
290bafec742SSukumar Swaminathan 			cur_stats->opackets += tx_ring->opackets;
291bafec742SSukumar Swaminathan 		}
292bafec742SSukumar Swaminathan 		val = cur_stats->opackets;
293bafec742SSukumar Swaminathan 		break;
294bafec742SSukumar Swaminathan 
295bafec742SSukumar Swaminathan 	case ETHER_STAT_DEFER_XMTS:
296bafec742SSukumar Swaminathan 		cur_stats->defer = 0;
297bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
298bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
299bafec742SSukumar Swaminathan 			cur_stats->defer += (tx_ring->defer);
300bafec742SSukumar Swaminathan 		}
301bafec742SSukumar Swaminathan 		val = cur_stats->defer;
302bafec742SSukumar Swaminathan 		break;
303bafec742SSukumar Swaminathan 
304bafec742SSukumar Swaminathan 	case MAC_STAT_OERRORS:
305bafec742SSukumar Swaminathan 		cur_stats->errxmt = 0;
306bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->tx_ring_count; i++) {
307bafec742SSukumar Swaminathan 			tx_ring = &qlge->tx_ring[i];
308bafec742SSukumar Swaminathan 			cur_stats->errxmt += tx_ring->errxmt;
309bafec742SSukumar Swaminathan 		}
310bafec742SSukumar Swaminathan 		val = cur_stats->errxmt;
311bafec742SSukumar Swaminathan 		break;
312bafec742SSukumar Swaminathan 
313bafec742SSukumar Swaminathan 	case MAC_STAT_RBYTES:
314bafec742SSukumar Swaminathan 		cur_stats->rbytes = 0;
315bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->rx_ring_count; i++) {
316bafec742SSukumar Swaminathan 			rx_ring = &qlge->rx_ring[i];
317bafec742SSukumar Swaminathan 			cur_stats->rbytes += rx_ring->rx_bytes;
318bafec742SSukumar Swaminathan 		}
319bafec742SSukumar Swaminathan 		val = cur_stats->rbytes;
320bafec742SSukumar Swaminathan 		break;
321bafec742SSukumar Swaminathan 
322bafec742SSukumar Swaminathan 	case MAC_STAT_IPACKETS:
323bafec742SSukumar Swaminathan 		cur_stats->rpackets = 0;
324bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->rx_ring_count; i++) {
325bafec742SSukumar Swaminathan 			rx_ring = &qlge->rx_ring[i];
326bafec742SSukumar Swaminathan 			cur_stats->rpackets += rx_ring->rx_packets;
327bafec742SSukumar Swaminathan 		}
328bafec742SSukumar Swaminathan 		val = cur_stats->rpackets;
329bafec742SSukumar Swaminathan 		break;
330bafec742SSukumar Swaminathan 
331bafec742SSukumar Swaminathan 	case ETHER_STAT_FCS_ERRORS:
332bafec742SSukumar Swaminathan 		cur_stats->crc = 0;
333bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->rx_ring_count; i++) {
334bafec742SSukumar Swaminathan 			rx_ring = &qlge->rx_ring[i];
335bafec742SSukumar Swaminathan 			cur_stats->crc += rx_ring->fcs_err;
336bafec742SSukumar Swaminathan 		}
337bafec742SSukumar Swaminathan 		val = cur_stats->crc;
338bafec742SSukumar Swaminathan 		break;
339bafec742SSukumar Swaminathan 
340bafec742SSukumar Swaminathan 	case ETHER_STAT_TOOLONG_ERRORS:
341bafec742SSukumar Swaminathan 		cur_stats->frame_too_long = 0;
342bafec742SSukumar Swaminathan 		for (i = 0; i < qlge->rx_ring_count; i++) {
343bafec742SSukumar Swaminathan 			rx_ring = &qlge->rx_ring[i];
344bafec742SSukumar Swaminathan 			cur_stats->frame_too_long +=
345bafec742SSukumar Swaminathan 			    rx_ring->frame_too_long;
346bafec742SSukumar Swaminathan 		}
347bafec742SSukumar Swaminathan 		val = cur_stats->frame_too_long;
348bafec742SSukumar Swaminathan 		break;
349bafec742SSukumar Swaminathan 
350bafec742SSukumar Swaminathan 	case ETHER_STAT_XCVR_INUSE:
351bafec742SSukumar Swaminathan 		val = XCVR_1000X;
352bafec742SSukumar Swaminathan 		break;
353bafec742SSukumar Swaminathan 	case ETHER_STAT_JABBER_ERRORS:
354bafec742SSukumar Swaminathan 		if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) !=
355bafec742SSukumar Swaminathan 		    DDI_SUCCESS) {
356bafec742SSukumar Swaminathan 			break;
357bafec742SSukumar Swaminathan 		}
3584aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS,
359bafec742SSukumar Swaminathan 		    &val32);
360bafec742SSukumar Swaminathan 		val = val32;
361bafec742SSukumar Swaminathan 		ql_sem_unlock(qlge, qlge->xgmac_sem_mask);
362bafec742SSukumar Swaminathan 		QL_PRINT(DBG_STATS, ("%s(%d) MAC_STAT_JABBER_ERRORS "
363bafec742SSukumar Swaminathan 		    "status %d\n", __func__, qlge->instance, val));
364bafec742SSukumar Swaminathan 		break;
365bafec742SSukumar Swaminathan 	case ETHER_STAT_LINK_DUPLEX:
366bafec742SSukumar Swaminathan 		if (qlge->duplex == 1)
367bafec742SSukumar Swaminathan 			val = LINK_DUPLEX_FULL;
368bafec742SSukumar Swaminathan 		else
369bafec742SSukumar Swaminathan 			val = LINK_DUPLEX_HALF;
370bafec742SSukumar Swaminathan 		break;
371bafec742SSukumar Swaminathan 
372bafec742SSukumar Swaminathan 	/* statics saved in hw */
373bafec742SSukumar Swaminathan 	case ETHER_STAT_MACRCV_ERRORS:
374bafec742SSukumar Swaminathan 		val = 0;
375bafec742SSukumar Swaminathan 		if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) !=
376bafec742SSukumar Swaminathan 		    DDI_SUCCESS) {
377bafec742SSukumar Swaminathan 			break;
378bafec742SSukumar Swaminathan 		}
3794aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_ALIGN_ERR,
380bafec742SSukumar Swaminathan 		    &val32);
381bafec742SSukumar Swaminathan 		val += val32;
3824aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_FCS_ERR, &val32);
383bafec742SSukumar Swaminathan 		val += val32;
3844aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS,
385bafec742SSukumar Swaminathan 		    &val32);
386bafec742SSukumar Swaminathan 		val += val32;
3874aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_SYM_ERR,
388bafec742SSukumar Swaminathan 		    &val32);
389bafec742SSukumar Swaminathan 		val += val32;
3904aa4baabSSukumar Swaminathan 		(void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_INT_ERR,
391bafec742SSukumar Swaminathan 		    &val32);
392bafec742SSukumar Swaminathan 		val += val32;
393bafec742SSukumar Swaminathan 		ql_sem_unlock(qlge, qlge->xgmac_sem_mask);
394bafec742SSukumar Swaminathan 		break;
395bafec742SSukumar Swaminathan 
396bafec742SSukumar Swaminathan 	default:
397bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
398bafec742SSukumar Swaminathan 		return (ENOTSUP);
399bafec742SSukumar Swaminathan 	}
400bafec742SSukumar Swaminathan 	*valp = val;
401bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
402bafec742SSukumar Swaminathan 
403bafec742SSukumar Swaminathan 	return (0);
404bafec742SSukumar Swaminathan 
405bafec742SSukumar Swaminathan }
406bafec742SSukumar Swaminathan 
407bafec742SSukumar Swaminathan /*
408bafec742SSukumar Swaminathan  * Set the physical network address
409bafec742SSukumar Swaminathan  */
410*accf27a5SSukumar Swaminathan int
ql_unicst_set(qlge_t * qlge,const uint8_t * macaddr,int slot)411bafec742SSukumar Swaminathan ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot)
412bafec742SSukumar Swaminathan {
413*accf27a5SSukumar Swaminathan 	int ret;
414bafec742SSukumar Swaminathan 
415*accf27a5SSukumar Swaminathan 	ret = ql_sem_spinlock(qlge, SEM_MAC_ADDR_MASK);
416*accf27a5SSukumar Swaminathan 	if (ret != DDI_SUCCESS)
417*accf27a5SSukumar Swaminathan 		goto exit;
418*accf27a5SSukumar Swaminathan 	ret = ql_set_mac_addr_reg(qlge, (uint8_t *)macaddr,
419bafec742SSukumar Swaminathan 	    MAC_ADDR_TYPE_CAM_MAC,
420bafec742SSukumar Swaminathan 	    (uint16_t)(qlge->func_number * MAX_CQ + slot));
421bafec742SSukumar Swaminathan 	ql_sem_unlock(qlge, SEM_MAC_ADDR_MASK);
422bafec742SSukumar Swaminathan 
423*accf27a5SSukumar Swaminathan exit:
424*accf27a5SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
425*accf27a5SSukumar Swaminathan 		ret = EIO;
426*accf27a5SSukumar Swaminathan 		if (qlge->fm_enable) {
427*accf27a5SSukumar Swaminathan 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
428*accf27a5SSukumar Swaminathan 		}
429*accf27a5SSukumar Swaminathan 	} else {
430*accf27a5SSukumar Swaminathan 		ret = 0;
431*accf27a5SSukumar Swaminathan 	}
432*accf27a5SSukumar Swaminathan 	return (ret);
433bafec742SSukumar Swaminathan }
434bafec742SSukumar Swaminathan 
435bafec742SSukumar Swaminathan /*
436bafec742SSukumar Swaminathan  * Set default MAC address
437bafec742SSukumar Swaminathan  * Each function has a total of 128 mac address, function0: 0~127,
438bafec742SSukumar Swaminathan  * function1 128~254 etc or func_number *128 + n (0~127), but
439bafec742SSukumar Swaminathan  * we only support one MAC address, so its address is
440bafec742SSukumar Swaminathan  * func_number*128+0
441bafec742SSukumar Swaminathan  */
442bafec742SSukumar Swaminathan static int
ql_m_unicst(void * arg,const uint8_t * mac)443bafec742SSukumar Swaminathan ql_m_unicst(void *arg, const uint8_t *mac)
444bafec742SSukumar Swaminathan {
445bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
446bafec742SSukumar Swaminathan 	int status;
447bafec742SSukumar Swaminathan 
448bafec742SSukumar Swaminathan 	ASSERT(qlge->mac_flags != QL_MAC_DETACH);
449bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
450bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
451bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
452bafec742SSukumar Swaminathan 		return (ECANCELED);
453bafec742SSukumar Swaminathan 	}
454bafec742SSukumar Swaminathan 
455bafec742SSukumar Swaminathan 	mutex_enter(&qlge->hw_mutex);
456bafec742SSukumar Swaminathan 	bcopy(mac, qlge->unicst_addr[0].addr.ether_addr_octet, ETHERADDRL);
457bafec742SSukumar Swaminathan 	/* Set Mac Address to slot 0 and Enable Primary Mac Function */
458bafec742SSukumar Swaminathan 	status = ql_unicst_set(qlge, mac, 0);
459bafec742SSukumar Swaminathan 	mutex_exit(&qlge->hw_mutex);
460bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
461bafec742SSukumar Swaminathan 
462bafec742SSukumar Swaminathan 	return (status);
463bafec742SSukumar Swaminathan }
464bafec742SSukumar Swaminathan 
465bafec742SSukumar Swaminathan /*
466bafec742SSukumar Swaminathan  * ql_m_tx is used only for sending data packets into ethernet wire.
467bafec742SSukumar Swaminathan  */
468bafec742SSukumar Swaminathan static mblk_t *
ql_m_tx(void * arg,mblk_t * mp)469bafec742SSukumar Swaminathan ql_m_tx(void *arg, mblk_t *mp)
470bafec742SSukumar Swaminathan {
471bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
472bafec742SSukumar Swaminathan 	struct tx_ring *tx_ring;
473bafec742SSukumar Swaminathan 	mblk_t *next;
474bafec742SSukumar Swaminathan 	int rval;
475bafec742SSukumar Swaminathan 	uint32_t tx_count = 0;
476*accf27a5SSukumar Swaminathan 	caddr_t bp;
477*accf27a5SSukumar Swaminathan 	uint8_t selected_ring = 0;
478bafec742SSukumar Swaminathan 
479*accf27a5SSukumar Swaminathan 	if ((qlge->port_link_state == LS_DOWN) ||
480*accf27a5SSukumar Swaminathan 	    (qlge->mac_flags != QL_MAC_STARTED)) {
481*accf27a5SSukumar Swaminathan 
482*accf27a5SSukumar Swaminathan 		cmn_err(CE_WARN, "!%s(%d): exit due to link down",
483bafec742SSukumar Swaminathan 		    __func__, qlge->instance);
484bafec742SSukumar Swaminathan 		freemsgchain(mp);
485bafec742SSukumar Swaminathan 		mp = NULL;
486bafec742SSukumar Swaminathan 		goto tx_exit;
487bafec742SSukumar Swaminathan 	}
488bafec742SSukumar Swaminathan 
489bafec742SSukumar Swaminathan 	/*
490*accf27a5SSukumar Swaminathan 	 * Calculate which tx ring to send this packet
491bafec742SSukumar Swaminathan 	 */
492*accf27a5SSukumar Swaminathan 	bp = (caddr_t)mp->b_rptr;
493*accf27a5SSukumar Swaminathan 	selected_ring = ql_tx_hashing(qlge, bp);
494*accf27a5SSukumar Swaminathan 	tx_ring = &qlge->tx_ring[selected_ring];
495bafec742SSukumar Swaminathan 	mutex_enter(&tx_ring->tx_lock);
496bafec742SSukumar Swaminathan 	if (tx_ring->mac_flags != QL_MAC_STARTED) {
497bafec742SSukumar Swaminathan 		mutex_exit(&tx_ring->tx_lock);
498bafec742SSukumar Swaminathan 		goto tx_exit;
499bafec742SSukumar Swaminathan 	}
500bafec742SSukumar Swaminathan 
501bafec742SSukumar Swaminathan 	/* we must try to send all */
502bafec742SSukumar Swaminathan 	while (mp != NULL) {
503bafec742SSukumar Swaminathan 		/*
504bafec742SSukumar Swaminathan 		 * if number of available slots is less than a threshold,
505bafec742SSukumar Swaminathan 		 * then quit
506bafec742SSukumar Swaminathan 		 */
507bafec742SSukumar Swaminathan 		if (tx_ring->tx_free_count <= TX_STOP_THRESHOLD) {
508bafec742SSukumar Swaminathan 			tx_ring->queue_stopped = 1;
509bafec742SSukumar Swaminathan 			rval = DDI_FAILURE;
510bafec742SSukumar Swaminathan 			/*
511bafec742SSukumar Swaminathan 			 * If we return the buffer back we are expected to
512bafec742SSukumar Swaminathan 			 * call mac_tx_ring_update() when
513bafec742SSukumar Swaminathan 			 * resources are available
514bafec742SSukumar Swaminathan 			 */
515bafec742SSukumar Swaminathan 			tx_ring->defer++;
516bafec742SSukumar Swaminathan 			break;
517bafec742SSukumar Swaminathan 		}
518bafec742SSukumar Swaminathan 		next = mp->b_next;
519bafec742SSukumar Swaminathan 		mp->b_next = NULL;
520bafec742SSukumar Swaminathan 
521bafec742SSukumar Swaminathan 		rval = ql_send_common(tx_ring, mp);
522bafec742SSukumar Swaminathan 
523bafec742SSukumar Swaminathan 		if (rval != DDI_SUCCESS) {
524bafec742SSukumar Swaminathan 			mp->b_next = next;
525bafec742SSukumar Swaminathan 			break;
526bafec742SSukumar Swaminathan 		}
527bafec742SSukumar Swaminathan 		tx_count++;
528bafec742SSukumar Swaminathan 		mp = next;
529bafec742SSukumar Swaminathan 	}
530bafec742SSukumar Swaminathan 	/*
531bafec742SSukumar Swaminathan 	 * After all msg blocks are mapped or copied to tx buffer,
532bafec742SSukumar Swaminathan 	 * trigger the hardware to send the msg!
533bafec742SSukumar Swaminathan 	 */
534bafec742SSukumar Swaminathan 	if (tx_count > 0) {
535bafec742SSukumar Swaminathan 		ql_write_doorbell_reg(tx_ring->qlge, tx_ring->prod_idx_db_reg,
536bafec742SSukumar Swaminathan 		    tx_ring->prod_idx);
537bafec742SSukumar Swaminathan 	}
538bafec742SSukumar Swaminathan 	mutex_exit(&tx_ring->tx_lock);
539bafec742SSukumar Swaminathan tx_exit:
540bafec742SSukumar Swaminathan 	return (mp);
541bafec742SSukumar Swaminathan }
542bafec742SSukumar Swaminathan 
543bafec742SSukumar Swaminathan static void
ql_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)544bafec742SSukumar Swaminathan ql_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
545bafec742SSukumar Swaminathan {
546bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
547bafec742SSukumar Swaminathan 	struct iocblk *iocp;
548bafec742SSukumar Swaminathan 	boolean_t need_privilege = B_TRUE;
549bafec742SSukumar Swaminathan 	int err, cmd;
550bafec742SSukumar Swaminathan 	enum ioc_reply status;
551bafec742SSukumar Swaminathan 
552bafec742SSukumar Swaminathan 	/*
553bafec742SSukumar Swaminathan 	 * Validate the command before bothering with the mutex...
554bafec742SSukumar Swaminathan 	 */
555bafec742SSukumar Swaminathan 	iocp = (struct iocblk *)(void *)mp->b_rptr;
556bafec742SSukumar Swaminathan 	iocp->ioc_error = 0;
557bafec742SSukumar Swaminathan 	cmd = iocp->ioc_cmd;
558bafec742SSukumar Swaminathan 
559bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
560bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
561bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
562bafec742SSukumar Swaminathan 		miocnak(wq, mp, 0, EINVAL);
563bafec742SSukumar Swaminathan 		return;
564bafec742SSukumar Swaminathan 	}
565bafec742SSukumar Swaminathan 	switch (cmd) {
566bafec742SSukumar Swaminathan 		default:
567bafec742SSukumar Swaminathan 			QL_PRINT(DBG_GLD, ("unknown ioctl cmd \n"));
568bafec742SSukumar Swaminathan 			miocnak(wq, mp, 0, EINVAL);
569bafec742SSukumar Swaminathan 			mutex_exit(&qlge->gen_mutex);
570bafec742SSukumar Swaminathan 			return;
571bafec742SSukumar Swaminathan 		case QLA_PCI_STATUS:
572bafec742SSukumar Swaminathan 		case QLA_WRITE_REG:
573bafec742SSukumar Swaminathan 		case QLA_READ_PCI_REG:
574bafec742SSukumar Swaminathan 		case QLA_WRITE_PCI_REG:
575bafec742SSukumar Swaminathan 		case QLA_GET_DBGLEAVEL:
576bafec742SSukumar Swaminathan 		case QLA_SET_DBGLEAVEL:
577bafec742SSukumar Swaminathan 		case QLA_READ_CONTRL_REGISTERS:
578bafec742SSukumar Swaminathan 		case QLA_MANUAL_READ_FLASH:
579bafec742SSukumar Swaminathan 		case QLA_MANUAL_WRITE_FLASH:
580bafec742SSukumar Swaminathan 		case QLA_GET_BINARY_CORE_DUMP:
581bafec742SSukumar Swaminathan 		case QLA_SUPPORTED_DUMP_TYPES:
582bafec742SSukumar Swaminathan 		case QLA_TRIGGER_SYS_ERROR_EVENT:
583bafec742SSukumar Swaminathan 		case QLA_READ_FLASH:
584bafec742SSukumar Swaminathan 		case QLA_WRITE_FLASH:
585bafec742SSukumar Swaminathan 		case QLA_READ_VPD:
586bafec742SSukumar Swaminathan 		case QLA_GET_PROP:
587bafec742SSukumar Swaminathan 		case QLA_SHOW_REGION:
588bafec742SSukumar Swaminathan 		case QLA_LIST_ADAPTER_INFO:
589bafec742SSukumar Swaminathan 		case QLA_READ_FW_IMAGE:
590bafec742SSukumar Swaminathan 		case QLA_WRITE_FW_IMAGE_HEADERS:
591bafec742SSukumar Swaminathan 		case QLA_CONTINUE_COPY_IN:
592bafec742SSukumar Swaminathan 		case QLA_CONTINUE_COPY_OUT:
593bafec742SSukumar Swaminathan 		case QLA_SOFT_RESET:
594bafec742SSukumar Swaminathan 			break;
595bafec742SSukumar Swaminathan 		case LB_GET_INFO_SIZE:
596bafec742SSukumar Swaminathan 		case LB_GET_INFO:
597bafec742SSukumar Swaminathan 		case LB_GET_MODE:
598bafec742SSukumar Swaminathan 			need_privilege = B_FALSE;
599bafec742SSukumar Swaminathan 		/* FALLTHRU */
600bafec742SSukumar Swaminathan 		case LB_SET_MODE:
601bafec742SSukumar Swaminathan 			break;
602bafec742SSukumar Swaminathan 	}
603bafec742SSukumar Swaminathan 
604bafec742SSukumar Swaminathan 	if (need_privilege) {
605bafec742SSukumar Swaminathan 		/*
606bafec742SSukumar Swaminathan 		 * Check for specific net_config privilege
607bafec742SSukumar Swaminathan 		 */
608bafec742SSukumar Swaminathan 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
609bafec742SSukumar Swaminathan 		if (err != 0) {
610bafec742SSukumar Swaminathan 			miocnak(wq, mp, 0, err);
611bafec742SSukumar Swaminathan 			mutex_exit(&qlge->gen_mutex);
612bafec742SSukumar Swaminathan 			return;
613bafec742SSukumar Swaminathan 		}
614bafec742SSukumar Swaminathan 	}
615bafec742SSukumar Swaminathan 	/*
616bafec742SSukumar Swaminathan 	 * Implement ioctl
617bafec742SSukumar Swaminathan 	 */
618bafec742SSukumar Swaminathan 	switch (cmd) {
619bafec742SSukumar Swaminathan 		case QLA_PCI_STATUS:
620bafec742SSukumar Swaminathan 		case QLA_WRITE_REG:
621bafec742SSukumar Swaminathan 		case QLA_READ_PCI_REG:
622bafec742SSukumar Swaminathan 		case QLA_WRITE_PCI_REG:
623bafec742SSukumar Swaminathan 		case QLA_GET_DBGLEAVEL:
624bafec742SSukumar Swaminathan 		case QLA_SET_DBGLEAVEL:
625bafec742SSukumar Swaminathan 		case QLA_READ_CONTRL_REGISTERS:
626bafec742SSukumar Swaminathan 		case QLA_MANUAL_READ_FLASH:
627bafec742SSukumar Swaminathan 		case QLA_MANUAL_WRITE_FLASH:
628bafec742SSukumar Swaminathan 		case QLA_GET_BINARY_CORE_DUMP:
629bafec742SSukumar Swaminathan 		case QLA_SUPPORTED_DUMP_TYPES:
630bafec742SSukumar Swaminathan 		case QLA_TRIGGER_SYS_ERROR_EVENT:
631bafec742SSukumar Swaminathan 		case QLA_READ_FLASH:
632bafec742SSukumar Swaminathan 		case QLA_WRITE_FLASH:
633bafec742SSukumar Swaminathan 		case QLA_READ_VPD:
634bafec742SSukumar Swaminathan 		case QLA_GET_PROP:
635bafec742SSukumar Swaminathan 		case QLA_SHOW_REGION:
636bafec742SSukumar Swaminathan 		case QLA_LIST_ADAPTER_INFO:
637bafec742SSukumar Swaminathan 		case QLA_READ_FW_IMAGE:
638bafec742SSukumar Swaminathan 		case QLA_WRITE_FW_IMAGE_HEADERS:
639bafec742SSukumar Swaminathan 		case QLA_CONTINUE_COPY_IN:
640bafec742SSukumar Swaminathan 		case QLA_CONTINUE_COPY_OUT:
641bafec742SSukumar Swaminathan 		case QLA_SOFT_RESET:
642bafec742SSukumar Swaminathan 			status = ql_chip_ioctl(qlge, wq, mp);
643bafec742SSukumar Swaminathan 			break;
644bafec742SSukumar Swaminathan 		case LB_GET_INFO_SIZE:
645bafec742SSukumar Swaminathan 		case LB_GET_INFO:
646bafec742SSukumar Swaminathan 		case LB_GET_MODE:
647bafec742SSukumar Swaminathan 		case LB_SET_MODE:
648bafec742SSukumar Swaminathan 			status = ql_loop_ioctl(qlge, wq, mp, iocp);
649bafec742SSukumar Swaminathan 			break;
650bafec742SSukumar Swaminathan 		default:
651bafec742SSukumar Swaminathan 			status = IOC_INVAL;
652bafec742SSukumar Swaminathan 			break;
653bafec742SSukumar Swaminathan 	}
654bafec742SSukumar Swaminathan 
655bafec742SSukumar Swaminathan 	/*
656bafec742SSukumar Swaminathan 	 * Decide how to reply
657bafec742SSukumar Swaminathan 	 */
658bafec742SSukumar Swaminathan 	switch (status) {
659bafec742SSukumar Swaminathan 	default:
660bafec742SSukumar Swaminathan 	case IOC_INVAL:
661bafec742SSukumar Swaminathan 		/*
662bafec742SSukumar Swaminathan 		 * Error, reply with a NAK and EINVAL or the specified error
663bafec742SSukumar Swaminathan 		 */
664bafec742SSukumar Swaminathan 		miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
665bafec742SSukumar Swaminathan 		    EINVAL : iocp->ioc_error);
666bafec742SSukumar Swaminathan 		break;
667bafec742SSukumar Swaminathan 
668bafec742SSukumar Swaminathan 	case IOC_DONE:
669bafec742SSukumar Swaminathan 		/*
670bafec742SSukumar Swaminathan 		 * OK, reply already sent
671bafec742SSukumar Swaminathan 		 */
672bafec742SSukumar Swaminathan 		break;
673bafec742SSukumar Swaminathan 
674bafec742SSukumar Swaminathan 	case IOC_ACK:
675bafec742SSukumar Swaminathan 		/*
676bafec742SSukumar Swaminathan 		 * OK, reply with an ACK
677bafec742SSukumar Swaminathan 		 */
678bafec742SSukumar Swaminathan 		miocack(wq, mp, 0, 0);
679bafec742SSukumar Swaminathan 		break;
680bafec742SSukumar Swaminathan 
681bafec742SSukumar Swaminathan 	case IOC_REPLY:
682bafec742SSukumar Swaminathan 		/*
683bafec742SSukumar Swaminathan 		 * OK, send prepared reply as ACK or NAK
684bafec742SSukumar Swaminathan 		 */
685bafec742SSukumar Swaminathan 		mp->b_datap->db_type = (uint8_t)(iocp->ioc_error == 0 ?
686bafec742SSukumar Swaminathan 		    M_IOCACK : M_IOCNAK);
687bafec742SSukumar Swaminathan 		qreply(wq, mp);
688bafec742SSukumar Swaminathan 		break;
689bafec742SSukumar Swaminathan 	}
690bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
691bafec742SSukumar Swaminathan }
692bafec742SSukumar Swaminathan /* ARGSUSED */
693bafec742SSukumar Swaminathan static int
qlge_set_priv_prop(qlge_t * qlge,const char * pr_name,uint_t pr_valsize,const void * pr_val)694bafec742SSukumar Swaminathan qlge_set_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize,
695bafec742SSukumar Swaminathan     const void *pr_val)
696bafec742SSukumar Swaminathan {
697bafec742SSukumar Swaminathan 	int err = 0;
698bafec742SSukumar Swaminathan 	long result;
699bafec742SSukumar Swaminathan 
700bafec742SSukumar Swaminathan 	if (strcmp(pr_name, "_adv_pause_mode") == 0) {
701bafec742SSukumar Swaminathan 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
702bafec742SSukumar Swaminathan 		if (result > PAUSE_MODE_PER_PRIORITY ||
703bafec742SSukumar Swaminathan 		    result < PAUSE_MODE_DISABLED) {
704bafec742SSukumar Swaminathan 			err = EINVAL;
705bafec742SSukumar Swaminathan 		} else if (qlge->pause != (uint32_t)result) {
706bafec742SSukumar Swaminathan 			qlge->pause = (uint32_t)result;
707bafec742SSukumar Swaminathan 			if (qlge->flags & INTERRUPTS_ENABLED) {
708bafec742SSukumar Swaminathan 				mutex_enter(&qlge->mbx_mutex);
709*accf27a5SSukumar Swaminathan 				if (ql_set_pause_mode(qlge) == DDI_FAILURE)
710bafec742SSukumar Swaminathan 					err = EINVAL;
711bafec742SSukumar Swaminathan 				mutex_exit(&qlge->mbx_mutex);
712bafec742SSukumar Swaminathan 			}
713bafec742SSukumar Swaminathan 		}
714bafec742SSukumar Swaminathan 		return (err);
715*accf27a5SSukumar Swaminathan 	} else if (strcmp(pr_name, "_fm_enable") == 0) {
716*accf27a5SSukumar Swaminathan 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
717*accf27a5SSukumar Swaminathan 		if ((result != 0) && (result != 1)) {
718*accf27a5SSukumar Swaminathan 			err = EINVAL;
719*accf27a5SSukumar Swaminathan 		} else if (qlge->fm_enable != (boolean_t)result) {
720*accf27a5SSukumar Swaminathan 			qlge->fm_enable = (boolean_t)result;
721*accf27a5SSukumar Swaminathan 		}
722*accf27a5SSukumar Swaminathan 		return (err);
723bafec742SSukumar Swaminathan 	}
724bafec742SSukumar Swaminathan 	return (ENOTSUP);
725bafec742SSukumar Swaminathan }
726bafec742SSukumar Swaminathan 
727bafec742SSukumar Swaminathan /*
728bafec742SSukumar Swaminathan  * callback functions for set/get of properties
729bafec742SSukumar Swaminathan  */
730bafec742SSukumar Swaminathan /* ARGSUSED */
731bafec742SSukumar Swaminathan static int
ql_m_setprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)732bafec742SSukumar Swaminathan ql_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
733bafec742SSukumar Swaminathan     uint_t pr_valsize, const void *pr_val)
734bafec742SSukumar Swaminathan {
735bafec742SSukumar Swaminathan 	qlge_t *qlge = barg;
736bafec742SSukumar Swaminathan 	int err = 0;
737bafec742SSukumar Swaminathan 	uint32_t cur_mtu, new_mtu;
738bafec742SSukumar Swaminathan 
739bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
740bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
741bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
742bafec742SSukumar Swaminathan 		return (ECANCELED);
743bafec742SSukumar Swaminathan 	}
744bafec742SSukumar Swaminathan 
745bafec742SSukumar Swaminathan 	switch (pr_num) {
746bafec742SSukumar Swaminathan 	case MAC_PROP_MTU:
747bafec742SSukumar Swaminathan 		cur_mtu = qlge->mtu;
748bafec742SSukumar Swaminathan 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
749bafec742SSukumar Swaminathan 
750bafec742SSukumar Swaminathan 		QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d \n",
751bafec742SSukumar Swaminathan 		    __func__, qlge->instance, new_mtu));
752bafec742SSukumar Swaminathan 		if (new_mtu == cur_mtu) {
753bafec742SSukumar Swaminathan 			err = 0;
754bafec742SSukumar Swaminathan 			break;
755bafec742SSukumar Swaminathan 		}
756bafec742SSukumar Swaminathan 		if ((new_mtu != ETHERMTU) && (new_mtu != JUMBO_MTU)) {
757bafec742SSukumar Swaminathan 			err = EINVAL;
758bafec742SSukumar Swaminathan 			break;
759bafec742SSukumar Swaminathan 		}
760bafec742SSukumar Swaminathan 		/*
761bafec742SSukumar Swaminathan 		 * do not change on the fly, allow only before
762bafec742SSukumar Swaminathan 		 * driver is started or stopped
763bafec742SSukumar Swaminathan 		 */
764bafec742SSukumar Swaminathan 		if ((qlge->mac_flags == QL_MAC_STARTED) ||
765bafec742SSukumar Swaminathan 		    (qlge->mac_flags == QL_MAC_DETACH)) {
766bafec742SSukumar Swaminathan 			err = EBUSY;
767bafec742SSukumar Swaminathan 			cmn_err(CE_WARN, "%s(%d) new mtu %d ignored, "
768bafec742SSukumar Swaminathan 			    "driver busy, mac_flags %d", __func__,
769bafec742SSukumar Swaminathan 			    qlge->instance, new_mtu, qlge->mac_flags);
770bafec742SSukumar Swaminathan 			break;
771bafec742SSukumar Swaminathan 		}
772bafec742SSukumar Swaminathan 		qlge->mtu = new_mtu;
773bafec742SSukumar Swaminathan 		err = mac_maxsdu_update(qlge->mh, qlge->mtu);
774bafec742SSukumar Swaminathan 		if (err == 0) {
775bafec742SSukumar Swaminathan 			/* EMPTY */
776bafec742SSukumar Swaminathan 			QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d set success\n",
777bafec742SSukumar Swaminathan 			    __func__, qlge->instance,
778bafec742SSukumar Swaminathan 			    new_mtu));
779bafec742SSukumar Swaminathan 		}
780bafec742SSukumar Swaminathan 		break;
781bafec742SSukumar Swaminathan 	case MAC_PROP_PRIVATE:
782bafec742SSukumar Swaminathan 		mutex_exit(&qlge->gen_mutex);
783bafec742SSukumar Swaminathan 		err = qlge_set_priv_prop(qlge, pr_name, pr_valsize,
784bafec742SSukumar Swaminathan 		    pr_val);
785bafec742SSukumar Swaminathan 		mutex_enter(&qlge->gen_mutex);
786bafec742SSukumar Swaminathan 		break;
787bafec742SSukumar Swaminathan 	default:
788bafec742SSukumar Swaminathan 		err = ENOTSUP;
789bafec742SSukumar Swaminathan 		break;
790bafec742SSukumar Swaminathan 	}
791bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
792bafec742SSukumar Swaminathan 	return (err);
793bafec742SSukumar Swaminathan }
794bafec742SSukumar Swaminathan 
7950dc2366fSVenugopal Iyer static int
qlge_get_priv_prop(qlge_t * qlge,const char * pr_name,uint_t pr_valsize,void * pr_val)7960dc2366fSVenugopal Iyer qlge_get_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize,
7970dc2366fSVenugopal Iyer     void *pr_val)
7980dc2366fSVenugopal Iyer {
7990dc2366fSVenugopal Iyer 	int err = ENOTSUP;
8000dc2366fSVenugopal Iyer 	uint32_t value;
8010dc2366fSVenugopal Iyer 
8020dc2366fSVenugopal Iyer 	if (strcmp(pr_name, "_adv_pause_mode") == 0) {
8030dc2366fSVenugopal Iyer 		value = qlge->pause;
8040dc2366fSVenugopal Iyer 		err = 0;
805*accf27a5SSukumar Swaminathan 	} else if (strcmp(pr_name, "_fm_enable") == 0) {
806*accf27a5SSukumar Swaminathan 		value = qlge->fm_enable;
807*accf27a5SSukumar Swaminathan 		err = 0;
8080dc2366fSVenugopal Iyer 	}
8090dc2366fSVenugopal Iyer 
8100dc2366fSVenugopal Iyer 	if (err == 0) {
8110dc2366fSVenugopal Iyer 		(void) snprintf(pr_val, pr_valsize, "%d", value);
8120dc2366fSVenugopal Iyer 	}
8130dc2366fSVenugopal Iyer 	return (err);
8140dc2366fSVenugopal Iyer }
8150dc2366fSVenugopal Iyer 
816bafec742SSukumar Swaminathan /* ARGSUSED */
817bafec742SSukumar Swaminathan static int
ql_m_getprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)818bafec742SSukumar Swaminathan ql_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
8190dc2366fSVenugopal Iyer     uint_t pr_valsize, void *pr_val)
820bafec742SSukumar Swaminathan {
821bafec742SSukumar Swaminathan 	qlge_t *qlge = barg;
822bafec742SSukumar Swaminathan 	uint64_t speed;
823bafec742SSukumar Swaminathan 	link_state_t link_state;
824bafec742SSukumar Swaminathan 	link_duplex_t link_duplex;
825bafec742SSukumar Swaminathan 	int err = 0;
826bafec742SSukumar Swaminathan 
827bafec742SSukumar Swaminathan 	mutex_enter(&qlge->gen_mutex);
828bafec742SSukumar Swaminathan 	if (qlge->mac_flags == QL_MAC_SUSPENDED) {
829bafec742SSukumar Swaminathan 		err = ECANCELED;
830bafec742SSukumar Swaminathan 		goto out;
831bafec742SSukumar Swaminathan 	}
832bafec742SSukumar Swaminathan 
833bafec742SSukumar Swaminathan 	switch (pr_num) {
834bafec742SSukumar Swaminathan 	case MAC_PROP_DUPLEX:
8350dc2366fSVenugopal Iyer 		ASSERT(pr_valsize >= sizeof (link_duplex_t));
836bafec742SSukumar Swaminathan 		if (qlge->duplex)
837bafec742SSukumar Swaminathan 			link_duplex = LINK_DUPLEX_FULL;
838bafec742SSukumar Swaminathan 		else
839bafec742SSukumar Swaminathan 			link_duplex = LINK_DUPLEX_HALF;
840bafec742SSukumar Swaminathan 
841bafec742SSukumar Swaminathan 		bcopy(&link_duplex, pr_val,
842bafec742SSukumar Swaminathan 		    sizeof (link_duplex_t));
843bafec742SSukumar Swaminathan 		break;
844bafec742SSukumar Swaminathan 	case MAC_PROP_SPEED:
8450dc2366fSVenugopal Iyer 		ASSERT(pr_valsize >= sizeof (speed));
846bafec742SSukumar Swaminathan 		speed = qlge->speed * 1000000ull;
847bafec742SSukumar Swaminathan 		bcopy(&speed, pr_val, sizeof (speed));
848bafec742SSukumar Swaminathan 		break;
849bafec742SSukumar Swaminathan 	case MAC_PROP_STATUS:
8500dc2366fSVenugopal Iyer 		ASSERT(pr_valsize >= sizeof (link_state_t));
851bafec742SSukumar Swaminathan 		if (qlge->port_link_state == LS_DOWN)
852bafec742SSukumar Swaminathan 			link_state = LINK_STATE_DOWN;
853bafec742SSukumar Swaminathan 		else
854bafec742SSukumar Swaminathan 			link_state = LINK_STATE_UP;
855bafec742SSukumar Swaminathan 		bcopy(&link_state, pr_val,
856bafec742SSukumar Swaminathan 		    sizeof (link_state_t));
857bafec742SSukumar Swaminathan 		break;
858bafec742SSukumar Swaminathan 
859bafec742SSukumar Swaminathan 	case MAC_PROP_PRIVATE:
8600dc2366fSVenugopal Iyer 		err = qlge_get_priv_prop(qlge, pr_name, pr_valsize, pr_val);
861bafec742SSukumar Swaminathan 		break;
862bafec742SSukumar Swaminathan 
863bafec742SSukumar Swaminathan 	default:
864bafec742SSukumar Swaminathan 		err = ENOTSUP;
865bafec742SSukumar Swaminathan 	}
866bafec742SSukumar Swaminathan out:
867bafec742SSukumar Swaminathan 	mutex_exit(&qlge->gen_mutex);
868bafec742SSukumar Swaminathan 	return (err);
869bafec742SSukumar Swaminathan }
870bafec742SSukumar Swaminathan 
871*accf27a5SSukumar Swaminathan /* ARGSUSED */
8720dc2366fSVenugopal Iyer static void
ql_m_propinfo(void * barg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)8730dc2366fSVenugopal Iyer ql_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
8740dc2366fSVenugopal Iyer     mac_prop_info_handle_t prh)
8750dc2366fSVenugopal Iyer {
8760dc2366fSVenugopal Iyer 	_NOTE(ARGUNUSED(barg));
8770dc2366fSVenugopal Iyer 
8780dc2366fSVenugopal Iyer 	switch (pr_num) {
8790dc2366fSVenugopal Iyer 	case MAC_PROP_DUPLEX:
8800dc2366fSVenugopal Iyer 	case MAC_PROP_SPEED:
8810dc2366fSVenugopal Iyer 	case MAC_PROP_STATUS:
8820dc2366fSVenugopal Iyer 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
8830dc2366fSVenugopal Iyer 		break;
8840dc2366fSVenugopal Iyer 
8850dc2366fSVenugopal Iyer 	case MAC_PROP_PRIVATE: {
8860dc2366fSVenugopal Iyer 		char val_str[64];
8870dc2366fSVenugopal Iyer 		int default_val;
8880dc2366fSVenugopal Iyer 
8890dc2366fSVenugopal Iyer 		if (strcmp(pr_name, "_adv_pause_mode") == 0)
8900dc2366fSVenugopal Iyer 			default_val = 2;
891*accf27a5SSukumar Swaminathan 		else if (strcmp(pr_name, "_fm_enable") == 0)
892*accf27a5SSukumar Swaminathan 			default_val = 1;
8930dc2366fSVenugopal Iyer 		else
8940dc2366fSVenugopal Iyer 			return;
8950dc2366fSVenugopal Iyer 
8960dc2366fSVenugopal Iyer 		(void) snprintf(val_str, sizeof (val_str), "%d", default_val);
8970dc2366fSVenugopal Iyer 		mac_prop_info_set_default_str(prh, val_str);
8980dc2366fSVenugopal Iyer 		break;
8990dc2366fSVenugopal Iyer 	}
9000dc2366fSVenugopal Iyer 	}
9010dc2366fSVenugopal Iyer }
9020dc2366fSVenugopal Iyer 
903bafec742SSukumar Swaminathan /* ARGSUSED */
904bafec742SSukumar Swaminathan static boolean_t
ql_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)905bafec742SSukumar Swaminathan ql_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
906bafec742SSukumar Swaminathan {
907bafec742SSukumar Swaminathan 	int ret = B_FALSE;
908bafec742SSukumar Swaminathan 	uint32_t cksum = 0;
909bafec742SSukumar Swaminathan 	qlge_t *qlge = (qlge_t *)arg;
910bafec742SSukumar Swaminathan 
911bafec742SSukumar Swaminathan 	switch (cap) {
912bafec742SSukumar Swaminathan 	case MAC_CAPAB_HCKSUM:
913bafec742SSukumar Swaminathan 		if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv4) != 0) {
914bafec742SSukumar Swaminathan 			cksum |= HCKSUM_INET_FULL_V4;
915bafec742SSukumar Swaminathan 		}
916bafec742SSukumar Swaminathan 		if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv6) != 0) {
917bafec742SSukumar Swaminathan 			cksum |= HCKSUM_INET_FULL_V6;
918bafec742SSukumar Swaminathan 		}
919bafec742SSukumar Swaminathan 		if ((qlge->cfg_flags & CFG_CKSUM_HEADER_IPv4) != 0) {
920bafec742SSukumar Swaminathan 			cksum |= HCKSUM_IPHDRCKSUM;
921bafec742SSukumar Swaminathan 		}
922bafec742SSukumar Swaminathan 		if ((qlge->cfg_flags & CFG_CKSUM_PARTIAL) != 0) {
923bafec742SSukumar Swaminathan 			cksum |= HCKSUM_INET_PARTIAL;
924bafec742SSukumar Swaminathan 		}
925bafec742SSukumar Swaminathan 		qlge->chksum_cap = cksum;
926bafec742SSukumar Swaminathan 		*(uint32_t *)cap_data = cksum;
927bafec742SSukumar Swaminathan 		ret = B_TRUE;
928bafec742SSukumar Swaminathan 		break;
929bafec742SSukumar Swaminathan 
930bafec742SSukumar Swaminathan 	case MAC_CAPAB_LSO: {
931bafec742SSukumar Swaminathan 		mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
932bafec742SSukumar Swaminathan 		uint32_t page_size;
933*accf27a5SSukumar Swaminathan 		uint32_t lso_max;
934bafec742SSukumar Swaminathan 
935bafec742SSukumar Swaminathan 		if ((qlge->cfg_flags & CFG_LSO)&&
936bafec742SSukumar Swaminathan 		    (qlge->cfg_flags & CFG_SUPPORT_SCATTER_GATHER)) {
937bafec742SSukumar Swaminathan 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
938bafec742SSukumar Swaminathan 			page_size = ddi_ptob(qlge->dip, (ulong_t)1);
939*accf27a5SSukumar Swaminathan 			lso_max = page_size * (QL_MAX_TX_DMA_HANDLES-1);
940*accf27a5SSukumar Swaminathan 			cap_lso->lso_basic_tcp_ipv4.lso_max =
941*accf27a5SSukumar Swaminathan 			    min(lso_max, QL_LSO_MAX);
942bafec742SSukumar Swaminathan 			ret = B_TRUE;
943bafec742SSukumar Swaminathan 		}
944bafec742SSukumar Swaminathan 		break;
945bafec742SSukumar Swaminathan 	}
946bafec742SSukumar Swaminathan 
947bafec742SSukumar Swaminathan 	default:
948bafec742SSukumar Swaminathan 		return (B_FALSE);
949bafec742SSukumar Swaminathan 	}
950bafec742SSukumar Swaminathan 	return (ret);
951bafec742SSukumar Swaminathan }
952bafec742SSukumar Swaminathan 
953bafec742SSukumar Swaminathan void
ql_gld3_init(qlge_t * qlge,mac_register_t * macp)954bafec742SSukumar Swaminathan ql_gld3_init(qlge_t *qlge, mac_register_t *macp)
955bafec742SSukumar Swaminathan {
956bafec742SSukumar Swaminathan 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
957bafec742SSukumar Swaminathan 	macp->m_driver = qlge;
958bafec742SSukumar Swaminathan 	macp->m_dip = qlge->dip;
959bafec742SSukumar Swaminathan 	/* This is the mac address from flash to be used by the port */
960bafec742SSukumar Swaminathan 	macp->m_src_addr = qlge->dev_addr.ether_addr_octet;
961bafec742SSukumar Swaminathan 	macp->m_min_sdu = 0;
962bafec742SSukumar Swaminathan 	macp->m_max_sdu = qlge->mtu;
963bafec742SSukumar Swaminathan 	macp->m_margin = VLAN_TAGSZ;
964bafec742SSukumar Swaminathan 	macp->m_priv_props = qlge_priv_prop;
965bafec742SSukumar Swaminathan 	macp->m_v12n = 0;
966bafec742SSukumar Swaminathan 	ql_m_callbacks.mc_unicst = ql_m_unicst;
967bafec742SSukumar Swaminathan 	ql_m_callbacks.mc_tx = ql_m_tx;
968bafec742SSukumar Swaminathan 	macp->m_callbacks = &ql_m_callbacks;
969bafec742SSukumar Swaminathan }
970