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
= FALSE
;
64 BOOLEAN QueueMiniportHandleInterrupt
= FALSE
;
65 PLOGICAL_ADAPTER Adapter
= ServiceContext
;
67 NDIS_DbgPrint(MAX_TRACE
, ("Called. Adapter (0x%X)\n", Adapter
));
69 if (Adapter
->NdisMiniportBlock
.Interrupt
->IsrRequested
) {
70 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.ISRHandler
)(
72 &QueueMiniportHandleInterrupt
,
73 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
75 } else if (Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.DisableInterruptHandler
) {
76 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.DisableInterruptHandler
)(
77 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
);
78 QueueMiniportHandleInterrupt
= TRUE
;
79 InterruptRecognized
= TRUE
;
83 if (QueueMiniportHandleInterrupt
)
85 NDIS_DbgPrint(MAX_TRACE
, ("Queuing DPC.\n"));
86 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.Interrupt
->InterruptDpc
, NULL
, NULL
);
89 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
91 return InterruptRecognized
;
100 NdisCompleteDmaTransfer(
101 OUT PNDIS_STATUS Status
,
102 IN PNDIS_HANDLE NdisDmaHandle
,
103 IN PNDIS_BUFFER Buffer
,
106 IN BOOLEAN WriteToDevice
)
117 NdisImmediateReadPortUchar(
118 IN NDIS_HANDLE WrapperConfigurationContext
,
122 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
123 *Data
= READ_PORT_UCHAR(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
132 NdisImmediateReadPortUlong(
133 IN NDIS_HANDLE WrapperConfigurationContext
,
137 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
138 *Data
= READ_PORT_ULONG(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
147 NdisImmediateReadPortUshort(
148 IN NDIS_HANDLE WrapperConfigurationContext
,
152 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
153 *Data
= READ_PORT_USHORT(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
162 NdisImmediateWritePortUchar(
163 IN NDIS_HANDLE WrapperConfigurationContext
,
167 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
168 WRITE_PORT_UCHAR(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
177 NdisImmediateWritePortUlong(
178 IN NDIS_HANDLE WrapperConfigurationContext
,
182 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
183 WRITE_PORT_ULONG(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
192 NdisImmediateWritePortUshort(
193 IN NDIS_HANDLE WrapperConfigurationContext
,
197 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
198 WRITE_PORT_USHORT(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
202 IO_ALLOCATION_ACTION NTAPI
NdisMapRegisterCallback (
203 IN PDEVICE_OBJECT DeviceObject
,
205 IN PVOID MapRegisterBase
,
208 * FUNCTION: Called back during reservation of map registers
210 * DeviceObject: Device object of the deivce setting up DMA
211 * Irp: Reserved; must be ignored
212 * MapRegisterBase: Map registers assigned for transfer
213 * Context: LOGICAL_ADAPTER object of the requesting miniport
215 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
216 * - Called at IRQL = DISPATCH_LEVEL
219 PLOGICAL_ADAPTER Adapter
= Context
;
221 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
223 Adapter
->NdisMiniportBlock
.MapRegisters
[Adapter
->NdisMiniportBlock
.CurrentMapRegister
].MapRegister
= MapRegisterBase
;
225 NDIS_DbgPrint(MAX_TRACE
, ("setting event and leaving.\n"));
227 KeSetEvent(Adapter
->NdisMiniportBlock
.AllocationEvent
, 0, FALSE
);
229 /* this is only the thing to do for busmaster NICs */
230 return DeallocateObjectKeepRegisters
;
239 NdisMAllocateMapRegisters(
240 IN NDIS_HANDLE MiniportAdapterHandle
,
243 IN ULONG BaseMapRegistersNeeded
,
244 IN ULONG MaximumBufferSize
)
246 * FUNCTION: Allocate map registers for use in DMA transfers
248 * MiniportAdapterHandle: Passed in to MiniportInitialize
249 * DmaChannel: DMA channel to use
250 * DmaSize: bit width of DMA transfers
251 * BaseMapRegistersNeeded: number of base map registers requested
252 * MaximumBufferSize: largest single buffer transferred
254 * NDIS_STATUS_SUCCESS on success
255 * NDIS_STATUS_RESOURCES on failure
257 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
258 * I'm implementing the 2k one.
259 * - do not confuse a "base map register" with a "map register" - they
260 * are different. Only NDIS seems to use the base concept. The idea
261 * is that a miniport supplies the number of base map registers it will
262 * need, which is equal to the number of DMA send buffers it manages.
263 * NDIS then allocates a number of map registers to go with each base
264 * map register, so that a driver just has to send the base map register
265 * number during dma operations and NDIS can find the group of real
266 * map registers that represent the transfer.
267 * - Because of the above sillyness, you can only specify a few base map
268 * registers at most. a 1514-byte packet is two map registers at 4k
270 * - NDIS limits the total number of allocated map registers to 64,
271 * which (in the case of the above example) limits the number of base
272 * map registers to 32.
275 DEVICE_DESCRIPTION Description
;
276 PDMA_ADAPTER AdapterObject
= 0;
277 UINT MapRegistersPerBaseRegister
= 0;
278 ULONG AvailableMapRegisters
;
280 PLOGICAL_ADAPTER Adapter
;
281 PDEVICE_OBJECT DeviceObject
= 0;
282 KEVENT AllocationEvent
;
285 NDIS_DbgPrint(MAX_TRACE
, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
286 MiniportAdapterHandle
, DmaChannel
, DmaSize
, BaseMapRegistersNeeded
, MaximumBufferSize
));
288 memset(&Description
,0,sizeof(Description
));
290 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
294 /* only bus masters may call this routine */
295 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
296 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
))
297 return NDIS_STATUS_SUCCESS
;
299 DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
301 KeInitializeEvent(&AllocationEvent
, NotificationEvent
, FALSE
);
302 Adapter
->NdisMiniportBlock
.AllocationEvent
= &AllocationEvent
;
305 * map registers correlate to physical pages. ndis documents a
306 * maximum of 64 map registers that it will return.
307 * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
309 * the number of registers required for a given physical mapping
310 * is (first register + last register + one per page size),
311 * given that physical mapping is > 2.
314 /* unhandled corner case: {1,2}-byte max buffer size */
315 ASSERT(MaximumBufferSize
> 2);
316 MapRegistersPerBaseRegister
= ((MaximumBufferSize
-2) / (2*PAGE_SIZE
)) + 2;
318 Description
.Version
= DEVICE_DESCRIPTION_VERSION
;
319 Description
.Master
= TRUE
; /* implied by calling this function */
320 Description
.ScatterGather
= TRUE
; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
321 Description
.Dma32BitAddresses
= DmaSize
;
322 Description
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
323 Description
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
324 Description
.DmaChannel
= DmaChannel
;
325 Description
.MaximumLength
= MaximumBufferSize
;
327 if(Adapter
->NdisMiniportBlock
.AdapterType
== Isa
)
331 Description
.DmaWidth
= Width8Bits
;
333 Description
.DmaWidth
= Width16Bits
;
335 Description
.DmaSpeed
= Compatible
;
337 else if(Adapter
->NdisMiniportBlock
.AdapterType
== PCIBus
)
339 if(DmaSize
== NDIS_DMA_64BITS
)
340 Description
.Dma64BitAddresses
= TRUE
;
342 Description
.Dma32BitAddresses
= TRUE
;
346 NDIS_DbgPrint(MIN_TRACE
, ("Unsupported bus type\n"));
350 AdapterObject
= IoGetDmaAdapter(
351 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, &Description
, &AvailableMapRegisters
);
355 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate an adapter object; bailing out\n"));
356 return NDIS_STATUS_RESOURCES
;
359 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= AdapterObject
;
361 if(AvailableMapRegisters
< MapRegistersPerBaseRegister
)
363 NDIS_DbgPrint(MIN_TRACE
, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
364 MapRegistersPerBaseRegister
, AvailableMapRegisters
));
366 return NDIS_STATUS_RESOURCES
;
369 /* allocate & zero space in the miniport block for the registers */
370 Adapter
->NdisMiniportBlock
.MapRegisters
= ExAllocatePool(NonPagedPool
, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
371 if(!Adapter
->NdisMiniportBlock
.MapRegisters
)
373 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
374 return NDIS_STATUS_RESOURCES
;
377 memset(Adapter
->NdisMiniportBlock
.MapRegisters
, 0, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
378 Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= (USHORT
)BaseMapRegistersNeeded
;
380 while(BaseMapRegistersNeeded
)
382 NDIS_DbgPrint(MAX_TRACE
, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded
));
384 BaseMapRegistersNeeded
--;
385 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= (USHORT
)BaseMapRegistersNeeded
;
386 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
388 NtStatus
= AdapterObject
->DmaOperations
->AllocateAdapterChannel(
389 AdapterObject
, DeviceObject
, MapRegistersPerBaseRegister
,
390 NdisMapRegisterCallback
, Adapter
);
392 KeLowerIrql(OldIrql
);
394 if(!NT_SUCCESS(NtStatus
))
396 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus
));
397 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
398 return NDIS_STATUS_RESOURCES
;
401 NDIS_DbgPrint(MAX_TRACE
, ("waiting on event\n"));
403 NtStatus
= KeWaitForSingleObject(&AllocationEvent
, Executive
, KernelMode
, FALSE
, 0);
405 if(!NT_SUCCESS(NtStatus
))
407 NDIS_DbgPrint(MIN_TRACE
, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus
));
408 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
409 return NDIS_STATUS_RESOURCES
;
412 NDIS_DbgPrint(MAX_TRACE
, ("resetting event\n"));
414 KeResetEvent(&AllocationEvent
);
417 NDIS_DbgPrint(MAX_TRACE
, ("returning success\n"));
418 return NDIS_STATUS_SUCCESS
;
427 NdisMStartBufferPhysicalMapping(
428 IN NDIS_HANDLE MiniportAdapterHandle
,
429 IN PNDIS_BUFFER Buffer
,
430 IN ULONG PhysicalMapRegister
,
431 IN BOOLEAN WriteToDevice
,
432 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray
,
435 * FUNCTION: Sets up map registers for a bus-master DMA transfer
437 * MiniportAdapterHandle: handle originally input to MiniportInitialize
438 * Buffer: data to be transferred
439 * PhysicalMapRegister: specifies the map register to set up
440 * WriteToDevice: if true, data is being written to the device; else it is being read
441 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
442 * ArraySize: number of elements in PhysicalAddressArray
444 * - Must be called at IRQL <= DISPATCH_LEVEL
445 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes
446 * in order to map all of the virtual memory to physical memoroy readable
448 * - The caller supplies storage for the physical address array.
451 PLOGICAL_ADAPTER Adapter
;
454 PHYSICAL_ADDRESS ReturnedAddress
;
457 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
458 ASSERT(MiniportAdapterHandle
&& Buffer
&& PhysicalAddressArray
&& ArraySize
);
460 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
461 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
462 TotalLength
= MmGetMdlByteCount(Buffer
);
466 ULONG Length
= TotalLength
;
468 ReturnedAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->MapTransfer(
469 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
470 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
471 CurrentVa
, &Length
, WriteToDevice
);
473 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
= WriteToDevice
;
475 PhysicalAddressArray
[LoopCount
].PhysicalAddress
= ReturnedAddress
;
476 PhysicalAddressArray
[LoopCount
].Length
= Length
;
478 TotalLength
-= Length
;
479 CurrentVa
= (PVOID
)((ULONG_PTR
)CurrentVa
+ Length
);
484 *ArraySize
= LoopCount
;
493 NdisMCompleteBufferPhysicalMapping(
494 IN NDIS_HANDLE MiniportAdapterHandle
,
495 IN PNDIS_BUFFER Buffer
,
496 IN ULONG PhysicalMapRegister
)
498 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
500 * - MiniportAdapterHandle: handle originally input to MiniportInitialize
501 * - Buffer: NDIS_BUFFER to complete the mapping on
502 * - PhyscialMapRegister: the chosen map register
504 * - May be called at IRQL <= DISPATCH_LEVEL
507 PLOGICAL_ADAPTER Adapter
;
511 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
512 ASSERT(MiniportAdapterHandle
&& Buffer
);
514 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
515 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
516 Length
= MmGetMdlByteCount(Buffer
);
518 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->FlushAdapterBuffers(
519 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
520 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
522 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
);
531 NdisMDeregisterDmaChannel(
532 IN PNDIS_HANDLE MiniportDmaHandle
)
543 NdisMDeregisterInterrupt(
544 IN PNDIS_MINIPORT_INTERRUPT Interrupt
)
546 * FUNCTION: Releases an interrupt vector
548 * Interrupt = Pointer to interrupt object
551 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
552 IoDisconnectInterrupt(Interrupt
->InterruptObject
);
561 NdisMDeregisterIoPortRange(
562 IN NDIS_HANDLE MiniportAdapterHandle
,
564 IN UINT NumberOfPorts
,
567 * FUNCTION: Releases a register mapping to I/O ports
569 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
570 * InitialPort = Bus-relative base port address of a range to be mapped
571 * NumberOfPorts = Specifies number of ports to be mapped
572 * PortOffset = Pointer to mapped base port address
575 NDIS_DbgPrint(MAX_TRACE
, ("called - IMPLEMENT ME.\n"));
584 NdisMFreeMapRegisters(
585 IN NDIS_HANDLE MiniportAdapterHandle
)
587 * FUNCTION: Free previously allocated map registers
589 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
594 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
595 PDMA_ADAPTER AdapterObject
;
596 UINT MapRegistersPerBaseRegister
;
599 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
603 /* only bus masters may call this routine */
604 ASSERT(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
605 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
) ||
606 Adapter
->NdisMiniportBlock
.SystemAdapterObject
== NULL
)
609 MapRegistersPerBaseRegister
= ((Adapter
->NdisMiniportBlock
.MaximumPhysicalMapping
- 2) / PAGE_SIZE
) + 2;
611 AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
613 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
615 for(i
= 0; i
< Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
; i
++)
617 AdapterObject
->DmaOperations
->FreeMapRegisters(
618 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
619 Adapter
->NdisMiniportBlock
.MapRegisters
[i
].MapRegister
,
620 MapRegistersPerBaseRegister
);
623 KeLowerIrql(OldIrql
);
625 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
626 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
628 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
638 OUT PVOID
*VirtualAddress
,
639 IN NDIS_HANDLE MiniportAdapterHandle
,
640 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
,
643 * FUNCTION: Maps a bus-relative address to a system-wide virtual address
645 * VirtualAddress: receives virtual address of mapping
646 * MiniportAdapterHandle: Handle originally input to MiniportInitialize
647 * PhysicalAddress: bus-relative address to map
648 * Length: Number of bytes to map
650 * NDIS_STATUS_SUCCESS: the operation completed successfully
651 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
652 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
653 * NDIS_STATUS_FAILURE: a general failure has occured
655 * - Must be called at IRQL = PASSIVE_LEVEL
657 * - Only supports things that MmMapIoSpace internally supports - what
658 * about considering bus type, etc?
659 * - doesn't track resources allocated...
663 ASSERT(VirtualAddress
&& MiniportAdapterHandle
);
665 *VirtualAddress
= MmMapIoSpace(PhysicalAddress
, Length
, MmNonCached
);
668 return NDIS_STATUS_RESOURCES
;
670 return NDIS_STATUS_SUCCESS
;
680 IN NDIS_HANDLE MiniportDmaHandle
)
682 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
683 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
685 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
687 if (AdapterObject
== NULL
)
690 return AdapterObject
->DmaOperations
->ReadDmaCounter(AdapterObject
);
699 NdisMGetDmaAlignment(
700 IN NDIS_HANDLE MiniportDmaHandle
)
702 PNDIS_MINIPORT_BLOCK MiniportBlock
= (PNDIS_MINIPORT_BLOCK
)MiniportDmaHandle
;
703 PDMA_ADAPTER AdapterObject
= MiniportBlock
->SystemAdapterObject
;
705 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
707 if (AdapterObject
== NULL
)
710 return AdapterObject
->DmaOperations
->GetDmaAlignment(AdapterObject
);
719 NdisMRegisterDmaChannel(
720 OUT PNDIS_HANDLE MiniportDmaHandle
,
721 IN NDIS_HANDLE MiniportAdapterHandle
,
723 IN BOOLEAN Dma32BitAddresses
,
724 IN PNDIS_DMA_DESCRIPTION DmaDescription
,
725 IN ULONG MaximumLength
)
729 return NDIS_STATUS_FAILURE
;
738 NdisMRegisterInterrupt(
739 OUT PNDIS_MINIPORT_INTERRUPT Interrupt
,
740 IN NDIS_HANDLE MiniportAdapterHandle
,
741 IN UINT InterruptVector
,
742 IN UINT InterruptLevel
,
743 IN BOOLEAN RequestIsr
,
744 IN BOOLEAN SharedInterrupt
,
745 IN NDIS_INTERRUPT_MODE InterruptMode
)
747 * FUNCTION: Claims access to an interrupt vector
749 * Interrupt = Address of interrupt object to initialize
750 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
751 * InterruptVector = Specifies bus-relative vector to register
752 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
753 * RequestIsr = TRUE if MiniportISR should always be called
754 * SharedInterrupt = TRUE if other devices may use the same interrupt
755 * InterruptMode = Specifies type of interrupt
757 * Status of operation
764 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
766 NDIS_DbgPrint(MAX_TRACE
, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
767 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
768 InterruptVector
, InterruptLevel
, SharedInterrupt
, InterruptMode
));
770 RtlZeroMemory(Interrupt
, sizeof(NDIS_MINIPORT_INTERRUPT
));
772 KeInitializeSpinLock(&Interrupt
->DpcCountLock
);
774 KeInitializeDpc(&Interrupt
->InterruptDpc
, HandleDeferredProcessing
, Adapter
);
776 KeInitializeEvent(&Interrupt
->DpcsCompletedEvent
, NotificationEvent
, FALSE
);
778 Interrupt
->SharedInterrupt
= SharedInterrupt
;
779 Interrupt
->IsrRequested
= RequestIsr
;
781 Adapter
->NdisMiniportBlock
.Interrupt
= Interrupt
;
783 MappedIRQ
= HalGetInterruptVector(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
784 InterruptLevel
, InterruptVector
, &DIrql
,
787 NDIS_DbgPrint(MAX_TRACE
, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ
, Affinity
));
789 Status
= IoConnectInterrupt(&Interrupt
->InterruptObject
, ServiceRoutine
, Adapter
, &Interrupt
->DpcCountLock
, MappedIRQ
,
790 DIrql
, DIrql
, InterruptMode
, SharedInterrupt
, Affinity
, FALSE
);
792 NDIS_DbgPrint(MAX_TRACE
, ("Leaving. Status (0x%X).\n", Status
));
794 if (NT_SUCCESS(Status
))
795 return NDIS_STATUS_SUCCESS
;
797 if (Status
== STATUS_INSUFFICIENT_RESOURCES
)
799 /* FIXME: Log error */
800 NDIS_DbgPrint(MIN_TRACE
, ("Resource conflict!\n"));
801 return NDIS_STATUS_RESOURCE_CONFLICT
;
804 NDIS_DbgPrint(MIN_TRACE
, ("Function failed. Status (0x%X).\n", Status
));
805 return NDIS_STATUS_FAILURE
;
814 NdisMRegisterIoPortRange(
815 OUT PVOID
*PortOffset
,
816 IN NDIS_HANDLE MiniportAdapterHandle
,
818 IN UINT NumberOfPorts
)
820 * FUNCTION: Sets up driver access to device I/O ports
822 * PortOffset = Address of buffer to place mapped base port address
823 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
824 * InitialPort = Bus-relative base port address of a range to be mapped
825 * NumberOfPorts = Specifies number of ports to be mapped
827 * Status of operation
830 PHYSICAL_ADDRESS PortAddress
, TranslatedAddress
;
831 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
832 ULONG AddressSpace
= 1; /* FIXME The HAL handles this wrong atm */
836 NDIS_DbgPrint(MAX_TRACE
, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort
, NumberOfPorts
));
838 memset(&PortAddress
, 0, sizeof(PortAddress
));
841 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
842 * we don't have a way to get the I/O base address yet (see
843 * NDIS_MINIPORT_BLOCK->AllocatedResources and
844 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
847 PortAddress
= RtlConvertUlongToLargeInteger(InitialPort
);
851 NDIS_DbgPrint(MAX_TRACE
, ("Translating address 0x%x 0x%x\n", PortAddress
.u
.HighPart
, PortAddress
.u
.LowPart
));
853 if(!HalTranslateBusAddress(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
854 PortAddress
, &AddressSpace
, &TranslatedAddress
))
856 NDIS_DbgPrint(MIN_TRACE
, ("Unable to translate address\n"));
857 return NDIS_STATUS_RESOURCES
;
860 NDIS_DbgPrint(MAX_TRACE
, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
861 AddressSpace
, TranslatedAddress
.u
.HighPart
, TranslatedAddress
.u
.LowPart
));
865 ASSERT(TranslatedAddress
.u
.HighPart
== 0);
866 *PortOffset
= (PVOID
)(ULONG_PTR
)TranslatedAddress
.QuadPart
;
867 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x\n", *PortOffset
));
868 return NDIS_STATUS_SUCCESS
;
871 NDIS_DbgPrint(MAX_TRACE
, ("calling MmMapIoSpace\n"));
873 *PortOffset
= MmMapIoSpace(TranslatedAddress
, NumberOfPorts
, MmNonCached
);
874 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x for port range\n", *PortOffset
));
877 return NDIS_STATUS_RESOURCES
;
879 return NDIS_STATUS_SUCCESS
;
889 IN NDIS_HANDLE MiniportAdapterHandle
,
890 IN PVOID VirtualAddress
,
893 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
895 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
896 * VirtualAddress: Address to un-map
897 * Length: length of the mapped memory space
899 * - Must be called at IRQL = PASSIVE_LEVEL
900 * - Must only be called from MiniportInitialize and MiniportHalt
901 * - See also: NdisMMapIoSpace
903 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
908 ASSERT(MiniportAdapterHandle
);
910 MmUnmapIoSpace(VirtualAddress
, Length
);