📄 if_ebsa285.c
字号:
#endif
goto try_again;
}
// This fires with one device on one of the customer boards!
// (but is OK on all other h/w. Worrying huh.)
if ( (EE_DATA_READ & retval) != 0 ) {
#ifdef DEBUG_EE
os_printf( "Read EEPROM: Dummy data bit not 0, reg %x\n" , retval );
#endif
}
eeprom_delay(1);
retval = 0;
for (i = EE_TOP_DATA_BIT; i >= 0; i--) {
OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
retval = (retval << 1) | ((INW(ee_addr) & EE_DATA_READ) ? 1 : 0);
eeprom_delay(EEPROM_SK_DELAY);
OUTW(EE_ENB, ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
}
// Terminate the EEPROM access.
OUTW(EE_ENB & ~EE_CS, ee_addr);
eeprom_delay(EEPROM_DONE_DELAY);
return retval;
}
// ------------------------------------------------------------------------
//
// NETWORK INTERFACE INITIALIZATION
//
// Function : Init82559
//
// Description :
// This routine resets, configures, and initializes the chip.
// It also clears the ethernet statistics structure, and selects
// which statistics are supported by this driver.
//
// ------------------------------------------------------------------------
static bool
ebsa285_i82559_init(struct cyg_netdevtab_entry * ndp)
{
static int initialized = 0; // only probe PCI et al *once*
struct eth_drv_sc *sc;
cyg_uint32 selftest;
volatile cyg_uint32 *p_selftest;
cyg_uint32 ioaddr;
cyg_uint16 checksum;
int count;
int i, ints;
int addr_length;
cyg_uint8 mac_address[6];
struct i82559 *p_i82559;
#ifdef DEBUG
db_printf("ebsa285_i82559_init\n");
#endif
sc = (struct eth_drv_sc *)(ndp->device_instance);
p_i82559 = (struct i82559 *)(sc->driver_private);
IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
os_printf( "Bad device private pointer %x\n", sc->driver_private );
#endif
return 0;
}
CHECK_NDP_SC_LINK();
if ( 0 == initialized++ ) {
// then this is the first time ever:
if ( ! pci_init_find_82559s() ) {
#ifdef DEBUG
os_printf( "pci_init_find_82559s failed" );
#endif
return 0;
}
}
if ( ! p_i82559->found ) // no device on PCI bus
return (0);
ioaddr = p_i82559->io_address; // get I/O address for 82559
#ifdef DEBUG
os_printf("Init82559 %d @ %x\n82559 Self Test\n",
p_i82559->index, (int)ndp);
#endif
ints = Mask82559Interrupt(p_i82559);
wait_for_cmd_done(ioaddr); // make sure no command operating
i82559_reset(p_i82559);
// Perform a system self-test. (get enough mem to round address)
if ( (selftest = (cyg_uint32)pciwindow_mem_alloc(32) ) == 0)
return (0);
p_selftest = (cyg_uint32 *) ((selftest + 15) & ~0xf);
p_selftest[0] = p_selftest[1] = -1;
OUTL( (VIRT_TO_BUS(p_selftest)) | I82559_SELFTEST, ioaddr + SCBPort);
count = 0x7FFFF; // Timeout for self-test.
do {
udelay(10);
} while ( (p_selftest[1] == -1) && (--count >= 0) );
Acknowledge82559Interrupt(p_i82559);
UnMask82559Interrupt(p_i82559, ints );
if (count < 0) {
// Test timed out.
#ifdef DEBUG
os_printf("Self test failed\n");
#endif
return (0);
}
#ifdef DEBUG
os_printf(" General self-test: %s.\n"
" Serial sub-system self-test: %s.\n"
" Internal registers self-test: %s.\n"
" ROM checksum self-test: %s (%08X).\n",
p_selftest[1] & 0x1000 ? "failed" : "passed",
p_selftest[1] & 0x0020 ? "failed" : "passed",
p_selftest[1] & 0x0008 ? "failed" : "passed",
p_selftest[1] & 0x0004 ? "failed" : "passed",
p_selftest[0]);
#endif
// read eeprom and get 82559's mac address
addr_length = get_eeprom_size(ioaddr);
// (this is the length of the *EEPROM*s address, not MAC address)
for (checksum = 0, i = 0, count = 0; count < 64; count++) {
cyg_uint16 value;
// read word from eeprom
value = read_eeprom(ioaddr, count, addr_length);
#ifdef DEBUG_EE
// os_printf( "%2d: %04x\n", count, value );
#endif
checksum += value;
if (count < 3) {
mac_address[i++] = value & 0xFF;
mac_address[i++] = (value >> 8) & 0xFF;
}
}
// If the EEPROM checksum is wrong, the MAC address read from the
// EEPROM is probably wrong as well. In that case, we don't set
// mac_addr_ok, but continue the initialization. If then somebody calls
// i82559_start without calling eth_set_mac_address() first, we refuse
// to bring up the interface, because running with an invalid MAC
// address is not a very brilliant idea.
if ((checksum & 0xFFFF) != 0xBABA) {
// selftest verified checksum, verify again
#ifdef DEBUG_EE
os_printf( "Warning: Invalid EEPROM checksum %04X for device %d\n",
checksum, p_i82559->index);
#endif
} else {
p_i82559->mac_addr_ok = 1;
#ifdef DEBUG_EE
os_printf("Valid EEPROM checksum\n");
#endif
}
#ifdef DEBUG
os_printf("MAC Address = %02X %02X %02X %02X %02X %02X\n",
mac_address[0], mac_address[1], mac_address[2], mac_address[3],
mac_address[4], mac_address[5]);
#endif
// record the MAC address in the device structure
p_i82559->mac_address[0] = mac_address[0];
p_i82559->mac_address[1] = mac_address[1];
p_i82559->mac_address[2] = mac_address[2];
p_i82559->mac_address[3] = mac_address[3];
p_i82559->mac_address[4] = mac_address[4];
p_i82559->mac_address[5] = mac_address[5];
// and record the net dev pointer
p_i82559->ndp = (void *)ndp;
InitRxRing(p_i82559);
InitTxRing(p_i82559);
// Initialize upper level driver
if ( p_i82559->mac_addr_ok )
(sc->funs->eth_drv->init)(sc, &(p_i82559->mac_address[0]) );
else
(sc->funs->eth_drv->init)(sc, 0 );
return (1);
}
// ------------------------------------------------------------------------
//
// Function : i82559_start
//
// ------------------------------------------------------------------------
static void i82559_start( struct eth_drv_sc *sc,
unsigned char *enaddr, int flags )
{
struct i82559 *p_i82559;
cyg_uint32 ioaddr;
#ifdef KEEP_STATISTICS
void *p_statistics;
#endif
#ifdef CYGPKG_NET
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif
p_i82559 = (struct i82559 *)sc->driver_private;
IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
os_printf( "i82559_start: Bad device pointer %x\n", p_i82559 );
#endif
return;
}
if ( ! p_i82559->mac_addr_ok ) {
#ifdef DEBUG
os_printf("i82559_start %d: invalid MAC address, "
"can't bring up interface\n",
p_i82559->index );
#endif
return;
}
if ( p_i82559->active )
i82559_stop( sc );
ioaddr = p_i82559->io_address; // get 82559's I/O address
#ifdef KEEP_STATISTICS
#ifdef CYGDBG_DEVS_ETH_ARM_EBSA285_KEEP_82559_STATISTICS
p_i82559->p_statistics =
p_statistics = pciwindow_mem_alloc(sizeof(I82559_COUNTERS));
memset(p_statistics, 0xFFFFFFFF, sizeof(I82559_COUNTERS));
wait_for_cmd_done(ioaddr); // make sure no command operating
// set statistics dump address
OUTL(VIRT_TO_BUS(p_statistics), ioaddr + SCBPointer);
OUTW(SCB_M | CU_STATSADDR, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr); // make sure no command operating
OUTW(SCB_M | CU_DUMPSTATS, ioaddr + SCBCmd); // start register dump
#endif
#endif
// Set the base address
wait_for_cmd_done(ioaddr);
OUTL(0, ioaddr + SCBPointer); // load ru base address = 0
OUTW(SCB_M | RUC_ADDR_LOAD, ioaddr + SCBCmd);
udelay( 1000 ); // load pointer to Rx Ring
OUTL(VIRT_TO_BUS(p_i82559->rx_ring[0]), ioaddr + SCBPointer);
OUTW(RUC_START, ioaddr + SCBCmd);
p_i82559->active = 1;
#ifdef CYGPKG_NET
/* Enable promiscuous mode if requested, reception of oversized frames always.
* The latter is needed for VLAN support and shouldn't hurt even if we're not
* using VLANs.
*/
i82559_configure(p_i82559, !!(ifp->if_flags & IFF_PROMISC), 1);
#endif
#ifdef DEBUG
{
int status = i82559_status( sc );
os_printf("i82559_start %d flg %x Link = %s, %s Mbps, %s Duplex\n",
p_i82559->index,
*(int *)p_i82559,
status & GEN_STATUS_LINK ? "Up" : "Down",
status & GEN_STATUS_100MBPS ? "100" : "10",
status & GEN_STATUS_FDX ? "Full" : "Half");
}
#endif
}
// ------------------------------------------------------------------------
//
// Function : i82559_status
//
// ------------------------------------------------------------------------
int i82559_status( struct eth_drv_sc *sc )
{
int status;
struct i82559 *p_i82559;
cyg_uint32 ioaddr;
p_i82559 = (struct i82559 *)sc->driver_private;
IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
os_printf( "i82559_status: Bad device pointer %x\n", p_i82559 );
#endif
return 0;
}
ioaddr = p_i82559->io_address; // get 82559's I/O address
status = INB(ioaddr + SCBGenStatus);
return status;
}
// ------------------------------------------------------------------------
//
// Function : BringDown82559
//
// ------------------------------------------------------------------------
static void i82559_stop( struct eth_drv_sc *sc )
{
struct i82559 *p_i82559;
p_i82559 = (struct i82559 *)sc->driver_private;
IF_BAD_82559( p_i82559 ) {
#ifdef DEBUG
os_printf( "i82559_stop: Bad device pointer %x\n", p_i82559 );
#endif
return;
}
#ifdef DEBUG
os_printf("i82559_stop %d flg %x\n", p_i82559->index, *(int *)p_i82559 );
#endif
p_i82559->active = 0; // stop people tormenting it
i82559_reset(p_i82559); // that should stop it
ResetRxRing( p_i82559 );
ResetTxRing( p_i82559 );
}
// ------------------------------------------------------------------------
//
// Function : InitRxRing
//
// ------------------------------------------------------------------------
static void InitRxRing(struct i82559* p_i82559)
{
int i;
RFD *rfd;
RFD *p_rfd = 0;
#ifdef DEBUG_82559
os_printf("InitRxRing %d\n", p_i82559->index);
#endif
for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) {
rfd = (RFD *)pciwindow_mem_alloc(sizeof(RFD) + MAX_RX_PACKET_SIZE);
p_i82559->rx_ring[i] = rfd;
if ( i )
p_rfd->link = VIRT_TO_BUS(rfd);
p_rfd = (RFD *)rfd;
}
// link last RFD to first:
p_rfd->link = VIRT_TO_BUS(p_i82559->rx_ring[0]);
ResetRxRing( p_i82559 );
}
// ------------------------------------------------------------------------
//
// Function : ResetRxRing
//
// ------------------------------------------------------------------------
static void ResetRxRing(struct i82559* p_i82559)
{
RFD *p_rfd;
int i;
#ifdef DEBUG_82559
os_printf("ResetRxRing %d\n", p_i82559->index);
#endif
for ( i = 0; i < MAX_RX_DESCRIPTORS; i++ ) {
p_rfd = p_i82559->rx_ring[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -