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

📄 driver.c

📁 RTL8139驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:

	case OID_802_3_XMIT_DEFERRED://					0x01020201
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_MAX_COLLISIONS://			0x01020202
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_RCV_OVERRUN://					0x01020203
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_UNDERRUN://					0x01020204
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_HEARTBEAT_FAILURE://			0x01020205
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_TIMES_CRS_LOST://			0x01020206
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_LATE_COLLISIONS://			0x01020207
        *((PULONG)inbuf) = (ULONG)0;
        break;

		//
		//	Required statistics
		//
	case OID_GEN_XMIT_OK://							0x00020101
		*((PULONG)inbuf) = adapter->XMIT_OK;
        break;

	case OID_GEN_RCV_OK://							0x00020102
		*((PULONG)inbuf) = adapter->RCV_OK;
        break;

	case OID_GEN_XMIT_ERROR://						0x00020103
		*((PULONG)inbuf) = adapter->XMIT_ERR;
        break;

	case OID_GEN_RCV_ERROR://						0x00020104
		*((PULONG)inbuf) = adapter->RCV_ERR;
        break;

	case OID_GEN_RCV_NO_BUFFER://					0x00020105
		*((PULONG)inbuf) = adapter->RCV_NO_BUFFER;
        break;

    default:
		break;
    }

    return (Status);
}


//IRQL:DISPATCH_LEVEL
VOID
RReturnPkt(
    IN NDIS_HANDLE  MiniportAdapterContext,
    IN PNDIS_PACKET  Packet
    )
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;

	//GetBackPkt(adapter, Packet);
}


//IRQL:DISPATCH_LEVEL
//#pragma LOCK_CODE
VOID
RSendPkts(
    IN NDIS_HANDLE  MiniportAdapterContext,
    IN PPNDIS_PACKET  PacketArray,
    IN UINT  NumberofPackets
    )
/*++
	Sending Packets on a Busmaster DMA NIC
--*/
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;
	UINT		i;
	
//	DbgPrint("RSendPkts:NumberofPackets=%x \n", NumberofPackets);

	for(i = 0; i < NumberofPackets; i ++){
		SendPkt(
			adapter, 
			PacketArray[i]
			);
	}//for

}

//IRQL:DISPATCH_LEVEL
//USED BY RSendPkts
//#pragma LOCK_CODE
BOOLEAN
SendPkt(
	IN PADAPTER		 adapter,
    IN PNDIS_PACKET  Packet
	)
/*++
	发送一个包
--*/
{
	static UINT		pkt_len;
	PUCHAR		vaddr;
	ULONG		paddr;


	if(adapter->FreeTxDesc > 0){//有空闲的描述寄存器
		adapter->FreeTxDesc --;
		vaddr = adapter->tx_bufs + (adapter->cur_tx * TX_BUF_SIZE);
		paddr = NdisGetPhysicalAddressLow(adapter->tx_bufs_dma) + (adapter->cur_tx * TX_BUF_SIZE);
	
		//1.COPY 包内容
		pkt_len = CopyPktToBuf(
							Packet,
							vaddr
							);
		adapter->xmit_byte += pkt_len;

		//dma oparater
		NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
		IssueCMD(adapter, adapter->cur_tx, paddr, pkt_len);
	
		adapter->cur_tx = NextTxDesc(adapter->cur_tx);

		return TRUE;
	}//has free tsd

	DbgPrint("SendPkt failure. no free txdesc. pkt_len=%x,cur_tx=%x \n", pkt_len, adapter->cur_tx);
	//由 NDIS 排队包
	NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_RESOURCES);

	return FALSE;
}


//IRQL:DISPATCH_LEVEL
//USED BY SendPkt
VOID
IssueCMD(
	PADAPTER	adapter,
	UINT		cur_tx,
	ULONG		paddr,
	UINT		len
	)
{
	ULONG offset = cur_tx << 2;
	ULONG	tmpTSD;
	UCHAR	tmpCMD;

	NdisRawReadPortUchar(adapter->ioaddr + ChipCmd, &tmpCMD);
	ASSERT(tmpCMD & CmdTxEnb);

	if(len < MIN_ETHERNET_FRAME_SIZE)	
		len = MIN_ETHERNET_FRAME_SIZE;


	NdisRawWritePortUlong(
		adapter->ioaddr + TxAddr0 + offset,
		paddr
		);

	NdisRawWritePortUlong(
		adapter->ioaddr + TxStatus0 + offset,
		len | (2 << 16)//64
		);
}


//IRQL:DISPATCH_LEVEL
//USED BY SendPkt
//#pragma LOCK_CODE
ULONG
CopyPktToBuf(
			PNDIS_PACKET packet,
			PUCHAR buff
			)
{

	PUCHAR			WritePtr = buff;
	UINT			BufferCount;
	PNDIS_BUFFER	srcBuff, NextBuff;
	UINT			PacketLength, BufferLength;
	UINT				i;
	PUCHAR			Address;

	NdisQueryPacket(
		packet,
		NULL,
		&BufferCount,
		&srcBuff,
		&PacketLength
		);

	ASSERT(PacketLength <= TX_BUF_SIZE); //每个发送包长

	for(i = 0; i < BufferCount; i ++){
		NdisQueryBuffer(
			srcBuff,
			&Address,
			&BufferLength
			);
		NdisMoveMemory(
				WritePtr,
				Address,
				BufferLength
				);

		WritePtr += BufferLength;

		NdisGetNextBuffer(
			srcBuff,
			&NextBuff
			);

		srcBuff = NextBuff;
	}//for

	return PacketLength;
}



