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

📄 ne2000.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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 NE2000 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.
    
--*/
#include <windows.h>
#include <halether.h>
#include <ceddk.h>
#include "ne2000hw.h"
#include "..\eboot\udp.h"
#include "ethdbg.h"


//
//	List of multicast addresses currently set to h/w
//

#define		MAX_MULTICAST_LIST		8

UCHAR		g_pucMulticastList[MAX_MULTICAST_LIST][6];
DWORD		g_dwMulticastListInUse;


//
//	Default fitler is Broadcast & directed.
//	Until this is changed via NE2000CurrentPacketFilter()
//
UCHAR	ucFilter	 = NIC_RECEIVE_BROADCAST;
DWORD	dwNdisFilter = 0x00;


//#define USE_ISA_PNP_STUFF
//#define DEBUG_SINGLE_CHAR   1

//
// Structure to track receive packets
//
#define RCV_Q_SIZE 32
typedef struct _RCV_ENTRY {
    BYTE re_state;
    BYTE re_next;       // next card receive buffer
    WORD re_len;        // packet length
    WORD re_ptr;        // location in card's buffer
} RCV_ENTRY, *PRCV_ENTRY;

//
// re_state values
//
#define RCV_FREE 0
#define RCV_USED 1

static RCV_ENTRY g_rcv_list[RCV_Q_SIZE];
static DWORD g_rcv_index;   // Next RCV_ENTRY to use
static DWORD g_rcv_next;    // Next RCV_ENTRY to indicate
static DWORD g_rcv_cnt;     // Number of packets to indicate

//
// Variables for remembering 8390 chip state
//
static BYTE command_reg;
static BYTE int_status;
static BYTE NextPage;
static BYTE overflowrestartflag;
static BYTE pstart;
static BYTE pstop;
static BYTE transmitting;
static DWORD srambase;
static DWORD sramsize;

static BYTE rcv_header[NIC_HEADER_LEN+16]; // NIC puts the current value of the Receive
#define rcv_status      rcv_header[0]     // Status Register in the frame header.
#define rcv_next_buff   rcv_header[1]   // Page number where next packet is/will be.
#define rcv_frame_len0  rcv_header[2]
#define rcv_frame_len1  rcv_header[3]   // This can be ignored since in high speed systems
                                        // it will be incorrect and can be calculated
                                        // using the page variables.
#define rcv_dest_addr0  rcv_header[4]
#define rcv_dest_addr1  rcv_header[5]

static BYTE new_current_page;

static BYTE tbb_start;
static WORD curr_xmit_len;

static BYTE erase_header[20];

// Mask to use for interrupts
static BYTE bIntMask;
static BYTE volatile *pbEthernetBase;
static BYTE ethernetaddr[6];

// Bitmask for configuration options passed to us from bootloader/kernel.
static DWORD dwConfigOptions;

static void InitRcvQueue(void);


#ifdef USE_ISA_PNP_STUFF
//
// Use stuff from platform\cepc\kernel\hal\isapnp.c
//
extern ULONG ISAGetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
                                   IN PVOID Buffer, IN ULONG Offset, IN ULONG Length);
extern ULONG ISASetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
                                   IN PVOID Buffer, IN ULONG Offset, IN ULONG Length);
extern void ISAPNP_Sleep(DWORD ms);
BYTE * NE2000InitISAPNP(DWORD dwIOBase, DWORD dwIRQ);

#define DEFAULT_IOBASE  0x300
#define DEFAULT_IRQ     10

#endif  // USE_ISA_PNP_STUFF

#ifdef x86
static void
NE2000_WRITE_PORT_UCHAR(volatile PUCHAR addr, UCHAR val)
{
    __asm {
        mov edx, addr
        mov al, val
        out dx, al
    }
}

static UCHAR
NE2000_READ_PORT_UCHAR(volatile PUCHAR addr)
{
    UCHAR val;
    __asm {
        mov edx, addr
        in  al, dx
        mov val, al
    }
    return val;
}

static void
NE2000_WRITE_PORT_USHORT(volatile PUSHORT addr, USHORT val)
{
    __asm {
        mov edx, addr
        mov ax, val
        out dx, ax
    }
}

static USHORT
NE2000_READ_PORT_USHORT(volatile PUSHORT addr)
{
    USHORT val;
    __asm {
        mov edx, addr
        in  ax, dx
        mov val, ax
    }
    return val;
}
#else
static void
NE2000_WRITE_PORT_UCHAR(volatile PUCHAR addr, UCHAR val)
{
    *addr = val;
}

static UCHAR
NE2000_READ_PORT_UCHAR(volatile PUCHAR addr)
{
    return *addr;
}

static void
NE2000_WRITE_PORT_USHORT(volatile PUSHORT addr, USHORT val)
{
    *addr = val;
}

static USHORT
NE2000_READ_PORT_USHORT(volatile PUSHORT addr)
{
    return *addr;
}
#endif

#define WriteByte(Offset, Value)    NE2000_WRITE_PORT_UCHAR((volatile PUCHAR)(pbEthernetBase+Offset), Value)
#define ReadByte(Offset)            NE2000_READ_PORT_UCHAR((volatile PUCHAR)(pbEthernetBase+Offset))
#define WriteWord(Offset, Value)    NE2000_WRITE_PORT_USHORT((volatile PUSHORT)(pbEthernetBase+Offset), Value)
#define ReadWord(Offset)            NE2000_READ_PORT_USHORT((volatile PUSHORT)(pbEthernetBase+Offset))

#define WriteCmd(Cmd)   WriteByte(NIC_COMMAND, Cmd)
#define ReadCmd()       ReadByte(NIC_COMMAND)
#define UsePage0()      WriteCmd(NIC_Page0)
#define UsePage1()      WriteCmd(NIC_Page1)
#define UsePage1Stop()  WriteCmd(NIC_Page1Stop)

//#define NE2000_DUMP_FRAMES 1
#ifdef NE2000_DUMP_FRAMES
static void DumpEtherFrame( BYTE *pFrame, WORD cwFrameLength );
static void DumpNE2000Header(void);
#endif

static void iodelay(int delay);
static void HWAccess(WORD addr, WORD count, PWORD mem, BYTE direction);
#define INSB(addr, count, mem) HWAccess(((WORD)(addr)), ((WORD)(count)), (WORD *)mem, NIC_RemoteDmaRd)
#define OUTSB(addr, count, mem) HWAccess(((WORD)(addr)), ((WORD)(count)), (WORD *)mem, NIC_RemoteDmaWr)


///////////////////////////////////////////////////////////////////////////
//
//   iodelay - Wait by polling the command register for "delay" iterations.
//
///////////////////////////////////////////////////////////////////////////
static void
iodelay(int delay)
{
    while (delay) {
        ReadCmd();
        delay--;
    }
}   // iodelay

///////////////////////////////////////////////////////////////////////////
//
//  insb/outsb - Read/Write bytes or words from/to adapter ram
//
//  In word mode, the caller must ensure that adapter ram access starts
//  on a word boundary.
//
///////////////////////////////////////////////////////////////////////////
static void
HWAccess(
    WORD addr,
    WORD count, 
    PWORD mem, 
    BYTE direction
    )
{
    WORD c;
    PBYTE pb = (PBYTE)mem;

    if (!count) {
        EdbgOutputDebugString("EDBG:NE2000:HWAccess - skipping 0 byte access!!!\r\n");
        return;     // Skip 0 length reads
    }
    
    WriteByte(NIC_INTR_STATUS, NIC_ISR_DMA_COMPLETE);

    // Set count, address, remote DMA address and direction,
    UsePage0();
    WriteByte(NIC_RMT_ADDR_LSB, (UCHAR)addr);
    WriteByte(NIC_RMT_ADDR_MSB, (UCHAR)(addr>>8));
    WriteByte(NIC_RMT_COUNT_LSB, (UCHAR)count);
    WriteByte(NIC_RMT_COUNT_MSB, (UCHAR)(count>>8));
    WriteCmd(direction);

    if (addr & 1) {     // Never start word IO on an odd adapter address
        EdbgOutputDebugString("EDBG:NE2000:HWAccess SKIPPING ODD ADAPTER ADDRESS ACCESS!!!\r\n");
        return;
    }

    c = count >> 1;    // word count.
    if (direction == NIC_RemoteDmaWr) {
        while (c) {
            WriteWord(NIC_RACK_NIC, *mem);
            mem++;
            c--;
        }
        if (count & 1) {    // trailing odd data byte will be on even adapter address
            WriteByte(NIC_RACK_NIC, *((PBYTE)mem));
        }
    } else {
        while (c) {
            *mem = ReadWord(NIC_RACK_NIC);
            mem++;
            c--;
        }
        if (count & 1) {
            *((PBYTE)mem) = ReadByte(NIC_RACK_NIC);
        }
    }

    c = 0;
    while ((++c) &&
      !(ReadByte(NIC_INTR_STATUS) & NIC_ISR_DMA_COMPLETE));
    return;
}   // HWAccess


/////////////////////////////////////////////////////////////////////////////
//
//  HWStartAdapter - initialize the data size (BYTE or WORD), set up the
//             receive configuration, and    unmask the receive and
//             transmit interrupts at the adapter.
//
/////////////////////////////////////////////////////////////////////////////
static void
HWStartAdapter(void)
{
    UsePage0();
    WriteByte(NIC_DATA_CONFIG, NIC_DCR_FIFO | NIC_DCR_NORMAL | NIC_DCR_WORD_XFER);
    WriteByte(NIC_XMIT_CONFIG, 0);  // Initialize transmit configuration for normal operation.
    
	//WriteByte(NIC_RCV_CONFIG, NIC_RECEIVE_BROADCAST);  // accept broadcast and directed packets.
	WriteByte(NIC_RCV_CONFIG, ucFilter); 

    WriteByte(NIC_INTR_STATUS, 0xff );                  // ack all interrupts
    WriteCmd(NIC_CMD_ABORT | NIC_CMD_START );           // Put NIC in START mode.
}   // HWStartAdapter


