diff options
author | gd78059 <none@none> | 2007-04-25 16:13:46 -0700 |
---|---|---|
committer | gd78059 <none@none> | 2007-04-25 16:13:46 -0700 |
commit | cc291a4c7fa2364298503d990fac11ec307b1765 (patch) | |
tree | 5da06febb7e616c5ba40c01f84f1dca5cb3410f8 /usr/src | |
parent | c17d6d0368a95d88a7901e522b92d3f7b95da5da (diff) | |
download | illumos-gate-cc291a4c7fa2364298503d990fac11ec307b1765.tar.gz |
PSARC 2007/221 DMFE conversion to GLDv3
6547091 dmfe should be converted to nemo
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/sun4u/dmfe/Makefile | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/dmfe/dmfe_main.c | 1200 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/dmfe/dmfe_mii.c | 100 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sys/dmfe_impl.h | 191 |
4 files changed, 610 insertions, 885 deletions
diff --git a/usr/src/uts/sun4u/dmfe/Makefile b/usr/src/uts/sun4u/dmfe/Makefile index f54fb779fe..db0b6a2f4f 100644 --- a/usr/src/uts/sun4u/dmfe/Makefile +++ b/usr/src/uts/sun4u/dmfe/Makefile @@ -20,7 +20,7 @@ # # # uts/sun4u/dmfe/Makefile -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -72,7 +72,7 @@ CFLAGS += $(CCVERBOSE) # # extra link arguments # -LDFLAGS += -dy -N misc/gld -N drv/ip +LDFLAGS += -dy -N misc/mac -N drv/ip # # For now, disable these lint checks; maintainers should endeavor diff --git a/usr/src/uts/sun4u/io/dmfe/dmfe_main.c b/usr/src/uts/sun4u/io/dmfe/dmfe_main.c index c8c1d479dd..bd12b6d5b8 100644 --- a/usr/src/uts/sun4u/io/dmfe/dmfe_main.c +++ b/usr/src/uts/sun4u/io/dmfe/dmfe_main.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,9 +29,8 @@ /* * This is the string displayed by modinfo, etc. - * Make sure you keep the version ID up to date! */ -static char dmfe_ident[] = "Davicom DM9102 v2.4"; +static char dmfe_ident[] = "Davicom DM9102 Ethernet"; /* @@ -195,24 +194,37 @@ static uint32_t factotum_fast_tix; static uint32_t factotum_start_tix; /* - * Versions of the O/S up to Solaris 8 didn't support network booting - * from any network interface except the first (NET0). Patching this - * flag to a non-zero value will tell the driver to work around this - * limitation by creating an extra (internal) pathname node. To do - * this, just add a line like the following to the CLIENT'S etc/system - * file ON THE ROOT FILESYSTEM SERVER before booting the client: - * - * set dmfe:dmfe_net1_boot_support = 1; - */ -static uint32_t dmfe_net1_boot_support = 0; - -/* * Property names */ static char localmac_propname[] = "local-mac-address"; static char opmode_propname[] = "opmode-reg-value"; static char debug_propname[] = "dmfe-debug-flags"; +static int dmfe_m_start(void *); +static void dmfe_m_stop(void *); +static int dmfe_m_promisc(void *, boolean_t); +static int dmfe_m_multicst(void *, boolean_t, const uint8_t *); +static int dmfe_m_unicst(void *, const uint8_t *); +static void dmfe_m_ioctl(void *, queue_t *, mblk_t *); +static boolean_t dmfe_m_getcapab(void *, mac_capab_t, void *); +static mblk_t *dmfe_m_tx(void *, mblk_t *); +static int dmfe_m_stat(void *, uint_t, uint64_t *); + +static mac_callbacks_t dmfe_m_callbacks = { + (MC_IOCTL | MC_GETCAPAB), + dmfe_m_stat, + dmfe_m_start, + dmfe_m_stop, + dmfe_m_promisc, + dmfe_m_multicst, + dmfe_m_unicst, + dmfe_m_tx, + NULL, + dmfe_m_ioctl, + dmfe_m_getcapab, +}; + + /* * Describes the chip's DMA engine */ @@ -348,8 +360,6 @@ dmfe_set_opmode(dmfe_t *dmfep) static void dmfe_stop_chip(dmfe_t *dmfep, enum chip_state newstate) { - DMFE_TRACE(("dmfe_stop_chip($%p, %d)", (void *)dmfep, newstate)); - ASSERT(mutex_owned(dmfep->oplock)); /* @@ -481,21 +491,17 @@ dmfe_init_rings(dmfe_t *dmfep) static void dmfe_start_chip(dmfe_t *dmfep, int mode) { - DMFE_TRACE(("dmfe_start_chip($%p, %d)", (void *)dmfep, mode)); - ASSERT(mutex_owned(dmfep->oplock)); dmfep->opmode |= mode; dmfe_set_opmode(dmfep); dmfe_chip_put32(dmfep, W_J_TIMER_REG, 0); -#if defined(VLAN_VID_NONE) /* * Enable VLAN length mode (allows packets to be 4 bytes Longer). */ - if (gld_recv_tagged != NULL) - dmfe_chip_put32(dmfep, W_J_TIMER_REG, VLAN_ENABLE); -#endif + dmfe_chip_put32(dmfep, W_J_TIMER_REG, VLAN_ENABLE); + /* * Clear any pending process-stopped interrupts */ @@ -572,11 +578,11 @@ dmfe_update_rx_stats(dmfe_t *dmfep, uint32_t desc0) * the last-fragment and error summary bits are set. */ if (((RX_LAST_DESC | RX_ERR_SUMMARY) & ~desc0) == 0) { - dmfep->rx_stats_errrcv += 1; + dmfep->rx_stats_ierrors += 1; /* * There are some other error bits in the descriptor for - * which there don't seem to be appropriate GLD statistics, + * which there don't seem to be appropriate MAC statistics, * notably RX_COLLISION and perhaps RX_DESC_ERR. The * latter may not be possible if it is supposed to indicate * that one buffer has been filled with a partial packet @@ -585,16 +591,17 @@ dmfe_update_rx_stats(dmfe_t *dmfep, uint32_t desc0) * enough for a whole packet without fragmenting. */ - if (desc0 & RX_OVERFLOW) + if (desc0 & RX_OVERFLOW) { dmfep->rx_stats_overflow += 1; - else if (desc0 & RX_RUNT_FRAME) + + } else if (desc0 & RX_RUNT_FRAME) dmfep->rx_stats_short += 1; if (desc0 & RX_CRC) - dmfep->rx_stats_crc += 1; + dmfep->rx_stats_fcs += 1; if (desc0 & RX_FRAME2LONG) - dmfep->rx_stats_frame_too_long += 1; + dmfep->rx_stats_toolong += 1; } /* @@ -603,45 +610,21 @@ dmfe_update_rx_stats(dmfe_t *dmfep, uint32_t desc0) * according to the chip data sheet :-? */ if (desc0 & RX_RCV_WD_TO) - dmfep->rx_stats_mac_rcv_error += 1; + dmfep->rx_stats_macrcv_errors += 1; if (desc0 & RX_DRIBBLING) - dmfep->rx_stats_frame += 1; + dmfep->rx_stats_align += 1; + if (desc0 & RX_MII_ERR) - dmfep->rx_stats_mac_rcv_error += 1; + dmfep->rx_stats_macrcv_errors += 1; } /* - * Ethernet packet-checking macros used in the receive code below. - * The <eap> parameter should be a pointer to the destination address found - * at the start of a received packet (an array of 6 (ETHERADDRL) bytes). - * - * A packet is intended for this station if the destination address exactly - * matches our own physical (unicast) address. - * - * A packet is a multicast (including broadcast) packet if the low-order bit - * of the first byte of the destination address is set (unicast addresses - * always have a zero in this bit). - * - * A packet should be passed up to GLD if it's multicast OR addressed to us - * OR if the device is in promiscuous mode, when all packets are passed up - * anyway. - */ -#define PKT_IS_MINE(eap, dmfep) (ether_cmp(eap, dmfep->curr_addr) == 0) -#define PKT_IS_MULTICAST(eap) (eap[0] & 1) -#define DEV_IS_PROMISC(dmfep) ((dmfep->opmode & PROMISC_MODE) != 0) - -#define PKT_WANTED(eap, dmfep) (PKT_IS_MULTICAST(eap) || \ - PKT_IS_MINE(eap, dmfep) || \ - DEV_IS_PROMISC(dmfep)) - -/* * Receive incoming packet(s) and pass them up ... */ static mblk_t * dmfe_getp(dmfe_t *dmfep) { - struct ether_header *ehp; dma_area_t *descp; mblk_t **tail; mblk_t *head; @@ -653,15 +636,13 @@ dmfe_getp(dmfe_t *dmfep) int packet_length; int index; - DMFE_TRACE(("dmfe_getp($%p)", (void *)dmfep)); - mutex_enter(dmfep->rxlock); /* * Update the missed frame statistic from the on-chip counter. */ misses = dmfe_chip_get32(dmfep, MISSED_FRAME_REG); - dmfep->rx_stats_missed += (misses & MISSED_FRAME_MASK); + dmfep->rx_stats_norcvbuf += (misses & MISSED_FRAME_MASK); /* * sync (all) receive descriptors before inspecting them @@ -713,6 +694,14 @@ dmfe_getp(dmfe_t *dmfep) "length %d", packet_length)); goto skip; } else if (packet_length < ETHERMIN) { + /* + * Note that VLAN packet would be even larger, + * but we don't worry about dropping runt VLAN + * frames. + * + * This check is probably redundant, as well, + * since the hardware should drop RUNT frames. + */ DMFE_DEBUG(("dmfe_getp: dropping undersize packet, " "length %d", packet_length)); goto skip; @@ -730,11 +719,14 @@ dmfe_getp(dmfe_t *dmfep) index*DMFE_BUF_SIZE, DMFE_BUF_SIZE, DDI_DMA_SYNC_FORKERNEL); rxb = &dmfep->rx_buff.mem_va[index*DMFE_BUF_SIZE]; - ehp = (struct ether_header *)rxb; - if (!PKT_WANTED(ehp->ether_dhost.ether_addr_octet, dmfep)) { - DMFE_DEBUG(("dmfe_getp: dropping aliased packet")); - goto skip; - } + + + /* + * We do not bother to check that the packet is really for + * us, we let the MAC framework make that check instead. + * This is especially important if we ever want to support + * multiple MAC addresses. + */ /* * Packet looks good; get a buffer to copy it into. We @@ -752,46 +744,29 @@ dmfe_getp(dmfe_t *dmfep) } /* + * Account for statistics of good packets. + */ + dmfep->rx_stats_ipackets += 1; + dmfep->rx_stats_rbytes += packet_length; + if (desc0 & RX_MULTI_FRAME) { + if (bcmp(rxb, dmfe_broadcast_addr, ETHERADDRL)) { + dmfep->rx_stats_multi += 1; + } else { + dmfep->rx_stats_bcast += 1; + } + } + + /* * Copy the packet into the STREAMS buffer */ dp = mp->b_rptr += DMFE_HEADROOM; mp->b_cont = mp->b_next = NULL; -#if !defined(VLAN_VID_NONE) - bcopy(rxb, dp, packet_length); -#else - if (ehp->ether_type != ETHERTYPE_VLAN || - gld_recv_tagged == NULL) { - /* - * An untagged packet (or, there's no runtime support - * for tagging so we treat all packets as untagged). - * Just copy the contents verbatim. - */ - bcopy(rxb, dp, packet_length); - } else { - /* - * A tagged packet. Extract the vtag & stash it in - * the b_cont field (we know that it's safe to grab - * the vtag directly because the way buffers are - * allocated guarantees their alignment). Copy the - * rest of the packet data to the mblk, dropping the - * vtag in the process. - * - * The magic number (2*ETHERADDRL) appears quite a - * lot here, because the vtag comes immediately after - * the destination & source Ethernet addresses in - * the packet header ... - */ - bcopy(rxb, dp, 2*ETHERADDRL); - rxb += 2*ETHERADDRL; - dp += 2*ETHERADDRL; - mp->b_cont = U32TOPTR(*(uint32_t *)rxb); - rxb += VTAG_SIZE; - packet_length -= VTAG_SIZE; - - bcopy(rxb, dp, packet_length - 2*ETHERADDRL); - } -#endif /* defined(VLAN_VID_NONE) */ + /* + * Don't worry about stripping the vlan tag, the MAC + * layer will take care of that for us. + */ + bcopy(rxb, dp, packet_length); /* * Fix up the packet length, and link it to the chain @@ -826,40 +801,6 @@ dmfe_getp(dmfe_t *dmfep) return (head); } -/* - * Take a chain of mblks (as returned by dmfe_getp() above) and pass - * them up to gld_recv() one at a time. This function should be called - * with *no* driver-defined locks held. - * - * If the driver is compiled with VLAN support enabled, this function - * also deals with routing vlan-tagged packets to the appropriate GLD - * entry point (gld_recv_tagged()). - */ -static void -dmfe_passup_chain(gld_mac_info_t *macinfo, mblk_t *mp) -{ - mblk_t *next; - uint32_t vtag; - - ASSERT(mp != NULL); - - do { - next = mp->b_next; - mp->b_next = NULL; -#if !defined(VLAN_VID_NONE) - gld_recv(macinfo, mp); -#else - vtag = PTRTOU32(mp->b_cont); - mp->b_cont = NULL; - if (vtag != VLAN_VTAG_NONE && gld_recv_tagged != NULL) - gld_recv_tagged(macinfo, mp, vtag); - else - gld_recv(macinfo, mp); -#endif /* defined(VLAN_VID_NONE) */ - mp = next; - } while (mp != NULL); -} - #undef DMFE_DBG @@ -936,7 +877,7 @@ dmfe_passup_chain(gld_mac_info_t *macinfo, mblk_t *mp) * Function to update transmit statistics on various errors */ static void -dmfe_update_tx_stats(dmfe_t *dmfep, uint32_t desc0) +dmfe_update_tx_stats(dmfe_t *dmfep, int index, uint32_t desc0, uint32_t desc1) { uint32_t collisions; uint32_t errbits; @@ -954,7 +895,7 @@ dmfe_update_tx_stats(dmfe_t *dmfep, uint32_t desc0) } if (desc0 & TX_ERR_SUMMARY) { - dmfep->tx_stats_errxmt += 1; + dmfep->tx_stats_oerrors += 1; /* * If we ever see a transmit jabber timeout, we count it @@ -963,7 +904,7 @@ dmfe_update_tx_stats(dmfe_t *dmfep, uint32_t desc0) * the chip in order to recover */ if (desc0 & TX_JABBER_TO) - dmfep->tx_stats_mac_xmt_error += 1; + dmfep->tx_stats_macxmt_errors += 1; if (desc0 & TX_UNDERFLOW) dmfep->tx_stats_underflow += 1; @@ -977,6 +918,21 @@ dmfe_update_tx_stats(dmfe_t *dmfep, uint32_t desc0) dmfep->tx_stats_excoll += 1; collisions = 16; } + } else { + int bit = index % NBBY; + int byt = index / NBBY; + + if (dmfep->tx_mcast[byt] & bit) { + dmfep->tx_mcast[byt] &= ~bit; + dmfep->tx_stats_multi += 1; + + } else if (dmfep->tx_bcast[byt] & bit) { + dmfep->tx_bcast[byt] &= ~bit; + dmfep->tx_stats_bcast += 1; + } + + dmfep->tx_stats_opackets += 1; + dmfep->tx_stats_obytes += desc1 & TX_BUFFER_SIZE1; } if (collisions == 1) @@ -1004,8 +960,6 @@ dmfe_reclaim_tx_desc(dmfe_t *dmfep) int nfree; int i; - DMFE_TRACE(("dmfe_reclaim_tx_desc($%p)", (void *)dmfep)); - ASSERT(mutex_owned(dmfep->txlock)); /* @@ -1061,7 +1015,7 @@ dmfe_reclaim_tx_desc(dmfe_t *dmfep) */ ASSERT(dmfe_ring_get32(descp, i, BUFFER1) == dmfep->tx_buff.mem_dvma + i*DMFE_BUF_SIZE); - dmfe_update_tx_stats(dmfep, desc0); + dmfe_update_tx_stats(dmfep, i, desc0, desc1); } #if DMFEDEBUG @@ -1102,8 +1056,8 @@ dmfe_reclaim_tx_desc(dmfe_t *dmfep) * Send the message in the message block chain <mp>. * * The message is freed if and only if its contents are successfully copied - * and queued for transmission (so that the return value is GLD_SUCCESS). - * If we can't queue the message, the return value is GLD_NORESOURCES and + * and queued for transmission (so that the return value is B_TRUE). + * If we can't queue the message, the return value is B_FALSE and * the message is *not* freed. * * This routine handles the special case of <mp> == NULL, which indicates @@ -1112,8 +1066,8 @@ dmfe_reclaim_tx_desc(dmfe_t *dmfep) * to say its a setup packet (from the global <dmfe_setup_desc1>), and the * setup packet *isn't* freed after use. */ -static int -dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) +static boolean_t +dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp) { dma_area_t *descp; mblk_t *bp; @@ -1123,9 +1077,6 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) size_t totlen; size_t mblen; - DMFE_TRACE(("dmfe_send_msg($%p, $%p, 0x%x)", - (void *)dmfep, (void *)mp, vtag)); - /* * If the number of free slots is below the reclaim threshold * (soft limit), we'll try to reclaim some. If we fail, and @@ -1137,13 +1088,13 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) dmfe_reclaim_tx_desc(dmfep) == B_FALSE && dmfep->tx.n_free <= dmfe_tx_min_free) { /* - * Resource shortage - return the proper GLD code, - * so the packet will be queued for retry after the - * next TX-done interrupt. + * Resource shortage - return B_FALSE so the packet + * will be queued for retry after the next TX-done + * interrupt. */ mutex_exit(dmfep->txlock); DMFE_DEBUG(("dmfe_send_msg: no free descriptors")); - return (GLD_NORESOURCES); + return (B_FALSE); } /* @@ -1202,51 +1153,6 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) totlen = 0; bp = mp; -#if defined(VLAN_VID_NONE) - if (vtag != VLAN_VTAG_NONE) { - /* - * A tagged packet. While copying the data from - * the first mblk into the Tx buffer, insert the - * vtag. IP and/or GLD have already guaranteed - * that the entire struct ether_header (14 bytes) - * at the start of the packet can be found in the - * first mblk, so we don't have to worry about it - * being split into multiple fragments. - * - * The magic number (2*ETHERADDRL) appears quite a - * lot here, because the vtag comes immediately after - * the destination & source Ethernet addresses in - * the packet header. - * - * The way we allocated the buffers guarantees - * their alignment, so it's safe to stash the vtag - * directly into the buffer at the proper offset - * (4 bytes, 12 bytes into the frame). - * - * Once we have copied the data from the first mblk, - * we can fall through to the untagged packet code - * to handle the rest of the chain, if any. - */ - mblen = bp->b_wptr - bp->b_rptr; - ASSERT(mblen >= sizeof (struct ether_header)); - - bcopy(bp->b_rptr, txb, 2*ETHERADDRL); - txb += 2*ETHERADDRL; - totlen += 2*ETHERADDRL; - mblen -= 2*ETHERADDRL; - - *(uint32_t *)txb = vtag; - txb += VTAG_SIZE; - totlen += VTAG_SIZE; - - bcopy(bp->b_rptr + 2*ETHERADDRL, txb, mblen); - txb += mblen; - totlen += mblen; - - bp = bp->b_cont; - } -#endif /* defined(VLAN_VID_NONE) */ - /* * Copy all (remaining) mblks in the message ... */ @@ -1259,6 +1165,22 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) } /* + * Is this a multicast or broadcast packet? We do + * this so that we can track statistics accurately + * when we reclaim it. + */ + txb = &dmfep->tx_buff.mem_va[index*DMFE_BUF_SIZE]; + if (txb[0] & 0x1) { + if (bcmp(txb, dmfe_broadcast_addr, ETHERADDRL) == 0) { + dmfep->tx_bcast[index / NBBY] |= + (1 << (index % NBBY)); + } else { + dmfep->tx_mcast[index / NBBY] |= + (1 << (index % NBBY)); + } + } + + /* * We'e reached the end of the chain; and we should have * collected no more than DMFE_MAX_PKT_SIZE bytes into our * buffer. Note that the <size> field in the descriptor is @@ -1272,6 +1194,7 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) (void) ddi_dma_sync(dmfep->tx_buff.dma_hdl, index*DMFE_BUF_SIZE, DMFE_BUF_SIZE, DDI_DMA_SYNC_FORDEV); + } /* @@ -1291,65 +1214,44 @@ dmfe_send_msg(dmfe_t *dmfep, mblk_t *mp, uint32_t vtag) */ if (mp) freemsg(mp); - return (GLD_SUCCESS); + return (B_TRUE); } /* - * dmfe_gld_send() -- send a packet + * dmfe_m_tx() -- send a chain of packets * - * Called when a packet is ready to be transmitted. A pointer to an + * Called when packet(s) are ready to be transmitted. A pointer to an * M_DATA message that contains the packet is passed to this routine. * The complete LLC header is contained in the message's first message * block, and the remainder of the packet is contained within * additional M_DATA message blocks linked to the first message block. - */ -static int -dmfe_gld_send(gld_mac_info_t *macinfo, mblk_t *mp) -{ - dmfe_t *dmfep; /* private device info */ - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_send($%p, $%p)", - (void *)macinfo, (void *)mp)); - - ASSERT(mp != NULL); - ASSERT(dmfep->gld_state == GLD_STARTED); - - if (dmfep->chip_state != CHIP_RUNNING) - return (GLD_NORESOURCES); - - return (dmfe_send_msg(dmfep, mp, VLAN_VTAG_NONE)); -} - -#if defined(VLAN_VID_NONE) -/* - * dmfe_gld_send_tagged() -- send a tagged packet * - * Called when a packet is ready to be transmitted. A pointer to an - * M_DATA message that contains the packet is passed to this routine. - * The complete LLC header is contained in the message's first message - * block, and the remainder of the packet is contained within - * additional M_DATA message blocks linked to the first message block. + * Additional messages may be passed by linking with b_next. */ -static int -dmfe_gld_send_tagged(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag) +static mblk_t * +dmfe_m_tx(void *arg, mblk_t *mp) { - dmfe_t *dmfep; /* private device info */ - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_send_vtag($%p, $%p, $%x)", - (void *)macinfo, (void *)mp, vtag)); + dmfe_t *dmfep = arg; /* private device info */ + mblk_t *next; ASSERT(mp != NULL); - ASSERT(dmfep->gld_state == GLD_STARTED); + ASSERT(dmfep->mac_state == DMFE_MAC_STARTED); if (dmfep->chip_state != CHIP_RUNNING) - return (GLD_NORESOURCES); + return (mp); - return (dmfe_send_msg(dmfep, mp, vtag)); -} -#endif /* defined(VLAN_VID_NONE) */ + while (mp != NULL) { + next = mp->b_next; + mp->b_next = NULL; + if (!dmfe_send_msg(dmfep, mp)) { + mp->b_next = next; + break; + } + mp = next; + } + return (mp); +} #undef DMFE_DBG @@ -1365,7 +1267,7 @@ dmfe_gld_send_tagged(gld_mac_info_t *macinfo, mblk_t *mp, uint32_t vtag) * This must mirror the way the hardware will actually calculate it! */ static uint32_t -dmfe_hash_index(uchar_t *address) +dmfe_hash_index(const uint8_t *address) { uint32_t const POLY = HASH_POLY; uint32_t crc = HASH_CRC; @@ -1424,22 +1326,16 @@ dmfe_update_hash(dmfe_t *dmfep, uint32_t index, boolean_t val) * changed), return B_FALSE */ static boolean_t -dmfe_update_mcast(dmfe_t *dmfep, uchar_t *mca, boolean_t val, const char *what) +dmfe_update_mcast(dmfe_t *dmfep, const uint8_t *mca, boolean_t val) { uint32_t index; uint8_t *refp; - uint8_t oldref; boolean_t change; index = dmfe_hash_index(mca); refp = &dmfep->mcast_refs[index]; - oldref = *refp; change = (val ? (*refp)++ : --(*refp)) == 0; - DMFE_DEBUG(("dmfe_update_mcast: %s %s %s index %d ref %d->%d%s", - ether_sprintf((void *)mca), val ? "ON" : "OFF", what, - index, oldref, *refp, change ? " (CHANGED)" : "")); - if (change) dmfe_update_hash(dmfep, index, val); @@ -1454,21 +1350,15 @@ dmfe_send_setup(dmfe_t *dmfep) { int status; - DMFE_TRACE(("dmfe_send_setup($%p)", (void *)dmfep)); - ASSERT(mutex_owned(dmfep->oplock)); /* * If the chip isn't running, we can't really send the setup frame * now but it doesn't matter, 'cos it will be sent when the transmit - * process is restarted (see dmfe_start()). It isn't an error; in - * fact, GLD v2 will always call dmfe_gld_set_mac_addr() after a - * reset, so that the address can be set up before the chip is - * started. In this context, the return code GLD_NOTSUPPORTED is - * taken as success! + * process is restarted (see dmfe_start()). */ if ((dmfep->opmode & START_TRANSMIT) == 0) - return (GLD_NOTSUPPORTED); + return (0); /* * "Send" the setup frame. If it fails (e.g. no resources), @@ -1477,25 +1367,21 @@ dmfe_send_setup(dmfe_t *dmfep) * had previously failed. We tell the caller that it worked * whether it did or not; after all, it *will* work eventually. */ - status = dmfe_send_msg(dmfep, NULL, VLAN_VTAG_NONE); - dmfep->need_setup = status != GLD_SUCCESS; - return (GLD_SUCCESS); + status = dmfe_send_msg(dmfep, NULL); + dmfep->need_setup = status ? B_FALSE : B_TRUE; + return (0); } /* - * dmfe_gld_set_mac_addr() -- set the physical network address + * dmfe_m_unicst() -- set the physical network address */ static int -dmfe_gld_set_mac_addr(gld_mac_info_t *macinfo, uchar_t *macaddr) +dmfe_m_unicst(void *arg, const uint8_t *macaddr) { - dmfe_t *dmfep; /* private device info */ + dmfe_t *dmfep = arg; int status; int index; - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_set_mac_addr($%p, %s)", - (void *)macinfo, ether_sprintf((void *)macaddr))); - /* * Update our current address and send out a new setup packet * @@ -1533,13 +1419,11 @@ dmfe_gld_set_mac_addr(gld_mac_info_t *macinfo, uchar_t *macaddr) mutex_enter(dmfep->oplock); if (dmfep->addr_set && dmfe_setup_desc1 & TX_FILTER_TYPE1) - (void) dmfe_update_mcast(dmfep, dmfep->curr_addr, B_FALSE, - "xaddr"); + (void) dmfe_update_mcast(dmfep, dmfep->curr_addr, B_FALSE); if (dmfe_setup_desc1 & TX_FILTER_TYPE1) - (void) dmfe_update_mcast(dmfep, macaddr, B_TRUE, "saddr"); + (void) dmfe_update_mcast(dmfep, macaddr, B_TRUE); if (!dmfep->addr_set) - (void) dmfe_update_mcast(dmfep, dmfe_broadcast_addr, B_TRUE, - "bcast"); + (void) dmfe_update_mcast(dmfep, dmfe_broadcast_addr, B_TRUE); /* * Remember the new current address @@ -1567,28 +1451,23 @@ dmfe_gld_set_mac_addr(gld_mac_info_t *macinfo, uchar_t *macaddr) } /* - * dmfe_gld_set_multicast() -- enable or disable a multicast address + * dmfe_m_multicst() -- enable or disable a multicast address * * Program the hardware to enable/disable the multicast address - * in "mca" (enable if "flag" is GLD_MULTI_ENABLE, otherwise disable). + * in "mca" (enable if add is true, otherwise disable it.) * We keep a refcount for each bit in the map, so that it still * works out properly if multiple addresses hash to the same bit. * dmfe_update_mcast() tells us whether the map actually changed; * if so, we have to re-"transmit" the magic setup packet. */ static int -dmfe_gld_set_multicast(gld_mac_info_t *macinfo, uchar_t *mca, int flag) +dmfe_m_multicst(void *arg, boolean_t add, const uint8_t *mca) { - dmfe_t *dmfep; /* private device info */ - int status; + dmfe_t *dmfep = arg; /* private device info */ + int status = 0; - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_set_multicast($%p, %s, %d)", - (void *)macinfo, ether_sprintf((void *)mca), flag)); - - status = GLD_SUCCESS; mutex_enter(dmfep->oplock); - if (dmfe_update_mcast(dmfep, mca, flag == GLD_MULTI_ENABLE, "mcast")) + if (dmfe_update_mcast(dmfep, mca, add)) status = dmfe_send_setup(dmfep); mutex_exit(dmfep->oplock); @@ -1606,9 +1485,9 @@ dmfe_gld_set_multicast(gld_mac_info_t *macinfo, uchar_t *mca, int flag) /* * These routines provide all the functionality required by the - * corresponding GLD entry points, but don't update the GLD state + * corresponding MAC layer entry points, but don't update the MAC layer state * so they can be called internally without disturbing our record - * of what GLD thinks we should be doing ... + * of what MAC layer thinks we should be doing ... */ /* @@ -1617,8 +1496,6 @@ dmfe_gld_set_multicast(gld_mac_info_t *macinfo, uchar_t *mca, int flag) static void dmfe_stop(dmfe_t *dmfep) { - DMFE_TRACE(("dmfe_stop($%p)", (void *)dmfep)); - ASSERT(mutex_owned(dmfep->oplock)); dmfe_stop_chip(dmfep, CHIP_STOPPED); @@ -1630,8 +1507,6 @@ dmfe_stop(dmfe_t *dmfep) static void dmfe_reset(dmfe_t *dmfep) { - DMFE_TRACE(("dmfe_reset($%p)", (void *)dmfep)); - ASSERT(mutex_owned(dmfep->oplock)); ASSERT(mutex_owned(dmfep->rxlock)); ASSERT(mutex_owned(dmfep->txlock)); @@ -1648,8 +1523,6 @@ dmfe_start(dmfe_t *dmfep) { uint32_t gpsr; - DMFE_TRACE(("dmfe_start($%p)", (void *)dmfep)); - ASSERT(mutex_owned(dmfep->oplock)); ASSERT(dmfep->chip_state == CHIP_RESET || @@ -1695,95 +1568,53 @@ dmfe_restart(dmfe_t *dmfep) dmfe_reset(dmfep); mutex_exit(dmfep->txlock); mutex_exit(dmfep->rxlock); - if (dmfep->gld_state == GLD_STARTED) + if (dmfep->mac_state == DMFE_MAC_STARTED) dmfe_start(dmfep); } /* - * ========== GLD-required management entry points ========== - */ - -/* - * dmfe_gld_reset() -- reset to initial state + * ========== MAC-required management entry points ========== */ -static int -dmfe_gld_reset(gld_mac_info_t *macinfo) -{ - dmfe_t *dmfep; /* private device info */ - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_reset($%p)", (void *)macinfo)); - - /* - * Reset chip & rings to initial state; also reset address - * filtering & record new GLD state. You need *all* the locks - * in order to stop all other activity while doing this! - */ - mutex_enter(dmfep->oplock); - mutex_enter(dmfep->rxlock); - mutex_enter(dmfep->txlock); - - dmfe_reset(dmfep); - bzero(dmfep->tx_desc.setup_va, SETUPBUF_SIZE); - bzero(dmfep->mcast_refs, MCASTBUF_SIZE); - dmfep->addr_set = B_FALSE; - dmfep->opmode &= ~(PROMISC_MODE | PASS_MULTICAST); - dmfep->gld_state = GLD_RESET; - - mutex_exit(dmfep->txlock); - mutex_exit(dmfep->rxlock); - mutex_exit(dmfep->oplock); - - return (0); -} /* - * dmfe_gld_stop() -- stop transmitting/receiving + * dmfe_m_stop() -- stop transmitting/receiving */ -static int -dmfe_gld_stop(gld_mac_info_t *macinfo) +static void +dmfe_m_stop(void *arg) { - dmfe_t *dmfep; /* private device info */ - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_stop($%p)", (void *)macinfo)); + dmfe_t *dmfep = arg; /* private device info */ /* - * Just stop processing, then record new GLD state + * Just stop processing, then record new MAC state */ mutex_enter(dmfep->oplock); dmfe_stop(dmfep); - dmfep->gld_state = GLD_STOPPED; + dmfep->mac_state = DMFE_MAC_STOPPED; mutex_exit(dmfep->oplock); - - return (0); } /* - * dmfe_gld_start() -- start transmitting/receiving + * dmfe_m_start() -- start transmitting/receiving */ static int -dmfe_gld_start(gld_mac_info_t *macinfo) +dmfe_m_start(void *arg) { - dmfe_t *dmfep; /* private device info */ - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_start($%p)", (void *)macinfo)); + dmfe_t *dmfep = arg; /* private device info */ /* - * Start processing and record new GLD state + * Start processing and record new MAC state */ mutex_enter(dmfep->oplock); dmfe_start(dmfep); - dmfep->gld_state = GLD_STARTED; + dmfep->mac_state = DMFE_MAC_STARTED; mutex_exit(dmfep->oplock); return (0); } /* - * dmfe_gld_set_promiscuous() -- set or reset promiscuous mode on the board + * dmfe_m_promisc() -- set or reset promiscuous mode on the board * * Program the hardware to enable/disable promiscuous and/or * receive-all-multicast modes. Davicom don't document this @@ -1791,48 +1622,60 @@ dmfe_gld_start(gld_mac_info_t *macinfo) * without stopping & restarting the TX/RX processes). */ static int -dmfe_gld_set_promiscuous(gld_mac_info_t *macinfo, int mode) +dmfe_m_promisc(void *arg, boolean_t on) { - dmfe_t *dmfep; - uint32_t pmode; - - dmfep = DMFE_STATE(macinfo); - DMFE_TRACE(("dmfe_gld_set_promiscuous($%p, %d)", - (void *)macinfo, mode)); - - /* - * Convert GLD-specified mode to DMFE opmode setting - */ - switch (mode) { - case GLD_MAC_PROMISC_NONE: - pmode = 0; - break; - - case GLD_MAC_PROMISC_MULTI: - pmode = PASS_MULTICAST; - break; - - case GLD_MAC_PROMISC_PHYS: - pmode = PROMISC_MODE; - break; - - default: - return (GLD_NOTSUPPORTED); - } + dmfe_t *dmfep = arg; mutex_enter(dmfep->oplock); dmfep->opmode &= ~(PROMISC_MODE | PASS_MULTICAST); - dmfep->opmode |= pmode; + if (on) + dmfep->opmode |= PROMISC_MODE; dmfe_set_opmode(dmfep); - pmode = dmfep->opmode; mutex_exit(dmfep->oplock); - DMFE_DEBUG(("dmfe_gld_set_promiscuous: mode %d => opmode 0x%x", - mode, pmode)); + return (0); +} - return (GLD_SUCCESS); +/*ARGSUSED*/ +static boolean_t +dmfe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) +{ + /* + * Note that the chip could support some form of polling and + * multiaddress support. We should look into adding polling + * support later, once Solaris is better positioned to take + * advantage of it, although it may be of little use since + * even a lowly 500MHz US-IIe should be able to keep up with + * 100Mbps. (Esp. if the packets are not unreasonably sized.) + * + * Multiaddress support, however, is likely to be of more + * utility with crossbow and virtualized NICs. Although, the + * fact that dmfe is only supported on low-end US-IIe hardware + * makes one wonder whether VNICs are likely to be used on + * such platforms. The chip certainly supports the notion, + * since it can be run in HASH-ONLY mode. (Though this would + * require software to drop unicast packets that are + * incorrectly received due to hash collision of the + * destination mac address.) + * + * Interestingly enough, modern Davicom chips (the 9102D) + * support full IP checksum offload, though its unclear + * whether any of these chips are used on any systems that can + * run Solaris. + * + * If this driver is ever supported on x86 hardware, then + * these assumptions should be revisited. + */ + switch (cap) { + case MAC_CAPAB_POLL: + case MAC_CAPAB_MULTIADDRESS: + case MAC_CAPAB_HCKSUM: + default: + return (B_FALSE); + } } + #undef DMFE_DBG @@ -1903,19 +1746,16 @@ dmfe_factotum(caddr_t arg) dmfep->update_phy = B_FALSE; } dmfe_recheck_link(dmfep, B_FALSE); - if (dmfep->gld_state == GLD_STARTED) + if (dmfep->mac_state == DMFE_MAC_STARTED) dmfe_start(dmfep); mutex_exit(dmfep->oplock); } mutex_exit(dmfep->milock); /* - * Keep GLD up-to-date about the state of the link ... + * Keep MAC up-to-date about the state of the link ... */ - if (gld_linkstate != NULL) - gld_linkstate(DMFE_MACINFO(dmfep), - dmfep->link_state == LINK_UP ? - GLD_LINKSTATE_UP : GLD_LINKSTATE_DOWN); + mac_link_update(dmfep->mh, dmfep->link_state); return (DDI_INTR_CLAIMED); } @@ -1976,11 +1816,12 @@ dmfe_tick_link_check(dmfe_t *dmfep, uint32_t gpsr, uint32_t istat) * Has the link status changed? If so, we might want to wake * the factotum to deal with it. */ - phy_state = (gpsr & GPS_LINK_STATUS) ? LINK_UP : LINK_DOWN; - utp_state = (gpsr & GPS_UTP_SIG) ? LINK_UP : LINK_DOWN; + phy_state = (gpsr & GPS_LINK_STATUS) ? LINK_STATE_UP : LINK_STATE_DOWN; + utp_state = (gpsr & GPS_UTP_SIG) ? LINK_STATE_UP : LINK_STATE_DOWN; if (phy_state != utp_state) why = "tick (phy <> utp)"; - else if (dmfep->link_state == LINK_UP && phy_state == LINK_DOWN) + else if ((dmfep->link_state == LINK_STATE_UP) && + (phy_state == LINK_STATE_DOWN)) why = "tick (UP -> DOWN)"; else if (phy_state != dmfep->link_state) { if (dmfep->link_poll_tix > factotum_fast_tix) @@ -2149,7 +1990,7 @@ dmfe_interrupt(caddr_t arg) * need to get the lock before going any further ... */ mutex_enter(dmfep->oplock); - dmfep->op_stats_intr += 1; + DRV_KS_INC(dmfep, KS_INTERRUPT); /* * Identify bits that represent enabled interrupts ... @@ -2269,12 +2110,12 @@ dmfe_interrupt(caddr_t arg) if (interrupts & RX_PKTDONE_INT) if ((mp = dmfe_getp(dmfep)) != NULL) - dmfe_passup_chain(DMFE_MACINFO(dmfep), mp); + mac_rx(dmfep->mh, NULL, mp); if (interrupts & TX_PKTDONE_INT) { /* * The only reason for taking this interrupt is to give - * GLD a chance to schedule queued packets after a + * MAC a chance to schedule queued packets after a * ring-full condition. To minimise the number of * redundant TX-Done interrupts, we only mark two of the * ring descriptors as 'interrupt-on-complete' - all the @@ -2284,7 +2125,7 @@ dmfe_interrupt(caddr_t arg) (void) dmfe_reclaim_tx_desc(dmfep); mutex_exit(dmfep->txlock); } - gld_sched(DMFE_MACINFO(dmfep)); + mac_tx_update(dmfep->mh); } return (DDI_INTR_CLAIMED); @@ -2300,47 +2141,226 @@ dmfe_interrupt(caddr_t arg) #define DMFE_DBG DMFE_DBG_STATS /* debug flag for this code */ static int -dmfe_gld_get_stats(gld_mac_info_t *macinfo, struct gld_stats *sp) +dmfe_m_stat(void *arg, uint_t stat, uint64_t *val) { - dmfe_t *dmfep; - - dmfep = DMFE_STATE(macinfo); + dmfe_t *dmfep = arg; + int rv = 0; + mutex_enter(dmfep->milock); mutex_enter(dmfep->oplock); mutex_enter(dmfep->rxlock); mutex_enter(dmfep->txlock); - sp->glds_speed = dmfep->op_stats_speed; - sp->glds_duplex = dmfep->op_stats_duplex; - sp->glds_media = dmfep->op_stats_media; - sp->glds_intr = dmfep->op_stats_intr; - - sp->glds_errrcv = dmfep->rx_stats_errrcv; - sp->glds_overflow = dmfep->rx_stats_overflow; - sp->glds_short = dmfep->rx_stats_short; - sp->glds_crc = dmfep->rx_stats_crc; - sp->glds_dot3_frame_too_long = dmfep->rx_stats_frame_too_long; - sp->glds_dot3_mac_rcv_error = dmfep->rx_stats_mac_rcv_error; - sp->glds_frame = dmfep->rx_stats_frame; - sp->glds_missed = dmfep->rx_stats_missed; - sp->glds_norcvbuf = dmfep->rx_stats_norcvbuf; - - sp->glds_errxmt = dmfep->tx_stats_errxmt; - sp->glds_dot3_mac_xmt_error = dmfep->tx_stats_mac_xmt_error; - sp->glds_underflow = dmfep->tx_stats_underflow; - sp->glds_xmtlatecoll = dmfep->tx_stats_xmtlatecoll; - sp->glds_nocarrier = dmfep->tx_stats_nocarrier; - sp->glds_excoll = dmfep->tx_stats_excoll; - sp->glds_dot3_first_coll = dmfep->tx_stats_first_coll; - sp->glds_dot3_multi_coll = dmfep->tx_stats_multi_coll; - sp->glds_collisions = dmfep->tx_stats_collisions; - sp->glds_defer = dmfep->tx_stats_defer; + /* make sure we have all the stats collected */ + (void) dmfe_reclaim_tx_desc(dmfep); + + switch (stat) { + case MAC_STAT_IFSPEED: + *val = dmfep->op_stats_speed; + break; + + case MAC_STAT_IPACKETS: + *val = dmfep->rx_stats_ipackets; + break; + + case MAC_STAT_MULTIRCV: + *val = dmfep->rx_stats_multi; + break; + + case MAC_STAT_BRDCSTRCV: + *val = dmfep->rx_stats_bcast; + break; + + case MAC_STAT_RBYTES: + *val = dmfep->rx_stats_rbytes; + break; + + case MAC_STAT_IERRORS: + *val = dmfep->rx_stats_ierrors; + break; + + case MAC_STAT_NORCVBUF: + *val = dmfep->rx_stats_norcvbuf; + break; + + case MAC_STAT_COLLISIONS: + *val = dmfep->tx_stats_collisions; + break; + + case MAC_STAT_OERRORS: + *val = dmfep->tx_stats_oerrors; + break; + + case MAC_STAT_OPACKETS: + *val = dmfep->tx_stats_opackets; + break; + + case MAC_STAT_MULTIXMT: + *val = dmfep->tx_stats_multi; + break; + + case MAC_STAT_BRDCSTXMT: + *val = dmfep->tx_stats_bcast; + break; + + case MAC_STAT_OBYTES: + *val = dmfep->tx_stats_obytes; + break; + + case MAC_STAT_OVERFLOWS: + *val = dmfep->rx_stats_overflow; + break; + + case MAC_STAT_UNDERFLOWS: + *val = dmfep->tx_stats_underflow; + break; + + case ETHER_STAT_ALIGN_ERRORS: + *val = dmfep->rx_stats_align; + break; + + case ETHER_STAT_FCS_ERRORS: + *val = dmfep->rx_stats_fcs; + break; + + case ETHER_STAT_TOOLONG_ERRORS: + *val = dmfep->rx_stats_toolong; + break; + + case ETHER_STAT_TOOSHORT_ERRORS: + *val = dmfep->rx_stats_short; + break; + + case ETHER_STAT_MACRCV_ERRORS: + *val = dmfep->rx_stats_macrcv_errors; + break; + + case ETHER_STAT_MACXMT_ERRORS: + *val = dmfep->tx_stats_macxmt_errors; + break; + + case ETHER_STAT_CARRIER_ERRORS: + *val = dmfep->tx_stats_nocarrier; + break; + + case ETHER_STAT_TX_LATE_COLLISIONS: + *val = dmfep->tx_stats_xmtlatecoll; + break; + + case ETHER_STAT_EX_COLLISIONS: + *val = dmfep->tx_stats_excoll; + break; + + case ETHER_STAT_DEFER_XMTS: + *val = dmfep->tx_stats_defer; + break; + + case ETHER_STAT_FIRST_COLLISIONS: + *val = dmfep->tx_stats_first_coll; + break; + + case ETHER_STAT_MULTI_COLLISIONS: + *val = dmfep->tx_stats_multi_coll; + break; + + case ETHER_STAT_XCVR_INUSE: + *val = dmfep->phy_inuse; + break; + + case ETHER_STAT_XCVR_ID: + *val = dmfep->phy_id; + break; + + case ETHER_STAT_XCVR_ADDR: + *val = dmfep->phy_addr; + break; + + case ETHER_STAT_LINK_DUPLEX: + *val = dmfep->op_stats_duplex; + break; + + case ETHER_STAT_CAP_100FDX: + *val = dmfep->param_bmsr_100fdx; + break; + + case ETHER_STAT_CAP_100HDX: + *val = dmfep->param_bmsr_100hdx; + break; + + case ETHER_STAT_CAP_10FDX: + *val = dmfep->param_bmsr_10fdx; + break; + + case ETHER_STAT_CAP_10HDX: + *val = dmfep->param_bmsr_10hdx; + break; + + case ETHER_STAT_CAP_AUTONEG: + *val = dmfep->param_bmsr_autoneg; + break; + + case ETHER_STAT_CAP_REMFAULT: + *val = dmfep->param_bmsr_remfault; + break; + + case ETHER_STAT_ADV_CAP_AUTONEG: + *val = dmfep->param_autoneg; + break; + + case ETHER_STAT_ADV_CAP_100FDX: + *val = dmfep->param_anar_100fdx; + break; + + case ETHER_STAT_ADV_CAP_100HDX: + *val = dmfep->param_anar_100hdx; + break; + + case ETHER_STAT_ADV_CAP_10FDX: + *val = dmfep->param_anar_10fdx; + break; + + case ETHER_STAT_ADV_CAP_10HDX: + *val = dmfep->param_anar_10hdx; + break; + + case ETHER_STAT_ADV_REMFAULT: + *val = dmfep->param_anar_remfault; + break; + + case ETHER_STAT_LP_CAP_AUTONEG: + *val = dmfep->param_lp_autoneg; + break; + + case ETHER_STAT_LP_CAP_100FDX: + *val = dmfep->param_lp_100fdx; + break; + + case ETHER_STAT_LP_CAP_100HDX: + *val = dmfep->param_lp_100hdx; + break; + + case ETHER_STAT_LP_CAP_10FDX: + *val = dmfep->param_lp_10fdx; + break; + + case ETHER_STAT_LP_CAP_10HDX: + *val = dmfep->param_lp_10hdx; + break; + + case ETHER_STAT_LP_REMFAULT: + *val = dmfep->param_lp_remfault; + break; + + default: + rv = ENOTSUP; + } mutex_exit(dmfep->txlock); mutex_exit(dmfep->rxlock); mutex_exit(dmfep->oplock); + mutex_exit(dmfep->milock); - return (GLD_SUCCESS); + return (rv); } #undef DMFE_DBG @@ -2360,6 +2380,9 @@ dmfe_gld_get_stats(gld_mac_info_t *macinfo, struct gld_stats *sp) * These will be used by netlbtest (see BugId 4370609) * * Note that changing the loopback mode causes a stop/restart cycle + * + * It would be nice to evolve this to support the ioctls in sys/netlb.h, + * but then it would be even better to use Brussels to configure this. */ static enum ioc_reply dmfe_loop_ioctl(dmfe_t *dmfep, queue_t *wq, mblk_t *mp, int cmd) @@ -2433,21 +2456,16 @@ dmfe_loop_ioctl(dmfe_t *dmfep, queue_t *wq, mblk_t *mp, int cmd) } /* - * Specific dmfe IOCTLs, the gld module handles the generic ones. + * Specific dmfe IOCTLs, the mac module handles the generic ones. */ -static int -dmfe_gld_ioctl(gld_mac_info_t *macinfo, queue_t *wq, mblk_t *mp) +static void +dmfe_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) { - dmfe_t *dmfep; + dmfe_t *dmfep = arg; struct iocblk *iocp; enum ioc_reply status; int cmd; - dmfep = DMFE_STATE(macinfo); - - DMFE_TRACE(("dmfe_gld_ioctl($%p, $%p, $%p)", - (void *)macinfo, (void *)wq, (void *)mp)); - /* * Validate the command before bothering with the mutexen ... */ @@ -2455,14 +2473,14 @@ dmfe_gld_ioctl(gld_mac_info_t *macinfo, queue_t *wq, mblk_t *mp) cmd = iocp->ioc_cmd; switch (cmd) { default: - DMFE_DEBUG(("dmfe_gld_ioctl: unknown cmd 0x%x", cmd)); + DMFE_DEBUG(("dmfe_m_ioctl: unknown cmd 0x%x", cmd)); miocnak(wq, mp, 0, EINVAL); - return (GLD_SUCCESS); + return; case DMFE_SET_LOOP_MODE: case DMFE_GET_LOOP_MODE: - case DMFE_ND_GET: - case DMFE_ND_SET: + case ND_GET: + case ND_SET: break; } @@ -2480,8 +2498,8 @@ dmfe_gld_ioctl(gld_mac_info_t *macinfo, queue_t *wq, mblk_t *mp) status = dmfe_loop_ioctl(dmfep, wq, mp, cmd); break; - case DMFE_ND_GET: - case DMFE_ND_SET: + case ND_GET: + case ND_SET: status = dmfe_nd_ioctl(dmfep, wq, mp, cmd); break; } @@ -2518,7 +2536,7 @@ dmfe_gld_ioctl(gld_mac_info_t *macinfo, queue_t *wq, mblk_t *mp) dmfe_wake_factotum(dmfep, KS_LINK_CHECK, "ioctl"); } - if (dmfep->gld_state == GLD_STARTED) + if (dmfep->mac_state == DMFE_MAC_STARTED) dmfe_start(dmfep); break; } @@ -2563,8 +2581,6 @@ dmfe_gld_ioctl(gld_mac_info_t *macinfo, queue_t *wq, mblk_t *mp) */ break; } - - return (GLD_SUCCESS); } #undef DMFE_DBG @@ -2591,17 +2607,17 @@ dmfe_find_mac_address(dmfe_t *dmfep) * the value of the property "local-mac-address", as set by OBP * (or a .conf file!) */ - bzero(dmfep->vendor_addr, sizeof (dmfep->vendor_addr)); + bzero(dmfep->curr_addr, sizeof (dmfep->curr_addr)); err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dmfep->devinfo, DDI_PROP_DONTPASS, localmac_propname, &prop, &propsize); if (err == DDI_PROP_SUCCESS) { if (propsize == ETHERADDRL) - ethaddr_copy(prop, dmfep->vendor_addr); + ethaddr_copy(prop, dmfep->curr_addr); ddi_prop_free(prop); } DMFE_DEBUG(("dmfe_setup_mac_address: factory %s", - ether_sprintf((void *)dmfep->vendor_addr))); + ether_sprintf((void *)dmfep->curr_addr))); } static int @@ -2703,6 +2719,12 @@ dmfe_alloc_bufs(dmfe_t *dmfep) if (err != DDI_SUCCESS) return (DDI_FAILURE); + /* + * Allocate bitmasks for tx packet type tracking + */ + dmfep->tx_mcast = kmem_zalloc(dmfep->tx.n_desc / NBBY, KM_SLEEP); + dmfep->tx_bcast = kmem_zalloc(dmfep->tx.n_desc / NBBY, KM_SLEEP); + return (DDI_SUCCESS); } @@ -2739,6 +2761,8 @@ dmfe_free_bufs(dmfe_t *dmfep) dmfe_free_dma_mem(&dmfep->rx_desc); dmfe_free_dma_mem(&dmfep->tx_buff); dmfe_free_dma_mem(&dmfep->tx_desc); + kmem_free(dmfep->tx_mcast, dmfep->tx.n_desc / NBBY); + kmem_free(dmfep->tx_bcast, dmfep->tx.n_desc / NBBY); } static void @@ -2753,8 +2777,6 @@ dmfe_unattach(dmfe_t *dmfep) mutex_exit(&cpu_lock); dmfep->cycid = CYCLIC_NONE; } - if (dmfep->ksp_mii != NULL) - kstat_delete(dmfep->ksp_mii); if (dmfep->ksp_drv != NULL) kstat_delete(dmfep->ksp_drv); if (dmfep->progress & PROGRESS_HWINT) { @@ -2772,7 +2794,6 @@ dmfe_unattach(dmfe_t *dmfep) if (dmfep->progress & PROGRESS_NDD) dmfe_nd_cleanup(dmfep); - gld_mac_free(DMFE_MACINFO(dmfep)); kmem_free(dmfep, sizeof (*dmfep)); } @@ -2812,44 +2833,12 @@ struct ks_index { char *name; }; -static const struct ks_index ks_mii_names[] = { - { KS_MII_XCVR_ADDR, "xcvr_addr" }, - { KS_MII_XCVR_ID, "xcvr_id" }, - { KS_MII_XCVR_INUSE, "xcvr_inuse" }, - - { KS_MII_LINK_UP, "link_up" }, - { KS_MII_LINK_DUPLEX, "link_duplex" }, - - { KS_MII_CAP_100FDX, "cap_100fdx" }, - { KS_MII_CAP_100HDX, "cap_100hdx" }, - { KS_MII_CAP_10FDX, "cap_10fdx" }, - { KS_MII_CAP_10HDX, "cap_10hdx" }, - { KS_MII_CAP_REMFAULT, "cap_rem_fault" }, - { KS_MII_CAP_AUTONEG, "cap_autoneg" }, - - { KS_MII_ADV_CAP_100FDX, "adv_cap_100fdx" }, - { KS_MII_ADV_CAP_100HDX, "adv_cap_100hdx" }, - { KS_MII_ADV_CAP_10FDX, "adv_cap_10fdx" }, - { KS_MII_ADV_CAP_10HDX, "adv_cap_10hdx" }, - { KS_MII_ADV_CAP_REMFAULT, "adv_rem_fault" }, - { KS_MII_ADV_CAP_AUTONEG, "adv_cap_autoneg" }, - - { KS_MII_LP_CAP_100FDX, "lp_cap_100fdx" }, - { KS_MII_LP_CAP_100HDX, "lp_cap_100hdx" }, - { KS_MII_LP_CAP_10FDX, "lp_cap_10fdx" }, - { KS_MII_LP_CAP_10HDX, "lp_cap_10hdx" }, - { KS_MII_LP_CAP_REMFAULT, "lp_cap_rem_fault" }, - { KS_MII_LP_CAP_AUTONEG, "lp_cap_autoneg" }, - - { -1, NULL } -}; - static const struct ks_index ks_drv_names[] = { + { KS_INTERRUPT, "intr" }, { KS_CYCLIC_RUN, "cyclic_run" }, { KS_TICK_LINK_STATE, "link_state_change" }, { KS_TICK_LINK_POLL, "link_state_poll" }, - { KS_LINK_INTERRUPT, "link_state_interrupt" }, { KS_TX_STALL, "tx_stall_detect" }, { KS_CHIP_ERROR, "chip_error_interrupt" }, @@ -2878,21 +2867,7 @@ dmfe_init_kstats(dmfe_t *dmfep, int instance) kstat_named_t *knp; const struct ks_index *ksip; - /* Create and initialise standard "mii" kstats */ - ksp = kstat_create(DRIVER_NAME, instance, "mii", "net", - KSTAT_TYPE_NAMED, KS_MII_COUNT, KSTAT_FLAG_PERSISTENT); - if (ksp != NULL) { - for (knp = ksp->ks_data, ksip = ks_mii_names; - ksip->name != NULL; ++ksip) { - kstat_named_init(&knp[ksip->index], ksip->name, - KSTAT_DATA_UINT32); - } - dmfep->ksp_mii = ksp; - dmfep->knp_mii = knp; - kstat_install(ksp); - } else { - dmfe_error(dmfep, "kstat_create() for mii failed"); - } + /* no need to create MII stats, the mac module already does it */ /* Create and initialise driver-defined kstats */ ksp = kstat_create(DRIVER_NAME, instance, "dmfe_events", "net", @@ -2914,19 +2889,17 @@ dmfe_init_kstats(dmfe_t *dmfep, int instance) static int dmfe_resume(dev_info_t *devinfo) { - gld_mac_info_t *macinfo; /* GLD structure */ dmfe_t *dmfep; /* Our private data */ chip_id_t chipid; - macinfo = (gld_mac_info_t *)ddi_get_driver_private(devinfo); - if (macinfo == NULL) + dmfep = ddi_get_driver_private(devinfo); + if (dmfep == NULL) return (DDI_FAILURE); /* * Refuse to resume if the data structures aren't consistent */ - dmfep = DMFE_STATE(macinfo); - if (dmfep->devinfo != devinfo || dmfep->macinfo != macinfo) + if (dmfep->devinfo != devinfo) return (DDI_FAILURE); /* @@ -2942,12 +2915,12 @@ dmfe_resume(dev_info_t *devinfo) return (DDI_FAILURE); /* - * All OK, reinitialise h/w & kick off GLD scheduling + * All OK, reinitialise h/w & kick off MAC scheduling */ mutex_enter(dmfep->oplock); dmfe_restart(dmfep); mutex_exit(dmfep->oplock); - gld_sched(macinfo); + mac_tx_update(dmfep->mh); return (DDI_SUCCESS); } @@ -2959,7 +2932,7 @@ dmfe_resume(dev_info_t *devinfo) static int dmfe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) { - gld_mac_info_t *macinfo; /* GLD structure */ + mac_register_t *macp; cyc_handler_t cychand; cyc_time_t cyctime; dmfe_t *dmfep; /* Our private data */ @@ -2969,9 +2942,6 @@ dmfe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) instance = ddi_get_instance(devinfo); - DMFE_GTRACE(("dmfe_attach($%p, %d) instance %d", - (void *)devinfo, cmd, instance)); - switch (cmd) { default: return (DDI_FAILURE); @@ -2983,21 +2953,10 @@ dmfe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) break; } - /* - * Allocate GLD macinfo and DMFE private structures, and - * cross-link them so that given either one of these or - * the devinfo the others can be derived. - */ - macinfo = gld_mac_alloc(devinfo); - ddi_set_driver_private(devinfo, (caddr_t)macinfo); - if (macinfo == NULL) - return (DDI_FAILURE); - dmfep = kmem_zalloc(sizeof (*dmfep), KM_SLEEP); - dmfep->dmfe_guard = DMFE_GUARD; + ddi_set_driver_private(devinfo, dmfep); dmfep->devinfo = devinfo; - dmfep->macinfo = macinfo; - macinfo->gldm_private = (caddr_t)dmfep; + dmfep->dmfe_guard = DMFE_GUARD; /* * Initialize more fields in DMFE private data @@ -3095,92 +3054,58 @@ dmfe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) * Reset & initialise the chip and the ring buffers * Initialise the (internal) PHY */ - (void) dmfe_gld_reset(macinfo); - dmfep->link_state = LINK_UNKNOWN; + mutex_enter(dmfep->oplock); + mutex_enter(dmfep->rxlock); + mutex_enter(dmfep->txlock); + + dmfe_reset(dmfep); + + /* + * Prepare the setup packet + */ + bzero(dmfep->tx_desc.setup_va, SETUPBUF_SIZE); + bzero(dmfep->mcast_refs, MCASTBUF_SIZE); + dmfep->addr_set = B_FALSE; + dmfep->opmode &= ~(PROMISC_MODE | PASS_MULTICAST); + dmfep->mac_state = DMFE_MAC_RESET; + + mutex_exit(dmfep->txlock); + mutex_exit(dmfep->rxlock); + mutex_exit(dmfep->oplock); + + dmfep->link_state = LINK_STATE_UNKNOWN; dmfep->link_up_msg = dmfep->link_down_msg = " (initialised)"; if (dmfe_init_phy(dmfep) != B_TRUE) goto attach_fail; dmfep->update_phy = B_TRUE; /* + * Send a reasonable setup frame. This configures our starting + * address and the broadcast address. + */ + dmfe_m_unicst(dmfep, dmfep->curr_addr); + + /* * Initialize pointers to device specific functions which * will be used by the generic layer. */ - macinfo->gldm_reset = dmfe_gld_reset; - macinfo->gldm_start = dmfe_gld_start; - macinfo->gldm_stop = dmfe_gld_stop; - macinfo->gldm_set_mac_addr = dmfe_gld_set_mac_addr; - macinfo->gldm_set_multicast = dmfe_gld_set_multicast; - macinfo->gldm_set_promiscuous = dmfe_gld_set_promiscuous; - macinfo->gldm_ioctl = dmfe_gld_ioctl; - macinfo->gldm_get_stats = dmfe_gld_get_stats; - macinfo->gldm_intr = NULL; - macinfo->gldm_send = dmfe_gld_send; -#if defined(VLAN_VID_NONE) - /* - * This assignment wouldn't be safe if running a new DMFE binary - * against an old GLD, because <gldm_send_tagged> extends the - * macinfo structure. So we need a runtime test as well as the - * compile-time one if we want full compatibility ... - */ - if (gld_recv_tagged != NULL) - macinfo->gldm_send_tagged = dmfe_gld_send_tagged; -#endif /* defined(VLAN_VID_NONE) */ - - /* - * Initialize board characteristics needed by the generic layer. - */ - macinfo->gldm_ident = dmfe_ident; - macinfo->gldm_type = DL_ETHER; - macinfo->gldm_minpkt = 0; /* no padding required */ - macinfo->gldm_maxpkt = ETHERMTU; - macinfo->gldm_addrlen = ETHERADDRL; - macinfo->gldm_saplen = -2; - macinfo->gldm_broadcast_addr = dmfe_broadcast_addr; - macinfo->gldm_vendor_addr = dmfep->vendor_addr; - macinfo->gldm_ppa = instance; - macinfo->gldm_devinfo = devinfo; - macinfo->gldm_cookie = dmfep->iblk; -#if defined(GLD_CAP_LINKSTATE) - /* - * This is safe even when running a new DMFE binary against an - * old GLD, because <gldm_capabilities> replaces a reserved - * field, rather than extending the macinfo structure - */ - macinfo->gldm_capabilities = GLD_CAP_LINKSTATE; -#endif /* defined(GLD_CAP_LINKSTATE) */ - - /* - * Workaround for booting from NET1 on early versions of Solaris, - * enabled by patching the global variable (dmfe_net1_boot_support) - * to non-zero. - * - * Up to Solaris 8, strplumb() assumed that PPA == minor number, - * which is not (and never has been) true for any GLD-based driver. - * In later versions, strplumb() and GLD have been made to cooperate - * so this isn't necessary; specifically, strplumb() has been changed - * to assume PPA == instance (rather than minor number), which *is* - * true for GLD v2 drivers, and GLD also specifically tells it the - * PPA for legacy (v0) drivers. - * - * The workaround creates an internal minor node with a minor number - * equal to the PPA; this node shouldn't ever appear under /devices - * in userland, but can be found internally when setting up the root - * (NFS) filesystem. - */ - if (dmfe_net1_boot_support) { - extern int ddi_create_internal_pathname(dev_info_t *dip, - char *name, int spec_type, minor_t minor_num); - - (void) ddi_create_internal_pathname(devinfo, DRIVER_NAME, - S_IFCHR, macinfo->gldm_ppa); - } + if ((macp = mac_alloc(MAC_VERSION)) == NULL) + goto attach_fail; + macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; + macp->m_driver = dmfep; + macp->m_dip = devinfo; + macp->m_src_addr = dmfep->curr_addr; + macp->m_callbacks = &dmfe_m_callbacks; + macp->m_min_sdu = 0; + macp->m_max_sdu = ETHERMTU; /* - * Finally, we're ready to register ourselves with the GLD + * Finally, we're ready to register ourselves with the MAC layer * interface; if this succeeds, we're all ready to start() */ - if (gld_register(devinfo, DRIVER_NAME, macinfo) != DDI_SUCCESS) + err = mac_register(macp, &dmfep->mh); + mac_free(macp); + if (err != 0) goto attach_fail; ASSERT(dmfep->dmfe_guard == DMFE_GUARD); @@ -3228,17 +3153,9 @@ dmfe_suspend(dmfe_t *dmfep) static int dmfe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) { - gld_mac_info_t *macinfo; /* GLD structure */ dmfe_t *dmfep; - DMFE_GTRACE(("dmfe_detach($%p, %d)", (void *)devinfo, cmd)); - - /* - * Get the GLD (macinfo) data from the devinfo and - * derive the driver's own state structure from that - */ - macinfo = (gld_mac_info_t *)ddi_get_driver_private(devinfo); - dmfep = DMFE_STATE(macinfo); + dmfep = ddi_get_driver_private(devinfo); switch (cmd) { default: @@ -3252,12 +3169,12 @@ dmfe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) } /* - * Unregister from the GLD subsystem. This can fail, in + * Unregister from the MAC subsystem. This can fail, in * particular if there are DLPI style-2 streams still open - * in which case we just return failure without shutting * down chip operations. */ - if (gld_unregister(macinfo) != DDI_SUCCESS) + if (mac_unregister(dmfep->mh) != DDI_SUCCESS) return (DDI_FAILURE); /* @@ -3272,76 +3189,8 @@ dmfe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) * ========== Module Loading Data & Entry Points ========== */ -static struct module_info dmfe_module_info = { - DMFEIDNUM, - DRIVER_NAME, - 0, - INFPSZ, - DMFEHIWAT, - DMFELOWAT -}; - -static struct qinit dmfe_r_qinit = { /* read queues */ - NULL, - gld_rsrv, - gld_open, - gld_close, - NULL, - &dmfe_module_info, - NULL -}; - -static struct qinit dmfe_w_qinit = { /* write queues */ - gld_wput, - gld_wsrv, - NULL, - NULL, - NULL, - &dmfe_module_info, - NULL -}; - -static struct streamtab dmfe_streamtab = { - &dmfe_r_qinit, - &dmfe_w_qinit, - NULL, - NULL -}; - -static struct cb_ops dmfe_cb_ops = { - nulldev, /* cb_open */ - nulldev, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - nodev, /* cb_read */ - nodev, /* cb_write */ - nodev, /* cb_ioctl */ - nodev, /* cb_devmap */ - nodev, /* cb_mmap */ - nodev, /* cb_segmap */ - nochpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - &dmfe_streamtab, /* cb_stream */ - D_MP, /* cb_flag */ - CB_REV, /* cb_rev */ - nodev, /* cb_aread */ - nodev /* cb_awrite */ -}; - -static struct dev_ops dmfe_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - gld_getinfo, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - dmfe_attach, /* devo_attach */ - dmfe_detach, /* devo_detach */ - nodev, /* devo_reset */ - &dmfe_cb_ops, /* devo_cb_ops */ - (struct bus_ops *)NULL, /* devo_bus_ops */ - NULL /* devo_power */ -}; +DDI_DEFINE_STREAM_OPS(dmfe_dev_ops, nulldev, nulldev, dmfe_attach, dmfe_detach, + nodev, NULL, D_MP, NULL); static struct modldrv dmfe_modldrv = { &mod_driverops, /* Type of module. This one is a driver */ @@ -3356,8 +3205,6 @@ static struct modlinkage modlinkage = { int _info(struct modinfo *modinfop) { - DMFE_GTRACE(("_info called")); - return (mod_info(&modlinkage, modinfop)); } @@ -3369,8 +3216,6 @@ _init(void) int i; int status; - DMFE_GTRACE(("_init called")); - /* Calculate global timing parameters */ tmp100 = (dmfe_tx100_stall_us+dmfe_tick_us-1)/dmfe_tick_us; tmp10 = (dmfe_tx10_stall_us+dmfe_tick_us-1)/dmfe_tick_us; @@ -3406,8 +3251,9 @@ _init(void) factotum_fast_tix = 1+(factotum_tix/5); factotum_start_tix = 1+(factotum_tix*2); + mac_init_ops(&dmfe_dev_ops, "dmfe"); status = mod_install(&modlinkage); - if (status == 0) + if (status == DDI_SUCCESS) dmfe_log_init(); return (status); @@ -3418,11 +3264,11 @@ _fini(void) { int status; - DMFE_GTRACE(("_fini called")); - status = mod_remove(&modlinkage); - if (status == 0) + if (status == DDI_SUCCESS) { + mac_fini_ops(&dmfe_dev_ops); dmfe_log_fini(); + } return (status); } diff --git a/usr/src/uts/sun4u/io/dmfe/dmfe_mii.c b/usr/src/uts/sun4u/io/dmfe/dmfe_mii.c index 22826921c9..1358453f28 100644 --- a/usr/src/uts/sun4u/io/dmfe/dmfe_mii.c +++ b/usr/src/uts/sun4u/io/dmfe/dmfe_mii.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -311,13 +310,6 @@ dmfe_find_phy(dmfe_t *dmfep) DMFE_DEBUG(("PHY at address %d, id 0x%x", mii_addr, dmfep->phy_id)); - /* - * DM9102A has an integrated MII interface, therefore we set - * the transceiver address kstat (KS_MII_XCVR_ADDR) to -1 - */ - MII_KS_SET(dmfep, KS_MII_XCVR_ADDR, dmfep->phy_addr); - MII_KS_SET(dmfep, KS_MII_XCVR_ID, dmfep->phy_id); - switch (PHY_MANUFACTURER(dmfep->phy_id)) { case OUI_DAVICOM: return (B_TRUE); @@ -527,7 +519,7 @@ dmfe_check_link(dmfe_t *dmfep) { if (dmfe_check_bmsr(dmfep)) return (B_TRUE); - return (dmfep->link_state == LINK_UNKNOWN); + return (dmfep->link_state == LINK_STATE_UNKNOWN); } @@ -543,7 +535,6 @@ dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex) const char *duplex_msg; const char *link_msg; boolean_t report; - int phy_inuse; int ks_id; ASSERT(mutex_owned(dmfep->milock)); @@ -551,7 +542,7 @@ dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex) ASSERT(newstate != dmfep->link_state); switch (newstate) { - case LINK_UP: + case LINK_STATE_UP: dmfep->param_linkup = 1; state_msg = "up"; link_msg = dmfep->link_up_msg; @@ -569,37 +560,32 @@ dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex) switch (speed) { case 100: - dmfep->op_stats_media = GLDM_100BTX; dmfep->op_stats_speed = 100000000; dmfep->param_speed = speed; - phy_inuse = XCVR_TYPE_100BASE_X; + dmfep->phy_inuse = XCVR_100X; speed_msg = " 100 Mbps"; break; case 10: - dmfep->op_stats_media = GLDM_10BT; dmfep->op_stats_speed = 10000000; dmfep->param_speed = speed; - phy_inuse = XCVR_TYPE_10BASE_T; + dmfep->phy_inuse = XCVR_10; speed_msg = " 10 Mbps"; break; default: - dmfep->op_stats_media = GLDM_TP; dmfep->op_stats_speed = 0; - phy_inuse = XCVR_TYPE_UNDEFINED; + dmfep->phy_inuse = XCVR_UNDEFINED; speed_msg = ""; break; } - MII_KS_SET(dmfep, KS_MII_XCVR_INUSE, phy_inuse); - switch (duplex) { - case GLD_DUPLEX_FULL: + case LINK_DUPLEX_FULL: duplex_msg = " Full-Duplex"; break; - case GLD_DUPLEX_HALF: + case LINK_DUPLEX_HALF: duplex_msg = " Half-Duplex"; break; @@ -617,7 +603,7 @@ dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex) * just log it. */ report = link_msg[0] == '\0'; - if (newstate == LINK_UP) + if (newstate == LINK_STATE_UP) ks_id = report ? KS_LINK_UP_CNT : KS_LINK_CYCLE_UP_CNT; else ks_id = report ? KS_LINK_DROP_CNT : KS_LINK_CYCLE_DOWN_CNT; @@ -646,37 +632,33 @@ dmfe_link_change(dmfe_t *dmfep, link_state_t newstate) ASSERT(newstate != dmfep->link_state); switch (newstate) { - case LINK_UP: - MII_KS_SET(dmfep, KS_MII_LINK_UP, 1); + case LINK_STATE_UP: gpsr = dmfe_chip_get32(dmfep, PHY_STATUS_REG); speed = gpsr & GPS_LINK_100 ? 100 : 10; - duplex = - (gpsr & GPS_FULL_DUPLEX) ? GLD_DUPLEX_FULL: GLD_DUPLEX_HALF; + duplex = (gpsr & GPS_FULL_DUPLEX) ? + LINK_DUPLEX_FULL: LINK_DUPLEX_HALF; report = B_TRUE; break; default: speed = 0; - duplex = GLD_DUPLEX_UNKNOWN; - MII_KS_SET(dmfep, KS_MII_LINK_UP, 0); + duplex = LINK_DUPLEX_UNKNOWN; switch (dmfep->link_state) { - case LINK_DOWN: /* DOWN->UNKNOWN */ + case LINK_STATE_DOWN: /* DOWN->UNKNOWN */ report = dmfep->link_down_msg[0] != '\0'; break; - case LINK_UNKNOWN: /* UNKNOWN->DOWN */ + case LINK_STATE_UNKNOWN: /* UNKNOWN->DOWN */ report = B_FALSE; break; - case LINK_UP: /* UP->DOWN/UNKNOWN */ + case LINK_STATE_UP: /* UP->DOWN/UNKNOWN */ report = B_TRUE; break; } break; } - MII_KS_SET(dmfep, KS_MII_LINK_DUPLEX, duplex); - /* * Update status & report new link state if required ... */ @@ -739,28 +721,11 @@ dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) dmfep->param_bmsr_remfault = 1; dmfep->param_bmsr_autoneg = BIS(bmsr, MII_STATUS_CANAUTONEG); - MII_KS_SET(dmfep, KS_MII_CAP_100FDX, dmfep->param_bmsr_100fdx); - MII_KS_SET(dmfep, KS_MII_CAP_100HDX, dmfep->param_bmsr_100hdx); - MII_KS_SET(dmfep, KS_MII_CAP_10FDX, dmfep->param_bmsr_10fdx); - MII_KS_SET(dmfep, KS_MII_CAP_10HDX, dmfep->param_bmsr_10hdx); - MII_KS_SET(dmfep, KS_MII_CAP_REMFAULT, dmfep->param_bmsr_remfault); - MII_KS_SET(dmfep, KS_MII_CAP_AUTONEG, dmfep->param_bmsr_autoneg); - /* * Advertised abilities of DM9102A */ anar = dmfep->phy_anar_r; - MII_KS_SET(dmfep, KS_MII_ADV_CAP_AUTONEG, dmfep->param_autoneg); - MII_KS_SET(dmfep, KS_MII_ADV_CAP_100FDX, - BIS(anar, MII_ABILITY_100BASE_TX_FD)); - MII_KS_SET(dmfep, KS_MII_ADV_CAP_100HDX, - BIS(anar, MII_ABILITY_100BASE_TX)); - MII_KS_SET(dmfep, KS_MII_ADV_CAP_10FDX, - BIS(anar, MII_ABILITY_10BASE_T_FD)); - MII_KS_SET(dmfep, KS_MII_ADV_CAP_10HDX, - BIS(anar, MII_ABILITY_10BASE_T)); - MII_KS_SET(dmfep, KS_MII_ADV_CAP_REMFAULT, - BIS(anar, MII_AN_ADVERT_REMFAULT)); + dmfep->param_anar_remfault = BIS(anar, MII_AN_ADVERT_REMFAULT); /* * Link Partners advertised abilities @@ -780,17 +745,11 @@ dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) dmfep->param_lp_10hdx = BIS(anlpar, MII_ABILITY_10BASE_T); dmfep->param_lp_remfault = BIS(anlpar, MII_AN_ADVERT_REMFAULT); - MII_KS_SET(dmfep, KS_MII_LP_CAP_100FDX, dmfep->param_lp_100fdx); - MII_KS_SET(dmfep, KS_MII_LP_CAP_100HDX, dmfep->param_lp_100hdx); - MII_KS_SET(dmfep, KS_MII_LP_CAP_10FDX, dmfep->param_lp_10fdx); - MII_KS_SET(dmfep, KS_MII_LP_CAP_10HDX, dmfep->param_lp_10hdx); - MII_KS_SET(dmfep, KS_MII_LP_CAP_AUTONEG, dmfep->param_lp_autoneg); - MII_KS_SET(dmfep, KS_MII_LP_CAP_REMFAULT, dmfep->param_lp_remfault); - /* * Derive new state & time since last change */ - newstate = (dmfep->phy_bmsr & MII_STATUS_LINKUP) ? LINK_UP : LINK_DOWN; + newstate = (dmfep->phy_bmsr & MII_STATUS_LINKUP) ? + LINK_STATE_UP : LINK_STATE_DOWN; time -= dmfep->phy_bmsr_lbolt; /* @@ -798,17 +757,18 @@ dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) * for all sorts of special cases before we decide :( */ if (dmfep->phy_bmsr == MII_STATUS_INVAL) - newstate = LINK_DOWN; - else if (dmfep->link_state == LINK_UP && newstate == LINK_DOWN) + newstate = LINK_STATE_DOWN; + else if ((dmfep->link_state == LINK_STATE_UP) && + (newstate == LINK_STATE_DOWN)) /*EMPTY*/; else if (time < drv_usectohz(dmfe_mii_settle_time)) - newstate = LINK_UNKNOWN; + newstate = LINK_STATE_UNKNOWN; else if (dmfep->phy_bmsr & MII_STATUS_ANDONE) /*EMPTY*/; else if (dmfep->phy_control & MII_CONTROL_ANE) - newstate = LINK_UNKNOWN; + newstate = LINK_STATE_UNKNOWN; - if (newstate == LINK_UP) { + if (newstate == LINK_STATE_UP) { /* * Link apparently UP - but get the PHY status register * (GPSR) and make sure it also shows a consistent value. @@ -824,7 +784,7 @@ dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) case GPS_LINK_STATUS|GPS_UTP_SIG: break; default: - newstate = LINK_UNKNOWN; + newstate = LINK_STATE_UNKNOWN; break; } @@ -833,7 +793,7 @@ dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) case GPS_LINK_10: break; default: - newstate = LINK_UNKNOWN; + newstate = LINK_STATE_UNKNOWN; break; } } @@ -889,7 +849,7 @@ dmfe_recheck_link(dmfe_t *dmfep, boolean_t ioctl) ASSERT(dmfep->link_state == newstate); if (again) continue; - if (newstate == LINK_UP) { + if (newstate == LINK_STATE_UP) { dmfep->update_phy = B_TRUE; break; } diff --git a/usr/src/uts/sun4u/sys/dmfe_impl.h b/usr/src/uts/sun4u/sys/dmfe_impl.h index ad3cc29045..2eac4c7633 100644 --- a/usr/src/uts/sun4u/sys/dmfe_impl.h +++ b/usr/src/uts/sun4u/sys/dmfe_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +41,6 @@ extern "C" { #include <sys/modctl.h> #include <sys/kstat.h> #include <sys/ethernet.h> -#include <sys/dlpi.h> #include <sys/devops.h> #include <sys/debug.h> #include <sys/cyclic.h> @@ -52,46 +50,18 @@ extern "C" { #include <inet/nd.h> #include <inet/mi.h> +#include <sys/vlan.h> + #include <sys/dditypes.h> #include <sys/ddi.h> #include <sys/sunddi.h> #include <sys/miiregs.h> #include <sys/dmfe.h> +#include <sys/mac.h> +#include <sys/mac_ether.h> -/* - * The following function *may* be defined in <sys/gld.h>. - * If so, the full definitions there will supplement these minimal - * versions; otherwise, these will suffice to allow the code to - * compile and then we'll test for them at runtime. - */ -extern void gld_linkstate(); -extern void gld_recv_tagged(); -#pragma weak gld_linkstate -#pragma weak gld_recv_tagged - -#include <sys/gld.h> - -/* - * Define these symbols if they're not already in <sys/gld.h> - */ -#ifndef GLD_LINKSTATE_UP -#define GLD_LINKSTATE_UP 1 -#define GLD_LINKSTATE_UNKNOWN 0 -#define GLD_LINKSTATE_DOWN -1 -#endif /* GLD_LINKSTATE_UP */ - -/* - * This driver can be compiled with VLAN support (if VLAN_VID_NONE - * is defined in <sys/gld.h>). If not, the definitions is the 'else' - * clause will allow the code to compile anyway. - */ -#ifdef VLAN_VID_NONE -#define DMFE_MAX_PKT_SIZE (VTAG_SIZE + ETHERMAX + ETHERFCSL) -#else -#define DMFE_MAX_PKT_SIZE (ETHERMAX + ETHERFCSL) -#define VLAN_VTAG_NONE 0 /* implies "untagged" */ -#endif /* VLAN_VID_NONE */ +#define DMFE_MAX_PKT_SIZE (VLAN_TAGSZ + ETHERMAX + ETHERFCSL) #define DRIVER_NAME "dmfe" @@ -166,6 +136,7 @@ enum { PARAM_ADV_100HDX_CAP, PARAM_ADV_10FDX_CAP, PARAM_ADV_10HDX_CAP, + PARAM_ADV_REMFAULT, PARAM_BMSR_AUTONEG_CAP, PARAM_BMSR_100T4_CAP, @@ -187,47 +158,6 @@ enum { }; /* - * Indexes into standard "mii" kstats, divided into: - * - * MII transceiver info - * MII link state - * MII device capabilities - * MII advertised capabilities - * MII link partner capabilities - */ -enum { - KS_MII_XCVR_ADDR, - KS_MII_XCVR_ID, - KS_MII_XCVR_INUSE, - - KS_MII_LINK_UP, - KS_MII_LINK_DUPLEX, - - KS_MII_CAP_100FDX, - KS_MII_CAP_100HDX, - KS_MII_CAP_10FDX, - KS_MII_CAP_10HDX, - KS_MII_CAP_REMFAULT, - KS_MII_CAP_AUTONEG, - - KS_MII_ADV_CAP_100FDX, - KS_MII_ADV_CAP_100HDX, - KS_MII_ADV_CAP_10FDX, - KS_MII_ADV_CAP_10HDX, - KS_MII_ADV_CAP_REMFAULT, - KS_MII_ADV_CAP_AUTONEG, - - KS_MII_LP_CAP_100FDX, - KS_MII_LP_CAP_100HDX, - KS_MII_LP_CAP_10FDX, - KS_MII_LP_CAP_10HDX, - KS_MII_LP_CAP_REMFAULT, - KS_MII_LP_CAP_AUTONEG, - - KS_MII_COUNT -}; - -/* * Indexes into the driver-specific kstats, divided into: * * cyclic activity @@ -241,7 +171,7 @@ enum { KS_TICK_LINK_STATE, KS_TICK_LINK_POLL, - KS_LINK_INTERRUPT, + KS_INTERRUPT, KS_TX_STALL, KS_CHIP_ERROR, @@ -277,29 +207,16 @@ enum chip_state { }; /* - * Required state according to GLD + * Required state according to MAC */ -enum gld_state { - GLD_UNKNOWN, - GLD_RESET, - GLD_STOPPED, - GLD_STARTED +enum mac_state { + DMFE_MAC_UNKNOWN, + DMFE_MAC_RESET, + DMFE_MAC_STOPPED, + DMFE_MAC_STARTED }; /* - * Current state of the physical link - * - * DOWN No link established. - * UNKNOWN Initial state, also indicates "autonegotiating". - * UP Link established, commuication should be possible. - */ -typedef enum { - LINK_DOWN = -1, - LINK_UNKNOWN = 0, - LINK_UP -} link_state_t; - -/* * (Internal) return values from ioctl subroutines */ enum ioc_reply { @@ -319,7 +236,7 @@ typedef struct { * These fields are set by attach() and unchanged thereafter ... */ dev_info_t *devinfo; /* device instance */ - gld_mac_info_t *macinfo; /* GLD instance data */ + mac_handle_t mh; /* MAC instance data */ ddi_acc_handle_t io_handle; /* DDI I/O handle */ caddr_t io_reg; /* mapped registers */ @@ -368,8 +285,8 @@ typedef struct { * milock >>> oplock >>> rxlock >>> txlock. * * *None* of these locks may be held across calls out to the - * GLD routines gld_recv() or gld_sched(); GLD's <maclock> must - * be regarded as an *outermost* lock in all cases, as it will + * MAC routines mac_rx() or mac_tx_notify(); MAC locks must + * be regarded as *outermost* locks in all cases, as they will * already be held before calling the ioctl() or get_stats() * entry points - which then have to acquire multiple locks, in * the order described here. @@ -382,8 +299,6 @@ typedef struct { /* * DMFE Extended kstats, protected by <oplock> */ - kstat_t *ksp_mii; - kstat_named_t *knp_mii; kstat_t *ksp_drv; kstat_named_t *knp_drv; @@ -391,30 +306,36 @@ typedef struct { * GLD statistics; the prefix tells which lock each is protected by. */ uint64_t op_stats_speed; - uint32_t op_stats_duplex; - uint32_t op_stats_media; - uint32_t op_stats_intr; - - uint32_t rx_stats_errrcv; - uint32_t rx_stats_overflow; - uint32_t rx_stats_short; - uint32_t rx_stats_crc; - uint32_t rx_stats_frame_too_long; - uint32_t rx_stats_mac_rcv_error; - uint32_t rx_stats_frame; - uint32_t rx_stats_missed; - uint32_t rx_stats_norcvbuf; - - uint32_t tx_stats_errxmt; - uint32_t tx_stats_mac_xmt_error; - uint32_t tx_stats_underflow; - uint32_t tx_stats_xmtlatecoll; - uint32_t tx_stats_nocarrier; - uint32_t tx_stats_excoll; - uint32_t tx_stats_first_coll; - uint32_t tx_stats_multi_coll; - uint32_t tx_stats_collisions; - uint32_t tx_stats_defer; + uint64_t op_stats_duplex; + + uint64_t rx_stats_ipackets; + uint64_t rx_stats_multi; + uint64_t rx_stats_bcast; + uint64_t rx_stats_ierrors; + uint64_t rx_stats_norcvbuf; + uint64_t rx_stats_rbytes; + uint64_t rx_stats_missed; + uint64_t rx_stats_align; + uint64_t rx_stats_fcs; + uint64_t rx_stats_toolong; + uint64_t rx_stats_macrcv_errors; + uint64_t rx_stats_overflow; + uint64_t rx_stats_short; + + uint64_t tx_stats_oerrors; + uint64_t tx_stats_opackets; + uint64_t tx_stats_multi; + uint64_t tx_stats_bcast; + uint64_t tx_stats_obytes; + uint64_t tx_stats_collisions; + uint64_t tx_stats_nocarrier; + uint64_t tx_stats_xmtlatecoll; + uint64_t tx_stats_excoll; + uint64_t tx_stats_macxmt_errors; + uint64_t tx_stats_defer; + uint64_t tx_stats_first_coll; + uint64_t tx_stats_multi_coll; + uint64_t tx_stats_underflow; /* * These two sets of desciptors are manipulated during @@ -427,6 +348,8 @@ typedef struct { * Miscellaneous Tx-side variables (protected by txlock) */ uint32_t tx_pending_tix; /* tix since reclaim */ + uint8_t *tx_mcast; /* bitmask: pkt is mcast */ + uint8_t *tx_bcast; /* bitmask: pkt is bcast */ /* * Miscellaneous operating variables (protected by oplock) @@ -436,7 +359,7 @@ typedef struct { uint16_t need_setup; /* send-setup pending */ uint32_t opmode; /* operating mode shadow */ uint32_t imask; /* interrupt mask shadow */ - enum gld_state gld_state; /* RESET/STOPPED/STARTED */ + enum mac_state mac_state; /* RESET/STOPPED/STARTED */ enum chip_state chip_state; /* see above */ /* @@ -449,6 +372,7 @@ typedef struct { /* * PHYceiver state data (protected by milock) */ + int phy_inuse; int phy_addr; /* should be -1! */ uint16_t phy_control; /* last value written */ uint16_t phy_anar_w; /* last value written */ @@ -510,6 +434,7 @@ typedef struct { #define param_anar_100hdx nd_params[PARAM_ADV_100HDX_CAP].ndp_val #define param_anar_10fdx nd_params[PARAM_ADV_10FDX_CAP].ndp_val #define param_anar_10hdx nd_params[PARAM_ADV_10HDX_CAP].ndp_val +#define param_anar_remfault nd_params[PARAM_ADV_REMFAULT].ndp_val #define param_bmsr_autoneg nd_params[PARAM_BMSR_AUTONEG_CAP].ndp_val #define param_bmsr_100T4 nd_params[PARAM_BMSR_100T4_CAP].ndp_val #define param_bmsr_100fdx nd_params[PARAM_BMSR_100FDX_CAP].ndp_val @@ -526,12 +451,6 @@ typedef struct { #define param_lp_remfault nd_params[PARAM_LP_REMFAULT].ndp_val /* - * Derive DMFE state from GLD's macinfo or vice versa - */ -#define DMFE_STATE(macinfo) ((dmfe_t *)((macinfo)->gldm_private)) -#define DMFE_MACINFO(dmfep) ((dmfep)->macinfo) - -/* * Sync a DMA area described by a dma_area_t */ #define DMA_SYNC(descp, flag) ((void) ddi_dma_sync((descp)->dma_hdl, \ @@ -619,7 +538,7 @@ typedef struct { /* * Debugging ... */ -#ifdef DEBUG +#if defined(DEBUG) || defined(lint) #define DMFEDEBUG 1 #else #define DMFEDEBUG 0 |