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  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 
  26 /*
  27  * SunOS MT STREAMS FEPS(SBus)/Cheerio(PCI) 10/100Mb Ethernet Device Driver
  28  */
  29 
  30 #include        <sys/types.h>
  31 #include        <sys/debug.h>
  32 #include        <sys/stream.h>
  33 #include        <sys/cmn_err.h>
  34 #include        <sys/kmem.h>
  35 #include        <sys/crc32.h>
  36 #include        <sys/modctl.h>
  37 #include        <sys/conf.h>
  38 #include        <sys/strsun.h>
  39 #include        <sys/kstat.h>
  40 #include        <sys/pattr.h>
  41 #include        <sys/dlpi.h>
  42 #include        <sys/strsubr.h>
  43 #include        <sys/mac_provider.h>
  44 #include        <sys/mac_ether.h>
  45 #include        <sys/mii.h>
  46 #include        <sys/ethernet.h>
  47 #include        <sys/vlan.h>
  48 #include        <sys/pci.h>
  49 #include        <sys/policy.h>
  50 #include        <sys/ddi.h>
  51 #include        <sys/sunddi.h>
  52 #include        <sys/byteorder.h>
  53 #include        "hme_phy.h"
  54 #include        "hme_mac.h"
  55 #include        "hme.h"
  56 
  57 typedef void    (*fptrv_t)();
  58 
  59 typedef enum {
  60         NO_MSG          = 0,
  61         AUTOCONFIG_MSG,
  62         DISPLAY_MSG,
  63         INIT_MSG,
  64         UNINIT_MSG,
  65         CONFIG_MSG,
  66         MII_MSG,
  67         FATAL_ERR_MSG,
  68         NFATAL_ERR_MSG,
  69         XCVR_MSG,
  70         NOXCVR_MSG,
  71         ERX_MSG,
  72         DDI_MSG,
  73 } msg_t;
  74 
  75 msg_t   hme_debug_level =       NO_MSG;
  76 
  77 static char     *msg_string[] = {
  78         "NONE       ",
  79         "AUTOCONFIG ",
  80         "DISPLAY        "
  81         "INIT       ",
  82         "UNINIT         ",
  83         "CONFIG ",
  84         "MII    ",
  85         "FATAL_ERR      ",
  86         "NFATAL_ERR     ",
  87         "XCVR   ",
  88         "NOXCVR ",
  89         "ERX    ",
  90         "DDI    ",
  91 };
  92 
  93 #define SEVERITY_NONE   0
  94 #define SEVERITY_LOW    0
  95 #define SEVERITY_MID    1
  96 #define SEVERITY_HIGH   2
  97 #define SEVERITY_UNKNOWN 99
  98 
  99 #define FEPS_URUN_BUG
 100 #define HME_CODEVIOL_BUG
 101 
 102 #define KIOIP   KSTAT_INTR_PTR(hmep->hme_intrstats)
 103 
 104 /*
 105  * The following variables are used for checking fixes in Sbus/FEPS 2.0
 106  */
 107 static  int     hme_urun_fix = 0;       /* Bug fixed in Sbus/FEPS 2.0 */
 108 
 109 /*
 110  * The following variables are used for configuring various features
 111  */
 112 static  int     hme_64bit_enable =      1;      /* Use 64-bit sbus transfers */
 113 static  int     hme_reject_own =        1;      /* Reject packets with own SA */
 114 static  int     hme_ngu_enable =        0;      /* Never Give Up mode */
 115 
 116 char *hme_priv_prop[] = {
 117         "_ipg0",
 118         "_ipg1",
 119         "_ipg2",
 120         "_lance_mode",
 121         NULL
 122 };
 123 
 124 static  int     hme_lance_mode =        1;      /* to enable lance mode */
 125 static  int     hme_ipg0 =              16;
 126 static  int     hme_ipg1 =              8;
 127 static  int     hme_ipg2 =              4;
 128 
 129 /*
 130  * The following parameters may be configured by the user. If they are not
 131  * configured by the user, the values will be based on the capabilities of
 132  * the transceiver.
 133  * The value "HME_NOTUSR" is ORed with the parameter value to indicate values
 134  * which are NOT configured by the user.
 135  */
 136 
 137 #define HME_NOTUSR      0x0f000000
 138 #define HME_MASK_1BIT   0x1
 139 #define HME_MASK_5BIT   0x1f
 140 #define HME_MASK_8BIT   0xff
 141 
 142 /*
 143  * All strings used by hme messaging functions
 144  */
 145 
 146 static  char *no_xcvr_msg =
 147         "No transceiver found.";
 148 
 149 static  char *burst_size_msg =
 150         "Could not identify the burst size";
 151 
 152 static  char *unk_rx_ringsz_msg =
 153         "Unknown receive RINGSZ";
 154 
 155 static  char *add_intr_fail_msg =
 156         "ddi_add_intr(9F) failed";
 157 
 158 static  char *mregs_4global_reg_fail_msg =
 159         "ddi_regs_map_setup(9F) for global reg failed";
 160 
 161 static  char *mregs_4etx_reg_fail_msg =
 162         "ddi_map_regs for etx reg failed";
 163 
 164 static  char *mregs_4erx_reg_fail_msg =
 165         "ddi_map_regs for erx reg failed";
 166 
 167 static  char *mregs_4bmac_reg_fail_msg =
 168         "ddi_map_regs for bmac reg failed";
 169 
 170 static  char *mregs_4mif_reg_fail_msg =
 171         "ddi_map_regs for mif reg failed";
 172 
 173 static  char *init_fail_gen_msg =
 174         "Failed to initialize hardware/driver";
 175 
 176 static  char *ddi_nregs_fail_msg =
 177         "ddi_dev_nregs failed(9F), returned %d";
 178 
 179 static  char *bad_num_regs_msg =
 180         "Invalid number of registers.";
 181 
 182 
 183 /* FATAL ERR msgs */
 184 /*
 185  * Function prototypes.
 186  */
 187 /* these two are global so that qfe can use them */
 188 int hmeattach(dev_info_t *, ddi_attach_cmd_t);
 189 int hmedetach(dev_info_t *, ddi_detach_cmd_t);
 190 int hmequiesce(dev_info_t *);
 191 static  boolean_t hmeinit_xfer_params(struct hme *);
 192 static  uint_t hmestop(struct hme *);
 193 static  void hmestatinit(struct hme *);
 194 static  int hmeallocthings(struct hme *);
 195 static  void hmefreethings(struct hme *);
 196 static  int hmeallocbuf(struct hme *, hmebuf_t *, int);
 197 static  int hmeallocbufs(struct hme *);
 198 static  void hmefreebufs(struct hme *);
 199 static  void hmeget_hm_rev_property(struct hme *);
 200 static  boolean_t hmestart(struct hme *, mblk_t *);
 201 static  uint_t hmeintr(caddr_t);
 202 static  void hmereclaim(struct hme *);
 203 static  int hmeinit(struct hme *);
 204 static  void hmeuninit(struct hme *hmep);
 205 static  mblk_t *hmeread(struct hme *, hmebuf_t *, uint32_t);
 206 static  void hmesavecntrs(struct hme *);
 207 static  void hme_fatal_err(struct hme *, uint_t);
 208 static  void hme_nonfatal_err(struct hme *, uint_t);
 209 static  int hmeburstsizes(struct hme *);
 210 static  void send_bit(struct hme *, uint16_t);
 211 static  uint16_t get_bit_std(uint8_t, struct hme *);
 212 static  uint16_t hme_bb_mii_read(struct hme *, uint8_t, uint8_t);
 213 static  void hme_bb_mii_write(struct hme *, uint8_t, uint8_t, uint16_t);
 214 static  void hme_bb_force_idle(struct hme *);
 215 static  uint16_t hme_mii_read(void *, uint8_t, uint8_t);
 216 static  void hme_mii_write(void *, uint8_t, uint8_t, uint16_t);
 217 static  void hme_setup_mac_address(struct hme *, dev_info_t *);
 218 static  void hme_mii_notify(void *, link_state_t);
 219 
 220 static void hme_fault_msg(struct hme *, uint_t, msg_t, char *, ...);
 221 
 222 static void hme_check_acc_handle(char *, uint_t, struct hme *,
 223     ddi_acc_handle_t);
 224 
 225 /*
 226  * Nemo (GLDv3) Functions.
 227  */
 228 static int      hme_m_stat(void *, uint_t, uint64_t *);
 229 static int      hme_m_start(void *);
 230 static void     hme_m_stop(void *);
 231 static int      hme_m_promisc(void *, boolean_t);
 232 static int      hme_m_multicst(void *, boolean_t, const uint8_t *);
 233 static int      hme_m_unicst(void *, const uint8_t *);
 234 static mblk_t   *hme_m_tx(void *, mblk_t *);
 235 static boolean_t        hme_m_getcapab(void *, mac_capab_t, void *);
 236 static int hme_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
 237 static void hme_m_propinfo(void *, const char *, mac_prop_id_t,
 238     mac_prop_info_handle_t);
 239 static int hme_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
 240     const void *);
 241 
 242 static mii_ops_t hme_mii_ops = {
 243         MII_OPS_VERSION,
 244         hme_mii_read,
 245         hme_mii_write,
 246         hme_mii_notify,
 247         NULL
 248 };
 249 
 250 static mac_callbacks_t hme_m_callbacks = {
 251         MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
 252         hme_m_stat,
 253         hme_m_start,
 254         hme_m_stop,
 255         hme_m_promisc,
 256         hme_m_multicst,
 257         hme_m_unicst,
 258         hme_m_tx,
 259         NULL,
 260         NULL,
 261         hme_m_getcapab,
 262         NULL,
 263         NULL,
 264         hme_m_setprop,
 265         hme_m_getprop,
 266         hme_m_propinfo
 267 };
 268 
 269 DDI_DEFINE_STREAM_OPS(hme_dev_ops, nulldev, nulldev, hmeattach, hmedetach,
 270     nodev, NULL, D_MP, NULL, hmequiesce);
 271 
 272 #define HME_FAULT_MSG1(p, s, t, f) \
 273     hme_fault_msg((p), (s), (t), (f));
 274 
 275 #define HME_FAULT_MSG2(p, s, t, f, a) \
 276     hme_fault_msg((p), (s), (t), (f), (a));
 277 
 278 #define HME_FAULT_MSG3(p, s, t, f, a, b) \
 279     hme_fault_msg((p), (s), (t), (f), (a), (b));
 280 
 281 #define HME_FAULT_MSG4(p, s, t, f, a, b, c) \
 282     hme_fault_msg((p), (s), (t), (f), (a), (b), (c));
 283 
 284 #define CHECK_MIFREG() \
 285         hme_check_acc_handle(__FILE__, __LINE__, hmep, hmep->hme_mifregh)
 286 #define CHECK_ETXREG() \
 287         hme_check_acc_handle(__FILE__, __LINE__, hmep, hmep->hme_etxregh)
 288 #define CHECK_ERXREG() \
 289         hme_check_acc_handle(__FILE__, __LINE__, hmep, hmep->hme_erxregh)
 290 #define CHECK_MACREG() \
 291         hme_check_acc_handle(__FILE__, __LINE__, hmep, hmep->hme_bmacregh)
 292 #define CHECK_GLOBREG() \
 293         hme_check_acc_handle(__FILE__, __LINE__, hmep, hmep->hme_globregh)
 294 
 295 /*
 296  * Claim the device is ultra-capable of burst in the beginning.  Use
 297  * the value returned by ddi_dma_burstsizes() to actually set the HME
 298  * global configuration register later.
 299  *
 300  * Sbus/FEPS supports burst sizes of 16, 32 and 64 bytes. Also, it supports
 301  * 32-bit and 64-bit Sbus transfers. Hence the dlim_burstsizes field contains
 302  * the the burstsizes in both the lo and hi words.
 303  */
 304 #define HMELIMADDRLO    ((uint64_t)0x00000000)
 305 #define HMELIMADDRHI    ((uint64_t)0xffffffff)
 306 
 307 /*
 308  * Note that rx and tx data buffers can be arbitrarily aligned, but
 309  * that the descriptor rings need to be aligned on 2K boundaries, per
 310  * the spec.
 311  */
 312 static ddi_dma_attr_t hme_dma_attr = {
 313         DMA_ATTR_V0,            /* version number. */
 314         (uint64_t)HMELIMADDRLO, /* low address */
 315         (uint64_t)HMELIMADDRHI, /* high address */
 316         (uint64_t)0x00ffffff,   /* address counter max */
 317         (uint64_t)HME_HMDALIGN, /* alignment */
 318         (uint_t)0x00700070,     /* dlim_burstsizes for 32 and 64 bit xfers */
 319         (uint32_t)0x1,          /* minimum transfer size */
 320         (uint64_t)0x7fffffff,   /* maximum transfer size */
 321         (uint64_t)0x00ffffff,   /* maximum segment size */
 322         1,                      /* scatter/gather list length */
 323         512,                    /* granularity */
 324         0                       /* attribute flags */
 325 };
 326 
 327 static ddi_device_acc_attr_t hme_buf_attr = {
 328         DDI_DEVICE_ATTR_V0,
 329         DDI_NEVERSWAP_ACC,
 330         DDI_STRICTORDER_ACC,    /* probably could allow merging & caching */
 331         DDI_DEFAULT_ACC,
 332 };
 333 
 334 static uchar_t pci_latency_timer = 0;
 335 
 336 /*
 337  * Module linkage information for the kernel.
 338  */
 339 static struct modldrv modldrv = {
 340         &mod_driverops,     /* Type of module.  This one is a driver */
 341         "Sun HME 10/100 Mb Ethernet",
 342         &hme_dev_ops,       /* driver ops */
 343 };
 344 
 345 static struct modlinkage modlinkage = {
 346         MODREV_1, &modldrv, NULL
 347 };
 348 
 349 /* <<<<<<<<<<<<<<<<<<<<<<  Register operations >>>>>>>>>>>>>>>>>>>>> */
 350 
 351 #define GET_MIFREG(reg) \
 352         ddi_get32(hmep->hme_mifregh, (uint32_t *)&hmep->hme_mifregp->reg)
 353 #define PUT_MIFREG(reg, value) \
 354         ddi_put32(hmep->hme_mifregh, (uint32_t *)&hmep->hme_mifregp->reg, value)
 355 
 356 #define GET_ETXREG(reg) \
 357         ddi_get32(hmep->hme_etxregh, (uint32_t *)&hmep->hme_etxregp->reg)
 358 #define PUT_ETXREG(reg, value) \
 359         ddi_put32(hmep->hme_etxregh, (uint32_t *)&hmep->hme_etxregp->reg, value)
 360 #define GET_ERXREG(reg) \
 361         ddi_get32(hmep->hme_erxregh, (uint32_t *)&hmep->hme_erxregp->reg)
 362 #define PUT_ERXREG(reg, value) \
 363         ddi_put32(hmep->hme_erxregh, (uint32_t *)&hmep->hme_erxregp->reg, value)
 364 #define GET_MACREG(reg) \
 365         ddi_get32(hmep->hme_bmacregh, (uint32_t *)&hmep->hme_bmacregp->reg)
 366 #define PUT_MACREG(reg, value) \
 367         ddi_put32(hmep->hme_bmacregh, \
 368                 (uint32_t *)&hmep->hme_bmacregp->reg, value)
 369 #define GET_GLOBREG(reg) \
 370         ddi_get32(hmep->hme_globregh, (uint32_t *)&hmep->hme_globregp->reg)
 371 #define PUT_GLOBREG(reg, value) \
 372         ddi_put32(hmep->hme_globregh, \
 373                 (uint32_t *)&hmep->hme_globregp->reg, value)
 374 #define PUT_TMD(ptr, paddr, len, flags)                                 \
 375         ddi_put32(hmep->hme_tmd_acch, &hmep->hme_tmdp[ptr].tmd_addr, paddr); \
 376         ddi_put32(hmep->hme_tmd_acch, &hmep->hme_tmdp[ptr].tmd_flags, \
 377             len | flags)
 378 #define GET_TMD_FLAGS(ptr)                                      \
 379         ddi_get32(hmep->hme_tmd_acch, &hmep->hme_tmdp[ptr].tmd_flags)
 380 #define PUT_RMD(ptr, paddr) \
 381         ddi_put32(hmep->hme_rmd_acch, &hmep->hme_rmdp[ptr].rmd_addr, paddr); \
 382         ddi_put32(hmep->hme_rmd_acch, &hmep->hme_rmdp[ptr].rmd_flags, \
 383             (uint32_t)(HMEBUFSIZE << HMERMD_BUFSIZE_SHIFT) | HMERMD_OWN)
 384 #define GET_RMD_FLAGS(ptr)                                      \
 385         ddi_get32(hmep->hme_rmd_acch, &hmep->hme_rmdp[ptr].rmd_flags)
 386 
 387 #define GET_ROM8(offset) \
 388         ddi_get8((hmep->hme_romh), (offset))
 389 
 390 /*
 391  * Ether_copy is not endian-correct. Define an endian-correct version.
 392  */
 393 #define ether_bcopy(a, b) (bcopy(a, b, 6))
 394 
 395 /*
 396  * Ether-type is specifically big-endian, but data region is unknown endian
 397  */
 398 #define get_ether_type(ptr) \
 399         (((((uint8_t *)ptr)[12] << 8) | (((uint8_t *)ptr)[13])))
 400 
 401 /* <<<<<<<<<<<<<<<<<<<<<<  Configuration Parameters >>>>>>>>>>>>>>>>>>>>> */
 402 
 403 #define BMAC_DEFAULT_JAMSIZE    (0x04)          /* jamsize equals 4 */
 404 #define BMAC_LONG_JAMSIZE       (0x10)          /* jamsize equals 0x10 */
 405 static  int     jamsize = BMAC_DEFAULT_JAMSIZE;
 406 
 407 
 408 /*
 409  * Calculate the bit in the multicast address filter that selects the given
 410  * address.
 411  */
 412 
 413 static uint32_t
 414 hmeladrf_bit(const uint8_t *addr)
 415 {
 416         uint32_t crc;
 417 
 418         CRC32(crc, addr, ETHERADDRL, -1U, crc32_table);
 419 
 420         /*
 421          * Just want the 6 most significant bits.
 422          */
 423         return (crc >> 26);
 424 }
 425 
 426 /* <<<<<<<<<<<<<<<<<<<<<<<<  Bit Bang Operations >>>>>>>>>>>>>>>>>>>>>>>> */
 427 
 428 static void
 429 send_bit(struct hme *hmep, uint16_t x)
 430 {
 431         PUT_MIFREG(mif_bbdata, x);
 432         PUT_MIFREG(mif_bbclk, HME_BBCLK_LOW);
 433         PUT_MIFREG(mif_bbclk, HME_BBCLK_HIGH);
 434 }
 435 
 436 
 437 /*
 438  * To read the MII register bits according to the IEEE Standard
 439  */
 440 static uint16_t
 441 get_bit_std(uint8_t phyad, struct hme *hmep)
 442 {
 443         uint16_t        x;
 444 
 445         PUT_MIFREG(mif_bbclk, HME_BBCLK_LOW);
 446         drv_usecwait(1);        /* wait for  >330 ns for stable data */
 447         if (phyad == HME_INTERNAL_PHYAD)
 448                 x = (GET_MIFREG(mif_cfg) & HME_MIF_CFGM0) ? 1 : 0;
 449         else
 450                 x = (GET_MIFREG(mif_cfg) & HME_MIF_CFGM1) ? 1 : 0;
 451         PUT_MIFREG(mif_bbclk, HME_BBCLK_HIGH);
 452         return (x);
 453 }
 454 
 455 #define SEND_BIT(x)             send_bit(hmep, x)
 456 #define GET_BIT_STD(phyad, x)   x = get_bit_std(phyad, hmep)
 457 
 458 
 459 static void
 460 hme_bb_mii_write(struct hme *hmep, uint8_t phyad, uint8_t regad, uint16_t data)
 461 {
 462         int     i;
 463 
 464         PUT_MIFREG(mif_bbopenb, 1);     /* Enable the MII driver */
 465         (void) hme_bb_force_idle(hmep);
 466         SEND_BIT(0); SEND_BIT(1);       /* <ST> */
 467         SEND_BIT(0); SEND_BIT(1);       /* <OP> */
 468 
 469         for (i = 4; i >= 0; i--) {           /* <AAAAA> */
 470                 SEND_BIT((phyad >> i) & 1);
 471         }
 472 
 473         for (i = 4; i >= 0; i--) {           /* <RRRRR> */
 474                 SEND_BIT((regad >> i) & 1);
 475         }
 476 
 477         SEND_BIT(1); SEND_BIT(0);       /* <TA> */
 478 
 479         for (i = 0xf; i >= 0; i--) { /* <DDDDDDDDDDDDDDDD> */
 480                 SEND_BIT((data >> i) & 1);
 481         }
 482 
 483         PUT_MIFREG(mif_bbopenb, 0);     /* Disable the MII driver */
 484         CHECK_MIFREG();
 485 }
 486 
 487 /* Return 0 if OK, 1 if error (Transceiver does not talk management) */
 488 static uint16_t
 489 hme_bb_mii_read(struct hme *hmep, uint8_t phyad, uint8_t regad)
 490 {
 491         int             i;
 492         uint32_t        x;
 493         uint16_t        data = 0;
 494 
 495         PUT_MIFREG(mif_bbopenb, 1);     /* Enable the MII driver */
 496         (void) hme_bb_force_idle(hmep);
 497         SEND_BIT(0); SEND_BIT(1);       /* <ST> */
 498         SEND_BIT(1); SEND_BIT(0);       /* <OP> */
 499         for (i = 4; i >= 0; i--) {           /* <AAAAA> */
 500                 SEND_BIT((phyad >> i) & 1);
 501         }
 502         for (i = 4; i >= 0; i--) {           /* <RRRRR> */
 503                 SEND_BIT((regad >> i) & 1);
 504         }
 505 
 506         PUT_MIFREG(mif_bbopenb, 0);     /* Disable the MII driver */
 507 
 508         GET_BIT_STD(phyad, x);
 509         GET_BIT_STD(phyad, x);          /* <TA> */
 510         for (i = 0xf; i >= 0; i--) { /* <DDDDDDDDDDDDDDDD> */
 511                 GET_BIT_STD(phyad, x);
 512                 data += (x << i);
 513         }
 514         /*
 515          * Kludge to get the Transceiver out of hung mode
 516          */
 517         GET_BIT_STD(phyad, x);
 518         GET_BIT_STD(phyad, x);
 519         GET_BIT_STD(phyad, x);
 520         CHECK_MIFREG();
 521         return (data);
 522 }
 523 
 524 
 525 static void
 526 hme_bb_force_idle(struct hme *hmep)
 527 {
 528         int     i;
 529 
 530         for (i = 0; i < 33; i++) {
 531                 SEND_BIT(1);
 532         }
 533 }
 534 
 535 /* <<<<<<<<<<<<<<<<<<<<End of Bit Bang Operations >>>>>>>>>>>>>>>>>>>>>>>> */
 536 
 537 
 538 /* <<<<<<<<<<<<< Frame Register used for MII operations >>>>>>>>>>>>>>>>>>>> */
 539 
 540 /* Return 0 if OK, 1 if error (Transceiver does not talk management) */
 541 static uint16_t
 542 hme_mii_read(void *arg, uint8_t phyad, uint8_t regad)
 543 {
 544         struct hme      *hmep = arg;
 545         uint32_t        frame;
 546         uint32_t        tmp_mif;
 547         uint32_t        tmp_xif;
 548 
 549         tmp_mif = GET_MIFREG(mif_cfg);
 550         tmp_xif = GET_MACREG(xifc);
 551 
 552         switch (phyad) {
 553         case HME_EXTERNAL_PHYAD:
 554                 PUT_MIFREG(mif_cfg, tmp_mif | HME_MIF_CFGPS);
 555                 PUT_MACREG(xifc, tmp_xif | BMAC_XIFC_MIIBUFDIS);
 556                 break;
 557         case HME_INTERNAL_PHYAD:
 558                 PUT_MIFREG(mif_cfg, tmp_mif & ~(HME_MIF_CFGPS));
 559                 PUT_MACREG(xifc, tmp_xif & ~(BMAC_XIFC_MIIBUFDIS));
 560                 break;
 561         default:
 562                 return (0xffff);
 563         }
 564 
 565         if (!hmep->hme_frame_enable) {
 566                 frame = (hme_bb_mii_read(hmep, phyad, regad));
 567                 PUT_MACREG(xifc, tmp_xif);
 568                 PUT_MIFREG(mif_cfg, tmp_mif);
 569                 return (frame & 0xffff);
 570         }
 571 
 572         PUT_MIFREG(mif_frame,
 573             HME_MIF_FRREAD | (phyad << HME_MIF_FRPHYAD_SHIFT) |
 574             (regad << HME_MIF_FRREGAD_SHIFT));
 575 /*
 576  *      HMEDELAY((*framerp & HME_MIF_FRTA0), HMEMAXRSTDELAY);
 577  */
 578         HMEDELAY((GET_MIFREG(mif_frame) & HME_MIF_FRTA0), 300);
 579         frame = GET_MIFREG(mif_frame);
 580         CHECK_MIFREG();
 581 
 582         PUT_MACREG(xifc, tmp_xif);
 583         PUT_MIFREG(mif_cfg, tmp_mif);
 584 
 585         if ((frame & HME_MIF_FRTA0) == 0) {
 586 
 587 
 588                 HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, MII_MSG,
 589                     "MIF Read failure");
 590                 return (0xffff);
 591         }
 592         return ((uint16_t)(frame & HME_MIF_FRDATA));
 593 }
 594 
 595 static void
 596 hme_mii_write(void *arg, uint8_t phyad, uint8_t regad, uint16_t data)
 597 {
 598         struct hme *hmep = arg;
 599         uint32_t frame;
 600         uint32_t tmp_mif;
 601         uint32_t tmp_xif;
 602 
 603         tmp_mif = GET_MIFREG(mif_cfg);
 604         tmp_xif = GET_MACREG(xifc);
 605 
 606         switch (phyad) {
 607         case HME_EXTERNAL_PHYAD:
 608                 PUT_MIFREG(mif_cfg, tmp_mif | HME_MIF_CFGPS);
 609                 PUT_MACREG(xifc, tmp_xif | BMAC_XIFC_MIIBUFDIS);
 610                 break;
 611         case HME_INTERNAL_PHYAD:
 612                 PUT_MIFREG(mif_cfg, tmp_mif & ~(HME_MIF_CFGPS));
 613                 PUT_MACREG(xifc, tmp_xif & ~(BMAC_XIFC_MIIBUFDIS));
 614                 break;
 615         default:
 616                 return;
 617         }
 618 
 619         if (!hmep->hme_frame_enable) {
 620                 hme_bb_mii_write(hmep, phyad, regad, data);
 621                 PUT_MACREG(xifc, tmp_xif);
 622                 PUT_MIFREG(mif_cfg, tmp_mif);
 623                 return;
 624         }
 625 
 626         PUT_MIFREG(mif_frame,
 627             HME_MIF_FRWRITE | (phyad << HME_MIF_FRPHYAD_SHIFT) |
 628             (regad << HME_MIF_FRREGAD_SHIFT) | data);
 629 /*
 630  *      HMEDELAY((*framerp & HME_MIF_FRTA0), HMEMAXRSTDELAY);
 631  */
 632         HMEDELAY((GET_MIFREG(mif_frame) & HME_MIF_FRTA0), 300);
 633         frame = GET_MIFREG(mif_frame);
 634         PUT_MACREG(xifc, tmp_xif);
 635         PUT_MIFREG(mif_cfg, tmp_mif);
 636         CHECK_MIFREG();
 637         if ((frame & HME_MIF_FRTA0) == 0) {
 638                 HME_FAULT_MSG1(hmep, SEVERITY_MID, MII_MSG,
 639                     "MIF Write failure");
 640         }
 641 }
 642 
 643 static void
 644 hme_mii_notify(void *arg, link_state_t link)
 645 {
 646         struct hme *hmep = arg;
 647 
 648         if (link == LINK_STATE_UP) {
 649                 (void) hmeinit(hmep);
 650         }
 651         mac_link_update(hmep->hme_mh, link);
 652 }
 653 
 654 /* <<<<<<<<<<<<<<<<<<<<<<<<<<<  LOADABLE ENTRIES  >>>>>>>>>>>>>>>>>>>>>>> */
 655 
 656 int
 657 _init(void)
 658 {
 659         int     status;
 660 
 661         mac_init_ops(&hme_dev_ops, "hme");
 662         if ((status = mod_install(&modlinkage)) != 0) {
 663                 mac_fini_ops(&hme_dev_ops);
 664         }
 665         return (status);
 666 }
 667 
 668 int
 669 _fini(void)
 670 {
 671         int     status;
 672 
 673         if ((status = mod_remove(&modlinkage)) == 0) {
 674                 mac_fini_ops(&hme_dev_ops);
 675         }
 676         return (status);
 677 }
 678 
 679 int
 680 _info(struct modinfo *modinfop)
 681 {
 682         return (mod_info(&modlinkage, modinfop));
 683 }
 684 
 685 /*
 686  * ddi_dma_sync() a TMD or RMD descriptor.
 687  */
 688 #define HMESYNCRMD(num, who)                            \
 689         (void) ddi_dma_sync(hmep->hme_rmd_dmah,              \
 690             (num * sizeof (struct hme_rmd)),            \
 691             sizeof (struct hme_rmd),                    \
 692             who)
 693 
 694 #define HMESYNCTMD(num, who)                            \
 695         (void) ddi_dma_sync(hmep->hme_tmd_dmah,              \
 696             (num * sizeof (struct hme_tmd)),            \
 697             sizeof (struct hme_tmd),                    \
 698             who)
 699 
 700 /*
 701  * Ethernet broadcast address definition.
 702  */
 703 static  struct ether_addr       etherbroadcastaddr = {
 704         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 705 };
 706 
 707 /*
 708  * MIB II broadcast/multicast packets
 709  */
 710 #define IS_BROADCAST(pkt) (bcmp(pkt, &etherbroadcastaddr, ETHERADDRL) == 0)
 711 #define IS_MULTICAST(pkt) ((pkt[0] & 01) == 1)
 712 #define BUMP_InNUcast(hmep, pkt) \
 713         if (IS_MULTICAST(pkt)) {                               \
 714                 if (IS_BROADCAST(pkt)) {                       \
 715                         hmep->hme_brdcstrcv++;                      \
 716                 } else {                                       \
 717                         hmep->hme_multircv++;                       \
 718                 }                                              \
 719         }
 720 #define BUMP_OutNUcast(hmep, pkt) \
 721         if (IS_MULTICAST(pkt)) {                               \
 722                 if (IS_BROADCAST(pkt)) {                       \
 723                         hmep->hme_brdcstxmt++;                      \
 724                 } else {                                       \
 725                         hmep->hme_multixmt++;                       \
 726                 }                                              \
 727         }
 728 
 729 static int
 730 hme_create_prop_from_kw(dev_info_t *dip, char *vpdname, char *vpdstr)
 731 {
 732         char propstr[80];
 733         int i, needprop = 0;
 734         struct ether_addr local_mac;
 735 
 736         if (strcmp(vpdname, "NA") == 0) {
 737                 (void) strcpy(propstr, "local-mac-address");
 738                 needprop = 1;
 739         } else if (strcmp(vpdname, "Z0") == 0) {
 740                 (void) strcpy(propstr, "model");
 741                 needprop = 1;
 742         } else if (strcmp(vpdname, "Z1") == 0) {
 743                 (void) strcpy(propstr, "board-model");
 744                 needprop = 1;
 745         }
 746 
 747         if (needprop == 1) {
 748 
 749                 if (strcmp(propstr, "local-mac-address") == 0) {
 750                         for (i = 0; i < ETHERADDRL; i++)
 751                                 local_mac.ether_addr_octet[i] =
 752                                     (uchar_t)vpdstr[i];
 753                         if (ddi_prop_create(DDI_DEV_T_NONE, dip,
 754                             DDI_PROP_CANSLEEP, propstr,
 755                             (char *)local_mac.ether_addr_octet, ETHERADDRL)
 756                             != DDI_SUCCESS) {
 757                                 return (DDI_FAILURE);
 758                         }
 759                 } else {
 760                         if (ddi_prop_create(DDI_DEV_T_NONE, dip,
 761                             DDI_PROP_CANSLEEP, propstr, vpdstr,
 762                             strlen(vpdstr)+1) != DDI_SUCCESS) {
 763                                 return (DDI_FAILURE);
 764                         }
 765                 }
 766         }
 767         return (0);
 768 }
 769 
 770 /*
 771  * Get properties from old VPD
 772  * for PCI cards
 773  */
 774 static int
 775 hme_get_oldvpd_props(dev_info_t *dip, int vpd_base)
 776 {
 777         struct hme *hmep;
 778         int vpd_start, vpd_len, kw_start, kw_len, kw_ptr;
 779         char kw_namestr[3];
 780         char kw_fieldstr[256];
 781         int i;
 782 
 783         hmep = ddi_get_driver_private(dip);
 784 
 785         vpd_start = vpd_base;
 786 
 787         if ((GET_ROM8(&hmep->hme_romp[vpd_start]) & 0xff) != 0x90) {
 788                 return (1); /* error */
 789         } else {
 790                 vpd_len = 9;
 791         }
 792 
 793         /* Get local-mac-address */
 794         kw_start = vpd_start + 3; /* Location of 1st keyword */
 795         kw_ptr = kw_start;
 796         while ((kw_ptr - kw_start) < vpd_len) { /* Get all keywords */
 797                 kw_namestr[0] = GET_ROM8(&hmep->hme_romp[kw_ptr]);
 798                 kw_namestr[1] = GET_ROM8(&hmep->hme_romp[kw_ptr+1]);
 799                 kw_namestr[2] = '\0';
 800                 kw_len = (int)(GET_ROM8(&hmep->hme_romp[kw_ptr+2]) & 0xff);
 801                 for (i = 0, kw_ptr += 3; i < kw_len; i++)
 802                         kw_fieldstr[i] = GET_ROM8(&hmep->hme_romp[kw_ptr+i]);
 803                 kw_fieldstr[i] = '\0';
 804                 if (hme_create_prop_from_kw(dip, kw_namestr, kw_fieldstr)) {
 805                         return (DDI_FAILURE);
 806                 }
 807                 kw_ptr += kw_len;
 808         } /* next keyword */
 809 
 810         if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "model",
 811             "SUNW,cheerio", strlen("SUNW,cheerio")+1) != DDI_SUCCESS) {
 812                 return (DDI_FAILURE);
 813         }
 814         return (0);
 815 }
 816 
 817 
 818 /*
 819  * Get properties from new VPD
 820  * for CompactPCI cards
 821  */
 822 static int
 823 hme_get_newvpd_props(dev_info_t *dip, int vpd_base)
 824 {
 825         struct hme *hmep;
 826         int vpd_start, vpd_len, kw_start, kw_len, kw_ptr;
 827         char kw_namestr[3];
 828         char kw_fieldstr[256];
 829         int maxvpdsize, i;
 830 
 831         hmep = ddi_get_driver_private(dip);
 832 
 833         maxvpdsize = 1024; /* Real size not known until after it is read */
 834 
 835         vpd_start = (int)((GET_ROM8(&(hmep->hme_romp[vpd_base+1])) & 0xff) |
 836             ((GET_ROM8(&hmep->hme_romp[vpd_base+2]) & 0xff) << 8)) +3;
 837         vpd_start = vpd_base + vpd_start;
 838         while (vpd_start < (vpd_base + maxvpdsize)) { /* Get all VPDs */
 839                 if ((GET_ROM8(&hmep->hme_romp[vpd_start]) & 0xff) != 0x90) {
 840                         break; /* no VPD found */
 841                 } else {
 842                         vpd_len = (int)((GET_ROM8(&hmep->hme_romp[vpd_start
 843                             + 1]) & 0xff) | (GET_ROM8(&hmep->hme_romp[vpd_start
 844                             + 2]) & 0xff) << 8);
 845                 }
 846                 /* Get all keywords in this VPD */
 847                 kw_start = vpd_start + 3; /* Location of 1st keyword */
 848                 kw_ptr = kw_start;
 849                 while ((kw_ptr - kw_start) < vpd_len) { /* Get all keywords */
 850                         kw_namestr[0] = GET_ROM8(&hmep->hme_romp[kw_ptr]);
 851                         kw_namestr[1] = GET_ROM8(&hmep->hme_romp[kw_ptr+1]);
 852                         kw_namestr[2] = '\0';
 853                         kw_len =
 854                             (int)(GET_ROM8(&hmep->hme_romp[kw_ptr+2]) & 0xff);
 855                         for (i = 0, kw_ptr += 3; i < kw_len; i++)
 856                                 kw_fieldstr[i] =
 857                                     GET_ROM8(&hmep->hme_romp[kw_ptr+i]);
 858                         kw_fieldstr[i] = '\0';
 859                         if (hme_create_prop_from_kw(dip, kw_namestr,
 860                             kw_fieldstr)) {
 861                                 return (DDI_FAILURE);
 862                         }
 863                         kw_ptr += kw_len;
 864                 } /* next keyword */
 865                 vpd_start += (vpd_len + 3);
 866         } /* next VPD */
 867         return (0);
 868 }
 869 
 870 
 871 /*
 872  * Get properties from VPD
 873  */
 874 static int
 875 hme_get_vpd_props(dev_info_t *dip)
 876 {
 877         struct hme *hmep;
 878         int v0, v1, vpd_base;
 879         int i, epromsrchlimit;
 880 
 881 
 882         hmep = ddi_get_driver_private(dip);
 883 
 884         v0 = (int)(GET_ROM8(&(hmep->hme_romp[0])));
 885         v1 = (int)(GET_ROM8(&(hmep->hme_romp[1])));
 886         v0 = ((v0 & 0xff) << 8 | v1);
 887 
 888         if ((v0 & 0xffff) != 0x55aa) {
 889                 cmn_err(CE_NOTE, " Valid pci prom not found \n");
 890                 return (1);
 891         }
 892 
 893         epromsrchlimit = 4096;
 894         for (i = 2; i < epromsrchlimit; i++) {
 895                 /* "PCIR" */
 896                 if (((GET_ROM8(&(hmep->hme_romp[i])) & 0xff) == 'P') &&
 897                     ((GET_ROM8(&(hmep->hme_romp[i+1])) & 0xff) == 'C') &&
 898                     ((GET_ROM8(&(hmep->hme_romp[i+2])) & 0xff) == 'I') &&
 899                     ((GET_ROM8(&(hmep->hme_romp[i+3])) & 0xff) == 'R')) {
 900                         vpd_base =
 901                             (int)((GET_ROM8(&(hmep->hme_romp[i+8])) & 0xff) |
 902                             (GET_ROM8(&(hmep->hme_romp[i+9])) & 0xff) << 8);
 903                         break; /* VPD pointer found */
 904                 }
 905         }
 906 
 907         /* No VPD found */
 908         if (vpd_base == 0) {
 909                 cmn_err(CE_NOTE, " Vital Product Data pointer not found \n");
 910                 return (1);
 911         }
 912 
 913         v0 = (int)(GET_ROM8(&(hmep->hme_romp[vpd_base])));
 914         if (v0 == 0x82) {
 915                 if (hme_get_newvpd_props(dip, vpd_base))
 916                         return (1);
 917                 return (0);
 918         } else if (v0 == 0x90) {
 919                 /* If we are are SUNW,qfe card, look for the Nth "NA" descr */
 920                 if ((GET_ROM8(&hmep->hme_romp[vpd_base + 12])  != 0x79) &&
 921                     GET_ROM8(&hmep->hme_romp[vpd_base + 4 * 12]) == 0x79) {
 922                         vpd_base += hmep->hme_devno * 12;
 923                 }
 924                 if (hme_get_oldvpd_props(dip, vpd_base))
 925                         return (1);
 926                 return (0);
 927         } else
 928                 return (1);     /* unknown start byte in VPD */
 929 }
 930 
 931 /*
 932  * For x86, the BIOS doesn't map the PCI Rom register for the qfe
 933  * cards, so we have to extract it from the ebus bridge that is
 934  * function zero of the same device.  This is a bit of an ugly hack.
 935  * (The ebus bridge leaves the entire ROM mapped at base address
 936  * register 0x10.)
 937  */
 938 
 939 typedef struct {
 940         struct hme              *hmep;
 941         dev_info_t              *parent;
 942         uint8_t                 bus, dev;
 943         ddi_acc_handle_t        acch;
 944         caddr_t                 romp;
 945 } ebus_rom_t;
 946 
 947 static int
 948 hme_mapebusrom(dev_info_t *dip, void *arg)
 949 {
 950         int             *regs;
 951         unsigned        nregs;
 952         int             reg;
 953         ebus_rom_t      *rom = arg;
 954         struct hme      *hmep = rom->hmep;
 955 
 956         /*
 957          * We only want to look at our peers.  Skip our parent.
 958          */
 959         if (dip == rom->parent) {
 960                 return (DDI_WALK_PRUNESIB);
 961         }
 962 
 963         if (ddi_get_parent(dip) != rom->parent)
 964                 return (DDI_WALK_CONTINUE);
 965 
 966         if ((ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0,
 967             "reg", &regs, &nregs)) != DDI_PROP_SUCCESS) {
 968                 return (DDI_WALK_PRUNECHILD);
 969         }
 970 
 971         if (nregs < 1) {
 972                 ddi_prop_free(regs);
 973                 return (DDI_WALK_PRUNECHILD);
 974         }
 975         reg = regs[0];
 976         ddi_prop_free(regs);
 977 
 978         /*
 979          * Look for function 0 on our bus and device.  If the device doesn't
 980          * match, it might be an alternate peer, in which case we don't want
 981          * to examine any of its children.
 982          */
 983         if ((PCI_REG_BUS_G(reg) != rom->bus) ||
 984             (PCI_REG_DEV_G(reg) != rom->dev) ||
 985             (PCI_REG_FUNC_G(reg) != 0)) {
 986                 return (DDI_WALK_PRUNECHILD);
 987         }
 988 
 989         (void) ddi_regs_map_setup(dip, 1, &rom->romp, 0, 0, &hmep->hme_dev_attr,
 990             &rom->acch);
 991         /*
 992          * If we can't map the registers, the caller will notice that
 993          * the acch is NULL.
 994          */
 995         return (DDI_WALK_TERMINATE);
 996 }
 997 
 998 static int
 999 hmeget_promebus(dev_info_t *dip)