/////////////////////////////////////////////////////////////////////////////
//
//  HWStopAdapter - shut down the adapter and leave it in loopback mode
//              preparatory to a reset.
//
/////////////////////////////////////////////////////////////////////////////
static void
HWStopAdapter(void)
{
    WORD    closeTimeout;

    WriteCmd(NIC_CMD_PAGE0 | NIC_CMD_ABORT | NIC_CMD_STOP); // Stop NIC from receiving or transmitting.
    WriteByte(NIC_INTR_STATUS, 0 );                         // mask all adapter interrupts
    WriteByte(NIC_RMT_COUNT_LSB, 0 );                       // Clear the remote byte count registers.
    WriteByte(NIC_RMT_COUNT_MSB, 0 );

    // Poll the card ISR for the RST bit.
    closeTimeout = 0;
    while ((++closeTimeout) &&
      !(ReadByte(NIC_INTR_STATUS) & NIC_ISR_RESET_STATUS));
    WriteByte(NIC_XMIT_CONFIG, 2);                          // Place NIC in internal loopback mode.
    WriteCmd(NIC_CMD_PAGE0 | NIC_CMD_START );               // Issue a start command. The NIC is still in loopback mode.
}   // HWStopAdapter


static void
HWReset(void)
{
    HWStopAdapter();
    WriteByte(NIC_PAGE_START, pstart);
    WriteByte(NIC_BOUNDARY, (BYTE)(pstart+1));
    WriteByte(NIC_PAGE_STOP, pstop);
    UsePage1Stop();
    WriteByte(NIC_CURRENT, (BYTE)(pstart+1));
    WriteCmd(NIC_AbortDmaStop); // back to page0
    NextPage = pstart+1;
    HWStartAdapter();
}

// checkRam and ram_test are used at bind time.

#define RAMCHECK_SIZE    4    // RAM test pattern
static BYTE ramCheck[RAMCHECK_SIZE] = { 0xAA, 0x55, 0xCC, 0x66 };


//
//  HWCheckRam - test adapter RAM by writing a test pattern and reading it.
//
//  Inputs:
//    addr  - internal adapter RAM buffer address
//    count - number of bytes to move
//
static BOOL
HWCheckRam(DWORD addr, DWORD count)
{
    DWORD i,j;
    BYTE buff[RAMCHECK_SIZE];

    // write the test pattern in 4 byte chunks
    for (i = 0; i < count; i += RAMCHECK_SIZE) {
        OUTSB((addr+i), min(RAMCHECK_SIZE,count), ramCheck);
    }

    // read it back and compare against the checkRam pattern.
    for (i = 0; i < count; i += RAMCHECK_SIZE) {
        INSB((addr+i), min(RAMCHECK_SIZE,count), buff);
        for (j = 0; j < min(RAMCHECK_SIZE,count); j++) {
            if (buff[j] != ramCheck[j]) {
                return FALSE;
            }
        }
    }
    return TRUE;
}

//
//  HWRamTest - figure out how much adapter RAM there is.
//
static BOOL
HWRamTest(void)
{
    DWORD ramEnd;
    BOOL bRet;

#define MAX_RAM_BASE 0x10000

    // find some RAM starting at 1K thru 64K. if it's greater then 64K, then
    // assume it isn't there.
    ramEnd = 0;
    HWStopAdapter();
    for (srambase = 1024; srambase < MAX_RAM_BASE; srambase += 1024) {
        if (HWCheckRam(srambase, 4)) {
            // found the starting point, now find out how much RAM there is.
            // assume it will increase in 1K chunks.
            for (ramEnd = srambase; !(ramEnd & 0xffff0000); ramEnd += 1024) {
                // RAM ends at the first location that fails the RAM test.
                if (!HWCheckRam(ramEnd, 4)) {
                    pstop = (BYTE)(ramEnd>>8);
                    break;
                }
            }
            break;
        }
    }

    // check for failure
    if ((srambase > MAX_RAM_BASE) || (srambase == ramEnd) || (ramEnd == 0)) {
        EdbgOutputDebugString("EDBG:NE2000:HWRamTest fail. srambase = 0x%X, ramEnd = 0x%X\r\n",
            srambase, ramEnd);
        bRet = FALSE;
        goto hwrt_done;
    }

    // if ramEnd is >= 64K, then back off one 256 byte chunk to avoid the 16
    // bit wrap around.

⌨️ 快捷键说明

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