URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [net/] [e100/] [e100_config.c] - Rev 1275
Go to most recent revision | Compare with Previous | Blame | View Log
/******************************************************************************* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: Linux NICS <linux.nics@intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /********************************************************************** * * * INTEL CORPORATION * * * * This software is supplied under the terms of the license included * * above. All use of this driver must be in accordance with the terms * * of that license. * * * * Module Name: e100_config.c * * * * Abstract: Functions for configuring the network adapter. * * * * Environment: This file is intended to be specific to the Linux * * operating system. * * * **********************************************************************/ #include "e100_config.h" static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable); static const u8 def_config[] = { CB_CFIG_BYTE_COUNT, 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01, 0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00, 0x40, 0xf2, 0x80, 0x3f, 0x05 }; /** * e100_config_init_82557 - config the 82557 adapter * @bdp: atapter's private data struct * * This routine will initialize the 82557 configure block. * All other init functions will only set values that are * different from the 82557 default. */ void e100_config_init_82557(struct e100_private *bdp) { /* initialize config block */ memcpy(bdp->config, def_config, sizeof (def_config)); bdp->config[0] = CB_CFIG_BYTE_COUNT; /* just in case */ e100_config_ifs(bdp); /* * Enable extended statistical counters (82558 and up) and TCO counters * (82559 and up) and set the statistical counters' mode in bdp * * stat. mode | TCO stat. bit (2) | Extended stat. bit (5) * ------------------------------------------------------------------ * Basic (557) | 0 | 1 * ------------------------------------------------------------------ * Extended (558) | 0 | 0 * ------------------------------------------------------------------ * TCO (559) | 1 | 1 * ------------------------------------------------------------------ * Reserved | 1 | 0 * ------------------------------------------------------------------ */ bdp->config[6] &= ~CB_CFIG_TCO_STAT; bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; bdp->stat_mode = E100_BASIC_STATS; /* Setup for MII or 503 operation. The CRS+CDT bit should only be set */ /* when operating in 503 mode. */ if (bdp->phy_addr == 32) { bdp->config[8] &= ~CB_CFIG_503_MII; bdp->config[15] |= CB_CFIG_CRS_OR_CDT; } else { bdp->config[8] |= CB_CFIG_503_MII; bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT; } e100_config_fc(bdp); e100_config_force_dplx(bdp); e100_config_promisc(bdp, false); e100_config_mulcast_enbl(bdp, false); } static void e100_config_init_82558(struct e100_private *bdp) { /* MWI enable. This should be turned on only if the adapter is a 82558/9 * and if the PCI command reg. has enabled the MWI bit. */ bdp->config[3] |= CB_CFIG_MWI_EN; bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS; if (bdp->rev_id >= D101MA_REV_ID) { /* this is 82559 and up - enable TCO counters */ bdp->config[6] |= CB_CFIG_TCO_STAT; bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; bdp->stat_mode = E100_TCO_STATS; if ((bdp->rev_id < D102_REV_ID) && (bdp->params.b_params & PRM_XSUMRX) && (bdp->pdev->device != 0x1209)) { bdp->flags |= DF_CSUM_OFFLOAD; bdp->config[9] |= 1; } } else { /* this is 82558 */ bdp->config[6] &= ~CB_CFIG_TCO_STAT; bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS; bdp->stat_mode = E100_EXTENDED_STATS; } e100_config_long_rx(bdp, true); } static void e100_config_init_82550(struct e100_private *bdp) { /* The D102 chip allows for 32 config bytes. This value is * supposed to be in Byte 0. Just add the extra bytes to * what was already setup in the block. */ bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; /* now we need to enable the extended RFD. When this is * enabled, the immediated receive data buffer starts at offset * 32 from the RFD base address, instead of at offset 16. */ bdp->config[7] |= CB_CFIG_EXTENDED_RFD; /* put the chip into D102 receive mode. This is necessary * for any parsing and offloading features. */ bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE; /* set the flag if checksum offloading was enabled */ if (bdp->params.b_params & PRM_XSUMRX) { bdp->flags |= DF_CSUM_OFFLOAD; } } /* Initialize the adapter's configure block */ void e100_config_init(struct e100_private *bdp) { e100_config_init_82557(bdp); if (bdp->flags & IS_BACHELOR) e100_config_init_82558(bdp); if (bdp->rev_id >= D102_REV_ID) e100_config_init_82550(bdp); } /** * e100_force_config - force a configure command * @bdp: atapter's private data struct * * This routine will force a configure command to the adapter. * The command will be executed in polled mode as interrupts * are _disabled_ at this time. * * Returns: * true: if the configure command was successfully issued and completed * false: otherwise */ unsigned char e100_force_config(struct e100_private *bdp) { spin_lock_bh(&(bdp->config_lock)); bdp->config[0] = CB_CFIG_BYTE_COUNT; if (bdp->rev_id >= D102_REV_ID) { /* The D102 chip allows for 32 config bytes. This value is supposed to be in Byte 0. Just add the extra bytes to what was already setup in the block. */ bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; } spin_unlock_bh(&(bdp->config_lock)); // although we call config outside the lock, there is no // race condition because config byte count has maximum value return e100_config(bdp); } /** * e100_config - issue a configure command * @bdp: atapter's private data struct * * This routine will issue a configure command to the 82557. * This command will be executed in polled mode as interrupts * are _disabled_ at this time. * * Returns: * true: if the configure command was successfully issued and completed * false: otherwise */ unsigned char e100_config(struct e100_private *bdp) { cb_header_t *pntcb_hdr; unsigned char res = true; nxmit_cb_entry_t *cmd; if (bdp->config[0] == 0) { goto exit; } if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { res = false; goto exit; } pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE); spin_lock_bh(&bdp->config_lock); if (bdp->config[0] < CB_CFIG_MIN_PARAMS) { bdp->config[0] = CB_CFIG_MIN_PARAMS; } /* Copy the device's config block to the device's memory */ memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config, bdp->config[0]); /* reset number of bytes to config next time */ bdp->config[0] = 0; spin_unlock_bh(&bdp->config_lock); res = e100_exec_non_cu_cmd(bdp, cmd); exit: if (netif_running(bdp->device)) netif_wake_queue(bdp->device); return res; } /** * e100_config_fc - config flow-control state * @bdp: adapter's private data struct * * This routine will enable or disable flow control support in the adapter's * config block. Flow control will be enable only if requested using the command * line option, and if the link is flow-contorl capable (both us and the link * partner). But, if link partner is capable of autoneg, but not capable of * flow control, received PAUSE frames are still honored. */ void e100_config_fc(struct e100_private *bdp) { unsigned char enable = false; /* 82557 doesn't support fc. Don't touch this option */ if (!(bdp->flags & IS_BACHELOR)) return; /* Enable fc if requested and if the link supports it */ if ((bdp->params.b_params & PRM_FC) && (bdp->flags & (DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) { enable = true; } spin_lock_bh(&(bdp->config_lock)); if (enable) { if (bdp->flags & DF_LINK_FC_TX_ONLY) { /* If link partner is capable of autoneg, but */ /* not capable of flow control, Received PAUSE */ /* frames are still honored, i.e., */ /* transmitted frames would be paused by */ /* incoming PAUSE frames */ bdp->config[16] = DFLT_NO_FC_DELAY_LSB; bdp->config[17] = DFLT_NO_FC_DELAY_MSB; bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART); bdp->config[19] |= CB_CFIG_FC_REJECT; bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; } else { bdp->config[16] = DFLT_FC_DELAY_LSB; bdp->config[17] = DFLT_FC_DELAY_MSB; bdp->config[19] |= CB_CFIG_FC_OPTS; bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; } } else { bdp->config[16] = DFLT_NO_FC_DELAY_LSB; bdp->config[17] = DFLT_NO_FC_DELAY_MSB; bdp->config[19] &= ~CB_CFIG_FC_OPTS; bdp->config[19] |= CB_CFIG_TX_FC_DIS; } E100_CONFIG(bdp, 19); spin_unlock_bh(&(bdp->config_lock)); return; } /** * e100_config_promisc - configure promiscuous mode * @bdp: atapter's private data struct * @enable: should we enable this option or not * * This routine will enable or disable promiscuous mode * in the adapter's config block. */ void e100_config_promisc(struct e100_private *bdp, unsigned char enable) { spin_lock_bh(&(bdp->config_lock)); /* if in promiscuous mode, save bad frames */ if (enable) { if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) { bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES; E100_CONFIG(bdp, 6); } if (bdp->config[7] & (u8) BIT_0) { bdp->config[7] &= (u8) (~BIT_0); E100_CONFIG(bdp, 7); } if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) { bdp->config[15] |= CB_CFIG_PROMISCUOUS; E100_CONFIG(bdp, 15); } } else { /* not in promiscuous mode */ if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) { bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES; E100_CONFIG(bdp, 6); } if (!(bdp->config[7] & (u8) BIT_0)) { bdp->config[7] |= (u8) (BIT_0); E100_CONFIG(bdp, 7); } if (bdp->config[15] & CB_CFIG_PROMISCUOUS) { bdp->config[15] &= ~CB_CFIG_PROMISCUOUS; E100_CONFIG(bdp, 15); } } spin_unlock_bh(&(bdp->config_lock)); } /** * e100_config_mulcast_enbl - configure allmulti mode * @bdp: atapter's private data struct * @enable: should we enable this option or not * * This routine will enable or disable reception of all multicast packets * in the adapter's config block. */ void e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable) { spin_lock_bh(&(bdp->config_lock)); /* this flag is used to enable receiving all multicast packet */ if (enable) { if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) { bdp->config[21] |= CB_CFIG_MULTICAST_ALL; E100_CONFIG(bdp, 21); } } else { if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) { bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL; E100_CONFIG(bdp, 21); } } spin_unlock_bh(&(bdp->config_lock)); } /** * e100_config_ifs - configure the IFS parameter * @bdp: atapter's private data struct * * This routine will configure the adaptive IFS value * in the adapter's config block. IFS values are only * relevant in half duplex, so set to 0 in full duplex. */ void e100_config_ifs(struct e100_private *bdp) { u8 value = 0; spin_lock_bh(&(bdp->config_lock)); /* IFS value is only needed to be specified at half-duplex mode */ if (bdp->cur_dplx_mode == HALF_DUPLEX) { value = (u8) bdp->ifs_value; } if (bdp->config[2] != value) { bdp->config[2] = value; E100_CONFIG(bdp, 2); } spin_unlock_bh(&(bdp->config_lock)); } /** * e100_config_force_dplx - configure the forced full duplex mode * @bdp: atapter's private data struct * * This routine will enable or disable force full duplex * in the adapter's config block. If the PHY is 503, and * the duplex is full, consider the adapter forced. */ void e100_config_force_dplx(struct e100_private *bdp) { spin_lock_bh(&(bdp->config_lock)); /* We must force full duplex on if we are using PHY 0, and we are */ /* supposed to run in FDX mode. We do this because the e100 has only */ /* one FDX# input pin, and that pin will be connected to PHY 1. */ /* Changed the 'if' condition below to fix performance problem * at 10 * full. The Phy was getting forced to full duplex while the MAC * was * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. * * This is how the condition was, initially. * This has been changed so * that the MAC gets forced to full duplex * simply if the user has * forced full duplex. * * if (( bdp->phy_addr == 0 ) && ( * bdp->cur_dplx_mode == 2 )) */ /* The rest of the fix is in the PhyDetect code. */ if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) || (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) || ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) { if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) { bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX; E100_CONFIG(bdp, 19); } } else { if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) { bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX); E100_CONFIG(bdp, 19); } } spin_unlock_bh(&(bdp->config_lock)); } /** * e100_config_long_rx * @bdp: atapter's private data struct * @enable: should we enable this option or not * * This routine will enable or disable reception of larger packets. * This is needed by VLAN implementations. */ static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable) { if (enable) { if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) { bdp->config[18] |= CB_CFIG_LONG_RX_OK; E100_CONFIG(bdp, 18); } } else { if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) { bdp->config[18] &= ~CB_CFIG_LONG_RX_OK; E100_CONFIG(bdp, 18); } } } /** * e100_config_wol * @bdp: atapter's private data struct * * This sets configuration options for PHY and Magic Packet WoL */ void e100_config_wol(struct e100_private *bdp) { spin_lock_bh(&(bdp->config_lock)); if (bdp->wolopts & WAKE_PHY) { bdp->config[9] |= CB_LINK_STATUS_WOL; } else { /* Disable PHY WoL */ bdp->config[9] &= ~CB_LINK_STATUS_WOL; } if (bdp->wolopts & WAKE_MAGIC) { bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE; } else { /* Disable Magic Packet WoL */ bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE; } E100_CONFIG(bdp, 19); spin_unlock_bh(&(bdp->config_lock)); } void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable) { spin_lock_bh(&(bdp->config_lock)); if (enable) { if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE; E100_CONFIG(bdp, 22); } } else { if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE; E100_CONFIG(bdp, 22); } } spin_unlock_bh(&(bdp->config_lock)); } /** * e100_config_loopback_mode * @bdp: atapter's private data struct * @mode: loopback mode(phy/mac/none) * */ unsigned char e100_config_loopback_mode(struct e100_private *bdp, u8 mode) { unsigned char bc_changed = false; u8 config_byte; spin_lock_bh(&(bdp->config_lock)); switch (mode) { case NO_LOOPBACK: config_byte = CB_CFIG_LOOPBACK_NORMAL; break; case MAC_LOOPBACK: config_byte = CB_CFIG_LOOPBACK_INTERNAL; break; case PHY_LOOPBACK: config_byte = CB_CFIG_LOOPBACK_EXTERNAL; break; default: printk(KERN_NOTICE "e100: e100_config_loopback_mode: " "Invalid argument 'mode': %d\n", mode); goto exit; } if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) { bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE); bdp->config[10] |= config_byte; E100_CONFIG(bdp, 10); bc_changed = true; } exit: spin_unlock_bh(&(bdp->config_lock)); return bc_changed; } unsigned char e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable) { unsigned char bc_changed = false; spin_lock_bh(&(bdp->config_lock)); if (enable) { if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) { bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS); E100_CONFIG(bdp, 6); bc_changed = true; } } else { if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) { bdp->config[6] |= CB_CFIG_EXT_TCB_DIS; E100_CONFIG(bdp, 6); bc_changed = true; } } spin_unlock_bh(&(bdp->config_lock)); return bc_changed; } unsigned char e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable) { unsigned char bc_changed = false; spin_lock_bh(&(bdp->config_lock)); if (enable) { if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) { bdp->config[7] |= CB_CFIG_DYNTBD_EN; E100_CONFIG(bdp, 7); bc_changed = true; } } else { if (bdp->config[7] & CB_CFIG_DYNTBD_EN) { bdp->config[7] &= (~CB_CFIG_DYNTBD_EN); E100_CONFIG(bdp, 7); bc_changed = true; } } spin_unlock_bh(&(bdp->config_lock)); return bc_changed; }
Go to most recent revision | Compare with Previous | Blame | View Log