⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miiphy.c

📁 lan91c111 测试代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *
 *	MIIPHY.EXE
 *
 *	This utility programs configurations of an MII compliant and
 *      manageable PHY device attached connected to a MAC of the FEAST
 *	(91C1XXxx) or EPIC (83C17X) families.
 *
 *	Compiled with Borland C++ v3.1 (Small model)
 *
 *	
 *     11/23/99  PG v2.21       Added the support for 91c110 dual function
 *				card.
 * 
 * 	01/07/99 RK v2.20	Fix incorrect OUI reporting when forced PHY
 *				address is used.
 *				Use Proprietary status to report duplex and
 *				speed when possible (instead of command)
 *				Add support for SEEQ PHY.
 *	10/28/98 RK v2.10	Fix access to PHYs from all EVBs to all
 *				PHYs including TDK and 180.
 *	08/21/98 RK v2.01	Add workaround for full duplex problem
 *				of FEAST110/FD not receiving if no CRS
 *				present even in full duplex. change PHY CRS
 *				default behaviour when in ful;l duplex thru
 *				bit 24.5
 *	08/07/98 RK v2.00	Add EPIC support.
 *				Change name to MIIPHY.EXE
 *				Add Q option.
 *				Add support to handle '/' prefixed commands
 *	08/06/98 RK v1.20	Add N, R , I options
 *				Add support for 83C180
 *	11/07/97 RK v1.00	Initial FEASTPHY.EXE version.
 */

// HEADERS

#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>

// TYPES

typedef	unsigned char	uchar;

// DEFINES

#define MAJOR_VER	2
#define MINOR_VER	21
#define DATE_STR	"991123"

#define TRUE	1==1
#define FALSE	0==1

#define DBG FALSE
//#define DBG TRUE

#define outword(addr,val) outport(addr,val)
#define inword(addr) inport(addr)

#define	MGMT		port+0x08	// FEAST Registers
#define	BANKSEL		port+0x0E

#define CONTROL		port+0x0C
#define NV_CONTROL	port+0x10
#define TEST		port+0x1C
#define MIICTRL		port+0x30
#define MIIDATA		port+0x34
#define MIICFG		port+0x38

#define MIIREAD		0x0001
#define MIIWRITE	0x0002

#define	MDO		0x01		// MII Resgiter bits
#define	MDI		0x02
#define	MCLK		0x04
#define	MDOE		0x08
#define	MALL 		0x0F
#define	OPWrite		0x01
#define	OPRead		0x02


#define PHY_CR		0		//PHY Registers and bits
#define PHY_CR_Reset	0x8000
#define PHY_CR_Speed	0x2000
#define PHY_CR_Duplex	0x0100

#define PHY_SR	1
#define PHY_ID1	2
#define PHY_ID2	3

// PHY propietary registers

#define PHY_NATIONAL_PAR		0x19
#define PHY_NATIONAL_PAR_DUPLEX		0x0080
#define PHY_NATIONAL_PAR_SPEED_10	0x0040

#define PHY_TDK_DIAG			0x12
#define PHY_TDK_DIAG_DUPLEX		0x0800
#define PHY_TDK_DIAG_RATE		0x0400

#define PHY_QSI_BASETX			0x1F
#define PHY_QSI_BASETX_OPMODE_MASK	0x001c
#define PHY_QSI_BASETX_OPMODE_10HD	(2<<0x1)
#define PHY_QSI_BASETX_OPMODE_100HD	(2<<0x2)
#define PHY_QSI_BASETX_OPMODE_10FD	(2<<0x5)
#define PHY_QSI_BASETX_OPMODE_100FD	(2<<0x6)

#define PHY_SEEQ_STATUS_OUTPUT		0x12
#define PHY_SEEQ_SPD_DET		0x80
#define PHY_SEEQ_DPLX_DET		0x40

#define PHY_OUI_QSI		0x006051
#define PHY_OUI_TDK		0x00C039
#define PHY_OUI_MITELSMSC	0x00A087
#define PHY_OUI_NATIONAL	0x080017
#define PHY_OUI_SEEQSMSC        0x0005BE

#define NWAY_TIMEOUT	10

// GLOBAL VARIABLES

unsigned int 	port=0x0;
unsigned long	OUI;
unsigned char 	Model, Revision;
unsigned char	MACType = 'F';		// 'F' for FEAST, 'E' for EPIC

// FUNCTIONS

int hextoi(char *buffer)
{
     int i,j,value,result=0;

     for (i=(strlen(buffer)-1),j=1;i>=0;i--,j=j*16)
	 {
	  value = *(buffer+i);
	  if ( (value >= 0x30) && (value <= 0x39) )
	      result += ( (value-'0') * j );
	  if ( (value >= 0x41) && (value <= 0x46) )
	      result += ( (value-'A'+10) * j );
	  if ( (value >= 0x61) && (value <= 0x66) )
	      result += ( (value-'a'+10) * j );
	 }

     return (result);
}

int dectoi(char *buffer)
{
     int i,j,value,result=0;

     for (i=(strlen(buffer)-1),j=1;i>=0;i--,j=j*10)
	 {
	  value = *(buffer+i);
	  if ( (value >= 0x30) && (value <= 0x39) )
	      result += ( (value-'0') * j );
	 }

     return (result);
}

void clkmdio(unsigned MGMTData)
{
  outword(MGMT, MGMTData);
  outword(MGMT, MGMTData | MCLK);
}

// ---------- Routine that actually generates the MII frames ----------

unsigned PHYAccess(uchar PHYAdd, uchar RegAdd, uchar OPCode, unsigned wData)
{
 // Local variables

 int i;
 unsigned MGMTval;

 // Filter unused bits from input variables.

 PHYAdd &= 0x1F;
 RegAdd &= 0x1F;
 OPCode &= 0x03;

 if (MACType == 'F')
 {
  MGMTval = inword(MGMT) & (MALL ^ 0xFFFF);

  // Output Preamble (32 '1's)

  for (i=0;i<32;i++)
   clkmdio(MGMTval | MDOE | MDO);

  // Output Start of Frame ('01')

  for (i=0;i<2;i++)
   clkmdio(MGMTval | MDOE | i);

  // Output OPCode ('01' for write or '10' for Read)

  for (i=1;i>=0;i--)
   clkmdio(MGMTval | MDOE | ((OPCode>>i) & 0x01) );

  // Output PHY Address

  for (i=4;i>=0;i--)
   clkmdio(MGMTval | MDOE | ((PHYAdd>>i) & 0x01) );

  // Output Register Address

  for (i=4;i>=0;i--)
   clkmdio(MGMTval | MDOE | ((RegAdd>>i) & 0x01) );

  if (OPCode == OPRead)
  {
   // Read Operation

   // Implement Turnaround ('Z0')

   clkmdio(MGMTval);
//   clkmdio(MGMTval | MDOE);

   // Read Data

   wData = 0;

   for (i=15;i>=0;i--)
   {
    clkmdio(MGMTval);
    wData |= (((inword(MGMT) & MDI) >> 1) << i);
   }

   // Add Idle state

   clkmdio(MGMTval);

   return (wData);
  }
  else
  {
   // Write Operation

   // Implement Turnaround ('10')

   for (i=1;i>=0;i--)
    clkmdio(MGMTval | MDOE | ((2>>i) & 0x01));

   // Write Data

   for (i=15;i>=0;i--)
    clkmdio(MGMTval | MDOE | ((wData>>i) & 0x01));

   // Add Idle state

   clkmdio(MGMTval);

   return (1);
  }
 }

 if (MACType == 'E')
 {
  if (OPCode == OPRead)
  {
   // Read Operation

   outport(MIICTRL, (((unsigned) PHYAdd) << 9) | (((unsigned) RegAdd) << 4) | MIIREAD);
   delay(1);
   wData = inport(MIIDATA);

   #if DBG
   printf("For PHYAdd = %02X, RegAdd = %02X, OPCode = %02X, wData = %04X\n\r", PHYAdd, RegAdd, OPCode, wData);
   printf("PHY register read = %04X\n\r",wData);
   #endif

   return(wData);
  }
  else
  {
   // Write Operation

   #if DBG
   printf("Writing to PHYAdd = %02X, RegAdd = %02X, OPCode = %02X, wData = %04X\n\r", PHYAdd, RegAdd, OPCode, wData);
   #endif
   outport(MIIDATA, wData);
   outport(MIICTRL, (((unsigned) PHYAdd) << 9) | (((unsigned) RegAdd) << 4) | MIIWRITE);
   delay(1);

   return(1);
  }
 }

 return(1);

}	 // End of Routine

unsigned char DetectPHY(void)
{
    unsigned int PhyId1, PhyId2;
    unsigned char PhyAdd=0xff;
    int Count;

    for (Count=31;Count>=0;Count--)
    {
	PhyId1 = PHYAccess(Count, PHY_ID1, OPRead, 0);
	PhyId1 = PHYAccess(Count, PHY_ID1, OPRead, 0);
	PhyId2 = PHYAccess(Count, PHY_ID2, OPRead, 0);
	PhyId2 = PHYAccess(Count, PHY_ID2, OPRead, 0);

	if(
		(PhyId1 > 0x0000) &&
		(PhyId1 < 0xffff) &&
		(PhyId2 > 0x0000) &&
		(PhyId2 < 0xffff) &&
		((PhyId1 != 0x8000) && (PhyId1 != 0x8000))
	  )
	  {
	   PhyAdd = (unsigned char) Count;
	   break;
	  }
	delay(1);
    }

    OUI = 	(((unsigned long) PhyId1) << 6) | ((PhyId2 & 0xfc00) >> 10);
    Model =	(unsigned char) ( (PhyId2 & 0x03f0) >> 4 );
    Revision = 	(unsigned char) (PhyId2 & 0x000f);

    return(PhyAdd);
}

unsigned char EpicIsThere(void)
{
	int i;
	#if DBG
	unsigned int temp;
	#endif

	#if DBG
	if( (temp = inport(port)) == 0xffff) return(FALSE); //Assume no board if read 0xffff
	printf("Read %04X from port %04X\n\r", temp, port);
	#else
	if( inport(port) == 0xffff) return(FALSE); //Assume no board if read 0xffff
	#endif

	outport(CONTROL, 0x0001);	//Reset EPIC
	delay(10);			//Wait for Reset complete

	for (i=0;i<10;i++) outport(TEST, 0x0008); // Fix flakiness

	#if DBG
	if((temp = (inport(CONTROL) & 0xefff)) == 0x0100)
	#else
	if((inport(CONTROL) & 0xefff) == 0x0100)
	#endif
	{
	 #if DBG
	 printf("Read %04X from port %04X\n\r", temp, CONTROL);
	 #endif
	 MACType = 'E';
	 outport(MIICFG, 0x0010);	// Enable MII management interface
	 return(TRUE);
	}
	else
	{
	 #if DBG
	 printf("Read %04X from port %04X\n\r", temp, CONTROL);
	 #endif
	 return(FALSE);
	}

}

unsigned char DetectMAC(void)
{

	if(!port)
	{
	 // No port specified, so lets search for a MAC.

	 // Look for FEAST type MAC @ 300h. This test looks for the 0x33
	 // signature pattern in the upper byte of the Bankselect register.

	 port = 0x0300;
	 if((inword(BANKSEL) & 0xff00) == 0x3300) return(TRUE);

	 // Look for EPIC type MAC @ 0fc00h, 6000 or 7000h
	 // A good test would search EPIC using PCI config space.
	 // The search mechanism used does not, it's just a small
	 // dummy verification only that checks on the default of
	 // the Control register after a Reset.


	 port = 0xfc00;
	 if(EpicIsThere()) return(TRUE);

	 port = 0x6000;
	 if(EpicIsThere()) return(TRUE);

	 port = 0x7000;
	 if(EpicIsThere()) return(TRUE);
	}
	else
	{
	 if((inword(BANKSEL) & 0xff00) == 0x3300) return(TRUE);
	 if(EpicIsThere()) return(TRUE);
	}

	// could not find any MAC, report failure.

	return(FALSE);
}

// MAIN PROGRAM

