📄 pcnet.c
字号:
/* initialize tx descriptors */
TransmitDescriptor = Adapter->TransmitDescriptorRingVirt;
for(i = 0; i < NUMBER_OF_BUFFERS; i++)
{
(TransmitDescriptor+i)->TBADR = (ULONG)Adapter->TransmitBufferPtrPhys + i * BUFFER_SIZE;
(TransmitDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */
(TransmitDescriptor+i)->FLAGS = TD1_STP | TD1_ENP;
}
DPRINT("transmit ring initialized\n");
/* initialize rx */
ReceiveDescriptor = Adapter->ReceiveDescriptorRingVirt;
for(i = 0; i < NUMBER_OF_BUFFERS; i++)
{
(ReceiveDescriptor+i)->RBADR = (ULONG)Adapter->ReceiveBufferPtrPhys + i * BUFFER_SIZE;
(ReceiveDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */
(ReceiveDescriptor+i)->FLAGS = RD_OWN;
}
DPRINT("receive ring initialized\n");
return NDIS_STATUS_SUCCESS;
}
static VOID
MiPrepareInitializationBlock(
PADAPTER Adapter)
/*
* FUNCTION: Initialize the initialization block
* ARGUMENTS:
* Adapter: pointer to the miniport's adapter object
*/
{
ULONG i = 0;
RtlZeroMemory(Adapter->InitializationBlockVirt, sizeof(INITIALIZATION_BLOCK));
/* read burned-in address from card */
for(i = 0; i < 6; i++)
NdisRawReadPortUchar(Adapter->PortOffset + i, Adapter->InitializationBlockVirt->PADR + i);
DPRINT("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
Adapter->InitializationBlockVirt->PADR[0],
Adapter->InitializationBlockVirt->PADR[1],
Adapter->InitializationBlockVirt->PADR[2],
Adapter->InitializationBlockVirt->PADR[3],
Adapter->InitializationBlockVirt->PADR[4],
Adapter->InitializationBlockVirt->PADR[5]);
/* set up receive ring */
DPRINT("Receive ring physical address: 0x%x\n", Adapter->ReceiveDescriptorRingPhys);
Adapter->InitializationBlockVirt->RDRA = (ULONG)Adapter->ReceiveDescriptorRingPhys;
Adapter->InitializationBlockVirt->RLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
/* set up transmit ring */
DPRINT("Transmit ring physical address: 0x%x\n", Adapter->TransmitDescriptorRingPhys);
Adapter->InitializationBlockVirt->TDRA = (ULONG)Adapter->TransmitDescriptorRingPhys;
Adapter->InitializationBlockVirt->TLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
}
static VOID
MiFreeSharedMemory(
PADAPTER Adapter)
/*
* FUNCTION: Free all allocated shared memory
* ARGUMENTS:
* Adapter: pointer to the miniport's adapter struct
*/
{
NDIS_PHYSICAL_ADDRESS PhysicalAddress;
PhysicalAddress.u.HighPart = 0;
if(Adapter->InitializationBlockVirt)
{
PhysicalAddress.u.LowPart = (ULONG)Adapter->InitializationBlockPhys;
NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength,
FALSE, Adapter->InitializationBlockVirt, PhysicalAddress);
}
if(Adapter->TransmitDescriptorRingVirt)
{
PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitDescriptorRingPhys;
NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength,
FALSE, Adapter->TransmitDescriptorRingVirt, PhysicalAddress);
}
if(Adapter->ReceiveDescriptorRingVirt)
{
PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveDescriptorRingPhys;
NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength,
FALSE, Adapter->ReceiveDescriptorRingVirt, PhysicalAddress);
}
if(Adapter->TransmitBufferPtrVirt)
{
PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitBufferPtrPhys;
NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength,
FALSE, Adapter->TransmitBufferPtrVirt, PhysicalAddress);
}
if(Adapter->ReceiveBufferPtrVirt)
{
PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveBufferPtrPhys;
NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength,
FALSE, Adapter->ReceiveBufferPtrVirt, PhysicalAddress);
}
}
static BOOLEAN
STDCALL
MiSyncStop(
IN PVOID SynchronizeContext)
/*
* FUNCTION: Stop the adapter
* ARGUMENTS:
* SynchronizeContext: Adapter context
*/
{
PADAPTER Adapter = (PADAPTER)SynchronizeContext;
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP);
return TRUE;
}
static VOID
STDCALL
MiniportHalt(
IN NDIS_HANDLE MiniportAdapterContext)
/*
* FUNCTION: Stop the adapter and release any per-adapter resources
* ARGUMENTS:
* MiniportAdapterContext: context specified to NdisMSetAttributes
* NOTES:
* - Called by NDIS at PASSIVE_LEVEL
*/
{
PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
BOOLEAN TimerCancelled;
DPRINT("Called\n");
ASSERT(Adapter);
/* stop the media detection timer */
NdisMCancelTimer(&Adapter->MediaDetectionTimer, &TimerCancelled);
/* stop the chip */
NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStop, Adapter);
/* deregister the interrupt */
NdisMDeregisterInterrupt(&Adapter->InterruptObject);
/* deregister i/o port range */
NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, (PVOID)Adapter->PortOffset);
/* free shared memory */
MiFreeSharedMemory(Adapter);
/* free map registers */
NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle);
/* free the lock */
NdisFreeSpinLock(&Adapter->Lock);
/* free the adapter */
NdisFreeMemory(Adapter, 0, 0);
}
static BOOLEAN
STDCALL
MiSyncMediaDetection(
IN PVOID SynchronizeContext)
/*
* FUNCTION: Stop the adapter
* ARGUMENTS:
* SynchronizeContext: Adapter context
*/
{
PADAPTER Adapter = (PADAPTER)SynchronizeContext;
NDIS_MEDIA_STATE MediaState = MiGetMediaState(Adapter);
DPRINT("Called\n");
DPRINT("MediaState: %d\n", MediaState);
if (MediaState != Adapter->MediaState)
{
Adapter->MediaState = MediaState;
return TRUE;
}
return FALSE;
}
static VOID
STDCALL
MiniportMediaDetectionTimer(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
/*
* FUNCTION: Periodially query media state
* ARGUMENTS:
* FunctionContext: Adapter context
* NOTES:
* - Called by NDIS at DISPATCH_LEVEL
*/
{
PADAPTER Adapter = (PADAPTER)FunctionContext;
if (NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject,
MiSyncMediaDetection,
FunctionContext))
{
NdisMIndicateStatus(Adapter->MiniportAdapterHandle,
Adapter->MediaState == NdisMediaStateConnected ?
NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT,
(PVOID)0, 0);
NdisMIndicateStatusComplete(Adapter->MiniportAdapterHandle);
}
}
static VOID
MiInitChip(
PADAPTER Adapter)
/*
* FUNCTION: Initialize and start the PCNET chip
* ARGUMENTS:
* Adapter: pointer to the miniport's adapter struct
* NOTES:
* - should be coded to detect failure and return an error
* - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that.
*/
{
USHORT Data = 0;
DPRINT("Called\n");
/*
* first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset
* twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the
* card is reset by reading from the reset register. on reset it's in 16-bit i/o mode.
*/
NdisRawReadPortUshort(Adapter->PortOffset + RESET32, &Data);
NdisRawReadPortUshort(Adapter->PortOffset + RESET16, &Data);
/* stop the chip */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP);
/* pause for 1ms so the chip will have time to reset */
NdisStallExecution(1);
DPRINT("chip stopped\n");
/* set the software style to 2 (32 bits) */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR58);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
Data |= SW_STYLE_2;
NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
/* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
Data |= CSR4_APAD_XMT | /* CSR4_DPOLL |*/ CSR4_TXSTRTM | CSR4_DMAPLUS;
NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
/* set up bcr18: burst read/write enable */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR18);
NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data);
Data |= BCR18_BREADE | BCR18_BWRITE ;
NdisRawWritePortUshort(Adapter->PortOffset + BDP, Data);
/* set up csr1 and csr2 with init block */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR1);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys & 0xffff));
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR2);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys >> 16) & 0xffff);
DPRINT("programmed with init block\n");
/* Set mode to 0 */
Data = 0;
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR15);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
/* load init block and start the card */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA);
/* detect the media state */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4);
NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR4_LNKSTE|BCR4_FDLSE);
Adapter->MediaState = MiGetMediaState(Adapter);
DPRINT("card started\n");
Adapter->Flags &= ~RESET_IN_PROGRESS;
}
#if DBG
static BOOLEAN
MiTestCard(
PADAPTER Adapter)
/*
* FUNCTION: Test the NIC
* ARGUMENTS:
* Adapter: pointer to the miniport's adapter struct
* RETURNS:
* TRUE if the test succeeds
* FALSE otherwise
* NOTES:
* - this is where to add diagnostics. This is called
* at the very end of initialization.
*/
{
int i = 0;
UCHAR address[6];
USHORT Data = 0;
/* see if we can read/write now */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("Port 0x%x RAP 0x%x CSR0 0x%x RDP 0x%x, Interupt status register is 0x%x\n", Adapter->PortOffset, RAP, CSR0, RDP, Data);
/* read the BIA */
for(i = 0; i < 6; i++)
NdisRawReadPortUchar(Adapter->PortOffset + i, &address[i]);
DPRINT("burned-in address: %x:%x:%x:%x:%x:%x\n", address[0], address[1], address[2], address[3], address[4], address[5]);
/* Read status flags from CSR0 */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("CSR0: 0x%x\n", Data);
/* Read status flags from CSR3 */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR3);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("CSR3: 0x%x\n", Data);
/* Read status flags from CSR4 */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("CSR4: 0x%x\n", Data);
/* Read status flags from CSR5 */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR5);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("CSR5: 0x%x\n", Data);
/* Read status flags from CSR6 */
NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR6);
NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
DPRINT("CSR6: 0x%x\n", Data);
return TRUE;
}
#endif
static NDIS_STATUS
STDCALL
MiniportInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext)
/*
* FUNCTION: Initialize a new miniport
* ARGUMENTS:
* OpenErrorStatus: pointer to a var to return status info in
* SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3)
* MediumArray: array of media that we can pick from
* MediumArraySize: size of MediumArray
* MiniportAdapterHandle: NDIS-assigned handle for this miniport instance
* WrapperConfigurationContext: temporary NDIS-assigned handle for passing
* to configuration APIs
* RETURNS:
* NDIS_STATUS_SUCCESS on success
* NDIS_STATUS_FAILURE on general failure
* NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray
* NDIS_STATUS_RESOURCES on insufficient system resources
* NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
* NOTES:
* - Called by NDIS at PASSIVE_LEVEL, once per detected card
* - Will int 3 on failure of MiTestCard if DBG=1
*/
{
UINT i = 0;
PADAPTER Adapter = 0;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
BOOLEAN InterruptRegistered = FALSE;
/* Pick a medium */
for(i = 0; i < MediumArraySize; i++)
if(MediumArray[i] == NdisMedium802_3)
break;
if(i == MediumArraySize)
{
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
DPRINT1("unsupported media\n");
BREAKPOINT;
*OpenErrorStatus = Status;
return Status;
}
*SelectedMediumIndex = i;
/* allocate our adapter struct */
Status = NdisAllocateMemoryWithTag((PVOID *)&Adapter, sizeof(ADAPTER), PCNET_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -