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
17 VOID NTAPI
HandleDeferredProcessing(
19 IN PVOID DeferredContext
,
20 IN PVOID SystemArgument1
,
21 IN PVOID SystemArgument2
)
23 * FUNCTION: Deferred interrupt processing routine
25 * Dpc = Pointer to DPC object
26 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
27 * SystemArgument1 = Unused
28 * SystemArgument2 = Unused
31 PLOGICAL_ADAPTER Adapter
= GET_LOGICAL_ADAPTER(DeferredContext
);
33 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
35 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
37 /* Call the deferred interrupt service handler for this adapter */
38 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.HandleInterruptHandler
)(
39 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
41 /* re-enable the interrupt */
42 NDIS_DbgPrint(MAX_TRACE
, ("re-enabling the interrupt\n"));
43 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.EnableInterruptHandler
)
44 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.EnableInterruptHandler
)(
45 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
47 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
51 BOOLEAN NTAPI
ServiceRoutine(
52 IN PKINTERRUPT Interrupt
,
53 IN PVOID ServiceContext
)
55 * FUNCTION: Interrupt service routine
57 * Interrupt = Pointer to interrupt object
58 * ServiceContext = Pointer to context information (LOGICAL_ADAPTER)
60 * TRUE if a miniport controlled device generated the interrupt
63 BOOLEAN InterruptRecognized
;
64 BOOLEAN QueueMiniportHandleInterrupt
;
65 PNDIS_MINIPORT_BLOCK Adapter
= (PNDIS_MINIPORT_BLOCK
)ServiceContext
;
67 NDIS_DbgPrint(MAX_TRACE
, ("Called. Adapter (0x%X)\n", Adapter
));
69 (*Adapter
->DriverHandle
->MiniportCharacteristics
.ISRHandler
)(
71 &QueueMiniportHandleInterrupt
,
72 Adapter
->MiniportAdapterContext
);
74 if (QueueMiniportHandleInterrupt
)
76 NDIS_DbgPrint(MAX_TRACE
, ("Queueing DPC.\n"));
77 KeInsertQueueDpc(&Adapter
->Interrupt
->InterruptDpc
, NULL
, NULL
);
80 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
82 return InterruptRecognized
;
91 NdisCompleteDmaTransfer(
92 OUT PNDIS_STATUS Status
,
93 IN PNDIS_HANDLE NdisDmaHandle
,
94 IN PNDIS_BUFFER Buffer
,
97 IN BOOLEAN WriteToDevice
)
108 NdisImmediateReadPortUchar(
109 IN NDIS_HANDLE WrapperConfigurationContext
,
113 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
114 *Data
= READ_PORT_UCHAR(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
123 NdisImmediateReadPortUlong(
124 IN NDIS_HANDLE WrapperConfigurationContext
,
128 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
129 *Data
= READ_PORT_ULONG(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
138 NdisImmediateReadPortUshort(
139 IN NDIS_HANDLE WrapperConfigurationContext
,
143 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
144 *Data
= READ_PORT_USHORT(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
153 NdisImmediateWritePortUchar(
154 IN NDIS_HANDLE WrapperConfigurationContext
,
158 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
159 WRITE_PORT_UCHAR(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
168 NdisImmediateWritePortUlong(
169 IN NDIS_HANDLE WrapperConfigurationContext
,
173 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
174 WRITE_PORT_ULONG(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
183 NdisImmediateWritePortUshort(
184 IN NDIS_HANDLE WrapperConfigurationContext
,
188 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
189 WRITE_PORT_USHORT(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
193 IO_ALLOCATION_ACTION NTAPI
NdisMapRegisterCallback (
194 IN PDEVICE_OBJECT DeviceObject
,
196 IN PVOID MapRegisterBase
,
199 * FUNCTION: Called back during reservation of map registers
201 * DeviceObject: Device object of the deivce setting up DMA
202 * Irp: Reserved; must be ignored
203 * MapRegisterBase: Map registers assigned for transfer
204 * Context: LOGICAL_ADAPTER object of the requesting miniport
206 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
207 * - Called at IRQL = DISPATCH_LEVEL
210 PNDIS_MINIPORT_BLOCK Adapter
= (PNDIS_MINIPORT_BLOCK
)Context
;
212 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
214 Adapter
->MapRegisters
[Adapter
->CurrentMapRegister
].MapRegister
= MapRegisterBase
;
216 NDIS_DbgPrint(MAX_TRACE
, ("setting event and leaving.\n"));
218 KeSetEvent(Adapter
->AllocationEvent
, 0, FALSE
);
220 /* this is only the thing to do for busmaster NICs */
221 return DeallocateObjectKeepRegisters
;
230 NdisMAllocateMapRegisters(
231 IN NDIS_HANDLE MiniportAdapterHandle
,
234 IN ULONG BaseMapRegistersNeeded
,
235 IN ULONG MaximumBufferSize
)
237 * FUNCTION: Allocate map registers for use in DMA transfers
239 * MiniportAdapterHandle: Passed in to MiniportInitialize
240 * DmaChannel: DMA channel to use
241 * DmaSize: bit width of DMA transfers
242 * BaseMapRegistersNeeded: number of base map registers requested
243 * MaximumBufferSize: largest single buffer transferred
245 * NDIS_STATUS_SUCCESS on success
246 * NDIS_STATUS_RESOURCES on failure
248 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
249 * I'm implementing the 2k one.
250 * - do not confuse a "base map register" with a "map register" - they
251 * are different. Only NDIS seems to use the base concept. The idea
252 * is that a miniport supplies the number of base map registers it will
253 * need, which is equal to the number of DMA send buffers it manages.
254 * NDIS then allocates a number of map registers to go with each base
255 * map register, so that a driver just has to send the base map register
256 * number during dma operations and NDIS can find the group of real
257 * map registers that represent the transfer.
258 * - Because of the above sillyness, you can only specify a few base map
259 * registers at most. a 1514-byte packet is two map registers at 4k
261 * - NDIS limits the total number of allocated map registers to 64,
262 * which (in the case of the above example) limits the number of base
263 * map registers to 32.
266 DEVICE_DESCRIPTION Description
;
267 PDMA_ADAPTER AdapterObject
= 0;
268 UINT MapRegistersPerBaseRegister
= 0;
269 ULONG AvailableMapRegisters
;
271 PLOGICAL_ADAPTER Adapter
;
272 PDEVICE_OBJECT DeviceObject
= 0;
273 KEVENT AllocationEvent
;
276 NDIS_DbgPrint(MAX_TRACE
, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
277 MiniportAdapterHandle
, DmaChannel
, DmaSize
, BaseMapRegistersNeeded
, MaximumBufferSize
));
279 memset(&Description
,0,sizeof(Description
));
281 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
285 /* only bus masters may call this routine */
286 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
287 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
))
288 return NDIS_STATUS_SUCCESS
;
290 DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
292 KeInitializeEvent(&AllocationEvent
, NotificationEvent
, FALSE
);
293 Adapter
->NdisMiniportBlock
.AllocationEvent
= &AllocationEvent
;
296 * map registers correlate to physical pages. ndis documents a
297 * maximum of 64 map registers that it will return.
298 * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
300 * the number of registers required for a given physical mapping
301 * is (first register + last register + one per page size),
302 * given that physical mapping is > 2.
305 /* unhandled corner case: {1,2}-byte max buffer size */
306 ASSERT(MaximumBufferSize
> 2);
307 MapRegistersPerBaseRegister
= ((MaximumBufferSize
-2) / (2*PAGE_SIZE
)) + 2;
309 Description
.Version
= DEVICE_DESCRIPTION_VERSION
;
310 Description
.Master
= TRUE
; /* implied by calling this function */
311 Description
.ScatterGather
= TRUE
; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
312 Description
.Dma32BitAddresses
= DmaSize
;
313 Description
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
314 Description
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
315 Description
.DmaChannel
= DmaChannel
;
316 Description
.MaximumLength
= MaximumBufferSize
;
318 if(Adapter
->NdisMiniportBlock
.AdapterType
== Isa
)
322 Description
.DmaWidth
= Width8Bits
;
324 Description
.DmaWidth
= Width16Bits
;
326 Description
.DmaSpeed
= Compatible
;
328 else if(Adapter
->NdisMiniportBlock
.AdapterType
== PCIBus
)
330 if(DmaSize
== NDIS_DMA_64BITS
)
331 Description
.Dma64BitAddresses
= TRUE
;
333 Description
.Dma32BitAddresses
= TRUE
;
337 NDIS_DbgPrint(MIN_TRACE
, ("Unsupported bus type\n"));
341 AdapterObject
= IoGetDmaAdapter(
342 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, &Description
, &AvailableMapRegisters
);
346 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate an adapter object; bailing out\n"));
347 return NDIS_STATUS_RESOURCES
;
350 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= AdapterObject
;
352 if(AvailableMapRegisters
< MapRegistersPerBaseRegister
)
354 NDIS_DbgPrint(MIN_TRACE
, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
355 MapRegistersPerBaseRegister
, AvailableMapRegisters
));
357 return NDIS_STATUS_RESOURCES
;
360 /* allocate & zero space in the miniport block for the registers */
361 Adapter
->NdisMiniportBlock
.MapRegisters
= ExAllocatePool(NonPagedPool
, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
362 if(!Adapter
->NdisMiniportBlock
.MapRegisters
)
364 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
365 return NDIS_STATUS_RESOURCES
;
368 memset(Adapter
->NdisMiniportBlock
.MapRegisters
, 0, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
369 Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= (USHORT
)BaseMapRegistersNeeded
;
371 while(BaseMapRegistersNeeded
)
373 NDIS_DbgPrint(MAX_TRACE
, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded
));
375 BaseMapRegistersNeeded
--;
376 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= (USHORT
)BaseMapRegistersNeeded
;
377 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
379 NtStatus
= AdapterObject
->DmaOperations
->AllocateAdapterChannel(
380 AdapterObject
, DeviceObject
, MapRegistersPerBaseRegister
,
381 NdisMapRegisterCallback
, Adapter
);
383 KeLowerIrql(OldIrql
);
385 if(!NT_SUCCESS(NtStatus
))
387 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus
));
388 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
389 return NDIS_STATUS_RESOURCES
;
392 NDIS_DbgPrint(MAX_TRACE
, ("waiting on event\n"));
394 NtStatus
= KeWaitForSingleObject(&AllocationEvent
, Executive
, KernelMode
, FALSE
, 0);
396 if(!NT_SUCCESS(NtStatus
))
398 NDIS_DbgPrint(MIN_TRACE
, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus
));
399 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
400 return NDIS_STATUS_RESOURCES
;
403 NDIS_DbgPrint(MAX_TRACE
, ("resetting event\n"));
405 KeResetEvent(&AllocationEvent
);
408 NDIS_DbgPrint(MAX_TRACE
, ("returning success\n"));
409 return NDIS_STATUS_SUCCESS
;
418 NdisMStartBufferPhysicalMapping(
419 IN NDIS_HANDLE MiniportAdapterHandle
,
420 IN PNDIS_BUFFER Buffer
,
421 IN ULONG PhysicalMapRegister
,
422 IN BOOLEAN WriteToDevice
,
423 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray
,
426 * FUNCTION: Sets up map registers for a bus-master DMA transfer
428 * MiniportAdapterHandle: handle originally input to MiniportInitialize
429 * Buffer: data to be transferred
430 * PhysicalMapRegister: specifies the map register to set up
431 * WriteToDevice: if true, data is being written to the device; else it is being read
432 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
433 * ArraySize: number of elements in PhysicalAddressArray
435 * - Must be called at IRQL <= DISPATCH_LEVEL
436 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes
437 * in order to map all of the virtual memory to physical memoroy readable
439 * - The caller supplies storage for the physical address array.
442 PLOGICAL_ADAPTER Adapter
;
445 PHYSICAL_ADDRESS ReturnedAddress
;
448 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
449 ASSERT(MiniportAdapterHandle
&& Buffer
&& PhysicalAddressArray
&& ArraySize
);
451 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
452 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
453 TotalLength
= MmGetMdlByteCount(Buffer
);
457 ULONG Length
= TotalLength
;
459 ReturnedAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->MapTransfer(
460 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
461 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
462 CurrentVa
, &Length
, WriteToDevice
);
464 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
= WriteToDevice
;
466 PhysicalAddressArray
[LoopCount
].PhysicalAddress
= ReturnedAddress
;
467 PhysicalAddressArray
[LoopCount
].Length
= Length
;
469 TotalLength
-= Length
;
470 CurrentVa
= (PVOID
)((ULONG_PTR
)CurrentVa
+ Length
);
475 *ArraySize
= LoopCount
;
484 NdisMCompleteBufferPhysicalMapping(
485 IN NDIS_HANDLE MiniportAdapterHandle
,
486 IN PNDIS_BUFFER Buffer
,
487 IN ULONG PhysicalMapRegister
)
489 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
491 * - MiniportAdapterHandle: handle originally input to MiniportInitialize
492 * - Buffer: NDIS_BUFFER to complete the mapping on
493 * - PhyscialMapRegister: the chosen map register
495 * - May be called at IRQL <= DISPATCH_LEVEL
498 PLOGICAL_ADAPTER Adapter
;
502 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
503 ASSERT(MiniportAdapterHandle
&& Buffer
);
505 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
506 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
507 Length
= MmGetMdlByteCount(Buffer
);
509 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->FlushAdapterBuffers(
510 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
511 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
513 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
);
522 NdisMDeregisterDmaChannel(
523 IN PNDIS_HANDLE MiniportDmaHandle
)
534 NdisMDeregisterInterrupt(
535 IN PNDIS_MINIPORT_INTERRUPT Interrupt
)
537 * FUNCTION: Releases an interrupt vector
539 * Interrupt = Pointer to interrupt object
542 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
543 IoDisconnectInterrupt(Interrupt
->InterruptObject
);
552 NdisMDeregisterIoPortRange(
553 IN NDIS_HANDLE MiniportAdapterHandle
,
555 IN UINT NumberOfPorts
,
558 * FUNCTION: Releases a register mapping to I/O ports
560 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
561 * InitialPort = Bus-relative base port address of a range to be mapped
562 * NumberOfPorts = Specifies number of ports to be mapped
563 * PortOffset = Pointer to mapped base port address
566 NDIS_DbgPrint(MAX_TRACE
, ("called - IMPLEMENT ME.\n"));
575 NdisMFreeMapRegisters(
576 IN NDIS_HANDLE MiniportAdapterHandle
)
578 * FUNCTION: Free previously allocated map registers
580 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
585 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
586 PDMA_ADAPTER AdapterObject
;
587 UINT MapRegistersPerBaseRegister
;
590 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
594 /* only bus masters may call this routine */
595 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
596 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
) ||
597 Adapter
->NdisMiniportBlock
.SystemAdapterObject
== NULL
)
600 MapRegistersPerBaseRegister
= ((Adapter
->NdisMiniportBlock
.MaximumPhysicalMapping
- 2) / PAGE_SIZE
) + 2;
602 AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
604 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
606 for(i
= 0; i
< Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
; i
++)
608 AdapterObject
->DmaOperations
->FreeMapRegisters(
609 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
610 Adapter
->NdisMiniportBlock
.MapRegisters
[i
].MapRegister
,
611 MapRegistersPerBaseRegister
);
614 KeLowerIrql(OldIrql
);
616 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
617 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
619 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
629 OUT PVOID
*VirtualAddress
,
630 IN NDIS_HANDLE MiniportAdapterHandle
,
631 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
,
634 * FUNCTION: Maps a bus-relative address to a system-wide virtual address
636 * VirtualAddress: receives virtual address of mapping
637 * MiniportAdapterHandle: Handle originally input to MiniportInitialize
638 * PhysicalAddress: bus-relative address to map
639 * Length: Number of bytes to map
641 * NDIS_STATUS_SUCCESS: the operation completed successfully
642 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
643 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
644 * NDIS_STATUS_FAILURE: a general failure has occured
646 * - Must be called at IRQL = PASSIVE_LEVEL
648 * - Only supports things that MmMapIoSpace internally supports - what
649 * about considering bus type, etc?
650 * - doesn't track resources allocated...
654 ASSERT(VirtualAddress
&& MiniportAdapterHandle
);
656 *VirtualAddress
= MmMapIoSpace(PhysicalAddress
, Length
, MmNonCached
);
659 return NDIS_STATUS_RESOURCES
;
661 return NDIS_STATUS_SUCCESS
;
671 IN NDIS_HANDLE MiniportDmaHandle
)
673 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
674 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
676 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
678 if (AdapterObject
== NULL
)
681 return AdapterObject
->DmaOperations
->ReadDmaCounter(AdapterObject
);
690 NdisMGetDmaAlignment(
691 IN NDIS_HANDLE MiniportDmaHandle
)
693 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
694 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
696 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
698 if (AdapterObject
== NULL
)
701 return AdapterObject
->DmaOperations
->GetDmaAlignment(AdapterObject
);
710 NdisMRegisterDmaChannel(
711 OUT PNDIS_HANDLE MiniportDmaHandle
,
712 IN NDIS_HANDLE MiniportAdapterHandle
,
714 IN BOOLEAN Dma32BitAddresses
,
715 IN PNDIS_DMA_DESCRIPTION DmaDescription
,
716 IN ULONG MaximumLength
)
720 return NDIS_STATUS_FAILURE
;
729 NdisMRegisterInterrupt(
730 OUT PNDIS_MINIPORT_INTERRUPT Interrupt
,
731 IN NDIS_HANDLE MiniportAdapterHandle
,
732 IN UINT InterruptVector
,
733 IN UINT InterruptLevel
,
734 IN BOOLEAN RequestIsr
,
735 IN BOOLEAN SharedInterrupt
,
736 IN NDIS_INTERRUPT_MODE InterruptMode
)
738 * FUNCTION: Claims access to an interrupt vector
740 * Interrupt = Address of interrupt object to initialize
741 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
742 * InterruptVector = Specifies bus-relative vector to register
743 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
744 * RequestIsr = TRUE if MiniportISR should always be called
745 * SharedInterrupt = TRUE if other devices may use the same interrupt
746 * InterruptMode = Specifies type of interrupt
748 * Status of operation
755 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
757 NDIS_DbgPrint(MAX_TRACE
, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
758 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
759 InterruptVector
, InterruptLevel
, SharedInterrupt
, InterruptMode
));
761 RtlZeroMemory(Interrupt
, sizeof(NDIS_MINIPORT_INTERRUPT
));
763 KeInitializeSpinLock(&Interrupt
->DpcCountLock
);
765 KeInitializeDpc(&Interrupt
->InterruptDpc
, HandleDeferredProcessing
, Adapter
);
767 KeInitializeEvent(&Interrupt
->DpcsCompletedEvent
, NotificationEvent
, FALSE
);
769 Interrupt
->SharedInterrupt
= SharedInterrupt
;
771 Adapter
->NdisMiniportBlock
.Interrupt
= Interrupt
;
773 MappedIRQ
= HalGetInterruptVector(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
774 InterruptLevel
, InterruptVector
, &DIrql
,
777 NDIS_DbgPrint(MAX_TRACE
, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ
, Affinity
));
779 Status
= IoConnectInterrupt(&Interrupt
->InterruptObject
, ServiceRoutine
, Adapter
, &Interrupt
->DpcCountLock
, MappedIRQ
,
780 DIrql
, DIrql
, InterruptMode
, SharedInterrupt
, Affinity
, FALSE
);
782 NDIS_DbgPrint(MAX_TRACE
, ("Leaving. Status (0x%X).\n", Status
));
784 if (NT_SUCCESS(Status
))
785 return NDIS_STATUS_SUCCESS
;
787 if (Status
== STATUS_INSUFFICIENT_RESOURCES
)
789 /* FIXME: Log error */
790 NDIS_DbgPrint(MIN_TRACE
, ("Resource conflict!\n"));
791 return NDIS_STATUS_RESOURCE_CONFLICT
;
794 NDIS_DbgPrint(MIN_TRACE
, ("Function failed. Status (0x%X).\n", Status
));
795 return NDIS_STATUS_FAILURE
;
804 NdisMRegisterIoPortRange(
805 OUT PVOID
*PortOffset
,
806 IN NDIS_HANDLE MiniportAdapterHandle
,
808 IN UINT NumberOfPorts
)
810 * FUNCTION: Sets up driver access to device I/O ports
812 * PortOffset = Address of buffer to place mapped base port address
813 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
814 * InitialPort = Bus-relative base port address of a range to be mapped
815 * NumberOfPorts = Specifies number of ports to be mapped
817 * Status of operation
820 PHYSICAL_ADDRESS PortAddress
, TranslatedAddress
;
821 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
822 ULONG AddressSpace
= 1; /* FIXME The HAL handles this wrong atm */
826 NDIS_DbgPrint(MAX_TRACE
, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort
, NumberOfPorts
));
828 memset(&PortAddress
, 0, sizeof(PortAddress
));
831 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
832 * we don't have a way to get the I/O base address yet (see
833 * NDIS_MINIPORT_BLOCK->AllocatedResources and
834 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
837 PortAddress
= RtlConvertUlongToLargeInteger(InitialPort
);
841 NDIS_DbgPrint(MAX_TRACE
, ("Translating address 0x%x 0x%x\n", PortAddress
.u
.HighPart
, PortAddress
.u
.LowPart
));
843 if(!HalTranslateBusAddress(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
844 PortAddress
, &AddressSpace
, &TranslatedAddress
))
846 NDIS_DbgPrint(MIN_TRACE
, ("Unable to translate address\n"));
847 return NDIS_STATUS_RESOURCES
;
850 NDIS_DbgPrint(MAX_TRACE
, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
851 AddressSpace
, TranslatedAddress
.u
.HighPart
, TranslatedAddress
.u
.LowPart
));
855 ASSERT(TranslatedAddress
.u
.HighPart
== 0);
856 *PortOffset
= (PVOID
)(ULONG_PTR
)TranslatedAddress
.QuadPart
;
857 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x\n", *PortOffset
));
858 return NDIS_STATUS_SUCCESS
;
861 NDIS_DbgPrint(MAX_TRACE
, ("calling MmMapIoSpace\n"));
863 *PortOffset
= MmMapIoSpace(TranslatedAddress
, NumberOfPorts
, MmNonCached
);
864 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x for port range\n", *PortOffset
));
867 return NDIS_STATUS_RESOURCES
;
869 return NDIS_STATUS_SUCCESS
;
879 IN NDIS_HANDLE MiniportAdapterHandle
,
880 IN PVOID VirtualAddress
,
883 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
885 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
886 * VirtualAddress: Address to un-map
887 * Length: length of the mapped memory space
889 * - Must be called at IRQL = PASSIVE_LEVEL
890 * - Must only be called from MiniportInitialize and MiniportHalt
891 * - See also: NdisMMapIoSpace
893 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
898 ASSERT(MiniportAdapterHandle
);
900 MmUnmapIoSpace(VirtualAddress
, Length
);