void main(int argc, char *argv[])
{
    unsigned int i, speed = 10, Address = 0xffff, PHYConfig, PHYConfig2, offset=0xffff, data;
    char duplex = 'H';
    unsigned char PHYAdd, ReadPort=0, PhyAddrRead=0, ForcedSpeed=0, ForcedDuplex = 0, NWAY=0, quiet = 0,ositech = 0;
	
    char report[100];

    // Get parameters and verify they are valid

    for (i=1;i<argc;i++)
	{
	 // Skip the first character if not a letter or '?'

	 if (
		(argv[i][0] != '?') &&
		(
		 (argv[i][0] < 'A') ||
		 (argv[i][0] > 'z') ||
		 ((argv[i][0] > 'Z') && (argv[i][0] <'a'))
		)
	    )
	 argv[i]++;

	 if ((argv[i][0] == 'P') || (argv[i][0] == 'p'))
	 {
	  // Skip ':' or '=' for numeric inputs as well.
	  if ((argv[i][1] == ':') || (argv[i][1] == '=')) argv[i]++;

	  port = hextoi(argv[i]+1);
	  ReadPort=1;
	 }
	 if ((argv[i][0] == 'S') || (argv[i][0] == 's'))
	 {
	  // Skip ':' or '=' for numeric inputs as well.
	  if ((argv[i][1] == ':') || (argv[i][1] == '=')) argv[i]++;

	  speed = dectoi(argv[i]+1);
	  ForcedSpeed=1;
	 }
	 if ((argv[i][0] == 'D') || (argv[i][0] == 'd'))
	 {
	  // Skip ':' or '=' for numeric inputs as well.
	  if ((argv[i][1] == ':') || (argv[i][1] == '=')) argv[i]++;

	  duplex = argv[i][1];
	  if(duplex == 'f') duplex = 'F';
	  if(duplex == 'h') duplex = 'H';
	  ForcedDuplex=1;
	 }
	 if ((argv[i][0] == 'I') || (argv[i][0] == 'i'))
	 {
	  // Skip ':' or '=' for numeric inputs as well.
	  if ((argv[i][1] == ':') || (argv[i][1] == '=')) argv[i]++;

	  Address = dectoi(argv[i]+1);
	  PhyAddrRead = 1;
	 }
	 if ((argv[i][0] == 'N') || (argv[i][0] == 'n'))
	 {
	  NWAY = 1;
	 }
	 if ((argv[i][0] == 'R') || (argv[i][0] == 'r'))
	 {
	  argv[i][3]=0;
	  offset = hextoi(argv[i]+1);
	  data = hextoi(argv[i]+4);
	 }
	 if ((argv[i][0] == 'Q') || (argv[i][0] == 'q'))
	  quiet = 1;
//PG 11/23/99 91C110 ositech dual function design support
	 if((argv[i][0] == 'A') || (argv[i][0] == 'a'))
		 ositech = 1;
	}

    clrscr();
    textcolor(GREEN);
    highvideo();

    printf("\n\r");
    cprintf("                           MIIPHY.EXE v%d.%02d (%s)\n\r",MAJOR_VER, MINOR_VER, DATE_STR);
    cprintf("                    PHY programming utility for SMSC boards.\n\r");

    if (argv[1][0] == '?')
       {
	textcolor(CYAN);
	highvideo();
	cprintf("\n\rSyntax:\n\r");
	cprintf("MIIPHY [P=p] [I=i] [D=d] [S=s] [N] [Roo=xxxx] [Q] [A]\n\r");
	printf("\n\r");
	printf("p: MAC IO port (hex. If not present will search at 300h, 6000h & 7000h)\n\r");
	printf("i: PHY Address (dec 0-31. Default is Autodetect)\n\r");
	printf("d: Force Duplex Mode ('F' or 'H')\n\r");
	printf("s: Force Speed Selection (10 or 100)\n\r");
	printf("N: Perform Autonegotiation (NWAY) and display results\n\r");
	printf("R: Write data xxxx into the register offset oo (both values in hex)\n\r");
	printf("Q: Run in quiet mode. Does not display the PHY register map\n\r");
	printf("A: Reset the PHY (EVB110G-PC-D)\n\r");
	printf("\n\r");
	printf("Example: MIIPHY P=320 S=100 D=H -> this sets the PHY to operate in 100\n\r");
	printf("         Mbps and half duplex modes using the MAC located at  IO=320h.\n\r");
	printf("\n\r");
	printf("All parameters are optional. When using D, S or N a reset will be\n\r");
	printf("performed to the PHY before the operation. Unless Q is  used  the\n\r");
	printf("the PHY's register map will be  displayed  after  performing  any\n\r");
	printf("operation (this does no alteration to the registers). The  groups\n\r");
	printf("of parameters N,  R  and  (S and/or D)  are  mutually  exclusive.\n\r");
	return;
       }
    else cprintf("                           (For Help run:  MIIPHY ?)\n\r\n\r");
    textcolor(WHITE);

    if(
	((ForcedSpeed || ForcedDuplex) && NWAY) ||
	((ForcedSpeed || ForcedDuplex) && (offset != 0xffff)) ||
	(NWAY && (offset != 0xffff))
      )
      {
	textcolor(YELLOW);
	highvideo();
	cprintf("\n\r\n\rUNRECOVERABLE ERROR: Incompatible options selected together. Type MIIPHY ? \n\r\n\r");
	exit(1);
      }



    if (ReadPort && ((port < 0x100) || (port > 0xff00)))
       {
	textcolor(YELLOW+BLINK);
	highvideo();
	cprintf ("INVALID PARAMETER: Port %Xh. MAC will be searched @ 300h, 6000h & 7000h.",port);
	delay(3000);
	printf("\r                                                              \r");

	port = 0x300;
       }

    if ((duplex != 'F') && (duplex !='H'))
       {
	textcolor(YELLOW+BLINK);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -