📄 ether_test.c
字号:
//=============================================================================
//
// ether_test.c - Cyclone Diagnostics
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
// Contributors:
// Date: 2001-01-25
// Purpose:
// Description:
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <redboot.h>
#include <cyg/io/pci_hw.h>
#include <cyg/io/pci.h>
#include "pci_bios.h"
#include "iq80310.h"
#include "ether_test.h"
/* Forward declarations */
static int i557SelfTest (void);
static int i557Init (void);
static int i557Config (UINT8 loopBackMode);
static int i557AddrSet (void);
static int i557RUStart (void);
static void setUpPacket (char *p);
static int txPacket (char *p);
static char *malloc (int n);
static int waitForRxInt(void);
static int get_ether_addr(int unit, UINT8 *buf, int print_flag);
/* Externals */
extern long decIn(void);
extern void sgets(char *s);
extern int enable_external_interrupt (int int_id);
extern int isr_connect(int int_num, void (*handler)(int), int arg);
extern STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg);
extern void delay_ms(int msecs);
extern int eeprom_read (UINT32 pci_base,/* PCI Base address */
int eeprom_addr, /* word offset from start of eeprom */
UINT16 *p_data,/* where to put data in memory */
int nwords /* number of 16bit words to read */
);
extern int eeprom_write (UINT32 pci_base,/* PCI Base address */
int eeprom_addr, /* word offset from start of eeprom */
UINT16 *p_data,/* data location in memory */
int nwords /* number of 16bit words to write */
);
/* Globals needed by both main program and irq handler */
static volatile struct SCBtype *pSCB; /* Pointer to SCB in use */
static volatile UINT32 waitSem; /* Used to block test until interrupt */
static volatile UINT32 rxSem; /* Used to block test until rx sinterrupt */
static UINT16 i557Status; /* Status code from SCB */
static volatile char *mem_pool; /* Ptr to malloc's free memory pool */
static UINT32 adapter[2]; /* Ptr to PCI Ethernet adapter */
static UINT8 node_address[6];
/*static long timer0_ticks = 0;*/
static char buf[4];
static int count = 0;
static int forever_flag = FALSE;
static UINT32 phy_id = 0;
/* 82557 required data structures which must be allocated */
static struct rfd *pRfd;
static union cmdBlock *pCmdBlock;
static char *pPacketBuf;
#define SPEED_NOLINK 0
#define SPEED_10M 10
#define SPEED_100M 100
static int link_speed = SPEED_NOLINK;
UINT8 unit_intpin;
int unit_devno, unit_busno, unit_funcno;
#define BUSY_WAIT_LIMIT 0xf000 /* the upper limit on a busy wait
for command completion, etc. */
static void mask_557_ints (void)
{
pSCB->cmdStat.bits.m = 1;
}
static void unmask_557_ints (void)
{
pSCB->cmdStat.bits.m = 0;
}
/*****************************************************************************
* pci_ether_test - i8255x PCI Ethernet test
*
* Main diagnostic routine for the Intel 8255x 10/100BaseT Ethernet Controller
* family. Arguments include the PCI bus, device and function numbers of the
* controller that is to be tested.
*
*/
void pci_ether_test (UINT32 busno, UINT32 devno, UINT32 funcno)
{
volatile int i;
int ntimes;
int broadcom_flag = FALSE;
UINT16 phy_addr_reg, temp1, temp2;
cyg_pci_device_id devid;
count = 0;
devid = CYG_PCI_DEV_MAKE_ID(busno, CYG_PCI_DEV_MAKE_DEVFN(devno,funcno));
/* read the PCI BAR for the Ethernet controller */
cyg_pci_read_config_uint32(devid, 0x10, &adapter[0]);
/* strip off BAR indicator bits */
adapter[0] &= 0xfffffff0;
unit_devno = devno;
unit_busno = busno;
unit_funcno = funcno;
/* pointer to on-chip SCB */
pSCB = (struct SCBtype *)(adapter[0] + SCB_OFFSET);
unit_intpin = INTA;
printf ("PCI Base Address = 0x%X\n", adapter[0]);
printf ("PCI Interrupt Pin = 0x%02X\n", unit_intpin);
/* Initialize malloc's memory pool pointer */
mem_pool = (char *) ETHER_MEM_POOL;
/* Start the timer for delay implementation
printf("Starting timer... ");
StartTimer(); */
printf("Done.\n Resetting chip... ");
/* reset the 82557 to start with a clean slate */
resetChip();
printf("Done.\n");
/* Get the UUT's ethernet address */
if (get_ether_addr (0, node_address, TRUE) == ERROR) {
printf("Error Reading Adapter Ethernet Address\n");
return;
}
temp1 = readMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_1);
temp2 = readMDI(0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_ID_2);
phy_id = ((temp1 << 16) | temp2);
if ((phy_id & 0xfffffff0) == I82555_PHY_ID) {
printf ("Intel 82555/558 PHY detected...\n");
/* dummy read for reliable status */
(void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
phy_addr_reg = readMDI (0, MDI_DEFAULT_PHY_ADDR, I82555_STATCTRL_REG);
if (temp1 & MDI_STAT_LINK) { /* speed only valid with good LNK */
printf ("Connect Speed is %s\n", (phy_addr_reg & I82555_100_MBPS) ? "100Mbps" : "10Mbps");
link_speed = (phy_addr_reg & I82555_100_MBPS) ? SPEED_100M : SPEED_10M;
} else
printf ("Connect Speed is NOT VALID\n");
}
if ((phy_id & 0xfffffff0) == ICS1890_PHY_ID) {
printf ("Integrated Circuit Systems ICS1890 PHY detected...\n");
printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
/* dummy read for reliable status */
(void)readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);
temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, ICS1890_QUICKPOLL_REG);
printf ("Status Register Link Status is %s\n", (temp1 & QUICK_LINK_VALID) ? "UP" : "DOWN");
if (temp1 & QUICK_LINK_VALID) { /* speed only valid with good LNK */
printf ("Connect Speed is %s\n", (temp1 & QUICK_100_MBPS) ? "100Mbps" : "10Mbps");
link_speed = (temp1 & QUICK_100_MBPS) ?
SPEED_100M : SPEED_10M;
} else
printf ("Connect Speed is NOT VALID\n");
}
if ((phy_id & 0xfffffff0) == DP83840_PHY_ID) {
printf ("National DP83840 PHY detected...\n");
printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
/* dummy read for reliable status */
(void)readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
temp1 = readMDI (0, MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
phy_addr_reg = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, DP83840_PHY_ADDR_REG);
if (temp1 & MDI_STAT_LINK) { /* speed only valid with good LNK */
printf ("Connect Speed is %s\n", (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? "10Mbps" : "100Mbps");
link_speed = (phy_addr_reg & PHY_ADDR_SPEED_10_MBPS) ? SPEED_10M : SPEED_100M;
}
else printf ("Connect Speed is NOT VALID\n");
}
if ((phy_id & 0xfffffff0) == I82553_PHY_ID) {
printf ("Intel 82553 PHY detected...\n");
printf ("Revision = %c\n", 'A' + (phy_id & REVISION_MASK));
broadcom_flag = TRUE;
}
if (phy_id == I82553_REVAB_PHY_ID) {
printf ("Intel 82553 PHY detected...\n");
printf ("Revision = B\n");
broadcom_flag = TRUE;
}
if (broadcom_flag == TRUE) {
temp2 = readMDI (0,MDI_DEFAULT_PHY_ADDR, I82553_PHY_EXT_REG0);
printf ("Stepping = %02X\n", GET_REV_CNTR(temp2));
/* dummy read for reliable status */
(void)readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
temp1 = readMDI (0 ,MDI_DEFAULT_PHY_ADDR, MDI_PHY_STAT);
printf ("Status Register Link Status is %s\n", (temp1 & MDI_STAT_LINK) ? "UP" : "DOWN");
if (temp1 & MDI_STAT_LINK) { /* speed only valid with good LNK */
printf ("Connect Speed is %s\n", (temp2 & EXT_REG0_100_MBPS) ? "100Mbps" : "10Mbps");
link_speed = (temp2 & EXT_REG0_100_MBPS) ? SPEED_100M : SPEED_10M;
} else
printf ("Connect Speed is NOT VALID\n");
}
printf ("\n");
/* Run the built-in self test through the port register */
if (i557SelfTest () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
/* Reset clears the interrupt mask */
mask_557_ints();
printf ("Press return to initialize ethernet controller.\n");
sgets (buf);
/* Initialize data structures */
if (i557Init () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
/* Set hardware address */
if (i557AddrSet () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
printf ("Press return to perform internal loopback test.\n");
sgets (buf);
/* Configure for internal loopback */
if (i557Config (INT_LOOP_BACK) == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
delay_ms(100);
/* Initialize receive buffer and enable receiver */
if (i557RUStart () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
/* Send a packet */
setUpPacket (pPacketBuf);
if (txPacket (pPacketBuf) == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
printf ("Press return to perform loopback through PHY.\n");
sgets (buf);
/* Configure for external loopback */
if (i557Config (EXT_LOOP_BACK) == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
delay_ms(100);
/* Initialize receive buffer and enable receiver */
if (i557RUStart () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
/* Send a packet */
setUpPacket (pPacketBuf);
if (txPacket (pPacketBuf) == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
printf ("Press return to perform external loopback through\n");
printf ("10/100 Base T Hub. NOTE: If test duration is not forever,\n");
printf ("this test will work only if a properly functioning Hub\n");
printf ("and Twisted Pair cable are attached to the network connector\n");
printf ("on the front panel.\n");
sgets (buf);
printf ("Enter the number of times to run test (0 = forever): ");
ntimes = decIn();
printf ("\n\n");
if (i557RUStart () == ERROR) {
mask_557_ints (); /* Disable 557 interrupt */
return;
}
setUpPacket (pPacketBuf);
if (ntimes == 0) {
forever_flag = TRUE;
while (1) {
if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) {
printf ("Double-check TP cable and 10/100 Base T Hub\n");
printf ("Try testing them with another system\n");
printf ("(such as a workstation) that is working correctly.\n");
mask_557_ints (); /* Disable 557 interrupt */
return;
}
count++;
if (((count) % 1000) == 0)
printf("Loopback Cycle Count = %d\n", count);
}
} else {
forever_flag = FALSE;
for (i=0; i<ntimes; i++) {
if ((i557RUStart() == ERROR)||(txPacket (pPacketBuf) == ERROR)) {
printf ("Double-check TP cable and 10/100 Base T Hub\n");
printf ("Try testing them with another system\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -