1/*
2 * Copyright 2014-2017 Cavium, Inc.
3 * The contents of this file are subject to the terms of the Common Development
4 * and Distribution License, v.1,  (the "License").
5 *
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the License at available
9 * at http://opensource.org/licenses/CDDL-1.0
10 *
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15/*
16 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
17 * Copyright (c) 2019, Joyent, Inc.
18 */
19
20#include "bnxgld.h"
21#include "bnxhwi.h"
22#include "bnxsnd.h"
23#include "bnxrcv.h"
24#include "bnxcfg.h"
25
26#include <sys/mac_provider.h>
27#include <sys/mac_ether.h>
28#include <sys/dlpi.h>
29#include <sys/policy.h>
30
31/*
32 * Name:    bnx_m_start
33 *
34 * Input:   ptr to driver device structure.
35 *
36 * Return:  DDI_SUCCESS or DDI_FAILURE
37 *
38 * Description:
39 *          This routine is called by GLD to enable device for
40 *          packet reception and enable interrupts.
41 */
42static int
43bnx_m_start(void *arg)
44{
45	int rc;
46	um_device_t *umdevice;
47
48	umdevice = (um_device_t *)arg;
49
50	mutex_enter(&umdevice->os_param.gld_mutex);
51
52	if (umdevice->dev_start == B_TRUE) {
53		/* We're already started.  Success! */
54		rc = 0;
55		goto done;
56	}
57
58	/* Always report the initial link state as unknown. */
59	bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
60
61	umdevice->link_updates_ok = B_TRUE;
62
63	if (bnx_hdwr_acquire(umdevice)) {
64		rc = EIO;
65		goto done;
66	}
67
68	umdevice->dev_start = B_TRUE;
69
70	rc = 0;
71
72done:
73	mutex_exit(&umdevice->os_param.gld_mutex);
74
75	return (rc);
76}
77
78/*
79 * Name:    bnx_m_stop
80 *
81 * Input:   ptr to driver device structure.
82 *
83 * Return:  DDI_SUCCESS or DDI_FAILURE
84 *
85 * Description:
86 *          This routine stops packet reception by clearing RX MASK
87 *          register. Also interrupts are disabled for this device.
88 */
89static void
90bnx_m_stop(void *arg)
91{
92	um_device_t *umdevice;
93
94	umdevice = (um_device_t *)arg;
95
96	mutex_enter(&umdevice->os_param.gld_mutex);
97
98	if (umdevice->dev_start == B_TRUE) {
99		umdevice->dev_start = B_FALSE;
100		umdevice->link_updates_ok = B_FALSE;
101
102		bnx_hdwr_release(umdevice);
103
104		/* Report the link state back to unknown. */
105		bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
106
107		umdevice->dev_var.indLink   = 0;
108		umdevice->dev_var.indMedium = 0;
109	}
110
111	mutex_exit(&umdevice->os_param.gld_mutex);
112}
113
114
115
116/*
117 * Name:    bnx_m_unicast
118 *
119 * Input:   ptr to driver device structure,
120 *          pointer to buffer containing MAC address.
121 *
122 * Return:  DDI_SUCCESS or DDI_FAILURE
123 *
124 * Description:
125 */
126static int
127bnx_m_unicast(void *arg, const uint8_t *macaddr)
128{
129	int rc;
130	um_device_t *umdevice;
131	lm_device_t *lmdevice;
132
133	umdevice = (um_device_t *)arg;
134	lmdevice = &(umdevice->lm_dev);
135
136	mutex_enter(&umdevice->os_param.gld_mutex);
137
138	/* Validate MAC address */
139	if (IS_ETH_MULTICAST(macaddr)) {
140		cmn_err(CE_WARN, "%s: Attempt to program a multicast / "
141		    "broadcast address as a MAC address.", umdevice->dev_name);
142		rc = EINVAL;
143		goto done;
144	}
145
146	if (umdevice->dev_start == B_TRUE) {
147		if (lm_set_mac_addr(lmdevice, 0,
148		    &(lmdevice->params.mac_addr[0])) != LM_STATUS_SUCCESS) {
149			cmn_err(CE_WARN, "%s: failed to program MAC address.",
150			    umdevice->dev_name);
151			rc = EIO;
152			goto done;
153		}
154	}
155
156	bcopy(macaddr, &(lmdevice->params.mac_addr[0]), ETHERADDRL);
157
158	rc = 0;
159
160done:
161	mutex_exit(&umdevice->os_param.gld_mutex);
162
163	return (rc);
164}
165
166static int
167bnx_mc_add(um_device_t *umdevice, const uint8_t *const mc_addr)
168{
169	int rc;
170	int index;
171	lm_status_t   lmstatus;
172	lm_device_t *lmdevice;
173
174	lmdevice = &(umdevice->lm_dev);
175
176	index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr);
177	if (index == -1) {
178		lmstatus = lm_add_mc(lmdevice, (u8_t *)mc_addr);
179		if (lmstatus == LM_STATUS_SUCCESS) {
180			umdevice->dev_var.rx_filter_mask |=
181			    LM_RX_MASK_ACCEPT_MULTICAST;
182			rc = 0;
183		} else {
184			rc = ENOMEM;
185		}
186	} else {
187		lmdevice->mc_table.addr_arr[index].ref_cnt++;
188		rc = 0;
189	}
190
191	return (rc);
192}
193
194static int
195bnx_mc_del(um_device_t *umdevice, const uint8_t *const mc_addr)
196{
197	int rc;
198	int index;
199	lm_status_t lmstatus;
200	lm_device_t *lmdevice;
201
202	lmdevice = &(umdevice->lm_dev);
203
204	index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr);
205	if (index == -1) {
206		rc = ENXIO;
207	} else {
208		lmstatus = lm_del_mc(lmdevice,
209		    lmdevice->mc_table.addr_arr[index].mc_addr);
210		if (lmstatus == LM_STATUS_SUCCESS) {
211			if (lmdevice->mc_table.entry_cnt == 0) {
212				umdevice->dev_var.rx_filter_mask &=
213				    ~LM_RX_MASK_ACCEPT_MULTICAST;
214			}
215
216			rc = 0;
217		} else {
218			rc = ENXIO;
219		}
220	}
221
222	return (rc);
223}
224
225
226
227/*
228 * Name:    bnx_m_multicast
229 *
230 * Input:   ptr to driver device structure,
231 *          boolean describing whether to enable or disable this address,
232 *          pointer to buffer containing multicast address.
233 *
234 * Return:  DDI_SUCCESS or DDI_FAILURE
235 *
236 * Description:
237 *          This function is used to enable or disable multicast packet
238 *          reception for particular multicast addresses.
239 */
240static int
241bnx_m_multicast(void * arg, boolean_t multiflag, const uint8_t *multicastaddr)
242{
243	um_device_t *umdevice;
244	int rc;
245
246	umdevice = (um_device_t *)arg;
247
248	mutex_enter(&umdevice->os_param.gld_mutex);
249
250	if (umdevice->dev_start != B_TRUE) {
251		rc = EAGAIN;
252		goto done;
253	}
254
255	switch (multiflag) {
256		case B_TRUE:
257			rc = bnx_mc_add(umdevice, multicastaddr);
258			break;
259
260		case B_FALSE:
261			rc = bnx_mc_del(umdevice, multicastaddr);
262			break;
263
264		default:
265			rc = EINVAL;
266			break;
267	}
268
269done:
270	mutex_exit(&umdevice->os_param.gld_mutex);
271
272	return (rc);
273}
274
275
276
277/*
278 * Name:    bnx_m_promiscuous
279 *
280 * Input:   ptr to driver device structure,
281 *          boolean describing whether to enable or disable promiscuous mode.
282 *
283 * Return:  DDI_SUCCESS or DDI_FAILURE
284 *
285 * Description:
286 *          This function enables promiscuous mode for this device.
287 *		'flags' argument determines the type of mode being set,
288 *		"PROMISC_PHY" enables reception of all packet types including
289 *		bad/error packets. "PROMISC_MULTI" mode will enable all
290 *		multicast packets, unicasts and broadcast packets to be
291 *		received. "PROMISC_NONE" will enable only broadcast and
292 *		unicast packets.
293 */
294static int
295bnx_m_promiscuous(void *arg, boolean_t promiscflag)
296{
297	int rc;
298	um_device_t *umdevice;
299
300	umdevice = (um_device_t *)arg;
301
302	mutex_enter(&umdevice->os_param.gld_mutex);
303
304	if (umdevice->dev_start != B_TRUE) {
305		rc = EAGAIN;
306		goto done;
307	}
308
309	switch (promiscflag) {
310		case B_TRUE:
311			umdevice->dev_var.rx_filter_mask |=
312			    LM_RX_MASK_PROMISCUOUS_MODE;
313			break;
314
315		case B_FALSE:
316			umdevice->dev_var.rx_filter_mask &=
317			    ~LM_RX_MASK_PROMISCUOUS_MODE;
318			break;
319
320		default:
321			rc = EINVAL;
322			goto done;
323	}
324
325	(void) lm_set_rx_mask(&(umdevice->lm_dev), RX_FILTER_USER_IDX0,
326	    umdevice->dev_var.rx_filter_mask);
327
328	rc = 0;
329
330done:
331	mutex_exit(&umdevice->os_param.gld_mutex);
332
333	return (rc);
334}
335
336
337static mblk_t *
338bnx_m_tx(void *arg, mblk_t *mp)
339{
340	int rc;
341	mblk_t *nmp;
342	um_device_t *umdevice;
343
344	umdevice = (um_device_t *)arg;
345
346	rw_enter(&umdevice->os_param.gld_snd_mutex, RW_READER);
347
348	if (umdevice->dev_start != B_TRUE ||
349	    umdevice->nddcfg.link_speed == 0) {
350		freemsgchain(mp);
351		mp = NULL;
352		goto done;
353	}
354
355	nmp = NULL;
356
357	while (mp) {
358		/* Save the next pointer, in case we do double copy. */
359		nmp = mp->b_next;
360		mp->b_next = NULL;
361
362		rc = bnx_xmit_ring_xmit_mblk(umdevice, 0, mp);
363
364		if (rc == BNX_SEND_GOODXMIT) {
365			mp = nmp;
366			continue;
367		}
368
369		if (rc == BNX_SEND_DEFERPKT)
370			mp = nmp;
371		else
372			mp->b_next = nmp;
373
374		break;
375	}
376
377done:
378	rw_exit(&umdevice->os_param.gld_snd_mutex);
379
380	return (mp);
381}
382
383
384static u64_t
385shift_left32(u32_t val)
386{
387	lm_u64_t tmp;
388
389	/* FIXME -- Get rid of shift_left32() */
390
391	tmp.as_u32.low = 0;
392	tmp.as_u32.high = val;
393
394	return (tmp.as_u64);
395}
396
397
398
399/*
400 * Name:    bnx_m_stats
401 *
402 * Input:   ptr to mac info structure, ptr to gld_stats struct
403 *
404 * Return:  DDI_SUCCESS or DDI_FAILURE
405 *
406 * Description: bnx_m_stats() populates gld_stats structure elements
407 *              from latest data from statistic block.
408 */
409static int
410bnx_m_stats(void * arg, uint_t stat, uint64_t *val)
411{
412	int rc;
413	um_device_t *umdevice;
414	lm_device_t *lmdevice;
415	const bnx_lnk_cfg_t *linkconf;
416
417	umdevice = (um_device_t *)arg;
418
419	if (umdevice == NULL || val == NULL) {
420		return (EINVAL);
421	}
422
423	lmdevice = &(umdevice->lm_dev);
424
425	/* FIXME -- Fix STATS collections */
426
427	if (umdevice->dev_var.isfiber) {
428		linkconf = &bnx_serdes_config;
429	} else {
430		linkconf = &bnx_copper_config;
431	}
432
433	mutex_enter(&umdevice->os_param.gld_mutex);
434
435	if (umdevice->dev_start != B_TRUE) {
436		rc = EAGAIN;
437		goto done;
438	}
439
440	*val = 0;
441	switch (stat) {
442	case MAC_STAT_IFSPEED:
443		*val = umdevice->nddcfg.link_speed * 1000000ull;
444		break;
445	case MAC_STAT_MULTIRCV:
446		*val += shift_left32(
447		    lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_hi);
448		*val +=
449		    lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo;
450		break;
451	case MAC_STAT_BRDCSTRCV:
452		*val += shift_left32(
453		    lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_hi);
454		*val +=
455		    lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo;
456		break;
457	case MAC_STAT_MULTIXMT:
458		*val += shift_left32(
459		    lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_hi);
460		*val +=
461		    lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo;
462		break;
463	case MAC_STAT_BRDCSTXMT:
464		*val += shift_left32(
465		    lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_hi);
466		*val +=
467		    lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo;
468		break;
469	case MAC_STAT_NORCVBUF:
470		*val = lmdevice->vars.stats_virt->stat_IfInMBUFDiscards;
471		break;
472	case ETHER_STAT_MACRCV_ERRORS:
473	case MAC_STAT_IERRORS:
474		*val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors +
475		    lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors +
476		    lmdevice->vars.stats_virt->stat_EtherStatsUndersizePkts +
477		    lmdevice->vars.stats_virt->stat_EtherStatsOverrsizePkts;
478		break;
479	case MAC_STAT_OERRORS:
480		*val = lmdevice->vars.stats_virt->
481		    stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
482		break;
483	case MAC_STAT_COLLISIONS:
484		*val = lmdevice->vars.stats_virt->stat_EtherStatsCollisions;
485		break;
486	case MAC_STAT_RBYTES:
487		*val += shift_left32(
488		    lmdevice->vars.stats_virt->stat_IfHCInOctets_hi);
489		*val +=
490		    lmdevice->vars.stats_virt->stat_IfHCInOctets_lo;
491		break;
492	case MAC_STAT_IPACKETS:
493		*val += shift_left32(lmdevice->vars.stats_virt->
494		    stat_IfHCInUcastPkts_hi);
495		*val += lmdevice->vars.stats_virt->stat_IfHCInUcastPkts_lo;
496
497		*val += shift_left32(lmdevice->vars.stats_virt->
498		    stat_IfHCInMulticastPkts_hi);
499		*val += lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo;
500
501		*val += shift_left32(lmdevice->vars.stats_virt->
502		    stat_IfHCInBroadcastPkts_hi);
503		*val += lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo;
504		break;
505	case MAC_STAT_OBYTES:
506		*val += shift_left32(
507		    lmdevice->vars.stats_virt->stat_IfHCOutOctets_hi);
508		*val +=
509		    lmdevice->vars.stats_virt->stat_IfHCOutOctets_lo;
510		break;
511	case MAC_STAT_OPACKETS:
512		*val += shift_left32(lmdevice->vars.stats_virt->
513		    stat_IfHCOutUcastPkts_hi);
514		*val += lmdevice->vars.stats_virt->stat_IfHCOutUcastPkts_lo;
515
516		*val += shift_left32(lmdevice->vars.stats_virt->
517		    stat_IfHCOutMulticastPkts_hi);
518		*val += lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo;
519
520		*val += shift_left32(lmdevice->vars.stats_virt->
521		    stat_IfHCOutBroadcastPkts_hi);
522		*val += lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo;
523		break;
524	case ETHER_STAT_ALIGN_ERRORS:
525		*val = lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors;
526		break;
527	case ETHER_STAT_FCS_ERRORS:
528		*val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors;
529		break;
530	case ETHER_STAT_FIRST_COLLISIONS:
531		*val = lmdevice->vars.stats_virt->
532		    stat_Dot3StatsSingleCollisionFrames;
533		break;
534	case ETHER_STAT_MULTI_COLLISIONS:
535		*val = lmdevice->vars.stats_virt->
536		    stat_Dot3StatsMultipleCollisionFrames;
537		break;
538	case ETHER_STAT_DEFER_XMTS:
539		*val = lmdevice->vars.stats_virt->
540		    stat_Dot3StatsDeferredTransmissions;
541		break;
542	case ETHER_STAT_TX_LATE_COLLISIONS:
543		*val = lmdevice->vars.stats_virt->
544		    stat_Dot3StatsLateCollisions;
545		break;
546	case ETHER_STAT_EX_COLLISIONS:
547		*val = lmdevice->vars.stats_virt->
548		    stat_Dot3StatsExcessiveCollisions;
549		break;
550	case ETHER_STAT_MACXMT_ERRORS:
551		*val = lmdevice->vars.stats_virt->
552		    stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
553		break;
554	case ETHER_STAT_CARRIER_ERRORS:
555		*val = lmdevice->vars.stats_virt->
556		    stat_Dot3StatsCarrierSenseErrors;
557		break;
558	case ETHER_STAT_TOOLONG_ERRORS:
559		*val = lmdevice->vars.stats_virt->
560		    stat_EtherStatsOverrsizePkts;
561		break;
562#if (MAC_VERSION > 1)
563	case ETHER_STAT_TOOSHORT_ERRORS:
564		*val = lmdevice->vars.stats_virt->
565		    stat_EtherStatsUndersizePkts;
566		break;
567#endif
568	case ETHER_STAT_XCVR_ADDR:
569		*val = lmdevice->params.phy_addr;
570		break;
571	case ETHER_STAT_XCVR_ID:
572		*val = lmdevice->hw_info.phy_id;
573		break;
574	case ETHER_STAT_XCVR_INUSE:
575		switch (umdevice->nddcfg.link_speed) {
576		case 1000:
577			*val = (umdevice->dev_var.isfiber) ?
578			    XCVR_1000X : XCVR_1000T;
579			break;
580		case 100:
581			*val = XCVR_100X;
582			break;
583		case 10:
584			*val = XCVR_10;
585			break;
586		default:
587			*val = XCVR_NONE;
588			break;
589		}
590		break;
591	case ETHER_STAT_CAP_1000FDX:
592		*val = 1;
593		break;
594	case ETHER_STAT_CAP_1000HDX:
595		*val = linkconf->param_1000hdx;
596		break;
597	case ETHER_STAT_CAP_100FDX:
598		*val = linkconf->param_100fdx;
599		break;
600	case ETHER_STAT_CAP_100HDX:
601		*val = linkconf->param_100hdx;
602		break;
603	case ETHER_STAT_CAP_10FDX:
604		*val = linkconf->param_10fdx;
605		break;
606	case ETHER_STAT_CAP_10HDX:
607		*val = linkconf->param_10hdx;
608		break;
609	case ETHER_STAT_CAP_ASMPAUSE:
610		*val = 1;
611		break;
612	case ETHER_STAT_CAP_PAUSE:
613		*val = 1;
614		break;
615	case ETHER_STAT_CAP_AUTONEG:
616		*val = 1;
617		break;
618#if (MAC_VERSION > 1)
619	case ETHER_STAT_CAP_REMFAULT:
620		*val = 1;
621		break;
622#endif
623	case ETHER_STAT_ADV_CAP_1000FDX:
624		*val = umdevice->curcfg.lnkcfg.param_1000fdx;
625		break;
626	case ETHER_STAT_ADV_CAP_1000HDX:
627		*val = umdevice->curcfg.lnkcfg.param_1000hdx;
628		break;
629	case ETHER_STAT_ADV_CAP_100FDX:
630		*val = umdevice->curcfg.lnkcfg.param_100fdx;
631		break;
632	case ETHER_STAT_ADV_CAP_100HDX:
633		*val = umdevice->curcfg.lnkcfg.param_100hdx;
634		break;
635	case ETHER_STAT_ADV_CAP_10FDX:
636		*val = umdevice->curcfg.lnkcfg.param_10fdx;
637		break;
638	case ETHER_STAT_ADV_CAP_10HDX:
639		*val = umdevice->curcfg.lnkcfg.param_10hdx;
640		break;
641	case ETHER_STAT_ADV_CAP_ASMPAUSE:
642		*val = 1;
643		break;
644	case ETHER_STAT_ADV_CAP_PAUSE:
645		*val = 1;
646		break;
647	case ETHER_STAT_ADV_CAP_AUTONEG:
648		*val = umdevice->curcfg.lnkcfg.link_autoneg;
649		break;
650#if (MAC_VERSION > 1)
651	case ETHER_STAT_ADV_REMFAULT:
652		*val = 1;
653		break;
654#endif
655	case ETHER_STAT_LP_CAP_1000FDX:
656		*val = umdevice->remote.param_1000fdx;
657		break;
658	case ETHER_STAT_LP_CAP_1000HDX:
659		*val = umdevice->remote.param_1000hdx;
660		break;
661	case ETHER_STAT_LP_CAP_100FDX:
662		*val = umdevice->remote.param_100fdx;
663		break;
664	case ETHER_STAT_LP_CAP_100HDX:
665		*val = umdevice->remote.param_100hdx;
666		break;
667	case ETHER_STAT_LP_CAP_10FDX:
668		*val = umdevice->remote.param_10fdx;
669		break;
670	case ETHER_STAT_LP_CAP_10HDX:
671		*val = umdevice->remote.param_10hdx;
672		break;
673	case ETHER_STAT_LP_CAP_ASMPAUSE:
674		/* FIXME -- Implement LP_ASYM_PAUSE stat */
675		break;
676	case ETHER_STAT_LP_CAP_PAUSE:
677		/* FIXME -- Implement LP_PAUSE stat */
678		break;
679	case ETHER_STAT_LP_CAP_AUTONEG:
680		*val = umdevice->remote.link_autoneg;
681		break;
682#if (MAC_VERSION > 1)
683	case ETHER_STAT_LP_REMFAULT:
684		/* FIXME -- Implement LP_REMFAULT stat */
685		break;
686#endif
687	case ETHER_STAT_LINK_ASMPAUSE:
688		/* FIXME -- Implement ASMPAUSE stat */
689		break;
690	case ETHER_STAT_LINK_PAUSE:
691		/* FIXME -- Implement PAUSE stat */
692		break;
693	case ETHER_STAT_LINK_AUTONEG:
694		*val = umdevice->curcfg.lnkcfg.link_autoneg;
695		break;
696	case ETHER_STAT_LINK_DUPLEX:
697		*val = umdevice->nddcfg.link_duplex == B_TRUE ?
698		    LINK_DUPLEX_FULL: LINK_DUPLEX_HALF;
699		break;
700	default:
701		rc = ENOTSUP;
702	}
703
704	rc = 0;
705
706done:
707	mutex_exit(&umdevice->os_param.gld_mutex);
708
709	return (rc);
710}
711
712static boolean_t
713bnx_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
714{
715	um_device_t *umdevice;
716
717	umdevice = (um_device_t *)arg;
718
719	switch (cap) {
720	case MAC_CAPAB_HCKSUM: {
721		uint32_t *txflags = cap_data;
722
723		*txflags = 0;
724
725		if (umdevice->dev_var.enabled_oflds &
726		    (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM)) {
727			*txflags |= HCKSUM_IPHDRCKSUM;
728		}
729
730		if (umdevice->dev_var.enabled_oflds &
731		    (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM |
732		    LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM)) {
733			*txflags |= HCKSUM_INET_FULL_V4;
734		}
735		break;
736	}
737	default:
738		return (B_FALSE);
739	}
740
741	return (B_TRUE);
742}
743
744static int
745bnx_refresh_rx_tx_pkts(um_device_t *umdevice)
746{
747	if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_HDWR_REGISTER) {
748		bnx_hdwr_fini(umdevice);
749		/*
750		 * Initialize the adapter resource.  Mainly allocating memory
751		 * needed by the driver, such as packet descriptors, shared
752		 * memory, etc.
753		 */
754		if (lm_init_resc(&(umdevice->lm_dev)) != LM_STATUS_SUCCESS) {
755			return (EIO);
756		}
757
758		if (bnx_txpkts_init(umdevice)) {
759			return (EIO);
760		}
761
762		if (bnx_rxpkts_init(umdevice)) {
763			return (EIO);
764		}
765	}
766	return (0);
767}
768
769static int
770bnx_set_priv_prop(um_device_t *umdevice, const char *pr_name,
771    uint_t pr_valsize, const void *pr_val)
772{
773	boolean_t refresh = B_FALSE;
774	long result;
775	int err = 0;
776
777	if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
778		if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) {
779			return (ENOTSUP);
780		}
781		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
782			return (EINVAL);
783		}
784		if (result != 1 && result != 0) {
785			return (EINVAL);
786		}
787		if (umdevice->hwinit.lnkcfg.param_2500fdx != (uint32_t)result) {
788			umdevice->hwinit.lnkcfg.param_2500fdx =
789			    (uint32_t)result;
790			umdevice->curcfg.lnkcfg.param_2500fdx =
791			    (uint32_t)result;
792			bnx_update_phy(umdevice);
793		}
794	} else if (strcmp(pr_name, "_checksum") == 0) {
795		if (umdevice->dev_start == B_TRUE) {
796			return (EBUSY);
797		}
798		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
799			return (EINVAL);
800		}
801		switch (result) {
802			case USER_OPTION_CKSUM_TX_ONLY:
803				umdevice->dev_var.enabled_oflds =
804				    LM_OFFLOAD_TX_IP_CKSUM |
805				    LM_OFFLOAD_TX_TCP_CKSUM |
806				    LM_OFFLOAD_TX_UDP_CKSUM;
807				break;
808
809			case USER_OPTION_CKSUM_RX_ONLY:
810				umdevice->dev_var.enabled_oflds =
811				    LM_OFFLOAD_RX_IP_CKSUM |
812				    LM_OFFLOAD_RX_TCP_CKSUM |
813				    LM_OFFLOAD_RX_UDP_CKSUM;
814				break;
815
816			case USER_OPTION_CKSUM_TX_RX:
817				umdevice->dev_var.enabled_oflds =
818				    LM_OFFLOAD_TX_IP_CKSUM |
819				    LM_OFFLOAD_RX_IP_CKSUM |
820				    LM_OFFLOAD_TX_TCP_CKSUM |
821				    LM_OFFLOAD_RX_TCP_CKSUM |
822				    LM_OFFLOAD_TX_UDP_CKSUM |
823				    LM_OFFLOAD_RX_UDP_CKSUM;
824				break;
825
826			case USER_OPTION_CKSUM_NONE:
827				umdevice->dev_var.enabled_oflds =
828				    LM_OFFLOAD_NONE;
829				break;
830
831			default:
832				return (EINVAL);
833		}
834	} else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
835		if (umdevice->dev_start == B_TRUE) {
836			return (EBUSY);
837		}
838		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
839			return (EINVAL);
840		}
841		if (result < USER_OPTION_TX_DESC_CNT_MIN ||
842		    result > USER_OPTION_TX_DESC_CNT_MAX) {
843			return (EINVAL);
844		}
845		_TX_QINFO(umdevice, 0).desc_cnt = result;
846		umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] =
847		    result / MAX_BD_PER_PAGE;
848		if (result % MAX_BD_PER_PAGE) {
849			umdevice->lm_dev.params.l2_tx_bd_page_cnt[0]++;
850		}
851		if (umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] > 127) {
852			umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] = 127;
853		}
854		refresh = B_TRUE;
855	} else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
856		if (umdevice->dev_start == B_TRUE) {
857			return (EBUSY);
858		}
859		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
860			return (EINVAL);
861		}
862		if (result < USER_OPTION_RX_DESC_CNT_MIN ||
863		    result > USER_OPTION_RX_DESC_CNT_MAX) {
864			return (EINVAL);
865		}
866		umdevice->lm_dev.params.l2_rx_desc_cnt[0] = result;
867		result = (result * BNX_RECV_MAX_FRAGS) / MAX_BD_PER_PAGE;
868		umdevice->lm_dev.params.l2_rx_bd_page_cnt[0] = result;
869		if (result % MAX_BD_PER_PAGE) {
870			umdevice->lm_dev.params.l2_rx_bd_page_cnt[0]++;
871		}
872		refresh = B_TRUE;
873	}
874#if 0
875	/* Initialized by init_hc() */
876	else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
877		if (umdevice->dev_start == B_TRUE) {
878			return (EBUSY);
879		}
880		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
881			return (EINVAL);
882		}
883		if (result < USER_OPTION_TICKS_MIN ||
884		    result > USER_OPTION_TICKS_MAX) {
885			return (EINVAL);
886		}
887		umdevice->lm_dev.params.tx_ticks = result;
888	} else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
889		if (umdevice->dev_start == B_TRUE) {
890			return (EBUSY);
891		}
892		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
893			return (EINVAL);
894		}
895		if (result < USER_OPTION_TICKS_INT_MIN ||
896		    result > USER_OPTION_TICKS_INT_MAX) {
897			return (EINVAL);
898		}
899		umdevice->lm_dev.params.tx_ticks_int = result;
900	} else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
901		if (umdevice->dev_start == B_TRUE) {
902			return (EBUSY);
903		}
904		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
905			return (EINVAL);
906		}
907		if (result < USER_OPTION_TICKS_MIN ||
908		    result > USER_OPTION_TICKS_MAX) {
909			return (EINVAL);
910		}
911		umdevice->lm_dev.params.rx_ticks = result;
912	} else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
913		if (umdevice->dev_start == B_TRUE) {
914			return (EBUSY);
915		}
916		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
917			return (EINVAL);
918		}
919		if (result < USER_OPTION_TICKS_INT_MIN ||
920		    result > USER_OPTION_TICKS_INT_MAX) {
921			return (EINVAL);
922		}
923		umdevice->lm_dev.params.rx_ticks_int = result;
924	} else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
925		if (umdevice->dev_start == B_TRUE) {
926			return (EBUSY);
927		}
928		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
929			return (EINVAL);
930		}
931		if (result < USER_OPTION_FRAMES_MIN ||
932		    result > USER_OPTION_FRAMES_MAX) {
933			return (EINVAL);
934		}
935		umdevice->lm_dev.params.tx_quick_cons_trip = result;
936	} else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
937		if (umdevice->dev_start == B_TRUE) {
938			return (EBUSY);
939		}
940		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
941			return (EINVAL);
942		}
943		if (result < USER_OPTION_FRAMES_MIN ||
944		    result > USER_OPTION_FRAMES_MAX) {
945			return (EINVAL);
946		}
947		umdevice->lm_dev.params.tx_quick_cons_trip_int = result;
948	} else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
949		if (umdevice->dev_start == B_TRUE) {
950			return (EBUSY);
951		}
952		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
953			return (EINVAL);
954		}
955		if (result < USER_OPTION_FRAMES_MIN ||
956		    result > USER_OPTION_FRAMES_MAX) {
957			return (EINVAL);
958		}
959		umdevice->lm_dev.params.rx_quick_cons_trip = result;
960	} else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
961		if (umdevice->dev_start == B_TRUE) {
962			return (EBUSY);
963		}
964		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
965			return (EINVAL);
966		}
967		if (result < USER_OPTION_FRAMES_MIN ||
968		    result > USER_OPTION_FRAMES_MAX) {
969			return (EINVAL);
970		}
971		umdevice->lm_dev.params.rx_quick_cons_trip_int = result;
972	} else if (strcmp(pr_name, "_statticks") == 0) {
973		if (umdevice->dev_start == B_TRUE) {
974			return (EBUSY);
975		}
976		if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
977			return (EINVAL);
978		}
979		if (result < USER_OPTION_STATSTICKS_MIN ||
980		    result > USER_OPTION_STATSTICKS_MAX) {
981			return (EINVAL);
982		}
983		umdevice->lm_dev.params.stats_ticks = result;
984	}
985#endif
986	else if (strcmp(pr_name, "_disable_msix") == 0) {
987		err = ENOTSUP;
988	} else {
989		err = ENOTSUP;
990	}
991
992	if (!err && refresh) {
993		err = bnx_refresh_rx_tx_pkts(umdevice);
994	}
995	return (err);
996}
997
998
999static int
1000bnx_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1001    uint_t pr_valsize, const void *pr_val)
1002{
1003	um_device_t *umdevice = arg;
1004	boolean_t reprogram = B_FALSE;
1005	boolean_t rxpause;
1006	boolean_t txpause;
1007	uint32_t mtu;
1008	link_flowctrl_t fl;
1009	int err = 0;
1010
1011	mutex_enter(&umdevice->os_param.gld_mutex);
1012
1013	if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1014		if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1015		    pr_num == MAC_PROP_EN_100HDX_CAP ||
1016		    pr_num == MAC_PROP_EN_10FDX_CAP ||
1017		    pr_num == MAC_PROP_EN_10HDX_CAP) {
1018			mutex_exit(&umdevice->os_param.gld_mutex);
1019			return (ENOTSUP);
1020		}
1021	}
1022
1023	switch (pr_num) {
1024		/* read-only properties */
1025		case MAC_PROP_ADV_1000FDX_CAP:
1026		case MAC_PROP_ADV_1000HDX_CAP:
1027		case MAC_PROP_ADV_100FDX_CAP:
1028		case MAC_PROP_ADV_100HDX_CAP:
1029		case MAC_PROP_ADV_10FDX_CAP:
1030		case MAC_PROP_ADV_10HDX_CAP:
1031		case MAC_PROP_STATUS:
1032		case MAC_PROP_SPEED:
1033		case MAC_PROP_DUPLEX:
1034		default:
1035
1036			err = ENOTSUP;
1037			break;
1038
1039
1040/* BEGIN CSTYLED */
1041#define	BNX_SETPROP_CASE(cap, param)							\
1042		case cap:								\
1043			if (umdevice->hwinit.lnkcfg.param != *(uint8_t *)pr_val) {	\
1044				umdevice->hwinit.lnkcfg.param = *(uint8_t *)pr_val;	\
1045				umdevice->curcfg.lnkcfg.param = *(uint8_t *)pr_val;	\
1046				reprogram = B_TRUE;					\
1047			}								\
1048			break
1049/* END CSTYLED */
1050
1051
1052		BNX_SETPROP_CASE(MAC_PROP_EN_1000FDX_CAP, param_1000fdx);
1053		BNX_SETPROP_CASE(MAC_PROP_EN_1000HDX_CAP, param_1000hdx);
1054		BNX_SETPROP_CASE(MAC_PROP_EN_100FDX_CAP, param_100fdx);
1055		BNX_SETPROP_CASE(MAC_PROP_EN_100HDX_CAP, param_100hdx);
1056		BNX_SETPROP_CASE(MAC_PROP_EN_10FDX_CAP, param_10fdx);
1057		BNX_SETPROP_CASE(MAC_PROP_EN_10HDX_CAP, param_10hdx);
1058		BNX_SETPROP_CASE(MAC_PROP_AUTONEG, link_autoneg);
1059
1060		case MAC_PROP_FLOWCTRL:
1061			bcopy(pr_val, &fl, sizeof (fl));
1062			switch (fl) {
1063				case LINK_FLOWCTRL_NONE:
1064
1065					rxpause = B_FALSE;
1066					txpause = B_FALSE;
1067					break;
1068
1069				case LINK_FLOWCTRL_RX:
1070
1071					rxpause = B_TRUE;
1072					txpause = B_FALSE;
1073					break;
1074
1075				case LINK_FLOWCTRL_TX:
1076
1077					rxpause = B_FALSE;
1078					txpause = B_TRUE;
1079					break;
1080
1081				case LINK_FLOWCTRL_BI:
1082
1083					rxpause = B_TRUE;
1084					txpause = B_TRUE;
1085					break;
1086
1087				default:
1088
1089					err = ENOTSUP;
1090					break;
1091			}
1092
1093			if (err == 0) {
1094				if (umdevice->hwinit.lnkcfg.param_tx_pause !=
1095				    txpause ||
1096				    umdevice->hwinit.lnkcfg.param_rx_pause !=
1097				    rxpause) {
1098					umdevice->hwinit.lnkcfg.param_tx_pause =
1099					    txpause;
1100					umdevice->hwinit.lnkcfg.param_rx_pause =
1101					    rxpause;
1102					umdevice->curcfg.lnkcfg.param_tx_pause =
1103					    txpause;
1104					umdevice->curcfg.lnkcfg.param_rx_pause =
1105					    rxpause;
1106					reprogram = B_TRUE;
1107				}
1108			}
1109
1110			break;
1111
1112		case MAC_PROP_MTU:
1113			if (umdevice->dev_start == B_TRUE) {
1114				err = EBUSY;
1115				break;
1116			}
1117
1118			bcopy(pr_val, &mtu, sizeof (mtu));
1119
1120			if (mtu < USER_OPTION_MTU_MIN ||
1121			    mtu > USER_OPTION_MTU_MAX) {
1122				err = EINVAL;
1123				break;
1124			}
1125
1126			if (umdevice->dev_var.mtu == mtu) {
1127				break;
1128			}
1129
1130			umdevice->dev_var.mtu = mtu;
1131			umdevice->lm_dev.params.mtu = umdevice->dev_var.mtu
1132			    + sizeof (struct ether_header) + VLAN_TAGSZ;
1133
1134			if (bnx_refresh_rx_tx_pkts(umdevice) != 0) {
1135				err = EIO;
1136			} else {
1137				reprogram = B_TRUE;
1138			}
1139			break;
1140
1141		case MAC_PROP_PRIVATE:
1142			err = bnx_set_priv_prop(umdevice, pr_name, pr_valsize,
1143			    pr_val);
1144			reprogram = B_TRUE;
1145			break;
1146	}
1147
1148	if (!err && reprogram) {
1149		bnx_update_phy(umdevice);
1150	}
1151
1152	mutex_exit(&umdevice->os_param.gld_mutex);
1153
1154	return (err);
1155}
1156
1157static int
1158bnx_get_priv_prop(um_device_t *umdevice, const char *pr_name,
1159    uint_t pr_valsize, void *pr_val)
1160{
1161	int value;
1162
1163	if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
1164		if (lm_get_medium(&umdevice->lm_dev) !=
1165		    LM_MEDIUM_TYPE_FIBER) {
1166			return (ENOTSUP);
1167		}
1168		value = umdevice->curcfg.lnkcfg.param_2500fdx;
1169	} else if (strcmp(pr_name, "_checksum") == 0) {
1170		value = umdevice->dev_var.enabled_oflds;
1171	} else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
1172		value = _TX_QINFO(umdevice, 0).desc_cnt;
1173	} else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
1174		value = umdevice->lm_dev.params.l2_rx_desc_cnt[0];
1175	} else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
1176		value = umdevice->lm_dev.params.tx_ticks;
1177	} else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
1178		value = umdevice->lm_dev.params.tx_ticks_int;
1179	} else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
1180		value = umdevice->lm_dev.params.rx_ticks;
1181	} else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
1182		value = umdevice->lm_dev.params.rx_ticks_int;
1183	} else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
1184		value = umdevice->lm_dev.params.tx_quick_cons_trip;
1185	} else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
1186		value = umdevice->lm_dev.params.tx_quick_cons_trip_int;
1187	} else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
1188		value = umdevice->lm_dev.params.rx_quick_cons_trip;
1189	} else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
1190		value = umdevice->lm_dev.params.rx_quick_cons_trip_int;
1191	} else if (strcmp(pr_name, "_statticks") == 0) {
1192		value = umdevice->lm_dev.params.stats_ticks;
1193	} else if (strcmp(pr_name, "_disable_msix") == 0) {
1194		value = umdevice->dev_var.disableMsix;
1195	} else {
1196		return (ENOTSUP);
1197	}
1198
1199	(void) snprintf(pr_val, pr_valsize, "%d", value);
1200	return (0);
1201
1202}
1203
1204static int
1205bnx_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1206    uint_t pr_valsize, void *pr_val)
1207{
1208	um_device_t *umdevice = arg;
1209	link_duplex_t link_duplex;
1210	uint64_t link_speed;
1211	link_state_t link_state;
1212	link_flowctrl_t fl;
1213
1214	if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1215		if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1216		    pr_num == MAC_PROP_EN_100HDX_CAP ||
1217		    pr_num == MAC_PROP_EN_10FDX_CAP ||
1218		    pr_num == MAC_PROP_EN_10HDX_CAP) {
1219			return (ENOTSUP);
1220		}
1221	}
1222
1223	switch (pr_num) {
1224		case MAC_PROP_DUPLEX:
1225			link_duplex = umdevice->nddcfg.link_duplex == B_TRUE ?
1226			    LINK_DUPLEX_FULL: LINK_DUPLEX_HALF;
1227
1228			ASSERT(pr_valsize >= sizeof (link_duplex_t));
1229
1230			bcopy(&link_duplex, pr_val, sizeof (link_duplex_t));
1231			break;
1232
1233		case MAC_PROP_SPEED:
1234			link_speed = umdevice->nddcfg.link_speed * 1000000ull;
1235
1236			ASSERT(pr_valsize >= sizeof (link_speed));
1237
1238			bcopy(&link_speed, pr_val, sizeof (link_speed));
1239			break;
1240
1241		case MAC_PROP_STATUS:
1242			link_state = umdevice->nddcfg.link_speed ?
1243			    LINK_STATE_UP : LINK_STATE_DOWN;
1244
1245			ASSERT(pr_valsize >= sizeof (link_state_t));
1246
1247			bcopy(&link_state, pr_val, sizeof (link_state));
1248			break;
1249
1250		case MAC_PROP_AUTONEG:
1251			*(uint8_t *)pr_val =
1252			    umdevice->curcfg.lnkcfg.link_autoneg;
1253			break;
1254
1255		case MAC_PROP_FLOWCTRL:
1256			ASSERT(pr_valsize >= sizeof (fl));
1257
1258			boolean_t txpause =
1259			    umdevice->curcfg.lnkcfg.param_tx_pause;
1260			boolean_t rxpause =
1261			    umdevice->curcfg.lnkcfg.param_rx_pause;
1262			if (txpause) {
1263				if (rxpause) {
1264					fl = LINK_FLOWCTRL_BI;
1265				} else {
1266					fl = LINK_FLOWCTRL_TX;
1267				}
1268			} else {
1269				if (rxpause) {
1270					fl = LINK_FLOWCTRL_RX;
1271				} else {
1272					fl = LINK_FLOWCTRL_NONE;
1273				}
1274			}
1275			bcopy(&fl, pr_val, sizeof (fl));
1276			break;
1277
1278		case MAC_PROP_ADV_1000FDX_CAP:
1279			*(uint8_t *)pr_val =
1280			    umdevice->curcfg.lnkcfg.param_1000fdx;
1281			break;
1282
1283		case MAC_PROP_EN_1000FDX_CAP:
1284			*(uint8_t *)pr_val =
1285			    umdevice->curcfg.lnkcfg.param_1000fdx;
1286			break;
1287
1288		case MAC_PROP_ADV_1000HDX_CAP:
1289			*(uint8_t *)pr_val =
1290			    umdevice->curcfg.lnkcfg.param_1000hdx;
1291			break;
1292
1293		case MAC_PROP_EN_1000HDX_CAP:
1294			*(uint8_t *)pr_val =
1295			    umdevice->curcfg.lnkcfg.param_1000hdx;
1296			break;
1297
1298		case MAC_PROP_ADV_100FDX_CAP:
1299			*(uint8_t *)pr_val =
1300			    umdevice->curcfg.lnkcfg.param_100fdx;
1301			break;
1302
1303		case MAC_PROP_EN_100FDX_CAP:
1304			*(uint8_t *)pr_val =
1305			    umdevice->curcfg.lnkcfg.param_100fdx;
1306			break;
1307
1308		case MAC_PROP_ADV_100HDX_CAP:
1309			*(uint8_t *)pr_val =
1310			    umdevice->curcfg.lnkcfg.param_100hdx;
1311			break;
1312
1313		case MAC_PROP_EN_100HDX_CAP:
1314			*(uint8_t *)pr_val =
1315			    umdevice->curcfg.lnkcfg.param_100hdx;
1316			break;
1317
1318		case MAC_PROP_ADV_10FDX_CAP:
1319			*(uint8_t *)pr_val =
1320			    umdevice->curcfg.lnkcfg.param_10fdx;
1321			break;
1322
1323		case MAC_PROP_EN_10FDX_CAP:
1324			*(uint8_t *)pr_val =
1325			    umdevice->curcfg.lnkcfg.param_10fdx;
1326			break;
1327
1328		case MAC_PROP_ADV_10HDX_CAP:
1329			*(uint8_t *)pr_val =
1330			    umdevice->curcfg.lnkcfg.param_10hdx;
1331			break;
1332
1333		case MAC_PROP_EN_10HDX_CAP:
1334			*(uint8_t *)pr_val =
1335			    umdevice->curcfg.lnkcfg.param_10hdx;
1336			break;
1337
1338		case MAC_PROP_PRIVATE:
1339			return (bnx_get_priv_prop(umdevice, pr_name, pr_valsize,
1340			    pr_val));
1341
1342		default:
1343
1344			return (ENOTSUP);
1345
1346	}
1347
1348	return (0);
1349
1350}
1351
1352static void
1353bnx_priv_propinfo(um_device_t *umdevice, const char *pr_name,
1354    mac_prop_info_handle_t prh)
1355{
1356	char valstr[64];
1357	int value;
1358
1359	if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
1360		if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) {
1361			return;
1362		}
1363		value = umdevice->curcfg.lnkcfg.param_2500fdx;
1364	} else if (strcmp(pr_name, "_checksum") == 0) {
1365		value = umdevice->dev_var.enabled_oflds;
1366	} else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
1367		value = _TX_QINFO(umdevice, 0).desc_cnt;
1368	} else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
1369		value = umdevice->lm_dev.params.l2_rx_desc_cnt[0];
1370	} else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
1371		value = umdevice->lm_dev.params.tx_ticks;
1372	} else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
1373		value = umdevice->lm_dev.params.tx_ticks_int;
1374	} else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
1375		value = umdevice->lm_dev.params.rx_ticks;
1376	} else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
1377		value = umdevice->lm_dev.params.rx_ticks_int;
1378	} else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
1379		value = umdevice->lm_dev.params.tx_quick_cons_trip;
1380	} else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
1381		value = umdevice->lm_dev.params.tx_quick_cons_trip_int;
1382	} else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
1383		value = umdevice->lm_dev.params.rx_quick_cons_trip;
1384	} else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
1385		value = umdevice->lm_dev.params.rx_quick_cons_trip_int;
1386	} else if (strcmp(pr_name, "_statticks") == 0) {
1387		value = umdevice->lm_dev.params.stats_ticks;
1388	} else if (strcmp(pr_name, "_disable_msix") == 0) {
1389		value = umdevice->dev_var.disableMsix;
1390	} else {
1391		return;
1392	}
1393
1394	(void) snprintf(valstr, sizeof (valstr), "%d", value);
1395	mac_prop_info_set_default_str(prh, valstr);
1396
1397}
1398
1399static void
1400bnx_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1401    mac_prop_info_handle_t prh)
1402{
1403	um_device_t *umdevice = arg;
1404
1405	if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1406		if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1407		    pr_num == MAC_PROP_ADV_100FDX_CAP ||
1408		    pr_num == MAC_PROP_EN_100HDX_CAP ||
1409		    pr_num == MAC_PROP_ADV_100HDX_CAP ||
1410		    pr_num == MAC_PROP_EN_10FDX_CAP ||
1411		    pr_num == MAC_PROP_ADV_10FDX_CAP ||
1412		    pr_num == MAC_PROP_EN_10HDX_CAP ||
1413		    pr_num == MAC_PROP_ADV_10HDX_CAP) {
1414			mac_prop_info_set_default_uint8(prh, 0);
1415			return;
1416		}
1417	}
1418	switch (pr_num) {
1419		case MAC_PROP_ADV_1000FDX_CAP:
1420		case MAC_PROP_ADV_1000HDX_CAP:
1421		case MAC_PROP_ADV_100FDX_CAP:
1422		case MAC_PROP_ADV_100HDX_CAP:
1423		case MAC_PROP_ADV_10FDX_CAP:
1424		case MAC_PROP_ADV_10HDX_CAP:
1425		case MAC_PROP_STATUS:
1426		case MAC_PROP_SPEED:
1427		case MAC_PROP_DUPLEX:
1428
1429			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1430			break;
1431
1432		case MAC_PROP_EN_1000FDX_CAP:
1433
1434			mac_prop_info_set_default_uint8(prh, 1);
1435			break;
1436
1437		case MAC_PROP_EN_1000HDX_CAP:
1438		case MAC_PROP_EN_100FDX_CAP:
1439		case MAC_PROP_EN_100HDX_CAP:
1440		case MAC_PROP_EN_10FDX_CAP:
1441		case MAC_PROP_EN_10HDX_CAP:
1442
1443			if (lm_get_medium(&umdevice->lm_dev) ==
1444			    LM_MEDIUM_TYPE_FIBER) {
1445				mac_prop_info_set_default_uint8(prh, 0);
1446			} else {
1447				mac_prop_info_set_default_uint8(prh, 1);
1448			}
1449			break;
1450
1451		case MAC_PROP_AUTONEG:
1452
1453			mac_prop_info_set_default_uint8(prh, 1);
1454			break;
1455
1456		case MAC_PROP_FLOWCTRL:
1457
1458			mac_prop_info_set_default_link_flowctrl(prh,
1459			    LINK_FLOWCTRL_BI);
1460			break;
1461
1462		case MAC_PROP_MTU:
1463
1464			mac_prop_info_set_range_uint32(prh,
1465			    USER_OPTION_MTU_MIN, USER_OPTION_MTU_MAX);
1466			break;
1467
1468		case MAC_PROP_PRIVATE:
1469
1470			bnx_priv_propinfo(umdevice, pr_name, prh);
1471			break;
1472		default:
1473			break;
1474	}
1475}
1476
1477static mac_callbacks_t bnx_callbacks = {
1478	(MC_GETCAPAB | MC_SETPROP | MC_GETPROP| MC_PROPINFO),
1479	bnx_m_stats,
1480	bnx_m_start,
1481	bnx_m_stop,
1482	bnx_m_promiscuous,
1483	bnx_m_multicast,
1484	bnx_m_unicast,
1485	bnx_m_tx,
1486	NULL,
1487	NULL,
1488	bnx_m_getcapab,
1489	NULL,
1490	NULL,
1491	bnx_m_setprop,
1492	bnx_m_getprop,
1493	bnx_m_propinfo
1494};
1495
1496
1497
1498/*
1499 * Name:    bnx_gld_init
1500 *
1501 * Input:   ptr to device structure.
1502 *
1503 * Return:  DDI_SUCCESS or DDI_FAILURE
1504 *
1505 * Description:
1506 *          This routine populates mac info structure for this device
1507 *          instance and registers device with GLD.
1508 */
1509int
1510bnx_gld_init(um_device_t *const umdevice)
1511{
1512	mac_register_t *macp;
1513	int rc;
1514
1515	umdevice->dev_start = B_FALSE;
1516
1517	mutex_init(&umdevice->os_param.gld_mutex, NULL,
1518	    MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority));
1519
1520	rw_init(&umdevice->os_param.gld_snd_mutex, NULL, RW_DRIVER, NULL);
1521
1522	macp = mac_alloc(MAC_VERSION);
1523	if (macp == NULL) {
1524		cmn_err(CE_WARN,
1525		    "%s: Failed to allocate GLD MAC memory.\n",
1526		    umdevice->dev_name);
1527		goto error;
1528	}
1529
1530	macp->m_driver = umdevice;
1531	macp->m_dip = umdevice->os_param.dip;
1532	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1533	macp->m_callbacks = &bnx_callbacks;
1534	macp->m_min_sdu = 0;
1535	macp->m_max_sdu = umdevice->dev_var.mtu;
1536	macp->m_src_addr  = &(umdevice->lm_dev.params.mac_addr[0]);
1537
1538	macp->m_margin = VLAN_TAG_SIZE;
1539
1540	/*
1541	 * Call mac_register() after initializing all
1542	 * the required elements of mac_t struct.
1543	 */
1544	rc = mac_register(macp, &umdevice->os_param.macp);
1545
1546	mac_free(macp);
1547
1548	if (rc != 0) {
1549		cmn_err(CE_WARN,
1550		    "%s: Failed to register with GLD.\n",
1551		    umdevice->dev_name);
1552		goto error;
1553	}
1554
1555	/* Always report the initial link state as unknown. */
1556	bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
1557
1558	return (0);
1559
1560error:
1561	rw_destroy(&umdevice->os_param.gld_snd_mutex);
1562	mutex_destroy(&umdevice->os_param.gld_mutex);
1563
1564	return (-1);
1565}
1566
1567void
1568bnx_gld_link(um_device_t * const umdevice, const link_state_t linkup)
1569{
1570	mac_link_update(umdevice->os_param.macp, linkup);
1571}
1572
1573int
1574bnx_gld_fini(um_device_t * const umdevice)
1575{
1576	if (umdevice->dev_start != B_FALSE) {
1577		cmn_err(CE_WARN,
1578		    "%s: Detaching device from GLD that is still started!!!\n",
1579		    umdevice->dev_name);
1580		return (-1);
1581	}
1582
1583	if (mac_unregister(umdevice->os_param.macp)) {
1584		cmn_err(CE_WARN,
1585		    "%s: Failed to unregister with the GLD.\n",
1586		    umdevice->dev_name);
1587		return (-1);
1588	}
1589
1590	rw_destroy(&umdevice->os_param.gld_snd_mutex);
1591	mutex_destroy(&umdevice->os_param.gld_mutex);
1592
1593	return (0);
1594}
1595