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 (PNDIS_MINIPORT_INTERRUPT)
60 * TRUE if a miniport controlled device generated the interrupt
63 BOOLEAN InterruptRecognized
= FALSE
;
64 BOOLEAN QueueMiniportHandleInterrupt
= FALSE
;
65 PNDIS_MINIPORT_INTERRUPT NdisInterrupt
= ServiceContext
;
66 PNDIS_MINIPORT_BLOCK NdisMiniportBlock
= NdisInterrupt
->Miniport
;
68 NDIS_DbgPrint(MAX_TRACE
, ("Called. Interrupt (0x%X)\n", NdisInterrupt
));
70 if (NdisInterrupt
->IsrRequested
) {
71 NDIS_DbgPrint(MAX_TRACE
, ("Calling MiniportISR\n"));
72 (*NdisMiniportBlock
->DriverHandle
->MiniportCharacteristics
.ISRHandler
)(
74 &QueueMiniportHandleInterrupt
,
75 NdisMiniportBlock
->MiniportAdapterContext
);
77 } else if (NdisMiniportBlock
->DriverHandle
->MiniportCharacteristics
.DisableInterruptHandler
) {
78 NDIS_DbgPrint(MAX_TRACE
, ("Calling MiniportDisableInterrupt\n"));
79 (*NdisMiniportBlock
->DriverHandle
->MiniportCharacteristics
.DisableInterruptHandler
)(
80 NdisMiniportBlock
->MiniportAdapterContext
);
81 QueueMiniportHandleInterrupt
= TRUE
;
82 InterruptRecognized
= TRUE
;
86 if (QueueMiniportHandleInterrupt
)
88 NDIS_DbgPrint(MAX_TRACE
, ("Queuing DPC.\n"));
89 KeInsertQueueDpc(&NdisInterrupt
->InterruptDpc
, NULL
, NULL
);
92 NDIS_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
94 return InterruptRecognized
;
103 NdisImmediateReadPortUchar(
104 IN NDIS_HANDLE WrapperConfigurationContext
,
108 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
109 *Data
= READ_PORT_UCHAR(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
118 NdisImmediateReadPortUlong(
119 IN NDIS_HANDLE WrapperConfigurationContext
,
123 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
124 *Data
= READ_PORT_ULONG(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
133 NdisImmediateReadPortUshort(
134 IN NDIS_HANDLE WrapperConfigurationContext
,
138 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
139 *Data
= READ_PORT_USHORT(UlongToPtr(Port
)); // FIXME: What to do with WrapperConfigurationContext?
148 NdisImmediateWritePortUchar(
149 IN NDIS_HANDLE WrapperConfigurationContext
,
153 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
154 WRITE_PORT_UCHAR(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
163 NdisImmediateWritePortUlong(
164 IN NDIS_HANDLE WrapperConfigurationContext
,
168 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
169 WRITE_PORT_ULONG(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
178 NdisImmediateWritePortUshort(
179 IN NDIS_HANDLE WrapperConfigurationContext
,
183 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
184 WRITE_PORT_USHORT(UlongToPtr(Port
), Data
); // FIXME: What to do with WrapperConfigurationContext?
188 IO_ALLOCATION_ACTION NTAPI
NdisMapRegisterCallback (
189 IN PDEVICE_OBJECT DeviceObject
,
191 IN PVOID MapRegisterBase
,
194 * FUNCTION: Called back during reservation of map registers
196 * DeviceObject: Device object of the deivce setting up DMA
197 * Irp: Reserved; must be ignored
198 * MapRegisterBase: Map registers assigned for transfer
199 * Context: LOGICAL_ADAPTER object of the requesting miniport
201 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
202 * - Called at IRQL = DISPATCH_LEVEL
205 PLOGICAL_ADAPTER Adapter
= Context
;
207 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
209 Adapter
->NdisMiniportBlock
.MapRegisters
[Adapter
->NdisMiniportBlock
.CurrentMapRegister
].MapRegister
= MapRegisterBase
;
211 NDIS_DbgPrint(MAX_TRACE
, ("setting event and leaving.\n"));
213 KeSetEvent(Adapter
->NdisMiniportBlock
.AllocationEvent
, 0, FALSE
);
215 /* this is only the thing to do for busmaster NICs */
216 return DeallocateObjectKeepRegisters
;
225 NdisMAllocateMapRegisters(
226 IN NDIS_HANDLE MiniportAdapterHandle
,
228 IN NDIS_DMA_SIZE DmaSize
,
229 IN ULONG BaseMapRegistersNeeded
,
230 IN ULONG MaximumBufferSize
)
232 * FUNCTION: Allocate map registers for use in DMA transfers
234 * MiniportAdapterHandle: Passed in to MiniportInitialize
235 * DmaChannel: DMA channel to use
236 * DmaSize: bit width of DMA transfers
237 * BaseMapRegistersNeeded: number of base map registers requested
238 * MaximumBufferSize: largest single buffer transferred
240 * NDIS_STATUS_SUCCESS on success
241 * NDIS_STATUS_RESOURCES on failure
243 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
244 * I'm implementing the 2k one.
245 * - do not confuse a "base map register" with a "map register" - they
246 * are different. Only NDIS seems to use the base concept. The idea
247 * is that a miniport supplies the number of base map registers it will
248 * need, which is equal to the number of DMA send buffers it manages.
249 * NDIS then allocates a number of map registers to go with each base
250 * map register, so that a driver just has to send the base map register
251 * number during dma operations and NDIS can find the group of real
252 * map registers that represent the transfer.
253 * - Because of the above sillyness, you can only specify a few base map
254 * registers at most. a 1514-byte packet is two map registers at 4k
256 * - NDIS limits the total number of allocated map registers to 64,
257 * which (in the case of the above example) limits the number of base
258 * map registers to 32.
261 DEVICE_DESCRIPTION Description
;
262 PDMA_ADAPTER AdapterObject
= 0;
263 UINT MapRegistersPerBaseRegister
= 0;
264 ULONG AvailableMapRegisters
;
266 PLOGICAL_ADAPTER Adapter
;
267 PDEVICE_OBJECT DeviceObject
= 0;
268 KEVENT AllocationEvent
;
271 NDIS_DbgPrint(MAX_TRACE
, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
272 MiniportAdapterHandle
, DmaChannel
, DmaSize
, BaseMapRegistersNeeded
, MaximumBufferSize
));
274 memset(&Description
,0,sizeof(Description
));
276 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
280 /* only bus masters may call this routine */
281 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
)) {
282 NDIS_DbgPrint(MIN_TRACE
, ("Not a bus master\n"));
283 return NDIS_STATUS_NOT_SUPPORTED
;
286 DeviceObject
= Adapter
->NdisMiniportBlock
.DeviceObject
;
288 KeInitializeEvent(&AllocationEvent
, NotificationEvent
, FALSE
);
289 Adapter
->NdisMiniportBlock
.AllocationEvent
= &AllocationEvent
;
292 * map registers correlate to physical pages. ndis documents a
293 * maximum of 64 map registers that it will return.
294 * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
296 * the number of registers required for a given physical mapping
297 * is (first register + last register + one per page size),
298 * given that physical mapping is > 2.
301 /* unhandled corner case: {1,2}-byte max buffer size */
302 ASSERT(MaximumBufferSize
> 2);
303 MapRegistersPerBaseRegister
= ((MaximumBufferSize
-2) / (2*PAGE_SIZE
)) + 2;
305 Description
.Version
= DEVICE_DESCRIPTION_VERSION
;
306 Description
.Master
= TRUE
; /* implied by calling this function */
307 Description
.ScatterGather
= TRUE
; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
308 Description
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
309 Description
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
310 Description
.DmaChannel
= DmaChannel
;
311 Description
.MaximumLength
= MaximumBufferSize
;
313 if(DmaSize
== NDIS_DMA_64BITS
)
314 Description
.Dma64BitAddresses
= TRUE
;
315 else if(DmaSize
== NDIS_DMA_32BITS
)
316 Description
.Dma32BitAddresses
= TRUE
;
318 AdapterObject
= IoGetDmaAdapter(
319 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, &Description
, &AvailableMapRegisters
);
323 NDIS_DbgPrint(MIN_TRACE
, ("Unable to allocate an adapter object; bailing out\n"));
324 return NDIS_STATUS_RESOURCES
;
327 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= AdapterObject
;
329 if(AvailableMapRegisters
< MapRegistersPerBaseRegister
)
331 NDIS_DbgPrint(MIN_TRACE
, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
332 MapRegistersPerBaseRegister
, AvailableMapRegisters
));
334 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
335 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
336 return NDIS_STATUS_RESOURCES
;
339 /* allocate & zero space in the miniport block for the registers */
340 Adapter
->NdisMiniportBlock
.MapRegisters
= ExAllocatePool(NonPagedPool
, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
341 if(!Adapter
->NdisMiniportBlock
.MapRegisters
)
343 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
344 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
345 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
346 return NDIS_STATUS_RESOURCES
;
349 memset(Adapter
->NdisMiniportBlock
.MapRegisters
, 0, BaseMapRegistersNeeded
* sizeof(MAP_REGISTER_ENTRY
));
350 Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= (USHORT
)BaseMapRegistersNeeded
;
352 while(BaseMapRegistersNeeded
)
354 NDIS_DbgPrint(MAX_TRACE
, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded
));
356 BaseMapRegistersNeeded
--;
357 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= (USHORT
)BaseMapRegistersNeeded
;
358 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
360 NtStatus
= AdapterObject
->DmaOperations
->AllocateAdapterChannel(
361 AdapterObject
, DeviceObject
, MapRegistersPerBaseRegister
,
362 NdisMapRegisterCallback
, Adapter
);
364 KeLowerIrql(OldIrql
);
366 if(!NT_SUCCESS(NtStatus
))
368 NDIS_DbgPrint(MIN_TRACE
, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus
));
369 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
370 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
371 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= 0;
372 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
373 return NDIS_STATUS_RESOURCES
;
376 NDIS_DbgPrint(MAX_TRACE
, ("waiting on event\n"));
378 NtStatus
= KeWaitForSingleObject(&AllocationEvent
, Executive
, KernelMode
, FALSE
, 0);
380 if(!NT_SUCCESS(NtStatus
))
382 NDIS_DbgPrint(MIN_TRACE
, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus
));
383 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
384 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
385 Adapter
->NdisMiniportBlock
.CurrentMapRegister
= Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
= 0;
386 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
387 return NDIS_STATUS_RESOURCES
;
390 NDIS_DbgPrint(MAX_TRACE
, ("resetting event\n"));
392 KeResetEvent(&AllocationEvent
);
395 NDIS_DbgPrint(MAX_TRACE
, ("returning success\n"));
396 return NDIS_STATUS_SUCCESS
;
405 NdisMStartBufferPhysicalMapping(
406 IN NDIS_HANDLE MiniportAdapterHandle
,
407 IN PNDIS_BUFFER Buffer
,
408 IN ULONG PhysicalMapRegister
,
409 IN BOOLEAN WriteToDevice
,
410 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray
,
413 * FUNCTION: Sets up map registers for a bus-master DMA transfer
415 * MiniportAdapterHandle: handle originally input to MiniportInitialize
416 * Buffer: data to be transferred
417 * PhysicalMapRegister: specifies the map register to set up
418 * WriteToDevice: if true, data is being written to the device; else it is being read
419 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
420 * ArraySize: number of elements in PhysicalAddressArray
422 * - Must be called at IRQL <= DISPATCH_LEVEL
423 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes
424 * in order to map all of the virtual memory to physical memoroy readable
426 * - The caller supplies storage for the physical address array.
429 PLOGICAL_ADAPTER Adapter
;
432 PHYSICAL_ADDRESS ReturnedAddress
;
435 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
436 ASSERT(MiniportAdapterHandle
&& Buffer
&& PhysicalAddressArray
&& ArraySize
);
438 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
439 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
440 TotalLength
= MmGetMdlByteCount(Buffer
);
444 ULONG Length
= TotalLength
;
446 ReturnedAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->MapTransfer(
447 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
448 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
449 CurrentVa
, &Length
, WriteToDevice
);
451 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
= WriteToDevice
;
453 PhysicalAddressArray
[LoopCount
].PhysicalAddress
= ReturnedAddress
;
454 PhysicalAddressArray
[LoopCount
].Length
= Length
;
456 TotalLength
-= Length
;
457 CurrentVa
= (PVOID
)((ULONG_PTR
)CurrentVa
+ Length
);
462 *ArraySize
= LoopCount
;
471 NdisMCompleteBufferPhysicalMapping(
472 IN NDIS_HANDLE MiniportAdapterHandle
,
473 IN PNDIS_BUFFER Buffer
,
474 IN ULONG PhysicalMapRegister
)
476 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
478 * - MiniportAdapterHandle: handle originally input to MiniportInitialize
479 * - Buffer: NDIS_BUFFER to complete the mapping on
480 * - PhyscialMapRegister: the chosen map register
482 * - May be called at IRQL <= DISPATCH_LEVEL
485 PLOGICAL_ADAPTER Adapter
;
489 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
490 ASSERT(MiniportAdapterHandle
&& Buffer
);
492 Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
493 CurrentVa
= MmGetMdlVirtualAddress(Buffer
);
494 Length
= MmGetMdlByteCount(Buffer
);
496 Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->FlushAdapterBuffers(
497 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Buffer
,
498 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].MapRegister
,
500 Adapter
->NdisMiniportBlock
.MapRegisters
[PhysicalMapRegister
].WriteToDevice
);
509 NdisMDeregisterDmaChannel(
510 IN NDIS_HANDLE MiniportDmaHandle
)
512 PNDIS_DMA_BLOCK DmaBlock
= MiniportDmaHandle
;
513 PDMA_ADAPTER AdapterObject
= (PDMA_ADAPTER
)DmaBlock
->SystemAdapterObject
;
515 if (AdapterObject
== ((PLOGICAL_ADAPTER
)DmaBlock
->Miniport
)->NdisMiniportBlock
.SystemAdapterObject
)
516 ((PLOGICAL_ADAPTER
)DmaBlock
->Miniport
)->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
518 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
520 ExFreePool(DmaBlock
);
529 NdisMDeregisterInterrupt(
530 IN PNDIS_MINIPORT_INTERRUPT Interrupt
)
532 * FUNCTION: Releases an interrupt vector
534 * Interrupt = Pointer to interrupt object
537 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
538 IoDisconnectInterrupt(Interrupt
->InterruptObject
);
539 Interrupt
->Miniport
->RegisteredInterrupts
--;
541 if (Interrupt
->Miniport
->Interrupt
== Interrupt
)
542 Interrupt
->Miniport
->Interrupt
= NULL
;
551 NdisMFreeMapRegisters(
552 IN NDIS_HANDLE MiniportAdapterHandle
)
554 * FUNCTION: Free previously allocated map registers
556 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
561 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
562 PDMA_ADAPTER AdapterObject
;
563 UINT MapRegistersPerBaseRegister
;
566 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
570 /* only bus masters may call this routine */
571 if(!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
) ||
572 Adapter
->NdisMiniportBlock
.SystemAdapterObject
== NULL
) {
573 NDIS_DbgPrint(MIN_TRACE
, ("Not bus master or bad adapter object\n"));
577 MapRegistersPerBaseRegister
= ((Adapter
->NdisMiniportBlock
.MaximumPhysicalMapping
- 2) / PAGE_SIZE
) + 2;
579 AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
581 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
583 for(i
= 0; i
< Adapter
->NdisMiniportBlock
.BaseMapRegistersNeeded
; i
++)
585 AdapterObject
->DmaOperations
->FreeMapRegisters(
586 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
587 Adapter
->NdisMiniportBlock
.MapRegisters
[i
].MapRegister
,
588 MapRegistersPerBaseRegister
);
591 KeLowerIrql(OldIrql
);
593 AdapterObject
->DmaOperations
->PutDmaAdapter(AdapterObject
);
594 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= NULL
;
596 ExFreePool(Adapter
->NdisMiniportBlock
.MapRegisters
);
606 OUT PVOID
*VirtualAddress
,
607 IN NDIS_HANDLE MiniportAdapterHandle
,
608 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
,
611 * FUNCTION: Maps a bus-relative address to a system-wide virtual address
613 * VirtualAddress: receives virtual address of mapping
614 * MiniportAdapterHandle: Handle originally input to MiniportInitialize
615 * PhysicalAddress: bus-relative address to map
616 * Length: Number of bytes to map
618 * NDIS_STATUS_SUCCESS: the operation completed successfully
619 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
620 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
621 * NDIS_STATUS_FAILURE: a general failure has occured
623 * - Must be called at IRQL = PASSIVE_LEVEL
626 PLOGICAL_ADAPTER Adapter
= MiniportAdapterHandle
;
627 ULONG AddressSpace
= 0; /* Memory Space */
628 NDIS_PHYSICAL_ADDRESS TranslatedAddress
;
631 ASSERT(VirtualAddress
&& MiniportAdapterHandle
);
633 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
635 if(!HalTranslateBusAddress(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
636 PhysicalAddress
, &AddressSpace
, &TranslatedAddress
))
638 NDIS_DbgPrint(MIN_TRACE
, ("Unable to translate address\n"));
639 return NDIS_STATUS_RESOURCES
;
642 *VirtualAddress
= MmMapIoSpace(TranslatedAddress
, Length
, MmNonCached
);
644 if(!*VirtualAddress
) {
645 NDIS_DbgPrint(MIN_TRACE
, ("MmMapIoSpace failed\n"));
646 return NDIS_STATUS_RESOURCES
;
649 return NDIS_STATUS_SUCCESS
;
659 IN NDIS_HANDLE MiniportDmaHandle
)
661 PNDIS_DMA_BLOCK DmaBlock
= MiniportDmaHandle
;
662 PDMA_ADAPTER AdapterObject
= (PDMA_ADAPTER
)DmaBlock
->SystemAdapterObject
;
664 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
666 return AdapterObject
->DmaOperations
->ReadDmaCounter(AdapterObject
);
675 NdisMGetDmaAlignment(
676 IN NDIS_HANDLE MiniportDmaHandle
)
678 PNDIS_DMA_BLOCK DmaBlock
= MiniportDmaHandle
;
679 PDMA_ADAPTER AdapterObject
= (PDMA_ADAPTER
)DmaBlock
->SystemAdapterObject
;
681 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
683 return AdapterObject
->DmaOperations
->GetDmaAlignment(AdapterObject
);
692 NdisMRegisterDmaChannel(
693 OUT PNDIS_HANDLE MiniportDmaHandle
,
694 IN NDIS_HANDLE MiniportAdapterHandle
,
696 IN BOOLEAN Dma32BitAddresses
,
697 IN PNDIS_DMA_DESCRIPTION DmaDescription
,
698 IN ULONG MaximumLength
)
700 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
701 DEVICE_DESCRIPTION DeviceDesc
;
703 PNDIS_DMA_BLOCK DmaBlock
;
705 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
707 RtlZeroMemory(&DeviceDesc
, sizeof(DEVICE_DESCRIPTION
));
709 DeviceDesc
.Version
= DEVICE_DESCRIPTION_VERSION
;
710 DeviceDesc
.Master
= (Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
);
711 DeviceDesc
.ScatterGather
= FALSE
; //Is this correct?
712 DeviceDesc
.DemandMode
= DmaDescription
->DemandMode
;
713 DeviceDesc
.AutoInitialize
= DmaDescription
->AutoInitialize
;
714 DeviceDesc
.Dma32BitAddresses
= Dma32BitAddresses
;
715 DeviceDesc
.Dma64BitAddresses
= !Dma32BitAddresses
; //Is this correct?
716 DeviceDesc
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
717 DeviceDesc
.DmaChannel
= DmaDescription
->DmaChannel
;
718 DeviceDesc
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
719 DeviceDesc
.DmaWidth
= DmaDescription
->DmaWidth
;
720 DeviceDesc
.DmaSpeed
= DmaDescription
->DmaSpeed
;
721 DeviceDesc
.MaximumLength
= MaximumLength
;
724 DmaBlock
= ExAllocatePool(NonPagedPool
, sizeof(NDIS_DMA_BLOCK
));
726 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
727 return NDIS_STATUS_RESOURCES
;
730 DmaBlock
->SystemAdapterObject
= (PVOID
)IoGetDmaAdapter(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, &DeviceDesc
, &MapRegisters
);
732 if (!DmaBlock
->SystemAdapterObject
) {
733 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
734 ExFreePool(DmaBlock
);
735 return NDIS_STATUS_RESOURCES
;
738 Adapter
->NdisMiniportBlock
.SystemAdapterObject
= (PDMA_ADAPTER
)DmaBlock
->SystemAdapterObject
;
740 DmaBlock
->Miniport
= Adapter
;
742 *MiniportDmaHandle
= DmaBlock
;
744 return NDIS_STATUS_SUCCESS
;
753 NdisMRegisterInterrupt(
754 OUT PNDIS_MINIPORT_INTERRUPT Interrupt
,
755 IN NDIS_HANDLE MiniportAdapterHandle
,
756 IN UINT InterruptVector
,
757 IN UINT InterruptLevel
,
758 IN BOOLEAN RequestIsr
,
759 IN BOOLEAN SharedInterrupt
,
760 IN NDIS_INTERRUPT_MODE InterruptMode
)
762 * FUNCTION: Claims access to an interrupt vector
764 * Interrupt = Address of interrupt object to initialize
765 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
766 * InterruptVector = Specifies bus-relative vector to register
767 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
768 * RequestIsr = TRUE if MiniportISR should always be called
769 * SharedInterrupt = TRUE if other devices may use the same interrupt
770 * InterruptMode = Specifies type of interrupt
772 * Status of operation
779 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
781 NDIS_DbgPrint(MAX_TRACE
, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
782 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
783 InterruptVector
, InterruptLevel
, SharedInterrupt
, InterruptMode
));
785 RtlZeroMemory(Interrupt
, sizeof(NDIS_MINIPORT_INTERRUPT
));
787 KeInitializeSpinLock(&Interrupt
->DpcCountLock
);
789 KeInitializeDpc(&Interrupt
->InterruptDpc
, HandleDeferredProcessing
, Adapter
);
791 KeInitializeEvent(&Interrupt
->DpcsCompletedEvent
, NotificationEvent
, FALSE
);
793 Interrupt
->SharedInterrupt
= SharedInterrupt
;
794 Interrupt
->IsrRequested
= RequestIsr
;
795 Interrupt
->Miniport
= &Adapter
->NdisMiniportBlock
;
797 MappedIRQ
= HalGetInterruptVector(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
798 InterruptLevel
, InterruptVector
, &DIrql
,
801 NDIS_DbgPrint(MAX_TRACE
, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ
, Affinity
));
803 Status
= IoConnectInterrupt(&Interrupt
->InterruptObject
, ServiceRoutine
, Interrupt
, &Interrupt
->DpcCountLock
, MappedIRQ
,
804 DIrql
, DIrql
, InterruptMode
, SharedInterrupt
, Affinity
, FALSE
);
806 NDIS_DbgPrint(MAX_TRACE
, ("Leaving. Status (0x%X).\n", Status
));
808 if (NT_SUCCESS(Status
)) {
809 Adapter
->NdisMiniportBlock
.Interrupt
= Interrupt
;
810 Adapter
->NdisMiniportBlock
.RegisteredInterrupts
++;
811 return NDIS_STATUS_SUCCESS
;
814 if (Status
== STATUS_INSUFFICIENT_RESOURCES
)
816 /* FIXME: Log error */
817 NDIS_DbgPrint(MIN_TRACE
, ("Resource conflict!\n"));
818 return NDIS_STATUS_RESOURCE_CONFLICT
;
821 NDIS_DbgPrint(MIN_TRACE
, ("Function failed. Status (0x%X).\n", Status
));
822 return NDIS_STATUS_FAILURE
;
831 NdisMRegisterIoPortRange(
832 OUT PVOID
*PortOffset
,
833 IN NDIS_HANDLE MiniportAdapterHandle
,
835 IN UINT NumberOfPorts
)
837 * FUNCTION: Sets up driver access to device I/O ports
839 * PortOffset = Address of buffer to place mapped base port address
840 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
841 * InitialPort = Bus-relative base port address of a range to be mapped
842 * NumberOfPorts = Specifies number of ports to be mapped
844 * Status of operation
847 PHYSICAL_ADDRESS PortAddress
, TranslatedAddress
;
848 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
849 ULONG AddressSpace
= 1; /* FIXME The HAL handles this wrong atm */
853 NDIS_DbgPrint(MAX_TRACE
, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort
, NumberOfPorts
));
855 memset(&PortAddress
, 0, sizeof(PortAddress
));
858 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
859 * we don't have a way to get the I/O base address yet (see
860 * NDIS_MINIPORT_BLOCK->AllocatedResources and
861 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
864 PortAddress
= RtlConvertUlongToLargeInteger(InitialPort
);
868 NDIS_DbgPrint(MAX_TRACE
, ("Translating address 0x%x 0x%x\n", PortAddress
.u
.HighPart
, PortAddress
.u
.LowPart
));
870 if(!HalTranslateBusAddress(Adapter
->NdisMiniportBlock
.BusType
, Adapter
->NdisMiniportBlock
.BusNumber
,
871 PortAddress
, &AddressSpace
, &TranslatedAddress
))
873 NDIS_DbgPrint(MIN_TRACE
, ("Unable to translate address\n"));
874 return NDIS_STATUS_RESOURCES
;
877 NDIS_DbgPrint(MAX_TRACE
, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
878 AddressSpace
, TranslatedAddress
.u
.HighPart
, TranslatedAddress
.u
.LowPart
));
882 ASSERT(TranslatedAddress
.u
.HighPart
== 0);
883 *PortOffset
= (PVOID
)(ULONG_PTR
)TranslatedAddress
.QuadPart
;
884 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x\n", *PortOffset
));
885 return NDIS_STATUS_SUCCESS
;
888 NDIS_DbgPrint(MAX_TRACE
, ("calling MmMapIoSpace\n"));
890 *PortOffset
= MmMapIoSpace(TranslatedAddress
, NumberOfPorts
, MmNonCached
);
891 NDIS_DbgPrint(MAX_TRACE
, ("Returning 0x%x for port range\n", *PortOffset
));
894 NDIS_DbgPrint(MIN_TRACE
, ("MmMapIoSpace failed\n"));
895 return NDIS_STATUS_RESOURCES
;
898 return NDIS_STATUS_SUCCESS
;
908 IN NDIS_HANDLE MiniportAdapterHandle
,
909 IN PVOID VirtualAddress
,
912 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
914 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
915 * VirtualAddress: Address to un-map
916 * Length: length of the mapped memory space
918 * - Must be called at IRQL = PASSIVE_LEVEL
919 * - Must only be called from MiniportInitialize and MiniportHalt
920 * - See also: NdisMMapIoSpace
922 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
927 ASSERT(MiniportAdapterHandle
);
929 MmUnmapIoSpace(VirtualAddress
, Length
);
937 NdisMInitializeScatterGatherDma(
938 IN NDIS_HANDLE MiniportAdapterHandle
,
939 IN BOOLEAN Dma64BitAddresses
,
940 IN ULONG MaximumPhysicalMapping
)
948 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
950 DEVICE_DESCRIPTION DeviceDesc
;
952 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
954 if (!(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_BUS_MASTER
)) {
955 NDIS_DbgPrint(MIN_TRACE
, ("Not a bus master\n"));
956 return NDIS_STATUS_NOT_SUPPORTED
;
959 RtlZeroMemory(&DeviceDesc
, sizeof(DEVICE_DESCRIPTION
));
961 DeviceDesc
.Version
= DEVICE_DESCRIPTION_VERSION
;
962 DeviceDesc
.Master
= TRUE
;
963 DeviceDesc
.ScatterGather
= TRUE
;
964 DeviceDesc
.Dma32BitAddresses
= !Dma64BitAddresses
;
965 DeviceDesc
.Dma64BitAddresses
= Dma64BitAddresses
;
966 DeviceDesc
.BusNumber
= Adapter
->NdisMiniportBlock
.BusNumber
;
967 DeviceDesc
.InterfaceType
= Adapter
->NdisMiniportBlock
.BusType
;
968 DeviceDesc
.MaximumLength
= MaximumPhysicalMapping
;
970 Adapter
->NdisMiniportBlock
.SystemAdapterObject
=
971 IoGetDmaAdapter(Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
, &DeviceDesc
, &MapRegisters
);
973 if (!Adapter
->NdisMiniportBlock
.SystemAdapterObject
)
974 return NDIS_STATUS_RESOURCES
;
976 /* FIXME: Right now we just use this as a place holder */
977 Adapter
->NdisMiniportBlock
.ScatterGatherListSize
= 1;
979 return NDIS_STATUS_SUCCESS
;
989 OUT PNDIS_STATUS Status
,
990 OUT PVOID
*VirtualAddress
,
991 IN NDIS_HANDLE NdisAdapterHandle
,
992 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
,
1001 *Status
= NdisMMapIoSpace(VirtualAddress
,
1014 IN PNDIS_HANDLE NdisDmaHandle
)
1022 NdisMDeregisterDmaChannel(NdisDmaHandle
);