📄 ne2000.c
字号:
if (ramEnd & 0xffff0000) {
pstop = 0xff;
}
//
// Allocate 1 packet for transmit
//
tbb_start = (BYTE)(srambase>>8);
pstart = tbb_start+6; // Allocate 6 256 byte buffers for transmit
// compute sramsize
sramsize = ramEnd - srambase;
EdbgOutputDebugString("EDBG:NE2000:HWRamTest: srambase: 0x%X, sramsize: 0x%X, pstart: 0x%B\r\n",
srambase, sramsize, pstart);
// check the full RAM bank
if (!HWCheckRam(srambase,sramsize)) {
EdbgOutputDebugString("EDBG:NE2000:HWRamTest full RAM check failed.\r\n");
bRet = FALSE;
goto hwrt_done;
}
bRet = TRUE;
hwrt_done:
HWStartAdapter();
return bRet;
} // HWRamTest
/*
// Obsolete, now replaced by HWSetMCRegs()
//
// HWClearMCRegs - Clear the adapter's multicast address registers.
//
static void
HWClearMCRegs()
{
DWORD j;
UsePage1();
j = NIC_MC_ADDR;
// Now clear out all multicast address registers.
while (j < NIC_MC_ADDR+8) {
WriteByte(j, 0);
j++;
}
UsePage0();
} // HWClearMCRegs
*/
////////////////////////////////////////////////////////////////////////////////
// HWSetMCRegs()
//
// Description:
//
// This function is used to set the multicast registers.
//
// Arguments:
//
// pucMulticastRegs :: If not null then use this instead of 0xFF or 0x00
// depending on bAllMulticast below.
//
// bAllMulticast :: TRUE == Set all to 0xff :: FALSE = Set all to 0x00
//
// Return value:
//
//
static void
HWSetMCRegs(PUCHAR pucMulticastRegs, BOOL bAllMulticast)
{
DWORD j;
UCHAR ucData;
UsePage1();
if (pucMulticastRegs)
{
EdbgOutputDebugString(
"Ne2kDbg:: MulticastRegs set to : %x-%x-%x-%x-%x-%x-%x-%x\r\n",
pucMulticastRegs[0],
pucMulticastRegs[1],
pucMulticastRegs[2],
pucMulticastRegs[3],
pucMulticastRegs[4],
pucMulticastRegs[5],
pucMulticastRegs[6],
pucMulticastRegs[7]);
for (j = 0 ; j < 8 ; j++)
WriteByte(NIC_MC_ADDR + j, pucMulticastRegs[j]);
}
else
{
if (bAllMulticast)
{
EdbgOutputDebugString("Ne2kDbg:: HWSetMCRegs():: Set all to 0xff\r\n");
ucData = 0xFF;
}
else
{
EdbgOutputDebugString("Ne2kDbg:: HWSetMCRegs():: Set all to 0x00\r\n");
ucData = 0x00;
}
for (j = 0 ; j < 8 ; j++)
WriteByte(NIC_MC_ADDR + j, ucData);
}
UsePage0();
} // HWSetMCRegs()
//
// HWInit - completely initialize the hardware and leave it in a
// state that is ready to transmit and receive packets.
//
static BOOL
HWInit(void)
{
int n;
WriteCmd(NIC_AbortDmaStop); // Stop the NIC
// Initialize Data Configuration register for auto remove.
// This gets reset later on.
WriteByte(NIC_DATA_CONFIG, NIC_DCR_FIFO|NIC_DCR_AUTO_INIT);
// Bug workaround for SRAM memory protection.
WriteByte(NIC_XMIT_START, 0xA0);
WriteByte(NIC_XMIT_CONFIG, 0);
WriteByte(NIC_RCV_CONFIG, NIC_RECEIVE_MONITOR_MODE);
WriteByte(NIC_PAGE_START, 4);
WriteByte(NIC_BOUNDARY, 4);
WriteByte(NIC_PAGE_STOP, 0xff);
WriteByte(NIC_XMIT_COUNT_LSB, 0x3c);
WriteByte(NIC_XMIT_COUNT_MSB, 0);
WriteByte(NIC_INTR_STATUS, 0xff);
UsePage1Stop();
WriteByte(NIC_CURRENT, 4);
UsePage0();
// If command register reflects the last command assume it is OK
if (ReadCmd() != NIC_Page0) {
EdbgOutputDebugString("EDBG:NE2000Init:HWInit failed to read cmd reg\r\n");
goto hw_dead;
}
WriteByte(NIC_RMT_COUNT_LSB, 55); // initialization errata
WriteCmd(NIC_RemoteDmaRd);
HWStartAdapter();
if (!HWRamTest()) { // see how much adapter RAM
EdbgOutputDebugString("EDBG:NE2000Init:HWInit HWRamTest failed\r\n");
goto hw_dead;
}
WriteCmd(NIC_AbortDmaStop);
// Read the ethernet address
// The NE2000 address PROM only decodes even addresses, so you
// have to read WORDs and discard the high byte.
WriteByte(NIC_RMT_COUNT_LSB, 12);
WriteByte(NIC_RMT_COUNT_MSB, 0);
WriteByte(NIC_RMT_ADDR_LSB, 0);
WriteByte(NIC_RMT_ADDR_MSB, 0);
WriteCmd(NIC_RemoteDmaRd);
for (n = 0; n < 6; n++) {
ethernetaddr[n] = (BYTE)ReadWord(NIC_RACK_NIC);
}
// copy node address to page1 physical address registers
UsePage1Stop();
for (n = 0; n < 6; n++) {
WriteByte(NIC_PHYS_ADDR+n, ethernetaddr[n]);
}
//
// Init multicast registers to 0
//
memset(
g_pucMulticastList,
0x00,
MAX_MULTICAST_LIST * 6);
g_dwMulticastListInUse = 0x00;
HWSetMCRegs(NULL, FALSE);
WriteCmd(NIC_AbortDmaStop); // back to page0
// Initialize the page start, stop, and boundary registers based on the
// results of ram_test().
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;
tbb_start = (BYTE)(srambase >> 8);
memset(erase_header, 0xff, sizeof(erase_header));
return TRUE;
hw_dead:
WriteCmd(NIC_AbortDmaStop); // stop NIC
return FALSE;
} // HWinit
// 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
NE2000Init( BYTE *pbBaseAddress, DWORD dwMultiplier, USHORT MacAddr[3])
{
BOOL bRet;
int n;
PBYTE pDst;
PBYTE pSrc;
EdbgOutputDebugString("+EDBG:NE2000Init\r\n");
#ifdef USE_ISA_PNP_STUFF
pbBaseAddress = NE2000InitISAPNP(DEFAULT_IOBASE, DEFAULT_IRQ);
#endif // USE_ISA_PNP_STUFF
pbEthernetBase = pbBaseAddress;
EdbgOutputDebugString("EDBG:NE2000Init using I/O range at 0x%X\r\n", pbBaseAddress);
InitRcvQueue();
bRet = HWInit();
if( NULL != MacAddr ) {
pDst = (PBYTE)MacAddr;
pSrc = ethernetaddr;
for (n = 6; n; n--) {
*pDst++ = *pSrc++;
}
}
EdbgOutputDebugString("-EDBG:NE2000Init\r\n");
return bRet;
} // NE2000Init
// Interrupts left disabled at init, call this function to turn them on
void
NE2000EnableInts()
{
//EdbgOutputDebugString("NE2000EnableInts\n");
bIntMask = IMR_RCV|IMR_XMIT|IMR_RCV_ERR|IMR_XMIT_ERR|IMR_OVERFLOW;
UsePage0();
WriteByte(NIC_INTR_MASK, bIntMask);
}
void
NE2000DisableInts()
{
//EdbgOutputDebugString("NE2000DisableInts\n");
bIntMask = 0;
UsePage0();
WriteByte(NIC_INTR_MASK, bIntMask);
}
////////////////////////////////////////////////////////////////////////////////
// NE2000CurrentPacketFilter()
//
// Description:
//
// This function is called to set the h/w filter.
// We support:
// PROMISCUOUS, ALL MULTICAST, BROADCAST, DIRECTED.
//
// Arguments:
//
// dwFilter:: The filter mode
//
// Return value:
//
// TRUE if successful, FALSE otherwise.
//
void
Ne2000CurrentPacketFilter(DWORD dwFilter)
{
DWORD dwReceiveConfig = 0x00;
if (dwFilter & (PACKET_TYPE_ALL_MULTICAST | PACKET_TYPE_PROMISCUOUS))
{
//
// Need all multicast..
//
HWSetMCRegs(NULL, TRUE);
}
else
{
//
// No longer need "all multicast".
// When we do support MULTICAST LIST then we should copy the list
// to the h/w here..
//
UCHAR pucMulticastList[MAX_MULTICAST_LIST][6];
memcpy(
pucMulticastList,
&(g_pucMulticastList[0][0]),
g_dwMulticastListInUse * 6);
NE2000MulticastList(
&(pucMulticastList[0][0]),
g_dwMulticastListInUse);
}
//
// The multicast bit in the RCR should be on if multicast/all multicast packets
// (or is promiscuous) is needed.
//
if(dwFilter &
(PACKET_TYPE_ALL_MULTICAST | PACKET_TYPE_MULTICAST | PACKET_TYPE_PROMISCUOUS))
{
dwReceiveConfig |= RCR_MULTICAST;
}
else
{
dwReceiveConfig &= ~RCR_MULTICAST;
}
//
// The promiscuous physical bit in the RCR should be on if ANY
// protocol wants to be promiscuous.
//
if (dwFilter & PACKET_TYPE_PROMISCUOUS)
{
dwReceiveConfig |= RCR_ALL_PHYS;
}
else
{
dwReceiveConfig &= ~RCR_ALL_PHYS;
}
//
// The broadcast bit in the RCR should be on if ANY protocol wants
// broadcast packets (or is promiscuous).
//
if
(
dwFilter & (PACKET_TYPE_BROADCAST |
PACKET_TYPE_PROMISCUOUS)
)
{
dwReceiveConfig |= RCR_BROADCAST;
}
else
{
dwReceiveConfig &= ~RCR_BROADCAST;
}
//
// EDBG always receive directed and broadcast as a minimum.
//
dwReceiveConfig |= RCR_BROADCAST;
ucFilter = (BYTE)dwReceiveConfig;
dwNdisFilter = dwFilter;
EdbgOutputDebugString("NE2KDBG:: Set Ndis filter [0x%x] -> [0x%x]\r\n",
dwFilter,
dwReceiveConfig);
UsePage0();
WriteByte(NIC_RCV_CONFIG, (BYTE)dwReceiveConfig);
} // Ne2000CurrentPacketFilter()
////////////////////////////////////////////////////////////////////////////////
// ComputeCrc()
//
// Description:
//
// Runs the AUTODIN II CRC algorithm on buffer Buffer of length Length.
//
// Arguments:
//
// Buffer - the input buffer
// Length - the length of Buffer
//
// Return value:
//
// The 32-bit CRC value.
//
// Note:
//
// This function is adopted from netcard\ne2000 miniport driver.
//
ULONG
ComputeCrc(
IN PUCHAR Buffer,
IN UINT Length)
{
ULONG Crc, Carry;
UINT i, j;
UCHAR CurByte;
Crc = 0xffffffff;
for (i = 0; i < Length; i++) {
CurByte = Buffer[i];
for (j = 0; j < 8; j++) {
Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
Crc <<= 1;
CurByte >>= 1;
if (Carry) {
Crc = (Crc ^ 0x04c11db6) | Carry;
}
}
}
return Crc;
} // ComputeCrc()
////////////////////////////////////////////////////////////////////////////////
// GetMulticastBit()
//
// Description:
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -