summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik/net/if_em/if_em.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/beatnik/net/if_em/if_em.c')
-rw-r--r--bsps/powerpc/beatnik/net/if_em/if_em.c3847
1 files changed, 0 insertions, 3847 deletions
diff --git a/bsps/powerpc/beatnik/net/if_em/if_em.c b/bsps/powerpc/beatnik/net/if_em/if_em.c
deleted file mode 100644
index db3607a20d..0000000000
--- a/bsps/powerpc/beatnik/net/if_em/if_em.c
+++ /dev/null
@@ -1,3847 +0,0 @@
-/**************************************************************************
-
-Copyright (c) 2001-2005, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-***************************************************************************/
-
-/*$FreeBSD: /repoman/r/ncvs/src/sys/dev/em/if_em.c,v 1.67 2005/08/03 00:18:29 rwatson Exp $*/
-#ifndef __rtems__
-#include <dev/em/if_em.h>
-#else
-#include <rtems.h>
-#include "rtemscompat_defs.h"
-#include "../porting/rtemscompat.h"
-#include "if_em.h"
-#include "../porting/rtemscompat1.h"
-#include <inttypes.h>
-#endif
-
-/*********************************************************************
- * Set this to one to display debug statistics
- *********************************************************************/
-int em_display_debug_stats = 0;
-
-/*********************************************************************
- * Linked list of board private structures for all NICs found
- *********************************************************************/
-
-struct adapter *em_adapter_list = NULL;
-
-
-/*********************************************************************
- * Driver version
- *********************************************************************/
-
-char em_driver_version[] = "2.1.7";
-
-
-/*********************************************************************
- * PCI Device ID Table
- *
- * Used by probe to select devices to load on
- * Last field stores an index into em_strings
- * Last entry must be all 0s
- *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
- *********************************************************************/
-
-static em_vendor_info_t em_vendor_info_array[] =
-{
- /* Intel(R) PRO/1000 Network Connection */
- { 0x8086, E1000_DEV_ID_82540EM, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82540EM_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82540EP, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82540EP_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82540EP_LP, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82541EI, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541ER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541ER_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541GI, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541GI_LF, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82541GI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82542, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82543GC_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82543GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82544EI_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82544EI_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82544GC_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82544GC_LOM, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82545EM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82545EM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82545GM_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82545GM_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82545GM_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82546EB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546EB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546EB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546GB_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546GB_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546GB_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546GB_PCIE, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82546GB_QUAD_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82547EI, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82547EI_MOBILE, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82547GI, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- { 0x8086, E1000_DEV_ID_82573E, PCI_ANY_ID, PCI_ANY_ID, 0},
- { 0x8086, E1000_DEV_ID_82573E_IAMT, PCI_ANY_ID, PCI_ANY_ID, 0},
-
- /* required last entry */
- { 0, 0, 0, 0, 0}
-};
-
-/*********************************************************************
- * Table of branding strings for all supported NICs.
- *********************************************************************/
-
-static char *em_strings[] = {
- "Intel(R) PRO/1000 Network Connection"
-};
-
-/*********************************************************************
- * Function prototypes
- *********************************************************************/
-static int em_probe(device_t);
-static int em_attach(device_t);
-#if !defined(__rtems__) || defined(DEBUG_MODULAR)
-static int em_detach(device_t);
-#endif
-#ifndef __rtems__
-static int em_shutdown(device_t);
-#endif
-static void em_intr(void *);
-static void em_start(struct ifnet *);
-#ifndef __rtems__
-static int em_ioctl(struct ifnet *, u_long, caddr_t);
-#else
-static int em_ioctl(struct ifnet *, ioctl_command_t, caddr_t);
-#endif
-static void em_watchdog(struct ifnet *);
-static void em_init(void *);
-static void em_init_locked(struct adapter *);
-static void em_stop(void *);
-static void em_media_status(struct ifnet *, struct ifmediareq *);
-#ifndef __rtems__
-static int em_media_change(struct ifnet *);
-#else
-static int em_media_change(struct ifnet *ifp, struct rtems_ifmedia *ifm);
-#endif
-static void em_identify_hardware(struct adapter *);
-static int em_allocate_pci_resources(struct adapter *);
-#ifndef __rtems__
-static void em_free_pci_resources(struct adapter *);
-static void em_local_timer(void *);
-#endif
-static int em_hardware_init(struct adapter *);
-static void em_setup_interface(device_t, struct adapter *);
-static int em_setup_transmit_structures(struct adapter *);
-static void em_initialize_transmit_unit(struct adapter *);
-static int em_setup_receive_structures(struct adapter *);
-static void em_initialize_receive_unit(struct adapter *);
-static void em_enable_intr(struct adapter *);
-static void em_disable_intr(struct adapter *);
-static void em_free_transmit_structures(struct adapter *);
-static void em_free_receive_structures(struct adapter *);
-static void em_update_stats_counters(struct adapter *);
-static void em_clean_transmit_interrupts(struct adapter *);
-static int em_allocate_receive_structures(struct adapter *);
-static int em_allocate_transmit_structures(struct adapter *);
-static void em_process_receive_interrupts(struct adapter *, int);
-#ifndef __rtems__
-static void em_receive_checksum(struct adapter *,
- struct em_rx_desc *,
- struct mbuf *);
-static void em_transmit_checksum_setup(struct adapter *,
- struct mbuf *,
- u_int32_t *,
- u_int32_t *);
-#endif
-static void em_set_promisc(struct adapter *);
-static void em_disable_promisc(struct adapter *);
-static void em_set_multi(struct adapter *);
-static void em_print_hw_stats(struct adapter *);
-static void em_print_link_status(struct adapter *);
-static int em_get_buf(int i, struct adapter *,
- struct mbuf *);
-#ifndef __rtems__
-static void em_enable_vlans(struct adapter *);
-static void em_disable_vlans(struct adapter *);
-#endif
-static int em_encap(struct adapter *, struct mbuf **);
-#ifndef __rtems__
-static void em_smartspeed(struct adapter *);
-#endif
-static int em_82547_fifo_workaround(struct adapter *, int);
-static void em_82547_update_fifo_head(struct adapter *, int);
-static int em_82547_tx_fifo_reset(struct adapter *);
-#ifndef __rtems__
-static void em_82547_move_tail(void *arg);
-#endif
-static void em_82547_move_tail_locked(struct adapter *);
-static int em_dma_malloc(struct adapter *, bus_size_t,
- struct em_dma_alloc *, int);
-static void em_dma_free(struct adapter *, struct em_dma_alloc *);
-#ifndef __rtems__
-static void em_print_debug_info(struct adapter *);
-#endif
-static int em_is_valid_ether_addr(u_int8_t *);
-#ifndef __rtems__
-static int em_sysctl_stats(SYSCTL_HANDLER_ARGS);
-static int em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
-#endif
-static u_int32_t em_fill_descriptors (u_int64_t address,
- u_int32_t length,
- PDESC_ARRAY desc_array);
-#ifndef __rtems__
-static int em_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
-static void em_add_int_delay_sysctl(struct adapter *, const char *,
- const char *, struct em_int_delay_info *,
- int, int);
-#endif
-
-/*********************************************************************
- * FreeBSD Device Interface Entry Points
- *********************************************************************/
-
-#ifndef __rtems__
-static device_method_t em_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, em_probe),
- DEVMETHOD(device_attach, em_attach),
- DEVMETHOD(device_detach, em_detach),
- DEVMETHOD(device_shutdown, em_shutdown),
- {0, 0}
-};
-
-static driver_t em_driver = {
- "em", em_methods, sizeof(struct adapter ),
-};
-
-static devclass_t em_devclass;
-DRIVER_MODULE(em, pci, em_driver, em_devclass, 0, 0);
-MODULE_DEPEND(em, pci, 1, 1, 1);
-MODULE_DEPEND(em, ether, 1, 1, 1);
-#else
-net_drv_tbl_t METHODS = {
- n_probe : em_probe,
- n_attach : em_attach,
-#ifdef DEBUG_MODULAR
- n_detach : em_detach,
-#else
- n_detach: 0,
-#endif
- n_intr : em_intr,
-};
-#endif
-
-/*********************************************************************
- * Tunable default values.
- *********************************************************************/
-
-#define E1000_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
-#define E1000_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
-
-#ifndef __rtems__
-static int em_tx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_TIDV);
-static int em_rx_int_delay_dflt = E1000_TICKS_TO_USECS(EM_RDTR);
-static int em_tx_abs_int_delay_dflt = E1000_TICKS_TO_USECS(EM_TADV);
-static int em_rx_abs_int_delay_dflt = E1000_TICKS_TO_USECS(EM_RADV);
-
-TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
-TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
-TUNABLE_INT("hw.em.tx_abs_int_delay", &em_tx_abs_int_delay_dflt);
-TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
-#endif
-
-/*********************************************************************
- * Device identification routine
- *
- * em_probe determines if the driver should be loaded on
- * adapter based on PCI vendor/device id of the adapter.
- *
- * return BUS_PROBE_DEFAULT on success, positive on failure
- *********************************************************************/
-
-static int
-em_probe(device_t dev)
-{
- em_vendor_info_t *ent;
-
- u_int16_t pci_vendor_id = 0;
- u_int16_t pci_device_id = 0;
- u_int16_t pci_subvendor_id = 0;
- u_int16_t pci_subdevice_id = 0;
- char adapter_name[60];
-
- INIT_DEBUGOUT("em_probe: begin");
-
- pci_vendor_id = pci_get_vendor(dev);
- if (pci_vendor_id != EM_VENDOR_ID)
- return(ENXIO);
-
- pci_device_id = pci_get_device(dev);
- pci_subvendor_id = pci_get_subvendor(dev);
- pci_subdevice_id = pci_get_subdevice(dev);
-
- ent = em_vendor_info_array;
- while (ent->vendor_id != 0) {
- if ((pci_vendor_id == ent->vendor_id) &&
- (pci_device_id == ent->device_id) &&
-
- ((pci_subvendor_id == ent->subvendor_id) ||
- (ent->subvendor_id == PCI_ANY_ID)) &&
-
- ((pci_subdevice_id == ent->subdevice_id) ||
- (ent->subdevice_id == PCI_ANY_ID))) {
- sprintf(adapter_name, "%s, Version - %s",
- em_strings[ent->index],
- em_driver_version);
- device_set_desc_copy(dev, adapter_name);
- return(BUS_PROBE_DEFAULT);
- }
- ent++;
- }
-
- return(ENXIO);
-}
-
-/*********************************************************************
- * Device initialization routine
- *
- * The attach entry point is called when the driver is being loaded.
- * This routine identifies the type of hardware, allocates all resources
- * and initializes the hardware.
- *
- * return 0 on success, positive on failure
- *********************************************************************/
-
-static int
-em_attach(device_t dev)
-{
- struct adapter * adapter;
- int tsize, rsize;
- int error = 0;
-
- INIT_DEBUGOUT("em_attach: begin");
-
- /* Allocate, clear, and link in our adapter structure */
- if (!(adapter = device_get_softc(dev))) {
- printf("em: adapter structure allocation failed\n");
- return(ENOMEM);
- }
-#ifndef __rtems__
- bzero(adapter, sizeof(struct adapter ));
-#else
- /* softc structure is maintained outside of this
- * and the osdep already contains vital fields (memory address)
- */
-#endif
- adapter->dev = dev;
- adapter->osdep.dev = dev;
- adapter->unit = device_get_unit(dev);
- EM_LOCK_INIT(adapter, device_get_nameunit(dev));
-
- if (em_adapter_list != NULL)
- em_adapter_list->prev = adapter;
- adapter->next = em_adapter_list;
- em_adapter_list = adapter;
-
-#ifndef __rtems__
- /* SYSCTL stuff */
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "debug_info", CTLTYPE_INT|CTLFLAG_RW,
- (void *)adapter, 0,
- em_sysctl_debug_info, "I", "Debug Information");
-
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
- OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW,
- (void *)adapter, 0,
- em_sysctl_stats, "I", "Statistics");
-#endif
-
- callout_init(&adapter->timer, CALLOUT_MPSAFE);
- callout_init(&adapter->tx_fifo_timer, CALLOUT_MPSAFE);
-
- /* Determine hardware revision */
- em_identify_hardware(adapter);
-
-#ifndef __rtems__
- /* Set up some sysctls for the tunable interrupt delays */
- em_add_int_delay_sysctl(adapter, "rx_int_delay",
- "receive interrupt delay in usecs", &adapter->rx_int_delay,
- E1000_REG_OFFSET(&adapter->hw, RDTR), em_rx_int_delay_dflt);
- em_add_int_delay_sysctl(adapter, "tx_int_delay",
- "transmit interrupt delay in usecs", &adapter->tx_int_delay,
- E1000_REG_OFFSET(&adapter->hw, TIDV), em_tx_int_delay_dflt);
- if (adapter->hw.mac_type >= em_82540) {
- em_add_int_delay_sysctl(adapter, "rx_abs_int_delay",
- "receive interrupt delay limit in usecs",
- &adapter->rx_abs_int_delay,
- E1000_REG_OFFSET(&adapter->hw, RADV),
- em_rx_abs_int_delay_dflt);
- em_add_int_delay_sysctl(adapter, "tx_abs_int_delay",
- "transmit interrupt delay limit in usecs",
- &adapter->tx_abs_int_delay,
- E1000_REG_OFFSET(&adapter->hw, TADV),
- em_tx_abs_int_delay_dflt);
- }
-#endif
-
- /* Parameters (to be read from user) */
- adapter->num_tx_desc = EM_MAX_TXD;
- adapter->num_rx_desc = EM_MAX_RXD;
-#ifdef __rtems__
- if ( dev->d_ifconfig->rbuf_count > 0 ) {
- adapter->num_rx_desc = dev->d_ifconfig->rbuf_count;
- }
- if ( adapter->num_rx_desc < 80 )
- adapter->num_rx_desc = 80;
- if ( adapter->num_rx_desc > 256 )
- adapter->num_rx_desc = 256;
- if ( dev->d_ifconfig->xbuf_count > 0 ) {
- adapter->num_tx_desc = dev->d_ifconfig->xbuf_count;
- }
- if ( adapter->num_tx_desc < 80 )
- adapter->num_tx_desc = 80;
- if ( adapter->num_tx_desc > 256 )
- adapter->num_tx_desc = 256;
- adapter->tx_cleanup_threshold = adapter->num_tx_desc/8;
-#endif
- adapter->hw.autoneg = DO_AUTO_NEG;
- adapter->hw.wait_autoneg_complete = WAIT_FOR_AUTO_NEG_DEFAULT;
- adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
- adapter->hw.tbi_compatibility_en = TRUE;
- adapter->rx_buffer_len = EM_RXBUFFER_2048;
-
- /*
- * These parameters control the automatic generation(Tx) and
- * response(Rx) to Ethernet PAUSE frames.
- */
- adapter->hw.fc_high_water = FC_DEFAULT_HI_THRESH;
- adapter->hw.fc_low_water = FC_DEFAULT_LO_THRESH;
- adapter->hw.fc_pause_time = FC_DEFAULT_TX_TIMER;
- adapter->hw.fc_send_xon = TRUE;
- adapter->hw.fc = em_fc_full;
-
- adapter->hw.phy_init_script = 1;
- adapter->hw.phy_reset_disable = FALSE;
-
-#ifndef EM_MASTER_SLAVE
- adapter->hw.master_slave = em_ms_hw_default;
-#else
- adapter->hw.master_slave = EM_MASTER_SLAVE;
-#endif
- /*
- * Set the max frame size assuming standard ethernet
- * sized frames
- */
- adapter->hw.max_frame_size =
- ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
-
- adapter->hw.min_frame_size =
- MINIMUM_ETHERNET_PACKET_SIZE + ETHER_CRC_LEN;
-
- /*
- * This controls when hardware reports transmit completion
- * status.
- */
- adapter->hw.report_tx_early = 1;
-
-
- if (em_allocate_pci_resources(adapter)) {
- printf("em%d: Allocation of PCI resources failed\n",
- adapter->unit);
- error = ENXIO;
- goto err_pci;
- }
-
-
- /* Initialize eeprom parameters */
- em_init_eeprom_params(&adapter->hw);
-
- tsize = EM_ROUNDUP(adapter->num_tx_desc *
- sizeof(struct em_tx_desc), 4096);
-
- /* Allocate Transmit Descriptor ring */
- if (em_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
- printf("em%d: Unable to allocate tx_desc memory\n",
- adapter->unit);
- error = ENOMEM;
- goto err_tx_desc;
- }
- adapter->tx_desc_base = (struct em_tx_desc *) adapter->txdma.dma_vaddr;
-
- rsize = EM_ROUNDUP(adapter->num_rx_desc *
- sizeof(struct em_rx_desc), 4096);
-
- /* Allocate Receive Descriptor ring */
- if (em_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
- printf("em%d: Unable to allocate rx_desc memory\n",
- adapter->unit);
- error = ENOMEM;
- goto err_rx_desc;
- }
- adapter->rx_desc_base = (struct em_rx_desc *) adapter->rxdma.dma_vaddr;
-
- /* Initialize the hardware */
- if (em_hardware_init(adapter)) {
- printf("em%d: Unable to initialize the hardware\n",
- adapter->unit);
- error = EIO;
- goto err_hw_init;
- }
-
- /* Copy the permanent MAC address out of the EEPROM */
- if (em_read_mac_addr(&adapter->hw) < 0) {
- printf("em%d: EEPROM read error while reading mac address\n",
- adapter->unit);
- error = EIO;
- goto err_mac_addr;
- }
-
-#ifdef __rtems__
- /* if the configuration has not set a mac address, copy the permanent
- * address from the device to the arpcom struct.
- */
- {
- int i;
- for ( i=0; i<ETHER_ADDR_LEN; i++ ) {
- if ( adapter->arpcom.ac_enaddr[i] )
- break;
- }
- if ( i >= ETHER_ADDR_LEN ) {
- /* all nulls */
- bcopy(adapter->hw.mac_addr, adapter->arpcom.ac_enaddr,
- ETHER_ADDR_LEN);
- }
- }
-#endif
-
- if (!em_is_valid_ether_addr(adapter->hw.mac_addr)) {
- printf("em%d: Invalid mac address\n", adapter->unit);
- error = EIO;
- goto err_mac_addr;
- }
-
- /* Setup OS specific network interface */
- em_setup_interface(dev, adapter);
-
- /* Initialize statistics */
- em_clear_hw_cntrs(&adapter->hw);
- em_update_stats_counters(adapter);
- adapter->hw.get_link_status = 1;
-#ifndef __rtems__
- em_check_for_link(&adapter->hw);
-#else
- /* first check during hw init usually fails - probably we need to wait longer;
- * could take a while till the link is up, depends on the partner?
- * in any case, rather than waiting here we just proceed...
- */
- em_check_for_link(&adapter->hw);
- /* em_check_for_link doesn't update 'link_active'
- * -- they usually call em_print_link_status() right
- * after check_for_link, so let's repeat this
- * algorithm here.
- */
- em_print_link_status(adapter);
-#endif
-
- /* Print the link status */
- if (adapter->link_active == 1) {
- em_get_speed_and_duplex(&adapter->hw, &adapter->link_speed,
- &adapter->link_duplex);
- printf("em%d: Speed:%d Mbps Duplex:%s\n",
- adapter->unit,
- adapter->link_speed,
- adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half");
- } else
- printf("em%d: Speed:N/A Duplex:N/A\n", adapter->unit);
-
- /* Identify 82544 on PCIX */
- em_get_bus_info(&adapter->hw);
- if(adapter->hw.bus_type == em_bus_type_pcix &&
- adapter->hw.mac_type == em_82544) {
- adapter->pcix_82544 = TRUE;
- }
- else {
- adapter->pcix_82544 = FALSE;
- }
- INIT_DEBUGOUT("em_attach: end");
- return(0);
-
-err_mac_addr:
-err_hw_init:
- em_dma_free(adapter, &adapter->rxdma);
-err_rx_desc:
- em_dma_free(adapter, &adapter->txdma);
-err_tx_desc:
-err_pci:
-#ifndef __rtems__
- em_free_pci_resources(adapter);
-#endif
- return(error);
-
-}
-
-/*********************************************************************
- * Device removal routine
- *
- * The detach entry point is called when the driver is being removed.
- * This routine stops the adapter and deallocates all the resources
- * that were allocated for driver operation.
- *
- * return 0 on success, positive on failure
- *********************************************************************/
-
-#if !defined(__rtems__) || defined(DEBUG_MODULAR)
-
-static int
-em_detach(device_t dev)
-{
- struct adapter * adapter = device_get_softc(dev);
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-
- INIT_DEBUGOUT("em_detach: begin");
-
- EM_LOCK(adapter);
- adapter->in_detach = 1;
- em_stop(adapter);
- em_phy_hw_reset(&adapter->hw);
- EM_UNLOCK(adapter);
-#ifndef __rtems__
-#if __FreeBSD_version < 500000
- ether_ifdetach(adapter->ifp, ETHER_BPF_SUPPORTED);
-#else
- ether_ifdetach(adapter->ifp);
- if_free(ifp);
-#endif
- em_free_pci_resources(adapter);
- bus_generic_detach(dev);
-#else
- ether_ifdetach(ifp);
-#endif
-
- /* Free Transmit Descriptor ring */
- if (adapter->tx_desc_base) {
- em_dma_free(adapter, &adapter->txdma);
- adapter->tx_desc_base = NULL;
- }
-
- /* Free Receive Descriptor ring */
- if (adapter->rx_desc_base) {
- em_dma_free(adapter, &adapter->rxdma);
- adapter->rx_desc_base = NULL;
- }
-
- /* Remove from the adapter list */
- if (em_adapter_list == adapter)
- em_adapter_list = adapter->next;
- if (adapter->next != NULL)
- adapter->next->prev = adapter->prev;
- if (adapter->prev != NULL)
- adapter->prev->next = adapter->next;
-
- EM_LOCK_DESTROY(adapter);
-
- ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
- ifp->if_timer = 0;
-
- return(0);
-}
-
-#endif
-
-#ifndef __rtems__
-/*********************************************************************
- *
- * Shutdown entry point
- *
- **********************************************************************/
-
-static int
-em_shutdown(device_t dev)
-{
- struct adapter *adapter = device_get_softc(dev);
- EM_LOCK(adapter);
- em_stop(adapter);
- EM_UNLOCK(adapter);
- return(0);
-}
-#endif
-
-/*********************************************************************
- * Transmit entry point
- *
- * em_start is called by the stack to initiate a transmit.
- * The driver will remain in this routine as long as there are
- * packets to transmit and transmit resources are available.
- * In case resources are not available stack is notified and
- * the packet is requeued.
- **********************************************************************/
-
-static void
-em_start_locked(struct ifnet *ifp)
-{
- struct mbuf *m_head;
- struct adapter *adapter = ifp->if_softc;
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- if (!adapter->link_active)
- return;
-
- while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
-
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
-
- if (m_head == NULL) break;
-
- /*
- * em_encap() can modify our pointer, and or make it NULL on
- * failure. In that event, we can't requeue.
- */
- if (em_encap(adapter, &m_head)) {
- if (m_head == NULL)
- break;
- ifp->if_flags |= IFF_OACTIVE;
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- break;
- }
-
- /* Send a copy of the frame to the BPF listener */
-#if __FreeBSD_version < 500000 && !defined(__rtems__)
- if (ifp->if_bpf)
- bpf_mtap(ifp, m_head);
-#else
- BPF_MTAP(ifp, m_head);
-#endif
-
- /* Set timeout in case hardware has problems transmitting */
- ifp->if_timer = EM_TX_TIMEOUT;
-
- }
- return;
-}
-
-static void
-em_start(struct ifnet *ifp)
-{
- struct adapter *adapter RTEMS_UNUSED = ifp->if_softc;
-
- EM_LOCK(adapter);
- em_start_locked(ifp);
- EM_UNLOCK(adapter);
- return;
-}
-
-/*********************************************************************
- * Ioctl entry point
- *
- * em_ioctl is called when the user wants to configure the
- * interface.
- *
- * return 0 on success, positive on failure
- **********************************************************************/
-
-#ifndef __rtems__
-static int
-em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
-#else
-static int
-em_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
-#endif
-{
-#ifndef __rtems__
- int mask, reinit, error = 0;
-#else
- int error = 0;
-#endif
- struct ifreq *ifr = (struct ifreq *) data;
- struct adapter * adapter = ifp->if_softc;
-
- if (adapter->in_detach) return(error);
-
- switch (command) {
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)");
- ether_ioctl(ifp, command, data);
- break;
- case SIOCSIFMTU:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
- if (ifr->ifr_mtu > MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN || \
- /* 82573 does not support jumbo frames */
- (adapter->hw.mac_type == em_82573 && ifr->ifr_mtu > ETHERMTU) ) {
- error = EINVAL;
- } else {
- EM_LOCK(adapter);
- ifp->if_mtu = ifr->ifr_mtu;
- adapter->hw.max_frame_size =
- ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
- em_init_locked(adapter);
- EM_UNLOCK(adapter);
- }
- break;
- case SIOCSIFFLAGS:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
- EM_LOCK(adapter);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_flags & IFF_RUNNING)) {
- em_init_locked(adapter);
- }
-
- em_disable_promisc(adapter);
- em_set_promisc(adapter);
- } else {
- if (ifp->if_flags & IFF_RUNNING) {
- em_stop(adapter);
- }
- }
- EM_UNLOCK(adapter);
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
-#ifdef __rtems__
- if ( (error = ( SIOCADDMULTI == command ?
- ether_addmulti( ifr, (struct arpcom*)ifp ) :
- ether_delmulti( ifr, (struct arpcom*)ifp ) ) ) ) {
- if ( ENETRESET == error )
- error = 0;
- else
- break;
- }
-#endif
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
- if (ifp->if_flags & IFF_RUNNING) {
- EM_LOCK(adapter);
- em_disable_intr(adapter);
- em_set_multi(adapter);
- if (adapter->hw.mac_type == em_82542_rev2_0) {
- em_initialize_receive_unit(adapter);
- }
-#ifdef DEVICE_POLLING
- if (!(ifp->if_flags & IFF_POLLING))
-#endif
- em_enable_intr(adapter);
- EM_UNLOCK(adapter);
- }
- break;
-#ifndef __rtems__
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
- error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
- break;
-#else
- case SIOCSIFMEDIA:
- {
- struct rtems_ifmedia mhack;
- mhack.ifm_media = ifr->ifr_media;
- error = em_media_change(ifp, &mhack);
- }
- break;
- case SIOCGIFMEDIA:
- {
- struct ifmediareq ifmr;
- em_media_status(ifp, &ifmr);
- ifr->ifr_media = ifmr.ifm_active;
- /* add-in rtems flags */
- if ( adapter->link_active )
- ifr->ifr_media |= IFM_LINK_OK;
- if ( !adapter->hw.autoneg )
- ifr->ifr_media |= IFM_ANEG_DIS;
- error = 0;
- }
- break;
-#endif
-#ifndef __rtems__
- case SIOCSIFCAP:
- IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
- reinit = 0;
- mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if (mask & IFCAP_POLLING)
- ifp->if_capenable ^= IFCAP_POLLING;
- if (mask & IFCAP_HWCSUM) {
- ifp->if_capenable ^= IFCAP_HWCSUM;
- reinit = 1;
- }
- if (mask & IFCAP_VLAN_HWTAGGING) {
- ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- reinit = 1;
- }
- if (reinit && (ifp->if_flags & IFF_RUNNING))
- em_init(adapter);
- break;
-#endif
-
-#ifdef __rtems__
- case SIO_RTEMS_SHOW_STATS:
- em_print_hw_stats(adapter);
- error = 0;
- break;
-#endif
-
- default:
- IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)", (int)command);
- error = EINVAL;
- }
-
- return(error);
-}
-
-/*********************************************************************
- * Watchdog entry point
- *
- * This routine is called whenever hardware quits transmitting.
- *
- **********************************************************************/
-
-static void
-em_watchdog(struct ifnet *ifp)
-{
- struct adapter * adapter;
- adapter = ifp->if_softc;
-
- /* If we are in this routine because of pause frames, then
- * don't reset the hardware.
- */
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF) {
- ifp->if_timer = EM_TX_TIMEOUT;
- return;
- }
-
- if (em_check_for_link(&adapter->hw))
- printf("em%d: watchdog timeout -- resetting\n", adapter->unit);
-
- ifp->if_flags &= ~IFF_RUNNING;
-
- em_init(adapter);
-
- ifp->if_oerrors++;
- return;
-}
-
-/*********************************************************************
- * Init entry point
- *
- * This routine is used in two ways. It is used by the stack as
- * init entry point in network interface structure. It is also used
- * by the driver as a hw/sw initialization routine to get to a
- * consistent state.
- *
- * return 0 on success, positive on failure
- **********************************************************************/
-
-static void
-em_init_locked(struct adapter * adapter)
-{
- struct ifnet *ifp;
-
- uint32_t pba;
- ifp = &adapter->arpcom.ac_if;
-
- INIT_DEBUGOUT("em_init: begin");
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- em_stop(adapter);
-
- /* Packet Buffer Allocation (PBA)
- * Writing PBA sets the receive portion of the buffer
- * the remainder is used for the transmit buffer.
- *
- * Devices before the 82547 had a Packet Buffer of 64K.
- * Default allocation: PBA=48K for Rx, leaving 16K for Tx.
- * After the 82547 the buffer was reduced to 40K.
- * Default allocation: PBA=30K for Rx, leaving 10K for Tx.
- * Note: default does not leave enough room for Jumbo Frame >10k.
- */
- if(adapter->hw.mac_type < em_82547) {
- /* Total FIFO is 64K */
- if(adapter->rx_buffer_len > EM_RXBUFFER_8192)
- pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */
- else
- pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */
- } else {
- /* Total FIFO is 40K */
- if(adapter->hw.max_frame_size > EM_RXBUFFER_8192) {
- pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */
- } else {
- pba = E1000_PBA_30K; /* 30K for Rx, 10K for Tx */
- }
- adapter->tx_fifo_head = 0;
- adapter->tx_head_addr = pba << EM_TX_HEAD_ADDR_SHIFT;
- adapter->tx_fifo_size = (E1000_PBA_40K - pba) << EM_PBA_BYTES_SHIFT;
- }
- INIT_DEBUGOUT1("em_init: pba=%" PRId32 "K",pba);
- E1000_WRITE_REG(&adapter->hw, PBA, pba);
-
- /* Get the latest mac address, User can use a LAA */
- bcopy(adapter->arpcom.ac_enaddr, adapter->hw.mac_addr,
- ETHER_ADDR_LEN);
-
- /* Initialize the hardware */
- if (em_hardware_init(adapter)) {
- printf("em%d: Unable to initialize the hardware\n",
- adapter->unit);
- return;
- }
-
-#ifndef __rtems__
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
- em_enable_vlans(adapter);
-#endif
-
- /* Prepare transmit descriptors and buffers */
- if (em_setup_transmit_structures(adapter)) {
- printf("em%d: Could not setup transmit structures\n",
- adapter->unit);
- em_stop(adapter);
- return;
- }
- em_initialize_transmit_unit(adapter);
-
- /* Setup Multicast table */
- em_set_multi(adapter);
-
- /* Prepare receive descriptors and buffers */
- if (em_setup_receive_structures(adapter)) {
- printf("em%d: Could not setup receive structures\n",
- adapter->unit);
- em_stop(adapter);
- return;
- }
- em_initialize_receive_unit(adapter);
-
- /* Don't loose promiscuous settings */
- em_set_promisc(adapter);
-
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
-
-#ifndef __rtems__
- if (adapter->hw.mac_type >= em_82543) {
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist = EM_CHECKSUM_FEATURES;
- else
- ifp->if_hwassist = 0;
- }
-#endif
-
- callout_reset(&adapter->timer, hz, em_local_timer, adapter);
- em_clear_hw_cntrs(&adapter->hw);
-#ifdef DEVICE_POLLING
- /*
- * Only enable interrupts if we are not polling, make sure
- * they are off otherwise.
- */
- if (ifp->if_flags & IFF_POLLING)
- em_disable_intr(adapter);
- else
-#endif /* DEVICE_POLLING */
- em_enable_intr(adapter);
-
- /* Don't reset the phy next time init gets called */
- adapter->hw.phy_reset_disable = TRUE;
-
- return;
-}
-
-static void
-em_init(void *arg)
-{
- struct adapter * adapter = arg;
-
- EM_LOCK(adapter);
- em_init_locked(adapter);
- EM_UNLOCK(adapter);
- return;
-}
-
-
-#ifdef DEVICE_POLLING
-static poll_handler_t em_poll;
-
-static void
-em_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct adapter *adapter = ifp->if_softc;
- u_int32_t reg_icr;
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
- if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
- em_enable_intr(adapter);
- return;
- }
- if (cmd == POLL_AND_CHECK_STATUS) {
- reg_icr = E1000_READ_REG(&adapter->hw, ICR);
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- callout_stop(&adapter->timer);
- adapter->hw.get_link_status = 1;
- em_check_for_link(&adapter->hw);
- em_print_link_status(adapter);
- callout_reset(&adapter->timer, hz, em_local_timer, adapter);
- }
- }
- if (ifp->if_flags & IFF_RUNNING) {
- em_process_receive_interrupts(adapter, count);
- em_clean_transmit_interrupts(adapter);
- }
-
- if (ifp->if_flags & IFF_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
-}
-
-static void
-em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct adapter *adapter = ifp->if_softc;
-
- EM_LOCK(adapter);
- em_poll_locked(ifp, cmd, count);
- EM_UNLOCK(adapter);
-}
-#endif /* DEVICE_POLLING */
-
-/*********************************************************************
- *
- * Interrupt Service routine
- *
- **********************************************************************/
-static void
-em_intr(void *arg)
-{
- u_int32_t loop_cnt = EM_MAX_INTR;
- u_int32_t reg_icr;
- struct ifnet *ifp;
- struct adapter *adapter = arg;
-
- EM_LOCK(adapter);
-
- ifp = &adapter->arpcom.ac_if;
-
-#ifdef DEVICE_POLLING
- if (ifp->if_flags & IFF_POLLING) {
- EM_UNLOCK(adapter);
- return;
- }
-
- if ((ifp->if_capenable & IFCAP_POLLING) &&
- ether_poll_register(em_poll, ifp)) {
- em_disable_intr(adapter);
- em_poll_locked(ifp, 0, 1);
- EM_UNLOCK(adapter);
- return;
- }
-#endif /* DEVICE_POLLING */
-
- reg_icr = E1000_READ_REG(&adapter->hw, ICR);
- if (!reg_icr) {
- EM_UNLOCK(adapter);
- return;
- }
-
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- callout_stop(&adapter->timer);
- adapter->hw.get_link_status = 1;
- em_check_for_link(&adapter->hw);
- em_print_link_status(adapter);
- callout_reset(&adapter->timer, hz, em_local_timer, adapter);
- }
-
- while (loop_cnt > 0) {
- if (ifp->if_flags & IFF_RUNNING) {
- em_process_receive_interrupts(adapter, -1);
- em_clean_transmit_interrupts(adapter);
- }
- loop_cnt--;
- }
-
- if (ifp->if_flags & IFF_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
-
- EM_UNLOCK(adapter);
- return;
-}
-
-
-
-/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called whenever the user queries the status of
- * the interface using ifconfig.
- *
- **********************************************************************/
-static void
-em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
- struct adapter * adapter = ifp->if_softc;
-
- INIT_DEBUGOUT("em_media_status: begin");
-
- em_check_for_link(&adapter->hw);
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
- if (adapter->link_active == 0) {
- em_get_speed_and_duplex(&adapter->hw,
- &adapter->link_speed,
- &adapter->link_duplex);
- adapter->link_active = 1;
- }
- } else {
- if (adapter->link_active == 1) {
- adapter->link_speed = 0;
- adapter->link_duplex = 0;
- adapter->link_active = 0;
- }
- }
-
- ifmr->ifm_status = IFM_AVALID;
- ifmr->ifm_active = IFM_ETHER;
-
- if (!adapter->link_active)
- return;
-
- ifmr->ifm_status |= IFM_ACTIVE;
-
- if (adapter->hw.media_type == em_media_type_fiber) {
- ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
- } else {
- switch (adapter->link_speed) {
- case 10:
- ifmr->ifm_active |= IFM_10_T;
- break;
- case 100:
- ifmr->ifm_active |= IFM_100_TX;
- break;
- case 1000:
-#if __FreeBSD_version < 500000 && !defined(__rtems__)
- ifmr->ifm_active |= IFM_1000_TX;
-#else
- ifmr->ifm_active |= IFM_1000_T;
-#endif
- break;
- }
- if (adapter->link_duplex == FULL_DUPLEX)
- ifmr->ifm_active |= IFM_FDX;
- else
- ifmr->ifm_active |= IFM_HDX;
- }
- return;
-}
-
-/*********************************************************************
- *
- * Media Ioctl callback
- *
- * This routine is called when the user changes speed/duplex using
- * media/mediopt option with ifconfig.
- *
- **********************************************************************/
-static int
-#ifndef __rtems__
-em_media_change(struct ifnet *ifp)
-#else
-em_media_change(struct ifnet *ifp, struct rtems_ifmedia *ifm)
-#endif
-{
- struct adapter * adapter = ifp->if_softc;
-#ifndef __rtems__
- struct ifmedia *ifm = &adapter->media;
-#endif
-
- INIT_DEBUGOUT("em_media_change: begin");
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return(EINVAL);
-
- switch (IFM_SUBTYPE(ifm->ifm_media)) {
- case IFM_AUTO:
- adapter->hw.autoneg = DO_AUTO_NEG;
- adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
- break;
- case IFM_1000_SX:
-#if __FreeBSD_version < 500000 && !defined(__rtems__)
- case IFM_1000_TX:
-#else
- case IFM_1000_T:
-#endif
- adapter->hw.autoneg = DO_AUTO_NEG;
- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
- break;
- case IFM_100_TX:
- adapter->hw.autoneg = FALSE;
- adapter->hw.autoneg_advertised = 0;
- if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
- adapter->hw.forced_speed_duplex = em_100_full;
- else
- adapter->hw.forced_speed_duplex = em_100_half;
- break;
- case IFM_10_T:
- adapter->hw.autoneg = FALSE;
- adapter->hw.autoneg_advertised = 0;
- if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
- adapter->hw.forced_speed_duplex = em_10_full;
- else
- adapter->hw.forced_speed_duplex = em_10_half;
- break;
- default:
- printf("em%d: Unsupported media type\n", adapter->unit);
- }
-
- /* As the speed/duplex settings my have changed we need to
- * reset the PHY.
- */
- adapter->hw.phy_reset_disable = FALSE;
-
- em_init(adapter);
-
- return(0);
-}
-
-/*********************************************************************
- *
- * This routine maps the mbufs to tx descriptors.
- *
- * return 0 on success, positive on failure
- **********************************************************************/
-static int
-em_encap(struct adapter *adapter, struct mbuf **m_headp)
-{
- u_int32_t txd_upper;
- u_int32_t txd_lower, txd_used = 0, txd_saved = 0;
- int i, j, error;
- u_int64_t address;
-
- struct mbuf *m_head;
-
- /* For 82544 Workaround */
- DESC_ARRAY desc_array;
- u_int32_t array_elements;
- u_int32_t counter;
-
-#ifndef __rtems__
-#if __FreeBSD_version < 500000
- struct ifvlan *ifv = NULL;
-#else
- struct m_tag *mtag;
-#endif
-#endif
- bus_dma_segment_t segs[EM_MAX_SCATTER];
-#ifndef __rtems__
- bus_dmamap_t map;
-#endif
- int nsegs;
- struct em_buffer *tx_buffer = NULL;
- struct em_tx_desc *current_tx_desc = NULL;
-#ifndef __rtems__
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-#endif
-
- m_head = *m_headp;
-
- /*
- * Force a cleanup if number of TX descriptors
- * available hits the threshold
- */
- if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
- em_clean_transmit_interrupts(adapter);
- if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
- adapter->no_tx_desc_avail1++;
- return(ENOBUFS);
- }
- }
-
-#ifndef __rtems__
- /*
- * Map the packet for DMA.
- */
- if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
- adapter->no_tx_map_avail++;
- return (ENOMEM);
- }
- error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
- &nsegs, BUS_DMA_NOWAIT);
- if (error != 0) {
- adapter->no_tx_dma_setup++;
- bus_dmamap_destroy(adapter->txtag, map);
- return (error);
- }
-#else
- (void)error;
- {
- struct mbuf *m;
- for ( m=m_head, nsegs=0; m; m=m->m_next, nsegs++ ) {
- if ( nsegs >= sizeof(segs)/sizeof(segs[0]) ) {
- break;
- }
- segs[nsegs].ds_addr = mtod(m, unsigned);
- segs[nsegs].ds_len = m->m_len;
- }
- }
-#endif
- KASSERT(nsegs != 0, ("em_encap: empty packet"));
-
- if (nsegs > adapter->num_tx_desc_avail) {
- adapter->no_tx_desc_avail2++;
- bus_dmamap_destroy(adapter->txtag, map);
- return (ENOBUFS);
- }
-
-
-#ifndef __rtems__
- if (ifp->if_hwassist > 0) {
- em_transmit_checksum_setup(adapter, m_head,
- &txd_upper, &txd_lower);
- } else
-#endif
- txd_upper = txd_lower = 0;
-
-
-#ifndef __rtems__
- /* Find out if we are in vlan mode */
-#if __FreeBSD_version < 500000
- if ((m_head->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
- m_head->m_pkthdr.rcvif != NULL &&
- m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN)
- ifv = m_head->m_pkthdr.rcvif->if_softc;
-#else
- mtag = VLAN_OUTPUT_TAG(ifp, m_head);
-#endif
-
- /*
- * When operating in promiscuous mode, hardware encapsulation for
- * packets is disabled. This means we have to add the vlan
- * encapsulation in the driver, since it will have come down from the
- * VLAN layer with a tag instead of a VLAN header.
- */
- if (mtag != NULL && adapter->em_insert_vlan_header) {
- struct ether_vlan_header *evl;
- struct ether_header eh;
-
- m_head = m_pullup(m_head, sizeof(eh));
- if (m_head == NULL) {
- *m_headp = NULL;
- bus_dmamap_destroy(adapter->txtag, map);
- return (ENOBUFS);
- }
- eh = *mtod(m_head, struct ether_header *);
- M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT);
- if (m_head == NULL) {
- *m_headp = NULL;
- bus_dmamap_destroy(adapter->txtag, map);
- return (ENOBUFS);
- }
- m_head = m_pullup(m_head, sizeof(*evl));
- if (m_head == NULL) {
- *m_headp = NULL;
- bus_dmamap_destroy(adapter->txtag, map);
- return (ENOBUFS);
- }
- evl = mtod(m_head, struct ether_vlan_header *);
- bcopy(&eh, evl, sizeof(*evl));
- evl->evl_proto = evl->evl_encap_proto;
- evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
- evl->evl_tag = htons(VLAN_TAG_VALUE(mtag));
- m_tag_delete(m_head, mtag);
- mtag = NULL;
- *m_headp = m_head;
- }
-#endif
-
- i = adapter->next_avail_tx_desc;
- if (adapter->pcix_82544) {
- txd_saved = i;
- txd_used = 0;
- }
- for (j = 0; j < nsegs; j++) {
- /* If adapter is 82544 and on PCIX bus */
- if(adapter->pcix_82544) {
- array_elements = 0;
- address = htole64(segs[j].ds_addr);
- /*
- * Check the Address and Length combination and
- * split the data accordingly
- */
- array_elements = em_fill_descriptors(address,
- htole32(segs[j].ds_len),
- &desc_array);
- for (counter = 0; counter < array_elements; counter++) {
- if (txd_used == adapter->num_tx_desc_avail) {
- adapter->next_avail_tx_desc = txd_saved;
- adapter->no_tx_desc_avail2++;
- bus_dmamap_destroy(adapter->txtag, map);
- return (ENOBUFS);
- }
- tx_buffer = &adapter->tx_buffer_area[i];
- current_tx_desc = &adapter->tx_desc_base[i];
- current_tx_desc->buffer_addr = htole64(
- desc_array.descriptor[counter].address);
- current_tx_desc->lower.data = htole32(
- (adapter->txd_cmd | txd_lower |
- (u_int16_t)desc_array.descriptor[counter].length));
- current_tx_desc->upper.data = htole32((txd_upper));
- if (++i == adapter->num_tx_desc)
- i = 0;
-
- tx_buffer->m_head = NULL;
- txd_used++;
- }
- } else {
- tx_buffer = &adapter->tx_buffer_area[i];
- current_tx_desc = &adapter->tx_desc_base[i];
-
- current_tx_desc->buffer_addr = htole64(segs[j].ds_addr);
- current_tx_desc->lower.data = htole32(
- adapter->txd_cmd | txd_lower | segs[j].ds_len);
- current_tx_desc->upper.data = htole32(txd_upper);
-
- if (++i == adapter->num_tx_desc)
- i = 0;
-
- tx_buffer->m_head = NULL;
- }
- }
-
- adapter->next_avail_tx_desc = i;
- if (adapter->pcix_82544) {
- adapter->num_tx_desc_avail -= txd_used;
- }
- else {
- adapter->num_tx_desc_avail -= nsegs;
- }
-
-#ifndef __rtems__
-#if __FreeBSD_version < 500000
- if (ifv != NULL) {
- /* Set the vlan id */
- current_tx_desc->upper.fields.special = htole16(ifv->ifv_tag);
-#else
- if (mtag != NULL) {
- /* Set the vlan id */
- current_tx_desc->upper.fields.special = htole16(VLAN_TAG_VALUE(mtag));
-#endif
-
- /* Tell hardware to add tag */
- current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_VLE);
- }
-#endif
-
- tx_buffer->m_head = m_head;
-#ifndef __rtems__
- tx_buffer->map = map;
-#endif
- bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
-
- /*
- * Last Descriptor of Packet needs End Of Packet (EOP)
- */
- current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_EOP);
-
- /*
- * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
- * that this frame is available to transmit.
- */
- bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- if (adapter->hw.mac_type == em_82547 &&
- adapter->link_duplex == HALF_DUPLEX) {
- em_82547_move_tail_locked(adapter);
- } else {
- E1000_WRITE_REG(&adapter->hw, TDT, i);
- if (adapter->hw.mac_type == em_82547) {
- em_82547_update_fifo_head(adapter, m_head->m_pkthdr.len);
- }
- }
-
- return(0);
-}
-
-/*********************************************************************
- *
- * 82547 workaround to avoid controller hang in half-duplex environment.
- * The workaround is to avoid queuing a large packet that would span
- * the internal Tx FIFO ring boundary. We need to reset the FIFO pointers
- * in this case. We do that only when FIFO is quiescent.
- *
- **********************************************************************/
-static void
-em_82547_move_tail_locked(struct adapter *adapter)
-{
- uint16_t hw_tdt;
- uint16_t sw_tdt;
- struct em_tx_desc *tx_desc;
- uint16_t length = 0;
- boolean_t eop = 0;
-
- EM_LOCK_ASSERT(adapter);
-
- hw_tdt = E1000_READ_REG(&adapter->hw, TDT);
- sw_tdt = adapter->next_avail_tx_desc;
-
- while (hw_tdt != sw_tdt) {
- tx_desc = &adapter->tx_desc_base[hw_tdt];
- length += tx_desc->lower.flags.length;
- eop = tx_desc->lower.data & E1000_TXD_CMD_EOP;
- if(++hw_tdt == adapter->num_tx_desc)
- hw_tdt = 0;
-
- if(eop) {
- if (em_82547_fifo_workaround(adapter, length)) {
- adapter->tx_fifo_wrk_cnt++;
- callout_reset(&adapter->tx_fifo_timer, 1,
- em_82547_move_tail, adapter);
- break;
- }
- E1000_WRITE_REG(&adapter->hw, TDT, hw_tdt);
- em_82547_update_fifo_head(adapter, length);
- length = 0;
- }
- }
- return;
-}
-
-#ifndef __rtems__
-static void
-em_82547_move_tail(void *arg)
-{
- struct adapter *adapter = arg;
-
- EM_LOCK(adapter);
- em_82547_move_tail_locked(adapter);
- EM_UNLOCK(adapter);
-}
-#endif
-
-static int
-em_82547_fifo_workaround(struct adapter *adapter, int len)
-{
- int fifo_space, fifo_pkt_len;
-
- fifo_pkt_len = EM_ROUNDUP(len + EM_FIFO_HDR, EM_FIFO_HDR);
-
- if (adapter->link_duplex == HALF_DUPLEX) {
- fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
-
- if (fifo_pkt_len >= (EM_82547_PKT_THRESH + fifo_space)) {
- if (em_82547_tx_fifo_reset(adapter)) {
- return(0);
- }
- else {
- return(1);
- }
- }
- }
-
- return(0);
-}
-
-static void
-em_82547_update_fifo_head(struct adapter *adapter, int len)
-{
- int fifo_pkt_len = EM_ROUNDUP(len + EM_FIFO_HDR, EM_FIFO_HDR);
-
- /* tx_fifo_head is always 16 byte aligned */
- adapter->tx_fifo_head += fifo_pkt_len;
- if (adapter->tx_fifo_head >= adapter->tx_fifo_size) {
- adapter->tx_fifo_head -= adapter->tx_fifo_size;
- }
-
- return;
-}
-
-
-static int
-em_82547_tx_fifo_reset(struct adapter *adapter)
-{
- uint32_t tctl;
-
- if ( (E1000_READ_REG(&adapter->hw, TDT) ==
- E1000_READ_REG(&adapter->hw, TDH)) &&
- (E1000_READ_REG(&adapter->hw, TDFT) ==
- E1000_READ_REG(&adapter->hw, TDFH)) &&
- (E1000_READ_REG(&adapter->hw, TDFTS) ==
- E1000_READ_REG(&adapter->hw, TDFHS)) &&
- (E1000_READ_REG(&adapter->hw, TDFPC) == 0)) {
-
- /* Disable TX unit */
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl & ~E1000_TCTL_EN);
-
- /* Reset FIFO pointers */
- E1000_WRITE_REG(&adapter->hw, TDFT, adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFH, adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFTS, adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFHS, adapter->tx_head_addr);
-
- /* Re-enable TX unit */
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
- E1000_WRITE_FLUSH(&adapter->hw);
-
- adapter->tx_fifo_head = 0;
- adapter->tx_fifo_reset_cnt++;
-
- return(TRUE);
- }
- else {
- return(FALSE);
- }
-}
-
-static void
-em_set_promisc(struct adapter * adapter)
-{
-
- u_int32_t reg_rctl;
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-
- reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
-
- if (ifp->if_flags & IFF_PROMISC) {
- reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
-#ifndef __rtems__
- /* Disable VLAN stripping in promiscous mode
- * This enables bridging of vlan tagged frames to occur
- * and also allows vlan tags to be seen in tcpdump
- */
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
- em_disable_vlans(adapter);
- adapter->em_insert_vlan_header = 1;
-#endif
- } else if (ifp->if_flags & IFF_ALLMULTI) {
- reg_rctl |= E1000_RCTL_MPE;
- reg_rctl &= ~E1000_RCTL_UPE;
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
-#ifndef __rtems__
- adapter->em_insert_vlan_header = 0;
- } else
- adapter->em_insert_vlan_header = 0;
-#else
- }
-#endif
-
- return;
-}
-
-static void
-em_disable_promisc(struct adapter * adapter)
-{
- u_int32_t reg_rctl;
-#ifndef __rtems__
- struct ifnet *ifp = adapter->ifp;
-#endif
-
- reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
-
- reg_rctl &= (~E1000_RCTL_UPE);
- reg_rctl &= (~E1000_RCTL_MPE);
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
-
-#ifndef __rtems__
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
- em_enable_vlans(adapter);
- adapter->em_insert_vlan_header = 0;
-#endif
-
- return;
-}
-
-
-/*********************************************************************
- * Multicast Update
- *
- * This routine is called whenever multicast address list is updated.
- *
- **********************************************************************/
-
-static void
-em_set_multi(struct adapter * adapter)
-{
- u_int32_t reg_rctl = 0;
- u_int8_t mta[MAX_NUM_MULTICAST_ADDRESSES * ETH_LENGTH_OF_ADDRESS];
-#ifndef __rtems__
- struct ifmultiaddr *ifma;
-#endif
- int mcnt = 0;
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-
- IOCTL_DEBUGOUT("em_set_multi: begin");
-
- if (adapter->hw.mac_type == em_82542_rev2_0) {
- reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
- if (adapter->hw.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
- em_pci_clear_mwi(&adapter->hw);
- }
- reg_rctl |= E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
- msec_delay(5);
- }
-
-#ifndef __rtems__
- IF_ADDR_LOCK(ifp);
-#if __FreeBSD_version < 500000
- LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#else
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#endif
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) break;
-
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- &mta[mcnt*ETH_LENGTH_OF_ADDRESS], ETH_LENGTH_OF_ADDRESS);
- mcnt++;
- }
- IF_ADDR_UNLOCK(ifp);
-#else
- {
- /* Don't know how to handle address ranges - we warn and ignore
- * for now...
- */
- struct ether_multi *enm;
- struct ether_multistep step;
-
- ETHER_FIRST_MULTI(step, (struct arpcom*)ifp, enm);
- while ( enm != NULL ) {
- if ( mcnt == MAX_NUM_MULTICAST_ADDRESSES )
- break;
- if ( memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) ) {
- printk("if_em: Unable to handle multicast wildcard (not ported yet); skipping/ignoring\n");
- goto skiptonext;
- } else {
- bcopy(enm->enm_addrlo, &mta[mcnt * ETHER_ADDR_LEN], ETHER_ADDR_LEN);
- }
- mcnt++;
-skiptonext:
- ETHER_NEXT_MULTI( step, enm );
- }
- }
-#endif
-
- if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) {
- reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
- reg_rctl |= E1000_RCTL_MPE;
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
- } else
- em_mc_addr_list_update(&adapter->hw, mta, mcnt, 0, 1);
-
- if (adapter->hw.mac_type == em_82542_rev2_0) {
- reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
- reg_rctl &= ~E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
- msec_delay(5);
- if (adapter->hw.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
- em_pci_set_mwi(&adapter->hw);
- }
- }
-
- return;
-}
-
-#ifndef __rtems__
-/*********************************************************************
- * Timer routine
- *
- * This routine checks for link status and updates statistics.
- *
- **********************************************************************/
-
-static void
-em_local_timer(void *arg)
-{
- struct ifnet *ifp;
- struct adapter * adapter = arg;
- ifp = &adapter->arpcom.ac_if;
-
- EM_LOCK(adapter);
-
- em_check_for_link(&adapter->hw);
- em_print_link_status(adapter);
- em_update_stats_counters(adapter);
- if (em_display_debug_stats && ifp->if_flags & IFF_RUNNING) {
- em_print_hw_stats(adapter);
- }
- em_smartspeed(adapter);
-
- callout_reset(&adapter->timer, hz, em_local_timer, adapter);
-
- EM_UNLOCK(adapter);
- return;
-}
-#endif
-
-static void
-em_print_link_status(struct adapter * adapter)
-{
-#ifndef __rtems__
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-#endif
-
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
- if (adapter->link_active == 0) {
- em_get_speed_and_duplex(&adapter->hw,
- &adapter->link_speed,
- &adapter->link_duplex);
- if (bootverbose)
- printf("em%d: Link is up %d Mbps %s\n",
- adapter->unit,
- adapter->link_speed,
- ((adapter->link_duplex == FULL_DUPLEX) ?
- "Full Duplex" : "Half Duplex"));
- adapter->link_active = 1;
- adapter->smartspeed = 0;
-#ifndef __rtems__
- if_link_state_change(ifp, LINK_STATE_UP);
-#endif
- }
- } else {
- if (adapter->link_active == 1) {
- adapter->link_speed = 0;
- adapter->link_duplex = 0;
- if (bootverbose)
- printf("em%d: Link is Down\n", adapter->unit);
- adapter->link_active = 0;
-#ifndef __rtems__
- if_link_state_change(ifp, LINK_STATE_UP);
- if_link_state_change(ifp, LINK_STATE_DOWN);
-#endif
- }
- }
-
- return;
-}
-
-/*********************************************************************
- *
- * This routine disables all traffic on the adapter by issuing a
- * global reset on the MAC and deallocates TX/RX buffers.
- *
- **********************************************************************/
-
-static void
-em_stop(void *arg)
-{
- struct ifnet *ifp;
- struct adapter * adapter = arg;
- ifp = &adapter->arpcom.ac_if;
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- INIT_DEBUGOUT("em_stop: begin");
-#ifdef DEVICE_POLLING
- ether_poll_deregister(ifp);
-#endif
- em_disable_intr(adapter);
- em_reset_hw(&adapter->hw);
- callout_stop(&adapter->timer);
- callout_stop(&adapter->tx_fifo_timer);
- em_free_transmit_structures(adapter);
- em_free_receive_structures(adapter);
-
-
- /* Tell the stack that the interface is no longer active */
- ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-
- return;
-}
-
-
-/*********************************************************************
- *
- * Determine hardware revision.
- *
- **********************************************************************/
-static void
-em_identify_hardware(struct adapter * adapter)
-{
- device_t dev = adapter->dev;
-
- /* Make sure our PCI config space has the necessary stuff set */
- adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
- if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&
- (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) {
- printf("em%d: Memory Access and/or Bus Master bits were not set!\n",
- adapter->unit);
- adapter->hw.pci_cmd_word |=
- (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
- pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2);
- }
-
- /* Save off the information about this board */
- adapter->hw.vendor_id = pci_get_vendor(dev);
- adapter->hw.device_id = pci_get_device(dev);
- adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
- adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
- adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
-
- /* Identify the MAC */
- if (em_set_mac_type(&adapter->hw))
- printf("em%d: Unknown MAC Type\n", adapter->unit);
-
- if(adapter->hw.mac_type == em_82541 ||
- adapter->hw.mac_type == em_82541_rev_2 ||
- adapter->hw.mac_type == em_82547 ||
- adapter->hw.mac_type == em_82547_rev_2)
- adapter->hw.phy_init_script = TRUE;
-
- return;
-}
-
-static int
-em_allocate_pci_resources(struct adapter * adapter)
-{
- int i, val, rid;
- device_t dev = adapter->dev;
-
- rid = EM_MMBA;
-
-#ifndef __rtems__
- adapter->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &rid, RF_ACTIVE);
- if (!(adapter->res_memory)) {
- printf("em%d: Unable to allocate bus resource: memory\n",
- adapter->unit);
- return(ENXIO);
- }
- adapter->osdep.mem_bus_space_tag =
- rman_get_bustag(adapter->res_memory);
- adapter->osdep.mem_bus_space_handle =
- rman_get_bushandle(adapter->res_memory);
-#endif
-
- adapter->hw.hw_addr = (uint8_t *)&adapter->osdep.mem_bus_space_handle;
-
-
- if (adapter->hw.mac_type > em_82543) {
- /* Figure our where our IO BAR is ? */
- rid = EM_MMBA;
- for (i = 0; i < 5; i++) {
- val = pci_read_config(dev, rid, 4);
- if (val & 0x00000001) {
-#ifndef __rtems__
- adapter->io_rid = rid;
-#endif
- break;
- }
- rid += 4;
- }
-
-#ifndef __rtems__
- adapter->res_ioport = bus_alloc_resource_any(dev,
- SYS_RES_IOPORT,
- &adapter->io_rid,
- RF_ACTIVE);
- if (!(adapter->res_ioport)) {
- printf("em%d: Unable to allocate bus resource: ioport\n",
- adapter->unit);
- return(ENXIO);
- }
-
- adapter->hw.io_base =
- rman_get_start(adapter->res_ioport);
-#else
- adapter->hw.io_base = val & PCI_BASE_ADDRESS_IO_MASK;
-#endif
- }
-
-#ifndef __rtems__
- rid = 0x0;
- adapter->res_interrupt = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE |
- RF_ACTIVE);
- if (!(adapter->res_interrupt)) {
- printf("em%d: Unable to allocate bus resource: interrupt\n",
- adapter->unit);
- return(ENXIO);
- }
- if (bus_setup_intr(dev, adapter->res_interrupt,
- INTR_TYPE_NET | INTR_MPSAFE,
- (void (*)(void *)) em_intr, adapter,
- &adapter->int_handler_tag)) {
- printf("em%d: Error registering interrupt handler!\n",
- adapter->unit);
- return(ENXIO);
- }
-#endif
-
- adapter->hw.back = &adapter->osdep;
-
- return(0);
-}
-
-#ifndef __rtems__
-static void
-em_free_pci_resources(struct adapter * adapter)
-{
- device_t dev = adapter->dev;
-
- if (adapter->res_interrupt != NULL) {
- bus_teardown_intr(dev, adapter->res_interrupt,
- adapter->int_handler_tag);
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- adapter->res_interrupt);
- }
- if (adapter->res_memory != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, EM_MMBA,
- adapter->res_memory);
- }
-
- if (adapter->res_ioport != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
- adapter->res_ioport);
- }
- return;
-}
-#endif
-
-/*********************************************************************
- *
- * Initialize the hardware to a configuration as specified by the
- * adapter structure. The controller is reset, the EEPROM is
- * verified, the MAC address is set, then the shared initialization
- * routines are called.
- *
- **********************************************************************/
-static int
-em_hardware_init(struct adapter * adapter)
-{
- INIT_DEBUGOUT("em_hardware_init: begin");
- /* Issue a global reset */
- em_reset_hw(&adapter->hw);
-
- /* When hardware is reset, fifo_head is also reset */
- adapter->tx_fifo_head = 0;
-
- /* Make sure we have a good EEPROM before we read from it */
- if (em_validate_eeprom_checksum(&adapter->hw) < 0) {
- printf("em%d: The EEPROM Checksum Is Not Valid\n",
- adapter->unit);
- return(EIO);
- }
-
- if (em_read_part_num(&adapter->hw, &(adapter->part_num)) < 0) {
- printf("em%d: EEPROM read error while reading part number\n",
- adapter->unit);
- return(EIO);
- }
-
- if (em_init_hw(&adapter->hw) < 0) {
- printf("em%d: Hardware Initialization Failed",
- adapter->unit);
- return(EIO);
- }
-
- em_check_for_link(&adapter->hw);
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)
- adapter->link_active = 1;
- else
- adapter->link_active = 0;
-
- if (adapter->link_active) {
- em_get_speed_and_duplex(&adapter->hw,
- &adapter->link_speed,
- &adapter->link_duplex);
- } else {
- adapter->link_speed = 0;
- adapter->link_duplex = 0;
- }
-
- return(0);
-}
-
-/*********************************************************************
- *
- * Setup networking device structure and register an interface.
- *
- **********************************************************************/
-static void
-em_setup_interface(device_t dev, struct adapter * adapter)
-{
- struct ifnet *ifp = &device_get_softc(dev)->arpcom.ac_if;
- INIT_DEBUGOUT("em_setup_interface: begin");
-
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_mtu = ETHERMTU;
- ifp->if_baudrate = 1000000000;
- ifp->if_init = em_init;
- ifp->if_softc = adapter;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-#ifdef __rtems__
- ifp->if_output = ether_output;
-#endif
- ifp->if_ioctl = em_ioctl;
- ifp->if_start = em_start;
- ifp->if_watchdog = em_watchdog;
-#ifndef __rtems__
- IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 1);
- ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 1;
- IFQ_SET_READY(&ifp->if_snd);
-#else
- ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
-#endif
-
-#ifndef __rtems__
-#if __FreeBSD_version < 500000
- ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
-#else
- ether_ifattach(ifp, adapter->hw.mac_addr);
-#endif
-#else
- if ( !ifp->if_addrlist ) /* reattach hack */
- {
- if_attach(ifp);
- ether_ifattach(ifp);
- }
-#endif
-
-#ifndef __rtems__
- ifp->if_capabilities = ifp->if_capenable = 0;
-
- if (adapter->hw.mac_type >= em_82543) {
- ifp->if_capabilities |= IFCAP_HWCSUM;
- ifp->if_capenable |= IFCAP_HWCSUM;
- }
-
- /*
- * Tell the upper layer(s) we support long frames.
- */
- ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
-#if __FreeBSD_version >= 500000
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
- ifp->if_capenable |= IFCAP_VLAN_MTU;
-#endif
-
-#ifdef DEVICE_POLLING
- ifp->if_capabilities |= IFCAP_POLLING;
- ifp->if_capenable |= IFCAP_POLLING;
-#endif
-
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&adapter->media, IFM_IMASK, em_media_change,
- em_media_status);
- if (adapter->hw.media_type == em_media_type_fiber) {
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
- 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX,
- 0, NULL);
- } else {
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX,
- 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX,
- 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX | IFM_FDX,
- 0, NULL);
-#if __FreeBSD_version < 500000
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_TX | IFM_FDX,
- 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_TX, 0, NULL);
-#else
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX,
- 0, NULL);
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
-#endif
- }
- ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
-#endif
-
- return;
-}
-
-#ifndef __rtems__
-/*********************************************************************
- *
- * Workaround for SmartSpeed on 82541 and 82547 controllers
- *
- **********************************************************************/
-static void
-em_smartspeed(struct adapter *adapter)
-{
- uint16_t phy_tmp;
-
- if(adapter->link_active || (adapter->hw.phy_type != em_phy_igp) ||
- !adapter->hw.autoneg || !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
- return;
-
- if(adapter->smartspeed == 0) {
- /* If Master/Slave config fault is asserted twice,
- * we assume back-to-back */
- em_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp);
- if(!(phy_tmp & SR_1000T_MS_CONFIG_FAULT)) return;
- em_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_tmp);
- if(phy_tmp & SR_1000T_MS_CONFIG_FAULT) {
- em_read_phy_reg(&adapter->hw, PHY_1000T_CTRL,
- &phy_tmp);
- if(phy_tmp & CR_1000T_MS_ENABLE) {
- phy_tmp &= ~CR_1000T_MS_ENABLE;
- em_write_phy_reg(&adapter->hw,
- PHY_1000T_CTRL, phy_tmp);
- adapter->smartspeed++;
- if(adapter->hw.autoneg &&
- !em_phy_setup_autoneg(&adapter->hw) &&
- !em_read_phy_reg(&adapter->hw, PHY_CTRL,
- &phy_tmp)) {
- phy_tmp |= (MII_CR_AUTO_NEG_EN |
- MII_CR_RESTART_AUTO_NEG);
- em_write_phy_reg(&adapter->hw,
- PHY_CTRL, phy_tmp);
- }
- }
- }
- return;
- } else if(adapter->smartspeed == EM_SMARTSPEED_DOWNSHIFT) {
- /* If still no link, perhaps using 2/3 pair cable */
- em_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_tmp);
- phy_tmp |= CR_1000T_MS_ENABLE;
- em_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_tmp);
- if(adapter->hw.autoneg &&
- !em_phy_setup_autoneg(&adapter->hw) &&
- !em_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_tmp)) {
- phy_tmp |= (MII_CR_AUTO_NEG_EN |
- MII_CR_RESTART_AUTO_NEG);
- em_write_phy_reg(&adapter->hw, PHY_CTRL, phy_tmp);
- }
- }
- /* Restart process after EM_SMARTSPEED_MAX iterations */
- if(adapter->smartspeed++ == EM_SMARTSPEED_MAX)
- adapter->smartspeed = 0;
-
- return;
-}
-
-
-/*
- * Manage DMA'able memory.
- */
-static void
-em_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- if (error)
- return;
- *(bus_addr_t*) arg = segs->ds_addr;
- return;
-}
-#endif
-
-static int
-em_dma_malloc(struct adapter *adapter, bus_size_t size,
- struct em_dma_alloc *dma, int mapflags)
-{
- int r;
-
-#ifndef __rtems__
- r = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- size, /* maxsize */
- 1, /* nsegments */
- size, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
- &dma->dma_tag);
- if (r != 0) {
- printf("em%d: em_dma_malloc: bus_dma_tag_create failed; "
- "error %u\n", adapter->unit, r);
- goto fail_0;
- }
-
- r = bus_dmamem_alloc(dma->dma_tag, (void**) &dma->dma_vaddr,
- BUS_DMA_NOWAIT, &dma->dma_map);
-#else
- if ( (dma->malloc_base = malloc( size + PAGE_SIZE, M_DEVBUF, M_NOWAIT )) ) {
- r = 0;
- dma->dma_vaddr = (caddr_t)_DO_ALIGN(dma->malloc_base, PAGE_SIZE);
- } else {
- r = -1;
- }
-#endif
- if (r != 0) {
-#ifndef __rtems__
- printf("em%d: em_dma_malloc: bus_dmammem_alloc failed; "
- "size %ju, error %d\n", adapter->unit,
- (uintmax_t)size, r);
-#else
- printf("em%d: em_dma_malloc: bus_dmammem_alloc failed; "
- "size %u, error %d\n", adapter->unit,
- size, r);
-#endif
- goto fail_2;
- }
-
-#ifndef __rtems__
- r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
- size,
- em_dmamap_cb,
- &dma->dma_paddr,
- mapflags | BUS_DMA_NOWAIT);
-#else
- dma->dma_paddr = kvtop(dma->dma_vaddr);
-#endif
- if (r != 0) {
- printf("em%d: em_dma_malloc: bus_dmamap_load failed; "
- "error %u\n", adapter->unit, r);
- goto fail_3;
- }
-
-#ifndef __rtems__
- dma->dma_size = size;
-#endif
- return (0);
-
-fail_3:
- bus_dmamap_unload(dma->dma_tag, dma->dma_map);
-fail_2:
-#ifndef __rtems__
- bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-#else
- free(dma->malloc_base, M_DEVBUF);
- dma->dma_vaddr = dma->malloc_base = 0;
- dma->dma_paddr = 0;
-#endif
- bus_dma_tag_destroy(dma->dma_tag);
-#ifndef __rtems__
-fail_0:
- dma->dma_map = NULL;
- dma->dma_tag = NULL;
-#endif
- return (r);
-}
-
-static void
-em_dma_free(struct adapter *adapter, struct em_dma_alloc *dma)
-{
- bus_dmamap_unload(dma->dma_tag, dma->dma_map);
-#ifndef __rtems__
- bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-#else
- free(dma->malloc_base, M_DEVBUF);
- dma->dma_vaddr = dma->malloc_base = 0;
- dma->dma_paddr = 0;
-#endif
- bus_dma_tag_destroy(dma->dma_tag);
-}
-
-
-/*********************************************************************
- *
- * Allocate memory for tx_buffer structures. The tx_buffer stores all
- * the information needed to transmit a packet on the wire.
- *
- **********************************************************************/
-static int
-em_allocate_transmit_structures(struct adapter * adapter)
-{
- if (!(adapter->tx_buffer_area =
- (struct em_buffer *) malloc(sizeof(struct em_buffer) *
- adapter->num_tx_desc, M_DEVBUF,
- M_NOWAIT))) {
- printf("em%d: Unable to allocate tx_buffer memory\n",
- adapter->unit);
- return ENOMEM;
- }
-
- bzero(adapter->tx_buffer_area,
- sizeof(struct em_buffer) * adapter->num_tx_desc);
-
- return 0;
-}
-
-/*********************************************************************
- *
- * Allocate and initialize transmit structures.
- *
- **********************************************************************/
-static int
-em_setup_transmit_structures(struct adapter * adapter)
-{
-#ifndef __rtems__
- /*
- * Setup DMA descriptor areas.
- */
- if (bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES * 8, /* maxsize */
- EM_MAX_SCATTER, /* nsegments */
- MCLBYTES * 8, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
- &adapter->txtag)) {
- printf("em%d: Unable to allocate TX DMA tag\n", adapter->unit);
- return (ENOMEM);
- }
-#endif
-
- if (em_allocate_transmit_structures(adapter))
- return (ENOMEM);
-
- bzero((void *) adapter->tx_desc_base,
- (sizeof(struct em_tx_desc)) * adapter->num_tx_desc);
-
- adapter->next_avail_tx_desc = 0;
- adapter->oldest_used_tx_desc = 0;
-
- /* Set number of descriptors available */
- adapter->num_tx_desc_avail = adapter->num_tx_desc;
-
- /* Set checksum context */
- adapter->active_checksum_context = OFFLOAD_NONE;
-
- return (0);
-}
-
-/*********************************************************************
- *
- * Enable transmit unit.
- *
- **********************************************************************/
-static void
-em_initialize_transmit_unit(struct adapter * adapter)
-{
- u_int32_t reg_tctl;
- u_int32_t reg_tipg = 0;
- u_int64_t bus_addr;
-
- INIT_DEBUGOUT("em_initialize_transmit_unit: begin");
- /* Setup the Base and Length of the Tx Descriptor Ring */
- bus_addr = adapter->txdma.dma_paddr;
- E1000_WRITE_REG(&adapter->hw, TDBAL, (u_int32_t)bus_addr);
- E1000_WRITE_REG(&adapter->hw, TDBAH, (u_int32_t)(bus_addr >> 32));
- E1000_WRITE_REG(&adapter->hw, TDLEN,
- adapter->num_tx_desc *
- sizeof(struct em_tx_desc));
-
- /* Setup the HW Tx Head and Tail descriptor pointers */
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
-
-
- HW_DEBUGOUT2("Base = %" PRIx32 ", Length = %" PRIx32 "\n",
- E1000_READ_REG(&adapter->hw, TDBAL),
- E1000_READ_REG(&adapter->hw, TDLEN));
-
- /* Set the default values for the Tx Inter Packet Gap timer */
- switch (adapter->hw.mac_type) {
- case em_82542_rev2_0:
- case em_82542_rev2_1:
- reg_tipg = DEFAULT_82542_TIPG_IPGT;
- reg_tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- reg_tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
- break;
- default:
- if (adapter->hw.media_type == em_media_type_fiber)
- reg_tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
- else
- reg_tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
- reg_tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- reg_tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
- }
-
- E1000_WRITE_REG(&adapter->hw, TIPG, reg_tipg);
- E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay.value);
- if(adapter->hw.mac_type >= em_82540)
- E1000_WRITE_REG(&adapter->hw, TADV,
- adapter->tx_abs_int_delay.value);
-
- /* Program the Transmit Control Register */
- reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- if (adapter->hw.mac_type >= em_82573)
- reg_tctl |= E1000_TCTL_MULR;
- if (adapter->link_duplex == 1) {
- reg_tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
- } else {
- reg_tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
- }
- E1000_WRITE_REG(&adapter->hw, TCTL, reg_tctl);
-
- /* Setup Transmit Descriptor Settings for this adapter */
- adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS;
-
- if (adapter->tx_int_delay.value > 0)
- adapter->txd_cmd |= E1000_TXD_CMD_IDE;
-
- return;
-}
-
-/*********************************************************************
- *
- * Free all transmit related data structures.
- *
- **********************************************************************/
-static void
-em_free_transmit_structures(struct adapter * adapter)
-{
- struct em_buffer *tx_buffer;
- int i;
-
- INIT_DEBUGOUT("free_transmit_structures: begin");
-
- if (adapter->tx_buffer_area != NULL) {
- tx_buffer = adapter->tx_buffer_area;
- for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
- if (tx_buffer->m_head != NULL) {
- bus_dmamap_unload(adapter->txtag, tx_buffer->map);
- bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
- m_freem(tx_buffer->m_head);
- }
- tx_buffer->m_head = NULL;
- }
- }
- if (adapter->tx_buffer_area != NULL) {
- free(adapter->tx_buffer_area, M_DEVBUF);
- adapter->tx_buffer_area = NULL;
- }
-#ifndef __rtems__
- if (adapter->txtag != NULL) {
- bus_dma_tag_destroy(adapter->txtag);
- adapter->txtag = NULL;
- }
-#endif
- return;
-}
-
-#ifndef __rtems__
-/*********************************************************************
- *
- * The offload context needs to be set when we transfer the first
- * packet of a particular protocol (TCP/UDP). We change the
- * context only if the protocol type changes.
- *
- **********************************************************************/
-static void
-em_transmit_checksum_setup(struct adapter * adapter,
- struct mbuf *mp,
- u_int32_t *txd_upper,
- u_int32_t *txd_lower)
-{
- struct em_context_desc *TXD;
- struct em_buffer *tx_buffer;
- int curr_txd;
-
- if (mp->m_pkthdr.csum_flags) {
-
- if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
- *txd_upper = E1000_TXD_POPTS_TXSM << 8;
- *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
- if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
- return;
- else
- adapter->active_checksum_context = OFFLOAD_TCP_IP;
-
- } else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
- *txd_upper = E1000_TXD_POPTS_TXSM << 8;
- *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
- if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
- return;
- else
- adapter->active_checksum_context = OFFLOAD_UDP_IP;
- } else {
- *txd_upper = 0;
- *txd_lower = 0;
- return;
- }
- } else {
- *txd_upper = 0;
- *txd_lower = 0;
- return;
- }
-
- /* If we reach this point, the checksum offload context
- * needs to be reset.
- */
- curr_txd = adapter->next_avail_tx_desc;
- tx_buffer = &adapter->tx_buffer_area[curr_txd];
- TXD = (struct em_context_desc *) &adapter->tx_desc_base[curr_txd];
-
- TXD->lower_setup.ip_fields.ipcss = ETHER_HDR_LEN;
- TXD->lower_setup.ip_fields.ipcso =
- ETHER_HDR_LEN + offsetof(struct ip, ip_sum);
- TXD->lower_setup.ip_fields.ipcse =
- htole16(ETHER_HDR_LEN + sizeof(struct ip) - 1);
-
- TXD->upper_setup.tcp_fields.tucss =
- ETHER_HDR_LEN + sizeof(struct ip);
- TXD->upper_setup.tcp_fields.tucse = htole16(0);
-
- if (adapter->active_checksum_context == OFFLOAD_TCP_IP) {
- TXD->upper_setup.tcp_fields.tucso =
- ETHER_HDR_LEN + sizeof(struct ip) +
- offsetof(struct tcphdr, th_sum);
- } else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
- TXD->upper_setup.tcp_fields.tucso =
- ETHER_HDR_LEN + sizeof(struct ip) +
- offsetof(struct udphdr, uh_sum);
- }
-
- TXD->tcp_seg_setup.data = htole32(0);
- TXD->cmd_and_length = htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
-
- tx_buffer->m_head = NULL;
-
- if (++curr_txd == adapter->num_tx_desc)
- curr_txd = 0;
-
- adapter->num_tx_desc_avail--;
- adapter->next_avail_tx_desc = curr_txd;
-
- return;
-}
-#endif
-
-/**********************************************************************
- *
- * Examine each tx_buffer in the used queue. If the hardware is done
- * processing the packet then free associated resources. The
- * tx_buffer is put back on the free queue.
- *
- **********************************************************************/
-static void
-em_clean_transmit_interrupts(struct adapter * adapter)
-{
- int i, num_avail;
- struct em_buffer *tx_buffer;
- struct em_tx_desc *tx_desc;
- struct ifnet *ifp = &adapter->arpcom.ac_if;
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
- return;
-
- num_avail = adapter->num_tx_desc_avail;
- i = adapter->oldest_used_tx_desc;
-
- tx_buffer = &adapter->tx_buffer_area[i];
- tx_desc = &adapter->tx_desc_base[i];
-
- bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
- BUS_DMASYNC_POSTREAD);
- while (tx_desc->upper.fields.status & E1000_TXD_STAT_DD) {
-
- tx_desc->upper.data = 0;
- num_avail++;
-
- if (tx_buffer->m_head) {
- ifp->if_opackets++;
- bus_dmamap_unload(adapter->txtag, tx_buffer->map);
- bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
-
- m_freem(tx_buffer->m_head);
- tx_buffer->m_head = NULL;
- }
-
- if (++i == adapter->num_tx_desc)
- i = 0;
-
- tx_buffer = &adapter->tx_buffer_area[i];
- tx_desc = &adapter->tx_desc_base[i];
- }
- bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- adapter->oldest_used_tx_desc = i;
-
- /*
- * If we have enough room, clear IFF_OACTIVE to tell the stack
- * that it is OK to send packets.
- * If there are no pending descriptors, clear the timeout. Otherwise,
- * if some descriptors have been freed, restart the timeout.
- */
- if (num_avail > EM_TX_CLEANUP_THRESHOLD) {
- ifp->if_flags &= ~IFF_OACTIVE;
- if (num_avail == adapter->num_tx_desc)
- ifp->if_timer = 0;
- else if (num_avail == adapter->num_tx_desc_avail)
- ifp->if_timer = EM_TX_TIMEOUT;
- }
- adapter->num_tx_desc_avail = num_avail;
- return;
-}
-
-/*********************************************************************
- *
- * Get a buffer from system mbuf buffer pool.
- *
- **********************************************************************/
-static int
-em_get_buf(int i, struct adapter *adapter,
- struct mbuf *nmp)
-{
- register struct mbuf *mp = nmp;
- struct em_buffer *rx_buffer;
- struct ifnet *ifp;
- bus_addr_t paddr;
-#ifndef __rtems__
- int error;
-#endif
-
- ifp = &adapter->arpcom.ac_if;
-
- if (mp == NULL) {
-#ifndef __rtems__
- mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
-#else
- MGETHDR(mp, M_DONTWAIT, MT_DATA);
- if ( mp ) {
- MCLGET( mp, M_DONTWAIT );
- if ( !(mp->m_flags & M_EXT) ) {
- m_freem(mp);
- mp = 0;
- }
- }
-#endif
- if (mp == NULL) {
- adapter->mbuf_cluster_failed++;
- return(ENOBUFS);
- }
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- } else {
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
- mp->m_data = mp->m_ext.ext_buf;
- mp->m_next = NULL;
- }
-
- if (ifp->if_mtu <= ETHERMTU) {
- m_adj(mp, ETHER_ALIGN);
- }
-
- rx_buffer = &adapter->rx_buffer_area[i];
-
-#ifndef __rtems__
- /*
- * Using memory from the mbuf cluster pool, invoke the
- * bus_dma machinery to arrange the memory mapping.
- */
- error = bus_dmamap_load(adapter->rxtag, rx_buffer->map,
- mtod(mp, void *), mp->m_len,
- em_dmamap_cb, &paddr, 0);
- if (error) {
- m_free(mp);
- return(error);
- }
-#else
- paddr = kvtop(mtod(mp, void*));
-#endif
-
- rx_buffer->m_head = mp;
- adapter->rx_desc_base[i].buffer_addr = htole64(paddr);
- bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
-
- return(0);
-}
-
-/*********************************************************************
- *
- * Allocate memory for rx_buffer structures. Since we use one
- * rx_buffer per received packet, the maximum number of rx_buffer's
- * that we'll need is equal to the number of receive descriptors
- * that we've allocated.
- *
- **********************************************************************/
-static int
-em_allocate_receive_structures(struct adapter * adapter)
-{
- int i, error;
-#ifndef __rtems__
- struct em_buffer *rx_buffer;
-#endif
-
- if (!(adapter->rx_buffer_area =
- (struct em_buffer *) malloc(sizeof(struct em_buffer) *
- adapter->num_rx_desc, M_DEVBUF,
- M_NOWAIT))) {
- printf("em%d: Unable to allocate rx_buffer memory\n",
- adapter->unit);
- return(ENOMEM);
- }
-
- bzero(adapter->rx_buffer_area,
- sizeof(struct em_buffer) * adapter->num_rx_desc);
-
-#ifndef __rtems__
- error = bus_dma_tag_create(NULL, /* parent */
- 1, 0, /* alignment, bounds */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES, /* maxsize */
- 1, /* nsegments */
- MCLBYTES, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
- &adapter->rxtag);
- if (error != 0) {
- printf("em%d: em_allocate_receive_structures: "
- "bus_dma_tag_create failed; error %u\n",
- adapter->unit, error);
- goto fail_0;
- }
- rx_buffer = adapter->rx_buffer_area;
- for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
- error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
- &rx_buffer->map);
- if (error != 0) {
- printf("em%d: em_allocate_receive_structures: "
- "bus_dmamap_create failed; error %u\n",
- adapter->unit, error);
- goto fail_1;
- }
- }
-
-#else
- error = 0;
-#endif
-
- for (i = 0; i < adapter->num_rx_desc; i++) {
- error = em_get_buf(i, adapter, NULL);
- if (error != 0) {
- adapter->rx_buffer_area[i].m_head = NULL;
- adapter->rx_desc_base[i].buffer_addr = 0;
- return(error);
- }
- }
- bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- return(0);
-
-#ifndef __rtems__
-fail_1:
- bus_dma_tag_destroy(adapter->rxtag);
-fail_0:
- adapter->rxtag = NULL;
-#endif
- free(adapter->rx_buffer_area, M_DEVBUF);
- adapter->rx_buffer_area = NULL;
- return (error);
-}
-
-/*********************************************************************
- *
- * Allocate and initialize receive structures.
- *
- **********************************************************************/
-static int
-em_setup_receive_structures(struct adapter * adapter)
-{
- bzero((void *) adapter->rx_desc_base,
- (sizeof(struct em_rx_desc)) * adapter->num_rx_desc);
-
- if (em_allocate_receive_structures(adapter))
- return ENOMEM;
-
- /* Setup our descriptor pointers */
- adapter->next_rx_desc_to_check = 0;
- return(0);
-}
-
-/*********************************************************************
- *
- * Enable receive unit.
- *
- **********************************************************************/
-static void
-em_initialize_receive_unit(struct adapter * adapter)
-{
- u_int32_t reg_rctl;
-#ifndef __rtems__
- u_int32_t reg_rxcsum;
-#endif
- struct ifnet *ifp;
- u_int64_t bus_addr;
-
- INIT_DEBUGOUT("em_initialize_receive_unit: begin");
- ifp = &adapter->arpcom.ac_if;
-
- /* Make sure receives are disabled while setting up the descriptor ring */
- E1000_WRITE_REG(&adapter->hw, RCTL, 0);
-
- /* Set the Receive Delay Timer Register */
- E1000_WRITE_REG(&adapter->hw, RDTR,
- adapter->rx_int_delay.value | E1000_RDT_FPDB);
-
- if(adapter->hw.mac_type >= em_82540) {
- E1000_WRITE_REG(&adapter->hw, RADV,
- adapter->rx_abs_int_delay.value);
-
- /* Set the interrupt throttling rate. Value is calculated
- * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */
-#define MAX_INTS_PER_SEC 8000
-#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
- E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
- }
-
- /* Setup the Base and Length of the Rx Descriptor Ring */
- bus_addr = adapter->rxdma.dma_paddr;
- E1000_WRITE_REG(&adapter->hw, RDBAL, (u_int32_t)bus_addr);
- E1000_WRITE_REG(&adapter->hw, RDBAH, (u_int32_t)(bus_addr >> 32));
- E1000_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
- sizeof(struct em_rx_desc));
-
- /* Setup the HW Rx Head and Tail Descriptor Pointers */
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1);
-
- /* Setup the Receive Control Register */
- reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
- E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
-
- if (adapter->hw.tbi_compatibility_on == TRUE)
- reg_rctl |= E1000_RCTL_SBP;
-
-
- switch (adapter->rx_buffer_len) {
- default:
- case EM_RXBUFFER_2048:
- reg_rctl |= E1000_RCTL_SZ_2048;
- break;
- case EM_RXBUFFER_4096:
- reg_rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- case EM_RXBUFFER_8192:
- reg_rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- case EM_RXBUFFER_16384:
- reg_rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- }
-
- if (ifp->if_mtu > ETHERMTU)
- reg_rctl |= E1000_RCTL_LPE;
-
-#ifndef __rtems__
- /* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if ((adapter->hw.mac_type >= em_82543) &&
- (ifp->if_capenable & IFCAP_RXCSUM)) {
- reg_rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
- reg_rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
- E1000_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum);
- }
-#endif
-
- /* Enable Receives */
- E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
-
- return;
-}
-
-/*********************************************************************
- *
- * Free receive related data structures.
- *
- **********************************************************************/
-static void
-em_free_receive_structures(struct adapter *adapter)
-{
- struct em_buffer *rx_buffer;
- int i;
-
- INIT_DEBUGOUT("free_receive_structures: begin");
-
- if (adapter->rx_buffer_area != NULL) {
- rx_buffer = adapter->rx_buffer_area;
- for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
-#ifndef __rtems__
- if (rx_buffer->map != NULL) {
- bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
- bus_dmamap_destroy(adapter->rxtag, rx_buffer->map);
- }
-#endif
- if (rx_buffer->m_head != NULL)
- m_freem(rx_buffer->m_head);
- rx_buffer->m_head = NULL;
- }
- }
- if (adapter->rx_buffer_area != NULL) {
- free(adapter->rx_buffer_area, M_DEVBUF);
- adapter->rx_buffer_area = NULL;
- }
-#ifndef __rtems__
- if (adapter->rxtag != NULL) {
- bus_dma_tag_destroy(adapter->rxtag);
- adapter->rxtag = NULL;
- }
-#endif
- return;
-}
-
-/*********************************************************************
- *
- * This routine executes in interrupt context. It replenishes
- * the mbufs in the descriptor and sends data which has been
- * dma'ed into host memory to upper layer.
- *
- * We loop at most count times if count is > 0, or until done if
- * count < 0.
- *
- *********************************************************************/
-static void
-em_process_receive_interrupts(struct adapter * adapter, int count)
-{
- struct ifnet *ifp;
- struct mbuf *mp;
-#if __FreeBSD_version < 500000
- struct ether_header *eh;
-#endif
- u_int8_t accept_frame = 0;
- u_int8_t eop = 0;
- u_int16_t len, desc_len, prev_len_adj;
- int i;
-
- /* Pointer to the receive descriptor being examined. */
- struct em_rx_desc *current_desc;
-
- mtx_assert(&adapter->mtx, MA_OWNED);
-
- ifp = &adapter->arpcom.ac_if;
- i = adapter->next_rx_desc_to_check;
- current_desc = &adapter->rx_desc_base[i];
- bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
- BUS_DMASYNC_POSTREAD);
-
- if (!((current_desc->status) & E1000_RXD_STAT_DD)) {
- return;
- }
-
- while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) {
-
- mp = adapter->rx_buffer_area[i].m_head;
- bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
- BUS_DMASYNC_POSTREAD);
-
- accept_frame = 1;
- prev_len_adj = 0;
- desc_len = le16toh(current_desc->length);
- if (current_desc->status & E1000_RXD_STAT_EOP) {
- count--;
- eop = 1;
- if (desc_len < ETHER_CRC_LEN) {
- len = 0;
- prev_len_adj = ETHER_CRC_LEN - desc_len;
- }
- else {
- len = desc_len - ETHER_CRC_LEN;
- }
- } else {
- eop = 0;
- len = desc_len;
- }
-
- if (current_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
- u_int8_t last_byte;
- u_int32_t pkt_len = desc_len;
-
- if (adapter->fmp != NULL)
- pkt_len += adapter->fmp->m_pkthdr.len;
-
- last_byte = *(mtod(mp, caddr_t) + desc_len - 1);
-
- if (TBI_ACCEPT(&adapter->hw, current_desc->status,
- current_desc->errors,
- pkt_len, last_byte)) {
- em_tbi_adjust_stats(&adapter->hw,
- &adapter->stats,
- pkt_len,
- adapter->hw.mac_addr);
- if (len > 0) len--;
- }
- else {
- accept_frame = 0;
- }
- }
-
- if (accept_frame) {
-
- if (em_get_buf(i, adapter, NULL) == ENOBUFS) {
- adapter->dropped_pkts++;
- em_get_buf(i, adapter, mp);
- if (adapter->fmp != NULL)
- m_freem(adapter->fmp);
- adapter->fmp = NULL;
- adapter->lmp = NULL;
- break;
- }
-
- /* Assign correct length to the current fragment */
- mp->m_len = len;
-
- if (adapter->fmp == NULL) {
- mp->m_pkthdr.len = len;
- adapter->fmp = mp; /* Store the first mbuf */
- adapter->lmp = mp;
- } else {
- /* Chain mbuf's together */
- mp->m_flags &= ~M_PKTHDR;
- /*
- * Adjust length of previous mbuf in chain if we
- * received less than 4 bytes in the last descriptor.
- */
- if (prev_len_adj > 0) {
- adapter->lmp->m_len -= prev_len_adj;
- adapter->fmp->m_pkthdr.len -= prev_len_adj;
- }
- adapter->lmp->m_next = mp;
- adapter->lmp = adapter->lmp->m_next;
- adapter->fmp->m_pkthdr.len += len;
- }
-
- if (eop) {
- adapter->fmp->m_pkthdr.rcvif = ifp;
- ifp->if_ipackets++;
-
-#if __FreeBSD_version < 500000
- eh = mtod(adapter->fmp, struct ether_header *);
- /* Remove ethernet header from mbuf */
- m_adj(adapter->fmp, sizeof(struct ether_header));
-#ifndef __rtems__
- em_receive_checksum(adapter, current_desc,
- adapter->fmp);
- if (current_desc->status & E1000_RXD_STAT_VP)
- VLAN_INPUT_TAG(eh, adapter->fmp,
- (current_desc->special &
- E1000_RXD_SPC_VLAN_MASK));
- else
-#endif
- ether_input(ifp, eh, adapter->fmp);
-#else
-
- em_receive_checksum(adapter, current_desc,
- adapter->fmp);
- if (current_desc->status & E1000_RXD_STAT_VP)
- VLAN_INPUT_TAG(ifp, adapter->fmp,
- (current_desc->special &
- E1000_RXD_SPC_VLAN_MASK),
- adapter->fmp = NULL);
-
- if (adapter->fmp != NULL) {
- EM_UNLOCK(adapter);
- (*ifp->if_input)(ifp, adapter->fmp);
- EM_LOCK(adapter);
- }
-#endif
- adapter->fmp = NULL;
- adapter->lmp = NULL;
- }
- } else {
- adapter->dropped_pkts++;
- em_get_buf(i, adapter, mp);
- if (adapter->fmp != NULL)
- m_freem(adapter->fmp);
- adapter->fmp = NULL;
- adapter->lmp = NULL;
- }
-
- /* Zero out the receive descriptors status */
- current_desc->status = 0;
-
- /* Advance the E1000's Receive Queue #0 "Tail Pointer". */
- E1000_WRITE_REG(&adapter->hw, RDT, i);
-
- /* Advance our pointers to the next descriptor */
- if (++i == adapter->num_rx_desc) {
- i = 0;
- current_desc = adapter->rx_desc_base;
- } else
- current_desc++;
- }
- bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- adapter->next_rx_desc_to_check = i;
- return;
-}
-
-#ifndef __rtems__
-/*********************************************************************
- *
- * Verify that the hardware indicated that the checksum is valid.
- * Inform the stack about the status of checksum so that stack
- * doesn't spend time verifying the checksum.
- *
- *********************************************************************/
-static void
-em_receive_checksum(struct adapter *adapter,
- struct em_rx_desc *rx_desc,
- struct mbuf *mp)
-{
- /* 82543 or newer only */
- if ((adapter->hw.mac_type < em_82543) ||
- /* Ignore Checksum bit is set */
- (rx_desc->status & E1000_RXD_STAT_IXSM)) {
- mp->m_pkthdr.csum_flags = 0;
- return;
- }
-
- if (rx_desc->status & E1000_RXD_STAT_IPCS) {
- /* Did it pass? */
- if (!(rx_desc->errors & E1000_RXD_ERR_IPE)) {
- /* IP Checksum Good */
- mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
- mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
-
- } else {
- mp->m_pkthdr.csum_flags = 0;
- }
- }
-
- if (rx_desc->status & E1000_RXD_STAT_TCPCS) {
- /* Did it pass? */
- if (!(rx_desc->errors & E1000_RXD_ERR_TCPE)) {
- mp->m_pkthdr.csum_flags |=
- (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
- mp->m_pkthdr.csum_data = htons(0xffff);
- }
- }
-
- return;
-}
-
-
-static void
-em_enable_vlans(struct adapter *adapter)
-{
- uint32_t ctrl;
-
- E1000_WRITE_REG(&adapter->hw, VET, ETHERTYPE_VLAN);
-
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
-
- return;
-}
-
-static void
-em_disable_vlans(struct adapter *adapter)
-{
- uint32_t ctrl;
-
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
- ctrl &= ~E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
-
- return;
-}
-#endif
-
-static void
-em_enable_intr(struct adapter * adapter)
-{
- E1000_WRITE_REG(&adapter->hw, IMS, (IMS_ENABLE_MASK));
- return;
-}
-
-static void
-em_disable_intr(struct adapter *adapter)
-{
- /*
- * The first version of 82542 had an errata where when link was forced it
- * would stay up even up even if the cable was disconnected. Sequence errors
- * were used to detect the disconnect and then the driver would unforce the link.
- * This code in the in the ISR. For this to work correctly the Sequence error
- * interrupt had to be enabled all the time.
- */
-
- if (adapter->hw.mac_type == em_82542_rev2_0)
- E1000_WRITE_REG(&adapter->hw, IMC,
- (0xffffffff & ~E1000_IMC_RXSEQ));
- else
- E1000_WRITE_REG(&adapter->hw, IMC,
- 0xffffffff);
- return;
-}
-
-static int
-em_is_valid_ether_addr(u_int8_t *addr)
-{
- char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
-
- if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) {
- return (FALSE);
- }
-
- return(TRUE);
-}
-
-void
-em_write_pci_cfg(struct em_hw *hw,
- uint32_t reg,
- uint16_t *value)
-{
- pci_write_config(((struct em_osdep *)hw->back)->dev, reg,
- *value, 2);
-}
-
-void
-em_read_pci_cfg(struct em_hw *hw, uint32_t reg,
- uint16_t *value)
-{
- *value = pci_read_config(((struct em_osdep *)hw->back)->dev,
- reg, 2);
- return;
-}
-
-void
-em_pci_set_mwi(struct em_hw *hw)
-{
- pci_write_config(((struct em_osdep *)hw->back)->dev,
- PCIR_COMMAND,
- (hw->pci_cmd_word | CMD_MEM_WRT_INVALIDATE), 2);
- return;
-}
-
-void
-em_pci_clear_mwi(struct em_hw *hw)
-{
- pci_write_config(((struct em_osdep *)hw->back)->dev,
- PCIR_COMMAND,
- (hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE), 2);
- return;
-}
-
-uint32_t
-em_io_read(struct em_hw *hw, unsigned long port)
-{
- return(inl(port));
-}
-
-void
-em_io_write(struct em_hw *hw, unsigned long port, uint32_t value)
-{
-#ifndef __rtems__
- outl(port, value);
-#else
- /* everybody else has this the other way round! */
- outl(value, port);
-#endif
- return;
-}
-
-/*********************************************************************
-* 82544 Coexistence issue workaround.
-* There are 2 issues.
-* 1. Transmit Hang issue.
-* To detect this issue, following equation can be used...
-* SIZE[3:0] + ADDR[2:0] = SUM[3:0].
-* If SUM[3:0] is in between 1 to 4, we will have this issue.
-*
-* 2. DAC issue.
-* To detect this issue, following equation can be used...
-* SIZE[3:0] + ADDR[2:0] = SUM[3:0].
-* If SUM[3:0] is in between 9 to c, we will have this issue.
-*
-*
-* WORKAROUND:
-* Make sure we do not have ending address as 1,2,3,4(Hang) or 9,a,b,c (DAC)
-*
-*** *********************************************************************/
-static u_int32_t
-em_fill_descriptors (u_int64_t address,
- u_int32_t length,
- PDESC_ARRAY desc_array)
-{
- /* Since issue is sensitive to length and address.*/
- /* Let us first check the address...*/
- u_int32_t safe_terminator;
- if (length <= 4) {
- desc_array->descriptor[0].address = address;
- desc_array->descriptor[0].length = length;
- desc_array->elements = 1;
- return desc_array->elements;
- }
- safe_terminator = (u_int32_t)((((u_int32_t)address & 0x7) + (length & 0xF)) & 0xF);
- /* if it does not fall between 0x1 to 0x4 and 0x9 to 0xC then return */
- if (safe_terminator == 0 ||
- (safe_terminator > 4 &&
- safe_terminator < 9) ||
- (safe_terminator > 0xC &&
- safe_terminator <= 0xF)) {
- desc_array->descriptor[0].address = address;
- desc_array->descriptor[0].length = length;
- desc_array->elements = 1;
- return desc_array->elements;
- }
-
- desc_array->descriptor[0].address = address;
- desc_array->descriptor[0].length = length - 4;
- desc_array->descriptor[1].address = address + (length - 4);
- desc_array->descriptor[1].length = 4;
- desc_array->elements = 2;
- return desc_array->elements;
-}
-
-/**********************************************************************
- *
- * Update the board statistics counters.
- *
- **********************************************************************/
-static void
-em_update_stats_counters(struct adapter *adapter)
-{
- struct ifnet *ifp;
-
- if(adapter->hw.media_type == em_media_type_copper ||
- (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
- adapter->stats.symerrs += E1000_READ_REG(&adapter->hw, SYMERRS);
- adapter->stats.sec += E1000_READ_REG(&adapter->hw, SEC);
- }
- adapter->stats.crcerrs += E1000_READ_REG(&adapter->hw, CRCERRS);
- adapter->stats.mpc += E1000_READ_REG(&adapter->hw, MPC);
- adapter->stats.scc += E1000_READ_REG(&adapter->hw, SCC);
- adapter->stats.ecol += E1000_READ_REG(&adapter->hw, ECOL);
-
- adapter->stats.mcc += E1000_READ_REG(&adapter->hw, MCC);
- adapter->stats.latecol += E1000_READ_REG(&adapter->hw, LATECOL);
- adapter->stats.colc += E1000_READ_REG(&adapter->hw, COLC);
- adapter->stats.dc += E1000_READ_REG(&adapter->hw, DC);
- adapter->stats.rlec += E1000_READ_REG(&adapter->hw, RLEC);
- adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, XONRXC);
- adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, XONTXC);
- adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, XOFFRXC);
- adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, XOFFTXC);
- adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, FCRUC);
- adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, PRC64);
- adapter->stats.prc127 += E1000_READ_REG(&adapter->hw, PRC127);
- adapter->stats.prc255 += E1000_READ_REG(&adapter->hw, PRC255);
- adapter->stats.prc511 += E1000_READ_REG(&adapter->hw, PRC511);
- adapter->stats.prc1023 += E1000_READ_REG(&adapter->hw, PRC1023);
- adapter->stats.prc1522 += E1000_READ_REG(&adapter->hw, PRC1522);
- adapter->stats.gprc += E1000_READ_REG(&adapter->hw, GPRC);
- adapter->stats.bprc += E1000_READ_REG(&adapter->hw, BPRC);
- adapter->stats.mprc += E1000_READ_REG(&adapter->hw, MPRC);
- adapter->stats.gptc += E1000_READ_REG(&adapter->hw, GPTC);
-
- /* For the 64-bit byte counters the low dword must be read first. */
- /* Both registers clear on the read of the high dword */
-
- adapter->stats.gorcl += E1000_READ_REG(&adapter->hw, GORCL);
- adapter->stats.gorch += E1000_READ_REG(&adapter->hw, GORCH);
- adapter->stats.gotcl += E1000_READ_REG(&adapter->hw, GOTCL);
- adapter->stats.gotch += E1000_READ_REG(&adapter->hw, GOTCH);
-
- adapter->stats.rnbc += E1000_READ_REG(&adapter->hw, RNBC);
- adapter->stats.ruc += E1000_READ_REG(&adapter->hw, RUC);
- adapter->stats.rfc += E1000_READ_REG(&adapter->hw, RFC);
- adapter->stats.roc += E1000_READ_REG(&adapter->hw, ROC);
- adapter->stats.rjc += E1000_READ_REG(&adapter->hw, RJC);
-
- adapter->stats.torl += E1000_READ_REG(&adapter->hw, TORL);
- adapter->stats.torh += E1000_READ_REG(&adapter->hw, TORH);
- adapter->stats.totl += E1000_READ_REG(&adapter->hw, TOTL);
- adapter->stats.toth += E1000_READ_REG(&adapter->hw, TOTH);
-
- adapter->stats.tpr += E1000_READ_REG(&adapter->hw, TPR);
- adapter->stats.tpt += E1000_READ_REG(&adapter->hw, TPT);
- adapter->stats.ptc64 += E1000_READ_REG(&adapter->hw, PTC64);
- adapter->stats.ptc127 += E1000_READ_REG(&adapter->hw, PTC127);
- adapter->stats.ptc255 += E1000_READ_REG(&adapter->hw, PTC255);
- adapter->stats.ptc511 += E1000_READ_REG(&adapter->hw, PTC511);
- adapter->stats.ptc1023 += E1000_READ_REG(&adapter->hw, PTC1023);
- adapter->stats.ptc1522 += E1000_READ_REG(&adapter->hw, PTC1522);
- adapter->stats.mptc += E1000_READ_REG(&adapter->hw, MPTC);
- adapter->stats.bptc += E1000_READ_REG(&adapter->hw, BPTC);
-
- if (adapter->hw.mac_type >= em_82543) {
- adapter->stats.algnerrc +=
- E1000_READ_REG(&adapter->hw, ALGNERRC);
- adapter->stats.rxerrc +=
- E1000_READ_REG(&adapter->hw, RXERRC);
- adapter->stats.tncrs +=
- E1000_READ_REG(&adapter->hw, TNCRS);
- adapter->stats.cexterr +=
- E1000_READ_REG(&adapter->hw, CEXTERR);
- adapter->stats.tsctc +=
- E1000_READ_REG(&adapter->hw, TSCTC);
- adapter->stats.tsctfc +=
- E1000_READ_REG(&adapter->hw, TSCTFC);
- }
- ifp = &adapter->arpcom.ac_if;
-
- /* Fill out the OS statistics structure */
- ifp->if_ibytes = adapter->stats.gorcl;
- ifp->if_obytes = adapter->stats.gotcl;
- ifp->if_imcasts = adapter->stats.mprc;
- ifp->if_collisions = adapter->stats.colc;
-
- /* Rx Errors */
- ifp->if_ierrors =
- adapter->dropped_pkts +
- adapter->stats.rxerrc +
- adapter->stats.crcerrs +
- adapter->stats.algnerrc +
- adapter->stats.rlec +
- adapter->stats.mpc + adapter->stats.cexterr;
-
- /* Tx Errors */
- ifp->if_oerrors = adapter->stats.ecol + adapter->stats.latecol;
-
-}
-
-#ifndef __rtems__
-/**********************************************************************
- *
- * This routine is called only when em_display_debug_stats is enabled.
- * This routine provides a way to take a look at important statistics
- * maintained by the driver and hardware.
- *
- **********************************************************************/
-static void
-em_print_debug_info(struct adapter *adapter)
-{
- int unit = adapter->unit;
- uint8_t *hw_addr = adapter->hw.hw_addr;
-
- printf("em%d: Adapter hardware address = %p \n", unit, hw_addr);
- printf("em%d:CTRL = 0x%x\n", unit,
- E1000_READ_REG(&adapter->hw, CTRL));
- printf("em%d:RCTL = 0x%x PS=(0x8402)\n", unit,
- E1000_READ_REG(&adapter->hw, RCTL));
- printf("em%d:tx_int_delay = %d, tx_abs_int_delay = %d\n", unit,
- E1000_READ_REG(&adapter->hw, TIDV),
- E1000_READ_REG(&adapter->hw, TADV));
- printf("em%d:rx_int_delay = %d, rx_abs_int_delay = %d\n", unit,
- E1000_READ_REG(&adapter->hw, RDTR),
- E1000_READ_REG(&adapter->hw, RADV));
- printf("em%d: fifo workaround = %lld, fifo_reset = %lld\n", unit,
- (long long)adapter->tx_fifo_wrk_cnt,
- (long long)adapter->tx_fifo_reset_cnt);
- printf("em%d: hw tdh = %d, hw tdt = %d\n", unit,
- E1000_READ_REG(&adapter->hw, TDH),
- E1000_READ_REG(&adapter->hw, TDT));
- printf("em%d: Num Tx descriptors avail = %d\n", unit,
- adapter->num_tx_desc_avail);
- printf("em%d: Tx Descriptors not avail1 = %ld\n", unit,
- adapter->no_tx_desc_avail1);
- printf("em%d: Tx Descriptors not avail2 = %ld\n", unit,
- adapter->no_tx_desc_avail2);
- printf("em%d: Std mbuf failed = %ld\n", unit,
- adapter->mbuf_alloc_failed);
- printf("em%d: Std mbuf cluster failed = %ld\n", unit,
- adapter->mbuf_cluster_failed);
- printf("em%d: Driver dropped packets = %ld\n", unit,
- adapter->dropped_pkts);
-
- return;
-}
-#endif
-
-static void
-em_print_hw_stats(struct adapter *adapter)
-{
- int unit = adapter->unit;
-
- printf("em%d: Excessive collisions = %lld\n", unit,
- (long long)adapter->stats.ecol);
- printf("em%d: Symbol errors = %lld\n", unit,
- (long long)adapter->stats.symerrs);
- printf("em%d: Sequence errors = %lld\n", unit,
- (long long)adapter->stats.sec);
- printf("em%d: Defer count = %lld\n", unit,
- (long long)adapter->stats.dc);
-
- printf("em%d: Missed Packets = %lld\n", unit,
- (long long)adapter->stats.mpc);
- printf("em%d: Receive No Buffers = %lld\n", unit,
- (long long)adapter->stats.rnbc);
- printf("em%d: Receive length errors = %lld\n", unit,
- (long long)adapter->stats.rlec);
- printf("em%d: Receive errors = %lld\n", unit,
- (long long)adapter->stats.rxerrc);
- printf("em%d: Crc errors = %lld\n", unit,
- (long long)adapter->stats.crcerrs);
- printf("em%d: Alignment errors = %lld\n", unit,
- (long long)adapter->stats.algnerrc);
- printf("em%d: Carrier extension errors = %lld\n", unit,
- (long long)adapter->stats.cexterr);
-
- printf("em%d: XON Rcvd = %lld\n", unit,
- (long long)adapter->stats.xonrxc);
- printf("em%d: XON Xmtd = %lld\n", unit,
- (long long)adapter->stats.xontxc);
- printf("em%d: XOFF Rcvd = %lld\n", unit,
- (long long)adapter->stats.xoffrxc);
- printf("em%d: XOFF Xmtd = %lld\n", unit,
- (long long)adapter->stats.xofftxc);
-
- printf("em%d: Good Packets Rcvd = %lld\n", unit,
- (long long)adapter->stats.gprc);
- printf("em%d: Good Packets Xmtd = %lld\n", unit,
- (long long)adapter->stats.gptc);
-
- return;
-}
-
-#ifndef __rtems__
-static int
-em_sysctl_debug_info(SYSCTL_HANDLER_ARGS)
-{
- int error;
- int result;
- struct adapter *adapter;
-
- result = -1;
- error = sysctl_handle_int(oidp, &result, 0, req);
-
- if (error || !req->newptr)
- return (error);
-
- if (result == 1) {
- adapter = (struct adapter *)arg1;
- em_print_debug_info(adapter);
- }
-
- return error;
-}
-
-static int
-em_sysctl_stats(SYSCTL_HANDLER_ARGS)
-{
- int error;
- int result;
- struct adapter *adapter;
-
- result = -1;
- error = sysctl_handle_int(oidp, &result, 0, req);
-
- if (error || !req->newptr)
- return (error);
-
- if (result == 1) {
- adapter = (struct adapter *)arg1;
- em_print_hw_stats(adapter);
- }
-
- return error;
-}
-
-static int
-em_sysctl_int_delay(SYSCTL_HANDLER_ARGS)
-{
- struct em_int_delay_info *info;
- struct adapter *adapter;
- u_int32_t regval;
- int error;
- int usecs;
- int ticks;
- int s;
-
- info = (struct em_int_delay_info *)arg1;
- adapter = info->adapter;
- usecs = info->value;
- error = sysctl_handle_int(oidp, &usecs, 0, req);
- if (error != 0 || req->newptr == NULL)
- return error;
- if (usecs < 0 || usecs > E1000_TICKS_TO_USECS(65535))
- return EINVAL;
- info->value = usecs;
- ticks = E1000_USECS_TO_TICKS(usecs);
-
- s = splimp();
- regval = E1000_READ_OFFSET(&adapter->hw, info->offset);
- regval = (regval & ~0xffff) | (ticks & 0xffff);
- /* Handle a few special cases. */
- switch (info->offset) {
- case E1000_RDTR:
- case E1000_82542_RDTR:
- regval |= E1000_RDT_FPDB;
- break;
- case E1000_TIDV:
- case E1000_82542_TIDV:
- if (ticks == 0) {
- adapter->txd_cmd &= ~E1000_TXD_CMD_IDE;
- /* Don't write 0 into the TIDV register. */
- regval++;
- } else
- adapter->txd_cmd |= E1000_TXD_CMD_IDE;
- break;
- }
- E1000_WRITE_OFFSET(&adapter->hw, info->offset, regval);
- splx(s);
- return 0;
-}
-
-static void
-em_add_int_delay_sysctl(struct adapter *adapter, const char *name,
- const char *description, struct em_int_delay_info *info,
- int offset, int value)
-{
- info->adapter = adapter;
- info->offset = offset;
- info->value = value;
- SYSCTL_ADD_PROC(device_get_sysctl_ctx(adapter->dev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
- OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW,
- info, 0, em_sysctl_int_delay, "I", description);
-}
-#endif
-
-#ifdef __rtems__
-/* Initialize bare minimals so we can check the phy link status */
-int
-em_hw_early_init(device_t dev)
-{
-struct adapter *adapter = device_get_softc(dev);
- adapter->dev = dev;
- adapter->osdep.dev = dev;
- em_identify_hardware(adapter);
- return em_allocate_pci_resources(adapter);
-}
-#endif