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