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

📄 smc.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 3 页
字号:

//  Copyright(C) Renesas Technology Corp. 1998-2005. All rights reserved.
//
//  LAN91C111 Ether Debug Library for HS7751RSTC01H
//
//  FILE      : SMC.C
//  CREATED   : 2002.09.19
//  MODIFIED  : 2005.08.10
//  AUTHOR    : Renesas Technology Corp.
//  HARDWARE  : RENESAS ITS-DS7
//  NOTES     : Target OS is Microsoft(R) Windows(R) CE, version 4.0 or later.
//              This Library is based on LAN91C96 Ether Debug Library in PB4.0.
//  HISTORY   :
//              2002.07.24
//              - Released as LAN91C111 Ether Debug Library for HS7751RSTC01H by modifying
//               LAN91C96 Ether Debug Library in PB4.0 reference drivers.
//              2002.09.19
//              - Released for HS7751RSTC01H as Ver. 1.0.0
//              2005.08.10
//              - Modified SMCInit 2nd argument for OAL to production-qualiry OAL model.

//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

Abstract:  
    Routines for the SMC111 ethernet controller used for the Windows CE
    debug ethernet services, and bootloaders.

Functions:


Notes: 
    These routines are called at system init and other times when system calls aren't allowed, so
    they can't make any system calls.
    
--*/


// Note : The Odo SMC implementation sometimes encounters read errors if we
// optimize this routine.  So for now I'm just going to turn of all 
// optimizations.
#pragma optimize("", off)

#include <windows.h>
#include <halether.h>
#include "smchw.h"
#include "smcsw.h"
#include <udp.h>

// The base address of the SMC registers.  Also, allow for a multiplier, since the Odo
// platform uses 32 bit accesses of the registers.
static BYTE volatile *pbEthernetBase;
static DWORD dwRegisterMultiplier=1;


#define ReadWord( wOffset ) READ_PORT_USHORT((PUSHORT)(pbEthernetBase + (wOffset*dwRegisterMultiplier)))
#define WriteWord( wOffset, Value ) WRITE_PORT_USHORT((PUSHORT)(pbEthernetBase + (wOffset*dwRegisterMultiplier)),(USHORT)(Value))

// If this is defined, broadcast frames will be discarded.  Since we need to process
// ARPs, leave broadcast filter off, and filter out packets as soon as we can.  This, since
// we have to take an interrupt anyway, looking at the first few bytes isn't that bad. If
// the SMC chip could be configured so that we didn't even get interrupts for broadcast
// packets, we might look at updating the ARP cache on the desktop and filtering out all
// broadcasts...
#define NO_BROADCAST 0

#define BROADCAST_FILTER_BIT 0x4000

// If any of the following bits are set in the received status word, discard frame
#if NO_BROADCAST
#define FRAME_FILTER  (0xAC00 | BROADCAST_FILTER_BIT)  // No broadcast
#else
#define FRAME_FILTER  0xAC00   // Allow broadcast
#endif

// For debugging, if defined, this will cause all Rx/Tx data to be dumped to debug serial port
#undef SMC_DUMP_FRAMES

// Mask to use for interrupts
static UINT16 wIntMask;

// Controls whether we filter out broadcast packets (except ARP requests...)
static DWORD dwConfigOptions;

static void SendFrameError( char *pszPrefix, UINT16 wCompletionCode );
#ifdef SMC_DUMP_FRAMES
static void DumpEtherFrame( BYTE *pFrame, WORD cwFrameLength );
#endif

void PHYDiag();
void WRITE_PHY(unsigned char address, unsigned short data);
unsigned short READ_PHY(unsigned char address);
void SendData0();
void SendData1();
void SendDataZ();


void PHYDiag()
{
	//Reset Phy module.
	WRITE_PHY( PHYCONTROL_REG,0x8000);
	while ((READ_PHY( PHYCONTROL_REG )&0x8000));

	EdbgOutputDebugString("LAN91C111 diagnostic testing...");

	if( (0x16 == READ_PHY(PHYID_REG1)) && (0xF840 == READ_PHY(PHYID_REG2))) {
		EdbgOutputDebugString("completed.\r\n");
	} else {
		EdbgOutputDebugString("LAN failed.\r\n");
		while(1);
	}
}


