📄 if_ixdp2400.c
字号:
if ( 0 == retval )
{
#ifdef DEBUG_EE
printf(" EEPROM address bits found:i = %d \n", i);
#endif
break; // The dummy zero est arrive'
}
}
addrbits = i;
if ( 6 != i && 8 != i ) {
#ifdef DEBUG_EE
printf( "*****EEPROM data bits not 6 or 8*****\n" );
#endif
i = 6;
addrbits = 0; // So caller can know if the EEPROM is missing
}
// clear the dataval, leave the clock low to read in the data regardless
OUTW(EE_ENB, ee_addr);
eeprom_delay(1);
retval = INW(ee_addr);
if ( (EE_DATA_READ & retval) != 0 ) {
#ifdef DEBUG_EE
os_printf( "Size EEPROM: Dummy data bit not 0, reg %x\n" , retval );
#endif
}
eeprom_delay(1);
for (i = EE_TOP_DATA_BIT; i >= 0; i--) {
OUTW(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
retval = INW(ee_addr);
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 addrbits;
}
// ------------------------------------------------------------------------
//
// READ EEPROM
//
// ------------------------------------------------------------------------
static int read_eeprom(long ioaddr, int location, int addr_len)
{
unsigned short retval = 0;
int ee_addr = ioaddr + SCBeeprom;
int read_cmd = location | EE_READ_CMD(addr_len);
int i, tries = 10;
try_again:
// Should already be not-selected, but anyway:
OUTW(EE_ENB & ~EE_CS, ee_addr);
eeprom_delay(EEPROM_ENABLE_DELAY);
OUTW(EE_ENB, ee_addr);
eeprom_delay(EEPROM_ENABLE_DELAY);
// Shift the read command bits out, changing only one bit per time.
for (i = EE_TOP_CMD_BIT(addr_len); i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
OUTW(EE_ENB | dataval , ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
OUTW(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
OUTW(EE_ENB | dataval , ee_addr);
eeprom_delay(EEPROM_SK_DELAY);
}
// clear the dataval, leave the clock low
OUTW(EE_ENB, ee_addr);
eeprom_delay(1);
retval = INW(ee_addr);
// This should show a zero in the data read bit to confirm that the
// address transfer is compelete. If not, go to the start and try
// again!
if ( (0 != (retval & EE_DATA_READ)) && (tries-- > 0) ) {
// Terminate the EEPROM access.
OUTW(EE_ENB & ~EE_CS, ee_addr);
eeprom_delay(EEPROM_DONE_DELAY);
#ifdef DEBUG_EE
os_printf( "Warning: Retrying EEPROM read word %d, address %x, try %d\n",
location, ee_addr, tries+1 );
#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;
}
// ------------------------------------------------------------------------
//
// MDI
//
// ------------------------------------------------------------------------
#define SPEED_NOLINK 0
#define SPEED_10M 10
#define SPEED_100M 100
// MDI Control Register
typedef union
{
struct
{
#ifdef __ARMEB__
cyg_uint32 rsrv : 2; // reserved
cyg_uint32 intEnab : 1; // 1 = interrupt at end of cycle
cyg_uint32 ready : 1; // 1 = operation complete
cyg_uint32 op : 2; // opcode, 1 for MDI write, 2 for MDI read
cyg_uint32 phyAdd : 5; // PHY address
cyg_uint32 regAdd : 5; // PHY register address
cyg_uint32 data : 16; // data to write or data read
#else
cyg_uint32 data : 16; // data to write or data read
cyg_uint32 regAdd : 5; // PHY register address
cyg_uint32 phyAdd : 5; // PHY address
cyg_uint32 op : 2; // opcode, 1 for MDI write, 2 for MDI read
cyg_uint32 ready : 1; // 1 = operation complete
cyg_uint32 intEnab : 1; // 1 = interrupt at end of cycle
cyg_uint32 rsrv : 2; // reserved
#endif
} bits;
cyg_uint32 word;
} MDICTL;
static cyg_uint16 readMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd)
{
int mdi_addr = ioaddr + SCBCtrlMDI;
MDICTL mdiCtrl;
int num_ms = 0;
// prepare for the MDI operation
mdiCtrl.bits.ready = MDI_NOT_READY;
mdiCtrl.bits.intEnab = MDI_POLLED; // no interrupts
mdiCtrl.bits.op = MDI_READ_OP;
mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
mdiCtrl.bits.regAdd = regAdd & 0x1f;
// start the operation
OUTL(mdiCtrl.word, mdi_addr);
// delay a bit
udelay (1000);
// poll for completion */
mdiCtrl.word = INL(mdi_addr);
while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) { // wait max 2secs
mdiCtrl.word = INL(mdi_addr);
udelay(1000);
num_ms++;
}
if (num_ms >= 2000) {
printf ("readMDI Timeout!\n");
return -1;
}
else
return (cyg_uint16)mdiCtrl.bits.data;
}
static void writeMDI (long ioaddr, cyg_uint8 phyAdd, cyg_uint8 regAdd, cyg_uint16 data)
{
int mdi_addr = ioaddr + SCBCtrlMDI;
register MDICTL mdiCtrl;
int num_ms = 0;
// prepare for the MDI operation
mdiCtrl.bits.ready = MDI_NOT_READY;
mdiCtrl.bits.intEnab = MDI_POLLED; // no interrupts
mdiCtrl.bits.op = MDI_WRITE_OP;
mdiCtrl.bits.phyAdd = phyAdd & 0x1f;
mdiCtrl.bits.regAdd = regAdd & 0x1f;
mdiCtrl.bits.data = data & 0xffff;
// start the operation
OUTL(mdiCtrl.word, mdi_addr);
// delay a bit
udelay(1000);
// poll for completion
mdiCtrl.word = INL(mdi_addr);
while ((mdiCtrl.bits.ready == MDI_NOT_READY) && (num_ms != 2000)) {
mdiCtrl.word = INL(mdi_addr);
udelay(1000);
num_ms++;
}
if (num_ms >= 2000)
CYG_FAIL ("writeMDI Timeout!\n");
return;
}
static int initPHY (long ioaddr, cyg_uint32 device_type)
{
cyg_uint16 temp_reg;
cyg_uint8 revision;
// strip off revision and phy. id information
revision = (cyg_uint8)(device_type & REVISION_MASK);
device_type &= ~REVISION_MASK;
switch (device_type) {
case ICS1890_PHY_ID:
temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL); // get ready for loopback setting
writeMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, MDI_PHY_CTRL, temp_reg);
break;
case DP83840_PHY_ID: // set the Intel-specified "must set" bits
temp_reg = readMDI(ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG);
temp_reg |= (PCR_TXREADY_SEL | PCR_FCONNECT);
writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_PCR_REG, temp_reg);
// get ready for loopback setting
temp_reg = readMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG);
temp_reg &= CLEAR_LOOP_BITS;
writeMDI (ioaddr, MDI_DEFAULT_PHY_ADDR, DP83840_LOOPBACK_REG, temp_reg);
break;
case I82553_PHY_ID:
case I82553_REVAB_PHY_ID:
case I82555_PHY_ID:
break;
default:
return 1;
break;
}
return 0;
}
// ------------------------------------------------------------------------
//
// 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
ixdp2400_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;
int count;
int i, ints;
cyg_uint16 checksum;
int addr_length;
cyg_uint8 mac_address[6];
struct i82559 *p_i82559;
cyg_uint8 *cfg_mac_addr;
#ifdef DEBUG
db_printf("ixdp2400_i82559_init\n");
#endif
display_led('E', 'T', 'H', 'I');
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 = 0x1FFFFF; // 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
printf( "%2d: %04x\n", count, value );
#endif
checksum += value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -