📄 driver.c
字号:
adapter->IRQVector,
adapter->IRQLevel,
TRUE, //IN BOOLEAN RequestIsr
TRUE, //IN BOOLEAN SharedInterrupt
adapter->IRQMode);
if(NDIS_STATUS_SUCCESS != Status)
goto err;
//------------------------------------------------------------------------------
ResetNIC(adapter);
StartDevice(adapter);
return Status;
err:
KdPrint(("claim system resource failure. \n"));
FreeRes(adapter);
return Status;
}
///////////////////////////////////////////////////////////////////////////////
//如果MiniportCheckForHang函数返回TRUE,NDIS将调用MiniportReset函数
// 对NIC进行硬件复位 和 复位 驱动程序的软件状态
//如果AddressingReset设为TRUE,NDIS随后将调用MiniportSetInformation函数
NDIS_STATUS RReset(OUT PBOOLEAN AddressingReset,IN NDIS_HANDLE MiniportAdapterContext)
{
PADAPTER adapter = (PADAPTER)MiniportAdapterContext;
NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);//禁止所有中断
NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, 0);//接收、传输禁止
ResetNIC(adapter);
StartDevice(adapter);
adapter->read_ptr = 0; //从环状缓冲区数据拷贝的起始地址
adapter->FreeRxPkt = NUM_OF_PACKETS;//被释放的可用接收包数量64
adapter->cur_rx = 0; //当前接收的包的包的序号
adapter->dirty_rx = 0;
adapter->FreeTxDesc = NUM_OF_DESC;//被释放的可用发送描述符数量4
adapter->cur_tx = 0; //当前发送的描述符的序号
return NDIS_STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////////
//按既定的顺序发送每一包数据 on a Busmaster DMA NIC
VOID RSendPkts(IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,//指向包数组中的首个元素,每一元素指定要发送数据包的包描述符的地址
IN UINT NumberofPackets )//包描述符的个数
{
PADAPTER adapter = (PADAPTER)MiniportAdapterContext;
UINT i;
PUCHAR vaddr;
ULONG paddr;
static UINT pkt_len;
UCHAR tmpCMD;
ULONG offset;
for(i = 0; i < NumberofPackets; i ++)
{
if(adapter->FreeTxDesc > 0)//被释放的可用发送描述符数量
{
adapter->FreeTxDesc --;
vaddr = adapter->tx_bufs + (adapter->cur_tx * TX_BUF_SIZE);
//发送数据的虚拟地址 = 发送缓冲区虚拟基地址 + (当前发送的描述符的序号 * 每个发送包长1536 )
paddr = //发送数据的物理地址
NdisGetPhysicalAddressLow(adapter->tx_bufs_dma) + (adapter->cur_tx * TX_BUF_SIZE);
pkt_len = CopyPktToBuf(PacketArray[i],vaddr);//拷贝要发送的包数据到缓冲区,返回包数据长度
adapter->xmit_byte += pkt_len;
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
NdisRawReadPortUchar(adapter->ioaddr + ChipCmd, &tmpCMD);
ASSERT(tmpCMD & CmdTxEnb); //发送使能
if(pkt_len < MIN_ETHERNET_FRAME_SIZE) //包长度 64
pkt_len = MIN_ETHERNET_FRAME_SIZE;
offset = adapter->cur_tx << 2;//当前发送的描述符的序号
NdisRawWritePortUlong(
adapter->ioaddr + TxAddr0 + offset, //描述符 cur_tx(0~3)的发送起始地址
paddr); //发送数据的物理地址
NdisRawWritePortUlong(
adapter->ioaddr + TxStatus0 + offset,//描述符 cur_tx(0~3)的发送状态
pkt_len | (2 << 16)); //Early Tx Threshold: 2 << 16 000010 2*32=64字节
adapter->cur_tx = NextTxDesc(adapter->cur_tx);//当前发送的描述符的序号+1
}
else //驱动程序由于当前资源受限而不能进行在给定包数组中指定的所有发送
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_RESOURCES);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//如果微端口通过调用NdisMIndicateReceivePacket来向上层指示包,那么它必须注册一个MiniportReturnPacket函数
VOID RReturnPkt( IN NDIS_HANDLE MiniportAdapterContext,IN PNDIS_PACKET Packet)
{
}
/**************************************************************************
被调用函数
***************************************************************************/
//----------------------------------------------------------------------------
VOID ResetNIC(PADAPTER adapter )
{
UCHAR TmpCM;
NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, CmdReset|1); //复位设备 0x10 |1
do{ //测试复位是否成功 复位操作期间TmpCM位维持为1,直到复位完成被自动清0
NdisRawReadPortUchar(adapter->ioaddr + ChipCmd, &TmpCM);
}while(TmpCM & CmdReset);
NdisRawReadPortUchar(adapter->ioaddr + Config1, &TmpCM);
ASSERT(TmpCM & Cfg1_PIO); //该宏tests an expression. If the expression is false, it breaks into the kernel debugger
//The operational registers are mapped into PCI I/O space.
ASSERT(TmpCM & Cfg1_MMIO);//The operational registers are mapped into PCI memory space
}
//-------------------EEPROM: AT93C46 1K位 64X16 地址位6位:A5~A0 数据位16位:D15~D0
USHORT readEEPROM(PUCHAR ioaddr, // port addr
USHORT reg) //寄存器位置 例如 为 7
{
int i;
UCHAR TmpVal;
USHORT retval = 0;
USHORT locate = (6 << 6) | reg; // (6<<6)|7 = 0001 1000 0111
int addrlen = 9; // Start Bit 1 + READ Code 1 0 + 地址位:A5~A0 = 总共 9 位
//操作类型 OP_READ 6
NdisRawWritePortUchar(ioaddr, EE_PRO); // 0x80 进入编程状态
NdisRawWritePortUchar(ioaddr, EE_ENB); // 0x88 片选 + 编程模式
for(i = addrlen; i >= 0; i --)//串行写入
{
TmpVal = (locate & (1 << i)) ? EE_DI : 0; //EE_DI 0x02
//当 locate 位(第9到0位)为1时 TmpVal值为0x02,为0时 TmpVal值为0
NdisRawWritePortUchar(ioaddr, EE_ENB | TmpVal); //low clk
NdisRawWritePortUchar(ioaddr, EE_ENB | TmpVal | EE_CLK); //raise clk
}
NdisRawWritePortUchar(ioaddr, EE_ENB); //low clk
for(i = 0; i < 16; i ++) //读结果
{
NdisRawWritePortUchar(ioaddr, EE_ENB | EE_CLK); //raise clk
NdisRawReadPortUchar(ioaddr, &TmpVal);
TmpVal &= EE_DO; // &0x01
retval = (retval << 1) | TmpVal;
NdisRawWritePortUchar(ioaddr, EE_ENB); //low clk
}
NdisRawWritePortUchar(ioaddr, ~EE_CS);
return retval;
}
//////////////////////////////////////////////////////////////////////////
NDIS_STATUS AllocRes(PADAPTER adapter )
{
NDIS_STATUS Status;
UINT i;
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
Status = NdisMAllocateMapRegisters( //为随后的总线DMA操作来在miniport驱动初始化期间预定系统资源
adapter->MiniportAdapterHandle,
0,//IN UINT DmaChannel must 0
CM_RESOURCE_DMA_32, //IN NDIS_DMA_SIZE DmaSize
1, //IN ULONG BaseMapRegistersNeeded
256 );//IN ULONG MaximumBufferSize dma transtrate max = 2k
if(NDIS_STATUS_SUCCESS != Status)
return Status;
//------------------------------------------------------------------发送
NdisMAllocateSharedMemory(
adapter->MiniportAdapterHandle,
TX_BUF_SIZE * NUM_OF_DESC, //1536 * 4
FALSE,//not cached
&adapter->tx_bufs, //发送缓冲区虚拟基地址
&PhysicalAddress); //物理地址
if(adapter->tx_bufs == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
adapter->tx_bufs_dma = PhysicalAddress;
//------------------------------------------------------------接收
//分配和映射一个主机存储器范围,以便于主机系统和DMA NIC可同时访问存储器范围
NdisMAllocateSharedMemory(//为数据结构分配共享内存
adapter->MiniportAdapterHandle,
RING_BUF_SIZE + RING_BUF_PAD, //IN ULONG Length 16K +1536
FALSE,// IN BOOLEAN Cached FALSE not cached
&adapter->rx_ring, //环状缓冲区虚拟基地址 OUT PVOID *VirtualAddress
//返回为微端口驱动程序使用而分配的虚拟基地址,若不能分配,则返回NULL
&PhysicalAddress); //物理地址 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
if(adapter->rx_ring == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
adapter->rx_ring_dma = PhysicalAddress;
NdisMAllocateSharedMemory(
adapter->MiniportAdapterHandle,
RX_BUF_SIZE * NUM_OF_PACKETS, //1536 * 64
FALSE,//not cached
&adapter->rx_bufs, //接收缓冲区虚拟基地址
&PhysicalAddress );//物理地址
if(adapter->rx_bufs == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
adapter->rx_bufs_dma = PhysicalAddress;
NdisAllocatePacketPool(//为包描述符池分配和初始化一个存储块
&Status, //OUT PNDIS_STATUS Status
&adapter->pkt_pool, //OUT PNDIS_HANDLE PoolHandle
NUM_OF_PACKETS, //IN UINT NumberOfDescriptors, 池应该包含的包描述符的个数64
16 ); // IN UINT ProtocolReservedLength 分配给每一包描述符ProtocolReserved数组的字节数
if(Status != NDIS_STATUS_SUCCESS)
return STATUS_INSUFFICIENT_RESOURCES;
NdisAllocateBufferPool(//返回一个调用者通过调用NdisAllocateBuffer用来分配缓冲描述符的句柄
&Status,
&adapter->buf_pool,
NUM_OF_PACKETS); //IN UINT NumberOfDescriptors 缓冲描述符的个数 64
if(Status != NDIS_STATUS_SUCCESS)
return STATUS_INSUFFICIENT_RESOURCES;
//-------------------
for(i = 0; i < NUM_OF_PACKETS; i ++) // 64个包描述符 64个缓冲描述符 0 ~63
{ // 一个包描述符包含一个缓冲描述符 每个缓冲描述符的大小为RX_BUF_SIZE(1536)
NdisAllocatePacket(//分配和初始化一个包描述符
&Status,
&adapter->pkt_desc[i], //OUT PNDIS_PACKET *Packet 返回分配的包描述符指针
adapter->pkt_pool); //IN NDIS_HANDLE PoolHandle
if(Status != NDIS_STATUS_SUCCESS)
return STATUS_INSUFFICIENT_RESOURCES;
NdisAllocateBuffer( //创建了,在一已经分配的非分页内存块内映射特定虚拟(子)范围的,缓冲描述符
&Status,
&adapter->buf_desc[i], //返回分配的缓冲描述符指针
adapter->buf_pool,
adapter->rx_bufs + (i * RX_BUF_SIZE), //IN PVOID VirtualAddress 接收缓冲区虚拟基地址
//指向原先分配的系统空间内存(将要在缓冲描述符指针中映射)的虚拟基地址
RX_BUF_SIZE); //IN UINT Length 要映射的字节数
NdisChainBufferAtBack( //把一给定的缓冲描述符链接到,已连接到包描述符的缓冲描述符链的尾部
//如果给定的包还没有缓冲描述符存在,则把给定的要链接的缓冲描述符链到链的头部
adapter->pkt_desc[i], //IN OUT PNDIS_PACKET Packet
adapter->buf_desc[i]); //IN OUT PNDIS_BUFFER Buffer
}
adapter->read_ptr = 0; //从环状缓冲区数据拷贝的起始地址
adapter->FreeRxPkt = NUM_OF_PACKETS; //被释放的可用接收包数量64
adapter->cur_rx = 0; //当前接收的包的包的序号
adapter->dirty_rx = 0;
adapter->FreeTxDesc = NUM_OF_DESC; //被释放的可用发送描述符数量4
adapter->cur_tx = 0;//当前发送的描述符的序号
return NDIS_STATUS_SUCCESS;
}
//-------------------------------------------//#pragma PAGE_CODE IRQL:PASSIVE_LEVEL
VOID StartDevice(PADAPTER adapter)
{
SetMII(adapter);
NdisRawWritePortUlong(adapter->ioaddr + RxConfig, rtl8139_rx_config);
NdisRawWritePortUlong(adapter->ioaddr + TxConfig, RL_TXCFG_CONFIG);
NdisRawWritePortUlong(adapter->ioaddr + RxBuf, //接收缓冲开始地址
NdisGetPhysicalAddressLow(adapter->rx_ring_dma));
NdisRawWritePortUlong(adapter->ioaddr + RxMissed, 0); //写入任何值都将复位RxMissed寄存器
adapter->PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST;
//Directed包 含有的目的地址等于NIC的station地址
//Multicast address packets sent to addresses in the multicast address list
NdisRawWritePortUlong(adapter->ioaddr + MAR0, 0x80004000);
NdisRawWritePortUlong(adapter->ioaddr + MAR0 + 4, 0);
((PULONG)adapter->mc_filter)[0] = 0x80004000; //multicast address list
((PULONG)adapter->mc_filter)[1] = 0;
NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, CmdRxEnb | CmdTxEnb);//使能 接收和发送
NdisRawWritePortUshort(adapter->ioaddr + IntrMask, R39_INTERRUPT_MASK);//使能大多数中断
}
//-------------------------------------------------------------------------
//#pragma PAGE_CODE 释放资源 IRQL:PASSIVE_LEVEL
VOID FreeRes(PADAPTER adapter)
{
if(adapter->ioaddr != 0) //释放 I/O 端口资源
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -