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

📄 smc.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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 SMC9000 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 <pkfuncs.h>
#include <ceddk.h>
#include <halether.h>
#include "smchw.h"
#include "smcsw.h"
#include "udp.h"
#include "platform.h"

volatile unsigned long *M68K_ADD;
volatile unsigned short *M68K_DATA;
// This flag indicates when Frames are pending in the receive buffer.
//  It is set by the ISR when a RCV_INT is generated, and will be cleared when the GetFrame() routine
//  detects that all Frames have been removed from the buffer.
static UINT16 fFrameReceived;

inline 		LAN91C96_Write(ULONG ADD,USHORT DATA);
inline ushort 	LAN91C96_Read(ULONG ADD);
static void 	SMC_ISR( void );
// 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

// 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]) {

    DWORD dwStartTime;
    USHORT wBSR,wConfig;
    
    if (! pbBaseAddress)
        return FALSE;
  
 //	EdbgOutputDebugString("==> SMCInit\r\n");
//	EdbgOutputDebugString( "0x%X\r\n",pbBaseAddress);

//Because using 68K bus, we should disable ITU656 and SCI
	if ((LONG *)pbBaseAddress == (LONG *)PHYS_68KBUS_BASE)
	{
//		EdbgOutputDebugString(" EBOOT \r\n");
		
		*(volatile long *)(PHYS_SC_BASE + 0x010C)	|= 0xC000;

		//mac addr in flash
		MacAddr[0] = (*(USHORT *)0xC40C0018)&0xFFFF;;
	    	MacAddr[1] = (USHORT)(((*(ULONG *)0xC40C0018)>>16)&0xFFFF);
	    	MacAddr[2] = (*(USHORT *)0xC40C001C)&0xFFFF;
	}
	else 
	{
//		EdbgOutputDebugString(" kitl debugger \r\n");
		
		*(volatile long *)(VA_SC_BASE + 0x010C)	|= 0xC000;
		
		//initialize GPIO8_1 as NIC IRQ pin
		*(volatile long *)(VA_GPIO8_BASE + GPIOIS)	|= 0x2;			//level int	
		*(volatile long *)(VA_GPIO8_BASE + GPIOIBE)	  = 0x0;			//no both edge trigger	
		*(volatile long *)(VA_GPIO8_BASE + GPIOIEV)	|= 0x2;			//high level
		*(volatile long *)(VA_GPIO8_BASE + GPIOIE)	|= 0x2;			//enable GPIO INT 

		//mac addr in flash
		MacAddr[0] = (*(USHORT *)0x800C0018)&0xFFFF;;
	    	MacAddr[1] = (USHORT)(((*(ULONG *)0x800C0018)>>16)&0xFFFF);
	    	MacAddr[2] = (*(USHORT *)0x800C001C)&0xFFFF;
	}
	
	M68K_ADD = (volatile unsigned long *)pbBaseAddress;
	M68K_DATA =(volatile unsigned short *) (pbBaseAddress+4);
// 	EdbgOutputDebugString( "SMC M68K_ADD 0x%X\r\n",M68K_ADD);
// 	EdbgOutputDebugString( "SMC M68K_DATA 0x%X\r\n",M68K_DATA);


 //enter 68K bus mode
 	LAN91C96_Write(0x200,0x01);

//	EdbgOutputDebugString( "0x%X\r\n",LAN91C96_Read(BANKSEL_REG));

    LAN91C96_Write( BANKSEL_REG, BANK1 );

    dwStartTime = OEMEthGetSecs();
    while( LAN91C96_Read( 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 = LAN91C96_Read(BANKSEL_REG);
	EdbgOutputDebugString(" I/O base 0x%X, BSR: 0x%X\n",M68K_ADD,wBSR);
    if ((wBSR & 0xFF00) != 0x3300) {
        EdbgOutputDebugString("SMC card not detected, I/O base 0x%X, BSR: 0x%X\n",M68K_ADD,wBSR);
        return FALSE;
    }


    // Read the MAC address from the 91C94.  This should have been read in from the EEPROM during reset
	if( NULL != MacAddr ) {
	    LAN91C96_Write( BANKSEL_REG, BANK1 );
	/*
	    MacAddr[0] = LAN91C96_Read( MACADDR_REG0 );
	    MacAddr[1] = LAN91C96_Read( MACADDR_REG1 );
	    MacAddr[2] = LAN91C96_Read( MACADDR_REG2 );
	*/

/*
//mac addr in ram
		MacAddr[0] =0x5555;
	    	MacAddr[1] = 0x4321;
	    	MacAddr[2] = 0x1234;
*/			

    	EdbgOutputDebugString("SMC Ethernet Address: %B:%B:%B:%B:%B:%B\r\n",
        	                  	MacAddr[0] & 0x00FF, MacAddr[0] >> 8,
            	              	MacAddr[1] & 0x00FF, MacAddr[1] >> 8,
                	          	MacAddr[2] & 0x00FF, MacAddr[2] >> 8);
	}
   
    // Set SQUELCH bit - this changes the threshold for a valid signal from 300mV to 180mV.
    // This is to attempt to fix problems we have seen with some (usually 8 port) hubs.
   wConfig = LAN91C96_Read(CONFIG_REG);
 // wConfig |= CFG_SETSQLCH|CFG_NO_WAIT;
 	wConfig |= CFG_NO_WAIT;
  LAN91C96_Write(CONFIG_REG, wConfig);
//   EdbgOutputDebugString("SMC config reg val: %X\n",wConfig);
    
    // Initialize the control register
    LAN91C96_Write( BANKSEL_REG, BANK1 );
//	LAN91C96_Write( CONTROL_REG, CONTROL_REG_INIT );

    // Initialize memory configuration register
    LAN91C96_Write( BANKSEL_REG, BANK0 );
	 LAN91C96_Write( MCR_REG, MCR_REG_INIT );

    // Initialize transmit control register
    LAN91C96_Write( BANKSEL_REG, BANK0 );
    LAN91C96_Write( TCR_REG, TCR_REG_INIT );

    // Initialize interrupt mask register (all ints disabled to start)
    LAN91C96_Write( BANKSEL_REG, BANK2 );
    LAN91C96_Write( INTERRUPT_REG, 0);

    // The receive register should be the last thing initialzed so that we don't start
    //  getting Frames before we're ready for them.
    
    // Initialize the Receive Control Register (Pg 39 of the SMC91C94 spec):
    LAN91C96_Write( BANKSEL_REG, BANK0 );
//  LAN91C96_Write( RCR_REG, RCR_REG_INIT );
 	LAN91C96_Write( RCR_REG, 0x302);
    EdbgOutputDebugString("SMC Reset complete\r\n");
    
    // Even if the card is present, it likes to have a second to stabilize before the first transmission
    while( OEMEthGetSecs() - dwStartTime < 2 );
//Output LAN91C96 register
/*
{	USHORT DAT;
	USHORT	SavedBS;
	SavedBS=LAN91C96_Read( BANKSEL_REG);
	LAN91C96_Write(BANKSEL_REG,(USHORT) 0);
	DAT = LAN91C96_Read( TCR_REG);
	RETAILMSG(1, (TEXT("		BANK0_TCR = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( EPHSTATUS_REG);
	RETAILMSG(1, (TEXT("		BANK0_STS = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( RCR_REG);
	RETAILMSG(1, (TEXT("		BANK0_RCR = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( COUNTER_REG);
	RETAILMSG(1, (TEXT("		BANK0_CTR = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MIR_REG);
	RETAILMSG(1, (TEXT("		BANK0_MIR = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MCR_REG);
	RETAILMSG(1, (TEXT("		BANK0_MCR = 0x%x\r\n"),DAT));

	LAN91C96_Write(BANKSEL_REG,(USHORT) 1);
	DAT = LAN91C96_Read( CONFIG_REG);
	RETAILMSG(1, (TEXT("		BANK1_CONFIG = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( BASE_REG);
	RETAILMSG(1, (TEXT("		BANK1_BASE = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MACADDR_REG0);
	RETAILMSG(1, (TEXT("		BANK1_IA0 = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MACADDR_REG1);
	RETAILMSG(1, (TEXT("		BANK1_GEN = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MACADDR_REG2);
	RETAILMSG(1, (TEXT("		BANK1_CTL = 0x%x\r\n"),DAT));

	LAN91C96_Write( BANKSEL_REG,(USHORT) 2);
	DAT = LAN91C96_Read( INTERRUPT_REG);
	RETAILMSG(1, (TEXT("		BANK2_INT_STS = 0x%x\r\n"),DAT));

	LAN91C96_Write(BANKSEL_REG,(USHORT) 3);
	DAT = LAN91C96_Read( MULTITAB_REG0);
	RETAILMSG(1, (TEXT("		BANK3_MT01 = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MULTITAB_REG1);
	RETAILMSG(1, (TEXT("		BANK3_MT23 = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MULTITAB_REG2);
	RETAILMSG(1, (TEXT("		BANK3_MT45 = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MULTITAB_REG3);
	RETAILMSG(1, (TEXT("		BANK3_MT67 = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( MGMT_REG);
	RETAILMSG(1, (TEXT("		BANK3_MGMT = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( REVISION_REG);
	RETAILMSG(1, (TEXT("		BANK3_REV = 0x%x\r\n"),DAT));
	DAT = LAN91C96_Read( ERCV_REG);
	RETAILMSG(1, (TEXT("		BANK3_ERCV = 0x%x\r\n"),DAT));
	
	LAN91C96_Write(BANKSEL_REG, SavedBS);
}   
*/
 //   EdbgOutputDebugString( "<== SMCInit\r\n");
    return TRUE;
}

// Interrupts left disabled at init, call this function to turn them on
void
SMCEnableInts()
{
    // Only enable receive interrupts (we poll for Tx completion)
    wIntMask = RCV_INTM;
	EdbgOutputDebugString( "SMCEnableInts\r\n");
    LAN91C96_Write( BANKSEL_REG, BANK2 );
    LAN91C96_Write( INTERRUPT_REG, wIntMask );

	//enable GPIO8_1 IRQ
//	*(volatile long *)(VA_GPIO8_BASE + GPIOIE)	|= 0x2;
}

void
SMCDisableInts()
{
    wIntMask = 0;
	EdbgOutputDebugString( "SMCEnableInts\r\n");
    LAN91C96_Write( BANKSEL_REG, BANK2 );
    LAN91C96_Write( INTERRUPT_REG, wIntMask );
	
	//disable GPIO8_1 IRQ
//	*(volatile long *)(VA_GPIO8_BASE + GPIOIE)	&= ~0x2;
}

DWORD
SMCGetPendingInterrupts()
{
    WORD wInts;
    DWORD dwRet = 0;
    UINT16 wBankSave;
	EdbgOutputDebugString( "SMCGetPendingInterrupts() \r\n");
    // I need to save/restore the affected registers in the 91C96
    wBankSave = LAN91C96_Read( BANKSEL_REG );
    LAN91C96_Write( BANKSEL_REG, BANK2 );
    wInts = LAN91C96_Read(INTERRUPT_REG);

    // Just check for Rx int
    if (wInts & (RCV_INT | RX_OVRN_INT)) {
        dwRet = INTR_TYPE_RX;
    }
    
    LAN91C96_Write( BANKSEL_REG, wBankSave );

    return dwRet;
}

//
// This routine is used by the OAL to configure the debug Ethernet driver. Currently
// the following options are defined:
//     OPT_BROADCAST_FILTERING  -- If set, filter out all broadcast packets except ARP packets
// 
DWORD
SMCSetOptions(DWORD dwOptions)
{
    DWORD dwOldOptions = dwConfigOptions;

    dwConfigOptions = dwOptions;
    return dwOldOptions;
}

static BOOL
SMCReleaseMemory (UINT16 wCmd)

⌨️ 快捷键说明

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