📄 driver.c
字号:
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 + -