📄 card.c
字号:
/****************************************************************************
2004.12 第十项目小组
主编:王翔 徐隽
协助:卢坚 夏亮 傅佳伟 郑皓 黄君炜
测试:王弥
Rtl8139 根据 Win2000 DDK提供的Network Samples框架基础上进行编码
(声明:本驱动程序仅用于学习、探索、实践计算机网络相关知识之用。
请勿在未征得本小组同意的情况下随意传播。对使用本程序可能造成的
硬件问题本小组概不负责。也请勿将它用于学习之外的任何用途,本小组
对此种行为可能造成的不良后果概不负责。)
****************************************************************************/
/****************************************************************************
模块名称:
card.c
模块功能:
此模块定义硬件特定功能函数,供注册函数调用,
结构上沿用Win2000 DDK提供的Network Samples提供的card.c文件
开发环境:
WinDDK XP
Visual C++6.0
Driver Studio 3.1
*****************************************************************************/
#define NDIS_WDM 1
#define NDIS_MINIPORT_DRIVER
#define NDIS50_MINIPORT 1 //NDIS版本5.0
#include "ndis.h"
#include "RTL8139sw.h"
#include "RTL8139hw.h"
BOOLEAN
CardSlotTest(
IN PRTL8139_ADAPTER Adapter
);
BOOLEAN
CardRamTest(
IN PRTL8139_ADAPTER Adapter
);
#pragma NDIS_PAGEABLE_FUNCTION(CardCheckParameters)
BOOLEAN CardCheckParameters(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Checks that the I/O base address is correct.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if IoBaseAddress appears correct.
--*/
{
UCHAR Tmp;
//
// If adapter responds to a stop command correctly -- assume it is there.
//
//
// Turn off interrupts first.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_MASK, 0);
//
// Stop the card.
//
SyncCardStop(Adapter);
//
// Pause
//
NdisStallExecution(2000);
//
// Read response
//
NdisRawReadPortUchar(Adapter->IoAddr + NIC_COMMAND, &Tmp);
if ((Tmp == (CR_NO_DMA | CR_STOP)) ||
(Tmp == (CR_NO_DMA | CR_STOP | CR_START))
)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
#ifdef RTL8139
#pragma NDIS_PAGEABLE_FUNCTION(CardSlotTest)
BOOLEAN CardSlotTest(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Checks if the card is in an 8 or 16 bit slot and sets a flag in the
adapter structure.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
UCHAR Tmp;
UCHAR RomCopy[32];
UCHAR i;
BOOLEAN found;
//
// Reset the chip
//
NdisRawReadPortUchar(Adapter->IoAddr + NIC_RESET, &Tmp);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RESET, 0xFF);
//
// Go to page 0 and stop
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_STOP | CR_NO_DMA);
//
// Pause
//
NdisStallExecution(2000);
//
// Check that it is stopped
//
NdisRawReadPortUchar(Adapter->IoAddr + NIC_COMMAND, &Tmp);
if (Tmp != (CR_NO_DMA | CR_STOP))
{
IF_LOUD(DbgPrint("Could not stop the card\n");)
return(FALSE);
}
//
// Setup to read from ROM
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_BYTE_WIDE | DCR_FIFO_8_BYTE | DCR_NORMAL
);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_MASK, 0x0);
//
// Ack any interrupts that may be hanging around
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_STATUS, 0xFF);
//
// Setup to read in the ROM, the address and byte count.
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_ADDR_LSB, 0x0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_ADDR_MSB, 0x0);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 32);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_MSB, 0x0);
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_DMA_READ | CR_START
);
//
// Read first 32 bytes in 16 bit mode
//
for (i = 0; i < 32; i++)
{
NdisRawReadPortUchar(Adapter->IoAddr + NIC_RACK_NIC, RomCopy + i);
}
IF_VERY_LOUD( DbgPrint("Resetting the chip\n"); )
//
// Reset the chip
//
NdisRawReadPortUchar(Adapter->IoAddr + NIC_RESET, &Tmp);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RESET, 0xFF);
//
// Check ROM for 'B' (byte) or 'W' (word)
// NOTE: If the buffer has bot BB and WW then use WW instead of BB
IF_VERY_LOUD( DbgPrint("Checking slot type\n"); )
found = FALSE;
for (i = 16; i < 31; i++)
{
if (((RomCopy[i] == 'B') && (RomCopy[i+1] == 'B')) ||
((RomCopy[i] == 'W') && (RomCopy[i+1] == 'W'))
)
{
if (RomCopy[i] == 'B')
{
Adapter->EightBitSlot = TRUE;
found = TRUE;
}
else
{
Adapter->EightBitSlot = FALSE;
found = TRUE;
break; // Go no farther
}
}
}
if (found)
{
IF_VERY_LOUD( (Adapter->EightBitSlot?DbgPrint("8 bit slot\n"):
DbgPrint("16 bit slot\n")); )
}
else
{
//
// If neither found -- then not an RTL8139
//
IF_VERY_LOUD( DbgPrint("Failed slot type\n"); )
}
return(found);
}
#endif // RTL8139
#pragma NDIS_PAGEABLE_FUNCTION(CardRamTest)
BOOLEAN
CardRamTest(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Finds out how much RAM the adapter has. It starts at 1K and checks thru
60K. It will set Adapter->RamSize to the appropriate value iff this
function returns TRUE.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
PUCHAR RamBase, RamPointer;
PUCHAR RamEnd;
UCHAR TestPattern[]={ 0xAA, 0x55, 0xFF, 0x00 };
PULONG pTestPattern = (PULONG)TestPattern;
UCHAR ReadPattern[4];
PULONG pReadPattern = (PULONG)ReadPattern;
for (RamBase = (PUCHAR)0x400; RamBase < (PUCHAR)0x10000; RamBase += 0x400) {
//
// Write Test pattern
//
if (!CardCopyDown(Adapter, RamBase, TestPattern, 4)) {
continue;
}
//
// Read pattern
//
if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
continue;
}
IF_VERY_LOUD( DbgPrint("Addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\n",
RamBase,
ReadPattern[0],
ReadPattern[1],
ReadPattern[2],
ReadPattern[3]
);
)
//
// If they are the same, find the end
//
if (*pReadPattern == *pTestPattern) {
for (RamEnd = RamBase; !(PtrToUlong(RamEnd) & 0xFFFF0000); RamEnd += 0x400) {
//
// Write test pattern
//
if (!CardCopyDown(Adapter, RamEnd, TestPattern, 4)) {
break;
}
//
// Read pattern
//
if (!CardCopyUp(Adapter, ReadPattern, RamEnd, 4)) {
break;
}
if (*pReadPattern != *pTestPattern) {
break;
}
}
break;
}
}
IF_LOUD( DbgPrint("RamBase 0x%x, RamEnd 0x%x\n", RamBase, RamEnd); )
//
// If not found, error out
//
if ((RamBase >= (PUCHAR)0x10000) || (RamBase == RamEnd)) {
return(FALSE);
}
//
// Watch for boundary case when RamEnd is maximum value
//
if ((ULONG_PTR)RamEnd & 0xFFFF0000) {
RamEnd -= 0x100;
}
//
// Check all of ram
//
for (RamPointer = RamBase; RamPointer < RamEnd; RamPointer += 4) {
//
// Write test pattern
//
if (!CardCopyDown(Adapter, RamPointer, TestPattern, 4)) {
return(FALSE);
}
//
// Read pattern
//
if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
return(FALSE);
}
if (*pReadPattern != *pTestPattern) {
return(FALSE);
}
}
//
// Store Results
//
Adapter->RamBase = RamBase;
Adapter->RamSize = (ULONG)(RamEnd - RamBase);
return(TRUE);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardInitialize)
BOOLEAN
CardInitialize(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Initializes the card into a running state.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
UCHAR Tmp;
USHORT i;
//
// Stop the card.
//
SyncCardStop(Adapter);
//
// Initialize the Data Configuration register.
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_AUTO_INIT | DCR_FIFO_8_BYTE
);
//
// Set Xmit start location
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_START, 0xA0);
//
// Set Xmit configuration
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_CONFIG, 0x0);
//
// Set Receive configuration
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RCV_CONFIG, RCR_MONITOR);
//
// Set Receive start
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_PAGE_START, 0x4);
//
// Set Receive end
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_PAGE_STOP, 0xFF);
//
// Set Receive boundary
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_BOUNDARY, 0x4);
//
// Set Xmit bytes
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_COUNT_LSB, 0x3C);
NdisRawWritePortUchar(Adapter->IoAddr + NIC_XMIT_COUNT_MSB, 0x0);
//
// Pause
//
NdisStallExecution(2000);
//
// Ack all interrupts that we might have produced
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_STATUS, 0xFF);
//
// Change to page 1
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_PAGE1 | CR_STOP);
//
// Set current
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_CURRENT, 0x4);
//
// Back to page 0
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_PAGE0 | CR_STOP);
//
// Pause
//
NdisStallExecution(2000);
//
// Check that Command register reflects this last command
//
NdisRawReadPortUchar(Adapter->IoAddr + NIC_COMMAND, &Tmp);
if (!(Tmp & CR_STOP))
{
IF_LOUD(DbgPrint("Invalid command register\n");)
return(FALSE);
}
//
// Do initialization errata
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_RMT_COUNT_LSB, 55);
//
// Setup for a read
//
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_COMMAND,
CR_DMA_READ | CR_START
);
Adapter->EightBitSlot = TRUE;
//
// Mask Interrupts
//
NdisRawWritePortUchar(Adapter->IoAddr + NIC_INTR_MASK, 0x0);
//
// Setup the Adapter for reading ram
//
// NdisRawWritePortUchar(Adapter->IoAddr + NIC_COMMAND, CR_PAGE0); // robin
if (Adapter->EightBitSlot)
{
NdisRawWritePortUchar(
Adapter->IoAddr + NIC_DATA_CONFIG,
DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_BYTE_WIDE
);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -