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

📄 ne2000.c

📁 该BSP是基于PXA270+WINCE的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++
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.
Copyright (c) 1998-2000 Microsoft Corporation.  All rights reserved.

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 ".\udp.h"

//#define USE_ISA_PNP_STUFF
//#define DEBUG_SINGLE_CHAR   1
void msWait(unsigned msVal);
//
// 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 & 0x000000FF);
}

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

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

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

static ULONG
NE2000_READ_PORT_ULONG(volatile PULONG 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 ReadLong(Offset)            NE2000_READ_PORT_ULONG((volatile PULONG)(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;
	int temp;
    PBYTE pb = (PBYTE)mem;

    if (!count) {
        EdbgOutputDebugString("EDBG:NE2000:HWAccess - skipping 0 byte access!!!\r\n");
        return;     // Skip 0 length reads
    }
/*
	ReadByte(0x10);
	ReadWord(0x10);
	ReadLong(0x10);
	while(1);
*/
    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((count / 4) != 0)
		{
			temp = ReadLong(NIC_RACK_NIC);
			*mem = (temp & 0x0000FFFF);
			mem++;
			*mem = ((temp & 0xFFFF0000) >> 16);
			mem++;
			count = count - 4;
		}
		if((count / 2) != 0)
		{
			temp = ReadLong(NIC_RACK_NIC);
			*mem = (temp & 0x0000FFFF);
			mem++;
			if (count == 3) // count is either 2 or 3
			{
				*((PBYTE)mem) = ((temp & 0x00FF0000) >> 16);
				count = count - 1;
			}
			count = count - 2;
		}
		if (count == 1)
		{
			temp = ReadLong(NIC_RACK_NIC);
			*((PBYTE)mem) = (temp & 0x000000FF);
		}
    }

    c = 0;
    while ((++c) && !(ReadByte(NIC_INTR_STATUS) & NIC_ISR_DMA_COMPLETE));



    return;
}   // HWAccess

#if 0
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
    }
/*
	ReadByte(0x10);
	ReadWord(0x10);
	ReadLong(0x10);
	while(1);
*/
    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);
			//EdbgOutputDebugString("W 0x%X \r\n", *mem);
            mem++;
            c--;
        }
        if (count & 1) {
            *((PBYTE)mem) = ReadByte(NIC_RACK_NIC);
			//EdbgOutputDebugString("B 0x%X \r\n", *((PBYTE)mem));
        }
    }

    c = 0;
    while ((++c) && !(ReadByte(NIC_INTR_STATUS) & NIC_ISR_DMA_COMPLETE));



    return;
}   // HWAccess
#endif


/////////////////////////////////////////////////////////////////////////////
//
//  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_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 };
static BYTE ramCheck2[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

//
//  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;
}

⌨️ 快捷键说明

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