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

📄 driver.c

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

	//tx_bufs
	NdisMAllocateSharedMemory(
			adapter->MiniportAdapterHandle,
			TX_BUF_SIZE * NUM_OF_DESC,
			FALSE,//not cached
			&adapter->tx_bufs, //虚拟地址
			&PhysicalAddress //物理地址
			);
	if(adapter->tx_bufs == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	adapter->tx_bufs_dma = PhysicalAddress;
	//align to 32
	DbgPrint("tx_bufs=%x, tx_bufs_dma=%x \n",adapter->tx_bufs,NdisGetPhysicalAddressLow(PhysicalAddress));

	//rx_bufs
	NdisMAllocateSharedMemory(
			adapter->MiniportAdapterHandle,
			RX_BUF_SIZE * NUM_OF_PACKETS,
			FALSE,//not cached
			&adapter->rx_bufs, //虚拟地址
			&PhysicalAddress //物理地址
			);
	if(adapter->rx_bufs == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	adapter->rx_bufs_dma = PhysicalAddress;
	//align to 32
	DbgPrint("rx_bufs=%x, rx_bufs_dma=%x \n",adapter->rx_bufs,NdisGetPhysicalAddressLow(PhysicalAddress));

	//分配 Packet pool,Buffer pool to rx
	NdisAllocatePacketPool(
		&Status,
		&adapter->pkt_pool,
		NUM_OF_PACKETS,	
		16
		);
	if(Status != NDIS_STATUS_SUCCESS)
		return STATUS_INSUFFICIENT_RESOURCES;
	DbgPrint("pkt_pool = %x \n", adapter->pkt_pool);

	NdisAllocateBufferPool(
		&Status,
		&adapter->buf_pool,
		NUM_OF_PACKETS	
		); 
	if(Status != NDIS_STATUS_SUCCESS)
		return STATUS_INSUFFICIENT_RESOURCES;
	DbgPrint("buf_pool = %x \n", adapter->buf_pool);


	for(i = 0; i < NUM_OF_PACKETS; i ++){
		NdisAllocatePacket(
			&Status,
			&adapter->pkt_desc[i],
			adapter->pkt_pool
			);
		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),
			RX_BUF_SIZE
			);
		//connection buf_desc->pkt_desc
		NdisChainBufferAtBack(
			adapter->pkt_desc[i],
			adapter->buf_desc[i]
			);
	}

	adapter->read_ptr = 0;

	adapter->FreeRxPkt = NUM_OF_PACKETS;
	adapter->cur_rx = 0;
	adapter->dirty_rx = 0;

	adapter->FreeTxDesc = NUM_OF_DESC;
	adapter->cur_tx = 0;
	adapter->dirty_tx = 0;

	return NDIS_STATUS_SUCCESS;
}


//IRQL:DISPATCH_LEVEL
//USED BY RIsrDpc
VOID
TxInt(
	PADAPTER adapter
	)
/*++
	发送中断处理
--*/
{
	UINT	i = 0;
    ULONG       Offset;
    ULONG       tmpTSD;


//	DbgPrint("TxInt:adapter->dirty_tx=%x \n", adapter->dirty_tx);
	while((i < 4)&&(adapter->FreeTxDesc < 4)){
		Offset = (i) << 2;
	    NdisRawReadPortUlong(adapter->ioaddr + TxStatus0 + Offset, &tmpTSD);

		if(tmpTSD & (TxStatOK | TxUnderrun | TxAborted)){
			//err
			if(tmpTSD & (TxUnderrun | TxAborted)){
				adapter->XMIT_ERR ++;
			}else{
				adapter->XMIT_OK ++;
			}

			adapter->FreeTxDesc ++;
		//	adapter->dirty_tx = NextTxDesc(adapter->dirty_tx);
			NdisMSendResourcesAvailable(adapter->MiniportAdapterHandle);
			i ++;
		}
	}//while
}

//IRQL:DISPATCH_LEVEL
//USED BY RIsrDpc
VOID
RxInt(
	PADAPTER adapter
	)
/*++
	接收中断处理
--*/
{
	UCHAR			TmpCMD;
	UINT			NumOfPkt = 0;
	PNDIS_PACKET	RevPacket[NUM_OF_PACKETS];

	UINT			i;
	NDIS_STATUS		Status;

	PUCHAR			buf;
	PNDIS_BUFFER	buf_desc;
	UINT			buf_len;

	do{
		//读命令寄存器 ChipCmd 
		NdisRawReadPortUchar(adapter->ioaddr + ChipCmd, &TmpCMD);
		if((TmpCMD & (UCHAR)RxBufEmpty)){
			adapter->RCV_NO_BUFFER ++;
			break;//缓冲区为空
		}
		//有接收包
		RevPacket[NumOfPkt] = RevOnePacket(adapter);
		if(RevPacket[NumOfPkt])	NumOfPkt ++;
		else break;

	}while(TRUE);

	if(NumOfPkt > 0){
	//	DbgPrint("RxInt:NumOfPkt=%x, RCV_OK=%x \n", NumOfPkt, adapter->RCV_OK);
		NdisMIndicateReceivePacket(
				adapter->MiniportAdapterHandle,
				RevPacket,
				NumOfPkt
				);

		adapter->FreeRxPkt += NumOfPkt;
	}//if
}

//IRQL:DISPATCH_LEVEL
//USED RxInt
//#pragma LOCK_CODE
PNDIS_PACKET
RevOnePacket(
		PADAPTER adapter
		)
{
	PUCHAR		ReadPtr;
	USHORT		write_ptr;
	PPACKETHEADER	head;

	NDIS_STATUS	Status;

	USHORT		pkt_size;
	USHORT		max_byte;

	PUCHAR			buf;
	PNDIS_PACKET	pkt_desc;
	PNDIS_BUFFER	buf_desc;

	INT		i;

	ReadPtr = adapter->rx_ring + adapter->read_ptr; 

	//chip write ptr
	NdisRawReadPortUshort(adapter->ioaddr + RxBufAddr, &write_ptr);
	write_ptr = write_ptr % RING_BUF_SIZE;
	if(write_ptr > adapter->read_ptr)
		max_byte = write_ptr - adapter->read_ptr;
	else
		max_byte = write_ptr + RING_BUF_SIZE - adapter->read_ptr;


	head = (PPACKETHEADER)ReadPtr;
	if(PacketOK(head)){
		if(adapter->FreeRxPkt <= 0) goto RES_BAD; //没有空 rx_pkt
		pkt_size = *((PUSHORT)(ReadPtr + 2)) - 4;

		if(head->PAM) {
			adapter->RCV_OK ++;
			adapter->rev_byte += pkt_size;
		}
/*		DbgPrint("write_ptr=%x,read_ptr=%x,ReadPtr=%x, max_byte=%x\n", write_ptr,adapter->read_ptr,ReadPtr,max_byte);
		if(head->MAR) 
			DbgPrint("RevOnePacket:multicase pkt. ");
		else if(head->PAM){ 
			adapter->RCV_OK ++;
			DbgPrint("RevOnePacket:phy dest pkt.");
		}else if(head->BAR)
			DbgPrint("RevOnePacket:broadcast pkt.");

		for(i = 0; i < 12; i ++)
			DbgPrint("%02x-", *(ReadPtr + 4 + i));
		DbgPrint(", cur_rx=%x", adapter->cur_rx);
		DbgPrint("\n");
*/
		if(pkt_size + 8 > max_byte){
			DbgPrint("pkt_size + 8 > max_byte(%x) \n", max_byte);
			return NULL;
		}
		adapter->FreeRxPkt --;	//可用包个数 - 1
		pkt_desc = adapter->pkt_desc[adapter->cur_rx];
		//内存接收包
		NdisMoveMemory(
			adapter->rx_bufs + (adapter->cur_rx * RX_BUF_SIZE),
			ReadPtr + 4,
			pkt_size
			);

		NdisAdjustBufferLength(
			adapter->buf_desc[adapter->cur_rx],
			pkt_size
			);

		adapter->cur_rx = NextRxDesc(adapter->cur_rx);

		NDIS_SET_PACKET_STATUS(pkt_desc, NDIS_STATUS_RESOURCES);
	}else{//PACKETOK
		//err
		DbgPrint("RevOnePacket:rev packet error. \n");
		RxErrHandle(adapter);
		return NULL;
	}

	//下移读位置
	adapter->read_ptr = (adapter->read_ptr + pkt_size + 8 + 3) & (~3); //对齐 32
	adapter->read_ptr %= RING_BUF_SIZE;

	//更新 RxBufPtr(读寄存器) -> RxReadOffset
	NdisRawWritePortUshort(adapter->ioaddr + RxBufPtr, adapter->read_ptr - 16);

	return pkt_desc;

RES_BAD:
	DbgPrint("resources not enought for rev pkt. \n");
	return NULL;
}

VOID
RxErrHandle(
		PADAPTER adapter
		)
{
	UCHAR		TmpCM;
	ULONG		TmpLong;

		NdisRawReadPortUlong(adapter->ioaddr + RxMissed, &TmpLong);
		adapter->ERR_COUNT += TmpLong;
		NdisRawWritePortUlong(adapter->ioaddr + RxMissed, 0);
		adapter->RCV_ERR ++;

		//更新 RxBufPtr(读寄存器) -> RxReadOffset
		NdisRawWritePortUshort(adapter->ioaddr + RxBufPtr, adapter->read_ptr - 16);
}

//IRQL:DISPATCH_LEVEL
//USED RxInt
//#pragma LOCK_CODE
BOOLEAN
PacketOK(
	PPACKETHEADER p
	)
{
    BOOLEAN BadPacket = p->RUNT ||p->LONG ||p->CRC  ||p->FAE;

    if(BadPacket
		||(p->PacketLength > MAX_ETHERNET_FRAME_SIZE)
		||(p->PacketLength < MIN_ETHERNET_FRAME_SIZE)){
	    return FALSE;
    }else{
		return TRUE;
    }
}



#define		BMCR_RST		0x8000	//bit15
#define		BMCR_SPEED		0x2000	//bit13
#define		BMCR_AUTONEG	0x1000	//bit12
#define		BMCR_RSTAUTO	0x200	//bit9
#define		BMCR_DUPLEX		0x100	//bit8

#define		BMSR_AUTOCOMP	0x20	//bit5

VOID
SetMII(
		PADAPTER	adapter
		)
{
	USHORT	TmpShort;
	USHORT	media, ad, lp;

	//reset
	NdisRawWritePortUshort(adapter->ioaddr + BasicModeCtrl, BMCR_RST);
	do{
		NdisRawReadPortUshort(adapter->ioaddr + BasicModeCtrl, &TmpShort);
	}while(TmpShort & BMCR_RST);
	DbgPrint("MII reset complete. \n");

	NdisRawReadPortUshort(adapter->ioaddr + BasicModeCtrl, &TmpShort);
	TmpShort |= BMCR_AUTONEG | BMCR_RSTAUTO;
	NdisRawWritePortUshort(adapter->ioaddr + BasicModeCtrl, TmpShort);

	//set duplx
	do{
		NdisRawReadPortUshort(adapter->ioaddr + BasicModeStatus, &TmpShort);
	}while(!(TmpShort & BMSR_AUTOCOMP));
	DbgPrint("MII AUTONEG complete. \n");

  //link ok
	NdisRawReadPortUshort(adapter->ioaddr + BasicModeStatus, &TmpShort);
	if(! (TmpShort & PHY_BMSR_LINKSTAT)){
		DbgPrint("link error.\n");
		return;
	}
	DbgPrint("link ok.\n");

	//
	NdisRawReadPortUshort(adapter->ioaddr + BasicModeCtrl, &media);
	NdisRawReadPortUshort(adapter->ioaddr + NWayAdvert, &ad);
	NdisRawReadPortUshort(adapter->ioaddr + NWayLPAR, &lp);

		if (ad & PHY_ANAR_100BT4 && lp & PHY_ANAR_100BT4) {
			media |= PHY_BMCR_SPEEDSEL;
			media &= ~PHY_BMCR_DUPLEX;
			DbgPrint("(100baseT4)\n");
		} else if (ad & PHY_ANAR_100BTXFULL &&
			lp & PHY_ANAR_100BTXFULL) {
			media |= PHY_BMCR_SPEEDSEL;
			media |= PHY_BMCR_DUPLEX;
			DbgPrint("(full-duplex, 100Mbps)\n");
		} else if (ad & PHY_ANAR_100BTXHALF &&
			lp & PHY_ANAR_100BTXHALF) {
			media |= PHY_BMCR_SPEEDSEL;
			media &= ~PHY_BMCR_DUPLEX;
			DbgPrint("(half-duplex, 100Mbps)\n");
		} else if (ad & PHY_ANAR_10BTFULL &&
			lp & PHY_ANAR_10BTFULL) {
			media &= ~PHY_BMCR_SPEEDSEL;
			media |= PHY_BMCR_DUPLEX;
			DbgPrint("(full-duplex, 10Mbps)\n");
		} else {
			media &= ~PHY_BMCR_SPEEDSEL;
			media &= ~PHY_BMCR_DUPLEX;
			DbgPrint("(half-duplex, 10Mbps)\n");
		}

	NdisRawWritePortUshort(adapter->ioaddr + BasicModeCtrl, media);
}

BOOLEAN
RCheck(
    IN NDIS_HANDLE  MiniportAdapterContext
)
{
//    PADAPTER   adapter = (PADAPTER)MiniportAdapterContext;
//		DbgPrint("RCheck. \n");

/*	if(adapter->FreeTxDesc == 0){//	return TRUE;
		adapter->FreeTxDesc = 4;
		adapter->cur_tx = 0;
	}
*/
	return FALSE;
}


#define	EIGHT_BIT_MODE	0//定义 93C46 读写模式


USHORT
opEEPROM(
		PUCHAR		ioaddr,//93c46 port addr
		ULONG		locate, //寄存器位置
		OP_ENUM		op,	//操作类型
		USHORT		data
		)
{
	int			i, addrlen;
	UCHAR		TmpVal;
	USHORT		retval = 0;

	switch(op){
	case OP_WRITE:	

#if (EIGHT_BIT_MODE)	//8BIT MODE
		locate = (op << 15) | (locate << 8) | ((UCHAR)data);
		addrlen = 18;
#else	//16BIT MODE
		locate = (op << 22) | (locate << 16) | data;
		addrlen = 25;
#endif

		break;
	case OP_READ:
	case OP_ERASE:

#if (EIGHT_BIT_MODE)	//8BIT MODE
		locate = (op << 7) | locate;
		addrlen = 10;
#else	//16BIT MODE
		locate = (op << 6) | locate;
		addrlen = 9;
#endif
		
		break;
	default: 
		return 0;
	}


	NdisRawWritePortUchar(ioaddr, EE_ENB & ~EE_CS); //进入编程状态
	NdisRawWritePortUchar(ioaddr, EE_ENB); //select chip

	for(i = addrlen; i >= 0; i --){//串行写入
		TmpVal = (locate & (1 << i)) ? EE_DI : 0;
		NdisRawWritePortUchar(ioaddr, EE_ENB | TmpVal);
		NdisRawWritePortUchar(ioaddr, EE_ENB | TmpVal | EE_CLK); //raise clk
	}

	NdisRawWritePortUchar(ioaddr, EE_ENB); //low clk

	//read result
	for(i = 0; i < 16; i ++){
		NdisRawWritePortUchar(ioaddr, EE_ENB | EE_CLK); //raise clk
		NdisRawReadPortUchar(ioaddr, &TmpVal);
		TmpVal &= EE_DO;
		retval = (retval << 1) | TmpVal;
		NdisRawWritePortUchar(ioaddr, EE_ENB); //low clk
	}
	NdisRawWritePortUchar(ioaddr, ~EE_CS);

	return retval;
}//finish

//IRQL:DISPATCH_LEVEL
NDIS_STATUS 
RReset(
    OUT PBOOLEAN  AddressingReset,
    IN NDIS_HANDLE  MiniportAdapterContext
    )
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
	PADAPTER		adapter = (PADAPTER)MiniportAdapterContext;

	DbgPrint("RReset \n");

	while(adapter->FreeRxPkt != NUM_OF_PACKETS) 
		DbgPrint("RReset: FreeRxPkt=%x \n", adapter->FreeRxPkt);
		
	while(adapter->FreeTxDesc != NUM_OF_DESC) 
		DbgPrint("RReset: FreeTxDesc=%x \n", adapter->FreeTxDesc);
		
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, 0);
   
	ResetNIC(adapter);
	StartDevice(adapter);

	adapter->read_ptr = 0;

	adapter->FreeRxPkt = NUM_OF_PACKETS;
	adapter->cur_rx = 0;
	adapter->dirty_rx = 0;

	adapter->FreeTxDesc = NUM_OF_DESC;
	adapter->cur_tx = 0;
	adapter->dirty_tx = 0;

	return Status;
}

VOID 
RHalt(
    IN NDIS_HANDLE  MiniportAdapterContext
    )
{
    PADAPTER   adapter = (PADAPTER)MiniportAdapterContext;

	DbgPrint("RHalt \n");

	while(adapter->FreeRxPkt != NUM_OF_PACKETS) 
		DbgPrint("RHalt: FreeRxPkt=%x \n", adapter->FreeRxPkt);
		
	while(adapter->FreeTxDesc != NUM_OF_DESC) 
		DbgPrint("RHalt: FreeTxDesc=%x \n", adapter->FreeTxDesc);
		
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, 0);

   
	FreeRes((PADAPTER)MiniportAdapterContext);
}

      

⌨️ 快捷键说明

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