📄 io.c
字号:
PVOID CurrentVa;
ULONG TotalLength;
PHYSICAL_ADDRESS ReturnedAddress;
UINT LoopCount = 0;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT(MiniportAdapterHandle && Buffer && PhysicalAddressArray && ArraySize);
Adapter = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
CurrentVa = MmGetMdlVirtualAddress(Buffer);
TotalLength = MmGetMdlByteCount(Buffer);
while(TotalLength)
{
ULONG Length = TotalLength;
ReturnedAddress = Adapter->SystemAdapterObject->DmaOperations->MapTransfer(
Adapter->SystemAdapterObject, Buffer,
Adapter->MapRegisters[PhysicalMapRegister].MapRegister,
CurrentVa, &Length, WriteToDevice);
Adapter->MapRegisters[PhysicalMapRegister].WriteToDevice = WriteToDevice;
PhysicalAddressArray[LoopCount].PhysicalAddress = ReturnedAddress;
PhysicalAddressArray[LoopCount].Length = Length;
TotalLength -= Length;
CurrentVa = (PVOID)((ULONG_PTR)CurrentVa + Length);
LoopCount++;
}
*ArraySize = LoopCount;
}
/*
* @implemented
*/
VOID
EXPORT
NdisMCompleteBufferPhysicalMapping(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_BUFFER Buffer,
IN ULONG PhysicalMapRegister)
/*
* FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
* ARGUMENTS:
* - MiniportAdapterHandle: handle originally input to MiniportInitialize
* - Buffer: NDIS_BUFFER to complete the mapping on
* - PhyscialMapRegister: the chosen map register
* NOTES:
* - May be called at IRQL <= DISPATCH_LEVEL
*/
{
PNDIS_MINIPORT_BLOCK Adapter;
VOID *CurrentVa;
ULONG Length;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT(MiniportAdapterHandle && Buffer);
Adapter = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
CurrentVa = MmGetMdlVirtualAddress(Buffer);
Length = MmGetMdlByteCount(Buffer);
Adapter->SystemAdapterObject->DmaOperations->FlushAdapterBuffers(
Adapter->SystemAdapterObject, Buffer,
Adapter->MapRegisters[PhysicalMapRegister].MapRegister,
CurrentVa, Length,
Adapter->MapRegisters[PhysicalMapRegister].WriteToDevice);
}
/*
* @unimplemented
*/
VOID
EXPORT
NdisMDeregisterDmaChannel(
IN PNDIS_HANDLE MiniportDmaHandle)
{
UNIMPLEMENTED
}
/*
* @implemented
*/
VOID
EXPORT
NdisMDeregisterInterrupt(
IN PNDIS_MINIPORT_INTERRUPT Interrupt)
/*
* FUNCTION: Releases an interrupt vector
* ARGUMENTS:
* Interrupt = Pointer to interrupt object
*/
{
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
IoDisconnectInterrupt(Interrupt->InterruptObject);
}
/*
* @unimplemented
*/
VOID
EXPORT
NdisMDeregisterIoPortRange(
IN NDIS_HANDLE MiniportAdapterHandle,
IN UINT InitialPort,
IN UINT NumberOfPorts,
IN PVOID PortOffset)
/*
* FUNCTION: Releases a register mapping to I/O ports
* ARGUMENTS:
* MiniportAdapterHandle = Specifies handle input to MiniportInitialize
* InitialPort = Bus-relative base port address of a range to be mapped
* NumberOfPorts = Specifies number of ports to be mapped
* PortOffset = Pointer to mapped base port address
*/
{
NDIS_DbgPrint(MAX_TRACE, ("called - IMPLEMENT ME.\n"));
}
/*
* @implemented
*/
VOID
EXPORT
NdisMFreeMapRegisters(
IN NDIS_HANDLE MiniportAdapterHandle)
/*
* FUNCTION: Free previously allocated map registers
* ARGUMENTS:
* MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
* NOTES:
*/
{
KIRQL OldIrql;
PNDIS_MINIPORT_BLOCK Adapter = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
PDMA_ADAPTER AdapterObject;
UINT MapRegistersPerBaseRegister;
UINT i;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
ASSERT(Adapter);
/* only bus masters may call this routine */
ASSERT(Adapter->Flags & NDIS_ATTRIBUTE_BUS_MASTER);
if(!(Adapter->Flags & NDIS_ATTRIBUTE_BUS_MASTER) ||
Adapter->SystemAdapterObject == NULL)
return;
MapRegistersPerBaseRegister = ((Adapter->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
AdapterObject = Adapter->SystemAdapterObject;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
{
for(i = 0; i < Adapter->BaseMapRegistersNeeded; i++)
{
AdapterObject->DmaOperations->FreeMapRegisters(
Adapter->SystemAdapterObject,
Adapter->MapRegisters[i].MapRegister,
MapRegistersPerBaseRegister);
}
}
KeLowerIrql(OldIrql);
AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
Adapter->SystemAdapterObject = NULL;
ExFreePool(Adapter->MapRegisters);
}
/*
* @implemented
*/
NDIS_STATUS
EXPORT
NdisMMapIoSpace(
OUT PVOID *VirtualAddress,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
IN UINT Length)
/*
* FUNCTION: Maps a bus-relative address to a system-wide virtual address
* ARGUMENTS:
* VirtualAddress: receives virtual address of mapping
* MiniportAdapterHandle: Handle originally input to MiniportInitialize
* PhysicalAddress: bus-relative address to map
* Length: Number of bytes to map
* RETURNS:
* NDIS_STATUS_SUCCESS: the operation completed successfully
* NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
* NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
* NDIS_STATUS_FAILURE: a general failure has occured
* NOTES:
* - Must be called at IRQL = PASSIVE_LEVEL
* BUGS:
* - Only supports things that MmMapIoSpace internally supports - what
* about considering bus type, etc?
* - doesn't track resources allocated...
*/
{
PAGED_CODE();
ASSERT(VirtualAddress && MiniportAdapterHandle);
*VirtualAddress = MmMapIoSpace(PhysicalAddress, Length, MmNonCached);
if(!*VirtualAddress)
return NDIS_STATUS_RESOURCES;
return NDIS_STATUS_SUCCESS;
}
/*
* @implemented
*/
ULONG
EXPORT
NdisMReadDmaCounter(
IN NDIS_HANDLE MiniportDmaHandle)
{
PNDIS_MINIPORT_BLOCK MiniportBlock = (PNDIS_MINIPORT_BLOCK)MiniportDmaHandle;
PDMA_ADAPTER AdapterObject = MiniportBlock->SystemAdapterObject;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
if (AdapterObject == NULL)
return 0;
return AdapterObject->DmaOperations->ReadDmaCounter(AdapterObject);
}
/*
* @implemented
*/
ULONG
EXPORT
NdisMGetDmaAlignment(
IN NDIS_HANDLE MiniportDmaHandle)
{
PNDIS_MINIPORT_BLOCK MiniportBlock = (PNDIS_MINIPORT_BLOCK)MiniportDmaHandle;
PDMA_ADAPTER AdapterObject = MiniportBlock->SystemAdapterObject;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
if (AdapterObject == NULL)
return 0;
return AdapterObject->DmaOperations->GetDmaAlignment(AdapterObject);
}
/*
* @unimplemented
*/
NDIS_STATUS
EXPORT
NdisMRegisterDmaChannel(
OUT PNDIS_HANDLE MiniportDmaHandle,
IN NDIS_HANDLE MiniportAdapterHandle,
IN UINT DmaChannel,
IN BOOLEAN Dma32BitAddresses,
IN PNDIS_DMA_DESCRIPTION DmaDescription,
IN ULONG MaximumLength)
{
UNIMPLEMENTED
return NDIS_STATUS_FAILURE;
}
/*
* @implemented
*/
NDIS_STATUS
EXPORT
NdisMRegisterInterrupt(
OUT PNDIS_MINIPORT_INTERRUPT Interrupt,
IN NDIS_HANDLE MiniportAdapterHandle,
IN UINT InterruptVector,
IN UINT InterruptLevel,
IN BOOLEAN RequestIsr,
IN BOOLEAN SharedInterrupt,
IN NDIS_INTERRUPT_MODE InterruptMode)
/*
* FUNCTION: Claims access to an interrupt vector
* ARGUMENTS:
* Interrupt = Address of interrupt object to initialize
* MiniportAdapterHandle = Specifies handle input to MiniportInitialize
* InterruptVector = Specifies bus-relative vector to register
* InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
* RequestIsr = TRUE if MiniportISR should always be called
* SharedInterrupt = TRUE if other devices may use the same interrupt
* InterruptMode = Specifies type of interrupt
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
ULONG MappedIRQ;
KIRQL DIrql;
KAFFINITY Affinity;
PNDIS_MINIPORT_BLOCK Adapter = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
"SharedInterrupt (%d) InterruptMode (0x%X)\n",
InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode));
RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT));
KeInitializeSpinLock(&Interrupt->DpcCountLock);
KeInitializeDpc(&Interrupt->InterruptDpc, HandleDeferredProcessing, Adapter);
KeInitializeEvent(&Interrupt->DpcsCompletedEvent, NotificationEvent, FALSE);
Interrupt->SharedInterrupt = SharedInterrupt;
Adapter->Interrupt = Interrupt;
MappedIRQ = HalGetInterruptVector(Adapter->BusType, Adapter->BusNumber,
InterruptLevel, InterruptVector, &DIrql,
&Affinity);
NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ, Affinity));
Status = IoConnectInterrupt(&Interrupt->InterruptObject, ServiceRoutine, Adapter, &Interrupt->DpcCountLock, MappedIRQ,
DIrql, DIrql, InterruptMode, SharedInterrupt, Affinity, FALSE);
NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
if (NT_SUCCESS(Status))
return NDIS_STATUS_SUCCESS;
if (Status == STATUS_INSUFFICIENT_RESOURCES)
{
/* FIXME: Log error */
NDIS_DbgPrint(MIN_TRACE, ("Resource conflict!\n"));
return NDIS_STATUS_RESOURCE_CONFLICT;
}
NDIS_DbgPrint(MIN_TRACE, ("Function failed\n"));
return NDIS_STATUS_FAILURE;
}
/*
* @unimplemented
*/
NDIS_STATUS
EXPORT
NdisMRegisterIoPortRange(
OUT PVOID *PortOffset,
IN NDIS_HANDLE MiniportAdapterHandle,
IN UINT InitialPort,
IN UINT NumberOfPorts)
/*
* FUNCTION: Sets up driver access to device I/O ports
* ARGUMENTS:
* PortOffset = Address of buffer to place mapped base port address
* MiniportAdapterHandle = Specifies handle input to MiniportInitialize
* InitialPort = Bus-relative base port address of a range to be mapped
* NumberOfPorts = Specifies number of ports to be mapped
* RETURNS:
* Status of operation
*/
{
PHYSICAL_ADDRESS PortAddress, TranslatedAddress;
PNDIS_MINIPORT_BLOCK Adapter = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
ULONG AddressSpace = 1; /* FIXME The HAL handles this wrong atm */
NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts));
memset(&PortAddress, 0, sizeof(PortAddress));
/*
* FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
* we don't have a way to get the I/O base address yet (see
* NDIS_MINIPORT_BLOCK->AllocatedResources and
* NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
*/
if(InitialPort)
PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
else
ASSERT(FALSE);
NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart));
if(!HalTranslateBusAddress(Adapter->BusType, Adapter->BusNumber,
PortAddress, &AddressSpace, &TranslatedAddress))
{
NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
return NDIS_STATUS_RESOURCES;
}
NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart));
if(AddressSpace)
{
ASSERT(TranslatedAddress.u.HighPart == 0);
*PortOffset = (PVOID) TranslatedAddress.u.LowPart;
NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset));
return NDIS_STATUS_SUCCESS;
}
NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n"));
*PortOffset = 0;
*PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached);
NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset));
if(!*PortOffset)
return NDIS_STATUS_RESOURCES;
return NDIS_STATUS_SUCCESS;
}
/*
* @implemented
*/
VOID
EXPORT
NdisMUnmapIoSpace(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PVOID VirtualAddress,
IN UINT Length)
/*
* FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
* ARGUMENTS:
* MiniportAdapterHandle: handle originally passed into MiniportInitialize
* VirtualAddress: Address to un-map
* Length: length of the mapped memory space
* NOTES:
* - Must be called at IRQL = PASSIVE_LEVEL
* - Must only be called from MiniportInitialize and MiniportHalt
* - See also: NdisMMapIoSpace
* BUGS:
* - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
*/
{
PAGED_CODE();
ASSERT(MiniportAdapterHandle);
MmUnmapIoSpace(VirtualAddress, Length);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -