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

📄 driver.c

📁 sis900网卡驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			adapter->MiniportAdapterHandle,
			RX_BUF_SIZE * NUM_RX_DESC,
			FALSE,//not cached
			&adapter->rx_bufs, //虚拟地址
			&PhysicalAddress //物理地址
			);
	if(adapter->rx_bufs == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	adapter->rx_buf_dma = PhysicalAddress;
	phy1 = NdisGetPhysicalAddressLow(PhysicalAddress);
	DbgPrint("rx_bufs=%x, rx_buf_dma=%x \n", adapter->rx_bufs, phy1);

	//rx_ring
	NdisMAllocateSharedMemory(
			adapter->MiniportAdapterHandle,
			NUM_RX_DESC * sizeof(RING_STRU),
			FALSE,//not cached
			(PVOID)&adapter->rx_ring, //虚拟地址
			&PhysicalAddress //物理地址
			);
	if(adapter->rx_ring == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	adapter->rx_ring_dma = PhysicalAddress;
	phy = NdisGetPhysicalAddressLow(PhysicalAddress);

	//align to 32?
	DbgPrint("rx_ring=%x, rx_ring_dma=%x \n", adapter->rx_ring, phy);
	for(i = 0; i < NUM_RX_DESC; i ++){
		adapter->rx_ring[i].link = phy + (i+1) * sizeof(RING_STRU);
		adapter->rx_ring[i].cmdsts = RX_BUF_SIZE;
		adapter->rx_ring[i].bufptr = phy1 + i * RX_BUF_SIZE;
		DbgPrint("rx_ring[%x]=(v)%x(p)%x,link=%x,cmdsts=%x,bufptr=%x \n", 
			i, &adapter->rx_ring[i],
			NdisGetPhysicalAddressLow(MmGetPhysicalAddress(adapter->rx_ring+i)),
			adapter->rx_ring[i].link, 
			adapter->rx_ring[i].cmdsts, 
			adapter->rx_ring[i].bufptr);
	}
	adapter->rx_ring[i-1].link = phy;

	/* load Receive Descriptor Register */
	NdisRawWritePortUlong(adapter->ioaddr + rxdp, phy);
	NdisRawWritePortUlong(adapter->ioaddr + cr, RxENA);

	adapter->dirty_tx = 0;
	adapter->cur_tx = 0;
	adapter->free_tx = NUM_TX_DESC;

	adapter->dirty_rx = 0;
//	adapter->cur_rx = 0;
	adapter->free_rx = NUM_RX_DESC;

	Status = allocpool(adapter);

    // Init the packet filter to directed and multicast.
    adapter->PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_MULTICAST;
	for(i = 0; i < 8; i ++)
		adapter->mc_filter[i]=0xffff;


	return Status;
}

NDIS_STATUS
allocpool(
	PADAPTER adapter
	)
{
	UINT		i;
	NDIS_STATUS	Status;


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

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

	//分配 pkt_desc & buf_desc
	for(i =0; i < NUM_RX_DESC; i ++){
		NdisAllocatePacket(
			&Status,
			&adapter->rx_pkt[i],
			adapter->pkt_pool
			);
		if(Status != NDIS_STATUS_SUCCESS)
			return STATUS_INSUFFICIENT_RESOURCES;

		NdisAllocateBuffer(
			&Status,
			&adapter->rx_buf[i],
			adapter->buf_pool,
			adapter->rx_bufs + i * RX_BUF_SIZE,
			RX_BUF_SIZE
			);
		if(Status != NDIS_STATUS_SUCCESS)
			return STATUS_INSUFFICIENT_RESOURCES;

		//connection buf_desc->pkt_desc
		NdisChainBufferAtBack(
			adapter->rx_pkt[i],
			adapter->rx_buf[i]
			);

		NDIS_SET_PACKET_STATUS(adapter->rx_pkt[i], NDIS_STATUS_RESOURCES);
		NDIS_SET_PACKET_HEADER_SIZE(adapter->rx_pkt[i], MAC_HEADER_SIZE);
	}

	return NDIS_STATUS_SUCCESS;
}


//IRQL:DISPATCH_LEVEL
//USED BY RIsrDpc
VOID
TxInt(
	PADAPTER adapter
	)
/*++
	发送中断处理
--*/
{
	u32			tx_status;
	UINT		dirty_tx = adapter->dirty_tx;
	NDIS_STATUS	Status;

	do{
		adapter->free_tx ++;

		tx_status = adapter->tx_ring[dirty_tx].cmdsts;
		DbgPrint("TxInt:free tx_ring[%x].cmdsts=%x.\n", dirty_tx, tx_status);

		if(tx_status & OWN){
			DbgPrint("TxInt:own not be clear. \n");
			break;//极少情况
		}

		//
		if(adapter->tx_complete[dirty_tx].pkt == NULL){//use tx_bufs
			DbgPrint("use tx_bufs. \n");
			adapter->free_tx_bufs ++;
			adapter->XMIT_OK ++;
		}else{

		//FREE res
		NdisMCompleteBufferPhysicalMapping(
			adapter->MiniportAdapterHandle,
			adapter->tx_complete[dirty_tx].buff,
			adapter->tx_complete[dirty_tx].MapReg
			);

		if(! (tx_status & MORE)){//是 xmit pkt 的最后一个 desc
			if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
				/* packet unsuccessfully transmitted */
				DbgPrint("Transmit error, Tx status %8.8x.\n", tx_status);
				adapter->ERR_COUNT ++;
				adapter->XMIT_ERR ++;

				Status = NDIS_STATUS_FAILURE;
			} else {
				/* packet successfully transmitted */
				adapter->XMIT_OK ++;
				Status = NDIS_STATUS_SUCCESS;
			}

			//FREE res
			NdisMSendComplete(
				adapter->MiniportAdapterHandle,
				adapter->tx_complete[dirty_tx].pkt,
				Status
				);
		}//if
		}//if use tx_bufs

		adapter->tx_ring[dirty_tx].cmdsts = 0;
		adapter->tx_ring[dirty_tx].bufptr = 0;
		dirty_tx = NextTxDesc(dirty_tx);

	}while(dirty_tx != adapter->cur_tx);

	adapter->dirty_tx = dirty_tx;
}

VOID
RxInt(
	PADAPTER adapter
	)
/*++
	接收中断处理
--*/
{
	UCHAR			TmpCMD;
	UINT			NumOfPkt = 0;
	PNDIS_PACKET	RevPacket[NUM_RX_DESC];

	UINT			i;
	NDIS_STATUS		Status;

	u32			rx_status;
	UINT		dirty_rx = adapter->dirty_rx;


	NDIS_SET_PACKET_STATUS(adapter->rx_pkt[dirty_rx], NDIS_STATUS_RESOURCES);
//	NDIS_SET_PACKET_HEADER_SIZE(adapter->rx_pkt[dirty_rx], MAC_HEADER_SIZE);

	do{
		if(adapter->free_rx == 0){//资源缺,包丢失
			DbgPrint("RxInt:rx_ring not enought. \n");
			adapter->RCV_ERR --;
			break;
		}

		rx_status = adapter->rx_ring[dirty_rx].cmdsts;
		DbgPrint("RxInt:rx_ring[%x].cmdsts=%x. \n", dirty_rx, rx_status);
		if(!(rx_status & OWN)){
			adapter->RCV_NO_BUFFER ++;
			break;
		}

		if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
			/* corrupted packet received */
			adapter->RCV_ERR ++;
			adapter->ERR_COUNT ++;
		}else{
			adapter->RCV_OK ++;
			//修改 rev 长度
			NdisAdjustBufferLength(
				adapter->rx_buf[dirty_rx],
				(rx_status & DSIZE)-CRC_SIZE
				);

			RevPacket[NumOfPkt] = adapter->rx_pkt[dirty_rx];
			NumOfPkt ++;

			adapter->free_rx --;
		}
		/* reset buffer descriptor state */
		adapter->rx_ring[dirty_rx].cmdsts = RX_BUF_SIZE;

		dirty_rx = NextTxDesc(dirty_rx);
	}while(TRUE);

	adapter->dirty_rx = dirty_rx;
	

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

		for(i = 0; i < NumOfPkt; i ++){
			Status = NDIS_GET_PACKET_STATUS(RevPacket[i]);
			if(Status != NDIS_STATUS_PENDING){
				adapter->free_rx ++;//get back res
				DbgPrint("rxint:get back res. adapter->RCV_OK=%x \n", adapter->RCV_OK);
			}else
				DbgPrint("the rx res not be free back.\n");
		}//for
	}
}

/*  EEPROM_Ctrl bits. */
#define EECLK	0x04	/* EEPROM shift clock. */
#define EECS	0x08	/* EEPROM chip select. */
#define EEDI	0x01	/* EEPROM chip data in. */
#define EEDO	0x02	/* EEPROM chip data out. */
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD	(5)
#define EE_READ_CMD		(6) //110
#define EE_ERASE_CMD	(7)

//
USHORT
ReadEEPROM(
		PADAPTER	adapter,
		USHORT		ReadReg, //6 bit addr
		UCHAR		addrlen
		)
{
	int			i;
	ULONG		TmpVal;
	USHORT		retval = 0;

	PUCHAR	ioaddr = adapter->ioaddr + mear; 

	ReadReg &= 0x3f;
	ReadReg |= EE_READ_CMD << addrlen; //加上命令前缀 110

	NdisRawWritePortUlong(ioaddr, EECS); //select chip

	for(i = addrlen + 2; i >= 0; i --){//串行写入
		TmpVal = (ReadReg & (1 << i)) ? EEDI : 0;
		NdisRawWritePortUlong(ioaddr, EECS | TmpVal);
		NdisRawWritePortUlong(ioaddr, EECS | TmpVal | EECLK); //raise clk
	}

	NdisRawWritePortUlong(ioaddr, EECS); //low clk

	//read result
	for(i = 0; i < 16; i ++){
		NdisRawWritePortUlong(ioaddr, EECS | EECLK); //raise clk
		NdisRawReadPortUlong(ioaddr, &TmpVal);
		TmpVal &= EEDO;
		retval = (retval << 1) | (TmpVal ? 1 : 0);
		NdisRawWritePortUlong(ioaddr, EECS); //low clk
	}
	NdisRawWritePortUlong(ioaddr, ~EECS);

	return retval;
}//finish


VOID
init_rxfilter(
		PADAPTER	adapter
		)
{
	ULONG	rfcrSave;
	ULONG	i;
	USHORT	w;

	NdisRawReadPortUlong(adapter->ioaddr + rfcr, &rfcrSave);

	/* disable packet filtering before setting filter */
	NdisRawWritePortUlong(adapter->ioaddr + rfcr, rfcrSave & ~RFEN);

	/* load MAC addr to filter data register */
	for (i = 0 ; i < 3 ; i++) {
		w = ((PUSHORT)adapter->NetworkAddress)[i];
		NdisRawWritePortUlong(adapter->ioaddr + rfcr, i << RFADDR_shift);
		NdisRawWritePortUlong(adapter->ioaddr + rfdr, w);
	}

	/* enable packet filitering */
	NdisRawWritePortUlong(adapter->ioaddr + rfcr, rfcrSave | RFEN);
}

VOID
set_rx_mode(
		PADAPTER	adapter
		)
{
	/* 128 bits multicast hash table */
	int		i;
	ULONG	rx_mode;

	/* too many multicast addresses or accept all multicast packet */
	rx_mode = RFAAB | RFAAM;

	/* update Multicast Hash Table in Receive Filter */
	for (i = 0; i < 8; i++) {
        /* why plus 0x04 ??, That makes the correct value for hash table. */
		NdisRawWritePortUlong(adapter->ioaddr + rfcr, (ULONG)(0x00000004+i) << RFADDR_shift);
		NdisRawWritePortUlong(adapter->ioaddr + rfdr, adapter->mc_filter[i]);
	}

	NdisRawWritePortUlong(adapter->ioaddr + rfcr, RFEN | rx_mode);

	return;
}

VOID
check_mode(
		PADAPTER	adapter
		)
{
	int speed, duplex;
	u32 tx_flags = 0, rx_flags = 0;

	read_mode(adapter, &speed, &duplex);

	tx_flags = TxATP | (TX_DMA_BURST << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
	rx_flags = RX_DMA_BURST << RxMXDMA_shift;

	if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS ) {
		rx_flags |= (RxDRNT_10 << RxDRNT_shift);
		tx_flags |= (TxDRNT_10 << TxDRNT_shift);
	}
	else {
		rx_flags |= (RxDRNT_100 << RxDRNT_shift);
		tx_flags |= (TxDRNT_100 << TxDRNT_shift);
	}

	if (duplex == FDX_CAPABLE_FULL_SELECTED) {
		tx_flags |= (TxCSI | TxHBI);
		rx_flags |= RxATX;
	}

	NdisRawWritePortUlong(adapter->ioaddr + txcfg, tx_flags);
	NdisRawWritePortUlong(adapter->ioaddr + rx_flags, rxcfg);
}

VOID
read_mode(
		PADAPTER	adapter,
		UINT		*speed,
		UINT		*duplex
		)
{
	int		i = 0;
	u32		status;
//	ULONG	TmpSt;

	/* STSOUT register is Latched on Transition, read operation updates it */
//	while (i++ < 2)	status = mdio_read(net_dev, phy_addr, MII_STSOUT);

	status = ACCESS_bit | RWCMD_read | MII_STSOUT<<REGADDR_shift;
	NdisRawWritePortUlong(adapter->ioaddr + epar, status);
	NdisRawWritePortUlong(adapter->ioaddr + epar, status);

	i = 10;
	do{
		NdisRawReadPortUlong(adapter->ioaddr + epar, &status);
	}while((status & ACCESS_bit) && (--i > 0));
	if(i <= 0)
		DbgPrint("Read MII_STSOUT failure. \n");
	status >>= 16;

	if (status & MII_STSOUT_SPD)
		*speed = HW_SPEED_100_MBPS;
	else
		*speed = HW_SPEED_10_MBPS;

	if (status & MII_STSOUT_DPLX)
		*duplex = FDX_CAPABLE_FULL_SELECTED;
	else
		*duplex = FDX_CAPABLE_HALF_SELECTED;

	if (status & MII_STSOUT_LINK_FAIL)
		DbgPrint("link err. \n");
	else
		DbgPrint("Media Link On %s %s-duplex \n",
		       *speed == HW_SPEED_100_MBPS ?
		       "100mbps" : "10mbps",
		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
		       "full" : "half");
}

VOID
PrintRxStatus(
		PADAPTER	adapter
		)
{
	UINT	i;
	u32		status;


	NdisRawReadPortUlong(adapter->ioaddr + isr, &status);
	DbgPrint("isr=%x \n", status);

	for(i = 0; i < NUM_RX_DESC; i ++){
		DbgPrint("rx_ring[%x].cmdsts=%x \n", i, adapter->rx_ring[i].cmdsts);
	}

	for(i = 0; i < NUM_TX_DESC; i ++){
		DbgPrint("tx_ring[%x].cmdsts=%x \n", i, adapter->tx_ring[i].cmdsts);
	}
}


USHORT
opPHY(
		PADAPTER	adapter,
		UCHAR		reg,
		UCHAR		op,
		USHORT		data
		)
{
	int		i = 0;
	u32		status;

	status = ACCESS_bit | op | reg<<REGADDR_shift | data << PHYDATA_shift;
	NdisRawWritePortUlong(adapter->ioaddr + epar, status);
	NdisMSleep(100);

	i = 10;
	do{
		NdisRawReadPortUlong(adapter->ioaddr + epar, &status);
	}while((status & ACCESS_bit) && (--i > 0));
	if(i <= 0)
		DbgPrint("Read MII_PHY failure. \n");
	
	return (USHORT)(status >> 16);
}

//status|MII_CNTL_SPEED|MII_CNTL_AUTO|MII_CNTL_FDX
VOID
setPHY(
	   PADAPTER	adapter
	   )
{
	USHORT status;

	status = opPHY(adapter, MII_CONTROL, RWCMD_read, 0);
	DbgPrint("MII_CONTROL.status=%x \n", status);

	status = opPHY(adapter, MII_CONTROL, RWCMD_write, status|MII_CNTL_AUTO);
	DbgPrint("MII_CONTROL.status=%x \n", status);

	status = opPHY(adapter, MII_CONTROL, RWCMD_read, 0);
	DbgPrint("MII_CONTROL.status=%x \n", status);
}


⌨️ 快捷键说明

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