summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2011-07-21 23:24:54 +0000
committerTill Straumann <strauman@slac.stanford.edu>2011-07-21 23:24:54 +0000
commitf552470eec83d3587c603922404ea5115c6963a7 (patch)
treef12fca8ecbff140b90683c083795da5299f89452
parent88f653ad2e278a42c3c1c480022820abdeea233f (diff)
downloadlibbsdport-f552470eec83d3587c603922404ea5115c6963a7.tar.bz2
2011-07-21 Till Straumann <Till.Straumann@TU-Berlin.de>
* 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).
-rw-r--r--bsd_eth_drivers/ChangeLog8
-rw-r--r--bsd_eth_drivers/if_em/e1000_osdep.c95
-rw-r--r--bsd_eth_drivers/if_em/e1000_osdep.h15
-rw-r--r--bsd_eth_drivers/if_em/if_em.c36
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 <Till.Straumann@TU-Berlin.de>
+
+ * 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 <Till.Straumann@TU-Berlin.de>
* 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<N_E1K_DEVS; i++ ) {
+ if ( PCISIG_INVAL == e1k_devs[i] ) {
+ j = i;
+ } else if ( sig == e1k_devs[i] ) {
+ j = -1;
+ break;
+ }
+ }
+ if ( j >= 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; i<N_E1K_DEVS; i++ ) {
+ if ( sig == e1k_devs[i] ) {
+ e1k_devs[i] = PCISIG_INVAL;
+ if ( s_p )
+ s_p->sig = 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);
}