2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: I/O related routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 Vizzini - DMA support
11 * 3 Oct 2003 Vizzini - Formatting and minor bugfixes
18 VOID STDCALL
HandleDeferredProcessing(
20 IN PVOID DeferredContext
,
21 IN PVOID SystemArgument1
,
22 IN PVOID SystemArgument2
)
24 * FUNCTION: Deferred interrupt processing routine
26 * Dpc = Pointer to DPC object
27 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
28 * SystemArgument1 = Unused
29 * SystemArgument2 = Unused
33 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
35 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
37 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
39 /* XXX try to grok WasBusy */
40 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
42 WasBusy
= Adapter
->MiniportBusy
;
43 Adapter
->MiniportBusy
= TRUE
;
45 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
47 /* Call the deferred interrupt service handler for this adapter */
48 (*Adapter
->Miniport
->Chars
.HandleInterruptHandler
)(
49 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
51 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
53 if ((!WasBusy
) && (Adapter
->WorkQueueHead
))
55 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
59 Adapter
->MiniportBusy
= WasBusy
;
62 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
64 /* re-enable the interrupt */
65 NDIS_DbgPrint(MAX_TRACE
, ("re-enabling the interrupt\n"));
66 if(Adapter
->Miniport
->Chars
.EnableInterruptHandler
)
67 (*Adapter
->Miniport
->Chars
.EnableInterruptHandler
)(
68 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
70 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
74 BOOLEAN STDCALL
ServiceRoutine(
75 IN PKINTERRUPT Interrupt
,
76 IN PVOID ServiceContext
)
78 * FUNCTION: Interrupt service routine
80 * Interrupt = Pointer to interrupt object
81 * ServiceContext = Pointer to context information (LOGICAL_ADAPTER)
83 * TRUE if a miniport controlled device generated the interrupt
86 BOOLEAN InterruptRecognized
;
87 BOOLEAN QueueMiniportHandleInterrupt
;
88 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(ServiceContext
);
90 NDIS_DbgPrint(MAX_TRACE
, ("Called. Adapter (0x%X)\n", Adapter
));
92 (*Adapter
->Miniport
->Chars
.ISRHandler
)(&InterruptRecognized
,
93 &QueueMiniportHandleInterrupt
,
94 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
96 if (QueueMiniportHandleInterrupt
)
98 NDIS_DbgPrint(MAX_TRACE
, ("Queueing DPC.\n"));
99 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.Interrupt
->InterruptDpc
, NULL
, NULL
);
102 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
104 return InterruptRecognized
;
113 NdisCompleteDmaTransfer(
114 OUT PNDIS_STATUS Status
,
115 IN PNDIS_HANDLE NdisDmaHandle
,
116 IN PNDIS_BUFFER Buffer
,
119 IN BOOLEAN WriteToDevice
)
131 IN PNDIS_BUFFER Buffer
,
132 IN BOOLEAN WriteToDevice
)
143 NdisGetCacheFillSize(
157 NdisImmediateReadPortUchar(
158 IN NDIS_HANDLE WrapperConfigurationContext
,
162 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
163 *Data
= READ_PORT_UCHAR((PUCHAR
)Port
); // FIXME: What to do with WrapperConfigurationContext?
172 NdisImmediateReadPortUlong(
173 IN NDIS_HANDLE WrapperConfigurationContext
,
177 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
178 *Data
= READ_PORT_ULONG((PULONG
)Port
); // FIXME: What to do with WrapperConfigurationContext?
187 NdisImmediateReadPortUshort(
188 IN NDIS_HANDLE WrapperConfigurationContext
,
192 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
193 *Data
= READ_PORT_USHORT((PUSHORT
)Port
); // FIXME: What to do with WrapperConfigurationContext?
202 NdisImmediateWritePortUchar(
203 IN NDIS_HANDLE WrapperConfigurationContext
,
207 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
208 WRITE_PORT_UCHAR((PUCHAR
)Port
, Data
); // FIXME: What to do with WrapperConfigurationContext?
217 NdisImmediateWritePortUlong(
218 IN NDIS_HANDLE WrapperConfigurationContext
,
222 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
223 WRITE_PORT_ULONG((PULONG
)Port
, Data
); // FIXME: What to do with WrapperConfigurationContext?
232 NdisImmediateWritePortUshort(
233 IN NDIS_HANDLE WrapperConfigurationContext
,
237 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
238 WRITE_PORT_USHORT((PUSHORT
)Port
, Data
); // FIXME: What to do with WrapperConfigurationContext?
242 IO_ALLOCATION_ACTION STDCALL
NdisMapRegisterCallback (
243 IN PDEVICE_OBJECT DeviceObject
,
245 IN PVOID MapRegisterBase
,
248 * FUNCTION: Called back during reservation of map registers
250 * DeviceObject: Device object of the deivce setting up DMA
251 * Irp: Reserved; must be ignored
252 * MapRegisterBase: Map registers assigned for transfer
253 * Context: LOGICAL_ADAPTER object of the requesting miniport
255 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
256 * - Called at IRQL = DISPATCH_LEVEL
259 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)Context
;
261 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
263 Adapter
->NdisMiniportBlock
.MapRegisters
[Adapter
->NdisMiniportBlock
.CurrentMapRegister
].MapRegister
= MapRegisterBase
;
265 NDIS_DbgPrint(MAX_TRACE
, ("setting event and leaving.\n"));
267 KeSetEvent(&Adapter
->DmaEvent
, 0, FALSE
);
269 /* this is only the thing to do for busmaster NICs */
270 return DeallocateObjectKeepRegisters
;
279 NdisMAllocateMapRegisters(
280 IN NDIS_HANDLE MiniportAdapterHandle
,
283 IN ULONG BaseMapRegistersNeeded
,
284 IN ULONG MaximumBufferSize
)
286 * FUNCTION: Allocate map registers for use in DMA transfers
288 * MiniportAdapterHandle: Passed in to MiniportInitialize
289 * DmaChannel: DMA channel to use
290 * DmaSize: bit width of DMA transfers
291 * BaseMapRegistersNeeded: number of base map registers requested
292 * MaximumBufferSize: largest single buffer transferred
294 * NDIS_STATUS_SUCCESS on success
295 * NDIS_STATUS_RESOURCES on failure
297 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
298 * I'm implementing the 2k one.
299 * - do not confuse a "base map register" with a "map register" - they
300 * are different. Only NDIS seems to use the base concept. The idea
301 * is that a miniport supplies the number of base map registers it will
302 * need, which is equal to the number of DMA send buffers it manages.
303 * NDIS then allocates a number of map registers to go with each base
304 * map register, so that a driver just has to send the base map register
305 * number during dma operations and NDIS can find the group of real
306 * map registers that represent the transfer.
307 * - Because of the above sillyness, you can only specify a few base map
308 * registers at most. a 1514-byte packet is two map registers at 4k
310 * - NDIS limits the total number of allocated map registers to 64,
311 * which (in the case of the above example) limits the number of base
312 * map registers to 32.
315 DEVICE_DESCRIPTION Description
;
316 PDMA_ADAPTER AdapterObject
= 0;
317 UINT MapRegistersPerBaseRegister
= 0;
318 ULONG AvailableMapRegisters
;
320 PLOGICAL_ADAPTER Adapter
= 0;
321 PDEVICE_OBJECT DeviceObject
= 0;
324 NDIS_DbgPrint(MAX_TRACE
, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
325 MiniportAdapterHandle
, DmaChannel
, DmaSize
, BaseMapRegistersNeeded
, MaximumBufferSize
));
327 memset(&Description
,0,sizeof(Description
));
329 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
333 /* only bus masters may call this routine */
334 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
335 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
))
336 return NDIS_STATUS_SUCCESS
;
338 DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
340 KeInitializeEvent(&Adapter
->DmaEvent
, NotificationEvent
, FALSE
);
341 KeInitializeSpinLock(&Adapter
->DmaLock
);
344 * map registers correlate to physical pages. ndis documents a
345 * maximum of 64 map registers that it will return.
346 * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
348 * the number of registers required for a given physical mapping
349 * is (first register + last register + one per page size),
350 * given that physical mapping is > 2.
353 /* unhandled corner case: {1,2}-byte max buffer size */
354 ASSERT(MaximumBufferSize
> 2);
355 MapRegistersPerBaseRegister
= ((MaximumBufferSize
-2) / (2*PAGE_SIZE
)) + 2;
357 Description
.Version
= DEVICE_DESCRIPTION_VERSION
;
358 Description
.Master
= TRUE
; /* implied by calling this function */
359 Description
.ScatterGather
= TRUE
; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
360 Description
.Dma32BitAddresses
= DmaSize
;
361 Description
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
362 Description
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
363 Description
.DmaChannel
= DmaChannel
;
364 Description
.MaximumLength
= MaximumBufferSize
;
366 if(Adapter
->NdisMiniportBlock
.AdapterType
== Isa
)
370 Description
.DmaWidth
= Width8Bits
;
372 Description
.DmaWidth
= Width16Bits
;
374 Description
.DmaSpeed
= Compatible
;
376 else if(Adapter
->NdisMiniportBlock
.AdapterType
== PCIBus
)
378 if(DmaSize
== NDIS_DMA_64BITS
)
379 Description
.Dma64BitAddresses
= TRUE
;
381 Description
.Dma32BitAddresses
= TRUE
;
385 NDIS_DbgPrint(MIN_TRACE
, ("Unsupported bus type\n"));
389 AdapterObject
= IoGetDmaAdapter(
390 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
391 &Description
, &AvailableMapRegisters
);
395 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate an adapter object; bailing out\n"));
396 return NDIS_STATUS_RESOURCES
;
399 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= AdapterObject
;
401 if(AvailableMapRegisters
< MapRegistersPerBaseRegister
)
403 NDIS_DbgPrint(MIN_TRACE
, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
404 MapRegistersPerBaseRegister
, AvailableMapRegisters
));
406 return NDIS_STATUS_RESOURCES
;
409 /* allocate & zero space in the miniport block for the registers */
410 Adapter
->NdisMiniportBlock
.MapRegisters
= ExAllocatePool(NonPagedPool
, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
411 if(!Adapter
->NdisMiniportBlock
.MapRegisters
)
413 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
414 return NDIS_STATUS_RESOURCES
;
417 memset(Adapter
->NdisMiniportBlock
.MapRegisters
, 0, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
418 Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= BaseMapRegistersNeeded
;
420 while(BaseMapRegistersNeeded
)
422 NDIS_DbgPrint(MAX_TRACE
, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded
));
424 BaseMapRegistersNeeded
--;
425 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= BaseMapRegistersNeeded
;
426 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
428 NtStatus
= AdapterObject
->DmaOperations
->AllocateAdapterChannel(
429 AdapterObject
, DeviceObject
, MapRegistersPerBaseRegister
,
430 NdisMapRegisterCallback
, Adapter
);
432 KeLowerIrql(OldIrql
);
434 if(!NT_SUCCESS(NtStatus
))
436 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus
));
437 return NDIS_STATUS_RESOURCES
;
440 NDIS_DbgPrint(MAX_TRACE
, ("waiting on event\n"));
442 NtStatus
= KeWaitForSingleObject(&Adapter
->DmaEvent
, Executive
, KernelMode
, FALSE
, 0);
444 if(!NT_SUCCESS(NtStatus
))
446 NDIS_DbgPrint(MIN_TRACE
, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus
));
447 return NDIS_STATUS_RESOURCES
;
450 NDIS_DbgPrint(MAX_TRACE
, ("resetting event\n"));
452 KeResetEvent(&Adapter
->DmaEvent
);
455 NDIS_DbgPrint(MAX_TRACE
, ("returning success\n"));
456 return NDIS_STATUS_SUCCESS
;
465 NdisMStartBufferPhysicalMapping(
466 IN NDIS_HANDLE MiniportAdapterHandle
,
467 IN PNDIS_BUFFER Buffer
,
468 IN ULONG PhysicalMapRegister
,
469 IN BOOLEAN WriteToDevice
,
470 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray
,
473 * FUNCTION: Sets up map registers for a bus-master DMA transfer
475 * MiniportAdapterHandle: handle originally input to MiniportInitialize
476 * Buffer: data to be transferred
477 * PhysicalMapRegister: specifies the map register to set up
478 * WriteToDevice: if true, data is being written to the device; else it is being read
479 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
480 * ArraySize: number of elements in PhysicalAddressArray
482 * - Must be called at IRQL <= DISPATCH_LEVEL
483 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes
484 * in order to map all of the virtual memory to physical memoroy readable
486 * - The caller supplies storage for the physical address array.
489 PLOGICAL_ADAPTER Adapter
= 0;
492 PHYSICAL_ADDRESS ReturnedAddress
;
495 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
496 ASSERT(MiniportAdapterHandle
&& Buffer
&& PhysicalAddressArray
&& ArraySize
);
498 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
499 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
500 TotalLength
= MmGetMdlByteCount(Buffer
);
504 ULONG Length
= TotalLength
;
506 ReturnedAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->MapTransfer(
507 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
508 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
509 CurrentVa
, &Length
, WriteToDevice
);
511 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
= WriteToDevice
;
513 PhysicalAddressArray
[LoopCount
].PhysicalAddress
= ReturnedAddress
;
514 PhysicalAddressArray
[LoopCount
].Length
= Length
;
516 TotalLength
-= Length
;
517 CurrentVa
= (PVOID
)((ULONG_PTR
)CurrentVa
+ Length
);
522 *ArraySize
= LoopCount
;
531 NdisMCompleteBufferPhysicalMapping(
532 IN NDIS_HANDLE MiniportAdapterHandle
,
533 IN PNDIS_BUFFER Buffer
,
534 IN ULONG PhysicalMapRegister
)
536 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
538 * - MiniportAdapterHandle: handle originally input to MiniportInitialize
539 * - Buffer: NDIS_BUFFER to complete the mapping on
540 * - PhyscialMapRegister: the chosen map register
542 * - May be called at IRQL <= DISPATCH_LEVEL
545 PLOGICAL_ADAPTER Adapter
= 0;
549 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
550 ASSERT(MiniportAdapterHandle
&& Buffer
);
552 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
553 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
554 Length
= MmGetMdlByteCount(Buffer
);
556 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->FlushAdapterBuffers(
557 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
558 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
560 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
);
570 NdisMCompleteDmaTransfer(
571 OUT PNDIS_STATUS Status
,
572 IN PNDIS_HANDLE MiniportDmaHandle
,
573 IN PNDIS_BUFFER Buffer
,
576 IN BOOLEAN WriteToDevice
)
587 NdisMDeregisterDmaChannel(
588 IN PNDIS_HANDLE MiniportDmaHandle
)
599 NdisMDeregisterInterrupt(
600 IN PNDIS_MINIPORT_INTERRUPT Interrupt
)
602 * FUNCTION: Releases an interrupt vector
604 * Interrupt = Pointer to interrupt object
607 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
608 IoDisconnectInterrupt(Interrupt
->InterruptObject
);
617 NdisMDeregisterIoPortRange(
618 IN NDIS_HANDLE MiniportAdapterHandle
,
620 IN UINT NumberOfPorts
,
623 * FUNCTION: Releases a register mapping to I/O ports
625 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
626 * InitialPort = Bus-relative base port address of a range to be mapped
627 * NumberOfPorts = Specifies number of ports to be mapped
628 * PortOffset = Pointer to mapped base port address
631 NDIS_DbgPrint(MAX_TRACE
, ("called - IMPLEMENT ME.\n"));
640 NdisMFreeMapRegisters(
641 IN NDIS_HANDLE MiniportAdapterHandle
)
643 * FUNCTION: Free previously allocated map registers
645 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
650 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
651 PDMA_ADAPTER AdapterObject
;
652 UINT MapRegistersPerBaseRegister
;
655 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
659 /* only bus masters may call this routine */
660 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
661 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
) ||
662 Adapter
->NdisMiniportBlock
.SystemAdapterObject
== NULL
)
665 MapRegistersPerBaseRegister
= ((Adapter
->NdisMiniportBlock
.MaximumPhysicalMapping
- 2) / PAGE_SIZE
) + 2;
667 AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
669 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
671 for(i
= 0; i
< Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
; i
++)
673 AdapterObject
->DmaOperations
->FreeMapRegisters(
674 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
675 Adapter
->NdisMiniportBlock
.MapRegisters
[i
].MapRegister
,
676 MapRegistersPerBaseRegister
);
679 KeLowerIrql(OldIrql
);
681 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
682 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
684 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
694 OUT PVOID
*VirtualAddress
,
695 IN NDIS_HANDLE MiniportAdapterHandle
,
696 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
,
699 * FUNCTION: Maps a bus-relative address to a system-wide virtual address
701 * VirtualAddress: receives virtual address of mapping
702 * MiniportAdapterHandle: Handle originally input to MiniportInitialize
703 * PhysicalAddress: bus-relative address to map
704 * Length: Number of bytes to map
706 * NDIS_STATUS_SUCCESS: the operation completed successfully
707 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
708 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
709 * NDIS_STATUS_FAILURE: a general failure has occured
711 * - Must be called at IRQL = PASSIVE_LEVEL
713 * - Only supports things that MmMapIoSpace internally supports - what
714 * about considering bus type, etc?
715 * - doesn't track resources allocated...
719 ASSERT(VirtualAddress
&& MiniportAdapterHandle
);
721 *VirtualAddress
= MmMapIoSpace(PhysicalAddress
, Length
, MmNonCached
);
724 return NDIS_STATUS_RESOURCES
;
726 return NDIS_STATUS_SUCCESS
;
736 IN NDIS_HANDLE MiniportDmaHandle
)
738 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
739 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
741 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
743 if (AdapterObject
== NULL
)
746 return AdapterObject
->DmaOperations
->ReadDmaCounter(AdapterObject
);
755 NdisMGetDmaAlignment(
756 IN NDIS_HANDLE MiniportDmaHandle
)
758 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
759 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
761 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
763 if (AdapterObject
== NULL
)
766 return AdapterObject
->DmaOperations
->GetDmaAlignment(AdapterObject
);
775 NdisMRegisterDmaChannel(
776 OUT PNDIS_HANDLE MiniportDmaHandle
,
777 IN NDIS_HANDLE MiniportAdapterHandle
,
779 IN BOOLEAN Dma32BitAddresses
,
780 IN PNDIS_DMA_DESCRIPTION DmaDescription
,
781 IN ULONG MaximumLength
)
785 return NDIS_STATUS_FAILURE
;
794 NdisMRegisterInterrupt(
795 OUT PNDIS_MINIPORT_INTERRUPT Interrupt
,
796 IN NDIS_HANDLE MiniportAdapterHandle
,
797 IN UINT InterruptVector
,
798 IN UINT InterruptLevel
,
799 IN BOOLEAN RequestIsr
,
800 IN BOOLEAN SharedInterrupt
,
801 IN NDIS_INTERRUPT_MODE InterruptMode
)
803 * FUNCTION: Claims access to an interrupt vector
805 * Interrupt = Address of interrupt object to initialize
806 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
807 * InterruptVector = Specifies bus-relative vector to register
808 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
809 * RequestIsr = TRUE if MiniportISR should always be called
810 * SharedInterrupt = TRUE if other devices may use the same interrupt
811 * InterruptMode = Specifies type of interrupt
813 * Status of operation
820 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
822 NDIS_DbgPrint(MAX_TRACE
, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
823 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
824 InterruptVector
, InterruptLevel
, SharedInterrupt
, InterruptMode
));
826 RtlZeroMemory(Interrupt
, sizeof(NDIS_MINIPORT_INTERRUPT
));
828 KeInitializeSpinLock(&Interrupt
->DpcCountLock
);
830 KeInitializeDpc(&Interrupt
->InterruptDpc
, HandleDeferredProcessing
, Adapter
);
832 KeInitializeEvent(&Interrupt
->DpcsCompletedEvent
, NotificationEvent
, FALSE
);
834 Interrupt
->SharedInterrupt
= SharedInterrupt
;
836 Adapter
->NdisMiniportBlock
.Interrupt
= Interrupt
;
838 MappedIRQ
= HalGetInterruptVector(Adapter
->NdisMiniportBlock
.BusType
,
839 Adapter
->NdisMiniportBlock
.BusNumber
,
840 InterruptLevel
, InterruptVector
, &DIrql
,
843 NDIS_DbgPrint(MAX_TRACE
, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ
, Affinity
));
845 Status
= IoConnectInterrupt(&Interrupt
->InterruptObject
, ServiceRoutine
, Adapter
, &Interrupt
->DpcCountLock
, MappedIRQ
,
846 DIrql
, DIrql
, InterruptMode
, SharedInterrupt
, Affinity
, FALSE
);
848 NDIS_DbgPrint(MAX_TRACE
, ("Leaving. Status (0x%X).\n", Status
));
850 if (NT_SUCCESS(Status
))
851 return NDIS_STATUS_SUCCESS
;
853 if (Status
== STATUS_INSUFFICIENT_RESOURCES
)
855 /* FIXME: Log error */
856 NDIS_DbgPrint(MIN_TRACE
, ("Resource conflict!\n"));
857 return NDIS_STATUS_RESOURCE_CONFLICT
;
860 NDIS_DbgPrint(MIN_TRACE
, ("Function failed\n"));
861 return NDIS_STATUS_FAILURE
;
870 NdisMRegisterIoPortRange(
871 OUT PVOID
*PortOffset
,
872 IN NDIS_HANDLE MiniportAdapterHandle
,
874 IN UINT NumberOfPorts
)
876 * FUNCTION: Sets up driver access to device I/O ports
878 * PortOffset = Address of buffer to place mapped base port address
879 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
880 * InitialPort = Bus-relative base port address of a range to be mapped
881 * NumberOfPorts = Specifies number of ports to be mapped
883 * Status of operation
886 PHYSICAL_ADDRESS PortAddress
, TranslatedAddress
;
887 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(MiniportAdapterHandle
);
888 ULONG AddressSpace
= 1; /* FIXME The HAL handles this wrong atm */
890 NDIS_DbgPrint(MAX_TRACE
, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort
, NumberOfPorts
));
892 memset(&PortAddress
, 0, sizeof(PortAddress
));
895 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
896 * we don't have a way to get the I/O base address yet (see
897 * NDIS_MINIPORT_BLOCK->AllocatedResources and
898 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
901 PortAddress
= RtlConvertUlongToLargeInteger(InitialPort
);
905 NDIS_DbgPrint(MAX_TRACE
, ("Translating address 0x%x 0x%x\n", PortAddress
.u
.HighPart
, PortAddress
.u
.LowPart
));
907 if(!HalTranslateBusAddress(Adapter
->NdisMiniportBlock
.BusType
,
908 Adapter
->NdisMiniportBlock
.BusNumber
,
909 PortAddress
, &AddressSpace
, &TranslatedAddress
))
911 NDIS_DbgPrint(MIN_TRACE
, ("Unable to translate address\n"));
912 return NDIS_STATUS_RESOURCES
;
915 NDIS_DbgPrint(MAX_TRACE
, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
916 AddressSpace
, TranslatedAddress
.u
.HighPart
, TranslatedAddress
.u
.LowPart
));
920 ASSERT(TranslatedAddress
.u
.HighPart
== 0);
921 *PortOffset
= (PVOID
) TranslatedAddress
.u
.LowPart
;
922 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x\n", *PortOffset
));
923 return NDIS_STATUS_SUCCESS
;
926 NDIS_DbgPrint(MAX_TRACE
, ("calling MmMapIoSpace\n"));
929 *PortOffset
= MmMapIoSpace(TranslatedAddress
, NumberOfPorts
, MmNonCached
);
930 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x for port range\n", *PortOffset
));
933 return NDIS_STATUS_RESOURCES
;
935 return NDIS_STATUS_SUCCESS
;
943 NdisMSetupDmaTransfer(
944 OUT PNDIS_STATUS Status
,
945 IN PNDIS_HANDLE MiniportDmaHandle
,
946 IN PNDIS_BUFFER Buffer
,
949 IN BOOLEAN WriteToDevice
)
961 IN NDIS_HANDLE MiniportAdapterHandle
,
962 IN PVOID VirtualAddress
,
965 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
967 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
968 * VirtualAddress: Address to un-map
969 * Length: length of the mapped memory space
971 * - Must be called at IRQL = PASSIVE_LEVEL
972 * - Must only be called from MiniportInitialize and MiniportHalt
973 * - See also: NdisMMapIoSpace
975 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
980 ASSERT(MiniportAdapterHandle
);
982 MmUnmapIoSpace(VirtualAddress
, Length
);