summaryrefslogtreecommitdiffstats
path: root/bsd_eth_drivers/if_em/e1000_osdep.c
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 /bsd_eth_drivers/if_em/e1000_osdep.c
parent2011-07-20 Till Straumann <Till.Straumann@TU-Berlin.de> (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).
Diffstat (limited to 'bsd_eth_drivers/if_em/e1000_osdep.c')
-rw-r--r--bsd_eth_drivers/if_em/e1000_osdep.c95
1 files changed, 85 insertions, 10 deletions
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);
+}