xref: /illumos-gate/usr/src/uts/common/io/bnxe/bnxe_gld.c (revision f20211217f12ce291fd518e61065cd273f23e4ea)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2014 QLogic Corporation
24  * The contents of this file are subject to the terms of the
25  * QLogic End User License (the "License").
26  * You may not use this file except in compliance with the License.
27  *
28  * You can obtain a copy of the License at
29  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30  * QLogic_End_User_Software_License.txt
31  * See the License for the specific language governing permissions
32  * and limitations under the License.
33  */
34 
35 /*
36  * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
37  * Copyright (c) 2017, Joyent, Inc.
38  */
39 
40 #include "bnxe.h"
41 
42 #include <sys/mac.h>
43 #include <sys/mac_ether.h>
44 #include <sys/dlpi.h>
45 
46 #if !(defined(__S11) || defined(__S12))
47 #define mri_driver  mr_driver
48 #define mri_start   mr_start
49 #define mri_stop    mr_stop
50 #define mri_intr    mr_intr
51 #define mri_poll    mr_poll
52 #define mri_tx      mr_send
53 #define mgi_driver  mrg_driver
54 #define mgi_start   mrg_start
55 #define mgi_stop    mrg_stop
56 #define mgi_count   mrg_count
57 #define mgi_addmac  mrg_addmac
58 #define mgi_remmac  mrg_addmac
59 #define mr_gaddring mr_gadd_ring
60 #define mr_gremring mr_grem_ring
61 #endif /* not __S11 or __S12 */
62 
63 /*
64  * Reconfiguring the network devices parameters require net_config
65  * privilege starting Solaris 10.  Only root user is allowed to
66  * update device parameter in Solaris 9 and earlier version. Following
67  * declaration allows single binary image to run on all OS versions.
68  */
69 extern int secpolicy_net_config(const cred_t *, boolean_t);
70 extern int drv_priv(cred_t *);
71 #pragma weak secpolicy_net_config
72 #pragma weak drv_priv
73 
74 #ifdef MC_SETPROP
75 
76 char * bnxeLink_priv_props[] =
77 {
78     "_adv_2500fdx_cap",
79     "_en_2500fdx_cap",
80     "_adv_txpause_cap",
81     "_en_txpause_cap",
82     "_txpause",
83     "_adv_rxpause_cap",
84     "_en_rxpause_cap",
85     "_rxpause",
86     "_autoneg_flow",
87     "_checksum",
88     "_num_rings",
89     "_rx_descs",
90     "_rx_free_reclaim",
91     "_rx_copy_threshold",
92     "_tx_descs",
93     "_tx_free_reclaim",
94     "_tx_copy_threshold",
95     "_tx_ring_policy",
96     "_interrupt_coalesce",
97     "_rx_interrupt_coalesce_usec",
98     "_tx_interrupt_coalesce_usec",
99     "_disable_msix",
100     "_l2_fw_flow_ctrl",
101     "_autogreeen_enable",
102     "_lso_enable",
103     "_log_enable",
104     "_fcoe_enable",
105     NULL
106 };
107 
108 #endif /* MC_SETPROP */
109 
110 
111 static int BnxeMacStats(void *     pArg,
112                         uint_t     stat,
113                         uint64_t * pVal)
114 {
115     um_device_t * pUM = (um_device_t *)pArg;
116     lm_device_t * pLM;
117     b10_l2_chip_statistics_t b10_l2_stats;
118     int idx, rc = 0;
119 
120     if ((pUM == NULL) || (pVal == NULL))
121     {
122         return EINVAL;
123     }
124 
125     pLM = &pUM->lm_dev;
126 
127     BNXE_LOCK_ENTER_GLD(pUM);
128 
129     if (!pUM->plumbed)
130     {
131         BNXE_LOCK_EXIT_GLD(pUM);
132         return EAGAIN;
133     }
134 
135     *pVal = 0;
136 
137     switch (stat)
138     {
139     case MAC_STAT_IFSPEED:
140         *pVal = (pUM->props.link_speed * 1000000ULL);
141         break;
142 
143     case MAC_STAT_MULTIRCV:
144         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
145                                    L2_CHIP_STATISTICS_VER_NUM_1);
146         *pVal = b10_l2_stats.IfHCInMulticastPkts;
147         break;
148 
149     case MAC_STAT_BRDCSTRCV:
150         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
151                                    L2_CHIP_STATISTICS_VER_NUM_1);
152         *pVal = b10_l2_stats.IfHCInBroadcastPkts;
153         break;
154 
155     case MAC_STAT_MULTIXMT:
156         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
157                                    L2_CHIP_STATISTICS_VER_NUM_1);
158         *pVal = b10_l2_stats.IfHCOutMulticastPkts;
159         break;
160 
161     case MAC_STAT_BRDCSTXMT:
162         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
163                                    L2_CHIP_STATISTICS_VER_NUM_1);
164         *pVal = b10_l2_stats.IfHCOutBroadcastPkts;
165         break;
166 
167     case MAC_STAT_NORCVBUF:
168         lm_get_stats(pLM, LM_STATS_RCV_NO_BUFFER_DROP, (u64_t *)pVal);
169         break;
170 
171     case MAC_STAT_NOXMTBUF:
172         *pVal = 0;
173         LM_FOREACH_TSS_IDX(pLM, idx)
174         {
175             *pVal += pUM->txq[idx].txRecycle;
176         }
177         break;
178 
179     case MAC_STAT_IERRORS:
180     case ETHER_STAT_MACRCV_ERRORS:
181         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
182                                    L2_CHIP_STATISTICS_VER_NUM_1);
183         *pVal = b10_l2_stats.IfInErrors;
184         break;
185 
186     case MAC_STAT_OERRORS:
187         /* XXX not available */
188         break;
189 
190     case MAC_STAT_COLLISIONS:
191         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
192                                    L2_CHIP_STATISTICS_VER_NUM_1);
193         *pVal = b10_l2_stats.EtherStatsCollisions;
194         break;
195 
196     case MAC_STAT_RBYTES:
197         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
198                                    L2_CHIP_STATISTICS_VER_NUM_1);
199         *pVal = b10_l2_stats.IfHCInOctets;
200         break;
201 
202     case MAC_STAT_IPACKETS:
203         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
204                                    L2_CHIP_STATISTICS_VER_NUM_1);
205         *pVal = b10_l2_stats.IfHCInPkts;
206         break;
207 
208     case MAC_STAT_OBYTES:
209         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
210                                    L2_CHIP_STATISTICS_VER_NUM_1);
211         *pVal = b10_l2_stats.IfHCOutOctets;
212         break;
213 
214     case MAC_STAT_OPACKETS:
215         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
216                                    L2_CHIP_STATISTICS_VER_NUM_1);
217         *pVal = b10_l2_stats.IfHCOutPkts;
218         break;
219 
220     case ETHER_STAT_ALIGN_ERRORS:
221         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
222                                    L2_CHIP_STATISTICS_VER_NUM_1);
223         *pVal = b10_l2_stats.Dot3StatsAlignmentErrors;
224         break;
225 
226     case ETHER_STAT_FCS_ERRORS:
227         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
228                                    L2_CHIP_STATISTICS_VER_NUM_1);
229         *pVal = b10_l2_stats.Dot3StatsFCSErrors;
230         break;
231 
232     case ETHER_STAT_FIRST_COLLISIONS:
233         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
234                                    L2_CHIP_STATISTICS_VER_NUM_1);
235         *pVal = b10_l2_stats.Dot3StatsSingleCollisionFrames;
236         break;
237 
238     case ETHER_STAT_MULTI_COLLISIONS:
239         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
240                                    L2_CHIP_STATISTICS_VER_NUM_1);
241         *pVal = b10_l2_stats.Dot3StatsMultipleCollisionFrames;
242         break;
243 
244     case ETHER_STAT_DEFER_XMTS:
245         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
246                                    L2_CHIP_STATISTICS_VER_NUM_1);
247         *pVal = b10_l2_stats.Dot3StatsDeferredTransmissions;
248         break;
249 
250     case ETHER_STAT_TX_LATE_COLLISIONS:
251         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
252                                    L2_CHIP_STATISTICS_VER_NUM_1);
253         *pVal = b10_l2_stats.Dot3StatsLateCollisions;
254         break;
255 
256     case ETHER_STAT_EX_COLLISIONS:
257         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
258                                    L2_CHIP_STATISTICS_VER_NUM_1);
259         *pVal = b10_l2_stats.Dot3StatsExcessiveCollisions;
260         break;
261 
262     case ETHER_STAT_MACXMT_ERRORS:
263         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
264                                    L2_CHIP_STATISTICS_VER_NUM_1);
265         *pVal = b10_l2_stats.Dot3StatsInternalMacTransmitErrors;
266         break;
267 
268     case ETHER_STAT_CARRIER_ERRORS:
269         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
270                                    L2_CHIP_STATISTICS_VER_NUM_1);
271         *pVal = b10_l2_stats.Dot3StatsCarrierSenseErrors;
272         break;
273 
274     case ETHER_STAT_TOOLONG_ERRORS:
275         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
276                                    L2_CHIP_STATISTICS_VER_NUM_1);
277         *pVal = b10_l2_stats.EtherStatsOverrsizePkts;
278         break;
279 
280 #if (MAC_VERSION > 1)
281     case ETHER_STAT_TOOSHORT_ERRORS:
282         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
283                                    L2_CHIP_STATISTICS_VER_NUM_1);
284         *pVal = b10_l2_stats.EtherStatsUndersizePkts;
285         break;
286 #endif
287 
288     case ETHER_STAT_XCVR_ADDR:
289         *pVal = pLM->vars.phy_addr;
290         break;
291 
292     case ETHER_STAT_XCVR_ID:
293         *pVal = 0;
294         break;
295 
296     case ETHER_STAT_XCVR_INUSE:
297         switch (pUM->props.link_speed)
298         {
299         case 0: /* no speed then status is down */
300             *pVal = XCVR_NONE;
301             break;
302 
303         case 1000:
304             *pVal = XCVR_1000X;
305             break;
306 
307         case 100:
308             *pVal = XCVR_100X;
309             break;
310 
311         case 10:
312             *pVal = XCVR_10;
313             break;
314 
315         default:
316             /* catches 2500/10000 */
317             *pVal = XCVR_UNDEFINED;
318         }
319         break;
320 
321 #if (MAC_VERSION > 1)
322     case ETHER_STAT_CAP_10GFDX:
323         *pVal = 1;
324         break;
325 #endif
326 
327     case ETHER_STAT_CAP_1000FDX:
328         *pVal = 1;
329         break;
330 
331 #if 0
332     case ETHER_STAT_CAP_1000HDX:
333         //*pVal = linkconf->param_1000hdx;
334         *pVal = 0;
335         break;
336 #endif
337 
338     case ETHER_STAT_CAP_100FDX:
339         //*pVal = linkconf->param_100fdx;
340         *pVal = 1;
341         break;
342 
343     case ETHER_STAT_CAP_100HDX:
344         //*pVal = linkconf->param_100hdx;
345         *pVal = 1;
346         break;
347 
348     case ETHER_STAT_CAP_10FDX:
349         //*pVal = linkconf->param_10fdx;
350         *pVal = 1;
351         break;
352 
353     case ETHER_STAT_CAP_10HDX:
354         //*pVal = linkconf->param_10hdx;
355         *pVal = 1;
356         break;
357 
358     case ETHER_STAT_CAP_ASMPAUSE:
359         *pVal = 1;
360         break;
361 
362     case ETHER_STAT_CAP_PAUSE:
363         *pVal = 1;
364         break;
365 
366     case ETHER_STAT_CAP_AUTONEG:
367         *pVal = 1;
368         break;
369 
370 #if (MAC_VERSION > 1)
371     case ETHER_STAT_CAP_REMFAULT:
372         *pVal = 1;
373         break;
374 #endif
375 
376 #if (MAC_VERSION > 1)
377     case ETHER_STAT_ADV_CAP_10GFDX:
378         *pVal = pUM->curcfg.lnkcfg.param_10000fdx;
379         break;
380 #endif
381 
382     case ETHER_STAT_ADV_CAP_1000FDX:
383         *pVal = pUM->curcfg.lnkcfg.param_1000fdx;
384         break;
385 
386 #if 0
387     case ETHER_STAT_ADV_CAP_1000HDX:
388         //*pVal = pUM->curcfg.lnkcfg.param_1000hdx;
389         *pVal = 0;
390         break;
391 #endif
392 
393     case ETHER_STAT_ADV_CAP_100FDX:
394         *pVal = pUM->curcfg.lnkcfg.param_100fdx;
395         break;
396 
397     case ETHER_STAT_ADV_CAP_100HDX:
398         *pVal = pUM->curcfg.lnkcfg.param_100hdx;
399         break;
400 
401     case ETHER_STAT_ADV_CAP_10FDX:
402         *pVal = pUM->curcfg.lnkcfg.param_10fdx;
403         break;
404 
405     case ETHER_STAT_ADV_CAP_10HDX:
406         *pVal = pUM->curcfg.lnkcfg.param_10hdx;
407         break;
408 
409     case ETHER_STAT_ADV_CAP_ASMPAUSE:
410         *pVal = 1;
411         break;
412 
413     case ETHER_STAT_ADV_CAP_PAUSE:
414         *pVal = 1;
415         break;
416 
417     case ETHER_STAT_ADV_CAP_AUTONEG:
418         *pVal = pUM->curcfg.lnkcfg.link_autoneg;
419         break;
420 
421 #if (MAC_VERSION > 1)
422     case ETHER_STAT_ADV_REMFAULT:
423         *pVal = 1;
424         break;
425 #endif
426 
427 #if 0 /* LP caps not supported */
428 #if (MAC_VERSION > 1)
429     case ETHER_STAT_LP_CAP_10GFDX:
430         *pVal = pUM->remote.param_10000fdx;
431         break;
432 #endif
433 
434     case ETHER_STAT_LP_CAP_1000FDX:
435         *pVal = pUM->remote.param_1000fdx;
436         break;
437 
438 #if 0
439     case ETHER_STAT_LP_CAP_1000HDX:
440         //*pVal = pUM->remote.param_1000hdx;
441         *pVal = 0;
442         break;
443 #endif
444 
445     case ETHER_STAT_LP_CAP_100FDX:
446         *pVal = pUM->remote.param_100fdx;
447         break;
448 
449     case ETHER_STAT_LP_CAP_100HDX:
450         *pVal = pUM->remote.param_100hdx;
451         break;
452 
453     case ETHER_STAT_LP_CAP_10FDX:
454         *pVal = pUM->remote.param_10fdx;
455         break;
456 
457     case ETHER_STAT_LP_CAP_10HDX:
458         *pVal = pUM->remote.param_10hdx;
459         break;
460 
461 #if 0
462     case ETHER_STAT_LP_CAP_ASMPAUSE:
463         /* XXX implement LP_ASYM_PAUSE stat */
464         break;
465 
466     case ETHER_STAT_LP_CAP_PAUSE:
467         /* XXX implement LP_PAUSE stat */
468         break;
469 #endif
470 
471     case ETHER_STAT_LP_CAP_AUTONEG:
472         *pVal = pUM->remote.link_autoneg;
473         break;
474 
475     case ETHER_STAT_LP_REMFAULT:
476         /* XXX implement LP_REMFAULT stat */
477         break;
478 #endif /* LP caps not supported */
479 
480 #if 0
481     case ETHER_STAT_LINK_ASMPAUSE:
482         /* XXX implement ASMPAUSE stat */
483         break;
484 
485     case ETHER_STAT_LINK_PAUSE:
486         /* XXX implement PAUSE stat */
487         break;
488 #endif
489 
490     case ETHER_STAT_LINK_AUTONEG:
491         *pVal = pUM->curcfg.lnkcfg.link_autoneg;
492         break;
493 
494     case ETHER_STAT_LINK_DUPLEX:
495         *pVal = (pUM->props.link_duplex == B_TRUE) ?
496                     LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
497         break;
498 
499     default:
500         rc = ENOTSUP;
501     }
502 
503     BNXE_LOCK_EXIT_GLD(pUM);
504 
505     return rc;
506 }
507 
508 
509 
510 /*
511  * This routine is called by GLD to enable device for packet reception and
512  * enable interrupts.
513  */
514 static int BnxeMacStart(void * pArg)
515 {
516     um_device_t * pUM = (um_device_t *)pArg;
517 
518     BNXE_LOCK_ENTER_GLD(pUM);
519 
520     if (pUM->plumbed)
521     {
522         /* already started */
523         BNXE_LOCK_EXIT_GLD(pUM);
524         return EAGAIN;
525     }
526 
527     /* Always report the initial link state as unknown. */
528     mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
529 
530     if (BnxeHwStartL2(pUM))
531     {
532         BNXE_LOCK_EXIT_GLD(pUM);
533         return EIO;
534     }
535 
536     atomic_swap_32(&pUM->plumbed, B_TRUE);
537 
538     mutex_enter(&bnxeLoaderMutex);
539     bnxeNumPlumbed++;
540     mutex_exit(&bnxeLoaderMutex);
541 
542     BNXE_LOCK_EXIT_GLD(pUM);
543 
544     return 0;
545 }
546 
547 
548 /*
549  * This routine stops packet reception by clearing RX MASK register.  Also
550  * interrupts are disabled for this device.
551  */
552 static void BnxeMacStop(void * pArg)
553 {
554     um_device_t * pUM = (um_device_t *)pArg;
555 
556     BNXE_LOCK_ENTER_GLD(pUM);
557 
558     if (pUM->plumbed)
559     {
560         atomic_swap_32(&pUM->plumbed, B_FALSE);
561 
562         BnxeHwStopL2(pUM);
563 
564         /* Report the link state back to unknown. */
565         mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
566 
567         mutex_enter(&bnxeLoaderMutex);
568         bnxeNumPlumbed--;
569         mutex_exit(&bnxeLoaderMutex);
570     }
571 
572     BNXE_LOCK_EXIT_GLD(pUM);
573 }
574 
575 /* (flag) TRUE = on, FALSE = off */
576 static int BnxeMacPromiscuous(void *    pArg,
577                               boolean_t flag)
578 {
579     um_device_t * pUM = (um_device_t *)pArg;
580 
581     BNXE_LOCK_ENTER_GLD(pUM);
582 
583     if (!pUM->plumbed)
584     {
585         BNXE_LOCK_EXIT_GLD(pUM);
586         return EAGAIN;
587     }
588 
589     if (flag)
590     {
591         pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] |=
592             LM_RX_MASK_PROMISCUOUS_MODE;
593     }
594     else
595     {
596         pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &=
597             ~LM_RX_MASK_PROMISCUOUS_MODE;
598     }
599 
600     BNXE_LOCK_ENTER_HWINIT(pUM);
601 
602     if (BnxeRxMask(pUM, LM_CLI_IDX_NDIS,
603                    pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]) < 0)
604     {
605         BNXE_LOCK_EXIT_HWINIT(pUM);
606         BNXE_LOCK_EXIT_GLD(pUM);
607         return ECANCELED;
608     }
609 
610     BNXE_LOCK_EXIT_HWINIT(pUM);
611 
612     BNXE_LOCK_EXIT_GLD(pUM);
613 
614     return 0;
615 }
616 
617 
618 /*
619  * This function is used to enable or disable multicast packet reception for
620  * particular multicast addresses.
621  * (flag) TRUE = add, FALSE = remove
622  */
623 static int BnxeMacMulticast(void *          pArg,
624                             boolean_t       flag,
625                             const uint8_t * pMcastAddr)
626 {
627     um_device_t * pUM = (um_device_t *)pArg;
628     int rc;
629 
630     BNXE_LOCK_ENTER_GLD(pUM);
631 
632     if (!pUM->plumbed)
633     {
634         BNXE_LOCK_EXIT_GLD(pUM);
635         return EAGAIN;
636     }
637 
638     BNXE_LOCK_ENTER_HWINIT(pUM);
639     rc = BnxeMulticast(pUM, LM_CLI_IDX_NDIS, flag, pMcastAddr, B_TRUE);
640     BNXE_LOCK_EXIT_HWINIT(pUM);
641 
642     BNXE_LOCK_EXIT_GLD(pUM);
643 
644     return rc;
645 }
646 
647 
648 #ifdef BNXE_RINGS
649 
650 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
651 static int BnxeRxRingGroupAddMac(void *          groupHandle,
652                                  const uint8_t * pMacAddr,
653                                  uint64_t        flags)
654 #else
655 static int BnxeRxRingGroupAddMac(void *          groupHandle,
656                                  const uint8_t * pMacAddr)
657 #endif
658 {
659     RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle;
660     um_device_t *  pUM       = (um_device_t *)pRxQGroup->pUM;
661     //u32_t          idx       = pRxQGroup->idx;
662     int rc;
663 
664 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
665     _NOTE(ARGUNUSED(flags))
666 #endif
667 
668     BNXE_LOCK_ENTER_GLD(pUM);
669 
670     if (!pUM->plumbed)
671     {
672         BNXE_LOCK_EXIT_GLD(pUM);
673         return ECANCELED;
674     }
675 
676     /* Validate MAC address */
677     if (IS_ETH_MULTICAST(pMacAddr))
678     {
679         BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address.");
680         BNXE_LOCK_EXIT_GLD(pUM);
681         return EINVAL;
682     }
683 
684     if (pUM->ucastTableLen == LM_MAX_UC_TABLE_SIZE)
685     {
686         BNXE_LOCK_EXIT_GLD(pUM);
687         return ENOMEM;
688     }
689 
690     BNXE_LOCK_ENTER_HWINIT(pUM);
691 
692     COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr);
693 
694     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE,
695                         pUM->lm_dev.params.mac_addr);
696 
697     BNXE_LOCK_EXIT_HWINIT(pUM);
698 
699     if (rc < 0)
700     {
701         BNXE_LOCK_EXIT_GLD(pUM);
702         return ECANCELED;
703     }
704 
705     pUM->ucastTableLen++;
706 
707     BNXE_LOCK_EXIT_GLD(pUM);
708     return 0;
709 }
710 
711 
712 static int BnxeRxRingGroupRemMac(void *          groupHandle,
713                                  const uint8_t * pMacAddr)
714 {
715     RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle;
716     um_device_t *  pUM       = (um_device_t *)pRxQGroup->pUM;
717     //u32_t          idx       = pRxQGroup->idx;
718     int rc;
719 
720     BNXE_LOCK_ENTER_GLD(pUM);
721 
722     if (!pUM->plumbed)
723     {
724         BNXE_LOCK_EXIT_GLD(pUM);
725         return ECANCELED;
726     }
727 
728     if (pUM->ucastTableLen == 0)
729     {
730         BNXE_LOCK_EXIT_GLD(pUM);
731         return EINVAL;
732     }
733 
734     BNXE_LOCK_ENTER_HWINIT(pUM);
735 
736     if (!IS_ETH_ADDRESS_EQUAL(pMacAddr, pUM->lm_dev.params.mac_addr))
737     {
738         BnxeLogWarn(pUM, "Deleting MAC address that doesn't match default");
739         /* XXX */
740     }
741 
742     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_FALSE,
743                         pUM->lm_dev.params.mac_addr);
744 
745     memset(pUM->lm_dev.params.mac_addr, 0, sizeof(pUM->lm_dev.params.mac_addr));
746 
747     BNXE_LOCK_EXIT_HWINIT(pUM);
748 
749     if (rc < 0)
750     {
751         BNXE_LOCK_EXIT_GLD(pUM);
752         return ECANCELED;
753     }
754 
755     pUM->ucastTableLen--;
756 
757     BNXE_LOCK_EXIT_GLD(pUM);
758     return 0;
759 }
760 
761 
762 static mblk_t * BnxeTxRingSend(void *   ringHandle,
763                                mblk_t * pMblk)
764 {
765     TxQueue *     pTxQ  = (TxQueue *)ringHandle;
766     um_device_t * pUM   = (um_device_t *)pTxQ->pUM;
767     u32_t         idx   = pTxQ->idx;
768     mblk_t *      pNextMblk;
769     int rc;
770 
771     while (pMblk)
772     {
773         pNextMblk = pMblk->b_next;
774         pMblk->b_next = NULL;
775 
776         rc = BnxeTxSendMblk(pUM, idx, pMblk, 0, 0);
777 
778         if (rc == BNXE_TX_GOODXMIT)
779         {
780             pMblk = pNextMblk;
781             continue;
782         }
783         else if (rc == BNXE_TX_DEFERPKT)
784         {
785             pMblk = pNextMblk;
786         }
787         else
788         {
789             pMblk->b_next = pNextMblk;
790         }
791 
792         break;
793     }
794 
795     return pMblk;
796 }
797 
798 #endif /* BNXE_RINGS */
799 
800 
801 static int BnxeMacUnicast(void *          pArg,
802                           const uint8_t * pMacAddr)
803 {
804     um_device_t * pUM = (um_device_t *)pArg;
805     int rc;
806 
807     BNXE_LOCK_ENTER_GLD(pUM);
808 
809     if (!pUM->plumbed)
810     {
811         memcpy(pUM->gldMac, pMacAddr, ETHERNET_ADDRESS_SIZE);
812         BNXE_LOCK_EXIT_GLD(pUM);
813         return 0;
814     }
815 
816     /* Validate MAC address */
817     if (IS_ETH_MULTICAST(pMacAddr))
818     {
819         BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address.");
820         BNXE_LOCK_EXIT_GLD(pUM);
821         return EINVAL;
822     }
823 
824     BNXE_LOCK_ENTER_HWINIT(pUM);
825 
826     COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr);
827 
828     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE,
829                         pUM->lm_dev.params.mac_addr);
830 
831     BNXE_LOCK_EXIT_HWINIT(pUM);
832 
833     if (rc < 0)
834     {
835         BNXE_LOCK_EXIT_GLD(pUM);
836         return EAGAIN;
837     }
838 
839     BNXE_LOCK_EXIT_GLD(pUM);
840     return 0;
841 }
842 
843 
844 static mblk_t * BnxeMacTx(void *   pArg,
845                           mblk_t * pMblk)
846 {
847     um_device_t * pUM = (um_device_t *)pArg;
848     mblk_t *      pNextMblk;
849     int ring, rc;
850 
851     BNXE_LOCK_ENTER_GLDTX(pUM, RW_READER);
852 
853     if (!pUM->plumbed)
854     {
855         freemsgchain(pMblk);
856         BNXE_LOCK_EXIT_GLDTX(pUM);
857 
858         return NULL;
859     }
860 
861     while (pMblk)
862     {
863         ring = BnxeRouteTxRing(pUM, pMblk);
864 
865         pNextMblk = pMblk->b_next;
866         pMblk->b_next = NULL;
867 
868         //rc = BnxeTxSendMblk(pUM, NDIS_CID(&pUM->lm_dev), pMblk, 0, 0);
869         rc = BnxeTxSendMblk(pUM, ring, pMblk, 0, 0);
870 
871         if (rc == BNXE_TX_GOODXMIT)
872         {
873             pMblk = pNextMblk;
874             continue;
875         }
876         else if (rc == BNXE_TX_DEFERPKT)
877         {
878             pMblk = pNextMblk;
879         }
880         else
881         {
882             pMblk->b_next = pNextMblk;
883         }
884 
885         break;
886     }
887 
888     BNXE_LOCK_EXIT_GLDTX(pUM);
889 
890     return pMblk;
891 }
892 
893 
894 #ifdef MC_RESOURCES
895 
896 static void BnxeBlank(void * pArg,
897                       time_t tick_cnt,
898                       uint_t pkt_cnt)
899 {
900     um_device_t * pUM = (um_device_t *)pArg;
901 
902     if (!pUM->plumbed)
903     {
904         return;
905     }
906 
907     /* XXX
908      * Need to dynamically reconfigure the hw with new interrupt
909      * coalescing params...
910      */
911 }
912 
913 
914 static void BnxeMacResources(void * pArg)
915 {
916     um_device_t * pUM = (um_device_t *)pArg;
917     mac_rx_fifo_t mrf;
918     int idx;
919 
920     mrf.mrf_type              = MAC_RX_FIFO;
921     mrf.mrf_blank             = BnxeBlank;
922     mrf.mrf_arg               = (void *)pUM;
923     mrf.mrf_normal_blank_time = 25;
924     mrf.mrf_normal_pkt_count  = 8;
925 
926     LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx)
927     {
928         pUM->macRxResourceHandles[idx] =
929             mac_resource_add(pUM->pMac, (mac_resource_t *)&mrf);
930     }
931 }
932 
933 #endif /* MC_RESOURCES */
934 
935 
936 static boolean_t BnxeReadReg(um_device_t *          pUM,
937                              struct bnxe_reg_data * pData)
938 {
939     if (pData->offset & 0x3)
940     {
941         BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXEREG ioctl");
942         return B_FALSE;
943     }
944 
945     LM_BAR_RD32_OFFSET(&pUM->lm_dev, 0, pData->offset, &pData->value);
946 
947     return B_TRUE;
948 }
949 
950 
951 static boolean_t BnxeWriteReg(um_device_t *          pUM,
952                               struct bnxe_reg_data * pData)
953 {
954     if (pData->offset & 0x3)
955     {
956         BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXEREG ioctl");
957         return B_FALSE;
958     }
959 
960     LM_BAR_WR32_OFFSET(&pUM->lm_dev, 0, pData->offset, pData->value);
961 
962     return B_TRUE;
963 }
964 
965 
966 static boolean_t BnxeReadNvm(um_device_t *            pUM,
967                              struct bnxe_nvram_data * pData)
968 {
969     if (pData->offset & 0x3)
970     {
971         BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXENVRM ioctl");
972         return B_FALSE;
973     }
974 
975     if (lm_nvram_read(&pUM->lm_dev,
976                       pData->offset,
977                       pData->value,
978                       (pData->num_of_u32 * sizeof(u32_t))) !=
979         LM_STATUS_SUCCESS)
980     {
981         return B_FALSE;
982     }
983 
984     return B_TRUE;
985 }
986 
987 
988 static boolean_t BnxeWriteNvm(um_device_t *            pUM,
989                               struct bnxe_nvram_data * pData)
990 {
991     if (pData->offset & 0x3)
992     {
993         BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXENVRM ioctl");
994         return B_FALSE;
995     }
996 
997     if (lm_nvram_write(&pUM->lm_dev,
998                        pData->offset,
999                        pData->value,
1000                        (pData->num_of_u32 * sizeof(u32_t))) !=
1001         LM_STATUS_SUCCESS)
1002     {
1003         return B_FALSE;
1004     }
1005 
1006     return B_TRUE;
1007 }
1008 
1009 
1010 static boolean_t BnxeReadPciCfg(um_device_t *          pUM,
1011                                 struct bnxe_reg_data * pData)
1012 {
1013     pData->value = pci_config_get32(pUM->pPciCfg, (off_t)pData->offset);
1014     return B_TRUE;
1015 }
1016 
1017 typedef enum {
1018     STATS_SHOW_TYPE_NUM,
1019     STATS_SHOW_TYPE_STR,
1020     STATS_SHOW_TYPE_CNT,
1021     STATS_SHOW_TYPE_MAX
1022 } stats_show_type_t;
1023 
1024 typedef union _b10_stats_show_data_t
1025 {
1026     u32_t op; /* ioctl sub-commond */
1027 
1028     struct
1029     {
1030         u32_t num; /* return number of stats */
1031         u32_t len; /* length of each string item */
1032     } desc;
1033 
1034     /* variable length... */
1035     char str[1]; /* holds names of desc.num stats, each desc.len in length */
1036 
1037     struct
1038     {
1039         b10_l2_chip_statistics_v2_t l2_chip_stats;
1040         b10_l4_chip_statistics_t    l4_chip_stats;
1041         b10_l2_driver_statistics_t  l2_drv_stats;
1042         b10_l4_driver_statistics_t  l4_drv_stats;
1043     } cnt;
1044 } b10_stats_show_data_t;
1045 
1046 
1047 static boolean_t BnxeStatsShow(um_device_t *           pUM,
1048                                b10_stats_show_data_t * pStats,
1049                                u32_t                   statsLen)
1050 {
1051     stats_show_type_t op;
1052     const size_t stats_size = sizeof(pStats->cnt);
1053 
1054     /*
1055      * All stats names MUST conform to STATS_STR_LEN length!!!
1056      */
1057 
1058     #define STATS_STR_LEN 39
1059 
1060     /* XXX
1061      * Note: these strings must be updated whenever any of
1062      * b10_l2_chip_statistics_t, b10_l4_chip_statistics_t,
1063      * b10_l2_driver_statistics_t or b10_l4_driver_statistics_t
1064      * are changed, or additional statistics are required.
1065      */
1066 
1067     const char p_stat_str[] =
1068 
1069         // b10_l2_chip_statistics_t
1070 
1071         "l2_chip_stats_ver_num\0                 "
1072         "IfHCInOctets\0                          "
1073         "IfHCInBadOctets\0                       "
1074         "IfHCOutOctets\0                         "
1075         "IfHCOutBadOctets\0                      "
1076         "IfHCOutPkts\0                           "
1077         "IfHCInPkts\0                            "
1078         "IfHCInUcastPkts\0                       "
1079         "IfHCInMulticastPkts\0                   "
1080         "IfHCInBroadcastPkts\0                   "
1081         "IfHCOutUcastPkts\0                      "
1082         "IfHCOutMulticastPkts\0                  "
1083         "IfHCOutBroadcastPkts\0                  "
1084         "IfHCInUcastOctets\0                     "
1085         "IfHCInMulticastOctets\0                 "
1086         "IfHCInBroadcastOctets\0                 "
1087         "IfHCOutUcastOctets\0                    "
1088         "IfHCOutMulticastOctets\0                "
1089         "IfHCOutBroadcastOctets\0                "
1090         "IfHCOutDiscards\0                       "
1091         "IfHCInFalseCarrierErrors\0              "
1092         "Dot3StatsInternalMacTransmitErrors\0    "
1093         "Dot3StatsCarrierSenseErrors\0           "
1094         "Dot3StatsFCSErrors\0                    "
1095         "Dot3StatsAlignmentErrors\0              "
1096         "Dot3StatsSingleCollisionFrames\0        "
1097         "Dot3StatsMultipleCollisionFrames\0      "
1098         "Dot3StatsDeferredTransmissions\0        "
1099         "Dot3StatsExcessiveCollisions\0          "
1100         "Dot3StatsLateCollisions\0               "
1101         "EtherStatsCollisions\0                  "
1102         "EtherStatsFragments\0                   "
1103         "EtherStatsJabbers\0                     "
1104         "EtherStatsUndersizePkts\0               "
1105         "EtherStatsOverrsizePkts\0               "
1106         "EtherStatsPktsTx64Octets\0              "
1107         "EtherStatsPktsTx65Octetsto127Octets\0   "
1108         "EtherStatsPktsTx128Octetsto255Octets\0  "
1109         "EtherStatsPktsTx256Octetsto511Octets\0  "
1110         "EtherStatsPktsTx512Octetsto1023Octets\0 "
1111         "EtherStatsPktsTx1024Octetsto1522Octets\0"
1112         "EtherStatsPktsTxOver1522Octets\0        "
1113         "XonPauseFramesReceived\0                "
1114         "XoffPauseFramesReceived\0               "
1115         "OutXonSent\0                            "
1116         "OutXoffSent\0                           "
1117         "FlowControlDone\0                       "
1118         "MacControlFramesReceived\0              "
1119         "XoffStateEntered\0                      "
1120         "IfInFramesL2FilterDiscards\0            "
1121         "IfInTTL0Discards\0                      "
1122         "IfInxxOverflowDiscards\0                "
1123         "IfInMBUFDiscards\0                      "
1124         "IfInErrors\0                            "
1125         "IfInErrorsOctets\0                      "
1126         "IfInNoBrbBuffer\0                       "
1127 
1128         "Nig_brb_packet\0                        "
1129         "Nig_brb_truncate\0                      "
1130         "Nig_flow_ctrl_discard\0                 "
1131         "Nig_flow_ctrl_octets\0                  "
1132         "Nig_flow_ctrl_packet\0                  "
1133         "Nig_mng_discard\0                       "
1134         "Nig_mng_octet_inp\0                     "
1135         "Nig_mng_octet_out\0                     "
1136         "Nig_mng_packet_inp\0                    "
1137         "Nig_mng_packet_out\0                    "
1138         "Nig_pbf_octets\0                        "
1139         "Nig_pbf_packet\0                        "
1140         "Nig_safc_inp\0                          "
1141 
1142         "Tx_Lpi_Count\0                          "        // This counter counts the number of timers the debounced version of EEE link idle is asserted
1143 
1144         // b10_l4_chip_statistics_t
1145 
1146         "l4_chip_stats_ver_num\0                 "
1147         "NoTxCqes\0                              "
1148         "InTCP4Segments\0                        "
1149         "OutTCP4Segments\0                       "
1150         "RetransmittedTCP4Segments\0             "
1151         "InTCP4Errors\0                          "
1152         "InIP4Receives\0                         "
1153         "InIP4HeaderErrors\0                     "
1154         "InIP4Discards\0                         "
1155         "InIP4Delivers\0                         "
1156         "InIP4Octets\0                           "
1157         "OutIP4Octets\0                          "
1158         "InIP4TruncatedPackets\0                 "
1159         "InTCP6Segments\0                        "
1160         "OutTCP6Segments\0                       "
1161         "RetransmittedTCP6Segments\0             "
1162         "InTCP6Errors\0                          "
1163         "InIP6Receives\0                         "
1164         "InIP6HeaderErrors\0                     "
1165         "InIP6Discards\0                         "
1166         "InIP6Delivers\0                         "
1167         "InIP6Octets\0                           "
1168         "OutIP6Octets\0                          "
1169         "InIP6TruncatedPackets\0                 "
1170 
1171         // b10_l2_driver_statistics_t
1172 
1173         "l2_driver_stats_ver_num\0               "
1174         "RxIPv4FragCount\0                       "
1175         "RxIpCsErrorCount\0                      "
1176         "RxTcpCsErrorCount\0                     "
1177         "RxLlcSnapCount\0                        "
1178         "RxPhyErrorCount\0                       "
1179         "RxIpv6ExtCount\0                        "
1180         "TxNoL2Bd\0                              "
1181         "TxNoSqWqe\0                             "
1182         "TxL2AssemblyBufUse\0                    "
1183 
1184         // b10_l4_driver_statistics_t
1185 
1186         "l4_driver_stats_ver_num\0               "
1187         "CurrentlyIpv4Established\0              "
1188         "OutIpv4Resets\0                         "
1189         "OutIpv4Fin\0                            "
1190         "InIpv4Reset\0                           "
1191         "InIpv4Fin\0                             "
1192         "CurrentlyIpv6Established\0              "
1193         "OutIpv6Resets\0                         "
1194         "OutIpv6Fin\0                            "
1195         "InIpv6Reset\0                           "
1196         "InIpv6Fin\0                             "
1197         "RxIndicateReturnPendingCnt\0            "
1198         "RxIndicateReturnDoneCnt\0               "
1199         "RxActiveGenBufCnt\0                     "
1200         "TxNoL4Bd\0                              "
1201         "TxL4AssemblyBufUse\0                   "
1202 
1203         ;
1204 
1205     ASSERT_STATIC((sizeof(p_stat_str) / STATS_STR_LEN) ==
1206                   (stats_size / sizeof(u64_t)));
1207 
1208     op = *((stats_show_type_t *)pStats);
1209 
1210     switch (op)
1211     {
1212     case STATS_SHOW_TYPE_NUM:
1213 
1214         if (statsLen < sizeof(pStats->desc))
1215         {
1216             return B_FALSE;
1217         }
1218 
1219         pStats->desc.num = (stats_size / sizeof(u64_t));
1220         pStats->desc.len = STATS_STR_LEN;
1221 
1222         return B_TRUE;
1223 
1224     case STATS_SHOW_TYPE_STR:
1225 
1226         if (statsLen != sizeof(p_stat_str))
1227         {
1228             return B_FALSE;
1229         }
1230 
1231         memcpy(pStats->str, p_stat_str, sizeof(p_stat_str));
1232 
1233         return B_TRUE;
1234 
1235     case STATS_SHOW_TYPE_CNT:
1236 
1237         if (statsLen != stats_size)
1238         {
1239             return B_FALSE;
1240         }
1241 
1242         lm_stats_get_l2_chip_stats(&pUM->lm_dev,
1243                                    &pStats->cnt.l2_chip_stats,
1244                                    L2_CHIP_STATISTICS_VER_NUM_2);
1245 
1246         lm_stats_get_l4_chip_stats(&pUM->lm_dev,
1247                                    &pStats->cnt.l4_chip_stats);
1248 
1249         lm_stats_get_l2_driver_stats(&pUM->lm_dev
1250                                      ,&pStats->cnt.l2_drv_stats);
1251 
1252         lm_stats_get_l4_driver_stats(&pUM->lm_dev,
1253                                      &pStats->cnt.l4_drv_stats);
1254 
1255         return B_TRUE;
1256 
1257     default:
1258 
1259         return B_FALSE;
1260     }
1261 }
1262 
1263 static void BnxeMacIoctl(void *    pArg,
1264                          queue_t * pQ,
1265                          mblk_t *  pMblk)
1266 {
1267     um_device_t * pUM = (um_device_t *)pArg;
1268     struct iocblk * pIoctl;
1269     int rc;
1270 
1271     if ((pQ == NULL) || (pMblk == NULL))
1272     {
1273         return;
1274     }
1275 
1276     if (pMblk->b_datap->db_type != M_IOCTL)
1277     {
1278         miocnak(pQ, pMblk, 0, EINVAL);
1279         return;
1280     }
1281 
1282     pIoctl = (struct iocblk *)pMblk->b_rptr;
1283 
1284     BNXE_LOCK_ENTER_GLD(pUM);
1285 
1286     switch (pIoctl->ioc_cmd)
1287     {
1288     case GIOCBNXELLDP:
1289 
1290         if ((pIoctl->ioc_count != sizeof(b10_lldp_params_get_t)) ||
1291             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1292             (miocpullup(pMblk, sizeof(b10_lldp_params_get_t)) < 0))
1293         {
1294             miocnak(pQ, pMblk, 0, EINVAL);
1295             break;
1296         }
1297 
1298         if (((b10_lldp_params_get_t *)pMblk->b_cont->b_rptr)->ver_num !=
1299             LLDP_PARAMS_VER_NUM)
1300         {
1301             miocnak(pQ, pMblk, 0, EINVAL);
1302             break;
1303         }
1304 
1305         if (lm_dcbx_lldp_read_params(&pUM->lm_dev,
1306                          (b10_lldp_params_get_t *)pMblk->b_cont->b_rptr) !=
1307             LM_STATUS_SUCCESS)
1308         {
1309             miocnak(pQ, pMblk, 0,
1310                     (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL);
1311             break;
1312         }
1313 
1314         miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1315         break;
1316 
1317     case GIOCBNXEDCBX:
1318 
1319         if ((pIoctl->ioc_count != sizeof(b10_dcbx_params_get_t)) ||
1320             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1321             (miocpullup(pMblk, sizeof(b10_dcbx_params_get_t)) < 0))
1322         {
1323             miocnak(pQ, pMblk, 0, EINVAL);
1324             break;
1325         }
1326 
1327         if (((b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr)->ver_num !=
1328             DCBX_PARAMS_VER_NUM)
1329         {
1330             miocnak(pQ, pMblk, 0, EINVAL);
1331             break;
1332         }
1333 
1334         if (lm_dcbx_read_params(&pUM->lm_dev,
1335                          (b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr) !=
1336             LM_STATUS_SUCCESS)
1337         {
1338             miocnak(pQ, pMblk, 0,
1339                     (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL);
1340             break;
1341         }
1342 
1343         miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1344         break;
1345 
1346     case SIOCBNXEDCBX:
1347 
1348         /* XXX */
1349         miocnak(pQ, pMblk, 0, EINVAL);
1350         break;
1351 
1352     case GIOCBNXEREG:
1353 
1354         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1355             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1356             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1357         {
1358             miocnak(pQ, pMblk, 0, EINVAL);
1359             break;
1360         }
1361 
1362         if (!BnxeReadReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1363         {
1364             miocnak(pQ, pMblk, 0, EINVAL);
1365         }
1366         else
1367         {
1368             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1369         }
1370 
1371         break;
1372 
1373     case SIOCBNXEREG:
1374 
1375         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1376             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1377             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1378         {
1379             miocnak(pQ, pMblk, 0, EINVAL);
1380             break;
1381         }
1382 
1383         if (!BnxeWriteReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1384         {
1385             miocnak(pQ, pMblk, 0, EINVAL);
1386         }
1387         else
1388         {
1389             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1390         }
1391 
1392         break;
1393 
1394     case GIOCBNXENVRM:
1395 
1396         if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) ||
1397             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1398             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1399         {
1400             miocnak(pQ, pMblk, 0, EINVAL);
1401             break;
1402         }
1403 
1404         if (!BnxeReadNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr))
1405         {
1406             miocnak(pQ, pMblk, 0, EINVAL);
1407         }
1408         else
1409         {
1410             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1411         }
1412 
1413         break;
1414 
1415     case SIOCBNXENVRM:
1416 
1417         if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) ||
1418             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1419             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1420         {
1421             miocnak(pQ, pMblk, 0, EINVAL);
1422             break;
1423         }
1424 
1425         if (!BnxeWriteNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr))
1426         {
1427             miocnak(pQ, pMblk, 0, EINVAL);
1428         }
1429         else
1430         {
1431             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1432         }
1433 
1434         break;
1435 
1436     case GIOCBNXEPCI:
1437 
1438         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1439             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1440             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1441         {
1442             miocnak(pQ, pMblk, 0, EINVAL);
1443             break;
1444         }
1445 
1446         if (!BnxeReadPciCfg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1447         {
1448             miocnak(pQ, pMblk, 0, EINVAL);
1449         }
1450         else
1451         {
1452             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1453         }
1454 
1455         break;
1456 
1457     case GIOCBNXESTATS:
1458 
1459         /* min size = sizeof(op) in b10_stats_show_data_t */
1460         if ((pIoctl->ioc_count < sizeof(u32_t)) ||
1461             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1462             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1463         {
1464             miocnak(pQ, pMblk, 0, EINVAL);
1465             break;
1466         }
1467 
1468         if (!BnxeStatsShow(pUM,
1469                            (b10_stats_show_data_t *)pMblk->b_cont->b_rptr,
1470                            pIoctl->ioc_count))
1471         {
1472             miocnak(pQ, pMblk, 0, EINVAL);
1473         }
1474         else
1475         {
1476             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1477         }
1478 
1479         break;
1480 
1481     default:
1482 
1483         miocnak(pQ, pMblk, 0, EINVAL);
1484         break;
1485     }
1486 
1487     BNXE_LOCK_EXIT_GLD(pUM);
1488 }
1489 
1490 
1491 #ifdef BNXE_RINGS
1492 
1493 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1494 static mblk_t * BnxeRxRingPoll(void * ringHandle,
1495                                int    numBytes,
1496                                int    numPkts)
1497 #else
1498 static mblk_t * BnxeRxRingPoll(void * ringHandle,
1499                                int    numBytes)
1500 #endif
1501 {
1502     RxQueue *     pRxQ  = (RxQueue *)ringHandle;
1503     um_device_t * pUM   = (um_device_t *)pRxQ->pUM;
1504     u32_t         idx   = pRxQ->idx;
1505     mblk_t *      pMblk = NULL;
1506     boolean_t     pktsRxed = 0;
1507     boolean_t     pktsTxed = 0;
1508 
1509 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1510     _NOTE(ARGUNUSED(numPkts))
1511 #endif
1512 
1513     if (numBytes <= 0)
1514     {
1515         return NULL;
1516     }
1517 
1518     if (pRxQ->inPollMode == B_FALSE)
1519     {
1520         BnxeLogWarn(pUM, "Polling on ring %d when NOT in poll mode!", idx);
1521         return NULL;
1522     }
1523 
1524     BNXE_LOCK_ENTER_INTR(pUM, idx);
1525 
1526     pRxQ->pollCnt++;
1527 
1528     BnxePollRxRing(pUM, idx, &pktsRxed, &pktsTxed);
1529 
1530     if (pktsTxed) BnxeTxRingProcess(pUM, idx);
1531     if (pktsRxed) pMblk = BnxeRxRingProcess(pUM, idx, TRUE, numBytes);
1532 
1533     /*
1534      * This is here for the off chance that all rings are in polling
1535      * mode and the default interrupt hasn't fired recently to handle
1536      * the sq.
1537      */
1538     lm_sq_post_pending(&pUM->lm_dev);
1539 
1540     BNXE_LOCK_EXIT_INTR(pUM, idx);
1541 
1542     return pMblk;
1543 }
1544 
1545 
1546 static int BnxeRxRingStart(mac_ring_driver_t ringHandle
1547 #if defined(__S11) || defined(__S12)
1548                            , uint64_t          genNumber
1549 #endif
1550                            )
1551 {
1552     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1553     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1554     u32_t         idx  = pRxQ->idx;
1555 
1556     BnxeLogDbg(pUM, "Starting Rx Ring %d", idx);
1557 
1558     BNXE_LOCK_ENTER_RX(pUM, idx);
1559 #if defined(__S11) || defined(__S12)
1560     pRxQ->genNumber      = genNumber;
1561 #endif
1562     pRxQ->inPollMode     = B_FALSE;
1563     pRxQ->intrDisableCnt = 0;
1564     pRxQ->intrEnableCnt  = 0;
1565     pRxQ->pollCnt        = 0;
1566     BNXE_LOCK_EXIT_RX(pUM, idx);
1567 
1568     return 0;
1569 }
1570 
1571 
1572 #if defined(__S11) || defined(__S12)
1573 
1574 static int BnxeRingStat(mac_ring_driver_t ringHandle,
1575                         uint_t            stat,
1576                         uint64_t *        val)
1577 {
1578     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1579     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1580 
1581     switch (stat)
1582     {
1583     case MAC_STAT_OERRORS:
1584     case MAC_STAT_OBYTES:
1585     case MAC_STAT_OPACKETS:
1586     case MAC_STAT_IERRORS:
1587     case MAC_STAT_RBYTES: /* MAC_STAT_IBYTES */
1588     case MAC_STAT_IPACKETS:
1589     default:
1590         return ENOTSUP;
1591     }
1592 
1593     return 0;
1594 }
1595 
1596 #endif /* __S11 or __S12 */
1597 
1598 
1599 #if defined(__S11) || defined(__S12)
1600 static int BnxeRxRingIntrEnable(mac_ring_driver_t ringHandle)
1601 #else
1602 static int BnxeRxRingIntrEnable(mac_intr_handle_t ringHandle)
1603 #endif
1604 {
1605     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1606     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1607 
1608     BnxeLogDbg(pUM, "Enabling Interrupt for Rx Ring %d", pRxQ->idx);
1609 
1610     /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */
1611     if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) &&
1612         CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) &&
1613         (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev)))
1614     {
1615         return 0; /* ok, already enabled */
1616     }
1617 
1618     BnxeIntrIguSbEnable(pUM, pRxQ->idx, B_FALSE);
1619 
1620     return 0;
1621 }
1622 
1623 
1624 #if defined(__S11) || defined(__S12)
1625 static int BnxeRxRingIntrDisable(mac_ring_driver_t ringHandle)
1626 #else
1627 static int BnxeRxRingIntrDisable(mac_intr_handle_t ringHandle)
1628 #endif
1629 {
1630     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1631     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1632 
1633     BnxeLogDbg(pUM, "Disabling Interrupt for Rx Ring %d", pRxQ->idx);
1634 
1635     /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */
1636     if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) &&
1637         CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) &&
1638         (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev)))
1639     {
1640         return -1; /* NO, keep enabled! */
1641     }
1642 
1643     BnxeIntrIguSbDisable(pUM, pRxQ->idx, B_FALSE);
1644 
1645     return 0;
1646 }
1647 
1648 
1649 /* callback function for MAC layer to register rings */
1650 static void BnxeFillRing(void *            arg,
1651                          mac_ring_type_t   ringType,
1652                          const int         ringGroupIndex,
1653                          const int         ringIndex,
1654                          mac_ring_info_t * pRingInfo,
1655                          mac_ring_handle_t ringHandle)
1656 {
1657     um_device_t * pUM = (um_device_t *)arg;
1658     RxQueue *     pRxQ;
1659     TxQueue *     pTxQ;
1660 
1661     switch (ringType)
1662     {
1663     case MAC_RING_TYPE_RX:
1664 
1665         BnxeLogInfo(pUM, "Initializing Rx Ring %d (Ring Group %d)",
1666                     ringIndex, ringGroupIndex);
1667 
1668         ASSERT(ringGroupIndex == 0);
1669         ASSERT(ringIndex < pUM->devParams.numRings);
1670 
1671         pRxQ = &pUM->rxq[ringIndex];
1672         pRxQ->ringHandle = ringHandle;
1673 
1674         pRingInfo->mri_driver = (mac_ring_driver_t)pRxQ;
1675         pRingInfo->mri_start  = BnxeRxRingStart;
1676         pRingInfo->mri_stop   = NULL;
1677 #if defined(__S11) || defined(__S12)
1678         pRingInfo->mri_stat   = BnxeRingStat;
1679 #endif
1680         pRingInfo->mri_poll   = BnxeRxRingPoll;
1681 
1682 #if !(defined(__S11) || defined(__S12))
1683         pRingInfo->mri_intr.mi_handle  = (mac_intr_handle_t)pRxQ;
1684 #endif
1685         pRingInfo->mri_intr.mi_enable  = (mac_intr_enable_t)BnxeRxRingIntrEnable;
1686         pRingInfo->mri_intr.mi_disable = (mac_intr_disable_t)BnxeRxRingIntrDisable;
1687 
1688         break;
1689 
1690     case MAC_RING_TYPE_TX:
1691 
1692         BnxeLogInfo(pUM, "Initializing Tx Ring %d (Ring Group %d)",
1693                     ringIndex, ringGroupIndex);
1694 
1695         ASSERT(ringGroupIndex == 0);
1696         ASSERT(ringIndex < pUM->devParams.numRings);
1697 
1698         pTxQ = &pUM->txq[ringIndex];
1699         pTxQ->ringHandle = ringHandle;
1700 
1701         pRingInfo->mri_driver = (mac_ring_driver_t)pTxQ;
1702         pRingInfo->mri_start  = NULL;
1703         pRingInfo->mri_stop   = NULL;
1704 #if defined(__S11) || defined(__S12)
1705         pRingInfo->mri_stat   = BnxeRingStat;
1706 #endif
1707         pRingInfo->mri_tx     = (mac_ring_send_t)BnxeTxRingSend;
1708 
1709         break;
1710 
1711     default:
1712         break;
1713     }
1714 }
1715 
1716 
1717 /* callback function for MAC layer to register groups */
1718 static void BnxeFillGroup(void *             arg,
1719                           mac_ring_type_t    ringType,
1720                           const int          ringGroupIndex,
1721                           mac_group_info_t * pGroupInfo,
1722                           mac_group_handle_t groupHandle)
1723 {
1724     um_device_t *  pUM = (um_device_t *)arg;
1725     RxQueueGroup * pRxQGroup;
1726 
1727     switch (ringType)
1728     {
1729     case MAC_RING_TYPE_RX:
1730 
1731         BnxeLogInfo(pUM, "Initializing Rx Group %d", ringGroupIndex);
1732 
1733         pRxQGroup = &pUM->rxqGroup[ringGroupIndex];
1734         pRxQGroup->groupHandle = groupHandle;
1735 
1736         pGroupInfo->mgi_driver = (mac_group_driver_t)pRxQGroup;
1737         pGroupInfo->mgi_start  = NULL;
1738         pGroupInfo->mgi_stop   = NULL;
1739         pGroupInfo->mgi_addmac = BnxeRxRingGroupAddMac;
1740         pGroupInfo->mgi_remmac = BnxeRxRingGroupRemMac;
1741         pGroupInfo->mgi_count  = (pUM->devParams.numRings /
1742                                   USER_OPTION_RX_RING_GROUPS_DEFAULT);
1743 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1744         pGroupInfo->mgi_flags  = MAC_GROUP_DEFAULT;
1745 #endif
1746 
1747         break;
1748 
1749     case MAC_RING_TYPE_TX:
1750     default:
1751         break;
1752     }
1753 }
1754 
1755 #endif /* BNXE_RINGS */
1756 
1757 
1758 static boolean_t BnxeMacGetCapability(void *      pArg,
1759                                       mac_capab_t capability,
1760                                       void *      pCapabilityData)
1761 {
1762     um_device_t * pUM = (um_device_t *)pArg;
1763     mac_capab_lso_t *   pCapLSO;
1764     mac_capab_rings_t * pCapRings;
1765 
1766     switch (capability)
1767     {
1768     case MAC_CAPAB_HCKSUM:
1769 
1770         *((u32_t *)pCapabilityData) = 0;
1771 
1772         if (pUM->devParams.enabled_oflds &
1773             (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM))
1774         {
1775             *((u32_t *)pCapabilityData) |= HCKSUM_IPHDRCKSUM;
1776         }
1777 
1778         if (pUM->devParams.enabled_oflds &
1779             (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM |
1780              LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM))
1781         {
1782             *((u32_t *)pCapabilityData) |= HCKSUM_INET_PARTIAL;
1783         }
1784 
1785         break;
1786 
1787     case MAC_CAPAB_LSO:
1788 
1789         pCapLSO = (mac_capab_lso_t *)pCapabilityData;
1790 
1791         if (pUM->devParams.lsoEnable)
1792         {
1793             pCapLSO->lso_flags                  = LSO_TX_BASIC_TCP_IPV4;
1794             pCapLSO->lso_basic_tcp_ipv4.lso_max = BNXE_LSO_MAXLEN;
1795             break;
1796         }
1797 
1798         return B_FALSE;
1799 
1800 #ifdef BNXE_RINGS
1801 
1802     case MAC_CAPAB_RINGS:
1803 
1804         if (!pUM->devParams.numRings)
1805         {
1806             return B_FALSE;
1807         }
1808 
1809         pCapRings = (mac_capab_rings_t *)pCapabilityData;
1810 
1811 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1812         pCapRings->mr_version    = MAC_RINGS_VERSION_1;
1813         pCapRings->mr_flags      = MAC_RINGS_FLAGS_NONE;
1814 #endif
1815         pCapRings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1816         pCapRings->mr_rnum       = pUM->devParams.numRings;
1817         pCapRings->mr_rget       = BnxeFillRing;
1818         pCapRings->mr_gaddring   = NULL;
1819         pCapRings->mr_gremring   = NULL;
1820 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1821         pCapRings->mr_ggetringtc = NULL;
1822 #endif
1823 
1824         switch (pCapRings->mr_type)
1825         {
1826         case MAC_RING_TYPE_RX:
1827 
1828             pCapRings->mr_gnum = USER_OPTION_RX_RING_GROUPS_DEFAULT;
1829             pCapRings->mr_gget = BnxeFillGroup;
1830             break;
1831 
1832         case MAC_RING_TYPE_TX:
1833 
1834 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1835             pCapRings->mr_gnum = 1;
1836 #else
1837             pCapRings->mr_gnum = 0;
1838 #endif
1839             pCapRings->mr_gget = NULL;
1840             break;
1841 
1842         default:
1843 
1844             return B_FALSE;
1845         }
1846 
1847         break;
1848 
1849 #endif /* BNXE_RINGS */
1850 
1851 #if !(defined(__S11) || defined(__S12))
1852 
1853     case MAC_CAPAB_POLL:
1854 
1855         /*
1856          * There's nothing for us to fill in, simply returning B_TRUE stating
1857          * that we support polling is sufficient.
1858          */
1859         break;
1860 
1861 #endif /* not __S11 or __S12 */
1862 
1863 #if defined(ILLUMOS)
1864     case MAC_CAPAB_TRANSCEIVER:
1865         return bnxe_fill_transceiver(pUM, pCapabilityData);
1866 #endif
1867 
1868     default:
1869 
1870         return B_FALSE;
1871     }
1872 
1873     return B_TRUE;
1874 }
1875 
1876 
1877 #ifdef MC_SETPROP
1878 
1879 static int BnxeSetPrivateProperty(um_device_t * pUM,
1880                                   const char *  pr_name,
1881                                   uint_t        pr_valsize,
1882                                   const void *  pr_val)
1883 {
1884     int err = 0;
1885     long result;
1886 
1887     if (strcmp(pr_name, "_en_2500fdx_cap") == 0)
1888     {
1889         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1890         {
1891             return EINVAL;
1892         }
1893 
1894         if ((result > 1) || (result < 0))
1895         {
1896             return EINVAL;
1897         }
1898 
1899         pUM->hwinit.lnkcfg.param_2500fdx = (uint32_t)result;
1900         pUM->curcfg.lnkcfg.param_2500fdx = (uint32_t)result;
1901         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1902     }
1903     else if (strcmp(pr_name, "_en_txpause_cap") == 0)
1904     {
1905         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1906         {
1907             return EINVAL;
1908         }
1909 
1910         if ((result > 1) || (result < 0))
1911         {
1912             return EINVAL;
1913         }
1914 
1915         pUM->hwinit.lnkcfg.param_txpause = (uint32_t)result;
1916         pUM->curcfg.lnkcfg.param_txpause = (uint32_t)result;
1917         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1918     }
1919     else if (strcmp(pr_name, "_en_rxpause_cap") == 0)
1920     {
1921         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1922         {
1923             return EINVAL;
1924         }
1925 
1926         if ((result > 1) || (result < 0))
1927         {
1928             return EINVAL;
1929         }
1930 
1931         pUM->hwinit.lnkcfg.param_rxpause = (uint32_t)result;
1932         pUM->curcfg.lnkcfg.param_rxpause = (uint32_t)result;
1933         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1934     }
1935     else if (strcmp(pr_name, "_autoneg_flow") == 0)
1936     {
1937         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1938         {
1939             return EINVAL;
1940         }
1941 
1942         if ((result > 1) || (result < 0))
1943         {
1944             return EINVAL;
1945         }
1946 
1947         pUM->hwinit.flow_autoneg = (uint32_t)result;
1948         pUM->curcfg.flow_autoneg = (uint32_t)result;
1949         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1950     }
1951     else if (strcmp(pr_name, "_checksum") == 0)
1952     {
1953         if (pUM->plumbed)
1954         {
1955             return EBUSY;
1956         }
1957 
1958         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1959         {
1960             return EINVAL;
1961         }
1962 
1963         switch (result)
1964         {
1965         case USER_OPTION_CKSUM_NONE:
1966 
1967             pUM->devParams.enabled_oflds = LM_OFFLOAD_NONE;
1968             break;
1969 
1970         case USER_OPTION_CKSUM_L3:
1971 
1972             pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM |
1973                                             LM_OFFLOAD_RX_IP_CKSUM);
1974             break;
1975 
1976         case USER_OPTION_CKSUM_L3_L4:
1977 
1978             pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM  |
1979                                             LM_OFFLOAD_RX_IP_CKSUM  |
1980                                             LM_OFFLOAD_TX_TCP_CKSUM |
1981                                             LM_OFFLOAD_RX_TCP_CKSUM |
1982                                             LM_OFFLOAD_TX_UDP_CKSUM |
1983                                             LM_OFFLOAD_RX_UDP_CKSUM);
1984             break;
1985 
1986         default:
1987 
1988             return EINVAL;
1989         }
1990 
1991         pUM->devParams.checksum = (uint32_t)result;
1992     }
1993     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
1994     {
1995         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1996         {
1997             return EINVAL;
1998         }
1999 
2000         switch (result)
2001         {
2002         case BNXE_ROUTE_RING_NONE:
2003         case BNXE_ROUTE_RING_TCPUDP:
2004         case BNXE_ROUTE_RING_DEST_MAC:
2005         case BNXE_ROUTE_RING_MSG_PRIO:
2006 
2007             break;
2008 
2009         default:
2010 
2011             return EINVAL;
2012         }
2013 
2014         pUM->devParams.routeTxRingPolicy = (uint32_t)result;
2015     }
2016     else if (strcmp(pr_name, "_num_rings") == 0)
2017     {
2018         if (pUM->plumbed)
2019         {
2020             return EBUSY;
2021         }
2022 
2023         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2024         {
2025             return EINVAL;
2026         }
2027 
2028         if ((result < USER_OPTION_NUM_RINGS_MIN) ||
2029             (result > USER_OPTION_NUM_RINGS_MAX))
2030         {
2031             return EINVAL;
2032         }
2033 
2034         pUM->devParams.numRings = (uint32_t)result;
2035     }
2036     else if (strcmp(pr_name, "_rx_descs") == 0)
2037     {
2038         if (pUM->plumbed)
2039         {
2040             return EBUSY;
2041         }
2042 
2043         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2044         {
2045             return EINVAL;
2046         }
2047 
2048         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2049         {
2050             return EINVAL;
2051         }
2052 
2053         pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result;
2054     }
2055     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2056     {
2057         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2058         {
2059             return EINVAL;
2060         }
2061 
2062         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2063         {
2064             return EINVAL;
2065         }
2066 
2067         pUM->devParams.maxRxFree = (uint32_t)result;
2068     }
2069     else if (strcmp(pr_name, "_tx_descs") == 0)
2070     {
2071         if (pUM->plumbed)
2072         {
2073             return EBUSY;
2074         }
2075 
2076         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2077         {
2078             return EINVAL;
2079         }
2080 
2081         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2082         {
2083             return EINVAL;
2084         }
2085 
2086         pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result;
2087     }
2088     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2089     {
2090         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2091         {
2092             return EINVAL;
2093         }
2094 
2095         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2096         {
2097             return EINVAL;
2098         }
2099 
2100         pUM->devParams.maxTxFree = (uint32_t)result;
2101     }
2102     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2103     {
2104         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2105         {
2106             return EINVAL;
2107         }
2108 
2109         pUM->devParams.rxCopyThreshold = (uint32_t)result;
2110     }
2111     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2112     {
2113         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2114         {
2115             return EINVAL;
2116         }
2117 
2118         pUM->devParams.txCopyThreshold = (uint32_t)result;
2119     }
2120     else if (strcmp(pr_name, "_interrupt_coalesce") == 0)
2121     {
2122         if (pUM->plumbed)
2123         {
2124             return EBUSY;
2125         }
2126 
2127         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2128         {
2129             return EINVAL;
2130         }
2131 
2132         if ((result > 1) || (result < 0))
2133         {
2134             return EINVAL;
2135         }
2136 
2137         pUM->devParams.intrCoalesce = (uint32_t)result;
2138     }
2139     else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0)
2140     {
2141         if (pUM->plumbed)
2142         {
2143             return EBUSY;
2144         }
2145 
2146         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2147         {
2148             return EINVAL;
2149         }
2150 
2151         if ((result < USER_OPTION_INTR_COALESCE_MIN) ||
2152             (result < USER_OPTION_INTR_COALESCE_MAX))
2153         {
2154             return EINVAL;
2155         }
2156 
2157         pUM->devParams.intrRxPerSec = (uint32_t)(1000000 / result);
2158     }
2159     else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0)
2160     {
2161         if (pUM->plumbed)
2162         {
2163             return EBUSY;
2164         }
2165 
2166         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2167         {
2168             return EINVAL;
2169         }
2170 
2171         if ((result < USER_OPTION_INTR_COALESCE_MIN) ||
2172             (result < USER_OPTION_INTR_COALESCE_MAX))
2173         {
2174             return EINVAL;
2175         }
2176 
2177         pUM->devParams.intrTxPerSec = (uint32_t)(1000000 / result);
2178     }
2179     else if (strcmp(pr_name, "_disable_msix") == 0)
2180     {
2181         if (pUM->plumbed)
2182         {
2183             return EBUSY;
2184         }
2185 
2186         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2187         {
2188             return EINVAL;
2189         }
2190 
2191         if ((result > 1) || (result < 0))
2192         {
2193             return EINVAL;
2194         }
2195 
2196         pUM->devParams.disableMsix = (uint32_t)result;
2197     }
2198     else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0)
2199     {
2200         if (pUM->plumbed)
2201         {
2202             return EBUSY;
2203         }
2204 
2205         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2206         {
2207             return EINVAL;
2208         }
2209 
2210         if ((result > 1) || (result < 0))
2211         {
2212             return EINVAL;
2213         }
2214 
2215         pUM->devParams.l2_fw_flow_ctrl = (uint32_t)result;
2216     }
2217     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2218     {
2219         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2220         {
2221             return EINVAL;
2222         }
2223 
2224         if ((result > 1) || (result < 0))
2225         {
2226             return EINVAL;
2227         }
2228 
2229         pUM->devParams.autogreeenEnable = (uint32_t)result;
2230         if (pUM->plumbed) BnxeUpdatePhy(pUM);
2231     }
2232     else if (strcmp(pr_name, "_lso_enable") == 0)
2233     {
2234         if (pUM->plumbed)
2235         {
2236             return EBUSY;
2237         }
2238 
2239         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2240         {
2241             return EINVAL;
2242         }
2243 
2244         if ((result > 1) || (result < 0))
2245         {
2246             return EINVAL;
2247         }
2248 
2249         pUM->devParams.lsoEnable = (uint32_t)result;
2250     }
2251     else if (strcmp(pr_name, "_log_enable") == 0)
2252     {
2253         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2254         {
2255             return EINVAL;
2256         }
2257 
2258         if ((result > 1) || (result < 0))
2259         {
2260             return EINVAL;
2261         }
2262 
2263         pUM->devParams.logEnable = (uint32_t)result;
2264     }
2265     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2266     {
2267         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2268         {
2269             return EINVAL;
2270         }
2271 
2272         if ((result > 1) || (result < 0))
2273         {
2274             return EINVAL;
2275         }
2276 
2277         pUM->devParams.fcoeEnable = (uint32_t)result;
2278 
2279         if (BNXE_FCOE(pUM))
2280         {
2281             BnxeFcoeStartStop(pUM);
2282         }
2283     }
2284     else
2285     {
2286         err = ENOTSUP;
2287     }
2288 
2289     return err;
2290 }
2291 
2292 
2293 static int BnxeMacSetProperty(void *        barg,
2294                               const char *  pr_name,
2295                               mac_prop_id_t pr_num,
2296                               uint_t        pr_valsize,
2297                               const void *  pr_val)
2298 {
2299     um_device_t *   pUM = barg;
2300     boolean_t       reprogram = B_FALSE;
2301     boolean_t       rxpause;
2302     boolean_t       txpause;
2303     uint32_t        mtu;
2304     link_flowctrl_t fl;
2305     int err = 0;
2306 
2307     BNXE_LOCK_ENTER_GLD(pUM);
2308 
2309     switch (pr_num)
2310     {
2311     /* read-only props */
2312     case MAC_PROP_STATUS:
2313     case MAC_PROP_SPEED:
2314     case MAC_PROP_DUPLEX:
2315 
2316     case MAC_PROP_ADV_10GFDX_CAP:
2317     case MAC_PROP_ADV_1000FDX_CAP:
2318     case MAC_PROP_ADV_1000HDX_CAP:
2319     case MAC_PROP_ADV_100FDX_CAP:
2320     case MAC_PROP_ADV_100HDX_CAP:
2321     case MAC_PROP_ADV_10FDX_CAP:
2322     case MAC_PROP_ADV_10HDX_CAP:
2323     case MAC_PROP_ADV_100T4_CAP:
2324 
2325     case MAC_PROP_EN_1000HDX_CAP:
2326     case MAC_PROP_EN_100T4_CAP:
2327 
2328     default:
2329 
2330         err = ENOTSUP;
2331         break;
2332 
2333     case MAC_PROP_EN_10GFDX_CAP:
2334 
2335         pUM->hwinit.lnkcfg.param_10000fdx = *(uint8_t *)pr_val;
2336         pUM->curcfg.lnkcfg.param_10000fdx = *(uint8_t *)pr_val;
2337         reprogram = B_TRUE;
2338         break;
2339 
2340     case MAC_PROP_EN_1000FDX_CAP:
2341 
2342         pUM->hwinit.lnkcfg.param_1000fdx = *(uint8_t *)pr_val;
2343         pUM->curcfg.lnkcfg.param_1000fdx = *(uint8_t *)pr_val;
2344         reprogram = B_TRUE;
2345         break;
2346 
2347     case MAC_PROP_EN_100FDX_CAP:
2348 
2349         pUM->hwinit.lnkcfg.param_100fdx = *(uint8_t *)pr_val;
2350         pUM->curcfg.lnkcfg.param_100fdx = *(uint8_t *)pr_val;
2351         reprogram = B_TRUE;
2352         break;
2353 
2354     case MAC_PROP_EN_100HDX_CAP:
2355 
2356         pUM->hwinit.lnkcfg.param_100hdx = *(uint8_t *)pr_val;
2357         pUM->curcfg.lnkcfg.param_100hdx = *(uint8_t *)pr_val;
2358         reprogram = B_TRUE;
2359         break;
2360 
2361     case MAC_PROP_EN_10FDX_CAP:
2362 
2363         pUM->hwinit.lnkcfg.param_10fdx = *(uint8_t *)pr_val;
2364         pUM->curcfg.lnkcfg.param_10fdx = *(uint8_t *)pr_val;
2365         reprogram = B_TRUE;
2366         break;
2367 
2368     case MAC_PROP_EN_10HDX_CAP:
2369 
2370         pUM->hwinit.lnkcfg.param_10hdx = *(uint8_t *)pr_val;
2371         pUM->curcfg.lnkcfg.param_10hdx = *(uint8_t *)pr_val;
2372         reprogram = B_TRUE;
2373         break;
2374 
2375     case MAC_PROP_AUTONEG:
2376 
2377         pUM->hwinit.lnkcfg.link_autoneg = *(uint8_t *)pr_val;
2378         pUM->curcfg.lnkcfg.link_autoneg = *(uint8_t *)pr_val;
2379         reprogram = B_TRUE;
2380         break;
2381 
2382     case MAC_PROP_FLOWCTRL:
2383 
2384         bcopy(pr_val, &fl, sizeof(fl));
2385 
2386         switch (fl)
2387         {
2388         case LINK_FLOWCTRL_NONE:
2389 
2390             rxpause = B_FALSE;
2391             txpause = B_FALSE;
2392             break;
2393 
2394         case LINK_FLOWCTRL_RX:
2395 
2396             rxpause = B_TRUE;
2397             txpause = B_FALSE;
2398             break;
2399 
2400         case LINK_FLOWCTRL_TX:
2401 
2402             rxpause = B_FALSE;
2403             txpause = B_TRUE;
2404             break;
2405 
2406         case LINK_FLOWCTRL_BI:
2407 
2408             rxpause = B_TRUE;
2409             txpause = B_TRUE;
2410             break;
2411 
2412         default:
2413 
2414             err = ENOTSUP;
2415             break;
2416         }
2417 
2418         if (err == 0)
2419         {
2420             pUM->hwinit.lnkcfg.param_rxpause = rxpause;
2421             pUM->hwinit.lnkcfg.param_txpause = txpause;
2422             pUM->curcfg.lnkcfg.param_rxpause = rxpause;
2423             pUM->curcfg.lnkcfg.param_txpause = txpause;
2424             reprogram = B_TRUE;
2425         }
2426 
2427         break;
2428 
2429     case MAC_PROP_MTU:
2430 
2431         if (pUM->plumbed)
2432         {
2433             err = EBUSY;
2434             break;
2435         }
2436 
2437         bcopy(pr_val, &mtu, sizeof (mtu));
2438 
2439         if ((mtu < USER_OPTION_MTU_MIN) || (mtu > USER_OPTION_MTU_MAX))
2440         {
2441             err = EINVAL;
2442             break;
2443         }
2444 
2445         if (pUM->devParams.mtu[LM_CLI_IDX_NDIS] == mtu)
2446         {
2447             break;
2448         }
2449 
2450         pUM->devParams.mtu[LM_CLI_IDX_NDIS] = mtu;
2451         err = mac_maxsdu_update(pUM->pMac, pUM->devParams.mtu[LM_CLI_IDX_NDIS]);
2452         pUM->lm_dev.params.mtu[LM_CLI_IDX_NDIS] = pUM->devParams.mtu[LM_CLI_IDX_NDIS];
2453         break;
2454 
2455     case MAC_PROP_PRIVATE:
2456 
2457         err = BnxeSetPrivateProperty(pUM, pr_name, pr_valsize, pr_val);
2458         break;
2459     }
2460 
2461     if (!err && reprogram)
2462     {
2463         if (pUM->plumbed) BnxeUpdatePhy(pUM);
2464     }
2465 
2466     BNXE_LOCK_EXIT_GLD(pUM);
2467     return err;
2468 }
2469 
2470 #endif /* MC_SETPROP */
2471 
2472 
2473 #ifdef MC_GETPROP
2474 
2475 static int BnxeGetPrivateProperty(um_device_t * pUM,
2476                                   const char *  pr_name,
2477                                   uint_t        pr_valsize,
2478                                   void *        pr_val)
2479 {
2480     BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg;
2481     BnxeLinkCfg * hw_cfg  = &pUM->hwinit.lnkcfg;
2482     int value;
2483     int err = 0;
2484 
2485     if (strcmp(pr_name, "_adv_2500fdx_cap") == 0)
2486     {
2487         value = lnk_cfg->param_2500fdx;
2488     }
2489     else if (strcmp(pr_name, "_en_2500fdx_cap") == 0)
2490     {
2491         value = hw_cfg->param_2500fdx;
2492     }
2493     else if (strcmp(pr_name, "_adv_txpause_cap") == 0)
2494     {
2495         value = lnk_cfg->param_txpause;
2496     }
2497     else if (strcmp(pr_name, "_en_txpause_cap") == 0)
2498     {
2499         value = hw_cfg->param_txpause;
2500     }
2501     else if (strcmp(pr_name, "_txpause") == 0)
2502     {
2503         value = pUM->props.link_txpause;
2504     }
2505     else if (strcmp(pr_name, "_adv_rxpause_cap") == 0)
2506     {
2507         value = lnk_cfg->param_rxpause;
2508     }
2509     else if (strcmp(pr_name, "_en_rxpause_cap") == 0)
2510     {
2511         value = hw_cfg->param_rxpause;
2512     }
2513     else if (strcmp(pr_name, "_rxpause") == 0)
2514     {
2515         value = pUM->props.link_rxpause;
2516     }
2517     else if (strcmp(pr_name, "_autoneg_flow") == 0)
2518     {
2519         value = pUM->hwinit.flow_autoneg;
2520     }
2521     else if (strcmp(pr_name, "_checksum") == 0)
2522     {
2523         value = pUM->devParams.checksum;
2524     }
2525     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
2526     {
2527         value = pUM->devParams.routeTxRingPolicy;
2528     }
2529     else if (strcmp(pr_name, "_num_rings") == 0)
2530     {
2531         value = pUM->devParams.numRings;
2532     }
2533     else if (strcmp(pr_name, "_rx_descs") == 0)
2534     {
2535         value = pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS];
2536     }
2537     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2538     {
2539         value = pUM->devParams.maxRxFree;
2540     }
2541     else if (strcmp(pr_name, "_tx_descs") == 0)
2542     {
2543         value = pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS];
2544     }
2545     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2546     {
2547         value = pUM->devParams.maxTxFree;
2548     }
2549     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2550     {
2551         value = pUM->devParams.rxCopyThreshold;
2552     }
2553     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2554     {
2555         value = pUM->devParams.txCopyThreshold;
2556     }
2557     else if (strcmp(pr_name, "_interrupt_coalesce") == 0)
2558     {
2559         value = pUM->devParams.intrCoalesce;
2560     }
2561     else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0)
2562     {
2563         value = pUM->devParams.intrRxPerSec;
2564     }
2565     else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0)
2566     {
2567         value = pUM->devParams.intrTxPerSec;
2568     }
2569     else if (strcmp(pr_name, "_disable_msix") == 0)
2570     {
2571         value = pUM->devParams.disableMsix;
2572     }
2573     else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0)
2574     {
2575         value = pUM->devParams.l2_fw_flow_ctrl;
2576     }
2577     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2578     {
2579         value = pUM->devParams.autogreeenEnable;
2580     }
2581     else if (strcmp(pr_name, "_lso_enable") == 0)
2582     {
2583         value = pUM->devParams.lsoEnable;
2584     }
2585     else if (strcmp(pr_name, "_log_enable") == 0)
2586     {
2587         value = pUM->devParams.logEnable;
2588     }
2589     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2590     {
2591         value = pUM->devParams.fcoeEnable;
2592     }
2593     else
2594     {
2595         err = ENOTSUP;
2596     }
2597 
2598     if (!err)
2599     {
2600         (void)snprintf(pr_val, pr_valsize, "%d", value);
2601     }
2602 
2603     return err;
2604 }
2605 
2606 
2607 static int BnxeMacGetProperty(void *        barg,
2608                               const char *  pr_name,
2609                               mac_prop_id_t pr_num,
2610                               uint_t        pr_valsize,
2611                               void *        pr_val)
2612 {
2613     um_device_t *   pUM = barg;
2614     link_flowctrl_t link_flowctrl;
2615     link_state_t    link_state;
2616     link_duplex_t   link_duplex;
2617     uint64_t        link_speed;
2618     BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg;
2619     BnxeLinkCfg * hw_cfg  = &pUM->hwinit.lnkcfg;
2620 
2621     switch (pr_num)
2622     {
2623     case MAC_PROP_MTU:
2624 
2625         ASSERT(pr_valsize >= sizeof(u32_t));
2626 
2627         bcopy(&pUM->devParams.mtu[LM_CLI_IDX_NDIS], pr_val, sizeof(u32_t));
2628         break;
2629 
2630     case MAC_PROP_DUPLEX:
2631 
2632         ASSERT(pr_valsize >= sizeof(link_duplex_t));
2633 
2634         link_duplex = pUM->props.link_duplex ?
2635                           LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
2636         bcopy(&link_duplex, pr_val, sizeof(link_duplex_t));
2637         break;
2638 
2639     case MAC_PROP_SPEED:
2640 
2641         ASSERT(pr_valsize >= sizeof(link_speed));
2642 
2643         link_speed = (pUM->props.link_speed * 1000000ULL);
2644         bcopy(&link_speed, pr_val, sizeof(link_speed));
2645         break;
2646 
2647     case MAC_PROP_STATUS:
2648 
2649         ASSERT(pr_valsize >= sizeof(link_state_t));
2650 
2651         link_state = pUM->props.link_speed ?
2652                          LINK_STATE_UP : LINK_STATE_DOWN;
2653         bcopy(&link_state, pr_val, sizeof(link_state_t));
2654         break;
2655 
2656     case MAC_PROP_AUTONEG:
2657 
2658         *(uint8_t *)pr_val = lnk_cfg->link_autoneg;
2659         break;
2660 
2661     case MAC_PROP_FLOWCTRL:
2662 
2663         ASSERT(pr_valsize >= sizeof(link_flowctrl_t));
2664 
2665         if (!lnk_cfg->param_rxpause && !lnk_cfg->param_txpause)
2666         {
2667             link_flowctrl = LINK_FLOWCTRL_NONE;
2668         }
2669         if (lnk_cfg->param_rxpause && !lnk_cfg->param_txpause)
2670         {
2671             link_flowctrl = LINK_FLOWCTRL_RX;
2672         }
2673         if (!lnk_cfg->param_rxpause && lnk_cfg->param_txpause)
2674         {
2675             link_flowctrl = LINK_FLOWCTRL_TX;
2676         }
2677         if (lnk_cfg->param_rxpause && lnk_cfg->param_txpause)
2678         {
2679             link_flowctrl = LINK_FLOWCTRL_BI;
2680         }
2681 
2682         bcopy(&link_flowctrl, pr_val, sizeof(link_flowctrl_t));
2683         break;
2684 
2685     case MAC_PROP_ADV_10GFDX_CAP:
2686 
2687         *(uint8_t *)pr_val = lnk_cfg->param_10000fdx;
2688         break;
2689 
2690     case MAC_PROP_EN_10GFDX_CAP:
2691 
2692         *(uint8_t *)pr_val = hw_cfg->param_10000fdx;
2693         break;
2694 
2695     case MAC_PROP_ADV_1000FDX_CAP:
2696 
2697         *(uint8_t *)pr_val = lnk_cfg->param_1000fdx;
2698         break;
2699 
2700     case MAC_PROP_EN_1000FDX_CAP:
2701 
2702         *(uint8_t *)pr_val = hw_cfg->param_1000fdx;
2703         break;
2704 
2705     case MAC_PROP_ADV_1000HDX_CAP:
2706     case MAC_PROP_EN_1000HDX_CAP:
2707 
2708         *(uint8_t *)pr_val = 0;
2709         break;
2710 
2711     case MAC_PROP_ADV_100FDX_CAP:
2712 
2713         *(uint8_t *)pr_val = lnk_cfg->param_100fdx;
2714         break;
2715 
2716     case MAC_PROP_EN_100FDX_CAP:
2717 
2718         *(uint8_t *)pr_val = hw_cfg->param_100fdx;
2719         break;
2720 
2721     case MAC_PROP_ADV_100HDX_CAP:
2722 
2723         *(uint8_t *)pr_val = lnk_cfg->param_100hdx;
2724         break;
2725 
2726     case MAC_PROP_EN_100HDX_CAP:
2727 
2728         *(uint8_t *)pr_val = hw_cfg->param_100hdx;
2729         break;
2730 
2731     case MAC_PROP_ADV_100T4_CAP:
2732     case MAC_PROP_EN_100T4_CAP:
2733 
2734         *(uint8_t *)pr_val = 0;
2735         break;
2736 
2737     case MAC_PROP_ADV_10FDX_CAP:
2738 
2739         *(uint8_t *)pr_val = lnk_cfg->param_10fdx;
2740         break;
2741 
2742     case MAC_PROP_EN_10FDX_CAP:
2743 
2744         *(uint8_t *)pr_val = hw_cfg->param_10fdx;
2745         break;
2746 
2747     case MAC_PROP_ADV_10HDX_CAP:
2748 
2749         *(uint8_t *)pr_val = lnk_cfg->param_10hdx;
2750         break;
2751 
2752     case MAC_PROP_EN_10HDX_CAP:
2753 
2754         *(uint8_t *)pr_val = hw_cfg->param_10hdx;
2755         break;
2756 
2757     case MAC_PROP_PRIVATE:
2758 
2759         return BnxeGetPrivateProperty(pUM,
2760                                       pr_name,
2761                                       pr_valsize,
2762                                       pr_val);
2763 
2764     default:
2765 
2766         return ENOTSUP;
2767     }
2768 
2769     return 0;
2770 }
2771 
2772 #endif /* MC_GETPROP */
2773 
2774 
2775 #ifdef MC_PROPINFO
2776 
2777 static void BnxeMacPrivatePropertyInfo(um_device_t *          pUM,
2778                                        const char *           pr_name,
2779                                        mac_prop_info_handle_t prh)
2780 {
2781     char valstr[64];
2782     BnxeLinkCfg * default_cfg = &bnxeLinkCfg;
2783     int default_val;
2784 
2785     bzero(valstr, sizeof (valstr));
2786 
2787     if ((strcmp(pr_name, "_adv_2500fdx_cap")            == 0) ||
2788         (strcmp(pr_name, "_adv_txpause_cap")            == 0) ||
2789         (strcmp(pr_name, "_txpause")                    == 0) ||
2790         (strcmp(pr_name, "_adv_rxpause_cap")            == 0) ||
2791         (strcmp(pr_name, "_rxpause")                    == 0) ||
2792         (strcmp(pr_name, "_checksum")                   == 0) ||
2793         (strcmp(pr_name, "_num_rings")                  == 0) ||
2794         (strcmp(pr_name, "_rx_descs")                   == 0) ||
2795         (strcmp(pr_name, "_tx_descs")                   == 0) ||
2796         (strcmp(pr_name, "_interrupt_coalesce")         == 0) ||
2797         (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0) ||
2798         (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0) ||
2799         (strcmp(pr_name, "_disable_msix")               == 0) ||
2800         (strcmp(pr_name, "_l2_fw_flow_ctrl")            == 0) ||
2801         (strcmp(pr_name, "_lso_enable")                 == 0))
2802     {
2803         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2804         return;
2805     }
2806 
2807     if (strcmp(pr_name, "_autoneg_flow") == 0)
2808     {
2809         default_val = B_TRUE;
2810     }
2811     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
2812     {
2813         default_val = BNXE_ROUTE_RING_TCPUDP;
2814     }
2815     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2816     {
2817         default_val = USER_OPTION_RX_MAX_FREE_DEFAULT;
2818     }
2819     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2820     {
2821         default_val = USER_OPTION_TX_MAX_FREE_DEFAULT;
2822     }
2823     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2824     {
2825         default_val = USER_OPTION_RX_DCOPY_THRESH_DEFAULT;
2826     }
2827     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2828     {
2829         default_val = USER_OPTION_TX_DCOPY_THRESH_DEFAULT;
2830     }
2831     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2832     {
2833         default_val = B_TRUE;
2834     }
2835     else if (strcmp(pr_name, "_log_enable") == 0)
2836     {
2837         default_val = B_TRUE;
2838     }
2839     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2840     {
2841         default_val = B_TRUE;
2842     }
2843     else
2844     {
2845         return;
2846     }
2847 
2848     snprintf(valstr, sizeof (valstr), "%d", default_val);
2849     mac_prop_info_set_default_str(prh, valstr);
2850 }
2851 
2852 
2853 static void BnxeMacPropertyInfo(void *                 barg,
2854                                 const char *           pr_name,
2855                                 mac_prop_id_t          pr_num,
2856                                 mac_prop_info_handle_t prh)
2857 {
2858     um_device_t * pUM = barg;
2859     link_flowctrl_t link_flowctrl;
2860     BnxeLinkCfg * default_cfg = &bnxeLinkCfg;
2861 
2862     switch (pr_num)
2863     {
2864     case MAC_PROP_STATUS:
2865     case MAC_PROP_SPEED:
2866     case MAC_PROP_DUPLEX:
2867 
2868     case MAC_PROP_ADV_10GFDX_CAP:
2869     case MAC_PROP_ADV_1000FDX_CAP:
2870     case MAC_PROP_ADV_1000HDX_CAP:
2871     case MAC_PROP_ADV_100FDX_CAP:
2872     case MAC_PROP_ADV_100HDX_CAP:
2873     case MAC_PROP_ADV_100T4_CAP:
2874     case MAC_PROP_ADV_10FDX_CAP:
2875     case MAC_PROP_ADV_10HDX_CAP:
2876 
2877     case MAC_PROP_EN_1000HDX_CAP:
2878     case MAC_PROP_EN_100T4_CAP:
2879 
2880         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2881         break;
2882 
2883     case MAC_PROP_EN_10GFDX_CAP:
2884 
2885         mac_prop_info_set_default_uint8(prh, default_cfg->param_10000fdx);
2886         break;
2887 
2888     case MAC_PROP_EN_1000FDX_CAP:
2889 
2890         mac_prop_info_set_default_uint8(prh, default_cfg->param_1000fdx);
2891         break;
2892 
2893     case MAC_PROP_EN_100FDX_CAP:
2894 
2895         mac_prop_info_set_default_uint8(prh, default_cfg->param_100fdx);
2896         break;
2897 
2898     case MAC_PROP_EN_100HDX_CAP:
2899 
2900         mac_prop_info_set_default_uint8(prh, default_cfg->param_100hdx);
2901         break;
2902 
2903     case MAC_PROP_EN_10FDX_CAP:
2904 
2905         mac_prop_info_set_default_uint8(prh, default_cfg->param_10fdx);
2906         break;
2907 
2908     case MAC_PROP_EN_10HDX_CAP:
2909 
2910         mac_prop_info_set_default_uint8(prh, default_cfg->param_10hdx);
2911         break;
2912 
2913     case MAC_PROP_MTU:
2914 
2915         mac_prop_info_set_range_uint32(prh,
2916                                        USER_OPTION_MTU_MIN,
2917                                        USER_OPTION_MTU_MAX);
2918         break;
2919 
2920     case MAC_PROP_AUTONEG:
2921 
2922         mac_prop_info_set_default_uint8(prh, default_cfg->link_autoneg);
2923         break;
2924 
2925     case MAC_PROP_FLOWCTRL:
2926 
2927         if (!default_cfg->param_rxpause && !default_cfg->param_txpause)
2928         {
2929             link_flowctrl = LINK_FLOWCTRL_NONE;
2930         }
2931 
2932         if (default_cfg->param_rxpause && !default_cfg->param_txpause)
2933         {
2934             link_flowctrl = LINK_FLOWCTRL_RX;
2935         }
2936 
2937         if (!default_cfg->param_rxpause && default_cfg->param_txpause)
2938         {
2939             link_flowctrl = LINK_FLOWCTRL_TX;
2940         }
2941 
2942         if (default_cfg->param_rxpause && default_cfg->param_txpause)
2943         {
2944             link_flowctrl = LINK_FLOWCTRL_BI;
2945         }
2946 
2947         mac_prop_info_set_default_link_flowctrl(prh, link_flowctrl);
2948         break;
2949 
2950     case MAC_PROP_PRIVATE:
2951 
2952         BnxeMacPrivatePropertyInfo(pUM, pr_name, prh);
2953         break;
2954     }
2955 }
2956 
2957 #endif /* MC_PROPINFO */
2958 
2959 
2960 static mac_callbacks_t bnxe_callbacks =
2961 {
2962     (
2963       MC_IOCTL
2964 #ifdef MC_RESOURCES
2965     | MC_RESOURCES
2966 #endif
2967 #ifdef MC_SETPROP
2968     | MC_SETPROP
2969 #endif
2970 #ifdef MC_GETPROP
2971     | MC_GETPROP
2972 #endif
2973 #ifdef MC_PROPINFO
2974     | MC_PROPINFO
2975 #endif
2976     | MC_GETCAPAB
2977     ),
2978     BnxeMacStats,
2979     BnxeMacStart,
2980     BnxeMacStop,
2981     BnxeMacPromiscuous,
2982     BnxeMacMulticast,
2983     NULL,
2984     BnxeMacTx,
2985 #ifdef MC_RESOURCES
2986     BnxeMacResources,
2987 #else
2988     NULL,
2989 #endif
2990     BnxeMacIoctl,
2991     BnxeMacGetCapability,
2992 #ifdef MC_OPEN
2993     NULL,
2994     NULL,
2995 #endif
2996 #ifdef MC_SETPROP
2997     BnxeMacSetProperty,
2998 #endif
2999 #ifdef MC_GETPROP
3000     BnxeMacGetProperty,
3001 #endif
3002 #ifdef MC_PROPINFO
3003     BnxeMacPropertyInfo
3004 #endif
3005 };
3006 
3007 
3008 boolean_t BnxeGldInit(um_device_t * pUM)
3009 {
3010     mac_register_t * pMac;
3011     int rc;
3012 
3013     atomic_swap_32(&pUM->plumbed, B_FALSE);
3014 
3015     if ((pMac = mac_alloc(MAC_VERSION)) == NULL)
3016     {
3017         BnxeLogWarn(pUM, "Failed to allocate GLD MAC memory");
3018         return B_FALSE;
3019     }
3020 
3021     pMac->m_driver     = pUM;
3022     pMac->m_dip        = pUM->pDev;
3023     pMac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
3024     pMac->m_callbacks  = &bnxe_callbacks;
3025     pMac->m_min_sdu    = 0;
3026     pMac->m_max_sdu    = pUM->devParams.mtu[LM_CLI_IDX_NDIS];
3027     pMac->m_src_addr   = &(pUM->lm_dev.params.mac_addr[0]);
3028 
3029 #ifdef MC_OPEN
3030     pMac->m_margin = VLAN_TAGSZ;
3031 #endif
3032 
3033 #ifdef MC_SETPROP
3034     pMac->m_priv_props = bnxeLink_priv_props;
3035 #endif
3036 
3037 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
3038     bnxe_callbacks.mc_unicst =
3039         (!pUM->devParams.numRings) ? BnxeMacUnicast : NULL;
3040 #else
3041     bnxe_callbacks.mc_unicst = BnxeMacUnicast;
3042 #endif
3043 
3044     rc = mac_register(pMac, &pUM->pMac);
3045 
3046     mac_free(pMac);
3047 
3048     if (rc != 0)
3049     {
3050         BnxeLogWarn(pUM, "Failed to register with GLD (%d)", rc);
3051         return B_FALSE;
3052     }
3053 
3054     /* Always report the initial link state as unknown. */
3055     mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
3056 
3057     return B_TRUE;
3058 }
3059 
3060 
3061 boolean_t BnxeGldFini(um_device_t * pUM)
3062 {
3063     int cnt;
3064 
3065     if (pUM->plumbed)
3066     {
3067         BnxeLogWarn(pUM, "Detaching device from GLD that is started!");
3068         return B_FALSE;
3069     }
3070 
3071     /* We must not detach until all packets held by stack are retrieved. */
3072     if (!BnxeWaitForPacketsFromClient(pUM, LM_CLI_IDX_NDIS))
3073     {
3074         return B_FALSE;
3075     }
3076 
3077     if (pUM->pMac)
3078     {
3079         if (mac_unregister(pUM->pMac))
3080         {
3081             BnxeLogWarn(pUM, "Failed to unregister with the GLD");
3082             return B_FALSE;
3083         }
3084     }
3085 
3086     return B_TRUE;
3087 }
3088 
3089 
3090 void BnxeGldLink(um_device_t * pUM,
3091                  link_state_t  state)
3092 {
3093     mac_link_update(pUM->pMac, state);
3094 }
3095 
3096