1000 {
1001         ebus_rom_t      rom;
1002         int             *regs;
1003         unsigned        nregs;
1004         struct hme      *hmep;
1005 
1006         hmep = ddi_get_driver_private(dip);
1007 
1008         bzero(&rom, sizeof (rom));
1009 
1010         /*
1011          * For x86, the BIOS doesn't map the PCI Rom register for the qfe
1012          * cards, so we have to extract it from the eBus bridge that is
1013          * function zero.  This is a bit of an ugly hack.
1014          */
1015         if ((ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0,
1016             "reg", &regs, &nregs)) != DDI_PROP_SUCCESS) {
1017                 return (DDI_FAILURE);
1018         }
1019 
1020         if (nregs < 5) {
1021                 ddi_prop_free(regs);
1022                 return (DDI_FAILURE);
1023         }
1024         rom.hmep = hmep;
1025         rom.bus = PCI_REG_BUS_G(regs[0]);
1026         rom.dev = PCI_REG_DEV_G(regs[0]);
1027         hmep->hme_devno = rom.dev;
1028         rom.parent = ddi_get_parent(dip);
1029 
1030         /*
1031          * The implementation of ddi_walk_devs says that we must not
1032          * be called during autoconfiguration.  However, it turns out
1033          * that it is safe to call this during our attach routine,
1034          * because we are not a nexus device.
1035          *
1036          * Previously we rooted our search at our immediate parent,
1037          * but this triggered an assertion panic in debug kernels.
1038          */
1039         ddi_walk_devs(ddi_root_node(), hme_mapebusrom, &rom);
1040 
1041         if (rom.acch) {
1042                 hmep->hme_romh = rom.acch;
1043                 hmep->hme_romp = (unsigned char *)rom.romp;
1044                 return (DDI_SUCCESS);
1045         }
1046         return (DDI_FAILURE);
1047 }
1048 
1049 static int
1050 hmeget_promprops(dev_info_t *dip)
1051 {
1052         struct hme *hmep;
1053         int rom_bar;
1054         ddi_acc_handle_t cfg_handle;
1055         struct {
1056                 uint16_t vendorid;
1057                 uint16_t devid;
1058                 uint16_t command;
1059                 uint16_t status;
1060                 uint32_t junk1;
1061                 uint8_t cache_line;
1062                 uint8_t latency;
1063                 uint8_t header;
1064                 uint8_t bist;
1065                 uint32_t base;
1066                 uint32_t base14;
1067                 uint32_t base18;
1068                 uint32_t base1c;
1069                 uint32_t base20;
1070                 uint32_t base24;
1071                 uint32_t base28;
1072                 uint32_t base2c;
1073                 uint32_t base30;
1074         } *cfg_ptr;
1075 
1076         hmep = ddi_get_driver_private(dip);
1077 
1078 
1079         /*
1080          * map configuration space
1081          */
1082         if (ddi_regs_map_setup(hmep->dip, 0, (caddr_t *)&cfg_ptr,
1083             0, 0, &hmep->hme_dev_attr, &cfg_handle)) {
1084                 return (DDI_FAILURE);
1085         }
1086 
1087         /*
1088          * Enable bus-master and memory accesses
1089          */
1090         ddi_put16(cfg_handle, &cfg_ptr->command,
1091             PCI_COMM_SERR_ENABLE | PCI_COMM_PARITY_DETECT |
1092             PCI_COMM_MAE | PCI_COMM_ME);
1093 
1094         /*
1095          * Enable rom accesses
1096          */
1097         rom_bar = ddi_get32(cfg_handle, &cfg_ptr->base30);
1098         ddi_put32(cfg_handle, &cfg_ptr->base30, rom_bar | 1);
1099 
1100 
1101         if ((ddi_regs_map_setup(dip, 2, (caddr_t *)&(hmep->hme_romp), 0, 0,
1102             &hmep->hme_dev_attr, &hmep->hme_romh) != DDI_SUCCESS) &&
1103             (hmeget_promebus(dip) != DDI_SUCCESS)) {
1104 
1105                 if (cfg_ptr)
1106                         ddi_regs_map_free(&cfg_handle);
1107                 return (DDI_FAILURE);
1108         } else {
1109                 if (hme_get_vpd_props(dip))
1110                         return (DDI_FAILURE);
1111         }
1112         if (hmep->hme_romp)
1113                 ddi_regs_map_free(&hmep->hme_romh);
1114         if (cfg_ptr)
1115                 ddi_regs_map_free(&cfg_handle);
1116         return (DDI_SUCCESS);
1117 
1118 }
1119 
1120 static void
1121 hmeget_hm_rev_property(struct hme *hmep)
1122 {
1123         int     hm_rev;
1124 
1125 
1126         hm_rev = hmep->asic_rev;
1127         switch (hm_rev) {
1128         case HME_2P1_REVID:
1129         case HME_2P1_REVID_OBP:
1130                 HME_FAULT_MSG2(hmep, SEVERITY_NONE, DISPLAY_MSG,
1131                     "SBus 2.1 Found (Rev Id = %x)", hm_rev);
1132                 hmep->hme_frame_enable = 1;
1133                 break;
1134 
1135         case HME_2P0_REVID:
1136                 HME_FAULT_MSG2(hmep, SEVERITY_NONE, DISPLAY_MSG,
1137                     "SBus 2.0 Found (Rev Id = %x)", hm_rev);
1138                 break;
1139 
1140         case HME_1C0_REVID:
1141                 HME_FAULT_MSG2(hmep, SEVERITY_NONE, DISPLAY_MSG,
1142                     "PCI IO 1.0 Found (Rev Id = %x)", hm_rev);
1143                 break;
1144 
1145         default:
1146                 HME_FAULT_MSG3(hmep, SEVERITY_NONE, DISPLAY_MSG,
1147                     "%s (Rev Id = %x) Found",
1148                     (hm_rev == HME_2C0_REVID) ? "PCI IO 2.0" : "Sbus", hm_rev);
1149                 hmep->hme_frame_enable = 1;
1150                 hmep->hme_lance_mode_enable = 1;
1151                 hmep->hme_rxcv_enable = 1;
1152                 break;
1153         }
1154 }
1155 
1156 /*
1157  * Interface exists: make available by filling in network interface
1158  * record.  System will initialize the interface when it is ready
1159  * to accept packets.
1160  */
1161 int
1162 hmeattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1163 {
1164         struct hme *hmep;
1165         mac_register_t *macp = NULL;
1166         int     regno;
1167         int hm_rev = 0;
1168         int prop_len = sizeof (int);
1169         ddi_acc_handle_t cfg_handle;
1170         struct {
1171                 uint16_t vendorid;
1172                 uint16_t devid;
1173                 uint16_t command;
1174                 uint16_t status;
1175                 uint8_t revid;
1176                 uint8_t j1;
1177                 uint16_t j2;
1178         } *cfg_ptr;
1179 
1180         switch (cmd) {
1181         case DDI_ATTACH:
1182                 break;
1183 
1184         case DDI_RESUME:
1185                 if ((hmep = ddi_get_driver_private(dip)) == NULL)
1186                         return (DDI_FAILURE);
1187 
1188                 hmep->hme_flags &= ~HMESUSPENDED;
1189 
1190                 mii_resume(hmep->hme_mii);
1191 
1192                 if (hmep->hme_started)
1193                         (void) hmeinit(hmep);
1194                 return (DDI_SUCCESS);
1195 
1196         default:
1197                 return (DDI_FAILURE);
1198         }
1199 
1200         /*
1201          * Allocate soft device data structure
1202          */
1203         hmep = kmem_zalloc(sizeof (*hmep), KM_SLEEP);
1204 
1205         /*
1206          * Might as well set up elements of data structure
1207          */
1208         hmep->dip =          dip;
1209         hmep->instance =     ddi_get_instance(dip);
1210         hmep->pagesize =     ddi_ptob(dip, (ulong_t)1); /* IOMMU PSize */
1211 
1212         /*
1213          *  Might as well setup the driver private
1214          * structure as part of the dip.
1215          */
1216         ddi_set_driver_private(dip, hmep);
1217 
1218         /*
1219          * Reject this device if it's in a slave-only slot.
1220          */
1221         if (ddi_slaveonly(dip) == DDI_SUCCESS) {
1222                 HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1223                     "Dev not used - dev in slave only slot");
1224                 goto error_state;
1225         }
1226 
1227         /*
1228          * Map in the device registers.
1229          *
1230          * Reg # 0 is the Global register set
1231          * Reg # 1 is the ETX register set
1232          * Reg # 2 is the ERX register set
1233          * Reg # 3 is the BigMAC register set.
1234          * Reg # 4 is the MIF register set
1235          */
1236         if (ddi_dev_nregs(dip, &regno) != (DDI_SUCCESS)) {
1237                 HME_FAULT_MSG2(hmep, SEVERITY_HIGH, INIT_MSG,
1238                     ddi_nregs_fail_msg, regno);
1239                 goto error_state;
1240         }
1241 
1242         switch (regno) {
1243         case 5:
1244                 hmep->hme_cheerio_mode = 0;
1245                 break;
1246         case 2:
1247         case 3: /* for hot swap/plug, there will be 3 entries in "reg" prop */
1248                 hmep->hme_cheerio_mode = 1;
1249                 break;
1250         default:
1251                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
1252                     bad_num_regs_msg);
1253                 goto error_state;
1254         }
1255 
1256         /* Initialize device attributes structure */
1257         hmep->hme_dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1258 
1259         if (hmep->hme_cheerio_mode)
1260                 hmep->hme_dev_attr.devacc_attr_endian_flags =
1261                     DDI_STRUCTURE_LE_ACC;
1262         else
1263                 hmep->hme_dev_attr.devacc_attr_endian_flags =
1264                     DDI_STRUCTURE_BE_ACC;
1265 
1266         hmep->hme_dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1267 
1268         if (hmep->hme_cheerio_mode) {
1269                 uint8_t         oldLT;
1270                 uint8_t         newLT = 0;
1271                 dev_info_t      *pdip;
1272                 const char      *pdrvname;
1273 
1274                 /*
1275                  * Map the PCI config space
1276                  */
1277                 if (pci_config_setup(dip, &hmep->pci_config_handle) !=
1278                     DDI_SUCCESS) {
1279                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1280                             "pci_config_setup() failed..");
1281                         goto error_state;
1282                 }
1283 
1284                 if (ddi_regs_map_setup(dip, 1,
1285                     (caddr_t *)&(hmep->hme_globregp), 0, 0,
1286                     &hmep->hme_dev_attr, &hmep->hme_globregh)) {
1287                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1288                             mregs_4global_reg_fail_msg);
1289                         goto error_unmap;
1290                 }
1291                 hmep->hme_etxregh = hmep->hme_erxregh = hmep->hme_bmacregh =
1292                     hmep->hme_mifregh = hmep->hme_globregh;
1293 
1294                 hmep->hme_etxregp =
1295                     (void *)(((caddr_t)hmep->hme_globregp) + 0x2000);
1296                 hmep->hme_erxregp =
1297                     (void *)(((caddr_t)hmep->hme_globregp) + 0x4000);
1298                 hmep->hme_bmacregp =
1299                     (void *)(((caddr_t)hmep->hme_globregp) + 0x6000);
1300                 hmep->hme_mifregp =
1301                     (void *)(((caddr_t)hmep->hme_globregp) + 0x7000);
1302 
1303                 /*
1304                  * Get parent pci bridge info.
1305                  */
1306                 pdip = ddi_get_parent(dip);
1307                 pdrvname = ddi_driver_name(pdip);
1308 
1309                 oldLT = pci_config_get8(hmep->pci_config_handle,
1310                     PCI_CONF_LATENCY_TIMER);
1311                 /*
1312                  * Honor value set in /etc/system
1313                  * "set hme:pci_latency_timer=0xYY"
1314                  */
1315                 if (pci_latency_timer)
1316                         newLT = pci_latency_timer;
1317                 /*
1318                  * Modify LT for simba
1319                  */
1320                 else if (strcmp("simba", pdrvname) == 0)
1321                         newLT = 0xf0;
1322                 /*
1323                  * Ensure minimum cheerio latency timer of 0x50
1324                  * Usually OBP or pci bridge should set this value
1325                  * based on cheerio
1326                  * min_grant * 8(33MHz) = 0x50 = 0xa * 0x8
1327                  * Some system set cheerio LT at 0x40
1328                  */
1329                 else if (oldLT < 0x40)
1330                         newLT = 0x50;
1331 
1332                 /*
1333                  * Now program cheerio's pci latency timer with newLT
1334                  */
1335                 if (newLT)
1336                         pci_config_put8(hmep->pci_config_handle,
1337                             PCI_CONF_LATENCY_TIMER, (uchar_t)newLT);
1338         } else { /* Map register sets */
1339                 if (ddi_regs_map_setup(dip, 0,
1340                     (caddr_t *)&(hmep->hme_globregp), 0, 0,
1341                     &hmep->hme_dev_attr, &hmep->hme_globregh)) {
1342                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1343                             mregs_4global_reg_fail_msg);
1344                         goto error_state;
1345                 }
1346                 if (ddi_regs_map_setup(dip, 1,
1347                     (caddr_t *)&(hmep->hme_etxregp), 0, 0,
1348                     &hmep->hme_dev_attr, &hmep->hme_etxregh)) {
1349                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1350                             mregs_4etx_reg_fail_msg);
1351                         goto error_unmap;
1352                 }
1353                 if (ddi_regs_map_setup(dip, 2,
1354                     (caddr_t *)&(hmep->hme_erxregp), 0, 0,
1355                     &hmep->hme_dev_attr, &hmep->hme_erxregh)) {
1356                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1357                             mregs_4erx_reg_fail_msg);
1358                         goto error_unmap;
1359                 }
1360                 if (ddi_regs_map_setup(dip, 3,
1361                     (caddr_t *)&(hmep->hme_bmacregp), 0, 0,
1362                     &hmep->hme_dev_attr, &hmep->hme_bmacregh)) {
1363                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1364                             mregs_4bmac_reg_fail_msg);
1365                         goto error_unmap;
1366                 }
1367 
1368                 if (ddi_regs_map_setup(dip, 4,
1369                     (caddr_t *)&(hmep->hme_mifregp), 0, 0,
1370                     &hmep->hme_dev_attr, &hmep->hme_mifregh)) {
1371                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1372                             mregs_4mif_reg_fail_msg);
1373                         goto error_unmap;
1374                 }
1375         } /* Endif cheerio_mode */
1376 
1377         /*
1378          * Based on the hm-rev, set some capabilities
1379          * Set up default capabilities for HM 2.0
1380          */
1381         hmep->hme_frame_enable = 0;
1382         hmep->hme_lance_mode_enable = 0;
1383         hmep->hme_rxcv_enable = 0;
1384 
1385         /* NEW routine to get the properties */
1386 
1387         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, hmep->dip, 0, "hm-rev",
1388             (caddr_t)&hm_rev, &prop_len) == DDI_PROP_SUCCESS) {
1389 
1390                 hmep->asic_rev = hm_rev;
1391                 hmeget_hm_rev_property(hmep);
1392         } else {
1393                 /*
1394                  * hm_rev property not found so, this is
1395                  * case of hot insertion of card without interpreting fcode.
1396                  * Get it from revid in config space after mapping it.
1397                  */
1398                 if (ddi_regs_map_setup(hmep->dip, 0, (caddr_t *)&cfg_ptr,
1399                     0, 0, &hmep->hme_dev_attr, &cfg_handle)) {
1400                         return (DDI_FAILURE);
1401                 }
1402                 /*
1403                  * Since this is cheerio-based PCI card, we write 0xC in the
1404                  * top 4 bits(4-7) of hm-rev and retain the bottom(0-3) bits
1405                  * for Cheerio version(1.0 or 2.0 = 0xC0 or 0xC1)
1406                  */
1407                 hm_rev = ddi_get8(cfg_handle, &cfg_ptr->revid);
1408                 hm_rev = HME_1C0_REVID | (hm_rev & HME_REV_VERS_MASK);
1409                 hmep->asic_rev = hm_rev;
1410                 if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
1411                     "hm-rev", (caddr_t)&hm_rev, sizeof (hm_rev)) !=
1412                     DDI_SUCCESS) {
1413                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, AUTOCONFIG_MSG,
1414                             "ddi_prop_create error for hm_rev");
1415                 }
1416                 ddi_regs_map_free(&cfg_handle);
1417 
1418                 hmeget_hm_rev_property(hmep);
1419 
1420                 /* get info via VPD */
1421                 if (hmeget_promprops(dip) != DDI_SUCCESS) {
1422                         HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, AUTOCONFIG_MSG,
1423                             "no promprops");
1424                 }
1425         }
1426 
1427         if (ddi_intr_hilevel(dip, 0)) {
1428                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, NFATAL_ERR_MSG,
1429                     " high-level interrupts are not supported");
1430                 goto error_unmap;
1431         }
1432 
1433         /*
1434          * Get intr. block cookie so that mutex locks can be initialized.
1435          */
1436         if (ddi_get_iblock_cookie(dip, 0, &hmep->hme_cookie) != DDI_SUCCESS)
1437                 goto error_unmap;
1438 
1439         /*
1440          * Initialize mutex's for this device.
1441          */
1442         mutex_init(&hmep->hme_xmitlock, NULL, MUTEX_DRIVER, hmep->hme_cookie);
1443         mutex_init(&hmep->hme_intrlock, NULL, MUTEX_DRIVER, hmep->hme_cookie);
1444 
1445         /*
1446          * Quiesce the hardware.
1447          */
1448         (void) hmestop(hmep);
1449 
1450         /*
1451          * Add interrupt to system
1452          */
1453         if (ddi_add_intr(dip, 0, (ddi_iblock_cookie_t *)NULL,
1454             (ddi_idevice_cookie_t *)NULL, hmeintr, (caddr_t)hmep)) {
1455                 HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, CONFIG_MSG,
1456                     add_intr_fail_msg);
1457                 goto error_mutex;
1458         }
1459 
1460         /*
1461          * Set up the ethernet mac address.
1462          */
1463         hme_setup_mac_address(hmep, dip);
1464 
1465         if (!hmeinit_xfer_params(hmep))
1466                 goto error_intr;
1467 
1468         if (hmeburstsizes(hmep) == DDI_FAILURE) {
1469                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG, burst_size_msg);
1470                 goto error_intr;
1471         }
1472 
1473         if (hmeallocthings(hmep) != DDI_SUCCESS) {
1474                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, CONFIG_MSG,
1475                     "resource allocation failed");
1476                 goto error_intr;
1477         }
1478 
1479         if (hmeallocbufs(hmep) != DDI_SUCCESS) {
1480                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, CONFIG_MSG,
1481                     "buffer allocation failed");
1482                 goto error_intr;
1483         }
1484 
1485         hmestatinit(hmep);
1486 
1487         /* our external (preferred) PHY is at address 0 */
1488         (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, "first-phy", 0);
1489 
1490         hmep->hme_mii = mii_alloc(hmep, dip, &hme_mii_ops);
1491         if (hmep->hme_mii == NULL) {
1492                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, CONFIG_MSG,
1493                     "mii_alloc failed");
1494                 goto error_intr;
1495         }
1496         /* force a probe for the PHY */
1497         mii_probe(hmep->hme_mii);
1498 
1499         if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
1500                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, CONFIG_MSG,
1501                     "mac_alloc failed");
1502                 goto error_intr;
1503         }
1504         macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1505         macp->m_driver = hmep;
1506         macp->m_dip = dip;
1507         macp->m_src_addr = hmep->hme_ouraddr.ether_addr_octet;
1508         macp->m_callbacks = &hme_m_callbacks;
1509         macp->m_min_sdu = 0;
1510         macp->m_max_sdu = ETHERMTU;
1511         macp->m_margin = VLAN_TAGSZ;
1512         macp->m_priv_props = hme_priv_prop;
1513         if (mac_register(macp, &hmep->hme_mh) != 0) {
1514                 mac_free(macp);
1515                 goto error_intr;
1516         }
1517 
1518         mac_free(macp);
1519 
1520         ddi_report_dev(dip);
1521         return (DDI_SUCCESS);
1522 
1523         /*
1524          * Failure Exit
1525          */
1526 
1527 error_intr:
1528         if (hmep->hme_cookie)
1529                 ddi_remove_intr(dip, 0, (ddi_iblock_cookie_t)0);
1530 
1531         if (hmep->hme_mii)
1532                 mii_free(hmep->hme_mii);
1533 
1534 error_mutex:
1535         mutex_destroy(&hmep->hme_xmitlock);
1536         mutex_destroy(&hmep->hme_intrlock);
1537 
1538 error_unmap:
1539         if (hmep->hme_globregh)
1540                 ddi_regs_map_free(&hmep->hme_globregh);
1541         if (hmep->hme_cheerio_mode == 0) {
1542                 if (hmep->hme_etxregh)
1543                         ddi_regs_map_free(&hmep->hme_etxregh);
1544                 if (hmep->hme_erxregh)
1545                         ddi_regs_map_free(&hmep->hme_erxregh);
1546                 if (hmep->hme_bmacregh)
1547                         ddi_regs_map_free(&hmep->hme_bmacregh);
1548                 if (hmep->hme_mifregh)
1549                         ddi_regs_map_free(&hmep->hme_mifregh);
1550         } else {
1551                 if (hmep->pci_config_handle)
1552                         (void) pci_config_teardown(&hmep->pci_config_handle);
1553                 hmep->hme_etxregh = hmep->hme_erxregh = hmep->hme_bmacregh =
1554                     hmep->hme_mifregh = hmep->hme_globregh = NULL;
1555         }
1556 
1557 error_state:
1558         hmefreethings(hmep);
1559         hmefreebufs(hmep);
1560 
1561         if (hmep) {
1562                 kmem_free((caddr_t)hmep, sizeof (*hmep));
1563                 ddi_set_driver_private(dip, NULL);
1564         }
1565 
1566         return (DDI_FAILURE);
1567 }
1568 
1569 int
1570 hmedetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1571 {
1572         struct hme *hmep;
1573 
1574         if ((hmep = ddi_get_driver_private(dip)) == NULL)
1575                 return (DDI_FAILURE);
1576 
1577         switch (cmd) {
1578         case DDI_DETACH:
1579                 break;
1580 
1581         case DDI_SUSPEND:
1582                 mii_suspend(hmep->hme_mii);
1583                 hmep->hme_flags |= HMESUSPENDED;
1584                 hmeuninit(hmep);
1585                 return (DDI_SUCCESS);
1586 
1587         default:
1588                 return (DDI_FAILURE);
1589         }
1590 
1591 
1592         if (mac_unregister(hmep->hme_mh) != 0) {
1593                 return (DDI_FAILURE);
1594         }
1595 
1596         /*
1597          * Make driver quiescent, we don't want to prevent the
1598          * detach on failure.  Note that this should be redundant,
1599          * since mac_stop should already have called hmeuninit().
1600          */
1601         if (!(hmep->hme_flags & HMESUSPENDED)) {
1602                 (void) hmestop(hmep);
1603         }
1604 
1605         if (hmep->hme_mii)
1606                 mii_free(hmep->hme_mii);
1607 
1608         /*
1609          * Remove instance of the intr
1610          */
1611         ddi_remove_intr(dip, 0, (ddi_iblock_cookie_t)0);
1612 
1613         /*
1614          * Unregister kstats.
1615          */
1616         if (hmep->hme_ksp != NULL)
1617                 kstat_delete(hmep->hme_ksp);
1618         if (hmep->hme_intrstats != NULL)
1619                 kstat_delete(hmep->hme_intrstats);
1620 
1621         hmep->hme_ksp = NULL;
1622         hmep->hme_intrstats = NULL;
1623 
1624         /*
1625          * Destroy all mutexes and data structures allocated during
1626          * attach time.
1627          *
1628          * Note: at this time we should be the only thread accessing
1629          * the structures for this instance.
1630          */
1631 
1632         if (hmep->hme_globregh)
1633                 ddi_regs_map_free(&hmep->hme_globregh);
1634         if (hmep->hme_cheerio_mode == 0) {
1635                 if (hmep->hme_etxregh)
1636                         ddi_regs_map_free(&hmep->hme_etxregh);
1637                 if (hmep->hme_erxregh)
1638                         ddi_regs_map_free(&hmep->hme_erxregh);
1639                 if (hmep->hme_bmacregh)
1640                         ddi_regs_map_free(&hmep->hme_bmacregh);
1641                 if (hmep->hme_mifregh)
1642                         ddi_regs_map_free(&hmep->hme_mifregh);
1643         } else {
1644                 if (hmep->pci_config_handle)
1645                         (void) pci_config_teardown(&hmep->pci_config_handle);
1646                 hmep->hme_etxregh = hmep->hme_erxregh = hmep->hme_bmacregh =
1647                     hmep->hme_mifregh = hmep->hme_globregh = NULL;
1648         }
1649 
1650         mutex_destroy(&hmep->hme_xmitlock);
1651         mutex_destroy(&hmep->hme_intrlock);
1652 
1653         hmefreethings(hmep);
1654         hmefreebufs(hmep);
1655 
1656         ddi_set_driver_private(dip, NULL);
1657         kmem_free(hmep, sizeof (struct hme));
1658 
1659         return (DDI_SUCCESS);
1660 }
1661 
1662 int
1663 hmequiesce(dev_info_t *dip)
1664 {
1665         struct hme *hmep;
1666 
1667         if ((hmep = ddi_get_driver_private(dip)) == NULL)
1668                 return (DDI_FAILURE);
1669 
1670         (void) hmestop(hmep);
1671         return (DDI_SUCCESS);
1672 }
1673 
1674 static boolean_t
1675 hmeinit_xfer_params(struct hme *hmep)
1676 {
1677         int hme_ipg1_conf, hme_ipg2_conf;
1678         int hme_ipg0_conf, hme_lance_mode_conf;
1679         int prop_len = sizeof (int);
1680         dev_info_t *dip;
1681 
1682         dip = hmep->dip;
1683 
1684         /*
1685          * Set up the start-up values for user-configurable parameters
1686          * Get the values from the global variables first.
1687          * Use the MASK to limit the value to allowed maximum.
1688          */
1689         hmep->hme_ipg1 = hme_ipg1 & HME_MASK_8BIT;
1690         hmep->hme_ipg2 = hme_ipg2 & HME_MASK_8BIT;
1691         hmep->hme_ipg0 = hme_ipg0 & HME_MASK_5BIT;
1692 
1693         /*
1694          * Get the parameter values configured in .conf file.
1695          */
1696         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg1",
1697             (caddr_t)&hme_ipg1_conf, &prop_len) == DDI_PROP_SUCCESS) {
1698                 hmep->hme_ipg1 = hme_ipg1_conf & HME_MASK_8BIT;
1699         }
1700 
1701         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg2",
1702             (caddr_t)&hme_ipg2_conf, &prop_len) == DDI_PROP_SUCCESS) {
1703                 hmep->hme_ipg2 = hme_ipg2_conf & HME_MASK_8BIT;
1704         }
1705 
1706         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg0",
1707             (caddr_t)&hme_ipg0_conf, &prop_len) == DDI_PROP_SUCCESS) {
1708                 hmep->hme_ipg0 = hme_ipg0_conf & HME_MASK_5BIT;
1709         }
1710 
1711         if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "lance_mode",
1712             (caddr_t)&hme_lance_mode_conf, &prop_len) == DDI_PROP_SUCCESS) {
1713                 hmep->hme_lance_mode = hme_lance_mode_conf & HME_MASK_1BIT;
1714         }
1715 
1716         return (B_TRUE);
1717 }
1718 
1719 /*
1720  * Return 0 upon success, 1 on failure.
1721  */
1722 static uint_t
1723 hmestop(struct hme *hmep)
1724 {
1725         /*
1726          * Disable the Tx dma engine.
1727          */
1728         PUT_ETXREG(config, (GET_ETXREG(config) & ~HMET_CONFIG_TXDMA_EN));
1729         HMEDELAY(((GET_ETXREG(state_mach) & 0x1f) == 0x1), HMEMAXRSTDELAY);
1730 
1731         /*
1732          * Disable the Rx dma engine.
1733          */
1734         PUT_ERXREG(config, (GET_ERXREG(config) & ~HMER_CONFIG_RXDMA_EN));
1735         HMEDELAY(((GET_ERXREG(state_mach) & 0x3f) == 0), HMEMAXRSTDELAY);
1736 
1737         /*
1738          * By this time all things should be quiet, so hit the
1739          * chip with a reset.
1740          */
1741         PUT_GLOBREG(reset, HMEG_RESET_GLOBAL);
1742 
1743         HMEDELAY((GET_GLOBREG(reset) == 0), HMEMAXRSTDELAY);
1744         if (GET_GLOBREG(reset)) {
1745                 return (1);
1746         }
1747 
1748         CHECK_GLOBREG();
1749         return (0);
1750 }
1751 
1752 static int
1753 hmestat_kstat_update(kstat_t *ksp, int rw)
1754 {
1755         struct hme *hmep;
1756         struct hmekstat *hkp;
1757 
1758         hmep = (struct hme *)ksp->ks_private;
1759         hkp = (struct hmekstat *)ksp->ks_data;
1760 
1761         if (rw != KSTAT_READ)
1762                 return (EACCES);
1763 
1764         /*
1765          * Update all the stats by reading all the counter registers.
1766          * Counter register stats are not updated till they overflow
1767          * and interrupt.
1768          */
1769 
1770         mutex_enter(&hmep->hme_xmitlock);
1771         if (hmep->hme_flags & HMERUNNING) {
1772                 hmereclaim(hmep);
1773                 hmesavecntrs(hmep);
1774         }
1775         mutex_exit(&hmep->hme_xmitlock);
1776 
1777         hkp->hk_cvc.value.ul         = hmep->hme_cvc;
1778         hkp->hk_lenerr.value.ul              = hmep->hme_lenerr;
1779         hkp->hk_buff.value.ul                = hmep->hme_buff;
1780         hkp->hk_missed.value.ul              = hmep->hme_missed;
1781         hkp->hk_allocbfail.value.ul  = hmep->hme_allocbfail;
1782         hkp->hk_babl.value.ul                = hmep->hme_babl;
1783         hkp->hk_tmder.value.ul               = hmep->hme_tmder;
1784         hkp->hk_txlaterr.value.ul    = hmep->hme_txlaterr;
1785         hkp->hk_rxlaterr.value.ul    = hmep->hme_rxlaterr;
1786         hkp->hk_slvparerr.value.ul   = hmep->hme_slvparerr;
1787         hkp->hk_txparerr.value.ul    = hmep->hme_txparerr;
1788         hkp->hk_rxparerr.value.ul    = hmep->hme_rxparerr;
1789         hkp->hk_slverrack.value.ul   = hmep->hme_slverrack;
1790         hkp->hk_txerrack.value.ul    = hmep->hme_txerrack;
1791         hkp->hk_rxerrack.value.ul    = hmep->hme_rxerrack;
1792         hkp->hk_txtagerr.value.ul    = hmep->hme_txtagerr;
1793         hkp->hk_rxtagerr.value.ul    = hmep->hme_rxtagerr;
1794         hkp->hk_eoperr.value.ul              = hmep->hme_eoperr;
1795         hkp->hk_notmds.value.ul              = hmep->hme_notmds;
1796         hkp->hk_notbufs.value.ul     = hmep->hme_notbufs;
1797         hkp->hk_norbufs.value.ul     = hmep->hme_norbufs;
1798 
1799         /*
1800          * Debug kstats
1801          */
1802         hkp->hk_inits.value.ul               = hmep->inits;
1803         hkp->hk_phyfail.value.ul     = hmep->phyfail;
1804 
1805         /*
1806          * xcvr kstats
1807          */
1808         hkp->hk_asic_rev.value.ul    = hmep->asic_rev;
1809 
1810         return (0);
1811 }
1812 
1813 static void
1814 hmestatinit(struct hme *hmep)
1815 {
1816         struct  kstat   *ksp;
1817         struct  hmekstat        *hkp;
1818         const char *driver;
1819         int     instance;
1820         char    buf[16];
1821 
1822         instance = hmep->instance;
1823         driver = ddi_driver_name(hmep->dip);
1824 
1825         if ((ksp = kstat_create(driver, instance,
1826             "driver_info", "net", KSTAT_TYPE_NAMED,
1827             sizeof (struct hmekstat) / sizeof (kstat_named_t), 0)) == NULL) {
1828                 HME_FAULT_MSG1(hmep, SEVERITY_UNKNOWN, INIT_MSG,
1829                     "kstat_create failed");
1830                 return;
1831         }
1832 
1833         (void) snprintf(buf, sizeof (buf), "%sc%d", driver, instance);
1834         hmep->hme_intrstats = kstat_create(driver, instance, buf, "controller",
1835             KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT);
1836         if (hmep->hme_intrstats)
1837                 kstat_install(hmep->hme_intrstats);
1838 
1839         hmep->hme_ksp = ksp;
1840         hkp = (struct hmekstat *)ksp->ks_data;
1841         kstat_named_init(&hkp->hk_cvc,                   "code_violations",
1842             KSTAT_DATA_ULONG);
1843         kstat_named_init(&hkp->hk_lenerr,                "len_errors",
1844             KSTAT_DATA_ULONG);
1845         kstat_named_init(&hkp->hk_buff,                  "buff",
1846             KSTAT_DATA_ULONG);
1847         kstat_named_init(&hkp->hk_missed,                "missed",
1848             KSTAT_DATA_ULONG);
1849         kstat_named_init(&hkp->hk_nocanput,              "nocanput",
1850             KSTAT_DATA_ULONG);
1851         kstat_named_init(&hkp->hk_allocbfail,            "allocbfail",
1852             KSTAT_DATA_ULONG);
1853         kstat_named_init(&hkp->hk_babl,                  "babble",
1854             KSTAT_DATA_ULONG);
1855         kstat_named_init(&hkp->hk_tmder,         "tmd_error",
1856             KSTAT_DATA_ULONG);
1857         kstat_named_init(&hkp->hk_txlaterr,              "tx_late_error",
1858             KSTAT_DATA_ULONG);
1859         kstat_named_init(&hkp->hk_rxlaterr,              "rx_late_error",
1860             KSTAT_DATA_ULONG);
1861         kstat_named_init(&hkp->hk_slvparerr,             "slv_parity_error",
1862             KSTAT_DATA_ULONG);
1863         kstat_named_init(&hkp->hk_txparerr,              "tx_parity_error",
1864             KSTAT_DATA_ULONG);
1865         kstat_named_init(&hkp->hk_rxparerr,              "rx_parity_error",
1866             KSTAT_DATA_ULONG);
1867         kstat_named_init(&hkp->hk_slverrack,             "slv_error_ack",
1868             KSTAT_DATA_ULONG);
1869         kstat_named_init(&hkp->hk_txerrack,              "tx_error_ack",
1870             KSTAT_DATA_ULONG);
1871         kstat_named_init(&hkp->hk_rxerrack,              "rx_error_ack",
1872             KSTAT_DATA_ULONG);
1873         kstat_named_init(&hkp->hk_txtagerr,              "tx_tag_error",
1874             KSTAT_DATA_ULONG);
1875         kstat_named_init(&hkp->hk_rxtagerr,              "rx_tag_error",
1876             KSTAT_DATA_ULONG);
1877         kstat_named_init(&hkp->hk_eoperr,                "eop_error",
1878             KSTAT_DATA_ULONG);
1879         kstat_named_init(&hkp->hk_notmds,                "no_tmds",
1880             KSTAT_DATA_ULONG);
1881         kstat_named_init(&hkp->hk_notbufs,               "no_tbufs",
1882             KSTAT_DATA_ULONG);
1883         kstat_named_init(&hkp->hk_norbufs,               "no_rbufs",
1884             KSTAT_DATA_ULONG);
1885 
1886         /*
1887          * Debugging kstats
1888          */
1889         kstat_named_init(&hkp->hk_inits,         "inits",
1890             KSTAT_DATA_ULONG);
1891         kstat_named_init(&hkp->hk_phyfail,               "phy_failures",
1892             KSTAT_DATA_ULONG);
1893 
1894         /*
1895          * xcvr kstats
1896          */
1897         kstat_named_init(&hkp->hk_asic_rev,              "asic_rev",
1898             KSTAT_DATA_ULONG);
1899 
1900         ksp->ks_update = hmestat_kstat_update;
1901         ksp->ks_private = (void *) hmep;
1902         kstat_install(ksp);
1903 }
1904 
1905 int
1906 hme_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
1907     void *val)
1908 {
1909         struct hme *hmep = arg;
1910         int value;
1911         int rv;
1912 
1913         rv = mii_m_getprop(hmep->hme_mii, name, num, sz, val);
1914         if (rv != ENOTSUP)
1915                 return (rv);
1916 
1917         switch (num) {
1918         case MAC_PROP_PRIVATE:
1919                 break;
1920         default:
1921                 return (ENOTSUP);
1922         }
1923 
1924         if (strcmp(name, "_ipg0") == 0) {
1925                 value = hmep->hme_ipg0;
1926         } else if (strcmp(name, "_ipg1") == 0) {
1927                 value = hmep->hme_ipg1;
1928         } else if (strcmp(name, "_ipg2") == 0) {
1929                 value = hmep->hme_ipg2;
1930         } else if (strcmp(name, "_lance_mode") == 0) {
1931                 value = hmep->hme_lance_mode;
1932         } else {
1933                 return (ENOTSUP);
1934         }
1935         (void) snprintf(val, sz, "%d", value);
1936         return (0);
1937 }
1938 
1939 static void
1940 hme_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
1941     mac_prop_info_handle_t mph)
1942 {
1943         struct hme *hmep = arg;
1944 
1945         mii_m_propinfo(hmep->hme_mii, name, num, mph);
1946 
1947         switch (num) {
1948         case MAC_PROP_PRIVATE: {
1949                 char valstr[64];
1950                 int default_val;
1951 
1952                 if (strcmp(name, "_ipg0") == 0) {
1953                         default_val = hme_ipg0;
1954                 } else if (strcmp(name, "_ipg1") == 0) {
1955                         default_val = hme_ipg1;
1956                 } else if (strcmp(name, "_ipg2") == 0) {
1957                         default_val = hme_ipg2;
1958                 } if (strcmp(name, "_lance_mode") == 0) {
1959                         default_val = hme_lance_mode;
1960                 } else {
1961                         return;
1962                 }
1963 
1964                 (void) snprintf(valstr, sizeof (valstr), "%d", default_val);
1965                 mac_prop_info_set_default_str(mph, valstr);
1966                 break;
1967         }
1968         }
1969 }
1970 
1971 int
1972 hme_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
1973     const void *val)
1974 {
1975         struct hme *hmep = arg;
1976         int rv;
1977         long lval;
1978         boolean_t init = B_FALSE;
1979 
1980         rv = mii_m_setprop(hmep->hme_mii, name, num, sz, val);
1981         if (rv != ENOTSUP)
1982                 return (rv);
1983         rv = 0;
1984 
1985         switch (num) {
1986         case MAC_PROP_PRIVATE:
1987                 break;
1988         default:
1989                 return (ENOTSUP);
1990         }
1991 
1992         (void) ddi_strtol(val, NULL, 0, &lval);
1993 
1994         if (strcmp(name, "_ipg1") == 0) {
1995                 if ((lval >= 0) && (lval <= 255)) {
1996                         hmep->hme_ipg1 = lval & 0xff;
1997                         init = B_TRUE;
1998                 } else {
1999                         return (EINVAL);
2000                 }
2001 
2002         } else if (strcmp(name, "_ipg2") == 0) {
2003                 if ((lval >= 0) && (lval <= 255)) {
2004                         hmep->hme_ipg2 = lval & 0xff;
2005                         init = B_TRUE;
2006                 } else {
2007                         return (EINVAL);
2008                 }
2009 
2010         } else if (strcmp(name, "_ipg0") == 0) {
2011                 if ((lval >= 0) && (lval <= 31)) {
2012                         hmep->hme_ipg0 = lval & 0xff;
2013                         init = B_TRUE;
2014                 } else {
2015                         return (EINVAL);
2016                 }
2017         } else if (strcmp(name, "_lance_mode") == 0) {
2018                 if ((lval >= 0) && (lval <= 1)) {
2019                         hmep->hme_lance_mode = lval & 0xff;
2020                         init = B_TRUE;
2021                 } else {
2022                         return (EINVAL);
2023                 }
2024 
2025         } else {
2026                 rv = ENOTSUP;
2027         }
2028 
2029         if (init) {
2030                 (void) hmeinit(hmep);
2031         }
2032         return (rv);
2033 }
2034 
2035 
2036 /*ARGSUSED*/
2037 static boolean_t
2038 hme_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
2039 {
2040         switch (cap) {
2041         case MAC_CAPAB_HCKSUM:
2042                 *(uint32_t *)cap_data = HCKSUM_INET_PARTIAL;
2043                 return (B_TRUE);
2044         default:
2045                 return (B_FALSE);
2046         }
2047 }
2048 
2049 static int
2050 hme_m_promisc(void *arg, boolean_t on)
2051 {
2052         struct hme *hmep = arg;
2053 
2054         hmep->hme_promisc = on;
2055         (void) hmeinit(hmep);
2056         return (0);
2057 }
2058 
2059 static int
2060 hme_m_unicst(void *arg, const uint8_t *macaddr)
2061 {
2062         struct hme *hmep = arg;
2063 
2064         /*
2065          * Set new interface local address and re-init device.
2066          * This is destructive to any other streams attached
2067          * to this device.
2068          */
2069         mutex_enter(&hmep->hme_intrlock);
2070         bcopy(macaddr, &hmep->hme_ouraddr, ETHERADDRL);
2071         mutex_exit(&hmep->hme_intrlock);
2072         (void) hmeinit(hmep);
2073         return (0);
2074 }
2075 
2076 static int
2077 hme_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
2078 {
2079         struct hme      *hmep = arg;
2080         uint32_t        ladrf_bit;
2081         boolean_t       doinit = B_FALSE;
2082 
2083         /*
2084          * If this address's bit was not already set in the local address
2085          * filter, add it and re-initialize the Hardware.
2086          */
2087         ladrf_bit = hmeladrf_bit(macaddr);
2088 
2089         mutex_enter(&hmep->hme_intrlock);
2090         if (add) {
2091                 hmep->hme_ladrf_refcnt[ladrf_bit]++;
2092                 if (hmep->hme_ladrf_refcnt[ladrf_bit] == 1) {
2093                         hmep->hme_ladrf[ladrf_bit >> 4] |=
2094                             1 << (ladrf_bit & 0xf);
2095                         hmep->hme_multi++;
2096                         doinit = B_TRUE;
2097                 }
2098         } else {
2099                 hmep->hme_ladrf_refcnt[ladrf_bit]--;
2100                 if (hmep->hme_ladrf_refcnt[ladrf_bit] == 0) {
2101                         hmep->hme_ladrf[ladrf_bit >> 4] &=
2102                             ~(1 << (ladrf_bit & 0xf));
2103                         doinit = B_TRUE;
2104                 }
2105         }
2106         mutex_exit(&hmep->hme_intrlock);
2107 
2108         if (doinit) {
2109                 (void) hmeinit(hmep);
2110         }
2111 
2112         return (0);
2113 }
2114 
2115 static int
2116 hme_m_start(void *arg)
2117 {
2118         struct hme *hmep = arg;
2119 
2120         if (hmeinit(hmep) != 0) {
2121                 /* initialization failed -- really want DL_INITFAILED */
2122                 return (EIO);
2123         } else {
2124                 hmep->hme_started = B_TRUE;
2125                 mii_start(hmep->hme_mii);
2126                 return (0);
2127         }
2128 }
2129 
2130 static void
2131 hme_m_stop(void *arg)
2132 {
2133         struct hme *hmep = arg;
2134 
2135         mii_stop(hmep->hme_mii);
2136         hmep->hme_started = B_FALSE;
2137         hmeuninit(hmep);
2138 }
2139 
2140 static int
2141 hme_m_stat(void *arg, uint_t stat, uint64_t *val)
2142 {
2143         struct hme      *hmep = arg;
2144 
2145         mutex_enter(&hmep->hme_xmitlock);
2146         if (hmep->hme_flags & HMERUNNING) {
2147                 hmereclaim(hmep);
2148                 hmesavecntrs(hmep);
2149         }
2150         mutex_exit(&hmep->hme_xmitlock);
2151 
2152 
2153         if (mii_m_getstat(hmep->hme_mii, stat, val) == 0) {
2154                 return (0);
2155         }
2156         switch (stat) {
2157         case MAC_STAT_IPACKETS:
2158                 *val = hmep->hme_ipackets;
2159                 break;
2160         case MAC_STAT_RBYTES:
2161                 *val = hmep->hme_rbytes;
2162                 break;
2163         case MAC_STAT_IERRORS:
2164                 *val = hmep->hme_ierrors;
2165                 break;
2166         case MAC_STAT_OPACKETS:
2167                 *val = hmep->hme_opackets;
2168                 break;
2169         case MAC_STAT_OBYTES:
2170                 *val = hmep->hme_obytes;
2171                 break;
2172         case MAC_STAT_OERRORS:
2173                 *val = hmep->hme_oerrors;
2174                 break;
2175         case MAC_STAT_MULTIRCV:
2176                 *val = hmep->hme_multircv;
2177                 break;
2178         case MAC_STAT_MULTIXMT:
2179                 *val = hmep->hme_multixmt;
2180                 break;
2181         case MAC_STAT_BRDCSTRCV:
2182                 *val = hmep->hme_brdcstrcv;
2183                 break;
2184         case MAC_STAT_BRDCSTXMT:
2185                 *val = hmep->hme_brdcstxmt;
2186                 break;
2187         case MAC_STAT_UNDERFLOWS:
2188                 *val = hmep->hme_uflo;
2189                 break;
2190         case MAC_STAT_OVERFLOWS:
2191                 *val = hmep->hme_oflo;
2192                 break;
2193         case MAC_STAT_COLLISIONS:
2194                 *val = hmep->hme_coll;
2195                 break;
2196         case MAC_STAT_NORCVBUF:
2197                 *val = hmep->hme_norcvbuf;
2198                 break;
2199         case MAC_STAT_NOXMTBUF:
2200                 *val = hmep->hme_noxmtbuf;
2201                 break;
2202         case ETHER_STAT_LINK_DUPLEX:
2203                 *val = hmep->hme_duplex;
2204                 break;
2205         case ETHER_STAT_ALIGN_ERRORS:
2206                 *val = hmep->hme_align_errors;
2207                 break;
2208         case ETHER_STAT_FCS_ERRORS:
2209                 *val = hmep->hme_fcs_errors;
2210                 break;
2211         case ETHER_STAT_EX_COLLISIONS:
2212                 *val = hmep->hme_excol;
2213                 break;
2214         case ETHER_STAT_DEFER_XMTS:
2215                 *val = hmep->hme_defer_xmts;
2216                 break;
2217         case ETHER_STAT_SQE_ERRORS:
2218                 *val = hmep->hme_sqe_errors;
2219                 break;
2220         case ETHER_STAT_FIRST_COLLISIONS:
2221                 *val = hmep->hme_fstcol;
2222                 break;
2223         case ETHER_STAT_TX_LATE_COLLISIONS:
2224                 *val = hmep->hme_tlcol;
2225                 break;
2226         case ETHER_STAT_TOOLONG_ERRORS:
2227                 *val = hmep->hme_toolong_errors;
2228                 break;
2229         case ETHER_STAT_TOOSHORT_ERRORS:
2230                 *val = hmep->hme_runt;
2231                 break;
2232         case ETHER_STAT_CARRIER_ERRORS:
2233                 *val = hmep->hme_carrier_errors;
2234                 break;
2235         default:
2236                 return (EINVAL);
2237         }
2238         return (0);
2239 }
2240 
2241 static mblk_t *
2242 hme_m_tx(void *arg, mblk_t *mp)
2243 {
2244         struct hme *hmep = arg;
2245         mblk_t *next;
2246 
2247         while (mp != NULL) {
2248                 next = mp->b_next;
2249                 mp->b_next = NULL;
2250                 if (!hmestart(hmep, mp)) {
2251                         mp->b_next = next;
2252                         break;
2253                 }
2254                 mp = next;
2255         }
2256         return (mp);
2257 }
2258 
2259 /*
2260  * Software IP checksum, for the edge cases that the
2261  * hardware can't handle.  See hmestart for more info.
2262  */
2263 static uint16_t
2264 hme_cksum(void *data, int len)
2265 {
2266         uint16_t        *words = data;
2267         int             i, nwords = len / 2;
2268         uint32_t        sum = 0;
2269 
2270         /* just add up the words */
2271         for (i = 0; i < nwords; i++) {
2272                 sum += *words++;
2273         }
2274 
2275         /* pick up residual byte ... assume even half-word allocations */
2276         if (len % 2) {
2277                 sum += (*words & htons(0xff00));
2278         }
2279 
2280         sum = (sum >> 16) + (sum & 0xffff);
2281         sum = (sum >> 16) + (sum & 0xffff);
2282 
2283         return (~(sum & 0xffff));
2284 }
2285 
2286 static boolean_t
2287 hmestart(struct hme *hmep, mblk_t *mp)
2288 {
2289         uint32_t        len;
2290         boolean_t       retval = B_TRUE;
2291         hmebuf_t        *tbuf;
2292         uint32_t        txptr;
2293 
2294         uint32_t        csflags = 0;
2295         uint32_t        flags;
2296         uint32_t        start_offset;
2297         uint32_t        stuff_offset;
2298 
2299         mac_hcksum_get(mp, &start_offset, &stuff_offset, NULL, NULL, &flags);
2300 
2301         if (flags & HCK_PARTIALCKSUM) {
2302                 if (get_ether_type(mp->b_rptr) == ETHERTYPE_VLAN) {
2303                         start_offset += sizeof (struct ether_header) + 4;
2304                         stuff_offset += sizeof (struct ether_header) + 4;
2305                 } else {
2306                         start_offset += sizeof (struct ether_header);
2307                         stuff_offset += sizeof (struct ether_header);
2308                 }
2309                 csflags = HMETMD_CSENABL |
2310                     (start_offset << HMETMD_CSSTART_SHIFT) |
2311                     (stuff_offset << HMETMD_CSSTUFF_SHIFT);
2312         }
2313 
2314         mutex_enter(&hmep->hme_xmitlock);
2315 
2316         if (hmep->hme_flags & HMESUSPENDED) {
2317                 hmep->hme_carrier_errors++;
2318                 hmep->hme_oerrors++;
2319                 goto bad;
2320         }
2321 
2322         if (hmep->hme_txindex != hmep->hme_txreclaim) {
2323                 hmereclaim(hmep);
2324         }
2325         if ((hmep->hme_txindex - HME_TMDMAX) == hmep->hme_txreclaim)
2326                 goto notmds;
2327         txptr = hmep->hme_txindex % HME_TMDMAX;
2328         tbuf = &hmep->hme_tbuf[txptr];
2329 
2330         /*
2331          * Note that for checksum offload, the hardware cannot
2332          * generate correct checksums if the packet is smaller than
2333          * 64-bytes.  In such a case, we bcopy the packet and use
2334          * a software checksum.
2335          */
2336 
2337         len = msgsize(mp);
2338         if (len < 64) {
2339                 /* zero fill the padding */
2340                 bzero(tbuf->kaddr, 64);
2341         }
2342         mcopymsg(mp, tbuf->kaddr);
2343 
2344         if ((csflags != 0) && ((len < 64) ||
2345             (start_offset > HMETMD_CSSTART_MAX) ||
2346             (stuff_offset > HMETMD_CSSTUFF_MAX))) {
2347                 uint16_t sum;
2348                 sum = hme_cksum(tbuf->kaddr + start_offset,
2349                     len - start_offset);
2350                 bcopy(&sum, tbuf->kaddr + stuff_offset, sizeof (sum));
2351                 csflags = 0;
2352         }
2353 
2354         if (ddi_dma_sync(tbuf->dmah, 0, len, DDI_DMA_SYNC_FORDEV) ==
2355             DDI_FAILURE) {
2356                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, DDI_MSG,
2357                     "ddi_dma_sync failed");
2358         }
2359 
2360         /*
2361          * update MIB II statistics
2362          */
2363         BUMP_OutNUcast(hmep, tbuf->kaddr);
2364 
2365         PUT_TMD(txptr, tbuf->paddr, len,
2366             HMETMD_OWN | HMETMD_SOP | HMETMD_EOP | csflags);
2367 
2368         HMESYNCTMD(txptr, DDI_DMA_SYNC_FORDEV);
2369         hmep->hme_txindex++;
2370 
2371         PUT_ETXREG(txpend, HMET_TXPEND_TDMD);
2372         CHECK_ETXREG();
2373 
2374         mutex_exit(&hmep->hme_xmitlock);
2375 
2376         hmep->hme_starts++;
2377         return (B_TRUE);
2378 
2379 bad:
2380         mutex_exit(&hmep->hme_xmitlock);
2381         freemsg(mp);
2382         return (B_TRUE);
2383 
2384 notmds:
2385         hmep->hme_notmds++;
2386         hmep->hme_wantw = B_TRUE;
2387         hmereclaim(hmep);
2388         retval = B_FALSE;
2389 done:
2390         mutex_exit(&hmep->hme_xmitlock);
2391 
2392         return (retval);
2393 }
2394 
2395 /*
2396  * Initialize channel.
2397  * Return 0 on success, nonzero on error.
2398  *
2399  * The recommended sequence for initialization is:
2400  * 1. Issue a Global Reset command to the Ethernet Channel.
2401  * 2. Poll the Global_Reset bits until the execution of the reset has been
2402  *    completed.
2403  * 2(a). Use the MIF Frame/Output register to reset the transceiver.
2404  *       Poll Register 0 to till the Resetbit is 0.
2405  * 2(b). Use the MIF Frame/Output register to set the PHY in in Normal-Op,
2406  *       100Mbps and Non-Isolated mode. The main point here is to bring the
2407  *       PHY out of Isolate mode so that it can generate the rx_clk and tx_clk
2408  *       to the MII interface so that the Bigmac core can correctly reset
2409  *       upon a software reset.
2410  * 2(c).  Issue another Global Reset command to the Ethernet Channel and poll
2411  *        the Global_Reset bits till completion.
2412  * 3. Set up all the data structures in the host memory.
2413  * 4. Program the TX_MAC registers/counters (excluding the TX_MAC Configuration
2414  *    Register).
2415  * 5. Program the RX_MAC registers/counters (excluding the RX_MAC Configuration
2416  *    Register).
2417  * 6. Program the Transmit Descriptor Ring Base Address in the ETX.
2418  * 7. Program the Receive Descriptor Ring Base Address in the ERX.
2419  * 8. Program the Global Configuration and the Global Interrupt Mask Registers.
2420  * 9. Program the ETX Configuration register (enable the Transmit DMA channel).
2421  * 10. Program the ERX Configuration register (enable the Receive DMA channel).
2422  * 11. Program the XIF Configuration Register (enable the XIF).
2423  * 12. Program the RX_MAC Configuration Register (Enable the RX_MAC).
2424  * 13. Program the TX_MAC Configuration Register (Enable the TX_MAC).
2425  */
2426 
2427 
2428 #ifdef FEPS_URUN_BUG
2429 static int hme_palen = 32;
2430 #endif
2431 
2432 static int
2433 hmeinit(struct hme *hmep)
2434 {
2435         uint32_t                i;
2436         int                     ret;
2437         boolean_t               fdx;
2438         int                     phyad;
2439 
2440         /*
2441          * Lock sequence:
2442          *      hme_intrlock, hme_xmitlock.
2443          */
2444         mutex_enter(&hmep->hme_intrlock);
2445 
2446         /*
2447          * Don't touch the hardware if we are suspended.  But don't
2448          * fail either.  Some time later we may be resumed, and then
2449          * we'll be back here to program the device using the settings
2450          * in the soft state.
2451          */
2452         if (hmep->hme_flags & HMESUSPENDED) {
2453                 mutex_exit(&hmep->hme_intrlock);
2454                 return (0);
2455         }
2456 
2457         /*
2458          * This should prevent us from clearing any interrupts that
2459          * may occur by temporarily stopping interrupts from occurring
2460          * for a short time.  We need to update the interrupt mask
2461          * later in this function.
2462          */
2463         PUT_GLOBREG(intmask, ~HMEG_MASK_MIF_INTR);
2464 
2465 
2466         /*
2467          * Rearranged the mutex acquisition order to solve the deadlock
2468          * situation as described in bug ID 4065896.
2469          */
2470 
2471         mutex_enter(&hmep->hme_xmitlock);
2472 
2473         hmep->hme_flags = 0;
2474         hmep->hme_wantw = B_FALSE;
2475 
2476         if (hmep->inits)
2477                 hmesavecntrs(hmep);
2478 
2479         /*
2480          * Perform Global reset of the Sbus/FEPS ENET channel.
2481          */
2482         (void) hmestop(hmep);
2483 
2484         /*
2485          * Clear all descriptors.
2486          */
2487         bzero(hmep->hme_rmdp, HME_RMDMAX * sizeof (struct hme_rmd));
2488         bzero(hmep->hme_tmdp, HME_TMDMAX * sizeof (struct hme_tmd));
2489 
2490         /*
2491          * Hang out receive buffers.
2492          */
2493         for (i = 0; i < HME_RMDMAX; i++) {
2494                 PUT_RMD(i, hmep->hme_rbuf[i].paddr);
2495         }
2496 
2497         /*
2498          * DMA sync descriptors.
2499          */
2500         (void) ddi_dma_sync(hmep->hme_rmd_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
2501         (void) ddi_dma_sync(hmep->hme_tmd_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
2502 
2503         /*
2504          * Reset RMD and TMD 'walking' pointers.
2505          */
2506         hmep->hme_rxindex = 0;
2507         hmep->hme_txindex = hmep->hme_txreclaim = 0;
2508 
2509         /*
2510          * This is the right place to initialize MIF !!!
2511          */
2512 
2513         PUT_MIFREG(mif_imask, HME_MIF_INTMASK); /* mask all interrupts */
2514 
2515         if (!hmep->hme_frame_enable)
2516                 PUT_MIFREG(mif_cfg, GET_MIFREG(mif_cfg) | HME_MIF_CFGBB);
2517         else
2518                 PUT_MIFREG(mif_cfg, GET_MIFREG(mif_cfg) & ~HME_MIF_CFGBB);
2519                                                 /* enable frame mode */
2520 
2521         /*
2522          * Depending on the transceiver detected, select the source
2523          * of the clocks for the MAC. Without the clocks, TX_MAC does
2524          * not reset. When the Global Reset is issued to the Sbus/FEPS
2525          * ASIC, it selects Internal by default.
2526          */
2527 
2528         switch ((phyad = mii_get_addr(hmep->hme_mii))) {
2529         case -1:
2530                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, XCVR_MSG, no_xcvr_msg);
2531                 goto init_fail; /* abort initialization */
2532 
2533         case HME_INTERNAL_PHYAD:
2534                 PUT_MACREG(xifc, 0);
2535                 break;
2536         case HME_EXTERNAL_PHYAD:
2537                 /* Isolate the Int. xcvr */
2538                 PUT_MACREG(xifc, BMAC_XIFC_MIIBUFDIS);
2539                 break;
2540         }
2541 
2542         hmep->inits++;
2543 
2544         /*
2545          * Initialize BigMAC registers.
2546          * First set the tx enable bit in tx config reg to 0 and poll on
2547          * it till it turns to 0. Same for rx config, hash and address
2548          * filter reg.
2549          * Here is the sequence per the spec.
2550          * MADD2 - MAC Address 2
2551          * MADD1 - MAC Address 1
2552          * MADD0 - MAC Address 0
2553          * HASH3, HASH2, HASH1, HASH0 for group address
2554          * AFR2, AFR1, AFR0 and AFMR for address filter mask
2555          * Program RXMIN and RXMAX for packet length if not 802.3
2556          * RXCFG - Rx config for not stripping CRC
2557          * XXX Anything else to hme configured in RXCFG
2558          * IPG1, IPG2, ALIMIT, SLOT, PALEN, PAPAT, TXSFD, JAM, TXMAX, TXMIN
2559          * if not 802.3 compliant
2560          * XIF register for speed selection
2561          * MASK  - Interrupt mask
2562          * Set bit 0 of TXCFG
2563          * Set bit 0 of RXCFG
2564          */
2565 
2566         /*
2567          * Initialize the TX_MAC registers
2568          * Initialization of jamsize to work around rx crc bug
2569          */
2570         PUT_MACREG(jam, jamsize);
2571 
2572 #ifdef  FEPS_URUN_BUG
2573         if (hme_urun_fix)
2574                 PUT_MACREG(palen, hme_palen);
2575 #endif
2576 
2577         PUT_MACREG(ipg1, hmep->hme_ipg1);
2578         PUT_MACREG(ipg2, hmep->hme_ipg2);
2579 
2580         PUT_MACREG(rseed,
2581             ((hmep->hme_ouraddr.ether_addr_octet[0] << 8) & 0x3) |
2582             hmep->hme_ouraddr.ether_addr_octet[1]);
2583 
2584         /* Initialize the RX_MAC registers */
2585 
2586         /*
2587          * Program BigMAC with local individual ethernet address.
2588          */
2589         PUT_MACREG(madd2, (hmep->hme_ouraddr.ether_addr_octet[4] << 8) |
2590             hmep->hme_ouraddr.ether_addr_octet[5]);
2591         PUT_MACREG(madd1, (hmep->hme_ouraddr.ether_addr_octet[2] << 8) |
2592             hmep->hme_ouraddr.ether_addr_octet[3]);
2593         PUT_MACREG(madd0, (hmep->hme_ouraddr.ether_addr_octet[0] << 8) |
2594             hmep->hme_ouraddr.ether_addr_octet[1]);
2595 
2596         /*
2597          * Set up multicast address filter by passing all multicast
2598          * addresses through a crc generator, and then using the
2599          * low order 6 bits as a index into the 64 bit logical
2600          * address filter. The high order three bits select the word,
2601          * while the rest of the bits select the bit within the word.
2602          */
2603         PUT_MACREG(hash0, hmep->hme_ladrf[0]);
2604         PUT_MACREG(hash1, hmep->hme_ladrf[1]);
2605         PUT_MACREG(hash2, hmep->hme_ladrf[2]);
2606         PUT_MACREG(hash3, hmep->hme_ladrf[3]);
2607 
2608         /*
2609          * Configure parameters to support VLAN.  (VLAN encapsulation adds
2610          * four bytes.)
2611          */
2612         PUT_MACREG(txmax, ETHERMAX + ETHERFCSL + 4);
2613         PUT_MACREG(rxmax, ETHERMAX + ETHERFCSL + 4);
2614 
2615         /*
2616          * Initialize HME Global registers, ETX registers and ERX registers.
2617          */
2618 
2619         PUT_ETXREG(txring, hmep->hme_tmd_paddr);
2620         PUT_ERXREG(rxring, hmep->hme_rmd_paddr);
2621 
2622         /*
2623          * ERX registers can be written only if they have even no. of bits set.
2624          * So, if the value written is not read back, set the lsb and write
2625          * again.
2626          * static       int     hme_erx_fix = 1;   : Use the fix for erx bug
2627          */
2628         {
2629                 uint32_t temp;
2630                 temp  = hmep->hme_rmd_paddr;
2631 
2632                 if (GET_ERXREG(rxring) != temp)
2633                         PUT_ERXREG(rxring, (temp | 4));
2634         }
2635 
2636         PUT_GLOBREG(config, (hmep->hme_config |
2637             (hmep->hme_64bit_xfer << HMEG_CONFIG_64BIT_SHIFT)));
2638 
2639         /*
2640          * Significant performance improvements can be achieved by
2641          * disabling transmit interrupt. Thus TMD's are reclaimed only
2642          * when we run out of them in hmestart().
2643          */
2644         PUT_GLOBREG(intmask,
2645             HMEG_MASK_INTR | HMEG_MASK_TINT | HMEG_MASK_TX_ALL);
2646 
2647         PUT_ETXREG(txring_size, ((HME_TMDMAX -1)>> HMET_RINGSZ_SHIFT));
2648         PUT_ETXREG(config, (GET_ETXREG(config) | HMET_CONFIG_TXDMA_EN
2649             | HMET_CONFIG_TXFIFOTH));
2650         /* get the rxring size bits */
2651         switch (HME_RMDMAX) {
2652         case 32:
2653                 i = HMER_CONFIG_RXRINGSZ32;
2654                 break;
2655         case 64:
2656                 i = HMER_CONFIG_RXRINGSZ64;
2657                 break;
2658         case 128:
2659                 i = HMER_CONFIG_RXRINGSZ128;
2660                 break;
2661         case 256:
2662                 i = HMER_CONFIG_RXRINGSZ256;
2663                 break;
2664         default:
2665                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2666                     unk_rx_ringsz_msg);
2667                 goto init_fail;
2668         }
2669         i |= (HME_FSTBYTE_OFFSET << HMER_CONFIG_FBO_SHIFT)
2670             | HMER_CONFIG_RXDMA_EN;
2671 
2672         /* h/w checks start offset in half words */
2673         i |= ((sizeof (struct ether_header) / 2) << HMER_RX_CSSTART_SHIFT);
2674 
2675         PUT_ERXREG(config, i);
2676 
2677         /*
2678          * Bug related to the parity handling in ERX. When erxp-config is
2679          * read back.
2680          * Sbus/FEPS drives the parity bit. This value is used while
2681          * writing again.
2682          * This fixes the RECV problem in SS5.
2683          * static       int     hme_erx_fix = 1;   : Use the fix for erx bug
2684          */
2685         {
2686                 uint32_t temp;
2687                 temp = GET_ERXREG(config);
2688                 PUT_ERXREG(config, i);
2689 
2690                 if (GET_ERXREG(config) != i)
2691                         HME_FAULT_MSG4(hmep, SEVERITY_UNKNOWN, ERX_MSG,
2692                             "error:temp = %x erxp->config = %x, should be %x",
2693                             temp, GET_ERXREG(config), i);
2694         }
2695 
2696         /*
2697          * Set up the rxconfig, txconfig and seed register without enabling
2698          * them the former two at this time
2699          *
2700          * BigMAC strips the CRC bytes by default. Since this is
2701          * contrary to other pieces of hardware, this bit needs to
2702          * enabled to tell BigMAC not to strip the CRC bytes.
2703          * Do not filter this node's own packets.
2704          */
2705 
2706         if (hme_reject_own) {
2707                 PUT_MACREG(rxcfg,
2708                     ((hmep->hme_promisc ? BMAC_RXCFG_PROMIS : 0) |
2709                     BMAC_RXCFG_MYOWN | BMAC_RXCFG_HASH));
2710         } else {
2711                 PUT_MACREG(rxcfg,
2712                     ((hmep->hme_promisc ? BMAC_RXCFG_PROMIS : 0) |
2713                     BMAC_RXCFG_HASH));
2714         }
2715 
2716         drv_usecwait(10);       /* wait after setting Hash Enable bit */
2717 
2718         fdx = (mii_get_duplex(hmep->hme_mii) == LINK_DUPLEX_FULL);
2719 
2720         if (hme_ngu_enable)
2721                 PUT_MACREG(txcfg, (fdx ? BMAC_TXCFG_FDX : 0) |
2722                     BMAC_TXCFG_NGU);
2723         else
2724                 PUT_MACREG(txcfg, (fdx ? BMAC_TXCFG_FDX: 0));
2725 
2726         i = 0;
2727         if ((hmep->hme_lance_mode) && (hmep->hme_lance_mode_enable))
2728                 i = ((hmep->hme_ipg0 & HME_MASK_5BIT) << BMAC_XIFC_IPG0_SHIFT)
2729                     | BMAC_XIFC_LANCE_ENAB;
2730         if (phyad == HME_INTERNAL_PHYAD)
2731                 PUT_MACREG(xifc, i | (BMAC_XIFC_ENAB));
2732         else
2733                 PUT_MACREG(xifc, i | (BMAC_XIFC_ENAB | BMAC_XIFC_MIIBUFDIS));
2734 
2735         PUT_MACREG(rxcfg, GET_MACREG(rxcfg) | BMAC_RXCFG_ENAB);
2736         PUT_MACREG(txcfg, GET_MACREG(txcfg) | BMAC_TXCFG_ENAB);
2737 
2738         hmep->hme_flags |= (HMERUNNING | HMEINITIALIZED);
2739         /*
2740          * Update the interrupt mask : this will re-allow interrupts to occur
2741          */
2742         PUT_GLOBREG(intmask, HMEG_MASK_INTR);
2743         mac_tx_update(hmep->hme_mh);
2744 
2745 init_fail:
2746         /*
2747          * Release the locks in reverse order
2748          */
2749         mutex_exit(&hmep->hme_xmitlock);
2750         mutex_exit(&hmep->hme_intrlock);
2751 
2752         ret = !(hmep->hme_flags & HMERUNNING);
2753         if (ret) {
2754                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2755                     init_fail_gen_msg);
2756         }
2757 
2758         /*
2759          * Hardware checks.
2760          */
2761         CHECK_GLOBREG();
2762         CHECK_MIFREG();
2763         CHECK_MACREG();
2764         CHECK_ERXREG();
2765         CHECK_ETXREG();
2766 
2767 init_exit:
2768         return (ret);
2769 }
2770 
2771 /*
2772  * Calculate the dvma burstsize by setting up a dvma temporarily.  Return
2773  * 0 as burstsize upon failure as it signifies no burst size.
2774  * Requests for 64-bit transfer setup, if the platform supports it.
2775  * NOTE: Do not use ddi_dma_alloc_handle(9f) then ddi_dma_burstsize(9f),
2776  * sun4u Ultra-2 incorrectly returns a 32bit transfer.
2777  */
2778 static int
2779 hmeburstsizes(struct hme *hmep)
2780 {
2781         int burstsizes;
2782         ddi_dma_handle_t handle;
2783 
2784         if (ddi_dma_alloc_handle(hmep->dip, &hme_dma_attr,
2785             DDI_DMA_DONTWAIT, NULL, &handle)) {
2786                 return (0);
2787         }
2788 
2789         hmep->hme_burstsizes = burstsizes = ddi_dma_burstsizes(handle);
2790         ddi_dma_free_handle(&handle);
2791 
2792         /*
2793          * Use user-configurable parameter for enabling 64-bit transfers
2794          */
2795         burstsizes = (hmep->hme_burstsizes >> 16);
2796         if (burstsizes)
2797                 hmep->hme_64bit_xfer = hme_64bit_enable; /* user config value */
2798         else
2799                 burstsizes = hmep->hme_burstsizes;
2800 
2801         if (hmep->hme_cheerio_mode)
2802                 hmep->hme_64bit_xfer = 0; /* Disable for cheerio */
2803 
2804         if (burstsizes & 0x40)
2805                 hmep->hme_config = HMEG_CONFIG_BURST64;
2806         else if (burstsizes & 0x20)
2807                 hmep->hme_config = HMEG_CONFIG_BURST32;
2808         else
2809                 hmep->hme_config = HMEG_CONFIG_BURST16;
2810 
2811         return (DDI_SUCCESS);
2812 }
2813 
2814 static int
2815 hmeallocbuf(struct hme *hmep, hmebuf_t *buf, int dir)
2816 {
2817         ddi_dma_cookie_t        dmac;
2818         size_t                  len;
2819         unsigned                ccnt;
2820 
2821         if (ddi_dma_alloc_handle(hmep->dip, &hme_dma_attr,
2822             DDI_DMA_DONTWAIT, NULL, &buf->dmah) != DDI_SUCCESS) {
2823                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2824                     "cannot allocate buf dma handle - failed");
2825                 return (DDI_FAILURE);
2826         }
2827 
2828         if (ddi_dma_mem_alloc(buf->dmah, ROUNDUP(HMEBUFSIZE, 512),
2829             &hme_buf_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL,
2830             &buf->kaddr, &len, &buf->acch) != DDI_SUCCESS) {
2831                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2832                     "cannot allocate buf memory - failed");
2833                 return (DDI_FAILURE);
2834         }
2835 
2836         if (ddi_dma_addr_bind_handle(buf->dmah, NULL, buf->kaddr,
2837             len, dir | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
2838             &dmac, &ccnt) != DDI_DMA_MAPPED) {
2839                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2840                     "cannot map buf for dma - failed");
2841                 return (DDI_FAILURE);
2842         }
2843         buf->paddr = dmac.dmac_address;
2844 
2845         /* apparently they don't handle multiple cookies */
2846         if (ccnt > 1) {
2847                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2848                     "too many buf dma cookies");
2849                 return (DDI_FAILURE);
2850         }
2851         return (DDI_SUCCESS);
2852 }
2853 
2854 static int
2855 hmeallocbufs(struct hme *hmep)
2856 {
2857         hmep->hme_tbuf = kmem_zalloc(HME_TMDMAX * sizeof (hmebuf_t), KM_SLEEP);
2858         hmep->hme_rbuf = kmem_zalloc(HME_RMDMAX * sizeof (hmebuf_t), KM_SLEEP);
2859 
2860         /* Alloc RX buffers. */
2861         for (int i = 0; i < HME_RMDMAX; i++) {
2862                 if (hmeallocbuf(hmep, &hmep->hme_rbuf[i], DDI_DMA_READ) !=
2863                     DDI_SUCCESS) {
2864                         return (DDI_FAILURE);
2865                 }
2866         }
2867 
2868         /* Alloc TX buffers. */
2869         for (int i = 0; i < HME_TMDMAX; i++) {
2870                 if (hmeallocbuf(hmep, &hmep->hme_tbuf[i], DDI_DMA_WRITE) !=
2871                     DDI_SUCCESS) {
2872                         return (DDI_FAILURE);
2873                 }
2874         }
2875         return (DDI_SUCCESS);
2876 }
2877 
2878 static void
2879 hmefreebufs(struct hme *hmep)
2880 {
2881         int i;
2882 
2883         if (hmep->hme_rbuf == NULL)
2884                 return;
2885 
2886         /*
2887          * Free and unload pending xmit and recv buffers.
2888          * Maintaining the 1-to-1 ordered sequence of
2889          * We have written the routine to be idempotent.
2890          */
2891 
2892         for (i = 0; i < HME_TMDMAX; i++) {
2893                 hmebuf_t *tbuf = &hmep->hme_tbuf[i];
2894                 if (tbuf->paddr) {
2895                         (void) ddi_dma_unbind_handle(tbuf->dmah);
2896                 }
2897                 if (tbuf->kaddr) {
2898                         ddi_dma_mem_free(&tbuf->acch);
2899                 }
2900                 if (tbuf->dmah) {
2901                         ddi_dma_free_handle(&tbuf->dmah);
2902                 }
2903         }
2904         for (i = 0; i < HME_RMDMAX; i++) {
2905                 hmebuf_t *rbuf = &hmep->hme_rbuf[i];
2906                 if (rbuf->paddr) {
2907                         (void) ddi_dma_unbind_handle(rbuf->dmah);
2908                 }
2909                 if (rbuf->kaddr) {
2910                         ddi_dma_mem_free(&rbuf->acch);
2911                 }
2912                 if (rbuf->dmah) {
2913                         ddi_dma_free_handle(&rbuf->dmah);
2914                 }
2915         }
2916         kmem_free(hmep->hme_rbuf, HME_RMDMAX * sizeof (hmebuf_t));
2917         kmem_free(hmep->hme_tbuf, HME_TMDMAX * sizeof (hmebuf_t));
2918 }
2919 
2920 /*
2921  * Un-initialize (STOP) HME channel.
2922  */
2923 static void
2924 hmeuninit(struct hme *hmep)
2925 {
2926         /*
2927          * Allow up to 'HMEDRAINTIME' for pending xmit's to complete.
2928          */
2929         HMEDELAY((hmep->hme_txindex == hmep->hme_txreclaim), HMEDRAINTIME);
2930 
2931         mutex_enter(&hmep->hme_intrlock);
2932         mutex_enter(&hmep->hme_xmitlock);
2933 
2934         hmep->hme_flags &= ~HMERUNNING;
2935 
2936         (void) hmestop(hmep);
2937 
2938         mutex_exit(&hmep->hme_xmitlock);
2939         mutex_exit(&hmep->hme_intrlock);
2940 }
2941 
2942 /*
2943  * Allocate CONSISTENT memory for rmds and tmds with appropriate alignment and
2944  * map it in IO space. Allocate space for transmit and receive ddi_dma_handle
2945  * structures to use the DMA interface.
2946  */
2947 static int
2948 hmeallocthings(struct hme *hmep)
2949 {
2950         int                     size;
2951         int                     rval;
2952         size_t                  real_len;
2953         uint_t                  cookiec;
2954         ddi_dma_cookie_t        dmac;
2955         dev_info_t              *dip = hmep->dip;
2956 
2957         /*
2958          * Allocate the TMD and RMD descriptors and extra for page alignment.
2959          */
2960 
2961         rval = ddi_dma_alloc_handle(dip, &hme_dma_attr, DDI_DMA_DONTWAIT, NULL,
2962             &hmep->hme_rmd_dmah);
2963         if (rval != DDI_SUCCESS) {
2964                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2965                     "cannot allocate rmd handle - failed");
2966                 return (DDI_FAILURE);
2967         }
2968         size = HME_RMDMAX * sizeof (struct hme_rmd);
2969         rval = ddi_dma_mem_alloc(hmep->hme_rmd_dmah, size,
2970             &hmep->hme_dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
2971             &hmep->hme_rmd_kaddr, &real_len, &hmep->hme_rmd_acch);
2972         if (rval != DDI_SUCCESS) {
2973                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2974                     "cannot allocate rmd dma mem - failed");
2975                 return (DDI_FAILURE);
2976         }
2977         hmep->hme_rmdp = (void *)(hmep->hme_rmd_kaddr);
2978         rval = ddi_dma_addr_bind_handle(hmep->hme_rmd_dmah, NULL,
2979             hmep->hme_rmd_kaddr, size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2980             DDI_DMA_DONTWAIT, NULL, &dmac, &cookiec);
2981         if (rval != DDI_DMA_MAPPED) {
2982                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2983                     "cannot allocate rmd dma - failed");
2984                 return (DDI_FAILURE);
2985         }
2986         hmep->hme_rmd_paddr = dmac.dmac_address;
2987         if (cookiec != 1) {
2988                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2989                     "too many rmd cookies - failed");
2990                 return (DDI_FAILURE);
2991         }
2992 
2993         rval = ddi_dma_alloc_handle(dip, &hme_dma_attr, DDI_DMA_DONTWAIT, NULL,
2994             &hmep->hme_tmd_dmah);
2995         if (rval != DDI_SUCCESS) {
2996                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
2997                     "cannot allocate tmd handle - failed");
2998                 return (DDI_FAILURE);
2999         }
3000         size = HME_TMDMAX * sizeof (struct hme_rmd);
3001         rval = ddi_dma_mem_alloc(hmep->hme_tmd_dmah, size,
3002             &hmep->hme_dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
3003             &hmep->hme_tmd_kaddr, &real_len, &hmep->hme_tmd_acch);
3004         if (rval != DDI_SUCCESS) {
3005                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
3006                     "cannot allocate tmd dma mem - failed");
3007                 return (DDI_FAILURE);
3008         }
3009         hmep->hme_tmdp = (void *)(hmep->hme_tmd_kaddr);
3010         rval = ddi_dma_addr_bind_handle(hmep->hme_tmd_dmah, NULL,
3011             hmep->hme_tmd_kaddr, size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
3012             DDI_DMA_DONTWAIT, NULL, &dmac, &cookiec);
3013         if (rval != DDI_DMA_MAPPED) {
3014                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
3015                     "cannot allocate tmd dma - failed");
3016                 return (DDI_FAILURE);
3017         }
3018         hmep->hme_tmd_paddr = dmac.dmac_address;
3019         if (cookiec != 1) {
3020                 HME_FAULT_MSG1(hmep, SEVERITY_HIGH, INIT_MSG,
3021                     "too many tmd cookies - failed");
3022                 return (DDI_FAILURE);
3023         }
3024 
3025         return (DDI_SUCCESS);
3026 }
3027 
3028 static void
3029 hmefreethings(struct hme *hmep)
3030 {
3031         if (hmep->hme_rmd_paddr) {
3032                 (void) ddi_dma_unbind_handle(hmep->hme_rmd_dmah);
3033                 hmep->hme_rmd_paddr = 0;
3034         }
3035         if (hmep->hme_rmd_acch)
3036                 ddi_dma_mem_free(&hmep->hme_rmd_acch);
3037         if (hmep->hme_rmd_dmah)
3038                 ddi_dma_free_handle(&hmep->hme_rmd_dmah);
3039 
3040         if (hmep->hme_tmd_paddr) {
3041                 (void) ddi_dma_unbind_handle(hmep->hme_tmd_dmah);
3042                 hmep->hme_tmd_paddr = 0;
3043         }
3044         if (hmep->hme_tmd_acch)
3045                 ddi_dma_mem_free(&hmep->hme_tmd_acch);
3046         if (hmep->hme_tmd_dmah)
3047                 ddi_dma_free_handle(&hmep->hme_tmd_dmah);
3048 }
3049 
3050 /*
3051  *      First check to see if it our device interrupting.
3052  */
3053 static uint_t
3054 hmeintr(caddr_t arg)
3055 {
3056         struct hme      *hmep = (void *)arg;
3057         uint32_t        hmesbits;
3058         uint32_t        serviced = DDI_INTR_UNCLAIMED;
3059         uint32_t        num_reads = 0;
3060         uint32_t        rflags;
3061         mblk_t          *mp, *head, **tail;
3062 
3063 
3064         head = NULL;
3065         tail = &head;
3066 
3067         mutex_enter(&hmep->hme_intrlock);
3068 
3069         /*
3070          * The status register auto-clears on read except for
3071          * MIF Interrupt bit
3072          */
3073         hmesbits = GET_GLOBREG(status);
3074         CHECK_GLOBREG();
3075 
3076         /*
3077          * Note: TINT is sometimes enabled in thr hmereclaim()
3078          */
3079 
3080         /*
3081          * Bugid 1227832 - to handle spurious interrupts on fusion systems.
3082          * Claim the first interrupt after initialization
3083          */
3084         if (hmep->hme_flags & HMEINITIALIZED) {
3085                 hmep->hme_flags &= ~HMEINITIALIZED;
3086                 serviced = DDI_INTR_CLAIMED;
3087         }
3088 
3089         if ((hmesbits & (HMEG_STATUS_INTR | HMEG_STATUS_TINT)) == 0) {
3090                                                 /* No interesting interrupt */
3091                 if (hmep->hme_intrstats) {
3092                         if (serviced == DDI_INTR_UNCLAIMED)
3093                                 KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
3094                         else
3095                                 KIOIP->intrs[KSTAT_INTR_HARD]++;
3096                 }
3097                 mutex_exit(&hmep->hme_intrlock);
3098                 return (serviced);
3099         }
3100 
3101         serviced = DDI_INTR_CLAIMED;
3102 
3103         if (!(hmep->hme_flags & HMERUNNING)) {
3104                 if (hmep->hme_intrstats)
3105                         KIOIP->intrs[KSTAT_INTR_HARD]++;
3106                 mutex_exit(&hmep->hme_intrlock);
3107                 hmeuninit(hmep);
3108                 return (serviced);
3109         }
3110 
3111         if (hmesbits & (HMEG_STATUS_FATAL_ERR | HMEG_STATUS_NONFATAL_ERR)) {
3112                 if (hmesbits & HMEG_STATUS_FATAL_ERR) {
3113 
3114                         if (hmep->hme_intrstats)
3115                                 KIOIP->intrs[KSTAT_INTR_HARD]++;
3116                         hme_fatal_err(hmep, hmesbits);
3117 
3118                         mutex_exit(&hmep->hme_intrlock);
3119                         (void) hmeinit(hmep);
3120                         return (serviced);
3121                 }
3122                 hme_nonfatal_err(hmep, hmesbits);
3123         }
3124 
3125         if (hmesbits & (HMEG_STATUS_TX_ALL | HMEG_STATUS_TINT)) {
3126                 mutex_enter(&hmep->hme_xmitlock);
3127 
3128                 hmereclaim(hmep);
3129                 mutex_exit(&hmep->hme_xmitlock);
3130         }
3131 
3132         if (hmesbits & HMEG_STATUS_RINT) {
3133 
3134                 /*
3135                  * This dummy PIO is required to flush the SBus
3136                  * Bridge buffers in QFE.
3137                  */
3138                 (void) GET_GLOBREG(config);
3139 
3140                 /*
3141                  * Loop through each RMD no more than once.
3142                  */
3143                 while (num_reads++ < HME_RMDMAX) {
3144                         hmebuf_t *rbuf;
3145                         int rxptr;
3146 
3147                         rxptr = hmep->hme_rxindex % HME_RMDMAX;
3148                         HMESYNCRMD(rxptr, DDI_DMA_SYNC_FORKERNEL);
3149 
3150                         rflags = GET_RMD_FLAGS(rxptr);
3151                         if (rflags & HMERMD_OWN) {
3152                                 /*
3153                                  * Chip still owns it.  We're done.
3154                                  */
3155                                 break;
3156                         }
3157 
3158                         /*
3159                          * Retrieve the packet.
3160                          */
3161                         rbuf = &hmep->hme_rbuf[rxptr];
3162                         mp = hmeread(hmep, rbuf, rflags);
3163 
3164                         /*
3165                          * Return ownership of the RMD.
3166                          */
3167                         PUT_RMD(rxptr, rbuf->paddr);
3168                         HMESYNCRMD(rxptr, DDI_DMA_SYNC_FORDEV);
3169 
3170                         if (mp != NULL) {
3171                                 *tail = mp;
3172                                 tail = &mp->b_next;
3173                         }
3174 
3175                         /*
3176                          * Advance to the next RMD.
3177                          */
3178                         hmep->hme_rxindex++;
3179                 }
3180         }
3181 
3182         if (hmep->hme_intrstats)
3183                 KIOIP->intrs[KSTAT_INTR_HARD]++;
3184 
3185         mutex_exit(&hmep->hme_intrlock);
3186 
3187         if (head != NULL)
3188                 mac_rx(hmep->hme_mh, NULL, head);
3189 
3190         return (serviced);
3191 }
3192 
3193 /*
3194  * Transmit completion reclaiming.
3195  */
3196 static void
3197 hmereclaim(struct hme *hmep)
3198 {
3199         boolean_t       reclaimed = B_FALSE;
3200 
3201         /*
3202          * Loop through each TMD.
3203          */
3204         while (hmep->hme_txindex > hmep->hme_txreclaim) {
3205 
3206                 int             reclaim;
3207                 uint32_t        flags;
3208 
3209                 reclaim = hmep->hme_txreclaim % HME_TMDMAX;
3210                 HMESYNCTMD(reclaim, DDI_DMA_SYNC_FORKERNEL);
3211 
3212                 flags = GET_TMD_FLAGS(reclaim);
3213                 if (flags & HMETMD_OWN) {
3214                         /*
3215                          * Chip still owns it.  We're done.
3216                          */
3217                         break;
3218                 }
3219 
3220                 /*
3221                  * Count a chained packet only once.
3222                  */
3223                 if (flags & HMETMD_SOP) {
3224                         hmep->hme_opackets++;
3225                 }
3226 
3227                 /*
3228                  * MIB II
3229                  */
3230                 hmep->hme_obytes += flags & HMETMD_BUFSIZE;
3231 
3232                 reclaimed = B_TRUE;
3233                 hmep->hme_txreclaim++;
3234         }
3235 
3236         if (reclaimed) {
3237                 /*
3238                  * we could reclaim some TMDs so turn off interrupts
3239                  */
3240                 if (hmep->hme_wantw) {
3241                         PUT_GLOBREG(intmask,
3242                             HMEG_MASK_INTR | HMEG_MASK_TINT |
3243                             HMEG_MASK_TX_ALL);
3244                         hmep->hme_wantw = B_FALSE;
3245                         mac_tx_update(hmep->hme_mh);
3246                 }
3247         } else {
3248                 /*
3249                  * enable TINTS: so that even if there is no further activity
3250                  * hmereclaim will get called
3251                  */
3252                 if (hmep->hme_wantw)
3253                         PUT_GLOBREG(intmask,
3254                             GET_GLOBREG(intmask) & ~HMEG_MASK_TX_ALL);
3255         }
3256         CHECK_GLOBREG();
3257 }
3258 
3259 /*
3260  * Handle interrupts for fatal errors
3261  * Need reinitialization of the ENET channel.
3262  */
3263 static void
3264 hme_fatal_err(struct hme *hmep, uint_t hmesbits)
3265 {
3266 
3267         if (hmesbits & HMEG_STATUS_SLV_PAR_ERR) {
3268                 hmep->hme_slvparerr++;
3269         }
3270 
3271         if (hmesbits & HMEG_STATUS_SLV_ERR_ACK) {
3272                 hmep->hme_slverrack++;
3273         }
3274 
3275         if (hmesbits & HMEG_STATUS_TX_TAG_ERR) {
3276                 hmep->hme_txtagerr++;
3277                 hmep->hme_oerrors++;
3278         }
3279 
3280         if (hmesbits & HMEG_STATUS_TX_PAR_ERR) {
3281                 hmep->hme_txparerr++;
3282                 hmep->hme_oerrors++;
3283         }
3284 
3285         if (hmesbits & HMEG_STATUS_TX_LATE_ERR) {
3286                 hmep->hme_txlaterr++;
3287                 hmep->hme_oerrors++;
3288         }
3289 
3290         if (hmesbits & HMEG_STATUS_TX_ERR_ACK) {
3291                 hmep->hme_txerrack++;
3292                 hmep->hme_oerrors++;
3293         }
3294 
3295         if (hmesbits & HMEG_STATUS_EOP_ERR) {
3296                 hmep->hme_eoperr++;
3297         }
3298 
3299         if (hmesbits & HMEG_STATUS_RX_TAG_ERR) {
3300                 hmep->hme_rxtagerr++;
3301                 hmep->hme_ierrors++;
3302         }
3303 
3304         if (hmesbits & HMEG_STATUS_RX_PAR_ERR) {
3305                 hmep->hme_rxparerr++;
3306                 hmep->hme_ierrors++;
3307         }
3308 
3309         if (hmesbits & HMEG_STATUS_RX_LATE_ERR) {
3310                 hmep->hme_rxlaterr++;
3311                 hmep->hme_ierrors++;
3312         }
3313 
3314         if (hmesbits & HMEG_STATUS_RX_ERR_ACK) {
3315                 hmep->hme_rxerrack++;
3316                 hmep->hme_ierrors++;
3317         }
3318 }
3319 
3320 /*
3321  * Handle interrupts regarding non-fatal errors.
3322  */
3323 static void
3324 hme_nonfatal_err(struct hme *hmep, uint_t hmesbits)
3325 {
3326 
3327         if (hmesbits & HMEG_STATUS_RX_DROP) {
3328                 hmep->hme_missed++;
3329                 hmep->hme_ierrors++;
3330         }
3331 
3332         if (hmesbits & HMEG_STATUS_DEFTIMR_EXP) {
3333                 hmep->hme_defer_xmts++;
3334         }
3335 
3336         if (hmesbits & HMEG_STATUS_FSTCOLC_EXP) {
3337                 hmep->hme_fstcol += 256;
3338         }
3339 
3340         if (hmesbits & HMEG_STATUS_LATCOLC_EXP) {
3341                 hmep->hme_tlcol += 256;
3342                 hmep->hme_oerrors += 256;
3343         }
3344 
3345         if (hmesbits & HMEG_STATUS_EXCOLC_EXP) {
3346                 hmep->hme_excol += 256;
3347                 hmep->hme_oerrors += 256;
3348         }
3349 
3350         if (hmesbits & HMEG_STATUS_NRMCOLC_EXP) {
3351                 hmep->hme_coll += 256;
3352         }
3353 
3354         if (hmesbits & HMEG_STATUS_MXPKTSZ_ERR) {
3355                 hmep->hme_babl++;
3356                 hmep->hme_oerrors++;
3357         }
3358 
3359         /*
3360          * This error is fatal and the board needs to
3361          * be reinitialized. Comments?
3362          */
3363         if (hmesbits & HMEG_STATUS_TXFIFO_UNDR) {
3364                 hmep->hme_uflo++;
3365                 hmep->hme_oerrors++;
3366         }
3367 
3368         if (hmesbits & HMEG_STATUS_SQE_TST_ERR) {
3369                 hmep->hme_sqe_errors++;
3370         }
3371 
3372         if (hmesbits & HMEG_STATUS_RCV_CNT_EXP) {
3373                 if (hmep->hme_rxcv_enable) {
3374                         hmep->hme_cvc += 256;
3375                 }
3376         }
3377 
3378         if (hmesbits & HMEG_STATUS_RXFIFO_OVFL) {
3379                 hmep->hme_oflo++;
3380                 hmep->hme_ierrors++;
3381         }
3382 
3383         if (hmesbits & HMEG_STATUS_LEN_CNT_EXP) {
3384                 hmep->hme_lenerr += 256;
3385                 hmep->hme_ierrors += 256;
3386         }
3387 
3388         if (hmesbits & HMEG_STATUS_ALN_CNT_EXP) {
3389                 hmep->hme_align_errors += 256;
3390                 hmep->hme_ierrors += 256;
3391         }
3392 
3393         if (hmesbits & HMEG_STATUS_CRC_CNT_EXP) {
3394                 hmep->hme_fcs_errors += 256;
3395                 hmep->hme_ierrors += 256;
3396         }
3397 }
3398 
3399 static mblk_t *
3400 hmeread(struct hme *hmep, hmebuf_t *rbuf, uint32_t rflags)
3401 {
3402         mblk_t          *bp;
3403         uint32_t        len;
3404         t_uscalar_t     type;
3405 
3406         len = (rflags & HMERMD_BUFSIZE) >> HMERMD_BUFSIZE_SHIFT;
3407 
3408         /*
3409          * Check for short packet
3410          * and check for overflow packet also. The processing is the
3411          * same for both the cases - reuse the buffer. Update the Buffer
3412          * overflow counter.
3413          */
3414         if ((len < ETHERMIN) || (rflags & HMERMD_OVFLOW) ||
3415             (len > (ETHERMAX + 4))) {
3416                 if (len < ETHERMIN)
3417                         hmep->hme_runt++;
3418 
3419                 else {
3420                         hmep->hme_buff++;
3421                         hmep->hme_toolong_errors++;
3422                 }
3423                 hmep->hme_ierrors++;
3424                 return (NULL);
3425         }
3426 
3427         /*
3428          * Sync the received buffer before looking at it.
3429          */
3430 
3431         (void) ddi_dma_sync(rbuf->dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
3432 
3433         /*
3434          * copy the packet data and then recycle the descriptor.
3435          */
3436 
3437         if ((bp = allocb(len + HME_FSTBYTE_OFFSET, BPRI_HI)) == NULL) {
3438 
3439                 hmep->hme_allocbfail++;
3440                 hmep->hme_norcvbuf++;
3441 
3442                 return (NULL);
3443         }
3444 
3445         bcopy(rbuf->kaddr, bp->b_rptr, len + HME_FSTBYTE_OFFSET);
3446 
3447         hmep->hme_ipackets++;
3448 
3449         /*  Add the First Byte offset to the b_rptr and copy */
3450         bp->b_rptr += HME_FSTBYTE_OFFSET;
3451         bp->b_wptr = bp->b_rptr + len;
3452 
3453         /*
3454          * update MIB II statistics
3455          */
3456         BUMP_InNUcast(hmep, bp->b_rptr);
3457         hmep->hme_rbytes += len;
3458 
3459         type = get_ether_type(bp->b_rptr);
3460 
3461         /*
3462          * TCP partial checksum in hardware
3463          */
3464         if (type == ETHERTYPE_IP || type == ETHERTYPE_IPV6) {
3465                 uint16_t cksum = ~rflags & HMERMD_CKSUM;
3466                 uint_t end = len - sizeof (struct ether_header);
3467                 mac_hcksum_set(bp, 0, 0, end, htons(cksum), HCK_PARTIALCKSUM);
3468         }
3469 
3470         return (bp);
3471 }
3472 
3473 /*VARARGS*/
3474 static void
3475 hme_fault_msg(struct hme *hmep, uint_t severity, msg_t type, char *fmt, ...)
3476 {
3477         char    msg_buffer[255];
3478         va_list ap;
3479 
3480         va_start(ap, fmt);
3481         (void) vsnprintf(msg_buffer, sizeof (msg_buffer), fmt, ap);
3482 
3483         if (hmep == NULL) {
3484                 cmn_err(CE_NOTE, "hme : %s", msg_buffer);
3485 
3486         } else if (type == DISPLAY_MSG) {
3487                 cmn_err(CE_CONT, "?%s%d : %s\n", ddi_driver_name(hmep->dip),
3488                     hmep->instance, msg_buffer);
3489         } else if (severity == SEVERITY_HIGH) {
3490                 cmn_err(CE_WARN, "%s%d : %s, SEVERITY_HIGH, %s\n",
3491                     ddi_driver_name(hmep->dip), hmep->instance,
3492                     msg_buffer, msg_string[type]);
3493         } else {
3494                 cmn_err(CE_CONT, "%s%d : %s\n", ddi_driver_name(hmep->dip),
3495                     hmep->instance, msg_buffer);
3496         }
3497         va_end(ap);
3498 }
3499 
3500 /*
3501  * if this is the first init do not bother to save the
3502  * counters. They should be 0, but do not count on it.
3503  */
3504 static void
3505 hmesavecntrs(struct hme *hmep)
3506 {
3507         uint32_t fecnt, aecnt, lecnt, rxcv;
3508         uint32_t ltcnt, excnt;
3509 
3510         /* XXX What all gets added in ierrors and oerrors? */
3511         fecnt = GET_MACREG(fecnt);
3512         PUT_MACREG(fecnt, 0);
3513 
3514         aecnt = GET_MACREG(aecnt);
3515         hmep->hme_align_errors += aecnt;
3516         PUT_MACREG(aecnt, 0);
3517 
3518         lecnt = GET_MACREG(lecnt);
3519         hmep->hme_lenerr += lecnt;
3520         PUT_MACREG(lecnt, 0);
3521 
3522         rxcv = GET_MACREG(rxcv);
3523 #ifdef HME_CODEVIOL_BUG
3524         /*
3525          * Ignore rxcv errors for Sbus/FEPS 2.1 or earlier
3526          */
3527         if (!hmep->hme_rxcv_enable) {
3528                 rxcv = 0;
3529         }
3530 #endif
3531         hmep->hme_cvc += rxcv;
3532         PUT_MACREG(rxcv, 0);
3533 
3534         ltcnt = GET_MACREG(ltcnt);
3535         hmep->hme_tlcol += ltcnt;
3536         PUT_MACREG(ltcnt, 0);
3537 
3538         excnt = GET_MACREG(excnt);
3539         hmep->hme_excol += excnt;
3540         PUT_MACREG(excnt, 0);
3541 
3542         hmep->hme_fcs_errors += fecnt;
3543         hmep->hme_ierrors += (fecnt + aecnt + lecnt);
3544         hmep->hme_oerrors += (ltcnt + excnt);
3545         hmep->hme_coll += (GET_MACREG(nccnt) + ltcnt);
3546 
3547         PUT_MACREG(nccnt, 0);
3548         CHECK_MACREG();
3549 }
3550 
3551 /*
3552  * To set up the mac address for the network interface:
3553  * The adapter card may support a local mac address which is published
3554  * in a device node property "local-mac-address". This mac address is
3555  * treated as the factory-installed mac address for DLPI interface.
3556  * If the adapter firmware has used the device for diskless boot
3557  * operation it publishes a property called "mac-address" for use by
3558  * inetboot and the device driver.
3559  * If "mac-address" is not found, the system options property
3560  * "local-mac-address" is used to select the mac-address. If this option
3561  * is set to "true", and "local-mac-address" has been found, then
3562  * local-mac-address is used; otherwise the system mac address is used
3563  * by calling the "localetheraddr()" function.
3564  */
3565 static void
3566 hme_setup_mac_address(struct hme *hmep, dev_info_t *dip)
3567 {
3568         char    *prop;
3569         int     prop_len = sizeof (int);
3570 
3571         hmep->hme_addrflags = 0;
3572 
3573         /*
3574          * Check if it is an adapter with its own local mac address
3575          * If it is present, save it as the "factory-address"
3576          * for this adapter.
3577          */
3578         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3579             "local-mac-address",
3580             (caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
3581                 if (prop_len == ETHERADDRL) {
3582                         hmep->hme_addrflags = HME_FACTADDR_PRESENT;
3583                         ether_bcopy(prop, &hmep->hme_factaddr);
3584                         HME_FAULT_MSG2(hmep, SEVERITY_NONE, DISPLAY_MSG,
3585                             "Local Ethernet address = %s",
3586                             ether_sprintf(&hmep->hme_factaddr));
3587                 }
3588                 kmem_free(prop, prop_len);
3589         }
3590 
3591         /*
3592          * Check if the adapter has published "mac-address" property.
3593          * If it is present, use it as the mac address for this device.
3594          */
3595         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3596             "mac-address", (caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
3597                 if (prop_len >= ETHERADDRL) {
3598                         ether_bcopy(prop, &hmep->hme_ouraddr);
3599                         kmem_free(prop, prop_len);
3600                         return;
3601                 }
3602                 kmem_free(prop, prop_len);
3603         }
3604 
3605 #ifdef  __sparc
3606         /*
3607          * On sparc, we might be able to use the mac address from the
3608          * system.  However, on all other systems, we need to use the
3609          * address from the PROM.
3610          */
3611         if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, "local-mac-address?",
3612             (caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
3613                 if ((strncmp("true", prop, prop_len) == 0) &&
3614                     (hmep->hme_addrflags & HME_FACTADDR_PRESENT)) {
3615                         hmep->hme_addrflags |= HME_FACTADDR_USE;
3616                         ether_bcopy(&hmep->hme_factaddr, &hmep->hme_ouraddr);
3617                         kmem_free(prop, prop_len);
3618                         HME_FAULT_MSG1(hmep, SEVERITY_NONE, DISPLAY_MSG,
3619                             "Using local MAC address");
3620                         return;
3621                 }
3622                 kmem_free(prop, prop_len);
3623         }
3624 
3625         /*
3626          * Get the system ethernet address.
3627          */
3628         (void) localetheraddr((struct ether_addr *)NULL, &hmep->hme_ouraddr);
3629 #else
3630         ether_bcopy(&hmep->hme_factaddr, &hmep->hme_ouraddr);
3631 #endif
3632 }
3633 
3634 /* ARGSUSED */
3635 static void
3636 hme_check_acc_handle(char *file, uint_t line, struct hme *hmep,
3637     ddi_acc_handle_t handle)
3638 {
3639 }