From 88f653ad2e278a42c3c1c480022820abdeea233f Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Wed, 20 Jul 2011 17:25:21 +0000 Subject: 2011-07-20 Till Straumann * if_em/Makefile.am, if_em/e1000_osdep.h, if_em/e1000_osdep.c, if_em/if_em.c: added e1000_osdep.c which implements all os-dependent parts in a bsdnet-agnostic fashion. Hence, the low-level driver can be used w/o bsdnet. FIXES: dependency on bsdnet initialization; PCI bus header was not initialized when not used via bsdnet (lanIpBasic driver crashed). --- bsd_eth_drivers/if_em/Makefile.am | 5 +- bsd_eth_drivers/if_em/e1000_osdep.c | 158 ++++++++++++++++++++++++++++++++++++ bsd_eth_drivers/if_em/e1000_osdep.h | 91 ++++++++++++--------- bsd_eth_drivers/if_em/if_em.c | 14 ++++ 4 files changed, 230 insertions(+), 38 deletions(-) create mode 100644 bsd_eth_drivers/if_em/e1000_osdep.c (limited to 'bsd_eth_drivers/if_em') diff --git a/bsd_eth_drivers/if_em/Makefile.am b/bsd_eth_drivers/if_em/Makefile.am index a795ef8..f1e26b0 100644 --- a/bsd_eth_drivers/if_em/Makefile.am +++ b/bsd_eth_drivers/if_em/Makefile.am @@ -4,6 +4,7 @@ AUTOMAKE_OPTIONS=foreign include $(top_srcdir)/rtems-pre.am libif_em_a_SOURCES = if_em.c +libif_em_a_SOURCES += e1000_osdep.c libif_em_a_SOURCES += e1000_80003es2lan.c e1000_82540.c e1000_82541.c libif_em_a_SOURCES += e1000_82543.c e1000_82571.c e1000_82575.c libif_em_a_SOURCES += e1000_api.c e1000_mac.c e1000_manage.c @@ -15,6 +16,8 @@ libif_em_a_SOURCES += e1000_defines.h e1000_hw.h e1000_ich8lan.h libif_em_a_SOURCES += e1000_mac.h e1000_manage.h e1000_nvm.h libif_em_a_SOURCES += e1000_osdep.h e1000_phy.h e1000_regs.h if_em.h +if_em.$(OBJEXT): AM_SRC_CPPFLAGS=-D_KERNEL + EXTRA_libif_em_a_SOURCES = e1000_82542.c e1000_ich8lan.c CPPFLAGS_82542_SUPPORT_NO = -DNO_82542_SUPPORT @@ -31,10 +34,10 @@ libif_em_a_DEPENDENCIES = $(libif_em_a_LIBADD) lib_LIBRARIES = libif_em.a -AM_CPPFLAGS += -D_KERNEL AM_CPPFLAGS += -I$(srcdir) AM_CPPFLAGS += -I$(srcdir)/../libbsdport -I../libbsdport -I../libbsdport/dummyheaders AM_CPPFLAGS += $(CPPFLAGS_82542_SUPPORT_$(ENBL_82542_SUPPORT)) AM_CPPFLAGS += $(CPPFLAGS_ICH8LAN_SUPPORT_$(ENBL_ICH8LAN_SUPPORT)) +AM_CPPFLAGS += $(AM_SRC_CPPFLAGS) include $(top_srcdir)/rtems.am diff --git a/bsd_eth_drivers/if_em/e1000_osdep.c b/bsd_eth_drivers/if_em/e1000_osdep.c new file mode 100644 index 0000000..781e99d --- /dev/null +++ b/bsd_eth_drivers/if_em/e1000_osdep.c @@ -0,0 +1,158 @@ +/************************************************************************** + +Copyright (c) 2001-2007, 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. + +***************************************************************************/ + +/* + * NOTE: the following routines using the e1000 + * naming style are provided to the shared + * code which expects that rather than 'em' + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef PCIR_COMMAND +#define PCIR_COMMAND PCI_COMMAND +#endif + +void +e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) +{ +struct e1000_pcisig *s = hw->back; + pci_write_config_word( s->bus, s->dev, s->fun, reg, *value ); +} + +void +e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) +{ +struct e1000_pcisig *s = hw->back; + pci_read_config_word( s->bus, s->dev, s->fun, reg, value ); +} + +void +e1000_pci_set_mwi(struct e1000_hw *hw) +{ +struct e1000_pcisig *s = hw->back; + pci_write_config_word( s->bus, s->dev, s->fun, PCIR_COMMAND, + (hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE) ); +} + +void +e1000_pci_clear_mwi(struct e1000_hw *hw) +{ +struct e1000_pcisig *s = hw->back; + pci_write_config_word( s->bus, s->dev, s->fun, PCIR_COMMAND, + (hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE) ); +} + +/* + * Read the PCI Express capabilities + */ +int32_t +e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) +{ + int32_t error = E1000_SUCCESS; + uint16_t cap_off; + + switch (hw->mac.type) { + + case e1000_82571: + case e1000_82572: + case e1000_82573: + case e1000_80003es2lan: + cap_off = 0xE0; + e1000_read_pci_cfg(hw, cap_off + reg, value); + break; + default: + error = ~E1000_NOT_IMPLEMENTED; + break; + } + + return (error); +} + +int32_t +e1000_alloc_zeroed_dev_spec_struct(struct e1000_hw *hw, uint32_t size) +{ + return (hw->dev_spec = calloc(1, size)) ? 0 : ENOMEM; +} + +void +e1000_free_dev_spec_struct(struct e1000_hw *hw) +{ + free ( hw->dev_spec ); +} + + +void +e1000_udelay(unsigned usecs) +{ +rtems_interval clock_f, ticks; +uint64_t tmp; +struct timespec then, now; + rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &clock_f ); + + /* round up to next tick: + floor( f*T + .5 ) = floor( f*T_us/1e6 + 0.5 ) + = floor( (f * T_us + 5e5) / 1e6 ) + */ + tmp = (uint64_t)clock_f * (uint64_t)usecs; + + if ( tmp < 500000ULL ) { + /* less than half a tick -- busy wait */ + clock_gettime( CLOCK_REALTIME, &then ); + then.tv_sec += usecs/1000000; + then.tv_nsec += (usecs % 1000000)*1000; + if ( then.tv_nsec >= 1000000000 ) { + then.tv_nsec -= 1000000000; + then.tv_sec++; + } + + do { + clock_gettime( CLOCK_REALTIME, &now ); + + } while ( now.tv_sec < then.tv_sec || + (now.tv_sec == then.tv_sec && now.tv_nsec < then.tv_nsec) ); + } else { + tmp += 500000ULL; + tmp /= 1000000ULL; + + ticks = (rtems_interval)tmp; + + rtems_task_wake_after( ticks ); + } +} diff --git a/bsd_eth_drivers/if_em/e1000_osdep.h b/bsd_eth_drivers/if_em/e1000_osdep.h index 96a7d84..134c4cc 100644 --- a/bsd_eth_drivers/if_em/e1000_osdep.h +++ b/bsd_eth_drivers/if_em/e1000_osdep.h @@ -41,31 +41,13 @@ POSSIBILITY OF SUCH DAMAGE. #include #include /* for non-_KERNEL boolean_t :-( */ -#ifdef _KERNEL -#ifndef __INSIDE_RTEMS_BSD_TCPIP_STACK__ -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ -#endif -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ASSERT(x) if(!(x)) panic("EM: x") - /* The happy-fun DELAY macro is defined in /usr/src/sys/i386/include/clock.h */ -#define usec_delay(x) DELAY(x) -#define msec_delay(x) DELAY(1000*(x)) +#define usec_delay(x) e1000_udelay(x) +#define msec_delay(x) e1000_udelay(1000*(x)) /* TODO: Should we be paranoid about delaying in interrupt context? */ -#define msec_delay_irq(x) DELAY(1000*(x)) -#include +#define msec_delay_irq(x) msec_delay(x) + +void e1000_udelay(unsigned); #define MSGOUT(S, A, B) printf(S "\n", A, B) #define DEBUGFUNC(F) DEBUGOUT(F); @@ -75,22 +57,8 @@ POSSIBILITY OF SUCH DAMAGE. #define DEBUGOUT3(S,A,B,C) #define DEBUGOUT7(S,A,B,C,D,E,F,G) -#include - -struct e1000_osdep -{ - uint32_t mem_bus_space_handle; - uint32_t io_bus_space_handle; - uint32_t flash_bus_space_handle; - /* these are currently unused; present for freebsd compatibility only */ - uint32_t mem_bus_space_tag; - uint32_t io_bus_space_tag; - uint32_t flash_bus_space_tag; - device_t dev; -}; #define STATIC static -#endif #ifndef FALSE #define FALSE 0 @@ -118,6 +86,12 @@ typedef int8_t s8 ; typedef volatile uint32_t __uint32_va_t __attribute__((may_alias)); typedef volatile uint16_t __uint16_va_t __attribute__((may_alias)); +struct e1000_pcisig { + uint16_t bus; + uint8_t dev; + uint8_t fun; +}; + #ifdef NO_82542_SUPPORT #define E1000_REGISTER(hw, reg) reg #else @@ -218,6 +192,49 @@ static inline void __outport_dword(unsigned long base, uint32_t off, uint32_t va #define USE_LIBBSDPORT_IO #endif +#if defined(USE_LIBBSDPORT_IO) && !defined(_KERNEL) +#define _KERNEL +#endif + +#ifdef _KERNEL +#ifndef __INSIDE_RTEMS_BSD_TCPIP_STACK__ +#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ASSERT(x) if(!(x)) panic("EM: x") + +#include + +struct e1000_osdep +{ + /* struct e1000_pcisig MUST be first since + * 'back' pointer is cast to (struct e1000_pcisig *) + * in e1000_osdep.c! + */ + struct e1000_pcisig pcisig; + uint32_t mem_bus_space_handle; + uint32_t io_bus_space_handle; + uint32_t flash_bus_space_handle; + /* these are currently unused; present for freebsd compatibility only */ + uint32_t mem_bus_space_tag; + uint32_t io_bus_space_tag; + uint32_t flash_bus_space_tag; + device_t dev; +}; +#endif + #ifdef USE_LIBBSDPORT_IO #define USE_EXPLICIT_BUSTAGS diff --git a/bsd_eth_drivers/if_em/if_em.c b/bsd_eth_drivers/if_em/if_em.c index 05d4216..9d2f8d5 100644 --- a/bsd_eth_drivers/if_em/if_em.c +++ b/bsd_eth_drivers/if_em/if_em.c @@ -441,6 +441,18 @@ em_probe(device_t dev) INIT_DEBUGOUT("em_probe: begin"); +#ifdef __rtems__ + /* copy PCI signature to the low-level (bsd-agnostic) support + * struct. + */ + { + struct adapter *adapter = device_get_softc(dev); + adapter->osdep.pcisig.bus = dev->bushdr.pci.bus; + adapter->osdep.pcisig.dev = dev->bushdr.pci.dev; + adapter->osdep.pcisig.fun = dev->bushdr.pci.fun; + } +#endif + pci_vendor_id = pci_get_vendor(dev); if (pci_vendor_id != EM_VENDOR_ID) return (ENXIO); @@ -4782,6 +4794,7 @@ em_is_valid_ether_addr(uint8_t *addr) return (TRUE); } +#ifndef __rtems__ /* * NOTE: the following routines using the e1000 * naming style are provided to the shared @@ -4864,6 +4877,7 @@ e1000_free_dev_spec_struct(struct e1000_hw *hw) free(hw->dev_spec, M_DEVBUF); return; } +#endif /* * Enable PCI Wake On Lan capability -- cgit v1.2.3