void AutoNegotiation()
{
	unsigned short capability;
	unsigned long AutoNegotiationTimeOver;


	EdbgOutputDebugString("Try Auto Negotiation.......");
	
	WriteWord(BANKSEL_REG , BANK0 );
	WriteWord( RPCR_REG, 0x0800 );

	AutoNegotiationTimeOver = 0;
	capability =0;

	WRITE_PHY( PHYCONTROL_REG,0x1000);

	while ( !(READ_PHY( STATUS_REG )&0x0020)) {
		if( AutoNegotiationTimeOver == 0x8000 ) {
			EdbgOutputDebugString("time out.\r\n");
			WRITE_PHY( MASK_REG, 0x3FC0);
			capability = 1;
			break;
		}
		WRITE_PHY( PHYCONTROL_REG,0x1000);
		AutoNegotiationTimeOver++;
	}

	if ( capability !=1 )
		EdbgOutputDebugString("completed.\r\n");
	
	if (!(capability))
		capability = READ_PHY(AN_REC_REG);


	WRITE_PHY( PHYCONTROL_REG,0x0000);


		if( capability & 0x0200) {
			EdbgOutputDebugString("100Base-T4 capable.\r\n");
			EdbgOutputDebugString("We will not support 100Base-T4.\r\n");
		}

		if( capability & 0x0100) {
			EdbgOutputDebugString("100Base-TX Full Duplex capable.\r\n");

			WRITE_PHY( PHYCONTROL_REG,0x2100);
			WriteWord( BANKSEL_REG , BANK0 );
			WriteWord( TCR_REG, 0x8881 );
			WriteWord( RPCR_REG, 0x30D4 );
		}
		else if( capability & 0x0080) {
			EdbgOutputDebugString("100Base-TX Half Duplex capable.\r\n");

			WRITE_PHY(PHYCONTROL_REG,0x2000);
			WriteWord(BANKSEL_REG , BANK0 );
			WriteWord( TCR_REG, 0x0081 );
			WriteWord( RPCR_REG, 0x20D4 );
		}
		else if( capability & 0x0040) {
			EdbgOutputDebugString("10Base-T Full Duplex capable.\r\n");

			WRITE_PHY(PHYCONTROL_REG,0x0100);
			WriteWord(BANKSEL_REG , BANK0 );
			WriteWord( TCR_REG, 0x8881 );
			WriteWord( RPCR_REG, 0x10C8 );
		}
		else if( capability & 0x0020) {
			EdbgOutputDebugString("10Base-T Half Duplex capable.\r\n");

			WRITE_PHY(PHYCONTROL_REG,0x0000);
			WriteWord(BANKSEL_REG , BANK0 );
			WriteWord( TCR_REG, 0x0081 );
			WriteWord( RPCR_REG, 0x00C8 );
		}
		else {
			EdbgOutputDebugString("Wait for partner in the state of AutoNegotiaton.\r\n");
			READ_PHY(STATUS_OUTPUT_REG);
		}
}


void WRITE_PHY(unsigned char address, unsigned short data)
{
	int i;
	unsigned char adr;
	unsigned short dat;

	adr = address;
	dat = data;

		for ( i=0; i<32; i++) SendData1();
		//start bits
		SendData0();
		SendData1();
		//write command
		SendData0();
		SendData1();
		//PHY address
		for ( i=0; i<5; i++) SendData0();
		//PHY reg.
		for ( i=0; i<5; i++) {
		if(adr & (0x10>>i))
			SendData1();
		else
			SendData0();
		}
		
		// TA
		SendData1();
		SendData0();
		//write data
		for ( i=0; i<16; i++) {
		if(dat & (0x8000>>i))
			SendData1();
		else
			SendData0();
		}
}