typedef struct tagISR_STATUS{
	USHORT	ROK:1;
	USHORT	RER:1;
	USHORT	TOK:1;
	USHORT	TER:1;
	USHORT	RXOVW:1;
	USHORT	LINKCHG:1;
	USHORT	RXFIFOOVW:1;
	USHORT	REV:6;
	USHORT	LENCHG:1;
	USHORT	TIMEOUT:1;
	USHORT	SERR:1;
}ISR_STATUS, *PISR_STATUS;

//IRQL:DIRQL
//USED BY NDIS
//#pragma LOCK_CODE
VOID
RIsr(
    OUT PBOOLEAN  InterruptRecognized,
    OUT PBOOLEAN  QueueMiniportHandleInterrupt,
    IN NDIS_HANDLE  MiniportAdapterContext
    )
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;
	USHORT		curISR, Tmp;
	UCHAR		cmd;

	//read isr status
	NdisRawReadPortUshort(adapter->ioaddr + IntrStatus, &curISR);
	NdisRawWritePortUshort(adapter->ioaddr + IntrStatus, curISR);
	DbgPrint("RIsr:IntrStatus=%x,FreeTxDesc=%x \n", curISR, adapter->FreeTxDesc);


	if(curISR & R39_INTERRUPT_MASK){

		NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);
		adapter->curISR = curISR & R39_INTERRUPT_MASK;
		
		//is our interrupt
		*InterruptRecognized = TRUE;
		*QueueMiniportHandleInterrupt = TRUE;

	}else{
		//is not our interrupt
		*InterruptRecognized = FALSE;
		*QueueMiniportHandleInterrupt = FALSE;
	}
}

//IRQL:DISPATCH_LEVEL
//USED BY NDIS
//#pragma LOCK_CODE
VOID 
RIsrDpc(
    IN NDIS_HANDLE  MiniportAdapterContext
    )
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;
	UCHAR		TmpTCR;
	ULONG		Tmplong;
	USHORT		cur_rx;
	USHORT		link_changed;

	USHORT		write_ptr;


    if(adapter->curISR & RxUnderrun){
		DbgPrint("RIsrDpc:RxUnderrun(link chg) \n");
	}

	//TX
    if((adapter->curISR & TxOK)||(adapter->curISR & TxErr)){
		TxInt(adapter);
	}

	//RX
	if(adapter->curISR & RxOK){
		RxInt(adapter);
	}

    if( adapter->curISR & (RxErr|RxOverflow|RxFIFOOver)){
		//chip write ptr
		NdisRawReadPortUshort(adapter->ioaddr + RxBufAddr, &write_ptr);

		DbgPrint("RIsrDpc:RxErr|RxOverflow|RxFIFOOver, write_ptr=%x,read_ptr=%x \n", write_ptr, adapter->read_ptr);
		//更新 RxBufPtr(读寄存器) -> RxReadOffset
		adapter->read_ptr = write_ptr % RING_BUF_SIZE;
		NdisRawWritePortUshort(adapter->ioaddr + RxBufPtr, adapter->read_ptr - 16);
		NdisRawWritePortUshort(adapter->ioaddr + IntrStatus, RxOK);
	}

	//enable interrupt
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, R39_INTERRUPT_MASK);
}


//IRQL:PASSIVE_LEVEL 
//USED BY RInit
//#pragma PAGE_CODE
VOID
FreeRes(
			PADAPTER	adapter
			)
{
	int		i;


	
	//free i/o
	if(adapter->ioaddr != 0){
		NdisMDeregisterIoPortRange(
			adapter->MiniportAdapterHandle,
			adapter->BaseIO,
			0x100,
			(PVOID)&adapter->ioaddr
			);
	}

	//free dma
	if(adapter){
		NdisMFreeMapRegisters(adapter->MiniportAdapterHandle);
	}
	//free interrupt
	if(adapter->IRQVector > 0){
		NdisMDeregisterInterrupt(adapter->MiniportAdapterHandle);
	}

	//free tx_bufs
	if(adapter->tx_bufs != NULL)
			NdisMFreeSharedMemory(
				adapter->MiniportAdapterHandle,
				TX_BUF_SIZE * NUM_OF_DESC,
				FALSE,//not cached
				adapter->tx_bufs,
				adapter->tx_bufs_dma
				);

	//free tx_bufs
	if(adapter->rx_bufs != NULL)
			NdisMFreeSharedMemory(
				adapter->MiniportAdapterHandle,
				RX_BUF_SIZE * NUM_OF_PACKETS,
				FALSE,//not cached
				adapter->rx_bufs,
				adapter->rx_bufs_dma
				);

	//free rx_ring
	if(adapter->rx_ring != NULL)
			NdisMFreeSharedMemory(
				adapter->MiniportAdapterHandle,
				RING_BUF_SIZE + RING_BUF_PAD,
				FALSE,//not cached
				adapter->rx_ring,
				adapter->rx_ring_dma
				);


	if(adapter->buf_pool != NULL)
		NdisFreeBufferPool(adapter->buf_pool);


	if(adapter->pkt_pool != NULL)
		NdisFreeBufferPool(adapter->pkt_pool);

	//free adapter mem
	NdisFreeMemory(
		(PVOID)adapter,
		sizeof(ADAPTER),
		0
		);

}

VOID
OpenPOWNER(
		PADAPTER	adapter
		)
{
	UCHAR	TmpUCHAR;

	NdisRawReadPortUchar(adapter->ioaddr + Config1, &TmpUCHAR);
	if(LWAKE & TmpUCHAR){
		DbgPrint("oh, no powner. \n");
		TmpUCHAR &= ~LWAKE;
		TmpUCHAR |= Cfg1_PM_Enable;

		//unlock
		NdisRawWritePortUchar(adapter->ioaddr + Cfg9346, Cfg9346_Unlock);

		NdisRawWritePortUchar(adapter->ioaddr + Config1, TmpUCHAR);

		NdisRawReadPortUchar(adapter->ioaddr + Config4, &TmpUCHAR);
		TmpUCHAR &= ~LWPTN;
		NdisRawWritePortUchar(adapter->ioaddr + Config4, TmpUCHAR);

		//lock
		NdisRawWritePortUchar(adapter->ioaddr + Cfg9346, Cfg9346_Lock);
	}
}

VOID
ResetNIC(
		PADAPTER	adapter
		)
{
	UCHAR	TmpCM;

	//reset device
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, CmdReset|1);

	//test rest success ?
	do{
		NdisRawReadPortUchar(adapter->ioaddr + ChipCmd, &TmpCM);
	}while(TmpCM & CmdReset);

	DbgPrint("Reset operate complete. ChipCmd=%x \n", TmpCM);

	//enable io,mem
	NdisRawReadPortUchar(adapter->ioaddr + Config1, &TmpCM);
	ASSERT(TmpCM & Cfg1_PIO);
	ASSERT(TmpCM & Cfg1_MMIO);
}

//IRQL:PASSIVE_LEVEL 
//USED BY RInit
//#pragma PAGE_CODE
NDIS_STATUS
StartDevice(
		PADAPTER	adapter
		)
{
	UCHAR	TmpCM;
	ULONG	Tmplong;
	UINT	i;
	USHORT	TmpShort;
	
	
//	SetMII(adapter);

	//enable dma Tx/Rx
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, CmdRxEnb | CmdTxEnb);

	//config rx
	NdisRawWritePortUlong(adapter->ioaddr + RxConfig, rtl8139_rx_config);
	//config tx
	NdisRawWritePortUlong(adapter->ioaddr + TxConfig, RL_TXCFG_CONFIG);

	/* init Rx ring buffer DMA address */
	NdisRawWritePortUlong(adapter->ioaddr + RxBuf, NdisGetPhysicalAddressLow(adapter->rx_ring_dma));

	//clear 0
	NdisRawWritePortUlong(adapter->ioaddr + RxMissed, 0);


	//all mult
    adapter->PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST;
	NdisRawWritePortUlong(adapter->ioaddr + MAR0, 0x80004000);
	NdisRawWritePortUlong(adapter->ioaddr + MAR0 + 4, 0);
	((PULONG)adapter->mc_filter)[0] = 0x80004000;
	((PULONG)adapter->mc_filter)[1] = 0;

	//enable dma Tx/Rx
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, CmdRxEnb | CmdTxEnb);

	//enable int
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, R39_INTERRUPT_MASK);
	
	return NDIS_STATUS_SUCCESS;
}

//IRQL:PASSIVE_LEVEL 
//USED BY RInit
//#pragma PAGE_CODE
NDIS_STATUS
AllocRes(
		PADAPTER	adapter
		)
{
	PUCHAR		Addr;
	UINT		bufsize;

	NDIS_STATUS	Status;
	UINT		i;
	PVOID		VirtualAddress;
	NDIS_PHYSICAL_ADDRESS	PhysicalAddress;
	ULONG		phy;

	//rx_ring
	NdisMAllocateSharedMemory(
			adapter->MiniportAdapterHandle,
			RING_BUF_SIZE + RING_BUF_PAD,
			FALSE,//not cached
			&adapter->rx_ring, //虚拟地址
			&PhysicalAddress //物理地址
			);
	if(adapter->rx_ring == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	adapter->rx_ring_dma = PhysicalAddress;
	//align to 32?
	DbgPrint("rx_ring=%x, rx_ring_dma=%x \n",adapter->rx_ring,NdisGetPhysicalAddressLow(PhysicalAddress));

⌨️ 快捷键说明

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