if_i21143.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,882 行 · 第 1/5 页
C
1,882 行
static int initialized = 0; // only probe PCI et al *once*
struct eth_drv_sc *sc;
struct i21143 *p_i21143;
cyg_uint8 mac_address[ETHER_ADDR_LEN];
#ifdef DEBUG
diag_printf("intel_i21143_init\n");
#endif
sc = (struct eth_drv_sc *)(ndp->device_instance);
p_i21143 = (struct i21143 *)(sc->driver_private);
IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
diag_printf( "Bad device private pointer %x\n", sc->driver_private );
#endif
return 0;
}
CHECK_NDP_SC_LINK();
p_i21143->ndp = (void *)ndp;
if ( 0 == initialized++ ) {
// then this is the first time ever:
if ( ! pci_init_find_21143s() ) {
#ifdef DEBUG
diag_printf( "pci_init_find_21143s failed" );
#endif
return 0;
}
}
// If this device is not present, exit
if (0 == p_i21143->found)
return 0;
p_i21143->mac_addr_ok = 0;
if ( p_i21143->hardwired_esa )
eth_set_mac_address( p_i21143, NULL ); // use that already there
// (actually a NOP because !active)
else {
int ee_addrbits;
int val[3];
int good = 0;
ee_addrbits = get_eeprom_size( p_i21143->io_address );
#ifdef DEBUG_EE
diag_printf( "EEPROM size = %d\n", ee_addrbits );
#endif
if ( 6 == ee_addrbits || 8 == ee_addrbits ) {
int i;
for ( i = 0; i < 3; i++ ) {
val[i] = read_eeprom_word( p_i21143->io_address,
ee_addrbits,
i );
#ifdef DEBUG_EE
diag_printf( "EEPROM: word at %04x = %04x\n", i, val[i] );
#endif
}
if ( 0x0000 != (val[0] | val[1] | val[2] ) && // some nonzero bits
0xffff != (val[0] & val[1] & val[2] ) && // not all ones
0x0000 == (val[0] & 0x80) ) { // not multicast
mac_address[0] = val[0] & 0xff;
mac_address[1] = val[0] >> 8;
mac_address[2] = val[1] & 0xff;
mac_address[3] = val[1] >> 8;
mac_address[4] = val[2] & 0xff;
mac_address[5] = val[2] >> 8;
good = 1;
#ifdef DEBUG_MAC
diag_printf( "EEPROM ESA OK: %04x %04x %04x\n",
val[0], val[1], val[2] );
#endif
}
}
if ( !good ) {
// Invent one
mac_address[0] = 0x01;
mac_address[1] = 0x23;
mac_address[2] = 0x45;
mac_address[3] = 0x67;
mac_address[4] = 0x98;
mac_address[5] = 0x76;
}
// Just copy into the structure - not into hardware 'cos !active
eth_set_mac_address( p_i21143, &mac_address[0] );
}
#if defined( DEBUG ) || defined( DEBUG_MAC )
diag_printf("MAC Address %s, ESA = %02X %02X %02X %02X %02X %02X\n",
p_i21143->mac_addr_ok ? "OK" : "**BAD**",
p_i21143->mac_address[0],
p_i21143->mac_address[1],
p_i21143->mac_address[2],
p_i21143->mac_address[3],
p_i21143->mac_address[4],
p_i21143->mac_address[5]);
#endif
// Initialize upper level driver
if ( p_i21143->mac_addr_ok )
(sc->funs->eth_drv->init)(sc, &(p_i21143->mac_address[0]) );
else
(sc->funs->eth_drv->init)(sc, NULL );
return (1);
}
// ------------------------------------------------------------------------
//
// Function : i21143_start
//
// ------------------------------------------------------------------------
static void
i21143_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags )
{
struct i21143 *p_i21143;
cyg_uint32 ioaddr;
cyg_uint32 l;
#ifdef CYGPKG_NET
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif
p_i21143 = (struct i21143 *)sc->driver_private;
ioaddr = p_i21143->io_address; // get 21143's I/O address
IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
diag_printf( "i21143_start: Bad device pointer %x\n", p_i21143 );
#endif
return;
}
if ( ! p_i21143->mac_addr_ok ) {
#ifdef DEBUG
diag_printf("i21143_start %d: invalid MAC address, "
"can't bring up interface\n",
p_i21143->index );
#endif
return;
}
#ifdef DEBUG
diag_printf( "i21143_start: enters\n" );
#endif
if ( p_i21143->active )
i21143_stop( sc );
// Update the cached copy of the status reg just in case
l = i21143_status( p_i21143 );
if ( l != p_i21143->line_status ) {
// It has changed!
i21143_reset(p_i21143); // sets line_status itself
}
// Enable device
p_i21143->active = 1;
// Initialize tx status
p_i21143->tx_endbuf = NO_TX_IN_PROGRESS;
eth_set_mac_address( p_i21143, NULL ); // to put it in the device
// After eth_set_mac_address() initialize the data structs for use:
InitRxRing( p_i21143 );
InitTxRing( p_i21143 );
// Enable promiscuous mode if requested.
i21143_configure(p_i21143, 0
#ifdef CYGPKG_NET
|| !!(ifp->if_flags & IFF_PROMISC)
#endif
#ifdef ETH_DRV_FLAGS_PROMISC_MODE
|| !!(flags & ETH_DRV_FLAGS_PROMISC_MODE)
#endif
);
#ifdef DEBUG
{
int status = p_i21143->line_status;
diag_printf("i21143_start %d flg %x Link = %s, %s Mbps, %s Duplex\n",
p_i21143->index,
*(int *)p_i21143,
(GEN_STATUS_LINK & status) ? "Up" : "Down",
(GEN_STATUS_100MBPS & status) ? "100" : "10",
(GEN_STATUS_FDX & status) ? "Full" : "Half");
}
#endif
// Load pointer to Rx Ring and enable receiver
OUTL( CYGHWR_PCI_VIRT_TO_BUS( (cyg_uint32)p_i21143->rx_ring ), CSR_RXBASE );
// Enable receive interrupts
l = INL( CSR_INTR_ENABLE );
l |= 0
| CSR_STATUS_NIS
| CSR_STATUS_AIS
// CSR_STATUS_ERI
// CSR_STATUS_FBE
// CSR_STATUS_LNF
// CSR_STATUS_GTE
// CSR_STATUS_ETI
// CSR_STATUS_RWT
| CSR_STATUS_RX_STOPPED
| CSR_STATUS_RBU
| CSR_STATUS_RX_INTR
// CSR_STATUS_UNF
// CSR_STATUS_LNP_ANC
// CSR_STATUS_TJT
| CSR_STATUS_TBU
| CSR_STATUS_TX_STOPPED
| CSR_STATUS_TX_INTR
;
OUTL( l, CSR_INTR_ENABLE );
// and start the receiver
l = INL( CSR_OPMODE );
l |= (CSR_OPMODE_RX_START);
OUTL( l, CSR_OPMODE );
INCR_STAT( rx_restart );
#ifdef DEBUG_DUMP_REGS
debug_dump_regs( ioaddr, BOTH );
#endif
}
// ------------------------------------------------------------------------
//
// Function : i21143_status
//
// ------------------------------------------------------------------------
int
i21143_status( struct i21143* p_i21143 )
{
int status;
int i, j;
cyg_uint32 ioaddr;
IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
diag_printf( "i21143_status: Bad device pointer %x\n", p_i21143 );
#endif
return 0;
}
ioaddr = p_i21143->io_address; // get 21143's I/O address
// Some of these bits latch and only reflect "the truth" on a 2nd reading.
// So read and discard.
status = mii_read_register( ioaddr, PHY_CONTROL_REG );
status = mii_read_register( ioaddr, PHY_STATUS_REG );
// Use the "and" of the local and remote capabilities words to infer
// what is selected:
status = 0;
i = mii_read_register( ioaddr, PHY_STATUS_REG );
if ( PHY_STATUS_LINK_OK & i )
status |= GEN_STATUS_LINK;
i = mii_read_register( ioaddr, PHY_AUTONEG_ADVERT );
j = mii_read_register( ioaddr, PHY_AUTONEG_REMOTE );
p_i21143->phy_autoneg_remote = j;
#if defined( DEBUG_TRAFFIC ) || defined( DEBUG_IOCTL )
diag_printf( "MII: capabilities are %04x, %04x; common %04x\n",
i, j, i & j );
#endif
j &= i; // select only common capabilities
if ( (PHY_AUTONEG_100BASET4 |
PHY_AUTONEG_100BASETX_FDX |
PHY_AUTONEG_100BASETX_HDX) & j )
status |= GEN_STATUS_100MBPS;
if ( (PHY_AUTONEG_100BASETX_FDX | PHY_AUTONEG_10BASET_FDX) & j )
status |= GEN_STATUS_FDX;
return status;
}
int
i21143_status_changed( struct i21143* p_i21143 )
{
cyg_uint32 ioaddr;
int j;
ioaddr = p_i21143->io_address; // get 21143's I/O address
j = mii_read_register( ioaddr, PHY_AUTONEG_REMOTE );
return ( j != p_i21143->phy_autoneg_remote );
}
// ------------------------------------------------------------------------
//
// Function : i21143_stop
//
// ------------------------------------------------------------------------
static void
i21143_stop( struct eth_drv_sc *sc )
{
struct i21143 *p_i21143;
p_i21143 = (struct i21143 *)sc->driver_private;
IF_BAD_21143( p_i21143 ) {
#ifdef DEBUG
diag_printf( "i21143_stop: Bad device pointer %x\n", p_i21143 );
#endif
return;
}
#ifdef DEBUG_STARTSTOPRESET
diag_printf("i21143_stop %d flg %x\n", p_i21143->index, *(int *)p_i21143 );
#endif
p_i21143->active = 0; // stop people tormenting it
if ( NO_TX_IN_PROGRESS != p_i21143->tx_endbuf) {
cyg_uint32 key;
CYG_ASSERT( TX_DESCRIPTORS > p_i21143->tx_endbuf, "tx_endbuf range" );
key = p_i21143->tx_keys[ 0 ];
// Common "done" code - key nonzero => report done
if (key) {
p_i21143->tx_keys[ 0 ] = 0;
p_i21143->tx_endbuf = NO_TX_IN_PROGRESS;
// Then tell the stack we are done:
INCR_STAT( tx_complete );
(sc->funs->eth_drv->tx_done)( sc, key, 0 );
}
}
i21143_reset(p_i21143); // that should stop it
}
// ------------------------------------------------------------------------
//
// Function : InitRxRing
//
// ------------------------------------------------------------------------
static void
InitRxRing(struct i21143* p_i21143)
{
int i;
volatile BUFDES *bp;
p_i21143->rx_ring =
(BUFDES *)CYGHWR_CACHED_TO_UNCACHED( &(p_i21143->_rx[0]) );
bp = p_i21143->rx_ring;
for ( i = 0 ; i < RX_DESCRIPTORS; i++ ) {
bp->des0 = DES0_STATUS_OWN_OPEN; // NIC owns it, not the CPU
bp->des1 = (MAX_RX_PACKET_SIZE << DES1_B1SIZE_SHIFT);
bp->buf1 = CYGHWR_PCI_VIRT_TO_BUS( &( p_i21143->_rxbufs[i][0] ) );
bp->buf2 = 0;
bp++;
}
bp--; // last one
bp->des1 |= DES1_ENDRING;
p_i21143->next_rx_descriptor = 0;
}
// ------------------------------------------------------------------------
//
// Function : PacketRxReady (Called from delivery thread & foreground)
//
// ------------------------------------------------------------------------
static void
PacketRxReady(struct i21143* p_i21143)
{
volatile BUFDES *bp;
int index;
struct eth_drv_sc *sc;
int count;
{
struct cyg_netdevtab_entry *ndp;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?