unsigned short READ_PHY(unsigned char address)
{
	unsigned short ret,temp;
	int i;
	unsigned char adr;

	adr = address;

		for ( i=0; i<32; i++) SendData1();
		//start bits
		SendData0();
		SendData1();
		//read command
		SendData1();
		SendData0();
		//PHY address
		for ( i=0; i<5; i++) SendData0();

		//PHY reg.
		for ( i=0; i<5; i++) {
		if(adr & (0x10>>i))
			SendData1();
		else
			SendData0();
		}

	// TA Z0h
		SendDataZ();
		SendData0();

	// Read	data
		temp=0;
		ret=0;
		for ( i=0; i<16; i++) {
			WriteWord(MGMT_REG , 0x3330 );
			temp = ReadWord(MGMT_REG);
			temp = (temp & 0x0002)>>1;
			ret |= (temp <<(15-i));
			WriteWord(MGMT_REG , 0x3334 );
		}
	return ret;
}


void SendData0()
{
	WriteWord(BANKSEL_REG , BANK3 );
	WriteWord(MGMT_REG , 0x3338 );
	WriteWord(MGMT_REG , 0x333C );
	WriteWord(MGMT_REG , 0x3338 );
}

void SendData1()
{
	WriteWord(BANKSEL_REG , BANK3 );
	WriteWord(MGMT_REG , 0x3339 );
	WriteWord(MGMT_REG , 0x333D );
	WriteWord(MGMT_REG , 0x3339 );
}

void SendDataZ()
{
	WriteWord(BANKSEL_REG , BANK3 );
	WriteWord(MGMT_REG , 0x3330 );
	WriteWord(MGMT_REG , 0x3334 );
	WriteWord(MGMT_REG , 0x3330 );
}




// This is called to initialze the ethernet low level driver.  The base address of the ethernet hardware
// is passed into the routine.  The routine will return TRUE for a successful initialization.
BOOL
//SMCInit( BYTE *pbBaseAddress, DWORD dwMultiplier, USHORT MacAddr[3])
SMCInit( BYTE *pbBaseAddress, DWORD offset, USHORT MacAddr[3])
{
    DWORD dwStartTime;
    USHORT wBSR;
    
    if (! pbBaseAddress)
        return FALSE;
    
    pbEthernetBase = pbBaseAddress;
//    dwRegisterMultiplier = dwMultiplier;

    // Should be RESET!
    WriteWord( BANKSEL_REG, BANK0 );// Bank 0
    WriteWord( RCR_REG, 0x8000 );// MAC Reset
    dwStartTime = OEMEthGetSecs();
    while( OEMEthGetSecs() - dwStartTime < 2);// Wait 500ms
    WriteWord( RCR_REG, 0x0000 );// Write to 0x0000

    // MMU Reset
    WriteWord( BANKSEL_REG, BANK2 );// Bank 2
    WriteWord( MMUCOMMAND_REG, 0x0040 );// Write to MMU 0x0040
    while(ReadWord(MMUCOMMAND_REG) & MMU_CMD_BUSY);// Wait BUSY bit = 0
        
    PHYDiag();// PHY Reset
    while( OEMEthGetSecs() - dwStartTime < 2);// Wait 1500ms
    
    
    // DANGER - May have to wait 750 usec after reset while EEPROM info loads (Pg 50 of the SMC91C94 spec).
    // until this occurs, SMC registers are inaccessible.
    EdbgOutputDebugString("+SMCInit\r\n");
    
    WriteWord( BANKSEL_REG, BANK1 );
    
    dwStartTime = OEMEthGetSecs();
    while( ReadWord( CONTROL_REG ) & 0x0003 && OEMEthGetSecs() - dwStartTime < 2);

    // Verify the I/O base.  The upper byte of the BSR always reads 0x33, use this.
    // For Odo, the bus cycles will time out and garbage values will be returned.
    wBSR = ReadWord(BANKSEL_REG);
    if ((wBSR & 0xFF00) != 0x3300) {
        EdbgOutputDebugString("SMC card not detected, I/O base 0x%X, BSR: 0x%X\n",pbEthernetBase,wBSR);
        return FALSE;
    }

⌨️ 快捷键说明

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