From f552470eec83d3587c603922404ea5115c6963a7 Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Thu, 21 Jul 2011 23:24:54 +0000 Subject: 2011-07-21 Till Straumann * if_em/e1000_osdep.h, if_em/e1000_osdep.c, if_em/if_em.c: added e1000_register()/e1000_unregister() to keep track of devices that are 'in-use'. This allows for sharing the low-level code between bsdnet and standalone drivers (e.g., for PtP GigE links). --- bsd_eth_drivers/ChangeLog | 8 ++++ bsd_eth_drivers/if_em/e1000_osdep.c | 95 +++++++++++++++++++++++++++++++++---- bsd_eth_drivers/if_em/e1000_osdep.h | 15 ++++-- bsd_eth_drivers/if_em/if_em.c | 36 +++++++++----- 4 files changed, 129 insertions(+), 25 deletions(-) diff --git a/bsd_eth_drivers/ChangeLog b/bsd_eth_drivers/ChangeLog index 8d56291..46fb31e 100644 --- a/bsd_eth_drivers/ChangeLog +++ b/bsd_eth_drivers/ChangeLog @@ -1,3 +1,11 @@ +2011-07-21 Till Straumann + + * if_em/e1000_osdep.h, if_em/e1000_osdep.c, if_em/if_em.c: + added e1000_register()/e1000_unregister() to keep track of + devices that are 'in-use'. This allows for sharing the low-level + code between bsdnet and standalone drivers (e.g., for PtP + GigE links). + 2011-07-20 Till Straumann * if_em/Makefile.am, if_em/e1000_osdep.h, if_em/e1000_osdep.c, diff --git a/bsd_eth_drivers/if_em/e1000_osdep.c b/bsd_eth_drivers/if_em/e1000_osdep.c index 781e99d..eec749b 100644 --- a/bsd_eth_drivers/if_em/e1000_osdep.c +++ b/bsd_eth_drivers/if_em/e1000_osdep.c @@ -49,34 +49,57 @@ POSSIBILITY OF SUCH DAMAGE. #define PCIR_COMMAND PCI_COMMAND #endif +#define PCISIG_INVAL 0xffffffff + +#define PCISIG_MK(b,d,f) ( ((b)<<8) | (((d)&0x1f)<<3) | ((f)&7) ) + +#define PCISIG_BUS(sig) ( ((sig) >> 8) & 0xffffff ) +#define PCISIG_DEV(sig) ( ((sig) >> 3) & 0x1f ) +#define PCISIG_FUN(sig) ( (sig) & 0x07 ) + + +static uint32_t e1k_devs[]={ + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL, + PCISIG_INVAL +}; + +#define N_E1K_DEVS (sizeof(e1k_devs)/sizeof(e1k_devs[0])) + 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 ); +struct e1000_pcisig *s_p = hw->back; +uint32_t s = s_p->sig; + + pci_write_config_word( PCISIG_BUS(s), PCISIG_DEV(s), PCISIG_FUN(s), 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 ); +struct e1000_pcisig *s_p = hw->back; +uint32_t s = s_p->sig; + pci_read_config_word( PCISIG_BUS(s), PCISIG_DEV(s), PCISIG_FUN(s), 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) ); +uint16_t v = (hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE); + e1000_write_pci_cfg( hw, PCIR_COMMAND, &v ); } 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) ); +uint16_t v = (hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE); + e1000_write_pci_cfg( hw, PCIR_COMMAND, &v ); } /* @@ -115,6 +138,7 @@ void e1000_free_dev_spec_struct(struct e1000_hw *hw) { free ( hw->dev_spec ); + hw->dev_spec = 0; } @@ -156,3 +180,54 @@ struct timespec then, now; rtems_task_wake_after( ticks ); } } + +int +e1000_register(struct e1000_pcisig *s_p, unsigned b, unsigned d, unsigned f ) +{ +int i,j,key; +uint32_t sig = PCISIG_MK(b,d,f); + + if ( PCISIG_INVAL == sig ) + return -1; + + j = -1; + + rtems_interrupt_disable(key); + for ( i = 0; i= 0 ) { + e1k_devs[j] = sig; + if ( s_p ) + s_p->sig = sig; + } + rtems_interrupt_enable(key); + + return j < 0; +} + +void +e1000_unregister(struct e1000_pcisig *s_p) +{ +int i,key; +uint32_t sig = s_p ? s_p->sig : PCISIG_INVAL; + + if ( PCISIG_INVAL == sig ) + return; + + rtems_interrupt_disable(key); + for ( i = 0; isig = PCISIG_INVAL; + break; + } + } + rtems_interrupt_enable(key); +} diff --git a/bsd_eth_drivers/if_em/e1000_osdep.h b/bsd_eth_drivers/if_em/e1000_osdep.h index 134c4cc..c6796f1 100644 --- a/bsd_eth_drivers/if_em/e1000_osdep.h +++ b/bsd_eth_drivers/if_em/e1000_osdep.h @@ -87,11 +87,20 @@ 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; + uint32_t sig; }; +/* Register an instance; if this returns nonzero + * then registration failed and the device with + * the pci signature passed in MUST NOT be used + * (since it is already in use by another driver). + */ +int +e1000_register(struct e1000_pcisig *sig_p_out, unsigned bus, unsigned dev, unsigned fun); + +void +e1000_unregister(struct e1000_pcisig *sig_p); + #ifdef NO_82542_SUPPORT #define E1000_REGISTER(hw, reg) reg #else diff --git a/bsd_eth_drivers/if_em/if_em.c b/bsd_eth_drivers/if_em/if_em.c index 9d2f8d5..f0e06d6 100644 --- a/bsd_eth_drivers/if_em/if_em.c +++ b/bsd_eth_drivers/if_em/if_em.c @@ -441,18 +441,6 @@ 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); @@ -471,6 +459,22 @@ em_probe(device_t dev) ((pci_subdevice_id == ent->subdevice_id) || (ent->subdevice_id == PCI_ANY_ID))) { +#ifdef __rtems__ + /* Copy PCI signature to the low-level (bsd-agnostic) + * support struct and register with ll-support. This + * step also detects if the device is already in use. + */ + { + struct adapter *adapter = device_get_softc(dev); + + if ( e1000_register( &adapter->osdep.pcisig, + dev->bushdr.pci.bus, + dev->bushdr.pci.dev, + dev->bushdr.pci.fun ) ) { + return (EBUSY); + } + } +#endif sprintf(adapter_name, "%s %s", em_strings[ent->index], em_driver_version); @@ -835,6 +839,10 @@ err_pci: em_free_pci_resources(adapter); EM_LOCK_DESTROY(adapter); +#ifdef __rtems__ + e1000_unregister( &adapter->osdep.pcisig ); +#endif + return (error); } @@ -910,6 +918,10 @@ em_detach(device_t dev) EM_LOCK_DESTROY(adapter); +#ifdef __rtems__ + e1000_unregister( &adapter->osdep.pcisig ); +#endif + return (0); } -- cgit v1.2.3