1 /*
   2  * sfe_util.c: general ethernet mac driver framework version 2.6
   3  *
   4  * Copyright (c) 2002-2008 Masayuki Murayama.  All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions are met:
   8  *
   9  * 1. Redistributions of source code must retain the above copyright notice,
  10  *    this list of conditions and the following disclaimer.
  11  *
  12  * 2. Redistributions in binary form must reproduce the above copyright notice,
  13  *    this list of conditions and the following disclaimer in the documentation
  14  *    and/or other materials provided with the distribution.
  15  *
  16  * 3. Neither the name of the author nor the names of its contributors may be
  17  *    used to endorse or promote products derived from this software without
  18  *    specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  30  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  31  * DAMAGE.
  32  */
  33 
  34 /*
  35  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  36  * Use is subject to license terms.
  37  */
  38 
  39 /*
  40  * System Header files.
  41  */
  42 #include <sys/types.h>
  43 #include <sys/conf.h>
  44 #include <sys/debug.h>
  45 #include <sys/kmem.h>
  46 #include <sys/vtrace.h>
  47 #include <sys/ethernet.h>
  48 #include <sys/modctl.h>
  49 #include <sys/errno.h>
  50 #include <sys/ddi.h>
  51 #include <sys/sunddi.h>
  52 #include <sys/stream.h>           /* required for MBLK* */
  53 #include <sys/strsun.h>           /* required for mionack() */
  54 #include <sys/byteorder.h>
  55 #include <sys/sysmacros.h>
  56 #include <sys/pci.h>
  57 #include <inet/common.h>
  58 #include <inet/led.h>
  59 #include <inet/mi.h>
  60 #include <inet/nd.h>
  61 #include <sys/crc32.h>
  62 
  63 #include <sys/note.h>
  64 
  65 #include "sfe_mii.h"
  66 #include "sfe_util.h"
  67 
  68 
  69 
  70 extern char ident[];
  71 
  72 /* Debugging support */
  73 #ifdef GEM_DEBUG_LEVEL
  74 static int gem_debug = GEM_DEBUG_LEVEL;
  75 #define DPRINTF(n, args)        if (gem_debug > (n)) cmn_err args
  76 #else
  77 #define DPRINTF(n, args)
  78 #undef ASSERT
  79 #define ASSERT(x)
  80 #endif
  81 
  82 #define IOC_LINESIZE    0x40    /* Is it right for amd64? */
  83 
  84 /*
  85  * Useful macros and typedefs
  86  */
  87 #define ROUNDUP(x, a)   (((x) + (a) - 1) & ~((a) - 1))
  88 
  89 #define GET_NET16(p)    ((((uint8_t *)(p))[0] << 8)| ((uint8_t *)(p))[1])
  90 #define GET_ETHERTYPE(p)        GET_NET16(((uint8_t *)(p)) + ETHERADDRL*2)
  91 
  92 #define GET_IPTYPEv4(p) (((uint8_t *)(p))[sizeof (struct ether_header) + 9])
  93 #define GET_IPTYPEv6(p) (((uint8_t *)(p))[sizeof (struct ether_header) + 6])
  94 
  95 
  96 #ifndef INT32_MAX
  97 #define INT32_MAX       0x7fffffff
  98 #endif
  99 
 100 #define VTAG_OFF        (ETHERADDRL*2)
 101 #ifndef VTAG_SIZE
 102 #define VTAG_SIZE       4
 103 #endif
 104 #ifndef VTAG_TPID
 105 #define VTAG_TPID       0x8100U
 106 #endif
 107 
 108 #define GET_TXBUF(dp, sn)       \
 109         &(dp)->tx_buf[SLOT((dp)->tx_slots_base + (sn), (dp)->gc.gc_tx_buf_size)]
 110 
 111 #define TXFLAG_VTAG(flag)       \
 112         (((flag) & GEM_TXFLAG_VTAG) >> GEM_TXFLAG_VTAG_SHIFT)
 113 
 114 #define MAXPKTBUF(dp)   \
 115         ((dp)->mtu + sizeof (struct ether_header) + VTAG_SIZE + ETHERFCSL)
 116 
 117 #define WATCH_INTERVAL_FAST     drv_usectohz(100*1000)  /* 100mS */
 118 #define BOOLEAN(x)      ((x) != 0)
 119 
 120 /*
 121  * Macros to distinct chip generation.
 122  */
 123 
 124 /*
 125  * Private functions
 126  */
 127 static void gem_mii_start(struct gem_dev *);
 128 static void gem_mii_stop(struct gem_dev *);
 129 
 130 /* local buffer management */
 131 static void gem_nd_setup(struct gem_dev *dp);
 132 static void gem_nd_cleanup(struct gem_dev *dp);
 133 static int gem_alloc_memory(struct gem_dev *);
 134 static void gem_free_memory(struct gem_dev *);
 135 static void gem_init_rx_ring(struct gem_dev *);
 136 static void gem_init_tx_ring(struct gem_dev *);
 137 __INLINE__ static void gem_append_rxbuf(struct gem_dev *, struct rxbuf *);
 138 
 139 static void gem_tx_timeout(struct gem_dev *);
 140 static void gem_mii_link_watcher(struct gem_dev *dp);
 141 static int gem_mac_init(struct gem_dev *dp);
 142 static int gem_mac_start(struct gem_dev *dp);
 143 static int gem_mac_stop(struct gem_dev *dp, uint_t flags);
 144 static void gem_mac_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp);
 145 
 146 static  struct ether_addr       gem_etherbroadcastaddr = {
 147         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 148 };
 149 
 150 int gem_speed_value[] = {10, 100, 1000};
 151 
 152 /* ============================================================== */
 153 /*
 154  * Misc runtime routines
 155  */
 156 /* ============================================================== */
 157 /*
 158  * Ether CRC calculation according to 21143 data sheet
 159  */
 160 uint32_t
 161 gem_ether_crc_le(const uint8_t *addr, int len)
 162 {
 163         uint32_t        crc;
 164 
 165         CRC32(crc, addr, ETHERADDRL, 0xffffffffU, crc32_table);
 166         return (crc);
 167 }
 168 
 169 uint32_t
 170 gem_ether_crc_be(const uint8_t *addr, int len)
 171 {
 172         int             idx;
 173         int             bit;
 174         uint_t          data;
 175         uint32_t        crc;
 176 #define CRC32_POLY_BE   0x04c11db7
 177 
 178         crc = 0xffffffff;
 179         for (idx = 0; idx < len; idx++) {
 180                 for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) {
 181                         crc = (crc << 1)
 182                             ^ ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0);
 183                 }
 184         }
 185         return (crc);
 186 #undef  CRC32_POLY_BE
 187 }
 188 
 189 int
 190 gem_prop_get_int(struct gem_dev *dp, char *prop_template, int def_val)
 191 {
 192         char    propname[32];
 193 
 194         (void) sprintf(propname, prop_template, dp->name);
 195 
 196         return (ddi_prop_get_int(DDI_DEV_T_ANY, dp->dip,
 197             DDI_PROP_DONTPASS, propname, def_val));
 198 }
 199 
 200 static int
 201 gem_population(uint32_t x)
 202 {
 203         int     i;
 204         int     cnt;
 205 
 206         cnt = 0;
 207         for (i = 0; i < 32; i++) {
 208                 if (x & (1 << i)) {
 209                         cnt++;
 210                 }
 211         }
 212         return (cnt);
 213 }
 214 
 215 #ifdef GEM_DEBUG_LEVEL
 216 #ifdef GEM_DEBUG_VLAN
 217 static void
 218 gem_dump_packet(struct gem_dev *dp, char *title, mblk_t *mp,
 219     boolean_t check_cksum)
 220 {
 221         char    msg[180];
 222         uint8_t buf[18+20+20];
 223         uint8_t *p;
 224         size_t  offset;
 225         uint_t  ethertype;
 226         uint_t  proto;
 227         uint_t  ipproto = 0;
 228         uint_t  iplen;
 229         uint_t  iphlen;
 230         uint_t  tcplen;
 231         uint_t  udplen;
 232         uint_t  cksum;
 233         int     rest;
 234         int     len;
 235         char    *bp;
 236         mblk_t  *tp;
 237         extern uint_t   ip_cksum(mblk_t *, int, uint32_t);
 238 
 239         msg[0] = 0;
 240         bp = msg;
 241 
 242         rest = sizeof (buf);
 243         offset = 0;
 244         for (tp = mp; tp; tp = tp->b_cont) {
 245                 len = tp->b_wptr - tp->b_rptr;
 246                 len = min(rest, len);
 247                 bcopy(tp->b_rptr, &buf[offset], len);
 248                 rest -= len;
 249                 offset += len;
 250                 if (rest == 0) {
 251                         break;
 252                 }
 253         }
 254 
 255         offset = 0;
 256         p = &buf[offset];
 257 
 258         /* ethernet address */
 259         sprintf(bp,
 260             "ether: %02x:%02x:%02x:%02x:%02x:%02x"
 261             " -> %02x:%02x:%02x:%02x:%02x:%02x",
 262             p[6], p[7], p[8], p[9], p[10], p[11],
 263             p[0], p[1], p[2], p[3], p[4], p[5]);
 264         bp = &msg[strlen(msg)];
 265 
 266         /* vlag tag and etherrtype */
 267         ethertype = GET_ETHERTYPE(p);
 268         if (ethertype == VTAG_TPID) {
 269                 sprintf(bp, " vtag:0x%04x", GET_NET16(&p[14]));
 270                 bp = &msg[strlen(msg)];
 271 
 272                 offset += VTAG_SIZE;
 273                 p = &buf[offset];
 274                 ethertype = GET_ETHERTYPE(p);
 275         }
 276         sprintf(bp, " type:%04x", ethertype);
 277         bp = &msg[strlen(msg)];
 278 
 279         /* ethernet packet length */
 280         sprintf(bp, " mblklen:%d", msgdsize(mp));
 281         bp = &msg[strlen(msg)];
 282         if (mp->b_cont) {
 283                 sprintf(bp, "(");
 284                 bp = &msg[strlen(msg)];
 285                 for (tp = mp; tp; tp = tp->b_cont) {
 286                         if (tp == mp) {
 287                                 sprintf(bp, "%d", tp->b_wptr - tp->b_rptr);
 288                         } else {
 289                                 sprintf(bp, "+%d", tp->b_wptr - tp->b_rptr);
 290                         }
 291                         bp = &msg[strlen(msg)];
 292                 }
 293                 sprintf(bp, ")");
 294                 bp = &msg[strlen(msg)];
 295         }
 296 
 297         if (ethertype != ETHERTYPE_IP) {
 298                 goto x;
 299         }
 300 
 301         /* ip address */
 302         offset += sizeof (struct ether_header);
 303         p = &buf[offset];
 304         ipproto = p[9];
 305         iplen = GET_NET16(&p[2]);
 306         sprintf(bp, ", ip: %d.%d.%d.%d -> %d.%d.%d.%d proto:%d iplen:%d",
 307             p[12], p[13], p[14], p[15],
 308             p[16], p[17], p[18], p[19],
 309             ipproto, iplen);
 310         bp = (void *)&msg[strlen(msg)];
 311 
 312         iphlen = (p[0] & 0xf) * 4;
 313 
 314         /* cksum for psuedo header */
 315         cksum = *(uint16_t *)&p[12];
 316         cksum += *(uint16_t *)&p[14];
 317         cksum += *(uint16_t *)&p[16];
 318         cksum += *(uint16_t *)&p[18];
 319         cksum += BE_16(ipproto);
 320 
 321         /* tcp or udp protocol header */
 322         offset += iphlen;
 323         p = &buf[offset];
 324         if (ipproto == IPPROTO_TCP) {
 325                 tcplen = iplen - iphlen;
 326                 sprintf(bp, ", tcp: len:%d cksum:%x",
 327                     tcplen, GET_NET16(&p[16]));
 328                 bp = (void *)&msg[strlen(msg)];
 329 
 330                 if (check_cksum) {
 331                         cksum += BE_16(tcplen);
 332                         cksum = (uint16_t)ip_cksum(mp, offset, cksum);
 333                         sprintf(bp, " (%s)",
 334                             (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
 335                         bp = (void *)&msg[strlen(msg)];
 336                 }
 337         } else if (ipproto == IPPROTO_UDP) {
 338                 udplen = GET_NET16(&p[4]);
 339                 sprintf(bp, ", udp: len:%d cksum:%x",
 340                     udplen, GET_NET16(&p[6]));
 341                 bp = (void *)&msg[strlen(msg)];
 342 
 343                 if (GET_NET16(&p[6]) && check_cksum) {
 344                         cksum += *(uint16_t *)&p[4];
 345                         cksum = (uint16_t)ip_cksum(mp, offset, cksum);
 346                         sprintf(bp, " (%s)",
 347                             (cksum == 0 || cksum == 0xffff) ? "ok" : "ng");
 348                         bp = (void *)&msg[strlen(msg)];
 349                 }
 350         }
 351 x:
 352         cmn_err(CE_CONT, "!%s: %s: %s", dp->name, title, msg);
 353 }
 354 #endif /* GEM_DEBUG_VLAN */
 355 #endif /* GEM_DEBUG_LEVEL */
 356 
 357 /* ============================================================== */
 358 /*
 359  * IO cache flush
 360  */
 361 /* ============================================================== */
 362 __INLINE__ void
 363 gem_rx_desc_dma_sync(struct gem_dev *dp, int head, int nslot, int how)
 364 {
 365         int     n;
 366         int     m;
 367         int     rx_desc_unit_shift = dp->gc.gc_rx_desc_unit_shift;
 368 
 369         /* sync active descriptors */
 370         if (rx_desc_unit_shift < 0 || nslot == 0) {
 371                 /* no rx descriptor ring */
 372                 return;
 373         }
 374 
 375         n = dp->gc.gc_rx_ring_size - head;
 376         if ((m = nslot - n) > 0) {
 377                 (void) ddi_dma_sync(dp->desc_dma_handle,
 378                     (off_t)0,
 379                     (size_t)(m << rx_desc_unit_shift),
 380                     how);
 381                 nslot = n;
 382         }
 383 
 384         (void) ddi_dma_sync(dp->desc_dma_handle,
 385             (off_t)(head << rx_desc_unit_shift),
 386             (size_t)(nslot << rx_desc_unit_shift),
 387             how);
 388 }
 389 
 390 __INLINE__ void
 391 gem_tx_desc_dma_sync(struct gem_dev *dp, int head, int nslot, int how)
 392 {
 393         int     n;
 394         int     m;
 395         int     tx_desc_unit_shift = dp->gc.gc_tx_desc_unit_shift;
 396 
 397         /* sync active descriptors */
 398         if (tx_desc_unit_shift < 0 || nslot == 0) {
 399                 /* no tx descriptor ring */
 400                 return;
 401         }
 402 
 403         n = dp->gc.gc_tx_ring_size - head;
 404         if ((m = nslot - n) > 0) {
 405                 (void) ddi_dma_sync(dp->desc_dma_handle,
 406                     (off_t)(dp->tx_ring_dma - dp->rx_ring_dma),
 407                     (size_t)(m << tx_desc_unit_shift),
 408                     how);
 409                 nslot = n;
 410         }
 411 
 412         (void) ddi_dma_sync(dp->desc_dma_handle,
 413             (off_t)((head << tx_desc_unit_shift)
 414             + (dp->tx_ring_dma - dp->rx_ring_dma)),
 415             (size_t)(nslot << tx_desc_unit_shift),
 416             how);
 417 }
 418 
 419 static void
 420 gem_rx_start_default(struct gem_dev *dp, int head, int nslot)
 421 {
 422         gem_rx_desc_dma_sync(dp,
 423             SLOT(head, dp->gc.gc_rx_ring_size), nslot,
 424             DDI_DMA_SYNC_FORDEV);
 425 }
 426 
 427 /* ============================================================== */
 428 /*
 429  * Buffer management
 430  */
 431 /* ============================================================== */
 432 static void
 433 gem_dump_txbuf(struct gem_dev *dp, int level, const char *title)
 434 {
 435         cmn_err(level,
 436             "!%s: %s: tx_active: %d[%d] %d[%d] (+%d), "
 437             "tx_softq: %d[%d] %d[%d] (+%d), "
 438             "tx_free: %d[%d] %d[%d] (+%d), "
 439             "tx_desc: %d[%d] %d[%d] (+%d), "
 440             "intr: %d[%d] (+%d), ",
 441             dp->name, title,
 442             dp->tx_active_head,
 443             SLOT(dp->tx_active_head, dp->gc.gc_tx_buf_size),
 444             dp->tx_active_tail,
 445             SLOT(dp->tx_active_tail, dp->gc.gc_tx_buf_size),
 446             dp->tx_active_tail - dp->tx_active_head,
 447             dp->tx_softq_head,
 448             SLOT(dp->tx_softq_head, dp->gc.gc_tx_buf_size),
 449             dp->tx_softq_tail,
 450             SLOT(dp->tx_softq_tail, dp->gc.gc_tx_buf_size),
 451             dp->tx_softq_tail - dp->tx_softq_head,
 452             dp->tx_free_head,
 453             SLOT(dp->tx_free_head, dp->gc.gc_tx_buf_size),
 454             dp->tx_free_tail,
 455             SLOT(dp->tx_free_tail, dp->gc.gc_tx_buf_size),
 456             dp->tx_free_tail - dp->tx_free_head,
 457             dp->tx_desc_head,
 458             SLOT(dp->tx_desc_head, dp->gc.gc_tx_ring_size),
 459             dp->tx_desc_tail,
 460             SLOT(dp->tx_desc_tail, dp->gc.gc_tx_ring_size),
 461             dp->tx_desc_tail - dp->tx_desc_head,
 462             dp->tx_desc_intr,
 463             SLOT(dp->tx_desc_intr, dp->gc.gc_tx_ring_size),
 464             dp->tx_desc_intr - dp->tx_desc_head);
 465 }
 466 
 467 static void
 468 gem_free_rxbuf(struct rxbuf *rbp)
 469 {
 470         struct gem_dev  *dp;
 471 
 472         dp = rbp->rxb_devp;
 473         ASSERT(mutex_owned(&dp->intrlock));
 474         rbp->rxb_next = dp->rx_buf_freelist;
 475         dp->rx_buf_freelist = rbp;
 476         dp->rx_buf_freecnt++;
 477 }
 478 
 479 /*
 480  * gem_get_rxbuf: supply a receive buffer which have been mapped into
 481  * DMA space.
 482  */
 483 struct rxbuf *
 484 gem_get_rxbuf(struct gem_dev *dp, int cansleep)
 485 {
 486         struct rxbuf            *rbp;
 487         uint_t                  count = 0;
 488         int                     i;
 489         int                     err;
 490 
 491         ASSERT(mutex_owned(&dp->intrlock));
 492 
 493         DPRINTF(3, (CE_CONT, "!gem_get_rxbuf: called freecnt:%d",
 494             dp->rx_buf_freecnt));
 495         /*
 496          * Get rx buffer management structure
 497          */
 498         rbp = dp->rx_buf_freelist;
 499         if (rbp) {
 500                 /* get one from the recycle list */
 501                 ASSERT(dp->rx_buf_freecnt > 0);
 502 
 503                 dp->rx_buf_freelist = rbp->rxb_next;
 504                 dp->rx_buf_freecnt--;
 505                 rbp->rxb_next = NULL;
 506                 return (rbp);
 507         }
 508 
 509         /*
 510          * Allocate a rx buffer management structure
 511          */
 512         rbp = kmem_zalloc(sizeof (*rbp), cansleep ? KM_SLEEP : KM_NOSLEEP);
 513         if (rbp == NULL) {
 514                 /* no memory */
 515                 return (NULL);
 516         }
 517 
 518         /*
 519          * Prepare a back pointer to the device structure which will be
 520          * refered on freeing the buffer later.
 521          */
 522         rbp->rxb_devp = dp;
 523 
 524         /* allocate a dma handle for rx data buffer */
 525         if ((err = ddi_dma_alloc_handle(dp->dip,
 526             &dp->gc.gc_dma_attr_rxbuf,
 527             (cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT),
 528             NULL, &rbp->rxb_dh)) != DDI_SUCCESS) {
 529 
 530                 cmn_err(CE_WARN,
 531                     "!%s: %s: ddi_dma_alloc_handle:1 failed, err=%d",
 532                     dp->name, __func__, err);
 533 
 534                 kmem_free(rbp, sizeof (struct rxbuf));
 535                 return (NULL);
 536         }
 537 
 538         /* allocate a bounce buffer for rx */
 539         if ((err = ddi_dma_mem_alloc(rbp->rxb_dh,
 540             ROUNDUP(dp->rx_buf_len, IOC_LINESIZE),
 541             &dp->gc.gc_buf_attr,
 542                 /*
 543                  * if the nic requires a header at the top of receive buffers,
 544                  * it may access the rx buffer randomly.
 545                  */
 546             (dp->gc.gc_rx_header_len > 0)
 547             ? DDI_DMA_CONSISTENT : DDI_DMA_STREAMING,
 548             cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
 549             NULL,
 550             &rbp->rxb_buf, &rbp->rxb_buf_len,
 551             &rbp->rxb_bah)) != DDI_SUCCESS) {
 552 
 553                 cmn_err(CE_WARN,
 554                     "!%s: %s: ddi_dma_mem_alloc: failed, err=%d",
 555                     dp->name, __func__, err);
 556 
 557                 ddi_dma_free_handle(&rbp->rxb_dh);
 558                 kmem_free(rbp, sizeof (struct rxbuf));
 559                 return (NULL);
 560         }
 561 
 562         /* Mapin the bounce buffer into the DMA space */
 563         if ((err = ddi_dma_addr_bind_handle(rbp->rxb_dh,
 564             NULL, rbp->rxb_buf, dp->rx_buf_len,
 565             ((dp->gc.gc_rx_header_len > 0)
 566             ?(DDI_DMA_RDWR | DDI_DMA_CONSISTENT)
 567             :(DDI_DMA_READ | DDI_DMA_STREAMING)),
 568             cansleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
 569             NULL,
 570             rbp->rxb_dmacookie,
 571             &count)) != DDI_DMA_MAPPED) {
 572 
 573                 ASSERT(err != DDI_DMA_INUSE);
 574                 DPRINTF(0, (CE_WARN,
 575                     "!%s: ddi_dma_addr_bind_handle: failed, err=%d",
 576                     dp->name, __func__, err));
 577 
 578                 /*
 579                  * we failed to allocate a dma resource
 580                  * for the rx bounce buffer.
 581                  */
 582                 ddi_dma_mem_free(&rbp->rxb_bah);
 583                 ddi_dma_free_handle(&rbp->rxb_dh);
 584                 kmem_free(rbp, sizeof (struct rxbuf));
 585                 return (NULL);
 586         }
 587 
 588         /* correct the rest of the DMA mapping */
 589         for (i = 1; i < count; i++) {
 590                 ddi_dma_nextcookie(rbp->rxb_dh, &rbp->rxb_dmacookie[i]);
 591         }
 592         rbp->rxb_nfrags = count;
 593 
 594         /* Now we successfully prepared an rx buffer */
 595         dp->rx_buf_allocated++;
 596 
 597         return (rbp);
 598 }
 599 
 600 /* ============================================================== */
 601 /*
 602  * memory resource management
 603  */
 604 /* ============================================================== */
 605 static int
 606 gem_alloc_memory(struct gem_dev *dp)
 607 {
 608         caddr_t                 ring;
 609         caddr_t                 buf;
 610         size_t                  req_size;
 611         size_t                  ring_len;
 612         size_t                  buf_len;
 613         ddi_dma_cookie_t        ring_cookie;
 614         ddi_dma_cookie_t        buf_cookie;
 615         uint_t                  count;
 616         int                     i;
 617         int                     err;
 618         struct txbuf            *tbp;
 619         int                     tx_buf_len;
 620         ddi_dma_attr_t          dma_attr_txbounce;
 621 
 622         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
 623 
 624         dp->desc_dma_handle = NULL;
 625         req_size = dp->rx_desc_size + dp->tx_desc_size + dp->gc.gc_io_area_size;
 626 
 627         if (req_size > 0) {
 628                 /*
 629                  * Alloc RX/TX descriptors and a io area.
 630                  */
 631                 if ((err = ddi_dma_alloc_handle(dp->dip,
 632                     &dp->gc.gc_dma_attr_desc,
 633                     DDI_DMA_SLEEP, NULL,
 634                     &dp->desc_dma_handle)) != DDI_SUCCESS) {
 635                         cmn_err(CE_WARN,
 636                             "!%s: %s: ddi_dma_alloc_handle failed: %d",
 637                             dp->name, __func__, err);
 638                         return (ENOMEM);
 639                 }
 640 
 641                 if ((err = ddi_dma_mem_alloc(dp->desc_dma_handle,
 642                     req_size, &dp->gc.gc_desc_attr,
 643                     DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
 644                     &ring, &ring_len,
 645                     &dp->desc_acc_handle)) != DDI_SUCCESS) {
 646                         cmn_err(CE_WARN,
 647                             "!%s: %s: ddi_dma_mem_alloc failed: "
 648                             "ret %d, request size: %d",
 649                             dp->name, __func__, err, (int)req_size);
 650                         ddi_dma_free_handle(&dp->desc_dma_handle);
 651                         return (ENOMEM);
 652                 }
 653 
 654                 if ((err = ddi_dma_addr_bind_handle(dp->desc_dma_handle,
 655                     NULL, ring, ring_len,
 656                     DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
 657                     DDI_DMA_SLEEP, NULL,
 658                     &ring_cookie, &count)) != DDI_SUCCESS) {
 659                         ASSERT(err != DDI_DMA_INUSE);
 660                         cmn_err(CE_WARN,
 661                             "!%s: %s: ddi_dma_addr_bind_handle failed: %d",
 662                             dp->name, __func__, err);
 663                         ddi_dma_mem_free(&dp->desc_acc_handle);
 664                         ddi_dma_free_handle(&dp->desc_dma_handle);
 665                         return (ENOMEM);
 666                 }
 667                 ASSERT(count == 1);
 668 
 669                 /* set base of rx descriptor ring */
 670                 dp->rx_ring = ring;
 671                 dp->rx_ring_dma = ring_cookie.dmac_laddress;
 672 
 673                 /* set base of tx descriptor ring */
 674                 dp->tx_ring = dp->rx_ring + dp->rx_desc_size;
 675                 dp->tx_ring_dma = dp->rx_ring_dma + dp->rx_desc_size;
 676 
 677                 /* set base of io area */
 678                 dp->io_area = dp->tx_ring + dp->tx_desc_size;
 679                 dp->io_area_dma = dp->tx_ring_dma + dp->tx_desc_size;
 680         }
 681 
 682         /*
 683          * Prepare DMA resources for tx packets
 684          */
 685         ASSERT(dp->gc.gc_tx_buf_size > 0);
 686 
 687         /* Special dma attribute for tx bounce buffers */
 688         dma_attr_txbounce = dp->gc.gc_dma_attr_txbuf;
 689         dma_attr_txbounce.dma_attr_sgllen = 1;
 690         dma_attr_txbounce.dma_attr_align =
 691             max(dma_attr_txbounce.dma_attr_align, IOC_LINESIZE);
 692 
 693         /* Size for tx bounce buffers must be max tx packet size. */
 694         tx_buf_len = MAXPKTBUF(dp);
 695         tx_buf_len = ROUNDUP(tx_buf_len, IOC_LINESIZE);
 696 
 697         ASSERT(tx_buf_len >= ETHERMAX+ETHERFCSL);
 698 
 699         for (i = 0, tbp = dp->tx_buf;
 700             i < dp->gc.gc_tx_buf_size; i++, tbp++) {
 701 
 702                 /* setup bounce buffers for tx packets */
 703                 if ((err = ddi_dma_alloc_handle(dp->dip,
 704                     &dma_attr_txbounce,
 705                     DDI_DMA_SLEEP, NULL,
 706                     &tbp->txb_bdh)) != DDI_SUCCESS) {
 707 
 708                         cmn_err(CE_WARN,
 709                     "!%s: %s ddi_dma_alloc_handle for bounce buffer failed:"
 710                             " err=%d, i=%d",
 711                             dp->name, __func__, err, i);
 712                         goto err_alloc_dh;
 713                 }
 714 
 715                 if ((err = ddi_dma_mem_alloc(tbp->txb_bdh,
 716                     tx_buf_len,
 717                     &dp->gc.gc_buf_attr,
 718                     DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
 719                     &buf, &buf_len,
 720                     &tbp->txb_bah)) != DDI_SUCCESS) {
 721                         cmn_err(CE_WARN,
 722                     "!%s: %s: ddi_dma_mem_alloc for bounce buffer failed"
 723                             "ret %d, request size %d",
 724                             dp->name, __func__, err, tx_buf_len);
 725                         ddi_dma_free_handle(&tbp->txb_bdh);
 726                         goto err_alloc_dh;
 727                 }
 728 
 729                 if ((err = ddi_dma_addr_bind_handle(tbp->txb_bdh,
 730                     NULL, buf, buf_len,
 731                     DDI_DMA_WRITE | DDI_DMA_STREAMING,
 732                     DDI_DMA_SLEEP, NULL,
 733                     &buf_cookie, &count)) != DDI_SUCCESS) {
 734                                 ASSERT(err != DDI_DMA_INUSE);
 735                                 cmn_err(CE_WARN,
 736         "!%s: %s: ddi_dma_addr_bind_handle for bounce buffer failed: %d",
 737                                     dp->name, __func__, err);
 738                                 ddi_dma_mem_free(&tbp->txb_bah);
 739                                 ddi_dma_free_handle(&tbp->txb_bdh);
 740                                 goto err_alloc_dh;
 741                 }
 742                 ASSERT(count == 1);
 743                 tbp->txb_buf = buf;
 744                 tbp->txb_buf_dma = buf_cookie.dmac_laddress;
 745         }
 746 
 747         return (0);
 748 
 749 err_alloc_dh:
 750         if (dp->gc.gc_tx_buf_size > 0) {
 751                 while (i-- > 0) {
 752                         (void) ddi_dma_unbind_handle(dp->tx_buf[i].txb_bdh);
 753                         ddi_dma_mem_free(&dp->tx_buf[i].txb_bah);
 754                         ddi_dma_free_handle(&dp->tx_buf[i].txb_bdh);
 755                 }
 756         }
 757 
 758         if (dp->desc_dma_handle) {
 759                 (void) ddi_dma_unbind_handle(dp->desc_dma_handle);
 760                 ddi_dma_mem_free(&dp->desc_acc_handle);
 761                 ddi_dma_free_handle(&dp->desc_dma_handle);
 762                 dp->desc_dma_handle = NULL;
 763         }
 764 
 765         return (ENOMEM);
 766 }
 767 
 768 static void
 769 gem_free_memory(struct gem_dev *dp)
 770 {
 771         int             i;
 772         struct rxbuf    *rbp;
 773         struct txbuf    *tbp;
 774 
 775         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
 776 
 777         /* Free TX/RX descriptors and tx padding buffer */
 778         if (dp->desc_dma_handle) {
 779                 (void) ddi_dma_unbind_handle(dp->desc_dma_handle);
 780                 ddi_dma_mem_free(&dp->desc_acc_handle);
 781                 ddi_dma_free_handle(&dp->desc_dma_handle);
 782                 dp->desc_dma_handle = NULL;
 783         }
 784 
 785         /* Free dma handles for Tx */
 786         for (i = dp->gc.gc_tx_buf_size, tbp = dp->tx_buf; i--; tbp++) {
 787                 /* Free bounce buffer associated to each txbuf */
 788                 (void) ddi_dma_unbind_handle(tbp->txb_bdh);
 789                 ddi_dma_mem_free(&tbp->txb_bah);
 790                 ddi_dma_free_handle(&tbp->txb_bdh);
 791         }
 792 
 793         /* Free rx buffer */
 794         while ((rbp = dp->rx_buf_freelist) != NULL) {
 795 
 796                 ASSERT(dp->rx_buf_freecnt > 0);
 797 
 798                 dp->rx_buf_freelist = rbp->rxb_next;
 799                 dp->rx_buf_freecnt--;
 800 
 801                 /* release DMA mapping */
 802                 ASSERT(rbp->rxb_dh != NULL);
 803 
 804                 /* free dma handles for rx bbuf */
 805                 /* it has dma mapping always */
 806                 ASSERT(rbp->rxb_nfrags > 0);
 807                 (void) ddi_dma_unbind_handle(rbp->rxb_dh);
 808 
 809                 /* free the associated bounce buffer and dma handle */
 810                 ASSERT(rbp->rxb_bah != NULL);
 811                 ddi_dma_mem_free(&rbp->rxb_bah);
 812                 /* free the associated dma handle */
 813                 ddi_dma_free_handle(&rbp->rxb_dh);
 814 
 815                 /* free the base memory of rx buffer management */
 816                 kmem_free(rbp, sizeof (struct rxbuf));
 817         }
 818 }
 819 
 820 /* ============================================================== */
 821 /*
 822  * Rx/Tx descriptor slot management
 823  */
 824 /* ============================================================== */
 825 /*
 826  * Initialize an empty rx ring.
 827  */
 828 static void
 829 gem_init_rx_ring(struct gem_dev *dp)
 830 {
 831         int             i;
 832         int             rx_ring_size = dp->gc.gc_rx_ring_size;
 833 
 834         DPRINTF(1, (CE_CONT, "!%s: %s ring_size:%d, buf_max:%d",
 835             dp->name, __func__,
 836             rx_ring_size, dp->gc.gc_rx_buf_max));
 837 
 838         /* make a physical chain of rx descriptors */
 839         for (i = 0; i < rx_ring_size; i++) {
 840                 (*dp->gc.gc_rx_desc_init)(dp, i);
 841         }
 842         gem_rx_desc_dma_sync(dp, 0, rx_ring_size, DDI_DMA_SYNC_FORDEV);
 843 
 844         dp->rx_active_head = (seqnum_t)0;
 845         dp->rx_active_tail = (seqnum_t)0;
 846 
 847         ASSERT(dp->rx_buf_head == (struct rxbuf *)NULL);
 848         ASSERT(dp->rx_buf_tail == (struct rxbuf *)NULL);
 849 }
 850 
 851 /*
 852  * Prepare rx buffers and put them into the rx buffer/descriptor ring.
 853  */
 854 static void
 855 gem_prepare_rx_buf(struct gem_dev *dp)
 856 {
 857         int             i;
 858         int             nrbuf;
 859         struct rxbuf    *rbp;
 860 
 861         ASSERT(mutex_owned(&dp->intrlock));
 862 
 863         /* Now we have no active buffers in rx ring */
 864 
 865         nrbuf = min(dp->gc.gc_rx_ring_size, dp->gc.gc_rx_buf_max);
 866         for (i = 0; i < nrbuf; i++) {
 867                 if ((rbp = gem_get_rxbuf(dp, B_TRUE)) == NULL) {
 868                         break;
 869                 }
 870                 gem_append_rxbuf(dp, rbp);
 871         }
 872 
 873         gem_rx_desc_dma_sync(dp,
 874             0, dp->gc.gc_rx_ring_size, DDI_DMA_SYNC_FORDEV);
 875 }
 876 
 877 /*
 878  * Reclaim active rx buffers in rx buffer ring.
 879  */
 880 static void
 881 gem_clean_rx_buf(struct gem_dev *dp)
 882 {
 883         int             i;
 884         struct rxbuf    *rbp;
 885         int             rx_ring_size = dp->gc.gc_rx_ring_size;
 886 #ifdef GEM_DEBUG_LEVEL
 887         int             total;
 888 #endif
 889         ASSERT(mutex_owned(&dp->intrlock));
 890 
 891         DPRINTF(2, (CE_CONT, "!%s: %s: %d buffers are free",
 892             dp->name, __func__, dp->rx_buf_freecnt));
 893         /*
 894          * clean up HW descriptors
 895          */
 896         for (i = 0; i < rx_ring_size; i++) {
 897                 (*dp->gc.gc_rx_desc_clean)(dp, i);
 898         }
 899         gem_rx_desc_dma_sync(dp, 0, rx_ring_size, DDI_DMA_SYNC_FORDEV);
 900 
 901 #ifdef GEM_DEBUG_LEVEL
 902         total = 0;
 903 #endif
 904         /*
 905          * Reclaim allocated rx buffers
 906          */
 907         while ((rbp = dp->rx_buf_head) != NULL) {
 908 #ifdef GEM_DEBUG_LEVEL
 909                 total++;
 910 #endif
 911                 /* remove the first one from rx buffer list */
 912                 dp->rx_buf_head = rbp->rxb_next;
 913 
 914                 /* recycle the rxbuf */
 915                 gem_free_rxbuf(rbp);
 916         }
 917         dp->rx_buf_tail = (struct rxbuf *)NULL;
 918 
 919         DPRINTF(2, (CE_CONT,
 920             "!%s: %s: %d buffers freeed, total: %d free",
 921             dp->name, __func__, total, dp->rx_buf_freecnt));
 922 }
 923 
 924 /*
 925  * Initialize an empty transmit buffer/descriptor ring
 926  */
 927 static void
 928 gem_init_tx_ring(struct gem_dev *dp)
 929 {
 930         int             i;
 931         int             tx_buf_size = dp->gc.gc_tx_buf_size;
 932         int             tx_ring_size = dp->gc.gc_tx_ring_size;
 933 
 934         DPRINTF(2, (CE_CONT, "!%s: %s: ring_size:%d, buf_size:%d",
 935             dp->name, __func__,
 936             dp->gc.gc_tx_ring_size, dp->gc.gc_tx_buf_size));
 937 
 938         ASSERT(!dp->mac_active);
 939 
 940         /* initialize active list and free list */
 941         dp->tx_slots_base =
 942             SLOT(dp->tx_slots_base + dp->tx_softq_head, tx_buf_size);
 943         dp->tx_softq_tail -= dp->tx_softq_head;
 944         dp->tx_softq_head = (seqnum_t)0;
 945 
 946         dp->tx_active_head = dp->tx_softq_head;
 947         dp->tx_active_tail = dp->tx_softq_head;
 948 
 949         dp->tx_free_head   = dp->tx_softq_tail;
 950         dp->tx_free_tail   = dp->gc.gc_tx_buf_limit;
 951 
 952         dp->tx_desc_head = (seqnum_t)0;
 953         dp->tx_desc_tail = (seqnum_t)0;
 954         dp->tx_desc_intr = (seqnum_t)0;
 955 
 956         for (i = 0; i < tx_ring_size; i++) {
 957                 (*dp->gc.gc_tx_desc_init)(dp, i);
 958         }
 959         gem_tx_desc_dma_sync(dp, 0, tx_ring_size, DDI_DMA_SYNC_FORDEV);
 960 }
 961 
 962 __INLINE__
 963 static void
 964 gem_txbuf_free_dma_resources(struct txbuf *tbp)
 965 {
 966         if (tbp->txb_mp) {
 967                 freemsg(tbp->txb_mp);
 968                 tbp->txb_mp = NULL;
 969         }
 970         tbp->txb_nfrags = 0;
 971         tbp->txb_flag = 0;
 972 }
 973 #pragma inline(gem_txbuf_free_dma_resources)
 974 
 975 /*
 976  * reclaim active tx buffers and reset positions in tx rings.
 977  */
 978 static void
 979 gem_clean_tx_buf(struct gem_dev *dp)
 980 {
 981         int             i;
 982         seqnum_t        head;
 983         seqnum_t        tail;
 984         seqnum_t        sn;
 985         struct txbuf    *tbp;
 986         int             tx_ring_size = dp->gc.gc_tx_ring_size;
 987 #ifdef GEM_DEBUG_LEVEL
 988         int             err;
 989 #endif
 990 
 991         ASSERT(!dp->mac_active);
 992         ASSERT(dp->tx_busy == 0);
 993         ASSERT(dp->tx_softq_tail == dp->tx_free_head);
 994 
 995         /*
 996          * clean up all HW descriptors
 997          */
 998         for (i = 0; i < tx_ring_size; i++) {
 999                 (*dp->gc.gc_tx_desc_clean)(dp, i);
1000         }
1001         gem_tx_desc_dma_sync(dp, 0, tx_ring_size, DDI_DMA_SYNC_FORDEV);
1002 
1003         /* dequeue all active and loaded buffers */
1004         head = dp->tx_active_head;
1005         tail = dp->tx_softq_tail;
1006 
1007         ASSERT(dp->tx_free_head - head >= 0);
1008         tbp = GET_TXBUF(dp, head);
1009         for (sn = head; sn != tail; sn++) {
1010                 gem_txbuf_free_dma_resources(tbp);
1011                 ASSERT(tbp->txb_mp == NULL);
1012                 dp->stats.errxmt++;
1013                 tbp = tbp->txb_next;
1014         }
1015 
1016 #ifdef GEM_DEBUG_LEVEL
1017         /* ensure no dma resources for tx are not in use now */
1018         err = 0;
1019         while (sn != head + dp->gc.gc_tx_buf_size) {
1020                 if (tbp->txb_mp || tbp->txb_nfrags) {
1021                         DPRINTF(0, (CE_CONT,
1022                             "%s: %s: sn:%d[%d] mp:%p nfrags:%d",
1023                             dp->name, __func__,
1024                             sn, SLOT(sn, dp->gc.gc_tx_buf_size),
1025                             tbp->txb_mp, tbp->txb_nfrags));
1026                         err = 1;
1027                 }
1028                 sn++;
1029                 tbp = tbp->txb_next;
1030         }
1031 
1032         if (err) {
1033                 gem_dump_txbuf(dp, CE_WARN,
1034                     "gem_clean_tx_buf: tbp->txb_mp != NULL");
1035         }
1036 #endif
1037         /* recycle buffers, now no active tx buffers in the ring */
1038         dp->tx_free_tail += tail - head;
1039         ASSERT(dp->tx_free_tail == dp->tx_free_head + dp->gc.gc_tx_buf_limit);
1040 
1041         /* fix positions in tx buffer rings */
1042         dp->tx_active_head = dp->tx_free_head;
1043         dp->tx_active_tail = dp->tx_free_head;
1044         dp->tx_softq_head  = dp->tx_free_head;
1045         dp->tx_softq_tail  = dp->tx_free_head;
1046 }
1047 
1048 /*
1049  * Reclaim transmitted buffers from tx buffer/descriptor ring.
1050  */
1051 __INLINE__ int
1052 gem_reclaim_txbuf(struct gem_dev *dp)
1053 {
1054         struct txbuf    *tbp;
1055         uint_t          txstat;
1056         int             err = GEM_SUCCESS;
1057         seqnum_t        head;
1058         seqnum_t        tail;
1059         seqnum_t        sn;
1060         seqnum_t        desc_head;
1061         int             tx_ring_size = dp->gc.gc_tx_ring_size;
1062         uint_t (*tx_desc_stat)(struct gem_dev *dp,
1063             int slot, int ndesc) = dp->gc.gc_tx_desc_stat;
1064         clock_t         now;
1065 
1066         now = ddi_get_lbolt();
1067         if (now == (clock_t)0) {
1068                 /* make non-zero timestamp */
1069                 now--;
1070         }
1071 
1072         mutex_enter(&dp->xmitlock);
1073 
1074         head = dp->tx_active_head;
1075         tail = dp->tx_active_tail;
1076 
1077 #if GEM_DEBUG_LEVEL > 2
1078         if (head != tail) {
1079                 cmn_err(CE_CONT, "!%s: %s: "
1080                     "testing active_head:%d[%d], active_tail:%d[%d]",
1081                     dp->name, __func__,
1082                     head, SLOT(head, dp->gc.gc_tx_buf_size),
1083                     tail, SLOT(tail, dp->gc.gc_tx_buf_size));
1084         }
1085 #endif
1086 #ifdef DEBUG
1087         if (dp->tx_reclaim_busy == 0) {
1088                 /* check tx buffer management consistency */
1089                 ASSERT(dp->tx_free_tail - dp->tx_active_head
1090                     == dp->gc.gc_tx_buf_limit);
1091                 /* EMPTY */
1092         }
1093 #endif
1094         dp->tx_reclaim_busy++;
1095 
1096         /* sync all active HW descriptors */
1097         gem_tx_desc_dma_sync(dp,
1098             SLOT(dp->tx_desc_head, tx_ring_size),
1099             dp->tx_desc_tail - dp->tx_desc_head,
1100             DDI_DMA_SYNC_FORKERNEL);
1101 
1102         tbp = GET_TXBUF(dp, head);
1103         desc_head = dp->tx_desc_head;
1104         for (sn = head; sn != tail;
1105             dp->tx_active_head = (++sn), tbp = tbp->txb_next) {
1106                 int     ndescs;
1107 
1108                 ASSERT(tbp->txb_desc == desc_head);
1109 
1110                 ndescs = tbp->txb_ndescs;
1111                 if (ndescs == 0) {
1112                         /* skip errored descriptors */
1113                         continue;
1114                 }
1115                 txstat = (*tx_desc_stat)(dp,
1116                     SLOT(tbp->txb_desc, tx_ring_size), ndescs);
1117 
1118                 if (txstat == 0) {
1119                         /* not transmitted yet */
1120                         break;
1121                 }
1122 
1123                 if (!dp->tx_blocked && (tbp->txb_flag & GEM_TXFLAG_INTR)) {
1124                         dp->tx_blocked = now;
1125                 }
1126 
1127                 ASSERT(txstat & (GEM_TX_DONE | GEM_TX_ERR));
1128 
1129                 if (txstat & GEM_TX_ERR) {
1130                         err = GEM_FAILURE;
1131                         cmn_err(CE_WARN, "!%s: tx error at desc %d[%d]",
1132                             dp->name, sn, SLOT(sn, tx_ring_size));
1133                 }
1134 #if GEM_DEBUG_LEVEL > 4
1135                 if (now - tbp->txb_stime >= 50) {
1136                         cmn_err(CE_WARN, "!%s: tx delay while %d mS",
1137                             dp->name, (now - tbp->txb_stime)*10);
1138                 }
1139 #endif
1140                 /* free transmitted descriptors */
1141                 desc_head += ndescs;
1142         }
1143 
1144         if (dp->tx_desc_head != desc_head) {
1145                 /* we have reclaimed one or more tx buffers */
1146                 dp->tx_desc_head = desc_head;
1147 
1148                 /* If we passed the next interrupt position, update it */
1149                 if (desc_head - dp->tx_desc_intr > 0) {
1150                         dp->tx_desc_intr = desc_head;
1151                 }
1152         }
1153         mutex_exit(&dp->xmitlock);
1154 
1155         /* free dma mapping resources associated with transmitted tx buffers */
1156         tbp = GET_TXBUF(dp, head);
1157         tail = sn;
1158 #if GEM_DEBUG_LEVEL > 2
1159         if (head != tail) {
1160                 cmn_err(CE_CONT, "%s: freeing head:%d[%d], tail:%d[%d]",
1161                     __func__,
1162                     head, SLOT(head, dp->gc.gc_tx_buf_size),
1163                     tail, SLOT(tail, dp->gc.gc_tx_buf_size));
1164         }
1165 #endif
1166         for (sn = head; sn != tail; sn++, tbp = tbp->txb_next) {
1167                 gem_txbuf_free_dma_resources(tbp);
1168         }
1169 
1170         /* recycle the tx buffers */
1171         mutex_enter(&dp->xmitlock);
1172         if (--dp->tx_reclaim_busy == 0) {
1173                 /* we are the last thread who can update free tail */
1174 #if GEM_DEBUG_LEVEL > 4
1175                 /* check all resouces have been deallocated */
1176                 sn = dp->tx_free_tail;
1177                 tbp = GET_TXBUF(dp, new_tail);
1178                 while (sn != dp->tx_active_head + dp->gc.gc_tx_buf_limit) {
1179                         if (tbp->txb_nfrags) {
1180                                 /* in use */
1181                                 break;
1182                         }
1183                         ASSERT(tbp->txb_mp == NULL);
1184                         tbp = tbp->txb_next;
1185                         sn++;
1186                 }
1187                 ASSERT(dp->tx_active_head + dp->gc.gc_tx_buf_limit == sn);
1188 #endif
1189                 dp->tx_free_tail =
1190                     dp->tx_active_head + dp->gc.gc_tx_buf_limit;
1191         }
1192         if (!dp->mac_active) {
1193                 /* someone may be waiting for me. */
1194                 cv_broadcast(&dp->tx_drain_cv);
1195         }
1196 #if GEM_DEBUG_LEVEL > 2
1197         cmn_err(CE_CONT, "!%s: %s: called, "
1198             "free_head:%d free_tail:%d(+%d) added:%d",
1199             dp->name, __func__,
1200             dp->tx_free_head, dp->tx_free_tail,
1201             dp->tx_free_tail - dp->tx_free_head, tail - head);
1202 #endif
1203         mutex_exit(&dp->xmitlock);
1204 
1205         return (err);
1206 }
1207 #pragma inline(gem_reclaim_txbuf)
1208 
1209 
1210 /*
1211  * Make tx descriptors in out-of-order manner
1212  */
1213 static void
1214 gem_tx_load_descs_oo(struct gem_dev *dp,
1215         seqnum_t start_slot, seqnum_t end_slot, uint64_t flags)
1216 {
1217         seqnum_t        sn;
1218         struct txbuf    *tbp;
1219         int     tx_ring_size = dp->gc.gc_tx_ring_size;
1220         int     (*tx_desc_write)
1221             (struct gem_dev *dp, int slot,
1222             ddi_dma_cookie_t *dmacookie,
1223             int frags, uint64_t flag) = dp->gc.gc_tx_desc_write;
1224         clock_t now = ddi_get_lbolt();
1225 
1226         sn = start_slot;
1227         tbp = GET_TXBUF(dp, sn);
1228         do {
1229 #if GEM_DEBUG_LEVEL > 1
1230                 if (dp->tx_cnt < 100) {
1231                         dp->tx_cnt++;
1232                         flags |= GEM_TXFLAG_INTR;
1233                 }
1234 #endif
1235                 /* write a tx descriptor */
1236                 tbp->txb_desc = sn;
1237                 tbp->txb_ndescs = (*tx_desc_write)(dp,
1238                     SLOT(sn, tx_ring_size),
1239                     tbp->txb_dmacookie,
1240                     tbp->txb_nfrags, flags | tbp->txb_flag);
1241                 tbp->txb_stime = now;
1242                 ASSERT(tbp->txb_ndescs == 1);
1243 
1244                 flags = 0;
1245                 sn++;
1246                 tbp = tbp->txb_next;
1247         } while (sn != end_slot);
1248 }
1249 
1250 __INLINE__
1251 static size_t
1252 gem_setup_txbuf_copy(struct gem_dev *dp, mblk_t *mp, struct txbuf *tbp)
1253 {
1254         size_t                  min_pkt;
1255         caddr_t                 bp;
1256         size_t                  off;
1257         mblk_t                  *tp;
1258         size_t                  len;
1259         uint64_t                flag;
1260 
1261         ASSERT(tbp->txb_mp == NULL);
1262 
1263         /* we use bounce buffer for the packet */
1264         min_pkt = ETHERMIN;
1265         bp = tbp->txb_buf;
1266         off = 0;
1267         tp = mp;
1268 
1269         flag = tbp->txb_flag;
1270         if (flag & GEM_TXFLAG_SWVTAG) {
1271                 /* need to increase min packet size */
1272                 min_pkt += VTAG_SIZE;
1273                 ASSERT((flag & GEM_TXFLAG_VTAG) == 0);
1274         }
1275 
1276         /* copy the rest */
1277         for (; tp; tp = tp->b_cont) {
1278                 if ((len = (long)tp->b_wptr - (long)tp->b_rptr) > 0) {
1279                         bcopy(tp->b_rptr, &bp[off], len);
1280                         off += len;
1281                 }
1282         }
1283 
1284         if (off < min_pkt &&
1285             (min_pkt > ETHERMIN || !dp->gc.gc_tx_auto_pad)) {
1286                 /*
1287                  * Extend the packet to minimum packet size explicitly.
1288                  * For software vlan packets, we shouldn't use tx autopad
1289                  * function because nics may not be aware of vlan.
1290                  * we must keep 46 octet of payload even if we use vlan.
1291                  */
1292                 bzero(&bp[off], min_pkt - off);
1293                 off = min_pkt;
1294         }
1295 
1296         (void) ddi_dma_sync(tbp->txb_bdh, (off_t)0, off, DDI_DMA_SYNC_FORDEV);
1297 
1298         tbp->txb_dmacookie[0].dmac_laddress = tbp->txb_buf_dma;
1299         tbp->txb_dmacookie[0].dmac_size = off;
1300 
1301         DPRINTF(2, (CE_CONT,
1302             "!%s: %s: copy: addr:0x%llx len:0x%x, vtag:0x%04x, min_pkt:%d",
1303             dp->name, __func__,
1304             tbp->txb_dmacookie[0].dmac_laddress,
1305             tbp->txb_dmacookie[0].dmac_size,
1306             (flag & GEM_TXFLAG_VTAG) >> GEM_TXFLAG_VTAG_SHIFT,
1307             min_pkt));
1308 
1309         /* save misc info */
1310         tbp->txb_mp = mp;
1311         tbp->txb_nfrags = 1;
1312 #ifdef DEBUG_MULTIFRAGS
1313         if (dp->gc.gc_tx_max_frags >= 3 &&
1314             tbp->txb_dmacookie[0].dmac_size > 16*3) {
1315                 tbp->txb_dmacookie[1].dmac_laddress =
1316                     tbp->txb_dmacookie[0].dmac_laddress + 16;
1317                 tbp->txb_dmacookie[2].dmac_laddress =
1318                     tbp->txb_dmacookie[1].dmac_laddress + 16;
1319 
1320                 tbp->txb_dmacookie[2].dmac_size =
1321                     tbp->txb_dmacookie[0].dmac_size - 16*2;
1322                 tbp->txb_dmacookie[1].dmac_size = 16;
1323                 tbp->txb_dmacookie[0].dmac_size = 16;
1324                 tbp->txb_nfrags  = 3;
1325         }
1326 #endif
1327         return (off);
1328 }
1329 #pragma inline(gem_setup_txbuf_copy)
1330 
1331 __INLINE__
1332 static void
1333 gem_tx_start_unit(struct gem_dev *dp)
1334 {
1335         seqnum_t        head;
1336         seqnum_t        tail;
1337         struct txbuf    *tbp_head;
1338         struct txbuf    *tbp_tail;
1339 
1340         /* update HW descriptors from soft queue */
1341         ASSERT(mutex_owned(&dp->xmitlock));
1342         ASSERT(dp->tx_softq_head == dp->tx_active_tail);
1343 
1344         head = dp->tx_softq_head;
1345         tail = dp->tx_softq_tail;
1346 
1347         DPRINTF(1, (CE_CONT,
1348             "%s: %s: called, softq %d %d[+%d], desc %d %d[+%d]",
1349             dp->name, __func__, head, tail, tail - head,
1350             dp->tx_desc_head, dp->tx_desc_tail,
1351             dp->tx_desc_tail - dp->tx_desc_head));
1352 
1353         ASSERT(tail - head > 0);
1354 
1355         dp->tx_desc_tail = tail;
1356 
1357         tbp_head = GET_TXBUF(dp, head);
1358         tbp_tail = GET_TXBUF(dp, tail - 1);
1359 
1360         ASSERT(tbp_tail->txb_desc + tbp_tail->txb_ndescs == dp->tx_desc_tail);
1361 
1362         dp->gc.gc_tx_start(dp,
1363             SLOT(tbp_head->txb_desc, dp->gc.gc_tx_ring_size),
1364             tbp_tail->txb_desc + tbp_tail->txb_ndescs - tbp_head->txb_desc);
1365 
1366         /* advance softq head and active tail */
1367         dp->tx_softq_head = dp->tx_active_tail = tail;
1368 }
1369 #pragma inline(gem_tx_start_unit)
1370 
1371 #ifdef GEM_DEBUG_LEVEL
1372 static int gem_send_cnt[10];
1373 #endif
1374 #define PKT_MIN_SIZE    (sizeof (struct ether_header) + 10 + VTAG_SIZE)
1375 #define EHLEN   (sizeof (struct ether_header))
1376 /*
1377  * check ether packet type and ip protocol
1378  */
1379 static uint64_t
1380 gem_txbuf_options(struct gem_dev *dp, mblk_t *mp, uint8_t *bp)
1381 {
1382         mblk_t          *tp;
1383         ssize_t         len;
1384         uint_t          vtag;
1385         int             off;
1386         uint64_t        flag;
1387 
1388         flag = 0ULL;
1389 
1390         /*
1391          * prepare continuous header of the packet for protocol analysis
1392          */
1393         if ((long)mp->b_wptr - (long)mp->b_rptr < PKT_MIN_SIZE) {
1394                 /* we use work buffer to copy mblk */
1395                 for (tp = mp, off = 0;
1396                     tp && (off < PKT_MIN_SIZE);
1397                     tp = tp->b_cont, off += len) {
1398                         len = (long)tp->b_wptr - (long)tp->b_rptr;
1399                         len = min(len, PKT_MIN_SIZE - off);
1400                         bcopy(tp->b_rptr, &bp[off], len);
1401                 }
1402         } else {
1403                 /* we can use mblk without copy */
1404                 bp = mp->b_rptr;
1405         }
1406 
1407         /* process vlan tag for GLD v3 */
1408         if (GET_NET16(&bp[VTAG_OFF]) == VTAG_TPID) {
1409                 if (dp->misc_flag & GEM_VLAN_HARD) {
1410                         vtag = GET_NET16(&bp[VTAG_OFF + 2]);
1411                         ASSERT(vtag);
1412                         flag |= vtag << GEM_TXFLAG_VTAG_SHIFT;
1413                 } else {
1414                         flag |= GEM_TXFLAG_SWVTAG;
1415                 }
1416         }
1417         return (flag);
1418 }
1419 #undef EHLEN
1420 #undef PKT_MIN_SIZE
1421 /*
1422  * gem_send_common is an exported function because hw depend routines may
1423  * use it for sending control frames like setup frames for 2114x chipset.
1424  */
1425 mblk_t *
1426 gem_send_common(struct gem_dev *dp, mblk_t *mp_head, uint32_t flags)
1427 {
1428         int                     nmblk;
1429         int                     avail;
1430         mblk_t                  *tp;
1431         mblk_t                  *mp;
1432         int                     i;
1433         struct txbuf            *tbp;
1434         seqnum_t                head;
1435         uint64_t                load_flags;
1436         uint64_t                len_total = 0;
1437         uint32_t                bcast = 0;
1438         uint32_t                mcast = 0;
1439 
1440         ASSERT(mp_head != NULL);
1441 
1442         mp = mp_head;
1443         nmblk = 1;
1444         while ((mp = mp->b_next) != NULL) {
1445                 nmblk++;
1446         }
1447 #ifdef GEM_DEBUG_LEVEL
1448         gem_send_cnt[0]++;
1449         gem_send_cnt[min(nmblk, 9)]++;
1450 #endif
1451         /*
1452          * Aquire resources
1453          */
1454         mutex_enter(&dp->xmitlock);
1455         if (dp->mac_suspended) {
1456                 mutex_exit(&dp->xmitlock);
1457                 mp = mp_head;
1458                 while (mp) {
1459                         tp = mp->b_next;
1460                         freemsg(mp);
1461                         mp = tp;
1462                 }
1463                 return (NULL);
1464         }
1465 
1466         if (!dp->mac_active && (flags & GEM_SEND_CTRL) == 0) {
1467                 /* don't send data packets while mac isn't active */
1468                 /* XXX - should we discard packets? */
1469                 mutex_exit(&dp->xmitlock);
1470                 return (mp_head);
1471         }
1472 
1473         /* allocate free slots */
1474         head = dp->tx_free_head;
1475         avail = dp->tx_free_tail - head;
1476 
1477         DPRINTF(2, (CE_CONT,
1478             "!%s: %s: called, free_head:%d free_tail:%d(+%d) req:%d",
1479             dp->name, __func__,
1480             dp->tx_free_head, dp->tx_free_tail, avail, nmblk));
1481 
1482         avail = min(avail, dp->tx_max_packets);
1483 
1484         if (nmblk > avail) {
1485                 if (avail == 0) {
1486                         /* no resources; short cut */
1487                         DPRINTF(2, (CE_CONT, "!%s: no resources", __func__));
1488                         dp->tx_max_packets = max(dp->tx_max_packets - 1, 1);
1489                         goto done;
1490                 }
1491                 nmblk = avail;
1492         }
1493 
1494         dp->tx_free_head = head + nmblk;
1495         load_flags = ((dp->tx_busy++) == 0) ? GEM_TXFLAG_HEAD : 0;
1496 
1497         /* update last interrupt position if tx buffers exhaust.  */
1498         if (nmblk == avail) {
1499                 tbp = GET_TXBUF(dp, head + avail - 1);
1500                 tbp->txb_flag = GEM_TXFLAG_INTR;
1501                 dp->tx_desc_intr = head + avail;
1502         }
1503         mutex_exit(&dp->xmitlock);
1504 
1505         tbp = GET_TXBUF(dp, head);
1506 
1507         for (i = nmblk; i > 0; i--, tbp = tbp->txb_next) {
1508                 uint8_t         *bp;
1509                 uint64_t        txflag;
1510 
1511                 /* remove one from the mblk list */
1512                 ASSERT(mp_head != NULL);
1513                 mp = mp_head;
1514                 mp_head = mp_head->b_next;
1515                 mp->b_next = NULL;
1516 
1517                 /* statistics for non-unicast packets */
1518                 bp = mp->b_rptr;
1519                 if ((bp[0] & 1) && (flags & GEM_SEND_CTRL) == 0) {
1520                         if (bcmp(bp, gem_etherbroadcastaddr.ether_addr_octet,
1521                             ETHERADDRL) == 0) {
1522                                 bcast++;
1523                         } else {
1524                                 mcast++;
1525                         }
1526                 }
1527 
1528                 /* save misc info */
1529                 txflag = tbp->txb_flag;
1530                 txflag |= (flags & GEM_SEND_CTRL) << GEM_TXFLAG_PRIVATE_SHIFT;
1531                 txflag |= gem_txbuf_options(dp, mp, (uint8_t *)tbp->txb_buf);
1532                 tbp->txb_flag = txflag;
1533 
1534                 len_total += gem_setup_txbuf_copy(dp, mp, tbp);
1535         }
1536 
1537         (void) gem_tx_load_descs_oo(dp, head, head + nmblk, load_flags);
1538 
1539         /* Append the tbp at the tail of the active tx buffer list */
1540         mutex_enter(&dp->xmitlock);
1541 
1542         if ((--dp->tx_busy) == 0) {
1543                 /* extend the tail of softq, as new packets have been ready. */
1544                 dp->tx_softq_tail = dp->tx_free_head;
1545 
1546                 if (!dp->mac_active && (flags & GEM_SEND_CTRL) == 0) {
1547                         /*
1548                          * The device status has changed while we are
1549                          * preparing tx buf.
1550                          * As we are the last one that make tx non-busy.
1551                          * wake up someone who may wait for us.
1552                          */
1553                         cv_broadcast(&dp->tx_drain_cv);
1554                 } else {
1555                         ASSERT(dp->tx_softq_tail - dp->tx_softq_head > 0);
1556                         gem_tx_start_unit(dp);
1557                 }
1558         }
1559         dp->stats.obytes += len_total;
1560         dp->stats.opackets += nmblk;
1561         dp->stats.obcast += bcast;
1562         dp->stats.omcast += mcast;
1563 done:
1564         mutex_exit(&dp->xmitlock);
1565 
1566         return (mp_head);
1567 }
1568 
1569 /* ========================================================== */
1570 /*
1571  * error detection and restart routines
1572  */
1573 /* ========================================================== */
1574 int
1575 gem_restart_nic(struct gem_dev *dp, uint_t flags)
1576 {
1577         ASSERT(mutex_owned(&dp->intrlock));
1578 
1579         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
1580 #ifdef GEM_DEBUG_LEVEL
1581 #if GEM_DEBUG_LEVEL > 1
1582         gem_dump_txbuf(dp, CE_CONT, "gem_restart_nic");
1583 #endif
1584 #endif
1585 
1586         if (dp->mac_suspended) {
1587                 /* should we return GEM_FAILURE ? */
1588                 return (GEM_FAILURE);
1589         }
1590 
1591         /*
1592          * We should avoid calling any routines except xxx_chip_reset
1593          * when we are resuming the system.
1594          */
1595         if (dp->mac_active) {
1596                 if (flags & GEM_RESTART_KEEP_BUF) {
1597                         /* stop rx gracefully */
1598                         dp->rxmode &= ~RXMODE_ENABLE;
1599                         (void) (*dp->gc.gc_set_rx_filter)(dp);
1600                 }
1601                 (void) gem_mac_stop(dp, flags);
1602         }
1603 
1604         /* reset the chip. */
1605         if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
1606                 cmn_err(CE_WARN, "%s: %s: failed to reset chip",
1607                     dp->name, __func__);
1608                 goto err;
1609         }
1610 
1611         if (gem_mac_init(dp) != GEM_SUCCESS) {
1612                 goto err;
1613         }
1614 
1615         /* setup media mode if the link have been up */
1616         if (dp->mii_state == MII_STATE_LINKUP) {
1617                 if ((dp->gc.gc_set_media)(dp) != GEM_SUCCESS) {
1618                         goto err;
1619                 }
1620         }
1621 
1622         /* setup mac address and enable rx filter */
1623         dp->rxmode |= RXMODE_ENABLE;
1624         if ((*dp->gc.gc_set_rx_filter)(dp) != GEM_SUCCESS) {
1625                 goto err;
1626         }
1627 
1628         /*
1629          * XXX - a panic happened because of linkdown.
1630          * We must check mii_state here, because the link can be down just
1631          * before the restart event happen. If the link is down now,
1632          * gem_mac_start() will be called from gem_mii_link_check() when
1633          * the link become up later.
1634          */
1635         if (dp->mii_state == MII_STATE_LINKUP) {
1636                 /* restart the nic */
1637                 ASSERT(!dp->mac_active);
1638                 (void) gem_mac_start(dp);
1639         }
1640         return (GEM_SUCCESS);
1641 err:
1642         return (GEM_FAILURE);
1643 }
1644 
1645 
1646 static void
1647 gem_tx_timeout(struct gem_dev *dp)
1648 {
1649         clock_t         now;
1650         boolean_t       tx_sched;
1651         struct txbuf    *tbp;
1652 
1653         mutex_enter(&dp->intrlock);
1654 
1655         tx_sched = B_FALSE;
1656         now = ddi_get_lbolt();
1657 
1658         mutex_enter(&dp->xmitlock);
1659         if (!dp->mac_active || dp->mii_state != MII_STATE_LINKUP) {
1660                 mutex_exit(&dp->xmitlock);
1661                 goto schedule_next;
1662         }
1663         mutex_exit(&dp->xmitlock);
1664 
1665         /* reclaim transmitted buffers to check the trasmitter hangs or not. */
1666         if (gem_reclaim_txbuf(dp) != GEM_SUCCESS) {
1667                 /* tx error happened, reset transmitter in the chip */
1668                 (void) gem_restart_nic(dp, 0);
1669                 tx_sched = B_TRUE;
1670                 dp->tx_blocked = (clock_t)0;
1671 
1672                 goto schedule_next;
1673         }
1674 
1675         mutex_enter(&dp->xmitlock);
1676         /* check if the transmitter thread is stuck */
1677         if (dp->tx_active_head == dp->tx_active_tail) {
1678                 /* no tx buffer is loaded to the nic */
1679                 if (dp->tx_blocked &&
1680                     now - dp->tx_blocked > dp->gc.gc_tx_timeout_interval) {
1681                         gem_dump_txbuf(dp, CE_WARN,
1682                             "gem_tx_timeout: tx blocked");
1683                         tx_sched = B_TRUE;
1684                         dp->tx_blocked = (clock_t)0;
1685                 }
1686                 mutex_exit(&dp->xmitlock);
1687                 goto schedule_next;
1688         }
1689 
1690         tbp = GET_TXBUF(dp, dp->tx_active_head);
1691         if (now - tbp->txb_stime < dp->gc.gc_tx_timeout) {
1692                 mutex_exit(&dp->xmitlock);
1693                 goto schedule_next;
1694         }
1695         mutex_exit(&dp->xmitlock);
1696 
1697         gem_dump_txbuf(dp, CE_WARN, "gem_tx_timeout: tx timeout");
1698 
1699         /* discard untransmitted packet and restart tx.  */
1700         (void) gem_restart_nic(dp, GEM_RESTART_NOWAIT);
1701         tx_sched = B_TRUE;
1702         dp->tx_blocked = (clock_t)0;
1703 
1704 schedule_next:
1705         mutex_exit(&dp->intrlock);
1706 
1707         /* restart the downstream if needed */
1708         if (tx_sched) {
1709                 mac_tx_update(dp->mh);
1710         }
1711 
1712         DPRINTF(4, (CE_CONT,
1713             "!%s: blocked:%d active_head:%d active_tail:%d desc_intr:%d",
1714             dp->name, BOOLEAN(dp->tx_blocked),
1715             dp->tx_active_head, dp->tx_active_tail, dp->tx_desc_intr));
1716         dp->timeout_id =
1717             timeout((void (*)(void *))gem_tx_timeout,
1718             (void *)dp, dp->gc.gc_tx_timeout_interval);
1719 }
1720 
1721 /* ================================================================== */
1722 /*
1723  * Interrupt handler
1724  */
1725 /* ================================================================== */
1726 __INLINE__
1727 static void
1728 gem_append_rxbuf(struct gem_dev *dp, struct rxbuf *rbp_head)
1729 {
1730         struct rxbuf    *rbp;
1731         seqnum_t        tail;
1732         int             rx_ring_size = dp->gc.gc_rx_ring_size;
1733 
1734         ASSERT(rbp_head != NULL);
1735         ASSERT(mutex_owned(&dp->intrlock));
1736 
1737         DPRINTF(3, (CE_CONT, "!%s: %s: slot_head:%d, slot_tail:%d",
1738             dp->name, __func__, dp->rx_active_head, dp->rx_active_tail));
1739 
1740         /*
1741          * Add new buffers into active rx buffer list
1742          */
1743         if (dp->rx_buf_head == NULL) {
1744                 dp->rx_buf_head = rbp_head;
1745                 ASSERT(dp->rx_buf_tail == NULL);
1746         } else {
1747                 dp->rx_buf_tail->rxb_next = rbp_head;
1748         }
1749 
1750         tail = dp->rx_active_tail;
1751         for (rbp = rbp_head; rbp; rbp = rbp->rxb_next) {
1752                 /* need to notify the tail for the lower layer */
1753                 dp->rx_buf_tail = rbp;
1754 
1755                 dp->gc.gc_rx_desc_write(dp,
1756                     SLOT(tail, rx_ring_size),
1757                     rbp->rxb_dmacookie,
1758                     rbp->rxb_nfrags);
1759 
1760                 dp->rx_active_tail = tail = tail + 1;
1761         }
1762 }
1763 #pragma inline(gem_append_rxbuf)
1764 
1765 mblk_t *
1766 gem_get_packet_default(struct gem_dev *dp, struct rxbuf *rbp, size_t len)
1767 {
1768         int             rx_header_len = dp->gc.gc_rx_header_len;
1769         uint8_t         *bp;
1770         mblk_t          *mp;
1771 
1772         /* allocate a new mblk */
1773         if (mp = allocb(len + VTAG_SIZE, BPRI_MED)) {
1774                 ASSERT(mp->b_next == NULL);
1775                 ASSERT(mp->b_cont == NULL);
1776 
1777                 mp->b_rptr += VTAG_SIZE;
1778                 bp = mp->b_rptr;
1779                 mp->b_wptr = bp + len;
1780 
1781                 /*
1782                  * flush the range of the entire buffer to invalidate
1783                  * all of corresponding dirty entries in iocache.
1784                  */
1785                 (void) ddi_dma_sync(rbp->rxb_dh, rx_header_len,
1786                     0, DDI_DMA_SYNC_FORKERNEL);
1787 
1788                 bcopy(rbp->rxb_buf + rx_header_len, bp, len);
1789         }
1790         return (mp);
1791 }
1792 
1793 #ifdef GEM_DEBUG_LEVEL
1794 uint_t  gem_rx_pkts[17];
1795 #endif
1796 
1797 
1798 int
1799 gem_receive(struct gem_dev *dp)
1800 {
1801         uint64_t        len_total = 0;
1802         struct rxbuf    *rbp;
1803         mblk_t          *mp;
1804         int             cnt = 0;
1805         uint64_t        rxstat;
1806         struct rxbuf    *newbufs;
1807         struct rxbuf    **newbufs_tailp;
1808         mblk_t          *rx_head;
1809         mblk_t          **rx_tailp;
1810         int             rx_ring_size = dp->gc.gc_rx_ring_size;
1811         seqnum_t        active_head;
1812         uint64_t        (*rx_desc_stat)(struct gem_dev *dp,
1813             int slot, int ndesc);
1814         int             ethermin = ETHERMIN;
1815         int             ethermax = dp->mtu + sizeof (struct ether_header);
1816         int             rx_header_len = dp->gc.gc_rx_header_len;
1817 
1818         ASSERT(mutex_owned(&dp->intrlock));
1819 
1820         DPRINTF(3, (CE_CONT, "!%s: gem_receive: rx_buf_head:%p",
1821             dp->name, dp->rx_buf_head));
1822 
1823         rx_desc_stat  = dp->gc.gc_rx_desc_stat;
1824         newbufs_tailp = &newbufs;
1825         rx_tailp = &rx_head;
1826         for (active_head = dp->rx_active_head;
1827             (rbp = dp->rx_buf_head) != NULL; active_head++) {
1828                 int             len;
1829                 if (cnt == 0) {
1830                         cnt = max(dp->poll_pkt_delay*2, 10);
1831                         cnt = min(cnt,
1832                             dp->rx_active_tail - active_head);
1833                         gem_rx_desc_dma_sync(dp,
1834                             SLOT(active_head, rx_ring_size),
1835                             cnt,
1836                             DDI_DMA_SYNC_FORKERNEL);
1837                 }
1838 
1839                 if (rx_header_len > 0) {
1840                         (void) ddi_dma_sync(rbp->rxb_dh, 0,
1841                             rx_header_len, DDI_DMA_SYNC_FORKERNEL);
1842                 }
1843 
1844                 if (((rxstat = (*rx_desc_stat)(dp,
1845                     SLOT(active_head, rx_ring_size),
1846                     rbp->rxb_nfrags))
1847                     & (GEM_RX_DONE | GEM_RX_ERR)) == 0) {
1848                         /* not received yet */
1849                         break;
1850                 }
1851 
1852                 /* Remove the head of the rx buffer list */
1853                 dp->rx_buf_head = rbp->rxb_next;
1854                 cnt--;
1855 
1856 
1857                 if (rxstat & GEM_RX_ERR) {
1858                         goto next;
1859                 }
1860 
1861                 len = rxstat & GEM_RX_LEN;
1862                 DPRINTF(3, (CE_CONT, "!%s: %s: rxstat:0x%llx, len:0x%x",
1863                     dp->name, __func__, rxstat, len));
1864 
1865                 /*
1866                  * Copy the packet
1867                  */
1868                 if ((mp = dp->gc.gc_get_packet(dp, rbp, len)) == NULL) {
1869                         /* no memory, discard the packet */
1870                         dp->stats.norcvbuf++;
1871                         goto next;
1872                 }
1873 
1874                 /*
1875                  * Process VLAN tag
1876                  */
1877                 ethermin = ETHERMIN;
1878                 ethermax = dp->mtu + sizeof (struct ether_header);
1879                 if (GET_NET16(mp->b_rptr + VTAG_OFF) == VTAG_TPID) {
1880                         ethermax += VTAG_SIZE;
1881                 }
1882 
1883                 /* check packet size */
1884                 if (len < ethermin) {
1885                         dp->stats.errrcv++;
1886                         dp->stats.runt++;
1887                         freemsg(mp);
1888                         goto next;
1889                 }
1890 
1891                 if (len > ethermax) {
1892                         dp->stats.errrcv++;
1893                         dp->stats.frame_too_long++;
1894                         freemsg(mp);
1895                         goto next;
1896                 }
1897 
1898                 len_total += len;
1899 
1900 #ifdef GEM_DEBUG_VLAN
1901                 if (GET_ETHERTYPE(mp->b_rptr) == VTAG_TPID) {
1902                         gem_dump_packet(dp, (char *)__func__, mp, B_TRUE);
1903                 }
1904 #endif
1905                 /* append received packet to temporaly rx buffer list */
1906                 *rx_tailp = mp;
1907                 rx_tailp  = &mp->b_next;
1908 
1909                 if (mp->b_rptr[0] & 1) {
1910                         if (bcmp(mp->b_rptr,
1911                             gem_etherbroadcastaddr.ether_addr_octet,
1912                             ETHERADDRL) == 0) {
1913                                 dp->stats.rbcast++;
1914                         } else {
1915                                 dp->stats.rmcast++;
1916                         }
1917                 }
1918 next:
1919                 ASSERT(rbp != NULL);
1920 
1921                 /* append new one to temporal new buffer list */
1922                 *newbufs_tailp = rbp;
1923                 newbufs_tailp  = &rbp->rxb_next;
1924         }
1925 
1926         /* advance rx_active_head */
1927         if ((cnt = active_head - dp->rx_active_head) > 0) {
1928                 dp->stats.rbytes += len_total;
1929                 dp->stats.rpackets += cnt;
1930         }
1931         dp->rx_active_head = active_head;
1932 
1933         /* terminate the working list */
1934         *newbufs_tailp = NULL;
1935         *rx_tailp = NULL;
1936 
1937         if (dp->rx_buf_head == NULL) {
1938                 dp->rx_buf_tail = NULL;
1939         }
1940 
1941         DPRINTF(4, (CE_CONT, "%s: %s: cnt:%d, rx_head:%p",
1942             dp->name, __func__, cnt, rx_head));
1943 
1944         if (newbufs) {
1945                 /*
1946                  * fillfull rx list with new buffers
1947                  */
1948                 seqnum_t        head;
1949 
1950                 /* save current tail */
1951                 head = dp->rx_active_tail;
1952                 gem_append_rxbuf(dp, newbufs);
1953 
1954                 /* call hw depend start routine if we have. */
1955                 dp->gc.gc_rx_start(dp,
1956                     SLOT(head, rx_ring_size), dp->rx_active_tail - head);
1957         }
1958 
1959         if (rx_head) {
1960                 /*
1961                  * send up received packets
1962                  */
1963                 mutex_exit(&dp->intrlock);
1964                 mac_rx(dp->mh, NULL, rx_head);
1965                 mutex_enter(&dp->intrlock);
1966         }
1967 
1968 #ifdef GEM_DEBUG_LEVEL
1969         gem_rx_pkts[min(cnt, sizeof (gem_rx_pkts)/sizeof (uint_t)-1)]++;
1970 #endif
1971         return (cnt);
1972 }
1973 
1974 boolean_t
1975 gem_tx_done(struct gem_dev *dp)
1976 {
1977         boolean_t       tx_sched = B_FALSE;
1978 
1979         if (gem_reclaim_txbuf(dp) != GEM_SUCCESS) {
1980                 (void) gem_restart_nic(dp, GEM_RESTART_KEEP_BUF);
1981                 DPRINTF(2, (CE_CONT, "!%s: gem_tx_done: tx_desc: %d %d",
1982                     dp->name, dp->tx_active_head, dp->tx_active_tail));
1983                 tx_sched = B_TRUE;
1984                 goto x;
1985         }
1986 
1987         mutex_enter(&dp->xmitlock);
1988 
1989         /* XXX - we must not have any packets in soft queue */
1990         ASSERT(dp->tx_softq_head == dp->tx_softq_tail);
1991         /*
1992          * If we won't have chance to get more free tx buffers, and blocked,
1993          * it is worth to reschedule the downstream i.e. tx side.
1994          */
1995         ASSERT(dp->tx_desc_intr - dp->tx_desc_head >= 0);
1996         if (dp->tx_blocked && dp->tx_desc_intr == dp->tx_desc_head) {
1997                 /*
1998                  * As no further tx-done interrupts are scheduled, this
1999                  * is the last chance to kick tx side, which may be
2000                  * blocked now, otherwise the tx side never works again.
2001                  */
2002                 tx_sched = B_TRUE;
2003                 dp->tx_blocked = (clock_t)0;
2004                 dp->tx_max_packets =
2005                     min(dp->tx_max_packets + 2, dp->gc.gc_tx_buf_limit);
2006         }
2007 
2008         mutex_exit(&dp->xmitlock);
2009 
2010         DPRINTF(3, (CE_CONT, "!%s: %s: ret: blocked:%d",
2011             dp->name, __func__, BOOLEAN(dp->tx_blocked)));
2012 x:
2013         return (tx_sched);
2014 }
2015 
2016 static uint_t
2017 gem_intr(struct gem_dev *dp)
2018 {
2019         uint_t          ret;
2020 
2021         mutex_enter(&dp->intrlock);
2022         if (dp->mac_suspended) {
2023                 mutex_exit(&dp->intrlock);
2024                 return (DDI_INTR_UNCLAIMED);
2025         }
2026         dp->intr_busy = B_TRUE;
2027 
2028         ret = (*dp->gc.gc_interrupt)(dp);
2029 
2030         if (ret == DDI_INTR_UNCLAIMED) {
2031                 dp->intr_busy = B_FALSE;
2032                 mutex_exit(&dp->intrlock);
2033                 return (ret);
2034         }
2035 
2036         if (!dp->mac_active) {
2037                 cv_broadcast(&dp->tx_drain_cv);
2038         }
2039 
2040 
2041         dp->stats.intr++;
2042         dp->intr_busy = B_FALSE;
2043 
2044         mutex_exit(&dp->intrlock);
2045 
2046         if (ret & INTR_RESTART_TX) {
2047                 DPRINTF(4, (CE_CONT, "!%s: calling mac_tx_update", dp->name));
2048                 mac_tx_update(dp->mh);
2049                 ret &= ~INTR_RESTART_TX;
2050         }
2051         return (ret);
2052 }
2053 
2054 static void
2055 gem_intr_watcher(struct gem_dev *dp)
2056 {
2057         (void) gem_intr(dp);
2058 
2059         /* schedule next call of tu_intr_watcher */
2060         dp->intr_watcher_id =
2061             timeout((void (*)(void *))gem_intr_watcher, (void *)dp, 1);
2062 }
2063 
2064 /* ======================================================================== */
2065 /*
2066  * MII support routines
2067  */
2068 /* ======================================================================== */
2069 static void
2070 gem_choose_forcedmode(struct gem_dev *dp)
2071 {
2072         /* choose media mode */
2073         if (dp->anadv_1000fdx || dp->anadv_1000hdx) {
2074                 dp->speed = GEM_SPD_1000;
2075                 dp->full_duplex = dp->anadv_1000fdx;
2076         } else if (dp->anadv_100fdx || dp->anadv_100t4) {
2077                 dp->speed = GEM_SPD_100;
2078                 dp->full_duplex = B_TRUE;
2079         } else if (dp->anadv_100hdx) {
2080                 dp->speed = GEM_SPD_100;
2081                 dp->full_duplex = B_FALSE;
2082         } else {
2083                 dp->speed = GEM_SPD_10;
2084                 dp->full_duplex = dp->anadv_10fdx;
2085         }
2086 }
2087 
2088 uint16_t
2089 gem_mii_read(struct gem_dev *dp, uint_t reg)
2090 {
2091         if ((dp->mii_status & MII_STATUS_MFPRMBLSUPR) == 0) {
2092                 (*dp->gc.gc_mii_sync)(dp);
2093         }
2094         return ((*dp->gc.gc_mii_read)(dp, reg));
2095 }
2096 
2097 void
2098 gem_mii_write(struct gem_dev *dp, uint_t reg, uint16_t val)
2099 {
2100         if ((dp->mii_status & MII_STATUS_MFPRMBLSUPR) == 0) {
2101                 (*dp->gc.gc_mii_sync)(dp);
2102         }
2103         (*dp->gc.gc_mii_write)(dp, reg, val);
2104 }
2105 
2106 #define fc_cap_decode(x)        \
2107         ((((x) & MII_ABILITY_PAUSE) ? 1 : 0) |      \
2108         (((x) & MII_ABILITY_ASMPAUSE) ? 2 : 0))
2109 
2110 int
2111 gem_mii_config_default(struct gem_dev *dp)
2112 {
2113         uint16_t        mii_stat;
2114         uint16_t        val;
2115         static uint16_t fc_cap_encode[4] = {
2116                 0, /* none */
2117                 MII_ABILITY_PAUSE, /* symmetric */
2118                 MII_ABILITY_ASMPAUSE, /* tx */
2119                 MII_ABILITY_PAUSE | MII_ABILITY_ASMPAUSE, /* rx-symmetric */
2120         };
2121 
2122         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2123 
2124         /*
2125          * Configure bits in advertisement register
2126          */
2127         mii_stat = dp->mii_status;
2128 
2129         DPRINTF(1, (CE_CONT, "!%s: %s: MII_STATUS reg:%b",
2130             dp->name, __func__, mii_stat, MII_STATUS_BITS));
2131 
2132         if ((mii_stat & MII_STATUS_ABILITY_TECH) == 0) {
2133                 /* it's funny */
2134                 cmn_err(CE_WARN, "!%s: wrong ability bits: mii_status:%b",
2135                     dp->name, mii_stat, MII_STATUS_BITS);
2136                 return (GEM_FAILURE);
2137         }
2138 
2139         /* Do not change the rest of the ability bits in the advert reg */
2140         val = gem_mii_read(dp, MII_AN_ADVERT) & ~MII_ABILITY_ALL;
2141 
2142         DPRINTF(0, (CE_CONT,
2143             "!%s: %s: 100T4:%d 100F:%d 100H:%d 10F:%d 10H:%d",
2144             dp->name, __func__,
2145             dp->anadv_100t4, dp->anadv_100fdx, dp->anadv_100hdx,
2146             dp->anadv_10fdx, dp->anadv_10hdx));
2147 
2148         if (dp->anadv_100t4) {
2149                 val |= MII_ABILITY_100BASE_T4;
2150         }
2151         if (dp->anadv_100fdx) {
2152                 val |= MII_ABILITY_100BASE_TX_FD;
2153         }
2154         if (dp->anadv_100hdx) {
2155                 val |= MII_ABILITY_100BASE_TX;
2156         }
2157         if (dp->anadv_10fdx) {
2158                 val |= MII_ABILITY_10BASE_T_FD;
2159         }
2160         if (dp->anadv_10hdx) {
2161                 val |= MII_ABILITY_10BASE_T;
2162         }
2163 
2164         /* set flow control capability */
2165         val |= fc_cap_encode[dp->anadv_flow_control];
2166 
2167         DPRINTF(0, (CE_CONT,
2168             "!%s: %s: setting MII_AN_ADVERT reg:%b, mii_mode:%d, fc:%d",
2169             dp->name, __func__, val, MII_ABILITY_BITS, dp->gc.gc_mii_mode,
2170             dp->anadv_flow_control));
2171 
2172         gem_mii_write(dp, MII_AN_ADVERT, val);
2173 
2174         if (mii_stat & MII_STATUS_XSTATUS) {
2175                 /*
2176                  * 1000Base-T GMII support
2177                  */
2178                 if (!dp->anadv_autoneg) {
2179                         /* enable manual configuration */
2180                         val = MII_1000TC_CFG_EN;
2181                 } else {
2182                         val = 0;
2183                         if (dp->anadv_1000fdx) {
2184                                 val |= MII_1000TC_ADV_FULL;
2185                         }
2186                         if (dp->anadv_1000hdx) {
2187                                 val |= MII_1000TC_ADV_HALF;
2188                         }
2189                 }
2190                 DPRINTF(0, (CE_CONT,
2191                     "!%s: %s: setting MII_1000TC reg:%b",
2192                     dp->name, __func__, val, MII_1000TC_BITS));
2193 
2194                 gem_mii_write(dp, MII_1000TC, val);
2195         }
2196 
2197         return (GEM_SUCCESS);
2198 }
2199 
2200 #define GEM_LINKUP(dp)          mac_link_update((dp)->mh, LINK_STATE_UP)
2201 #define GEM_LINKDOWN(dp)        mac_link_update((dp)->mh, LINK_STATE_DOWN)
2202 
2203 static uint8_t gem_fc_result[4 /* my cap */ ][4 /* lp cap */] = {
2204 /*       none   symm    tx      rx/symm */
2205 /* none */
2206         {FLOW_CONTROL_NONE,
2207                 FLOW_CONTROL_NONE,
2208                         FLOW_CONTROL_NONE,
2209                                 FLOW_CONTROL_NONE},
2210 /* sym */
2211         {FLOW_CONTROL_NONE,
2212                 FLOW_CONTROL_SYMMETRIC,
2213                         FLOW_CONTROL_NONE,
2214                                 FLOW_CONTROL_SYMMETRIC},
2215 /* tx */
2216         {FLOW_CONTROL_NONE,
2217                 FLOW_CONTROL_NONE,
2218                         FLOW_CONTROL_NONE,
2219                                 FLOW_CONTROL_TX_PAUSE},
2220 /* rx/symm */
2221         {FLOW_CONTROL_NONE,
2222                 FLOW_CONTROL_SYMMETRIC,
2223                         FLOW_CONTROL_RX_PAUSE,
2224                                 FLOW_CONTROL_SYMMETRIC},
2225 };
2226 
2227 static char *gem_fc_type[] = {
2228         "without",
2229         "with symmetric",
2230         "with tx",
2231         "with rx",
2232 };
2233 
2234 boolean_t
2235 gem_mii_link_check(struct gem_dev *dp)
2236 {
2237         uint16_t        old_mii_state;
2238         boolean_t       tx_sched = B_FALSE;
2239         uint16_t        status;
2240         uint16_t        advert;
2241         uint16_t        lpable;
2242         uint16_t        exp;
2243         uint16_t        ctl1000;
2244         uint16_t        stat1000;
2245         uint16_t        val;
2246         clock_t         now;
2247         clock_t         diff;
2248         int             linkdown_action;
2249         boolean_t       fix_phy = B_FALSE;
2250 
2251         now = ddi_get_lbolt();
2252         old_mii_state = dp->mii_state;
2253 
2254         DPRINTF(3, (CE_CONT, "!%s: %s: time:%d state:%d",
2255             dp->name, __func__, now, dp->mii_state));
2256 
2257         diff = now - dp->mii_last_check;
2258         dp->mii_last_check = now;
2259 
2260         /*
2261          * For NWAM, don't show linkdown state right
2262          * after the system boots
2263          */
2264         if (dp->linkup_delay > 0) {
2265                 if (dp->linkup_delay > diff) {
2266                         dp->linkup_delay -= diff;
2267                 } else {
2268                         /* link up timeout */
2269                         dp->linkup_delay = -1;
2270                 }
2271         }
2272 
2273 next_nowait:
2274         switch (dp->mii_state) {
2275         case MII_STATE_UNKNOWN:
2276                 /* power-up, DP83840 requires 32 sync bits */
2277                 (*dp->gc.gc_mii_sync)(dp);
2278                 goto reset_phy;
2279 
2280         case MII_STATE_RESETTING:
2281                 dp->mii_timer -= diff;
2282                 if (dp->mii_timer > 0) {
2283                         /* don't read phy registers in resetting */
2284                         dp->mii_interval = WATCH_INTERVAL_FAST;
2285                         goto next;
2286                 }
2287 
2288                 /* Timer expired, ensure reset bit is not set */
2289 
2290                 if (dp->mii_status & MII_STATUS_MFPRMBLSUPR) {
2291                         /* some phys need sync bits after reset */
2292                         (*dp->gc.gc_mii_sync)(dp);
2293                 }
2294                 val = gem_mii_read(dp, MII_CONTROL);
2295                 if (val & MII_CONTROL_RESET) {
2296                         cmn_err(CE_NOTE,
2297                             "!%s: time:%ld resetting phy not complete."
2298                             " mii_control:0x%b",
2299                             dp->name, ddi_get_lbolt(),
2300                             val, MII_CONTROL_BITS);
2301                 }
2302 
2303                 /* ensure neither isolated nor pwrdown nor auto-nego mode */
2304                 /* XXX -- this operation is required for NS DP83840A. */
2305                 gem_mii_write(dp, MII_CONTROL, 0);
2306 
2307                 /* As resetting PHY has completed, configure PHY registers */
2308                 if ((*dp->gc.gc_mii_config)(dp) != GEM_SUCCESS) {
2309                         /* we failed to configure PHY. */
2310                         goto reset_phy;
2311                 }
2312 
2313                 /* mii_config may disable autonegatiation */
2314                 gem_choose_forcedmode(dp);
2315 
2316                 dp->mii_lpable = 0;
2317                 dp->mii_advert = 0;
2318                 dp->mii_exp = 0;
2319                 dp->mii_ctl1000 = 0;
2320                 dp->mii_stat1000 = 0;
2321                 dp->flow_control = FLOW_CONTROL_NONE;
2322 
2323                 if (!dp->anadv_autoneg) {
2324                         /* skip auto-negotiation phase */
2325                         dp->mii_state = MII_STATE_MEDIA_SETUP;
2326                         dp->mii_timer = 0;
2327                         dp->mii_interval = 0;
2328                         goto next_nowait;
2329                 }
2330 
2331                 /* Issue auto-negotiation command */
2332                 goto autonego;
2333 
2334         case MII_STATE_AUTONEGOTIATING:
2335                 /*
2336                  * Autonegotiation is in progress
2337                  */
2338                 dp->mii_timer -= diff;
2339                 if (dp->mii_timer -
2340                     (dp->gc.gc_mii_an_timeout
2341                     - dp->gc.gc_mii_an_wait) > 0) {
2342                         /*
2343                          * wait for a while, typically autonegotiation
2344                          * completes in 2.3 - 2.5 sec.
2345                          */
2346                         dp->mii_interval = WATCH_INTERVAL_FAST;
2347                         goto next;
2348                 }
2349 
2350                 /* read PHY status */
2351                 status = gem_mii_read(dp, MII_STATUS);
2352                 DPRINTF(4, (CE_CONT,
2353                     "!%s: %s: called: mii_state:%d MII_STATUS reg:%b",
2354                     dp->name, __func__, dp->mii_state,
2355                     status, MII_STATUS_BITS));
2356 
2357                 if (status & MII_STATUS_REMFAULT) {
2358                         /*
2359                          * The link parnert told me something wrong happend.
2360                          * What do we do ?
2361                          */
2362                         cmn_err(CE_CONT,
2363                             "!%s: auto-negotiation failed: remote fault",
2364                             dp->name);
2365                         goto autonego;
2366                 }
2367 
2368                 if ((status & MII_STATUS_ANDONE) == 0) {
2369                         if (dp->mii_timer <= 0) {
2370                                 /*
2371                                  * Auto-negotiation was timed out,
2372                                  * try again w/o resetting phy.
2373                                  */
2374                                 if (!dp->mii_supress_msg) {
2375                                         cmn_err(CE_WARN,
2376                                     "!%s: auto-negotiation failed: timeout",
2377                                             dp->name);
2378                                         dp->mii_supress_msg = B_TRUE;
2379                                 }
2380                                 goto autonego;
2381                         }
2382                         /*
2383                          * Auto-negotiation is in progress. Wait.
2384                          */
2385                         dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2386                         goto next;
2387                 }
2388 
2389                 /*
2390                  * Auto-negotiation have completed.
2391                  * Assume linkdown and fall through.
2392                  */
2393                 dp->mii_supress_msg = B_FALSE;
2394                 dp->mii_state = MII_STATE_AN_DONE;
2395                 DPRINTF(0, (CE_CONT,
2396                     "!%s: auto-negotiation completed, MII_STATUS:%b",
2397                     dp->name, status, MII_STATUS_BITS));
2398 
2399                 if (dp->gc.gc_mii_an_delay > 0) {
2400                         dp->mii_timer = dp->gc.gc_mii_an_delay;
2401                         dp->mii_interval = drv_usectohz(20*1000);
2402                         goto next;
2403                 }
2404 
2405                 dp->mii_timer = 0;
2406                 diff = 0;
2407                 goto next_nowait;
2408 
2409         case MII_STATE_AN_DONE:
2410                 /*
2411                  * Auto-negotiation have done. Now we can set up media.
2412                  */
2413                 dp->mii_timer -= diff;
2414                 if (dp->mii_timer > 0) {
2415                         /* wait for a while */
2416                         dp->mii_interval = WATCH_INTERVAL_FAST;
2417                         goto next;
2418                 }
2419 
2420                 /*
2421                  * set up the result of auto negotiation
2422                  */
2423 
2424                 /*
2425                  * Read registers required to determin current
2426                  * duplex mode and media speed.
2427                  */
2428                 if (dp->gc.gc_mii_an_delay > 0) {
2429                         /*
2430                          * As the link watcher context has been suspended,
2431                          * 'status' is invalid. We must status register here
2432                          */
2433                         status = gem_mii_read(dp, MII_STATUS);
2434                 }
2435                 advert = gem_mii_read(dp, MII_AN_ADVERT);
2436                 lpable = gem_mii_read(dp, MII_AN_LPABLE);
2437                 exp = gem_mii_read(dp, MII_AN_EXPANSION);
2438                 if (exp == 0xffff) {
2439                         /* some phys don't have exp register */
2440                         exp = 0;
2441                 }
2442                 ctl1000  = 0;
2443                 stat1000 = 0;
2444                 if (dp->mii_status & MII_STATUS_XSTATUS) {
2445                         ctl1000  = gem_mii_read(dp, MII_1000TC);
2446                         stat1000 = gem_mii_read(dp, MII_1000TS);
2447                 }
2448                 dp->mii_lpable = lpable;
2449                 dp->mii_advert = advert;
2450                 dp->mii_exp = exp;
2451                 dp->mii_ctl1000  = ctl1000;
2452                 dp->mii_stat1000 = stat1000;
2453 
2454                 cmn_err(CE_CONT,
2455                 "!%s: auto-negotiation done, advert:%b, lpable:%b, exp:%b",
2456                     dp->name,
2457                     advert, MII_ABILITY_BITS,
2458                     lpable, MII_ABILITY_BITS,
2459                     exp, MII_AN_EXP_BITS);
2460 
2461                 if (dp->mii_status & MII_STATUS_XSTATUS) {
2462                         cmn_err(CE_CONT,
2463                             "! MII_1000TC:%b, MII_1000TS:%b",
2464                             ctl1000, MII_1000TC_BITS,
2465                             stat1000, MII_1000TS_BITS);
2466                 }
2467 
2468                 if (gem_population(lpable) <= 1 &&
2469                     (exp & MII_AN_EXP_LPCANAN) == 0) {
2470                         if ((advert & MII_ABILITY_TECH) != lpable) {
2471                                 cmn_err(CE_WARN,
2472                                     "!%s: but the link partnar doesn't seem"
2473                                     " to have auto-negotiation capability."
2474                                     " please check the link configuration.",
2475                                     dp->name);
2476                         }
2477                         /*
2478                          * it should be result of parallel detection, which
2479                          * cannot detect duplex mode.
2480                          */
2481                         if (lpable & MII_ABILITY_100BASE_TX) {
2482                                 /*
2483                                  * we prefer full duplex mode for 100Mbps
2484                                  * connection, if we can.
2485                                  */
2486                                 lpable |= advert & MII_ABILITY_100BASE_TX_FD;
2487                         }
2488 
2489                         if ((advert & lpable) == 0 &&
2490                             lpable & MII_ABILITY_10BASE_T) {
2491                                 lpable |= advert & MII_ABILITY_10BASE_T_FD;
2492                         }
2493                         /*
2494                          * as the link partnar isn't auto-negotiatable, use
2495                          * fixed mode temporally.
2496                          */
2497                         fix_phy = B_TRUE;
2498                 } else if (lpable == 0) {
2499                         cmn_err(CE_WARN, "!%s: wrong lpable.", dp->name);
2500                         goto reset_phy;
2501                 }
2502                 /*
2503                  * configure current link mode according to AN priority.
2504                  */
2505                 val = advert & lpable;
2506                 if ((ctl1000 & MII_1000TC_ADV_FULL) &&
2507                     (stat1000 & MII_1000TS_LP_FULL)) {
2508                         /* 1000BaseT & full duplex */
2509                         dp->speed     = GEM_SPD_1000;
2510                         dp->full_duplex  = B_TRUE;
2511                 } else if ((ctl1000 & MII_1000TC_ADV_HALF) &&
2512                     (stat1000 & MII_1000TS_LP_HALF)) {
2513                         /* 1000BaseT & half duplex */
2514                         dp->speed = GEM_SPD_1000;
2515                         dp->full_duplex = B_FALSE;
2516                 } else if (val & MII_ABILITY_100BASE_TX_FD) {
2517                         /* 100BaseTx & full duplex */
2518                         dp->speed = GEM_SPD_100;
2519                         dp->full_duplex = B_TRUE;
2520                 } else if (val & MII_ABILITY_100BASE_T4) {
2521                         /* 100BaseT4 & full duplex */
2522                         dp->speed = GEM_SPD_100;
2523                         dp->full_duplex = B_TRUE;
2524                 } else if (val & MII_ABILITY_100BASE_TX) {
2525                         /* 100BaseTx & half duplex */
2526                         dp->speed     = GEM_SPD_100;
2527                         dp->full_duplex  = B_FALSE;
2528                 } else if (val & MII_ABILITY_10BASE_T_FD) {
2529                         /* 10BaseT & full duplex */
2530                         dp->speed     = GEM_SPD_10;
2531                         dp->full_duplex  = B_TRUE;
2532                 } else if (val & MII_ABILITY_10BASE_T) {
2533                         /* 10BaseT & half duplex */
2534                         dp->speed     = GEM_SPD_10;
2535                         dp->full_duplex  = B_FALSE;
2536                 } else {
2537                         /*
2538                          * It seems that the link partnar doesn't have
2539                          * auto-negotiation capability and our PHY
2540                          * could not report the correct current mode.
2541                          * We guess current mode by mii_control register.
2542                          */
2543                         val = gem_mii_read(dp, MII_CONTROL);
2544 
2545                         /* select 100m full or 10m half */
2546                         dp->speed = (val & MII_CONTROL_100MB) ?
2547                             GEM_SPD_100 : GEM_SPD_10;
2548                         dp->full_duplex = dp->speed != GEM_SPD_10;
2549                         fix_phy = B_TRUE;
2550 
2551                         cmn_err(CE_NOTE,
2552                             "!%s: auto-negotiation done but "
2553                             "common ability not found.\n"
2554                             "PHY state: control:%b advert:%b lpable:%b\n"
2555                             "guessing %d Mbps %s duplex mode",
2556                             dp->name,
2557                             val, MII_CONTROL_BITS,
2558                             advert, MII_ABILITY_BITS,
2559                             lpable, MII_ABILITY_BITS,
2560                             gem_speed_value[dp->speed],
2561                             dp->full_duplex ? "full" : "half");
2562                 }
2563 
2564                 if (dp->full_duplex) {
2565                         dp->flow_control =
2566                             gem_fc_result[fc_cap_decode(advert)]
2567                             [fc_cap_decode(lpable)];
2568                 } else {
2569                         dp->flow_control = FLOW_CONTROL_NONE;
2570                 }
2571                 dp->mii_state = MII_STATE_MEDIA_SETUP;
2572                 /* FALLTHROUGH */
2573 
2574         case MII_STATE_MEDIA_SETUP:
2575                 dp->mii_state = MII_STATE_LINKDOWN;
2576                 dp->mii_timer = dp->gc.gc_mii_linkdown_timeout;
2577                 DPRINTF(2, (CE_CONT, "!%s: setup midia mode done", dp->name));
2578                 dp->mii_supress_msg = B_FALSE;
2579 
2580                 /* use short interval */
2581                 dp->mii_interval = WATCH_INTERVAL_FAST;
2582 
2583                 if ((!dp->anadv_autoneg) ||
2584                     dp->gc.gc_mii_an_oneshot || fix_phy) {
2585 
2586                         /*
2587                          * write specified mode to phy.
2588                          */
2589                         val = gem_mii_read(dp, MII_CONTROL);
2590                         val &= ~(MII_CONTROL_SPEED | MII_CONTROL_FDUPLEX |
2591                             MII_CONTROL_ANE | MII_CONTROL_RSAN);
2592 
2593                         if (dp->full_duplex) {
2594                                 val |= MII_CONTROL_FDUPLEX;
2595                         }
2596 
2597                         switch (dp->speed) {
2598                         case GEM_SPD_1000:
2599                                 val |= MII_CONTROL_1000MB;
2600                                 break;
2601 
2602                         case GEM_SPD_100:
2603                                 val |= MII_CONTROL_100MB;
2604                                 break;
2605 
2606                         default:
2607                                 cmn_err(CE_WARN, "%s: unknown speed:%d",
2608                                     dp->name, dp->speed);
2609                                 /* FALLTHROUGH */
2610                         case GEM_SPD_10:
2611                                 /* for GEM_SPD_10, do nothing */
2612                                 break;
2613                         }
2614 
2615                         if (dp->mii_status & MII_STATUS_XSTATUS) {
2616                                 gem_mii_write(dp,
2617                                     MII_1000TC, MII_1000TC_CFG_EN);
2618                         }
2619                         gem_mii_write(dp, MII_CONTROL, val);
2620                 }
2621 
2622                 if (dp->nic_state >= NIC_STATE_INITIALIZED) {
2623                         /* notify the result of auto-negotiation to mac */
2624                         (*dp->gc.gc_set_media)(dp);
2625                 }
2626 
2627                 if ((void *)dp->gc.gc_mii_tune_phy) {
2628                         /* for built-in sis900 */
2629                         /* XXX - this code should be removed.  */
2630                         (*dp->gc.gc_mii_tune_phy)(dp);
2631                 }
2632 
2633                 goto next_nowait;
2634 
2635         case MII_STATE_LINKDOWN:
2636                 status = gem_mii_read(dp, MII_STATUS);
2637                 if (status & MII_STATUS_LINKUP) {
2638                         /*
2639                          * Link going up
2640                          */
2641                         dp->mii_state = MII_STATE_LINKUP;
2642                         dp->mii_supress_msg = B_FALSE;
2643 
2644                         DPRINTF(0, (CE_CONT,
2645                             "!%s: link up detected: mii_stat:%b",
2646                             dp->name, status, MII_STATUS_BITS));
2647 
2648                         /*
2649                          * MII_CONTROL_100MB and  MII_CONTROL_FDUPLEX are
2650                          * ignored when MII_CONTROL_ANE is set.
2651                          */
2652                         cmn_err(CE_CONT,
2653                             "!%s: Link up: %d Mbps %s duplex %s flow control",
2654                             dp->name,
2655                             gem_speed_value[dp->speed],
2656                             dp->full_duplex ? "full" : "half",
2657                             gem_fc_type[dp->flow_control]);
2658 
2659                         dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2660 
2661                         /* XXX - we need other timer to watch statictics */
2662                         if (dp->gc.gc_mii_hw_link_detection &&
2663                             dp->nic_state == NIC_STATE_ONLINE) {
2664                                 dp->mii_interval = 0;
2665                         }
2666 
2667                         if (dp->nic_state == NIC_STATE_ONLINE) {
2668                                 if (!dp->mac_active) {
2669                                         (void) gem_mac_start(dp);
2670                                 }
2671                                 tx_sched = B_TRUE;
2672                         }
2673                         goto next;
2674                 }
2675 
2676                 dp->mii_supress_msg = B_TRUE;
2677                 if (dp->anadv_autoneg) {
2678                         dp->mii_timer -= diff;
2679                         if (dp->mii_timer <= 0) {
2680                                 /*
2681                                  * link down timer expired.
2682                                  * need to restart auto-negotiation.
2683                                  */
2684                                 linkdown_action =
2685                                     dp->gc.gc_mii_linkdown_timeout_action;
2686                                 goto restart_autonego;
2687                         }
2688                 }
2689                 /* don't change mii_state */
2690                 break;
2691 
2692         case MII_STATE_LINKUP:
2693                 status = gem_mii_read(dp, MII_STATUS);
2694                 if ((status & MII_STATUS_LINKUP) == 0) {
2695                         /*
2696                          * Link going down
2697                          */
2698                         cmn_err(CE_NOTE,
2699                             "!%s: link down detected: mii_stat:%b",
2700                             dp->name, status, MII_STATUS_BITS);
2701 
2702                         if (dp->nic_state == NIC_STATE_ONLINE &&
2703                             dp->mac_active &&
2704                             dp->gc.gc_mii_stop_mac_on_linkdown) {
2705                                 (void) gem_mac_stop(dp, 0);
2706 
2707                                 if (dp->tx_blocked) {
2708                                         /* drain tx */
2709                                         tx_sched = B_TRUE;
2710                                 }
2711                         }
2712 
2713                         if (dp->anadv_autoneg) {
2714                                 /* need to restart auto-negotiation */
2715                                 linkdown_action = dp->gc.gc_mii_linkdown_action;
2716                                 goto restart_autonego;
2717                         }
2718 
2719                         dp->mii_state = MII_STATE_LINKDOWN;
2720                         dp->mii_timer = dp->gc.gc_mii_linkdown_timeout;
2721 
2722                         if ((void *)dp->gc.gc_mii_tune_phy) {
2723                                 /* for built-in sis900 */
2724                                 (*dp->gc.gc_mii_tune_phy)(dp);
2725                         }
2726                         dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2727                         goto next;
2728                 }
2729 
2730                 /* don't change mii_state */
2731                 if (dp->gc.gc_mii_hw_link_detection &&
2732                     dp->nic_state == NIC_STATE_ONLINE) {
2733                         dp->mii_interval = 0;
2734                         goto next;
2735                 }
2736                 break;
2737         }
2738         dp->mii_interval = dp->gc.gc_mii_link_watch_interval;
2739         goto next;
2740 
2741         /* Actions on the end of state routine */
2742 
2743 restart_autonego:
2744         switch (linkdown_action) {
2745         case MII_ACTION_RESET:
2746                 if (!dp->mii_supress_msg) {
2747                         cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
2748                 }
2749                 dp->mii_supress_msg = B_TRUE;
2750                 goto reset_phy;
2751 
2752         case MII_ACTION_NONE:
2753                 dp->mii_supress_msg = B_TRUE;
2754                 if (dp->gc.gc_mii_an_oneshot) {
2755                         goto autonego;
2756                 }
2757                 /* PHY will restart autonego automatically */
2758                 dp->mii_state = MII_STATE_AUTONEGOTIATING;
2759                 dp->mii_timer = dp->gc.gc_mii_an_timeout;
2760                 dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2761                 goto next;
2762 
2763         case MII_ACTION_RSA:
2764                 if (!dp->mii_supress_msg) {
2765                         cmn_err(CE_CONT, "!%s: restarting auto-negotiation",
2766                             dp->name);
2767                 }
2768                 dp->mii_supress_msg = B_TRUE;
2769                 goto autonego;
2770 
2771         default:
2772                 cmn_err(CE_WARN, "!%s: unknowm linkdown action: %d",
2773                     dp->name, dp->gc.gc_mii_linkdown_action);
2774                 dp->mii_supress_msg = B_TRUE;
2775         }
2776         /* NOTREACHED */
2777 
2778 reset_phy:
2779         if (!dp->mii_supress_msg) {
2780                 cmn_err(CE_CONT, "!%s: resetting PHY", dp->name);
2781         }
2782         dp->mii_state = MII_STATE_RESETTING;
2783         dp->mii_timer = dp->gc.gc_mii_reset_timeout;
2784         if (!dp->gc.gc_mii_dont_reset) {
2785                 gem_mii_write(dp, MII_CONTROL, MII_CONTROL_RESET);
2786         }
2787         dp->mii_interval = WATCH_INTERVAL_FAST;
2788         goto next;
2789 
2790 autonego:
2791         if (!dp->mii_supress_msg) {
2792                 cmn_err(CE_CONT, "!%s: auto-negotiation started", dp->name);
2793         }
2794         dp->mii_state = MII_STATE_AUTONEGOTIATING;
2795         dp->mii_timer = dp->gc.gc_mii_an_timeout;
2796 
2797         /* start/restart auto nego */
2798         val = gem_mii_read(dp, MII_CONTROL) &
2799             ~(MII_CONTROL_ISOLATE | MII_CONTROL_PWRDN | MII_CONTROL_RESET);
2800 
2801         gem_mii_write(dp, MII_CONTROL,
2802             val | MII_CONTROL_RSAN | MII_CONTROL_ANE);
2803 
2804         dp->mii_interval = dp->gc.gc_mii_an_watch_interval;
2805 
2806 next:
2807         if (dp->link_watcher_id == 0 && dp->mii_interval) {
2808                 /* we must schedule next mii_watcher */
2809                 dp->link_watcher_id =
2810                     timeout((void (*)(void *))&gem_mii_link_watcher,
2811                     (void *)dp, dp->mii_interval);
2812         }
2813 
2814         if (old_mii_state != dp->mii_state) {
2815                 /* notify new mii link state */
2816                 if (dp->mii_state == MII_STATE_LINKUP) {
2817                         dp->linkup_delay = 0;
2818                         GEM_LINKUP(dp);
2819                 } else if (dp->linkup_delay <= 0) {
2820                         GEM_LINKDOWN(dp);
2821                 }
2822         } else if (dp->linkup_delay < 0) {
2823                 /* first linkup timeout */
2824                 dp->linkup_delay = 0;
2825                 GEM_LINKDOWN(dp);
2826         }
2827 
2828         return (tx_sched);
2829 }
2830 
2831 static void
2832 gem_mii_link_watcher(struct gem_dev *dp)
2833 {
2834         boolean_t       tx_sched;
2835 
2836         mutex_enter(&dp->intrlock);
2837 
2838         dp->link_watcher_id = 0;
2839         tx_sched = gem_mii_link_check(dp);
2840 #if GEM_DEBUG_LEVEL > 2
2841         if (dp->link_watcher_id == 0) {
2842                 cmn_err(CE_CONT, "%s: link watcher stopped", dp->name);
2843         }
2844 #endif
2845         mutex_exit(&dp->intrlock);
2846 
2847         if (tx_sched) {
2848                 /* kick potentially stopped downstream */
2849                 mac_tx_update(dp->mh);
2850         }
2851 }
2852 
2853 int
2854 gem_mii_probe_default(struct gem_dev *dp)
2855 {
2856         int8_t          phy;
2857         uint16_t        status;
2858         uint16_t        adv;
2859         uint16_t        adv_org;
2860 
2861         DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2862 
2863         /*
2864          * Scan PHY
2865          */
2866         /* ensure to send sync bits */
2867         dp->mii_status = 0;
2868 
2869         /* Try default phy first */
2870         if (dp->mii_phy_addr) {
2871                 status = gem_mii_read(dp, MII_STATUS);
2872                 if (status != 0xffff && status != 0) {
2873                         gem_mii_write(dp, MII_CONTROL, 0);
2874                         goto PHY_found;
2875                 }
2876 
2877                 if (dp->mii_phy_addr < 0) {
2878                         cmn_err(CE_NOTE,
2879             "!%s: failed to probe default internal and/or non-MII PHY",
2880                             dp->name);
2881                         return (GEM_FAILURE);
2882                 }
2883 
2884                 cmn_err(CE_NOTE,
2885                     "!%s: failed to probe default MII PHY at %d",
2886                     dp->name, dp->mii_phy_addr);
2887         }
2888 
2889         /* Try all possible address */
2890         for (phy = dp->gc.gc_mii_addr_min; phy < 32; phy++) {
2891                 dp->mii_phy_addr = phy;
2892                 status = gem_mii_read(dp, MII_STATUS);
2893 
2894                 if (status != 0xffff && status != 0) {
2895                         gem_mii_write(dp, MII_CONTROL, 0);
2896                         goto PHY_found;
2897                 }
2898         }
2899 
2900         for (phy = dp->gc.gc_mii_addr_min; phy < 32; phy++) {
2901                 dp->mii_phy_addr = phy;
2902                 gem_mii_write(dp, MII_CONTROL, 0);
2903                 status = gem_mii_read(dp, MII_STATUS);
2904 
2905                 if (status != 0xffff && status != 0) {
2906                         goto PHY_found;
2907                 }
2908         }
2909 
2910         cmn_err(CE_NOTE, "!%s: no MII PHY found", dp->name);
2911         dp->mii_phy_addr = -1;
2912 
2913         return (GEM_FAILURE);
2914 
2915 PHY_found:
2916         dp->mii_status = status;
2917         dp->mii_phy_id  = (gem_mii_read(dp, MII_PHYIDH) << 16) |
2918             gem_mii_read(dp, MII_PHYIDL);
2919 
2920         if (dp->mii_phy_addr < 0) {
2921                 cmn_err(CE_CONT, "!%s: using internal/non-MII PHY(0x%08x)",
2922                     dp->name, dp->mii_phy_id);
2923         } else {
2924                 cmn_err(CE_CONT, "!%s: MII PHY (0x%08x) found at %d",
2925                     dp->name, dp->mii_phy_id, dp->mii_phy_addr);
2926         }
2927 
2928         cmn_err(CE_CONT, "!%s: PHY control:%b, status:%b, advert:%b, lpar:%b",
2929             dp->name,
2930             gem_mii_read(dp, MII_CONTROL), MII_CONTROL_BITS,
2931             status, MII_STATUS_BITS,
2932             gem_mii_read(dp, MII_AN_ADVERT), MII_ABILITY_BITS,
2933             gem_mii_read(dp, MII_AN_LPABLE), MII_ABILITY_BITS);
2934 
2935         dp->mii_xstatus = 0;
2936         if (status & MII_STATUS_XSTATUS) {
2937                 dp->mii_xstatus = gem_mii_read(dp, MII_XSTATUS);
2938 
2939                 cmn_err(CE_CONT, "!%s: xstatus:%b",
2940                     dp->name, dp->mii_xstatus, MII_XSTATUS_BITS);
2941         }
2942 
2943         /* check if the phy can advertize pause abilities */
2944         adv_org = gem_mii_read(dp, MII_AN_ADVERT);
2945 
2946         gem_mii_write(dp, MII_AN_ADVERT,
2947             MII_ABILITY_PAUSE | MII_ABILITY_ASMPAUSE);
2948 
2949         adv = gem_mii_read(dp, MII_AN_ADVERT);
2950 
2951         if ((adv & MII_ABILITY_PAUSE) == 0) {
2952                 dp->gc.gc_flow_control &= ~1;
2953         }
2954 
2955         if ((adv & MII_ABILITY_ASMPAUSE) == 0) {
2956                 dp->gc.gc_flow_control &= ~2;
2957         }
2958 
2959         gem_mii_write(dp, MII_AN_ADVERT, adv_org);
2960 
2961         return (GEM_SUCCESS);
2962 }
2963 
2964 static void
2965 gem_mii_start(struct gem_dev *dp)
2966 {
2967         DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2968 
2969         /* make a first call of check link */
2970         dp->mii_state = MII_STATE_UNKNOWN;
2971         dp->mii_last_check = ddi_get_lbolt();
2972         dp->linkup_delay = dp->gc.gc_mii_linkdown_timeout;
2973         (void) gem_mii_link_watcher(dp);
2974 }
2975 
2976 static void
2977 gem_mii_stop(struct gem_dev *dp)
2978 {
2979         DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
2980 
2981         /* Ensure timer routine stopped */
2982         mutex_enter(&dp->intrlock);
2983         if (dp->link_watcher_id) {
2984                 while (untimeout(dp->link_watcher_id) == -1)
2985                         ;
2986                 dp->link_watcher_id = 0;
2987         }
2988         mutex_exit(&dp->intrlock);
2989 }
2990 
2991 boolean_t
2992 gem_get_mac_addr_conf(struct gem_dev *dp)
2993 {
2994         char            propname[32];
2995         char            *valstr;
2996         uint8_t         mac[ETHERADDRL];
2997         char            *cp;
2998         int             c;
2999         int             i;
3000         int             j;
3001         uint8_t         v;
3002         uint8_t         d;
3003         uint8_t         ored;
3004 
3005         DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3006         /*
3007          * Get ethernet address from .conf file
3008          */
3009         (void) sprintf(propname, "mac-addr");
3010         if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dp->dip,
3011             DDI_PROP_DONTPASS, propname, &valstr)) !=
3012             DDI_PROP_SUCCESS) {
3013                 return (B_FALSE);
3014         }
3015 
3016         if (strlen(valstr) != ETHERADDRL*3-1) {
3017                 goto syntax_err;
3018         }
3019 
3020         cp = valstr;
3021         j  = 0;
3022         ored = 0;
3023         for (;;) {
3024                 v = 0;
3025                 for (i = 0; i < 2; i++) {
3026                         c = *cp++;
3027 
3028                         if (c >= 'a' && c <= 'f') {
3029                                 d = c - 'a' + 10;
3030                         } else if (c >= 'A' && c <= 'F') {
3031                                 d = c - 'A' + 10;
3032                         } else if (c >= '0' && c <= '9') {
3033                                 d = c - '0';
3034                         } else {
3035                                 goto syntax_err;
3036                         }
3037                         v = (v << 4) | d;
3038                 }
3039 
3040                 mac[j++] = v;
3041                 ored |= v;
3042                 if (j == ETHERADDRL) {
3043                         /* done */
3044                         break;
3045                 }
3046 
3047                 c = *cp++;
3048                 if (c != ':') {
3049                         goto syntax_err;
3050                 }
3051         }
3052 
3053         if (ored == 0) {
3054                 goto err;
3055         }
3056         for (i = 0; i < ETHERADDRL; i++) {
3057                 dp->dev_addr.ether_addr_octet[i] = mac[i];
3058         }
3059         ddi_prop_free(valstr);
3060         return (B_TRUE);
3061 
3062 syntax_err:
3063         cmn_err(CE_CONT,
3064             "!%s: read mac addr: trying .conf: syntax err %s",
3065             dp->name, valstr);
3066 err:
3067         ddi_prop_free(valstr);
3068 
3069         return (B_FALSE);
3070 }
3071 
3072 
3073 /* ============================================================== */
3074 /*
3075  * internal start/stop interface
3076  */
3077 /* ============================================================== */
3078 static int
3079 gem_mac_set_rx_filter(struct gem_dev *dp)
3080 {
3081         return ((*dp->gc.gc_set_rx_filter)(dp));
3082 }
3083 
3084 /*
3085  * gem_mac_init: cold start
3086  */
3087 static int
3088 gem_mac_init(struct gem_dev *dp)
3089 {
3090         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3091 
3092         if (dp->mac_suspended) {
3093                 return (GEM_FAILURE);
3094         }
3095 
3096         dp->mac_active = B_FALSE;
3097 
3098         gem_init_rx_ring(dp);
3099         gem_init_tx_ring(dp);
3100 
3101         /* reset transmitter state */
3102         dp->tx_blocked = (clock_t)0;
3103         dp->tx_busy = 0;
3104         dp->tx_reclaim_busy = 0;
3105         dp->tx_max_packets = dp->gc.gc_tx_buf_limit;
3106 
3107         if ((*dp->gc.gc_init_chip)(dp) != GEM_SUCCESS) {
3108                 return (GEM_FAILURE);
3109         }
3110 
3111         gem_prepare_rx_buf(dp);
3112 
3113         return (GEM_SUCCESS);
3114 }
3115 /*
3116  * gem_mac_start: warm start
3117  */
3118 static int
3119 gem_mac_start(struct gem_dev *dp)
3120 {
3121         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3122 
3123         ASSERT(mutex_owned(&dp->intrlock));
3124         ASSERT(dp->nic_state == NIC_STATE_ONLINE);
3125         ASSERT(dp->mii_state ==  MII_STATE_LINKUP);
3126 
3127         /* enable tx and rx */
3128         mutex_enter(&dp->xmitlock);
3129         if (dp->mac_suspended) {
3130                 mutex_exit(&dp->xmitlock);
3131                 return (GEM_FAILURE);
3132         }
3133         dp->mac_active = B_TRUE;
3134         mutex_exit(&dp->xmitlock);
3135 
3136         /* setup rx buffers */
3137         (*dp->gc.gc_rx_start)(dp,
3138             SLOT(dp->rx_active_head, dp->gc.gc_rx_ring_size),
3139             dp->rx_active_tail - dp->rx_active_head);
3140 
3141         if ((*dp->gc.gc_start_chip)(dp) != GEM_SUCCESS) {
3142                 cmn_err(CE_WARN, "%s: %s: start_chip: failed",
3143                     dp->name, __func__);
3144                 return (GEM_FAILURE);
3145         }
3146 
3147         mutex_enter(&dp->xmitlock);
3148 
3149         /* load untranmitted packets to the nic */
3150         ASSERT(dp->tx_softq_tail - dp->tx_softq_head >= 0);
3151         if (dp->tx_softq_tail - dp->tx_softq_head > 0) {
3152                 gem_tx_load_descs_oo(dp,
3153                     dp->tx_softq_head, dp->tx_softq_tail,
3154                     GEM_TXFLAG_HEAD);
3155                 /* issue preloaded tx buffers */
3156                 gem_tx_start_unit(dp);
3157         }
3158 
3159         mutex_exit(&dp->xmitlock);
3160 
3161         return (GEM_SUCCESS);
3162 }
3163 
3164 static int
3165 gem_mac_stop(struct gem_dev *dp, uint_t flags)
3166 {
3167         int             i;
3168         int             wait_time; /* in uS */
3169 #ifdef GEM_DEBUG_LEVEL
3170         clock_t         now;
3171 #endif
3172         int             ret = GEM_SUCCESS;
3173 
3174         DPRINTF(1, (CE_CONT, "!%s: %s: called, rx_buf_free:%d",
3175             dp->name, __func__, dp->rx_buf_freecnt));
3176 
3177         ASSERT(mutex_owned(&dp->intrlock));
3178         ASSERT(!mutex_owned(&dp->xmitlock));
3179 
3180         /*
3181          * Block transmits
3182          */
3183         mutex_enter(&dp->xmitlock);
3184         if (dp->mac_suspended) {
3185                 mutex_exit(&dp->xmitlock);
3186                 return (GEM_SUCCESS);
3187         }
3188         dp->mac_active = B_FALSE;
3189 
3190         while (dp->tx_busy > 0) {
3191                 cv_wait(&dp->tx_drain_cv, &dp->xmitlock);
3192         }
3193         mutex_exit(&dp->xmitlock);
3194 
3195         if ((flags & GEM_RESTART_NOWAIT) == 0) {
3196                 /*
3197                  * Wait for all tx buffers sent.
3198                  */
3199                 wait_time =
3200                     2 * (8 * MAXPKTBUF(dp) / gem_speed_value[dp->speed]) *
3201                     (dp->tx_active_tail - dp->tx_active_head);
3202 
3203                 DPRINTF(0, (CE_CONT, "%s: %s: max drain time: %d uS",
3204                     dp->name, __func__, wait_time));
3205                 i = 0;
3206 #ifdef GEM_DEBUG_LEVEL
3207                 now = ddi_get_lbolt();
3208 #endif
3209                 while (dp->tx_active_tail != dp->tx_active_head) {
3210                         if (i > wait_time) {
3211                                 /* timeout */
3212                                 cmn_err(CE_NOTE, "%s: %s timeout: tx drain",
3213                                     dp->name, __func__);
3214                                 break;
3215                         }
3216                         (void) gem_reclaim_txbuf(dp);
3217                         drv_usecwait(100);
3218                         i += 100;
3219                 }
3220                 DPRINTF(0, (CE_NOTE,
3221                     "!%s: %s: the nic have drained in %d uS, real %d mS",
3222                     dp->name, __func__, i,
3223                     10*((int)(ddi_get_lbolt() - now))));
3224         }
3225 
3226         /*
3227          * Now we can stop the nic safely.
3228          */
3229         if ((*dp->gc.gc_stop_chip)(dp) != GEM_SUCCESS) {
3230                 cmn_err(CE_NOTE, "%s: %s: resetting the chip to stop it",
3231                     dp->name, __func__);
3232                 if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
3233                         cmn_err(CE_WARN, "%s: %s: failed to reset chip",
3234                             dp->name, __func__);
3235                 }
3236         }
3237 
3238         /*
3239          * Clear all rx buffers
3240          */
3241         if (flags & GEM_RESTART_KEEP_BUF) {
3242                 (void) gem_receive(dp);
3243         }
3244         gem_clean_rx_buf(dp);
3245 
3246         /*
3247          * Update final statistics
3248          */
3249         (*dp->gc.gc_get_stats)(dp);
3250 
3251         /*
3252          * Clear all pended tx packets
3253          */
3254         ASSERT(dp->tx_active_tail == dp->tx_softq_head);
3255         ASSERT(dp->tx_softq_tail == dp->tx_free_head);
3256         if (flags & GEM_RESTART_KEEP_BUF) {
3257                 /* restore active tx buffers */
3258                 dp->tx_active_tail = dp->tx_active_head;
3259                 dp->tx_softq_head  = dp->tx_active_head;
3260         } else {
3261                 gem_clean_tx_buf(dp);
3262         }
3263 
3264         return (ret);
3265 }
3266 
3267 static int
3268 gem_add_multicast(struct gem_dev *dp, const uint8_t *ep)
3269 {
3270         int             cnt;
3271         int             err;
3272 
3273         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3274 
3275         mutex_enter(&dp->intrlock);
3276         if (dp->mac_suspended) {
3277                 mutex_exit(&dp->intrlock);
3278                 return (GEM_FAILURE);
3279         }
3280 
3281         if (dp->mc_count_req++ < GEM_MAXMC) {
3282                 /* append the new address at the end of the mclist */
3283                 cnt = dp->mc_count;
3284                 bcopy(ep, dp->mc_list[cnt].addr.ether_addr_octet,
3285                     ETHERADDRL);
3286                 if (dp->gc.gc_multicast_hash) {
3287                         dp->mc_list[cnt].hash =
3288                             (*dp->gc.gc_multicast_hash)(dp, (uint8_t *)ep);
3289                 }
3290                 dp->mc_count = cnt + 1;
3291         }
3292 
3293         if (dp->mc_count_req != dp->mc_count) {
3294                 /* multicast address list overflow */
3295                 dp->rxmode |= RXMODE_MULTI_OVF;
3296         } else {
3297                 dp->rxmode &= ~RXMODE_MULTI_OVF;
3298         }
3299 
3300         /* tell new multicast list to the hardware */
3301         err = gem_mac_set_rx_filter(dp);
3302 
3303         mutex_exit(&dp->intrlock);
3304 
3305         return (err);
3306 }
3307 
3308 static int
3309 gem_remove_multicast(struct gem_dev *dp, const uint8_t *ep)
3310 {
3311         size_t          len;
3312         int             i;
3313         int             cnt;
3314         int             err;
3315 
3316         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3317 
3318         mutex_enter(&dp->intrlock);
3319         if (dp->mac_suspended) {
3320                 mutex_exit(&dp->intrlock);
3321                 return (GEM_FAILURE);
3322         }
3323 
3324         dp->mc_count_req--;
3325         cnt = dp->mc_count;
3326         for (i = 0; i < cnt; i++) {
3327                 if (bcmp(ep, &dp->mc_list[i].addr, ETHERADDRL)) {
3328                         continue;
3329                 }
3330                 /* shrink the mclist by copying forward */
3331                 len = (cnt - (i + 1)) * sizeof (*dp->mc_list);
3332                 if (len > 0) {
3333                         bcopy(&dp->mc_list[i+1], &dp->mc_list[i], len);
3334                 }
3335                 dp->mc_count--;
3336                 break;
3337         }
3338 
3339         if (dp->mc_count_req != dp->mc_count) {
3340                 /* multicast address list overflow */
3341                 dp->rxmode |= RXMODE_MULTI_OVF;
3342         } else {
3343                 dp->rxmode &= ~RXMODE_MULTI_OVF;
3344         }
3345         /* In gem v2, don't hold xmitlock on calling set_rx_filter */
3346         err = gem_mac_set_rx_filter(dp);
3347 
3348         mutex_exit(&dp->intrlock);
3349 
3350         return (err);
3351 }
3352 
3353 /* ============================================================== */
3354 /*
3355  * ND interface
3356  */
3357 /* ============================================================== */
3358 enum {
3359         PARAM_AUTONEG_CAP,
3360         PARAM_PAUSE_CAP,
3361         PARAM_ASYM_PAUSE_CAP,
3362         PARAM_1000FDX_CAP,
3363         PARAM_1000HDX_CAP,
3364         PARAM_100T4_CAP,
3365         PARAM_100FDX_CAP,
3366         PARAM_100HDX_CAP,
3367         PARAM_10FDX_CAP,
3368         PARAM_10HDX_CAP,
3369 
3370         PARAM_ADV_AUTONEG_CAP,
3371         PARAM_ADV_PAUSE_CAP,
3372         PARAM_ADV_ASYM_PAUSE_CAP,
3373         PARAM_ADV_1000FDX_CAP,
3374         PARAM_ADV_1000HDX_CAP,
3375         PARAM_ADV_100T4_CAP,
3376         PARAM_ADV_100FDX_CAP,
3377         PARAM_ADV_100HDX_CAP,
3378         PARAM_ADV_10FDX_CAP,
3379         PARAM_ADV_10HDX_CAP,
3380 
3381         PARAM_LP_AUTONEG_CAP,
3382         PARAM_LP_PAUSE_CAP,
3383         PARAM_LP_ASYM_PAUSE_CAP,
3384         PARAM_LP_1000FDX_CAP,
3385         PARAM_LP_1000HDX_CAP,
3386         PARAM_LP_100T4_CAP,
3387         PARAM_LP_100FDX_CAP,
3388         PARAM_LP_100HDX_CAP,
3389         PARAM_LP_10FDX_CAP,
3390         PARAM_LP_10HDX_CAP,
3391 
3392         PARAM_LINK_STATUS,
3393         PARAM_LINK_SPEED,
3394         PARAM_LINK_DUPLEX,
3395 
3396         PARAM_LINK_AUTONEG,
3397         PARAM_LINK_RX_PAUSE,
3398         PARAM_LINK_TX_PAUSE,
3399 
3400         PARAM_LOOP_MODE,
3401         PARAM_MSI_CNT,
3402 
3403 #ifdef DEBUG_RESUME
3404         PARAM_RESUME_TEST,
3405 #endif
3406         PARAM_COUNT
3407 };
3408 
3409 enum ioc_reply {
3410         IOC_INVAL = -1,                         /* bad, NAK with EINVAL */
3411         IOC_DONE,                               /* OK, reply sent       */
3412         IOC_ACK,                                /* OK, just send ACK    */
3413         IOC_REPLY,                              /* OK, just send reply  */
3414         IOC_RESTART_ACK,                        /* OK, restart & ACK        */
3415         IOC_RESTART_REPLY                       /* OK, restart & reply      */
3416 };
3417 
3418 struct gem_nd_arg {
3419         struct gem_dev  *dp;
3420         int             item;
3421 };
3422 
3423 static int
3424 gem_param_get(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *credp)
3425 {
3426         struct gem_dev  *dp = ((struct gem_nd_arg *)(void *)arg)->dp;
3427         int             item = ((struct gem_nd_arg *)(void *)arg)->item;
3428         long            val;
3429 
3430         DPRINTF(0, (CE_CONT, "!%s: %s: called, item:%d",
3431             dp->name, __func__, item));
3432 
3433         switch (item) {
3434         case PARAM_AUTONEG_CAP:
3435                 val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
3436                 DPRINTF(0, (CE_CONT, "autoneg_cap:%d", val));
3437                 break;
3438 
3439         case PARAM_PAUSE_CAP:
3440                 val = BOOLEAN(dp->gc.gc_flow_control & 1);
3441                 break;
3442 
3443         case PARAM_ASYM_PAUSE_CAP:
3444                 val = BOOLEAN(dp->gc.gc_flow_control & 2);
3445                 break;
3446 
3447         case PARAM_1000FDX_CAP:
3448                 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
3449                     (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
3450                 break;
3451 
3452         case PARAM_1000HDX_CAP:
3453                 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
3454                     (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
3455                 break;
3456 
3457         case PARAM_100T4_CAP:
3458                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
3459                 break;
3460 
3461         case PARAM_100FDX_CAP:
3462                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
3463                 break;
3464 
3465         case PARAM_100HDX_CAP:
3466                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
3467                 break;
3468 
3469         case PARAM_10FDX_CAP:
3470                 val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
3471                 break;
3472 
3473         case PARAM_10HDX_CAP:
3474                 val = BOOLEAN(dp->mii_status & MII_STATUS_10);
3475                 break;
3476 
3477         case PARAM_ADV_AUTONEG_CAP:
3478                 val = dp->anadv_autoneg;
3479                 break;
3480 
3481         case PARAM_ADV_PAUSE_CAP:
3482                 val = BOOLEAN(dp->anadv_flow_control & 1);
3483                 break;
3484 
3485         case PARAM_ADV_ASYM_PAUSE_CAP:
3486                 val = BOOLEAN(dp->anadv_flow_control & 2);
3487                 break;
3488 
3489         case PARAM_ADV_1000FDX_CAP:
3490                 val = dp->anadv_1000fdx;
3491                 break;
3492 
3493         case PARAM_ADV_1000HDX_CAP:
3494                 val = dp->anadv_1000hdx;
3495                 break;
3496 
3497         case PARAM_ADV_100T4_CAP:
3498                 val = dp->anadv_100t4;
3499                 break;
3500 
3501         case PARAM_ADV_100FDX_CAP:
3502                 val = dp->anadv_100fdx;
3503                 break;
3504 
3505         case PARAM_ADV_100HDX_CAP:
3506                 val = dp->anadv_100hdx;
3507                 break;
3508 
3509         case PARAM_ADV_10FDX_CAP:
3510                 val = dp->anadv_10fdx;
3511                 break;
3512 
3513         case PARAM_ADV_10HDX_CAP:
3514                 val = dp->anadv_10hdx;
3515                 break;
3516 
3517         case PARAM_LP_AUTONEG_CAP:
3518                 val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3519                 break;
3520 
3521         case PARAM_LP_PAUSE_CAP:
3522                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE);
3523                 break;
3524 
3525         case PARAM_LP_ASYM_PAUSE_CAP:
3526                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASMPAUSE);
3527                 break;
3528 
3529         case PARAM_LP_1000FDX_CAP:
3530                 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
3531                 break;
3532 
3533         case PARAM_LP_1000HDX_CAP:
3534                 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
3535                 break;
3536 
3537         case PARAM_LP_100T4_CAP:
3538                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4);
3539                 break;
3540 
3541         case PARAM_LP_100FDX_CAP:
3542                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
3543                 break;
3544 
3545         case PARAM_LP_100HDX_CAP:
3546                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
3547                 break;
3548 
3549         case PARAM_LP_10FDX_CAP:
3550                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
3551                 break;
3552 
3553         case PARAM_LP_10HDX_CAP:
3554                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
3555                 break;
3556 
3557         case PARAM_LINK_STATUS:
3558                 val = (dp->mii_state == MII_STATE_LINKUP);
3559                 break;
3560 
3561         case PARAM_LINK_SPEED:
3562                 val = gem_speed_value[dp->speed];
3563                 break;
3564 
3565         case PARAM_LINK_DUPLEX:
3566                 val = 0;
3567                 if (dp->mii_state == MII_STATE_LINKUP) {
3568                         val = dp->full_duplex ? 2 : 1;
3569                 }
3570                 break;
3571 
3572         case PARAM_LINK_AUTONEG:
3573                 val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
3574                 break;
3575 
3576         case PARAM_LINK_RX_PAUSE:
3577                 val = (dp->flow_control == FLOW_CONTROL_SYMMETRIC) ||
3578                     (dp->flow_control == FLOW_CONTROL_RX_PAUSE);
3579                 break;
3580 
3581         case PARAM_LINK_TX_PAUSE:
3582                 val = (dp->flow_control == FLOW_CONTROL_SYMMETRIC) ||
3583                     (dp->flow_control == FLOW_CONTROL_TX_PAUSE);
3584                 break;
3585 
3586 #ifdef DEBUG_RESUME
3587         case PARAM_RESUME_TEST:
3588                 val = 0;
3589                 break;
3590 #endif
3591         default:
3592                 cmn_err(CE_WARN, "%s: unimplemented ndd control (%d)",
3593                     dp->name, item);
3594                 break;
3595         }
3596 
3597         (void) mi_mpprintf(mp, "%ld", val);
3598 
3599         return (0);
3600 }
3601 
3602 static int
3603 gem_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t arg, cred_t *credp)
3604 {
3605         struct gem_dev  *dp = ((struct gem_nd_arg *)(void *)arg)->dp;
3606         int             item = ((struct gem_nd_arg *)(void *)arg)->item;
3607         long            val;
3608         char            *end;
3609 
3610         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3611         if (ddi_strtol(value, &end, 10, &val)) {
3612                 return (EINVAL);
3613         }
3614         if (end == value) {
3615                 return (EINVAL);
3616         }
3617 
3618         switch (item) {
3619         case PARAM_ADV_AUTONEG_CAP:
3620                 if (val != 0 && val != 1) {
3621                         goto err;
3622                 }
3623                 if (val && (dp->mii_status & MII_STATUS_CANAUTONEG) == 0) {
3624                         goto err;
3625                 }
3626                 dp->anadv_autoneg = (int)val;
3627                 break;
3628 
3629         case PARAM_ADV_PAUSE_CAP:
3630                 if (val != 0 && val != 1) {
3631                         goto err;
3632                 }
3633                 if (val) {
3634                         dp->anadv_flow_control |= 1;
3635                 } else {
3636                         dp->anadv_flow_control &= ~1;
3637                 }
3638                 break;
3639 
3640         case PARAM_ADV_ASYM_PAUSE_CAP:
3641                 if (val != 0 && val != 1) {
3642                         goto err;
3643                 }
3644                 if (val) {
3645                         dp->anadv_flow_control |= 2;
3646                 } else {
3647                         dp->anadv_flow_control &= ~2;
3648                 }
3649                 break;
3650 
3651         case PARAM_ADV_1000FDX_CAP:
3652                 if (val != 0 && val != 1) {
3653                         goto err;
3654                 }
3655                 if (val && (dp->mii_xstatus &
3656                     (MII_XSTATUS_1000BASET_FD |
3657                     MII_XSTATUS_1000BASEX_FD)) == 0) {
3658                         goto err;
3659                 }
3660                 dp->anadv_1000fdx = (int)val;
3661                 break;
3662 
3663         case PARAM_ADV_1000HDX_CAP:
3664                 if (val != 0 && val != 1) {
3665                         goto err;
3666                 }
3667                 if (val && (dp->mii_xstatus &
3668                     (MII_XSTATUS_1000BASET | MII_XSTATUS_1000BASEX)) == 0) {
3669                         goto err;
3670                 }
3671                 dp->anadv_1000hdx = (int)val;
3672                 break;
3673 
3674         case PARAM_ADV_100T4_CAP:
3675                 if (val != 0 && val != 1) {
3676                         goto err;
3677                 }
3678                 if (val && (dp->mii_status & MII_STATUS_100_BASE_T4) == 0) {
3679                         goto err;
3680                 }
3681                 dp->anadv_100t4 = (int)val;
3682                 break;
3683 
3684         case PARAM_ADV_100FDX_CAP:
3685                 if (val != 0 && val != 1) {
3686                         goto err;
3687                 }
3688                 if (val && (dp->mii_status & MII_STATUS_100_BASEX_FD) == 0) {
3689                         goto err;
3690                 }
3691                 dp->anadv_100fdx = (int)val;
3692                 break;
3693 
3694         case PARAM_ADV_100HDX_CAP:
3695                 if (val != 0 && val != 1) {
3696                         goto err;
3697                 }
3698                 if (val && (dp->mii_status & MII_STATUS_100_BASEX) == 0) {
3699                         goto err;
3700                 }
3701                 dp->anadv_100hdx = (int)val;
3702                 break;
3703 
3704         case PARAM_ADV_10FDX_CAP:
3705                 if (val != 0 && val != 1) {
3706                         goto err;
3707                 }
3708                 if (val && (dp->mii_status & MII_STATUS_10_FD) == 0) {
3709                         goto err;
3710                 }
3711                 dp->anadv_10fdx = (int)val;
3712                 break;
3713 
3714         case PARAM_ADV_10HDX_CAP:
3715                 if (val != 0 && val != 1) {
3716                         goto err;
3717                 }
3718                 if (val && (dp->mii_status & MII_STATUS_10) == 0) {
3719                         goto err;
3720                 }
3721                 dp->anadv_10hdx = (int)val;
3722                 break;
3723         }
3724 
3725         /* sync with PHY */
3726         gem_choose_forcedmode(dp);
3727 
3728         dp->mii_state = MII_STATE_UNKNOWN;
3729         if (dp->gc.gc_mii_hw_link_detection && dp->link_watcher_id == 0) {
3730                 /* XXX - Can we ignore the return code ? */
3731                 (void) gem_mii_link_check(dp);
3732         }
3733 
3734         return (0);
3735 err:
3736         return (EINVAL);
3737 }
3738 
3739 static void
3740 gem_nd_load(struct gem_dev *dp, char *name, ndgetf_t gf, ndsetf_t sf, int item)
3741 {
3742         struct gem_nd_arg       *arg;
3743 
3744         ASSERT(item >= 0);
3745         ASSERT(item < PARAM_COUNT);
3746 
3747         arg = &((struct gem_nd_arg *)(void *)dp->nd_arg_p)[item];
3748         arg->dp = dp;
3749         arg->item = item;
3750 
3751         DPRINTF(2, (CE_CONT, "!%s: %s: name:%s, item:%d",
3752             dp->name, __func__, name, item));
3753         (void) nd_load(&dp->nd_data_p, name, gf, sf, (caddr_t)arg);
3754 }
3755 
3756 static void
3757 gem_nd_setup(struct gem_dev *dp)
3758 {
3759         DPRINTF(0, (CE_CONT, "!%s: %s: called, mii_status:0x%b",
3760             dp->name, __func__, dp->mii_status, MII_STATUS_BITS));
3761 
3762         ASSERT(dp->nd_arg_p == NULL);
3763 
3764         dp->nd_arg_p =
3765             kmem_zalloc(sizeof (struct gem_nd_arg) * PARAM_COUNT, KM_SLEEP);
3766 
3767 #define SETFUNC(x)      ((x) ? gem_param_set : NULL)
3768 
3769         gem_nd_load(dp, "autoneg_cap",
3770             gem_param_get, NULL, PARAM_AUTONEG_CAP);
3771         gem_nd_load(dp, "pause_cap",
3772             gem_param_get, NULL, PARAM_PAUSE_CAP);
3773         gem_nd_load(dp, "asym_pause_cap",
3774             gem_param_get, NULL, PARAM_ASYM_PAUSE_CAP);
3775         gem_nd_load(dp, "1000fdx_cap",
3776             gem_param_get, NULL, PARAM_1000FDX_CAP);
3777         gem_nd_load(dp, "1000hdx_cap",
3778             gem_param_get, NULL, PARAM_1000HDX_CAP);
3779         gem_nd_load(dp, "100T4_cap",
3780             gem_param_get, NULL, PARAM_100T4_CAP);
3781         gem_nd_load(dp, "100fdx_cap",
3782             gem_param_get, NULL, PARAM_100FDX_CAP);
3783         gem_nd_load(dp, "100hdx_cap",
3784             gem_param_get, NULL, PARAM_100HDX_CAP);
3785         gem_nd_load(dp, "10fdx_cap",
3786             gem_param_get, NULL, PARAM_10FDX_CAP);
3787         gem_nd_load(dp, "10hdx_cap",
3788             gem_param_get, NULL, PARAM_10HDX_CAP);
3789 
3790         /* Our advertised capabilities */
3791         gem_nd_load(dp, "adv_autoneg_cap", gem_param_get,
3792             SETFUNC(dp->mii_status & MII_STATUS_CANAUTONEG),
3793             PARAM_ADV_AUTONEG_CAP);
3794         gem_nd_load(dp, "adv_pause_cap", gem_param_get,
3795             SETFUNC(dp->gc.gc_flow_control & 1),
3796             PARAM_ADV_PAUSE_CAP);
3797         gem_nd_load(dp, "adv_asym_pause_cap", gem_param_get,
3798             SETFUNC(dp->gc.gc_flow_control & 2),
3799             PARAM_ADV_ASYM_PAUSE_CAP);
3800         gem_nd_load(dp, "adv_1000fdx_cap", gem_param_get,
3801             SETFUNC(dp->mii_xstatus &
3802             (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD)),
3803             PARAM_ADV_1000FDX_CAP);
3804         gem_nd_load(dp, "adv_1000hdx_cap", gem_param_get,
3805             SETFUNC(dp->mii_xstatus &
3806             (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET)),
3807             PARAM_ADV_1000HDX_CAP);
3808         gem_nd_load(dp, "adv_100T4_cap", gem_param_get,
3809             SETFUNC((dp->mii_status & MII_STATUS_100_BASE_T4) &&
3810             !dp->mii_advert_ro),
3811             PARAM_ADV_100T4_CAP);
3812         gem_nd_load(dp, "adv_100fdx_cap", gem_param_get,
3813             SETFUNC((dp->mii_status & MII_STATUS_100_BASEX_FD) &&
3814             !dp->mii_advert_ro),
3815             PARAM_ADV_100FDX_CAP);
3816         gem_nd_load(dp, "adv_100hdx_cap", gem_param_get,
3817             SETFUNC((dp->mii_status & MII_STATUS_100_BASEX) &&
3818             !dp->mii_advert_ro),
3819             PARAM_ADV_100HDX_CAP);
3820         gem_nd_load(dp, "adv_10fdx_cap", gem_param_get,
3821             SETFUNC((dp->mii_status & MII_STATUS_10_FD) &&
3822             !dp->mii_advert_ro),
3823             PARAM_ADV_10FDX_CAP);
3824         gem_nd_load(dp, "adv_10hdx_cap", gem_param_get,
3825             SETFUNC((dp->mii_status & MII_STATUS_10) &&
3826             !dp->mii_advert_ro),
3827             PARAM_ADV_10HDX_CAP);
3828 
3829         /* Partner's advertised capabilities */
3830         gem_nd_load(dp, "lp_autoneg_cap",
3831             gem_param_get, NULL, PARAM_LP_AUTONEG_CAP);
3832         gem_nd_load(dp, "lp_pause_cap",
3833             gem_param_get, NULL, PARAM_LP_PAUSE_CAP);
3834         gem_nd_load(dp, "lp_asym_pause_cap",
3835             gem_param_get, NULL, PARAM_LP_ASYM_PAUSE_CAP);
3836         gem_nd_load(dp, "lp_1000fdx_cap",
3837             gem_param_get, NULL, PARAM_LP_1000FDX_CAP);
3838         gem_nd_load(dp, "lp_1000hdx_cap",
3839             gem_param_get, NULL, PARAM_LP_1000HDX_CAP);
3840         gem_nd_load(dp, "lp_100T4_cap",
3841             gem_param_get, NULL, PARAM_LP_100T4_CAP);
3842         gem_nd_load(dp, "lp_100fdx_cap",
3843             gem_param_get, NULL, PARAM_LP_100FDX_CAP);
3844         gem_nd_load(dp, "lp_100hdx_cap",
3845             gem_param_get, NULL, PARAM_LP_100HDX_CAP);
3846         gem_nd_load(dp, "lp_10fdx_cap",
3847             gem_param_get, NULL, PARAM_LP_10FDX_CAP);
3848         gem_nd_load(dp, "lp_10hdx_cap",
3849             gem_param_get, NULL, PARAM_LP_10HDX_CAP);
3850 
3851         /* Current operating modes */
3852         gem_nd_load(dp, "link_status",
3853             gem_param_get, NULL, PARAM_LINK_STATUS);
3854         gem_nd_load(dp, "link_speed",
3855             gem_param_get, NULL, PARAM_LINK_SPEED);
3856         gem_nd_load(dp, "link_duplex",
3857             gem_param_get, NULL, PARAM_LINK_DUPLEX);
3858         gem_nd_load(dp, "link_autoneg",
3859             gem_param_get, NULL, PARAM_LINK_AUTONEG);
3860         gem_nd_load(dp, "link_rx_pause",
3861             gem_param_get, NULL, PARAM_LINK_RX_PAUSE);
3862         gem_nd_load(dp, "link_tx_pause",
3863             gem_param_get, NULL, PARAM_LINK_TX_PAUSE);
3864 #ifdef DEBUG_RESUME
3865         gem_nd_load(dp, "resume_test",
3866             gem_param_get, NULL, PARAM_RESUME_TEST);
3867 #endif
3868 #undef  SETFUNC
3869 }
3870 
3871 static
3872 enum ioc_reply
3873 gem_nd_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
3874 {
3875         boolean_t       ok;
3876 
3877         ASSERT(mutex_owned(&dp->intrlock));
3878 
3879         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3880 
3881         switch (iocp->ioc_cmd) {
3882         case ND_GET:
3883                 ok = nd_getset(wq, dp->nd_data_p, mp);
3884                 DPRINTF(0, (CE_CONT,
3885                     "%s: get %s", dp->name, ok ? "OK" : "FAIL"));
3886                 return (ok ? IOC_REPLY : IOC_INVAL);
3887 
3888         case ND_SET:
3889                 ok = nd_getset(wq, dp->nd_data_p, mp);
3890 
3891                 DPRINTF(0, (CE_CONT, "%s: set %s err %d",
3892                     dp->name, ok ? "OK" : "FAIL", iocp->ioc_error));
3893 
3894                 if (!ok) {
3895                         return (IOC_INVAL);
3896                 }
3897 
3898                 if (iocp->ioc_error) {
3899                         return (IOC_REPLY);
3900                 }
3901 
3902                 return (IOC_RESTART_REPLY);
3903         }
3904 
3905         cmn_err(CE_WARN, "%s: invalid cmd 0x%x", dp->name, iocp->ioc_cmd);
3906 
3907         return (IOC_INVAL);
3908 }
3909 
3910 static void
3911 gem_nd_cleanup(struct gem_dev *dp)
3912 {
3913         ASSERT(dp->nd_data_p != NULL);
3914         ASSERT(dp->nd_arg_p != NULL);
3915 
3916         nd_free(&dp->nd_data_p);
3917 
3918         kmem_free(dp->nd_arg_p, sizeof (struct gem_nd_arg) * PARAM_COUNT);
3919         dp->nd_arg_p = NULL;
3920 }
3921 
3922 static void
3923 gem_mac_ioctl(struct gem_dev *dp, queue_t *wq, mblk_t *mp)
3924 {
3925         struct iocblk   *iocp;
3926         enum ioc_reply  status;
3927         int             cmd;
3928 
3929         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
3930 
3931         /*
3932          * Validate the command before bothering with the mutex ...
3933          */
3934         iocp = (void *)mp->b_rptr;
3935         iocp->ioc_error = 0;
3936         cmd = iocp->ioc_cmd;
3937 
3938         DPRINTF(0, (CE_CONT, "%s: %s cmd:0x%x", dp->name, __func__, cmd));
3939 
3940         mutex_enter(&dp->intrlock);
3941         mutex_enter(&dp->xmitlock);
3942 
3943         switch (cmd) {
3944         default:
3945                 _NOTE(NOTREACHED)
3946                 status = IOC_INVAL;
3947                 break;
3948 
3949         case ND_GET:
3950         case ND_SET:
3951                 status = gem_nd_ioctl(dp, wq, mp, iocp);
3952                 break;
3953         }
3954 
3955         mutex_exit(&dp->xmitlock);
3956         mutex_exit(&dp->intrlock);
3957 
3958 #ifdef DEBUG_RESUME
3959         if (cmd == ND_GET)  {
3960                 gem_suspend(dp->dip);
3961                 gem_resume(dp->dip);
3962         }
3963 #endif
3964         /*
3965          * Finally, decide how to reply
3966          */
3967         switch (status) {
3968         default:
3969         case IOC_INVAL:
3970                 /*
3971                  * Error, reply with a NAK and EINVAL or the specified error
3972                  */
3973                 miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
3974                     EINVAL : iocp->ioc_error);
3975                 break;
3976 
3977         case IOC_DONE:
3978                 /*
3979                  * OK, reply already sent
3980                  */
3981                 break;
3982 
3983         case IOC_RESTART_ACK:
3984         case IOC_ACK:
3985                 /*
3986                  * OK, reply with an ACK
3987                  */
3988                 miocack(wq, mp, 0, 0);
3989                 break;
3990 
3991         case IOC_RESTART_REPLY:
3992         case IOC_REPLY:
3993                 /*
3994                  * OK, send prepared reply as ACK or NAK
3995                  */
3996                 mp->b_datap->db_type =
3997                     iocp->ioc_error == 0 ? M_IOCACK : M_IOCNAK;
3998                 qreply(wq, mp);
3999                 break;
4000         }
4001 }
4002 
4003 #ifndef SYS_MAC_H
4004 #define XCVR_UNDEFINED  0
4005 #define XCVR_NONE       1
4006 #define XCVR_10         2
4007 #define XCVR_100T4      3
4008 #define XCVR_100X       4
4009 #define XCVR_100T2      5
4010 #define XCVR_1000X      6
4011 #define XCVR_1000T      7
4012 #endif
4013 static int
4014 gem_mac_xcvr_inuse(struct gem_dev *dp)
4015 {
4016         int     val = XCVR_UNDEFINED;
4017 
4018         if ((dp->mii_status & MII_STATUS_XSTATUS) == 0) {
4019                 if (dp->mii_status & MII_STATUS_100_BASE_T4) {
4020                         val = XCVR_100T4;
4021                 } else if (dp->mii_status &
4022                     (MII_STATUS_100_BASEX_FD |
4023                     MII_STATUS_100_BASEX)) {
4024                         val = XCVR_100X;
4025                 } else if (dp->mii_status &
4026                     (MII_STATUS_100_BASE_T2_FD |
4027                     MII_STATUS_100_BASE_T2)) {
4028                         val = XCVR_100T2;
4029                 } else if (dp->mii_status &
4030                     (MII_STATUS_10_FD | MII_STATUS_10)) {
4031                         val = XCVR_10;
4032                 }
4033         } else if (dp->mii_xstatus &
4034             (MII_XSTATUS_1000BASET_FD | MII_XSTATUS_1000BASET)) {
4035                 val = XCVR_1000T;
4036         } else if (dp->mii_xstatus &
4037             (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASEX)) {
4038                 val = XCVR_1000X;
4039         }
4040 
4041         return (val);
4042 }
4043 
4044 /* ============================================================== */
4045 /*
4046  * GLDv3 interface
4047  */
4048 /* ============================================================== */
4049 static int              gem_m_getstat(void *, uint_t, uint64_t *);
4050 static int              gem_m_start(void *);
4051 static void             gem_m_stop(void *);
4052 static int              gem_m_setpromisc(void *, boolean_t);
4053 static int              gem_m_multicst(void *, boolean_t, const uint8_t *);
4054 static int              gem_m_unicst(void *, const uint8_t *);
4055 static mblk_t           *gem_m_tx(void *, mblk_t *);
4056 static void             gem_m_ioctl(void *, queue_t *, mblk_t *);
4057 static boolean_t        gem_m_getcapab(void *, mac_capab_t, void *);
4058 
4059 #define GEM_M_CALLBACK_FLAGS    (MC_IOCTL | MC_GETCAPAB)
4060 
4061 static mac_callbacks_t gem_m_callbacks = {
4062         GEM_M_CALLBACK_FLAGS,
4063         gem_m_getstat,
4064         gem_m_start,
4065         gem_m_stop,
4066         gem_m_setpromisc,
4067         gem_m_multicst,
4068         gem_m_unicst,
4069         gem_m_tx,
4070         NULL,
4071         gem_m_ioctl,
4072         gem_m_getcapab,
4073 };
4074 
4075 static int
4076 gem_m_start(void *arg)
4077 {
4078         int             err = 0;
4079         struct gem_dev *dp = arg;
4080 
4081         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4082 
4083         mutex_enter(&dp->intrlock);
4084         if (dp->mac_suspended) {
4085                 err = EIO;
4086                 goto x;
4087         }
4088         if (gem_mac_init(dp) != GEM_SUCCESS) {
4089                 err = EIO;
4090                 goto x;
4091         }
4092         dp->nic_state = NIC_STATE_INITIALIZED;
4093 
4094         /* reset rx filter state */
4095         dp->mc_count = 0;
4096         dp->mc_count_req = 0;
4097 
4098         /* setup media mode if the link have been up */
4099         if (dp->mii_state == MII_STATE_LINKUP) {
4100                 (dp->gc.gc_set_media)(dp);
4101         }
4102 
4103         /* setup initial rx filter */
4104         bcopy(dp->dev_addr.ether_addr_octet,
4105             dp->cur_addr.ether_addr_octet, ETHERADDRL);
4106         dp->rxmode |= RXMODE_ENABLE;
4107 
4108         if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4109                 err = EIO;
4110                 goto x;
4111         }
4112 
4113         dp->nic_state = NIC_STATE_ONLINE;
4114         if (dp->mii_state == MII_STATE_LINKUP) {
4115                 if (gem_mac_start(dp) != GEM_SUCCESS) {
4116                         err = EIO;
4117                         goto x;
4118                 }
4119         }
4120 
4121         dp->timeout_id = timeout((void (*)(void *))gem_tx_timeout,
4122             (void *)dp, dp->gc.gc_tx_timeout_interval);
4123         mutex_exit(&dp->intrlock);
4124 
4125         return (0);
4126 x:
4127         dp->nic_state = NIC_STATE_STOPPED;
4128         mutex_exit(&dp->intrlock);
4129         return (err);
4130 }
4131 
4132 static void
4133 gem_m_stop(void *arg)
4134 {
4135         struct gem_dev  *dp = arg;
4136 
4137         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4138 
4139         /* stop rx */
4140         mutex_enter(&dp->intrlock);
4141         if (dp->mac_suspended) {
4142                 mutex_exit(&dp->intrlock);
4143                 return;
4144         }
4145         dp->rxmode &= ~RXMODE_ENABLE;
4146         (void) gem_mac_set_rx_filter(dp);
4147         mutex_exit(&dp->intrlock);
4148 
4149         /* stop tx timeout watcher */
4150         if (dp->timeout_id) {
4151                 while (untimeout(dp->timeout_id) == -1)
4152                         ;
4153                 dp->timeout_id = 0;
4154         }
4155 
4156         /* make the nic state inactive */
4157         mutex_enter(&dp->intrlock);
4158         if (dp->mac_suspended) {
4159                 mutex_exit(&dp->intrlock);
4160                 return;
4161         }
4162         dp->nic_state = NIC_STATE_STOPPED;
4163 
4164         /* we need deassert mac_active due to block interrupt handler */
4165         mutex_enter(&dp->xmitlock);
4166         dp->mac_active = B_FALSE;
4167         mutex_exit(&dp->xmitlock);
4168 
4169         /* block interrupts */
4170         while (dp->intr_busy) {
4171                 cv_wait(&dp->tx_drain_cv, &dp->intrlock);
4172         }
4173         (void) gem_mac_stop(dp, 0);
4174         mutex_exit(&dp->intrlock);
4175 }
4176 
4177 static int
4178 gem_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
4179 {
4180         int             err;
4181         int             ret;
4182         struct gem_dev  *dp = arg;
4183 
4184         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4185 
4186         if (add) {
4187                 ret = gem_add_multicast(dp, ep);
4188         } else {
4189                 ret = gem_remove_multicast(dp, ep);
4190         }
4191 
4192         err = 0;
4193         if (ret != GEM_SUCCESS) {
4194                 err = EIO;
4195         }
4196 
4197         return (err);
4198 }
4199 
4200 static int
4201 gem_m_setpromisc(void *arg, boolean_t on)
4202 {
4203         int             err = 0;        /* no error */
4204         struct gem_dev  *dp = arg;
4205 
4206         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4207 
4208         mutex_enter(&dp->intrlock);
4209         if (dp->mac_suspended) {
4210                 mutex_exit(&dp->intrlock);
4211                 return (EIO);
4212         }
4213         if (on) {
4214                 dp->rxmode |= RXMODE_PROMISC;
4215         } else {
4216                 dp->rxmode &= ~RXMODE_PROMISC;
4217         }
4218 
4219         if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4220                 err = EIO;
4221         }
4222         mutex_exit(&dp->intrlock);
4223 
4224         return (err);
4225 }
4226 
4227 int
4228 gem_m_getstat(void *arg, uint_t stat, uint64_t *valp)
4229 {
4230         struct gem_dev          *dp = arg;
4231         struct gem_stats        *gstp = &dp->stats;
4232         uint64_t                val = 0;
4233 
4234         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4235 
4236         if (mutex_owned(&dp->intrlock)) {
4237                 if (dp->mac_suspended) {
4238                         return (EIO);
4239                 }
4240         } else {
4241                 mutex_enter(&dp->intrlock);
4242                 if (dp->mac_suspended) {
4243                         mutex_exit(&dp->intrlock);
4244                         return (EIO);
4245                 }
4246                 mutex_exit(&dp->intrlock);
4247         }
4248 
4249         if ((*dp->gc.gc_get_stats)(dp) != GEM_SUCCESS) {
4250                 return (EIO);
4251         }
4252 
4253         switch (stat) {
4254         case MAC_STAT_IFSPEED:
4255                 val = gem_speed_value[dp->speed] *1000000ull;
4256                 break;
4257 
4258         case MAC_STAT_MULTIRCV:
4259                 val = gstp->rmcast;
4260                 break;
4261 
4262         case MAC_STAT_BRDCSTRCV:
4263                 val = gstp->rbcast;
4264                 break;
4265 
4266         case MAC_STAT_MULTIXMT:
4267                 val = gstp->omcast;
4268                 break;
4269 
4270         case MAC_STAT_BRDCSTXMT:
4271                 val = gstp->obcast;
4272                 break;
4273 
4274         case MAC_STAT_NORCVBUF:
4275                 val = gstp->norcvbuf + gstp->missed;
4276                 break;
4277 
4278         case MAC_STAT_IERRORS:
4279                 val = gstp->errrcv;
4280                 break;
4281 
4282         case MAC_STAT_NOXMTBUF:
4283                 val = gstp->noxmtbuf;
4284                 break;
4285 
4286         case MAC_STAT_OERRORS:
4287                 val = gstp->errxmt;
4288                 break;
4289 
4290         case MAC_STAT_COLLISIONS:
4291                 val = gstp->collisions;
4292                 break;
4293 
4294         case MAC_STAT_RBYTES:
4295                 val = gstp->rbytes;
4296                 break;
4297 
4298         case MAC_STAT_IPACKETS:
4299                 val = gstp->rpackets;
4300                 break;
4301 
4302         case MAC_STAT_OBYTES:
4303                 val = gstp->obytes;
4304                 break;
4305 
4306         case MAC_STAT_OPACKETS:
4307                 val = gstp->opackets;
4308                 break;
4309 
4310         case MAC_STAT_UNDERFLOWS:
4311                 val = gstp->underflow;
4312                 break;
4313 
4314         case MAC_STAT_OVERFLOWS:
4315                 val = gstp->overflow;
4316                 break;
4317 
4318         case ETHER_STAT_ALIGN_ERRORS:
4319                 val = gstp->frame;
4320                 break;
4321 
4322         case ETHER_STAT_FCS_ERRORS:
4323                 val = gstp->crc;
4324                 break;
4325 
4326         case ETHER_STAT_FIRST_COLLISIONS:
4327                 val = gstp->first_coll;
4328                 break;
4329 
4330         case ETHER_STAT_MULTI_COLLISIONS:
4331                 val = gstp->multi_coll;
4332                 break;
4333 
4334         case ETHER_STAT_SQE_ERRORS:
4335                 val = gstp->sqe;
4336                 break;
4337 
4338         case ETHER_STAT_DEFER_XMTS:
4339                 val = gstp->defer;
4340                 break;
4341 
4342         case ETHER_STAT_TX_LATE_COLLISIONS:
4343                 val = gstp->xmtlatecoll;
4344                 break;
4345 
4346         case ETHER_STAT_EX_COLLISIONS:
4347                 val = gstp->excoll;
4348                 break;
4349 
4350         case ETHER_STAT_MACXMT_ERRORS:
4351                 val = gstp->xmit_internal_err;
4352                 break;
4353 
4354         case ETHER_STAT_CARRIER_ERRORS:
4355                 val = gstp->nocarrier;
4356                 break;
4357 
4358         case ETHER_STAT_TOOLONG_ERRORS:
4359                 val = gstp->frame_too_long;
4360                 break;
4361 
4362         case ETHER_STAT_MACRCV_ERRORS:
4363                 val = gstp->rcv_internal_err;
4364                 break;
4365 
4366         case ETHER_STAT_XCVR_ADDR:
4367                 val = dp->mii_phy_addr;
4368                 break;
4369 
4370         case ETHER_STAT_XCVR_ID:
4371                 val = dp->mii_phy_id;
4372                 break;
4373 
4374         case ETHER_STAT_XCVR_INUSE:
4375                 val = gem_mac_xcvr_inuse(dp);
4376                 break;
4377 
4378         case ETHER_STAT_CAP_1000FDX:
4379                 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) ||
4380                     (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD);
4381                 break;
4382 
4383         case ETHER_STAT_CAP_1000HDX:
4384                 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) ||
4385                     (dp->mii_xstatus & MII_XSTATUS_1000BASEX);
4386                 break;
4387 
4388         case ETHER_STAT_CAP_100FDX:
4389                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4390                 break;
4391 
4392         case ETHER_STAT_CAP_100HDX:
4393                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4394                 break;
4395 
4396         case ETHER_STAT_CAP_10FDX:
4397                 val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4398                 break;
4399 
4400         case ETHER_STAT_CAP_10HDX:
4401                 val = BOOLEAN(dp->mii_status & MII_STATUS_10);
4402                 break;
4403 
4404         case ETHER_STAT_CAP_ASMPAUSE:
4405                 val = BOOLEAN(dp->gc.gc_flow_control & 2);
4406                 break;
4407 
4408         case ETHER_STAT_CAP_PAUSE:
4409                 val = BOOLEAN(dp->gc.gc_flow_control & 1);
4410                 break;
4411 
4412         case ETHER_STAT_CAP_AUTONEG:
4413                 val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4414                 break;
4415 
4416         case ETHER_STAT_ADV_CAP_1000FDX:
4417                 val = dp->anadv_1000fdx;
4418                 break;
4419 
4420         case ETHER_STAT_ADV_CAP_1000HDX:
4421                 val = dp->anadv_1000hdx;
4422                 break;
4423 
4424         case ETHER_STAT_ADV_CAP_100FDX:
4425                 val = dp->anadv_100fdx;
4426                 break;
4427 
4428         case ETHER_STAT_ADV_CAP_100HDX:
4429                 val = dp->anadv_100hdx;
4430                 break;
4431 
4432         case ETHER_STAT_ADV_CAP_10FDX:
4433                 val = dp->anadv_10fdx;
4434                 break;
4435 
4436         case ETHER_STAT_ADV_CAP_10HDX:
4437                 val = dp->anadv_10hdx;
4438                 break;
4439 
4440         case ETHER_STAT_ADV_CAP_ASMPAUSE:
4441                 val = BOOLEAN(dp->anadv_flow_control & 2);
4442                 break;
4443 
4444         case ETHER_STAT_ADV_CAP_PAUSE:
4445                 val = BOOLEAN(dp->anadv_flow_control & 1);
4446                 break;
4447 
4448         case ETHER_STAT_ADV_CAP_AUTONEG:
4449                 val = dp->anadv_autoneg;
4450                 break;
4451 
4452         case ETHER_STAT_LP_CAP_1000FDX:
4453                 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL);
4454                 break;
4455 
4456         case ETHER_STAT_LP_CAP_1000HDX:
4457                 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF);
4458                 break;
4459 
4460         case ETHER_STAT_LP_CAP_100FDX:
4461                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD);
4462                 break;
4463 
4464         case ETHER_STAT_LP_CAP_100HDX:
4465                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX);
4466                 break;
4467 
4468         case ETHER_STAT_LP_CAP_10FDX:
4469                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD);
4470                 break;
4471 
4472         case ETHER_STAT_LP_CAP_10HDX:
4473                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T);
4474                 break;
4475 
4476         case ETHER_STAT_LP_CAP_ASMPAUSE:
4477                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASMPAUSE);
4478                 break;
4479 
4480         case ETHER_STAT_LP_CAP_PAUSE:
4481                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE);
4482                 break;
4483 
4484         case ETHER_STAT_LP_CAP_AUTONEG:
4485                 val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
4486                 break;
4487 
4488         case ETHER_STAT_LINK_ASMPAUSE:
4489                 val = BOOLEAN(dp->flow_control & 2);
4490                 break;
4491 
4492         case ETHER_STAT_LINK_PAUSE:
4493                 val = BOOLEAN(dp->flow_control & 1);
4494                 break;
4495 
4496         case ETHER_STAT_LINK_AUTONEG:
4497                 val = dp->anadv_autoneg &&
4498                     BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN);
4499                 break;
4500 
4501         case ETHER_STAT_LINK_DUPLEX:
4502                 val = (dp->mii_state == MII_STATE_LINKUP) ?
4503                     (dp->full_duplex ? 2 : 1) : 0;
4504                 break;
4505 
4506         case ETHER_STAT_TOOSHORT_ERRORS:
4507                 val = gstp->runt;
4508                 break;
4509         case ETHER_STAT_LP_REMFAULT:
4510                 val = BOOLEAN(dp->mii_lpable & MII_AN_ADVERT_REMFAULT);
4511                 break;
4512 
4513         case ETHER_STAT_JABBER_ERRORS:
4514                 val = gstp->jabber;
4515                 break;
4516 
4517         case ETHER_STAT_CAP_100T4:
4518                 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
4519                 break;
4520 
4521         case ETHER_STAT_ADV_CAP_100T4:
4522                 val = dp->anadv_100t4;
4523                 break;
4524 
4525         case ETHER_STAT_LP_CAP_100T4:
4526                 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4);
4527                 break;
4528 
4529         default:
4530 #if GEM_DEBUG_LEVEL > 2
4531                 cmn_err(CE_WARN,
4532                     "%s: unrecognized parameter value = %d",
4533                     __func__, stat);
4534 #endif
4535                 return (ENOTSUP);
4536         }
4537 
4538         *valp = val;
4539 
4540         return (0);
4541 }
4542 
4543 static int
4544 gem_m_unicst(void *arg, const uint8_t *mac)
4545 {
4546         int             err = 0;
4547         struct gem_dev  *dp = arg;
4548 
4549         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4550 
4551         mutex_enter(&dp->intrlock);
4552         if (dp->mac_suspended) {
4553                 mutex_exit(&dp->intrlock);
4554                 return (EIO);
4555         }
4556         bcopy(mac, dp->cur_addr.ether_addr_octet, ETHERADDRL);
4557         dp->rxmode |= RXMODE_ENABLE;
4558 
4559         if (gem_mac_set_rx_filter(dp) != GEM_SUCCESS) {
4560                 err = EIO;
4561         }
4562         mutex_exit(&dp->intrlock);
4563 
4564         return (err);
4565 }
4566 
4567 /*
4568  * gem_m_tx is used only for sending data packets into ethernet wire.
4569  */
4570 static mblk_t *
4571 gem_m_tx(void *arg, mblk_t *mp)
4572 {
4573         uint32_t        flags = 0;
4574         struct gem_dev  *dp = arg;
4575         mblk_t          *tp;
4576 
4577         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4578 
4579         ASSERT(dp->nic_state == NIC_STATE_ONLINE);
4580         if (dp->mii_state != MII_STATE_LINKUP) {
4581                 /* Some nics hate to send packets when the link is down. */
4582                 while (mp) {
4583                         tp = mp->b_next;
4584                         mp->b_next = NULL;
4585                         freemsg(mp);
4586                         mp = tp;
4587                 }
4588                 return (NULL);
4589         }
4590 
4591         return (gem_send_common(dp, mp, flags));
4592 }
4593 
4594 static void
4595 gem_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
4596 {
4597         DPRINTF(0, (CE_CONT, "!%s: %s: called",
4598             ((struct gem_dev *)arg)->name, __func__));
4599 
4600         gem_mac_ioctl((struct gem_dev *)arg, wq, mp);
4601 }
4602 
4603 /* ARGSUSED */
4604 static boolean_t
4605 gem_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
4606 {
4607         return (B_FALSE);
4608 }
4609 
4610 static void
4611 gem_gld3_init(struct gem_dev *dp, mac_register_t *macp)
4612 {
4613         macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
4614         macp->m_driver = dp;
4615         macp->m_dip = dp->dip;
4616         macp->m_src_addr = dp->dev_addr.ether_addr_octet;
4617         macp->m_callbacks = &gem_m_callbacks;
4618         macp->m_min_sdu = 0;
4619         macp->m_max_sdu = dp->mtu;
4620 
4621         if (dp->misc_flag & GEM_VLAN) {
4622                 macp->m_margin = VTAG_SIZE;
4623         }
4624 }
4625 
4626 /* ======================================================================== */
4627 /*
4628  * attach/detatch support
4629  */
4630 /* ======================================================================== */
4631 static void
4632 gem_read_conf(struct gem_dev *dp)
4633 {
4634         int     val;
4635 
4636         DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__));
4637 
4638         /*
4639          * Get media mode infomation from .conf file
4640          */
4641         dp->anadv_autoneg = gem_prop_get_int(dp, "adv_autoneg_cap", 1) != 0;
4642         dp->anadv_1000fdx = gem_prop_get_int(dp, "adv_1000fdx_cap", 1) != 0;
4643         dp->anadv_1000hdx = gem_prop_get_int(dp, "adv_1000hdx_cap", 1) != 0;
4644         dp->anadv_100t4   = gem_prop_get_int(dp, "adv_100T4_cap", 1) != 0;
4645         dp->anadv_100fdx  = gem_prop_get_int(dp, "adv_100fdx_cap", 1) != 0;
4646         dp->anadv_100hdx  = gem_prop_get_int(dp, "adv_100hdx_cap", 1) != 0;
4647         dp->anadv_10fdx   = gem_prop_get_int(dp, "adv_10fdx_cap", 1) != 0;
4648         dp->anadv_10hdx   = gem_prop_get_int(dp, "adv_10hdx_cap", 1) != 0;
4649 
4650         if ((ddi_prop_exists(DDI_DEV_T_ANY, dp->dip,
4651             DDI_PROP_DONTPASS, "full-duplex"))) {
4652                 dp->full_duplex = gem_prop_get_int(dp, "full-duplex", 1) != 0;
4653                 dp->anadv_autoneg = B_FALSE;
4654                 if (dp->full_duplex) {
4655                         dp->anadv_1000hdx = B_FALSE;
4656                         dp->anadv_100hdx = B_FALSE;
4657                         dp->anadv_10hdx = B_FALSE;
4658                 } else {
4659                         dp->anadv_1000fdx = B_FALSE;
4660                         dp->anadv_100fdx = B_FALSE;
4661                         dp->anadv_10fdx = B_FALSE;
4662                 }
4663         }
4664 
4665         if ((val = gem_prop_get_int(dp, "speed", 0)) > 0) {
4666                 dp->anadv_autoneg = B_FALSE;
4667                 switch (val) {
4668                 case 1000:
4669                         dp->speed = GEM_SPD_1000;
4670                         dp->anadv_100t4   = B_FALSE;
4671                         dp->anadv_100fdx  = B_FALSE;
4672                         dp->anadv_100hdx  = B_FALSE;
4673                         dp->anadv_10fdx   = B_FALSE;
4674                         dp->anadv_10hdx   = B_FALSE;
4675                         break;
4676                 case 100:
4677                         dp->speed = GEM_SPD_100;
4678                         dp->anadv_1000fdx = B_FALSE;
4679                         dp->anadv_1000hdx = B_FALSE;
4680                         dp->anadv_10fdx   = B_FALSE;
4681                         dp->anadv_10hdx   = B_FALSE;
4682                         break;
4683                 case 10:
4684                         dp->speed = GEM_SPD_10;
4685                         dp->anadv_1000fdx = B_FALSE;
4686                         dp->anadv_1000hdx = B_FALSE;
4687                         dp->anadv_100t4   = B_FALSE;
4688                         dp->anadv_100fdx  = B_FALSE;
4689                         dp->anadv_100hdx  = B_FALSE;
4690                         break;
4691                 default:
4692                         cmn_err(CE_WARN,
4693                             "!%s: property %s: illegal value:%d",
4694                             dp->name, "speed", val);
4695                         dp->anadv_autoneg = B_TRUE;
4696                         break;
4697                 }
4698         }
4699 
4700         val = gem_prop_get_int(dp, "flow-control", dp->gc.gc_flow_control);
4701         if (val > FLOW_CONTROL_RX_PAUSE || val < FLOW_CONTROL_NONE) {
4702                 cmn_err(CE_WARN,
4703                     "!%s: property %s: illegal value:%d",
4704                     dp->name, "flow-control", val);
4705         } else {
4706                 val = min(val, dp->gc.gc_flow_control);
4707         }
4708         dp->anadv_flow_control = val;
4709 
4710         if (gem_prop_get_int(dp, "nointr", 0)) {
4711                 dp->misc_flag |= GEM_NOINTR;
4712                 cmn_err(CE_NOTE, "!%s: polling mode enabled", dp->name);
4713         }
4714 
4715         dp->mtu = gem_prop_get_int(dp, "mtu", dp->mtu);
4716         dp->txthr = gem_prop_get_int(dp, "txthr", dp->txthr);
4717         dp->rxthr = gem_prop_get_int(dp, "rxthr", dp->rxthr);
4718         dp->txmaxdma = gem_prop_get_int(dp, "txmaxdma", dp->txmaxdma);
4719         dp->rxmaxdma = gem_prop_get_int(dp, "rxmaxdma", dp->rxmaxdma);
4720 }
4721 
4722 
4723 /*
4724  * Gem kstat support
4725  */
4726 
4727 #define GEM_LOCAL_DATA_SIZE(gc) \
4728         (sizeof (struct gem_dev) + \
4729         sizeof (struct mcast_addr) * GEM_MAXMC + \
4730         sizeof (struct txbuf) * ((gc)->gc_tx_buf_size) + \
4731         sizeof (void *) * ((gc)->gc_tx_buf_size))
4732 
4733 struct gem_dev *
4734 gem_do_attach(dev_info_t *dip, int port,
4735         struct gem_conf *gc, void *base, ddi_acc_handle_t *regs_handlep,
4736         void *lp, int lmsize)
4737 {
4738         struct gem_dev          *dp;
4739         int                     i;
4740         ddi_iblock_cookie_t     c;
4741         mac_register_t          *macp = NULL;
4742         int                     ret;
4743         int                     unit;
4744         int                     nports;
4745 
4746         unit = ddi_get_instance(dip);
4747         if ((nports = gc->gc_nports) == 0) {
4748                 nports = 1;
4749         }
4750         if (nports == 1) {
4751                 ddi_set_driver_private(dip, NULL);
4752         }
4753 
4754         DPRINTF(2, (CE_CONT, "!gem%d: gem_do_attach: called cmd:ATTACH",
4755             unit));
4756 
4757         /*
4758          * Allocate soft data structure
4759          */
4760         dp = kmem_zalloc(GEM_LOCAL_DATA_SIZE(gc), KM_SLEEP);
4761 
4762         if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
4763                 cmn_err(CE_WARN, "!gem%d: %s: mac_alloc failed",
4764                     unit, __func__);
4765                 return (NULL);
4766         }
4767         /* ddi_set_driver_private(dip, dp); */
4768 
4769         /* link to private area */
4770         dp->private = lp;
4771         dp->priv_size = lmsize;
4772         dp->mc_list = (struct mcast_addr *)&dp[1];
4773 
4774         dp->dip = dip;
4775         (void) sprintf(dp->name, gc->gc_name, nports * unit + port);
4776 
4777         /*
4778          * Get iblock cookie
4779          */
4780         if (ddi_get_iblock_cookie(dip, 0, &c) != DDI_SUCCESS) {
4781                 cmn_err(CE_CONT,
4782                     "!%s: gem_do_attach: ddi_get_iblock_cookie: failed",
4783                     dp->name);
4784                 goto err_free_private;
4785         }
4786         dp->iblock_cookie = c;
4787 
4788         /*
4789          * Initialize mutex's for this device.
4790          */
4791         mutex_init(&dp->intrlock, NULL, MUTEX_DRIVER, (void *)c);
4792         mutex_init(&dp->xmitlock, NULL, MUTEX_DRIVER, (void *)c);
4793         cv_init(&dp->tx_drain_cv, NULL, CV_DRIVER, NULL);
4794 
4795         /*
4796          * configure gem parameter
4797          */
4798         dp->base_addr = base;
4799         dp->regs_handle = *regs_handlep;
4800         dp->gc = *gc;
4801         gc = &dp->gc;
4802         /* patch for simplify dma resource management */
4803         gc->gc_tx_max_frags = 1;
4804         gc->gc_tx_max_descs_per_pkt = 1;
4805         gc->gc_tx_ring_size = gc->gc_tx_buf_size;
4806         gc->gc_tx_ring_limit = gc->gc_tx_buf_limit;
4807         gc->gc_tx_desc_write_oo = B_TRUE;
4808 
4809         gc->gc_nports = nports;      /* fix nports */
4810 
4811         /* fix copy threadsholds */
4812         gc->gc_tx_copy_thresh = max(ETHERMIN, gc->gc_tx_copy_thresh);
4813         gc->gc_rx_copy_thresh = max(ETHERMIN, gc->gc_rx_copy_thresh);
4814 
4815         /* fix rx buffer boundary for iocache line size */
4816         ASSERT(gc->gc_dma_attr_txbuf.dma_attr_align-1 == gc->gc_tx_buf_align);
4817         ASSERT(gc->gc_dma_attr_rxbuf.dma_attr_align-1 == gc->gc_rx_buf_align);
4818         gc->gc_rx_buf_align = max(gc->gc_rx_buf_align, IOC_LINESIZE - 1);
4819         gc->gc_dma_attr_rxbuf.dma_attr_align = gc->gc_rx_buf_align + 1;
4820 
4821         /* fix descriptor boundary for cache line size */
4822         gc->gc_dma_attr_desc.dma_attr_align =
4823             max(gc->gc_dma_attr_desc.dma_attr_align, IOC_LINESIZE);
4824 
4825         /* patch get_packet method */
4826         if (gc->gc_get_packet == NULL) {
4827                 gc->gc_get_packet = &gem_get_packet_default;
4828         }
4829 
4830         /* patch get_rx_start method */
4831         if (gc->gc_rx_start == NULL) {
4832                 gc->gc_rx_start = &gem_rx_start_default;
4833         }
4834 
4835         /* calculate descriptor area */
4836         if (gc->gc_rx_desc_unit_shift >= 0) {
4837                 dp->rx_desc_size =
4838                     ROUNDUP(gc->gc_rx_ring_size << gc->gc_rx_desc_unit_shift,
4839                     gc->gc_dma_attr_desc.dma_attr_align);
4840         }
4841         if (gc->gc_tx_desc_unit_shift >= 0) {
4842                 dp->tx_desc_size =
4843                     ROUNDUP(gc->gc_tx_ring_size << gc->gc_tx_desc_unit_shift,
4844                     gc->gc_dma_attr_desc.dma_attr_align);
4845         }
4846 
4847         dp->mtu = ETHERMTU;
4848         dp->tx_buf = (void *)&dp->mc_list[GEM_MAXMC];
4849         /* link tx buffers */
4850         for (i = 0; i < dp->gc.gc_tx_buf_size; i++) {
4851                 dp->tx_buf[i].txb_next =
4852                     &dp->tx_buf[SLOT(i + 1, dp->gc.gc_tx_buf_size)];
4853         }
4854 
4855         dp->rxmode      = 0;
4856         dp->speed       = GEM_SPD_10;        /* default is 10Mbps */
4857         dp->full_duplex    = B_FALSE;                /* default is half */
4858         dp->flow_control   = FLOW_CONTROL_NONE;
4859         dp->poll_pkt_delay = 8;              /* typical coalease for rx packets */
4860 
4861         /* performance tuning parameters */
4862         dp->txthr    = ETHERMAX;     /* tx fifo threshold */
4863         dp->txmaxdma = 16*4;         /* tx max dma burst size */
4864         dp->rxthr    = 128;          /* rx fifo threshold */
4865         dp->rxmaxdma = 16*4;         /* rx max dma burst size */
4866 
4867         /*
4868          * Get media mode information from .conf file
4869          */
4870         gem_read_conf(dp);
4871 
4872         /* rx_buf_len is required buffer length without padding for alignment */
4873         dp->rx_buf_len = MAXPKTBUF(dp) + dp->gc.gc_rx_header_len;
4874 
4875         /*
4876          * Reset the chip
4877          */
4878         mutex_enter(&dp->intrlock);
4879         dp->nic_state = NIC_STATE_STOPPED;
4880         ret = (*dp->gc.gc_reset_chip)(dp);
4881         mutex_exit(&dp->intrlock);
4882         if (ret != GEM_SUCCESS) {
4883                 goto err_free_regs;
4884         }
4885 
4886         /*
4887          * HW dependant paremeter initialization
4888          */
4889         mutex_enter(&dp->intrlock);
4890         ret = (*dp->gc.gc_attach_chip)(dp);
4891         mutex_exit(&dp->intrlock);
4892         if (ret != GEM_SUCCESS) {
4893                 goto err_free_regs;
4894         }
4895 
4896 #ifdef DEBUG_MULTIFRAGS
4897         dp->gc.gc_tx_copy_thresh = dp->mtu;
4898 #endif
4899         /* allocate tx and rx resources */
4900         if (gem_alloc_memory(dp)) {
4901                 goto err_free_regs;
4902         }
4903 
4904         DPRINTF(0, (CE_CONT,
4905             "!%s: at 0x%x, %02x:%02x:%02x:%02x:%02x:%02x",
4906             dp->name, (long)dp->base_addr,
4907             dp->dev_addr.ether_addr_octet[0],
4908             dp->dev_addr.ether_addr_octet[1],
4909             dp->dev_addr.ether_addr_octet[2],
4910             dp->dev_addr.ether_addr_octet[3],
4911             dp->dev_addr.ether_addr_octet[4],
4912             dp->dev_addr.ether_addr_octet[5]));
4913 
4914         /* copy mac address */
4915         dp->cur_addr = dp->dev_addr;
4916 
4917         gem_gld3_init(dp, macp);
4918 
4919         /* Probe MII phy (scan phy) */
4920         dp->mii_lpable = 0;
4921         dp->mii_advert = 0;
4922         dp->mii_exp = 0;
4923         dp->mii_ctl1000 = 0;
4924         dp->mii_stat1000 = 0;
4925         if ((*dp->gc.gc_mii_probe)(dp) != GEM_SUCCESS) {
4926                 goto err_free_ring;
4927         }
4928 
4929         /* mask unsupported abilities */
4930         dp->anadv_autoneg &= BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG);
4931         dp->anadv_1000fdx &=
4932             BOOLEAN(dp->mii_xstatus &
4933             (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD));
4934         dp->anadv_1000hdx &=
4935             BOOLEAN(dp->mii_xstatus &
4936             (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET));
4937         dp->anadv_100t4  &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4);
4938         dp->anadv_100fdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD);
4939         dp->anadv_100hdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX);
4940         dp->anadv_10fdx  &= BOOLEAN(dp->mii_status & MII_STATUS_10_FD);
4941         dp->anadv_10hdx  &= BOOLEAN(dp->mii_status & MII_STATUS_10);
4942 
4943         gem_choose_forcedmode(dp);
4944 
4945         /* initialize MII phy if required */
4946         if (dp->gc.gc_mii_init) {
4947                 if ((*dp->gc.gc_mii_init)(dp) != GEM_SUCCESS) {
4948                         goto err_free_ring;
4949                 }
4950         }
4951 
4952         /*
4953          * initialize kstats including mii statistics
4954          */
4955         gem_nd_setup(dp);
4956 
4957         /*
4958          * Add interrupt to system.
4959          */
4960         if (ret = mac_register(macp, &dp->mh)) {
4961                 cmn_err(CE_WARN, "!%s: mac_register failed, error:%d",
4962                     dp->name, ret);
4963                 goto err_release_stats;
4964         }
4965         mac_free(macp);
4966         macp = NULL;
4967 
4968         if (dp->misc_flag & GEM_SOFTINTR) {
4969                 if (ddi_add_softintr(dip,
4970                     DDI_SOFTINT_LOW, &dp->soft_id,
4971                     NULL, NULL,
4972                     (uint_t (*)(caddr_t))gem_intr,
4973                     (caddr_t)dp) != DDI_SUCCESS) {
4974                         cmn_err(CE_WARN, "!%s: ddi_add_softintr failed",
4975                             dp->name);
4976                         goto err_unregister;
4977                 }
4978         } else if ((dp->misc_flag & GEM_NOINTR) == 0) {
4979                 if (ddi_add_intr(dip, 0, NULL, NULL,
4980                     (uint_t (*)(caddr_t))gem_intr,
4981                     (caddr_t)dp) != DDI_SUCCESS) {
4982                         cmn_err(CE_WARN, "!%s: ddi_add_intr failed", dp->name);
4983                         goto err_unregister;
4984                 }
4985         } else {
4986                 /*
4987                  * Dont use interrupt.
4988                  * schedule first call of gem_intr_watcher
4989                  */
4990                 dp->intr_watcher_id =
4991                     timeout((void (*)(void *))gem_intr_watcher,
4992                     (void *)dp, drv_usectohz(3*1000000));
4993         }
4994 
4995         /* link this device to dev_info */
4996         dp->next = (struct gem_dev *)ddi_get_driver_private(dip);
4997         dp->port = port;
4998         ddi_set_driver_private(dip, (caddr_t)dp);
4999 
5000         /* reset mii phy and start mii link watcher */
5001         gem_mii_start(dp);
5002 
5003         DPRINTF(2, (CE_CONT, "!gem_do_attach: return: success"));
5004         return (dp);
5005 
5006 err_unregister:
5007         (void) mac_unregister(dp->mh);
5008 err_release_stats:
5009         /* release NDD resources */
5010         gem_nd_cleanup(dp);
5011 
5012 err_free_ring:
5013         gem_free_memory(dp);
5014 err_free_regs:
5015         ddi_regs_map_free(&dp->regs_handle);
5016 err_free_locks:
5017         mutex_destroy(&dp->xmitlock);
5018         mutex_destroy(&dp->intrlock);
5019         cv_destroy(&dp->tx_drain_cv);
5020 err_free_private:
5021         if (macp) {
5022                 mac_free(macp);
5023         }
5024         kmem_free((caddr_t)dp, GEM_LOCAL_DATA_SIZE(gc));
5025 
5026         return (NULL);
5027 }
5028 
5029 int
5030 gem_do_detach(dev_info_t *dip)
5031 {
5032         struct gem_dev  *dp;
5033         struct gem_dev  *tmp;
5034         caddr_t         private;
5035         int             priv_size;
5036         ddi_acc_handle_t        rh;
5037 
5038         dp = GEM_GET_DEV(dip);
5039         if (dp == NULL) {
5040                 return (DDI_SUCCESS);
5041         }
5042 
5043         rh = dp->regs_handle;
5044         private = dp->private;
5045         priv_size = dp->priv_size;
5046 
5047         while (dp) {
5048                 /* unregister with gld v3 */
5049                 if (mac_unregister(dp->mh) != 0) {
5050                         return (DDI_FAILURE);
5051                 }
5052 
5053                 /* ensure any rx buffers are not used */
5054                 if (dp->rx_buf_allocated != dp->rx_buf_freecnt) {
5055                         /* resource is busy */
5056                         cmn_err(CE_PANIC,
5057                             "!%s: %s: rxbuf is busy: allocated:%d, freecnt:%d",
5058                             dp->name, __func__,
5059                             dp->rx_buf_allocated, dp->rx_buf_freecnt);
5060                         /* NOT REACHED */
5061                 }
5062 
5063                 /* stop mii link watcher */
5064                 gem_mii_stop(dp);
5065 
5066                 /* unregister interrupt handler */
5067                 if (dp->misc_flag & GEM_SOFTINTR) {
5068                         ddi_remove_softintr(dp->soft_id);
5069                 } else if ((dp->misc_flag & GEM_NOINTR) == 0) {
5070                         ddi_remove_intr(dip, 0, dp->iblock_cookie);
5071                 } else {
5072                         /* stop interrupt watcher */
5073                         if (dp->intr_watcher_id) {
5074                                 while (untimeout(dp->intr_watcher_id) == -1)
5075                                         ;
5076                                 dp->intr_watcher_id = 0;
5077                         }
5078                 }
5079 
5080                 /* release NDD resources */
5081                 gem_nd_cleanup(dp);
5082                 /* release buffers, descriptors and dma resources */
5083                 gem_free_memory(dp);
5084 
5085                 /* release locks and condition variables */
5086                 mutex_destroy(&dp->xmitlock);
5087                 mutex_destroy(&dp->intrlock);
5088                 cv_destroy(&dp->tx_drain_cv);
5089 
5090                 /* release basic memory resources */
5091                 tmp = dp->next;
5092                 kmem_free((caddr_t)dp, GEM_LOCAL_DATA_SIZE(&dp->gc));
5093                 dp = tmp;
5094         }
5095 
5096         /* release common private memory for the nic */
5097         kmem_free(private, priv_size);
5098 
5099         /* release register mapping resources */
5100         ddi_regs_map_free(&rh);
5101 
5102         DPRINTF(2, (CE_CONT, "!%s%d: gem_do_detach: return: success",
5103             ddi_driver_name(dip), ddi_get_instance(dip)));
5104 
5105         return (DDI_SUCCESS);
5106 }
5107 
5108 int
5109 gem_suspend(dev_info_t *dip)
5110 {
5111         struct gem_dev  *dp;
5112 
5113         /*
5114          * stop the device
5115          */
5116         dp = GEM_GET_DEV(dip);
5117         ASSERT(dp);
5118 
5119         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
5120 
5121         for (; dp; dp = dp->next) {
5122 
5123                 /* stop mii link watcher */
5124                 gem_mii_stop(dp);
5125 
5126                 /* stop interrupt watcher for no-intr mode */
5127                 if (dp->misc_flag & GEM_NOINTR) {
5128                         if (dp->intr_watcher_id) {
5129                                 while (untimeout(dp->intr_watcher_id) == -1)
5130                                         ;
5131                         }
5132                         dp->intr_watcher_id = 0;
5133                 }
5134 
5135                 /* stop tx timeout watcher */
5136                 if (dp->timeout_id) {
5137                         while (untimeout(dp->timeout_id) == -1)
5138                                 ;
5139                         dp->timeout_id = 0;
5140                 }
5141 
5142                 /* make the nic state inactive */
5143                 mutex_enter(&dp->intrlock);
5144                 (void) gem_mac_stop(dp, 0);
5145                 ASSERT(!dp->mac_active);
5146 
5147                 /* no further register access */
5148                 dp->mac_suspended = B_TRUE;
5149                 mutex_exit(&dp->intrlock);
5150         }
5151 
5152         /* XXX - power down the nic */
5153 
5154         return (DDI_SUCCESS);
5155 }
5156 
5157 int
5158 gem_resume(dev_info_t *dip)
5159 {
5160         struct gem_dev  *dp;
5161 
5162         /*
5163          * restart the device
5164          */
5165         dp = GEM_GET_DEV(dip);
5166         ASSERT(dp);
5167 
5168         DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__));
5169 
5170         for (; dp; dp = dp->next) {
5171 
5172                 /*
5173                  * Bring up the nic after power up
5174                  */
5175 
5176                 /* gem_xxx.c layer to setup power management state. */
5177                 ASSERT(!dp->mac_active);
5178 
5179                 /* reset the chip, because we are just after power up. */
5180                 mutex_enter(&dp->intrlock);
5181 
5182                 dp->mac_suspended = B_FALSE;
5183                 dp->nic_state = NIC_STATE_STOPPED;
5184 
5185                 if ((*dp->gc.gc_reset_chip)(dp) != GEM_SUCCESS) {
5186                         cmn_err(CE_WARN, "%s: %s: failed to reset chip",
5187                             dp->name, __func__);
5188                         mutex_exit(&dp->intrlock);
5189                         goto err;
5190                 }
5191                 mutex_exit(&dp->intrlock);
5192 
5193                 /* initialize mii phy because we are just after power up */
5194                 if (dp->gc.gc_mii_init) {
5195                         (void) (*dp->gc.gc_mii_init)(dp);
5196                 }
5197 
5198                 if (dp->misc_flag & GEM_NOINTR) {
5199                         /*
5200                          * schedule first call of gem_intr_watcher
5201                          * instead of interrupts.
5202                          */
5203                         dp->intr_watcher_id =
5204                             timeout((void (*)(void *))gem_intr_watcher,
5205                             (void *)dp, drv_usectohz(3*1000000));
5206                 }
5207 
5208                 /* restart mii link watcher */
5209                 gem_mii_start(dp);
5210 
5211                 /* restart mac */
5212                 mutex_enter(&dp->intrlock);
5213 
5214                 if (gem_mac_init(dp) != GEM_SUCCESS) {
5215                         mutex_exit(&dp->intrlock);
5216                         goto err_reset;
5217                 }
5218                 dp->nic_state = NIC_STATE_INITIALIZED;
5219 
5220                 /* setup media mode if the link have been up */
5221                 if (dp->mii_state == MII_STATE_LINKUP) {
5222                         if ((dp->gc.gc_set_media)(dp) != GEM_SUCCESS) {
5223                                 mutex_exit(&dp->intrlock);
5224                                 goto err_reset;
5225                         }
5226                 }
5227 
5228                 /* enable mac address and rx filter */
5229                 dp->rxmode |= RXMODE_ENABLE;
5230                 if ((*dp->gc.gc_set_rx_filter)(dp) != GEM_SUCCESS) {
5231                         mutex_exit(&dp->intrlock);
5232                         goto err_reset;
5233                 }
5234                 dp->nic_state = NIC_STATE_ONLINE;
5235 
5236                 /* restart tx timeout watcher */
5237                 dp->timeout_id = timeout((void (*)(void *))gem_tx_timeout,
5238                     (void *)dp,
5239                     dp->gc.gc_tx_timeout_interval);
5240 
5241                 /* now the nic is fully functional */
5242                 if (dp->mii_state == MII_STATE_LINKUP) {
5243                         if (gem_mac_start(dp) != GEM_SUCCESS) {
5244                                 mutex_exit(&dp->intrlock);
5245                                 goto err_reset;
5246                         }
5247                 }
5248                 mutex_exit(&dp->intrlock);
5249         }
5250 
5251         return (DDI_SUCCESS);
5252 
5253 err_reset:
5254         if (dp->intr_watcher_id) {
5255                 while (untimeout(dp->intr_watcher_id) == -1)
5256                         ;
5257                 dp->intr_watcher_id = 0;
5258         }
5259         mutex_enter(&dp->intrlock);
5260         (*dp->gc.gc_reset_chip)(dp);
5261         dp->nic_state = NIC_STATE_STOPPED;
5262         mutex_exit(&dp->intrlock);
5263 
5264 err:
5265         return (DDI_FAILURE);
5266 }
5267 
5268 /*
5269  * misc routines for PCI
5270  */
5271 uint8_t
5272 gem_search_pci_cap(dev_info_t *dip,
5273                 ddi_acc_handle_t conf_handle, uint8_t target)
5274 {
5275         uint8_t         pci_cap_ptr;
5276         uint32_t        pci_cap;
5277 
5278         /* search power management capablities */
5279         pci_cap_ptr = pci_config_get8(conf_handle, PCI_CONF_CAP_PTR);
5280         while (pci_cap_ptr) {
5281                 /* read pci capability header */
5282                 pci_cap = pci_config_get32(conf_handle, pci_cap_ptr);
5283                 if ((pci_cap & 0xff) == target) {
5284                         /* found */
5285                         break;
5286                 }
5287                 /* get next_ptr */
5288                 pci_cap_ptr = (pci_cap >> 8) & 0xff;
5289         }
5290         return (pci_cap_ptr);
5291 }
5292 
5293 int
5294 gem_pci_set_power_state(dev_info_t *dip,
5295                 ddi_acc_handle_t conf_handle, uint_t new_mode)
5296 {
5297         uint8_t         pci_cap_ptr;
5298         uint32_t        pmcsr;
5299         uint_t          unit;
5300         const char      *drv_name;
5301 
5302         ASSERT(new_mode < 4);
5303 
5304         unit = ddi_get_instance(dip);
5305         drv_name = ddi_driver_name(dip);
5306 
5307         /* search power management capablities */
5308         pci_cap_ptr = gem_search_pci_cap(dip, conf_handle, PCI_CAP_ID_PM);
5309 
5310         if (pci_cap_ptr == 0) {
5311                 cmn_err(CE_CONT,
5312                     "!%s%d: doesn't have pci power management capability",
5313                     drv_name, unit);
5314                 return (DDI_FAILURE);
5315         }
5316 
5317         /* read power management capabilities */
5318         pmcsr = pci_config_get32(conf_handle, pci_cap_ptr + PCI_PMCSR);
5319 
5320         DPRINTF(0, (CE_CONT,
5321             "!%s%d: pmc found at 0x%x: pmcsr: 0x%08x",
5322             drv_name, unit, pci_cap_ptr, pmcsr));
5323 
5324         /*
5325          * Is the resuested power mode supported?
5326          */
5327         /* not yet */
5328 
5329         /*
5330          * move to new mode
5331          */
5332         pmcsr = (pmcsr & ~PCI_PMCSR_STATE_MASK) | new_mode;
5333         pci_config_put32(conf_handle, pci_cap_ptr + PCI_PMCSR, pmcsr);
5334 
5335         return (DDI_SUCCESS);
5336 }
5337 
5338 /*
5339  * select suitable register for by specified address space or register
5340  * offset in PCI config space
5341  */
5342 int
5343 gem_pci_regs_map_setup(dev_info_t *dip, uint32_t which, uint32_t mask,
5344         struct ddi_device_acc_attr *attrp,
5345         caddr_t *basep, ddi_acc_handle_t *hp)
5346 {
5347         struct pci_phys_spec    *regs;
5348         uint_t          len;
5349         uint_t          unit;
5350         uint_t          n;
5351         uint_t          i;
5352         int             ret;
5353         const char      *drv_name;
5354 
5355         unit = ddi_get_instance(dip);
5356         drv_name = ddi_driver_name(dip);
5357 
5358         /* Search IO-range or memory-range to be mapped */
5359         regs = NULL;
5360         len  = 0;
5361 
5362         if ((ret = ddi_prop_lookup_int_array(
5363             DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
5364             "reg", (void *)&regs, &len)) != DDI_PROP_SUCCESS) {
5365                 cmn_err(CE_WARN,
5366                     "!%s%d: failed to get reg property (ret:%d)",
5367                     drv_name, unit, ret);
5368                 return (DDI_FAILURE);
5369         }
5370         n = len / (sizeof (struct pci_phys_spec) / sizeof (int));
5371 
5372         ASSERT(regs != NULL && len > 0);
5373 
5374 #if GEM_DEBUG_LEVEL > 0
5375         for (i = 0; i < n; i++) {
5376                 cmn_err(CE_CONT,
5377                     "!%s%d: regs[%d]: %08x.%08x.%08x.%08x.%08x",
5378                     drv_name, unit, i,
5379                     regs[i].pci_phys_hi,
5380                     regs[i].pci_phys_mid,
5381                     regs[i].pci_phys_low,
5382                     regs[i].pci_size_hi,
5383                     regs[i].pci_size_low);
5384         }
5385 #endif
5386         for (i = 0; i < n; i++) {
5387                 if ((regs[i].pci_phys_hi & mask) == which) {
5388                         /* it's the requested space */
5389                         ddi_prop_free(regs);
5390                         goto address_range_found;
5391                 }
5392         }
5393         ddi_prop_free(regs);
5394         return (DDI_FAILURE);
5395 
5396 address_range_found:
5397         if ((ret = ddi_regs_map_setup(dip, i, basep, 0, 0, attrp, hp))
5398             != DDI_SUCCESS) {
5399                 cmn_err(CE_CONT,
5400                     "!%s%d: ddi_regs_map_setup failed (ret:%d)",
5401                     drv_name, unit, ret);
5402         }
5403 
5404         return (ret);
5405 }
5406 
5407 void
5408 gem_mod_init(struct dev_ops *dop, char *name)
5409 {
5410         mac_init_ops(dop, name);
5411 }
5412 
5413 void
5414 gem_mod_fini(struct dev_ops *dop)
5415 {
5416         mac_fini_ops(dop);
5417 }