e1000g_main.c revision 35ae85e6c0b2dadbe199cf99921e7cc382be5035
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This file is provided under a CDDLv1 license. When using or
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * redistributing this file, you may do so under this license.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * In redistributing this file this license must be included
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and no other modification of this header file is permitted.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * CDDL LICENSE SUMMARY
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Copyright(c) 1999 - 2008 Intel Corporation. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * The contents of this file are subject to the terms of Version
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 1.0 of the Common Development and Distribution License (the "License").
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You should have received a copy of the License with this software.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You can obtain a copy of the License at
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * http://www.opensolaris.org/os/licensing.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * See the License for the specific language governing permissions
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * and limitations under the License.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Use is subject to license terms of the CDDLv1.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#pragma ident "%Z%%M% %I% %E% SMI"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * **********************************************************************
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Module Name: *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This file contains the interface routines for the solaris OS. *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * It has all DDI entry point routines and GLD entry point routines. *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This file also contains routines that take care of initialization *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * uninit routine and interrupt routine. *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * **********************************************************************
#pragma inline(e1000g_intr_work)
#pragma inline(e1000g_get_itr)
static int e1000g_m_start(void *);
static void e1000g_m_stop(void *);
uint_t, const void *);
uint_t, void *);
static void e1000g_link_timer(void *);
static void e1000g_local_timer(void *);
#ifdef E1000G_DEBUG
#ifdef __sparc
const void *impl_data);
#define E1000G_MAX_PRIV_PROPS \
#define E1000G_M_CALLBACK_FLAGS \
NULL,
NULL,
NULL,
#ifdef __sparc
_init(void)
int status;
return (status);
_fini(void)
int status;
if (e1000g_mblks_pending != 0) {
return (EBUSY);
if (e1000g_force_detach) {
sizeof (struct dev_info));
sizeof (private_devi_list_t));
return (status);
int instance;
switch (cmd) {
return (DDI_FAILURE);
case DDI_RESUME:
case DDI_ATTACH:
Adapter =
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
goto attach_fail;
if (e1000g_force_detach) {
sizeof (struct dev_info));
return (DDI_SUCCESS);
return (DDI_FAILURE);
int err;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
goto regs_map_fail;
goto regs_map_fail;
goto regs_map_fail;
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
if (bar64) {
#ifdef __sparc
return (DDI_SUCCESS);
#ifdef __sparc
if (iommu_pagesize != 0) {
* aligned...so all wiseman boards to have 256 byte aligned
switch (cmd) {
return (DDI_FAILURE);
case DDI_SUSPEND:
case DDI_DETACH:
return (DDI_FAILURE);
return (DDI_FAILURE);
if (e1000g_force_detach) {
if (!rx_drain)
return (DDI_FAILURE);
return (DDI_SUCCESS);
if (free_flag) {
sizeof (struct dev_info));
sizeof (private_devi_list_t));
if (free_flag) {
sizeof (struct dev_info));
sizeof (private_devi_list_t));
int result;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_SUCCESS);
int result;
goto init_fail;
goto init_fail;
result = 0;
#ifdef __sparc
if (!result) {
goto init_fail;
goto init_fail;
goto init_fail;
* Configure/Initialize hardware
goto init_fail;
goto init_fail;
goto init_fail;
return (DDI_SUCCESS);
return (DDI_FAILURE);
static boolean_t
return (link_up);
int err;
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
case LB_SET_MODE:
#ifdef E1000G_DEBUG
case E1000G_IOC_REG_PEEK:
case E1000G_IOC_REG_POKE:
case E1000G_IOC_CHIP_RESET:
switch (status) {
case IOC_INVAL:
case IOC_DONE:
case IOC_ACK:
case IOC_REPLY:
if (global) {
return (ENOTACTIVE);
if (global)
return (ENOTACTIVE);
return (ENOTACTIVE);
int result;
if (global)
packet_count = 0;
packet_count++;
if (packet_count > 0) {
static boolean_t
for (i = 0; i < TX_DRAIN_TIME; i++) {
if (done)
return (done);
static boolean_t
return (done);
return (B_FALSE);
return (B_TRUE);
return (B_FALSE);
return (B_TRUE);
static uint_t
return (DDI_INTR_CLAIMED);
return (DDI_INTR_UNCLAIMED);
static uint_t
if (icr) {
return (DDI_INTR_CLAIMED);
return (DDI_INTR_UNCLAIMED);
if (itr) {
if (link_changed) {
if (tid != 0)
static uint32_t
goto itr_done;
goto itr_done;
return (new_itr);
int slot;
if (slot == 0) {
return (EIO);
int err;
return (EINVAL);
return (ENOSPC);
return (err);
int err;
return (EINVAL);
return (err);
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
int res = 0;
goto done;
goto done;
done:
return (res);
ETHERADDRL) == 0) {
done:
return (EIO);
* address registers for its node/network/mac/individual address.
if (on)
rctl |=
return (EIO);
static boolean_t
switch (cap) {
case MAC_CAPAB_HCKSUM: {
return (B_FALSE);
case MAC_CAPAB_POLL:
case MAC_CAPAB_MULTIADDRESS: {
case MAC_CAPAB_LSO: {
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
static boolean_t
switch (pr_num) {
case MAC_PROP_EN_1000FDX_CAP:
case MAC_PROP_EN_1000HDX_CAP:
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_EN_100HDX_CAP:
case MAC_PROP_EN_10FDX_CAP:
case MAC_PROP_EN_10HDX_CAP:
case MAC_PROP_AUTONEG:
case MAC_PROP_FLOWCTRL:
return (B_TRUE);
return (B_FALSE);
int err = 0;
return (EBUSY);
switch (pr_num) {
case MAC_PROP_EN_1000FDX_CAP:
goto reset;
case MAC_PROP_EN_1000HDX_CAP:
goto reset;
case MAC_PROP_EN_100FDX_CAP:
goto reset;
case MAC_PROP_EN_100HDX_CAP:
goto reset;
case MAC_PROP_EN_10FDX_CAP:
goto reset;
case MAC_PROP_EN_10HDX_CAP:
goto reset;
case MAC_PROP_AUTONEG:
goto reset;
case MAC_PROP_FLOWCTRL:
switch (flowctrl) {
case LINK_FLOWCTRL_NONE:
case LINK_FLOWCTRL_RX:
case LINK_FLOWCTRL_TX:
case LINK_FLOWCTRL_BI:
if (err == 0) {
case MAC_PROP_ADV_1000FDX_CAP:
case MAC_PROP_ADV_1000HDX_CAP:
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_ADV_100HDX_CAP:
case MAC_PROP_ADV_10FDX_CAP:
case MAC_PROP_ADV_10HDX_CAP:
case MAC_PROP_STATUS:
case MAC_PROP_SPEED:
case MAC_PROP_DUPLEX:
case MAC_PROP_MTU:
err = 0;
if (err == 0) {
case MAC_PROP_PRIVATE:
return (err);
int err = 0;
if (pr_valsize == 0)
return (EINVAL);
switch (pr_num) {
case MAC_PROP_DUPLEX:
sizeof (link_duplex_t));
case MAC_PROP_SPEED:
case MAC_PROP_AUTONEG:
case MAC_PROP_FLOWCTRL:
case e1000_fc_none:
case e1000_fc_rx_pause:
case e1000_fc_tx_pause:
case e1000_fc_full:
case MAC_PROP_ADV_1000FDX_CAP:
case MAC_PROP_EN_1000FDX_CAP:
case MAC_PROP_ADV_1000HDX_CAP:
case MAC_PROP_EN_1000HDX_CAP:
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_ADV_100HDX_CAP:
case MAC_PROP_EN_100HDX_CAP:
case MAC_PROP_ADV_10FDX_CAP:
case MAC_PROP_EN_10FDX_CAP:
case MAC_PROP_ADV_10HDX_CAP:
case MAC_PROP_EN_10HDX_CAP:
case MAC_PROP_ADV_100T4_CAP:
case MAC_PROP_EN_100T4_CAP:
case MAC_PROP_PRIVATE:
return (err);
int err = 0;
long result;
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (err);
return (ENOTSUP);
int value;
if (is_default)
goto done;
err = 0;
goto done;
if (is_default)
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
err = 0;
goto done;
done:
if (err == 0) {
return (err);
* e1000g_get_conf - get configurations set in e1000g.conf
* file e1000g.conf.
* get each configurable property from e1000g.conf
case e1000_82540:
case e1000_82544:
case e1000_82545:
case e1000_82545_rev_3:
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
case e1000_82572:
case e1000_82573:
* file e1000g.conf.
"Not Enough %s values found in e1000g.conf"
"Too High %s value in e1000g.conf - set to %d\n",
"Too Low %s value in e1000g.conf - set to %d\n",
return (propval);
static boolean_t
return (link_changed);
if (invalid) {
if (link_changed)
* e1000g_force_speed_duplex - read forced speed/duplex out of e1000g.conf
* and also for 1000 Mbps speeds from the e1000g.conf file
int forced;
switch (forced) {
case GDIAG_10_HALF:
case GDIAG_10_FULL:
case GDIAG_100_HALF:
case GDIAG_100_FULL:
case GDIAG_1000_FULL:
* e1000g_get_max_frame_size - get jumbo frame setting from e1000g.conf
* This function reads MaxFrameSize from e1000g.conf
int max_frame;
switch (max_frame) {
#pragma inline(arm_watchdog_timer)
if (tid != 0)
if (tid != 0)
if (tid != 0)
if (tid != 0)
phy_ctrl |=
static boolean_t
return (B_FALSE);
return (B_TRUE);
static boolean_t
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
#ifdef E1000G_DEBUG
static enum ioc_reply
case E1000G_IOC_REG_PEEK:
case E1000G_IOC_REG_POKE:
return (IOC_INVAL);
return (IOC_INVAL);
return (IOC_INVAL);
return (IOC_INVAL);
case E1000G_PP_SPACE_REG:
return (IOC_INVAL);
return (IOC_INVAL);
mem_va = 0;
case E1000G_PP_SPACE_E1000G:
return (IOC_INVAL);
return (IOC_INVAL);
regaddr =
regaddr =
void *vaddr;
void *vaddr;
static enum ioc_reply
return (IOC_INVAL);
return (IOC_INVAL);
return (IOC_INVAL);
case LB_GET_INFO_SIZE:
return (IOC_INVAL);
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case LB_GET_INFO:
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
return (IOC_INVAL);
value = 0;
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case LB_GET_MODE:
return (IOC_INVAL);
case LB_SET_MODE:
size = 0;
return (IOC_INVAL);
return (IOC_INVAL);
return (IOC_INVAL);
return (IOC_REPLY);
static boolean_t
case e1000_82540:
case e1000_82545:
case e1000_82545_rev_3:
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82541:
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
case e1000_82571:
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
return (B_TRUE);
return (B_FALSE);
static boolean_t
int i, times;
return (B_TRUE);
times = 0;
return (B_TRUE);
switch (mode) {
return (B_FALSE);
case E1000G_LB_EXTERNAL_1000:
case E1000G_LB_EXTERNAL_100:
case E1000G_LB_EXTERNAL_10:
case E1000G_LB_INTERNAL_PHY:
times++;
if (!link_up) {
goto again;
return (B_TRUE);
case e1000_82540:
case e1000_82545:
case e1000_82545_rev_3:
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82573:
case e1000_80003es2lan:
case e1000_82540:
case e1000_82545:
case e1000_82545_rev_3:
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
case e1000_82572:
case e1000_82573:
case e1000_82571:
case e1000_82572:
case e1000_media_type_copper:
case e1000_media_type_fiber:
case e1000_80003es2lan:
#ifdef __sparc
static boolean_t
int err;
while (nelts--)
while (nelts--)
if (found) {
return (found);
int intr_types;
int rc;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
int flag;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
for (y = 0; y < actual; y++)
return (DDI_FAILURE);
for (x = 0; x < actual; x++) {
(void) ddi_intr_remove_handler(
for (y = 0; y < actual; y++)
return (DDI_FAILURE);
for (y = 0; y < actual; y++) {
return (DDI_FAILURE);
return (DDI_SUCCESS);
int rc;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
int rc;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
int rc;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
fma_acc_flag = 0;
fma_dma_flag = 0;
int err = 0;
switch (pr_num) {
case MAC_PROP_AUTONEG:
case MAC_PROP_FLOWCTRL:
return (EINVAL);
case MAC_PROP_ADV_1000FDX_CAP:
case MAC_PROP_EN_1000FDX_CAP:
case MAC_PROP_ADV_1000HDX_CAP:
case MAC_PROP_EN_1000HDX_CAP:
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_ADV_100HDX_CAP:
case MAC_PROP_EN_100HDX_CAP:
case MAC_PROP_ADV_10FDX_CAP:
case MAC_PROP_EN_10FDX_CAP:
case MAC_PROP_ADV_10HDX_CAP:
case MAC_PROP_EN_10HDX_CAP:
return (err);