[DRIVERS] Use KeClearEvent instead of KeResetEvent where the previous state is not...
[reactos.git] / drivers / network / ndis / ndis / io.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/io.c
5 * PURPOSE: I/O related routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 Vizzini - DMA support
11 * 3 Oct 2003 Vizzini - Formatting and minor bugfixes
12 */
13
14 #include "ndissys.h"
15
16 VOID NTAPI HandleDeferredProcessing(
17 IN PKDPC Dpc,
18 IN PVOID DeferredContext,
19 IN PVOID SystemArgument1,
20 IN PVOID SystemArgument2)
21 /*
22 * FUNCTION: Deferred interrupt processing routine
23 * ARGUMENTS:
24 * Dpc = Pointer to DPC object
25 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
26 * SystemArgument1 = Unused
27 * SystemArgument2 = Unused
28 */
29 {
30 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
31
32 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
33
34 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
35
36 /* Call the deferred interrupt service handler for this adapter */
37 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HandleInterruptHandler)(
38 Adapter->NdisMiniportBlock.MiniportAdapterContext);
39
40 /* re-enable the interrupt */
41 NDIS_DbgPrint(MAX_TRACE, ("re-enabling the interrupt\n"));
42 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler)
43 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler)(
44 Adapter->NdisMiniportBlock.MiniportAdapterContext);
45
46 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
47 }
48
49 BOOLEAN NTAPI ServiceRoutine(
50 IN PKINTERRUPT Interrupt,
51 IN PVOID ServiceContext)
52 /*
53 * FUNCTION: Interrupt service routine
54 * ARGUMENTS:
55 * Interrupt = Pointer to interrupt object
56 * ServiceContext = Pointer to context information (PNDIS_MINIPORT_INTERRUPT)
57 * RETURNS
58 * TRUE if a miniport controlled device generated the interrupt
59 */
60 {
61 BOOLEAN InterruptRecognized = FALSE;
62 BOOLEAN QueueMiniportHandleInterrupt = FALSE;
63 PNDIS_MINIPORT_INTERRUPT NdisInterrupt = ServiceContext;
64 PNDIS_MINIPORT_BLOCK NdisMiniportBlock = NdisInterrupt->Miniport;
65 BOOLEAN Initializing;
66
67 NDIS_DbgPrint(MAX_TRACE, ("Called. Interrupt (0x%X)\n", NdisInterrupt));
68
69 /* Certain behavior differs if MiniportInitialize is executing when the interrupt is generated */
70 Initializing = (NdisMiniportBlock->PnPDeviceState != NdisPnPDeviceStarted);
71 NDIS_DbgPrint(MAX_TRACE, ("MiniportInitialize executing: %s\n", (Initializing ? "yes" : "no")));
72
73 /* MiniportISR is always called for interrupts during MiniportInitialize */
74 if ((Initializing) || (NdisInterrupt->IsrRequested) || (NdisInterrupt->SharedInterrupt)) {
75 NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportISR\n"));
76 (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.ISRHandler)(
77 &InterruptRecognized,
78 &QueueMiniportHandleInterrupt,
79 NdisMiniportBlock->MiniportAdapterContext);
80
81 } else if (NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler) {
82 NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportDisableInterrupt\n"));
83 (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler)(
84 NdisMiniportBlock->MiniportAdapterContext);
85 QueueMiniportHandleInterrupt = TRUE;
86 InterruptRecognized = TRUE;
87 }
88
89 /* TODO: Figure out if we should call this or not if Initializing is true. It appears
90 * that calling it fixes some NICs, but documentation is contradictory on it. */
91 if (QueueMiniportHandleInterrupt)
92 {
93 NDIS_DbgPrint(MAX_TRACE, ("Queuing DPC.\n"));
94 KeInsertQueueDpc(&NdisInterrupt->InterruptDpc, NULL, NULL);
95 }
96
97 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
98
99 return InterruptRecognized;
100 }
101
102 /*
103 * @implemented
104 */
105 VOID
106 EXPORT
107 NdisImmediateReadPortUchar(
108 IN NDIS_HANDLE WrapperConfigurationContext,
109 IN ULONG Port,
110 OUT PUCHAR Data)
111 {
112 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
113 *Data = READ_PORT_UCHAR(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
114 }
115
116 /*
117 * @implemented
118 */
119 VOID
120 EXPORT
121 NdisImmediateReadPortUlong(
122 IN NDIS_HANDLE WrapperConfigurationContext,
123 IN ULONG Port,
124 OUT PULONG Data)
125 {
126 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
127 *Data = READ_PORT_ULONG(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
128 }
129
130 /*
131 * @implemented
132 */
133 VOID
134 EXPORT
135 NdisImmediateReadPortUshort(
136 IN NDIS_HANDLE WrapperConfigurationContext,
137 IN ULONG Port,
138 OUT PUSHORT Data)
139 {
140 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
141 *Data = READ_PORT_USHORT(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
142 }
143
144 /*
145 * @implemented
146 */
147 VOID
148 EXPORT
149 NdisImmediateWritePortUchar(
150 IN NDIS_HANDLE WrapperConfigurationContext,
151 IN ULONG Port,
152 IN UCHAR Data)
153 {
154 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
155 WRITE_PORT_UCHAR(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
156 }
157
158 /*
159 * @implemented
160 */
161 VOID
162 EXPORT
163 NdisImmediateWritePortUlong(
164 IN NDIS_HANDLE WrapperConfigurationContext,
165 IN ULONG Port,
166 IN ULONG Data)
167 {
168 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
169 WRITE_PORT_ULONG(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
170 }
171
172 /*
173 * @implemented
174 */
175 VOID
176 EXPORT
177 NdisImmediateWritePortUshort(
178 IN NDIS_HANDLE WrapperConfigurationContext,
179 IN ULONG Port,
180 IN USHORT Data)
181 {
182 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
183 WRITE_PORT_USHORT(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
184 }
185
186 IO_ALLOCATION_ACTION NTAPI NdisSubordinateMapRegisterCallback (
187 IN PDEVICE_OBJECT DeviceObject,
188 IN PIRP Irp,
189 IN PVOID MapRegisterBase,
190 IN PVOID Context)
191 /*
192 * FUNCTION: Called back during reservation of map registers
193 * ARGUMENTS:
194 * DeviceObject: Device object of the device setting up DMA
195 * Irp: Reserved; must be ignored
196 * MapRegisterBase: Map registers assigned for transfer
197 * Context: LOGICAL_ADAPTER object of the requesting miniport
198 * NOTES:
199 * - Called at IRQL = DISPATCH_LEVEL
200 */
201 {
202 PNDIS_DMA_BLOCK DmaBlock = Context;
203
204 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
205
206 DmaBlock->MapRegisterBase = MapRegisterBase;
207
208 NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n"));
209
210 KeSetEvent(&DmaBlock->AllocationEvent, 0, FALSE);
211
212 /* We have to hold the object open to keep our lock on the system DMA controller */
213 return KeepObject;
214 }
215
216 IO_ALLOCATION_ACTION NTAPI NdisBusMasterMapRegisterCallback (
217 IN PDEVICE_OBJECT DeviceObject,
218 IN PIRP Irp,
219 IN PVOID MapRegisterBase,
220 IN PVOID Context)
221 /*
222 * FUNCTION: Called back during reservation of map registers
223 * ARGUMENTS:
224 * DeviceObject: Device object of the device setting up DMA
225 * Irp: Reserved; must be ignored
226 * MapRegisterBase: Map registers assigned for transfer
227 * Context: LOGICAL_ADAPTER object of the requesting miniport
228 * NOTES:
229 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
230 * - Called at IRQL = DISPATCH_LEVEL
231 */
232 {
233 PLOGICAL_ADAPTER Adapter = Context;
234
235 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
236
237 Adapter->NdisMiniportBlock.MapRegisters[Adapter->NdisMiniportBlock.CurrentMapRegister].MapRegister = MapRegisterBase;
238
239 NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n"));
240
241 KeSetEvent(Adapter->NdisMiniportBlock.AllocationEvent, 0, FALSE);
242
243 /* We're a bus master so we can go ahead and deallocate the object now */
244 return DeallocateObjectKeepRegisters;
245 }
246
247 /*
248 * @implemented
249 */
250 NDIS_STATUS
251 EXPORT
252 NdisMAllocateMapRegisters(
253 IN NDIS_HANDLE MiniportAdapterHandle,
254 IN UINT DmaChannel,
255 IN NDIS_DMA_SIZE DmaSize,
256 IN ULONG BaseMapRegistersNeeded,
257 IN ULONG MaximumBufferSize)
258 /*
259 * FUNCTION: Allocate map registers for use in DMA transfers
260 * ARGUMENTS:
261 * MiniportAdapterHandle: Passed in to MiniportInitialize
262 * DmaChannel: DMA channel to use
263 * DmaSize: bit width of DMA transfers
264 * BaseMapRegistersNeeded: number of base map registers requested
265 * MaximumBufferSize: largest single buffer transferred
266 * RETURNS:
267 * NDIS_STATUS_SUCCESS on success
268 * NDIS_STATUS_RESOURCES on failure
269 * NOTES:
270 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
271 * I'm implementing the 2k one.
272 * - do not confuse a "base map register" with a "map register" - they
273 * are different. Only NDIS seems to use the base concept. The idea
274 * is that a miniport supplies the number of base map registers it will
275 * need, which is equal to the number of DMA send buffers it manages.
276 * NDIS then allocates a number of map registers to go with each base
277 * map register, so that a driver just has to send the base map register
278 * number during dma operations and NDIS can find the group of real
279 * map registers that represent the transfer.
280 * - Because of the above sillyness, you can only specify a few base map
281 * registers at most. a 1514-byte packet is two map registers at 4k
282 * page size.
283 * - NDIS limits the total number of allocated map registers to 64,
284 * which (in the case of the above example) limits the number of base
285 * map registers to 32.
286 */
287 {
288 DEVICE_DESCRIPTION Description;
289 PDMA_ADAPTER AdapterObject = 0;
290 UINT MapRegistersPerBaseRegister = 0;
291 ULONG AvailableMapRegisters;
292 NTSTATUS NtStatus;
293 PLOGICAL_ADAPTER Adapter;
294 PDEVICE_OBJECT DeviceObject = 0;
295 KEVENT AllocationEvent;
296 KIRQL OldIrql;
297
298 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
299 MiniportAdapterHandle, DmaChannel, DmaSize, BaseMapRegistersNeeded, MaximumBufferSize));
300
301 memset(&Description,0,sizeof(Description));
302
303 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
304
305 ASSERT(Adapter);
306
307 /* only bus masters may call this routine */
308 if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) {
309 NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n"));
310 return NDIS_STATUS_NOT_SUPPORTED;
311 }
312
313 DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
314
315 KeInitializeEvent(&AllocationEvent, NotificationEvent, FALSE);
316 Adapter->NdisMiniportBlock.AllocationEvent = &AllocationEvent;
317
318 /*
319 * map registers correlate to physical pages. ndis documents a
320 * maximum of 64 map registers that it will return.
321 * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
322 *
323 * the number of registers required for a given physical mapping
324 * is (first register + last register + one per page size),
325 * given that physical mapping is > 2.
326 */
327
328 /* unhandled corner case: {1,2}-byte max buffer size */
329 ASSERT(MaximumBufferSize > 2);
330 MapRegistersPerBaseRegister = ((MaximumBufferSize-2) / (2*PAGE_SIZE)) + 2;
331
332 Description.Version = DEVICE_DESCRIPTION_VERSION;
333 Description.Master = TRUE; /* implied by calling this function */
334 Description.ScatterGather = TRUE; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
335 Description.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
336 Description.InterfaceType = Adapter->NdisMiniportBlock.BusType;
337 Description.DmaChannel = DmaChannel;
338 Description.MaximumLength = MaximumBufferSize;
339
340 if(DmaSize == NDIS_DMA_64BITS)
341 Description.Dma64BitAddresses = TRUE;
342 else if(DmaSize == NDIS_DMA_32BITS)
343 Description.Dma32BitAddresses = TRUE;
344
345 AdapterObject = IoGetDmaAdapter(
346 Adapter->NdisMiniportBlock.PhysicalDeviceObject, &Description, &AvailableMapRegisters);
347
348 if(!AdapterObject)
349 {
350 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate an adapter object; bailing out\n"));
351 return NDIS_STATUS_RESOURCES;
352 }
353
354 Adapter->NdisMiniportBlock.SystemAdapterObject = AdapterObject;
355
356 if(AvailableMapRegisters < MapRegistersPerBaseRegister)
357 {
358 NDIS_DbgPrint(MIN_TRACE, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
359 MapRegistersPerBaseRegister, AvailableMapRegisters));
360
361 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
362 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
363 return NDIS_STATUS_RESOURCES;
364 }
365
366 /* allocate & zero space in the miniport block for the registers */
367 Adapter->NdisMiniportBlock.MapRegisters = ExAllocatePool(NonPagedPool, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY));
368 if(!Adapter->NdisMiniportBlock.MapRegisters)
369 {
370 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
371 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
372 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
373 return NDIS_STATUS_RESOURCES;
374 }
375
376 memset(Adapter->NdisMiniportBlock.MapRegisters, 0, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY));
377 Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = (USHORT)BaseMapRegistersNeeded;
378
379 while(BaseMapRegistersNeeded)
380 {
381 NDIS_DbgPrint(MAX_TRACE, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded));
382
383 BaseMapRegistersNeeded--;
384 Adapter->NdisMiniportBlock.CurrentMapRegister = (USHORT)BaseMapRegistersNeeded;
385 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
386 {
387 NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(
388 AdapterObject, DeviceObject, MapRegistersPerBaseRegister,
389 NdisBusMasterMapRegisterCallback, Adapter);
390 }
391 KeLowerIrql(OldIrql);
392
393 if(!NT_SUCCESS(NtStatus))
394 {
395 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus));
396 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
397 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
398 Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0;
399 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
400 return NDIS_STATUS_RESOURCES;
401 }
402
403 NDIS_DbgPrint(MAX_TRACE, ("waiting on event\n"));
404
405 NtStatus = KeWaitForSingleObject(&AllocationEvent, Executive, KernelMode, FALSE, 0);
406
407 if(!NT_SUCCESS(NtStatus))
408 {
409 NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus));
410 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
411 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
412 Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0;
413 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
414 return NDIS_STATUS_RESOURCES;
415 }
416
417 NDIS_DbgPrint(MAX_TRACE, ("resetting event\n"));
418
419 KeClearEvent(&AllocationEvent);
420 }
421
422 NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
423 return NDIS_STATUS_SUCCESS;
424 }
425
426
427 /*
428 * @implemented
429 */
430 VOID
431 EXPORT
432 NdisMSetupDmaTransfer(OUT PNDIS_STATUS Status,
433 IN NDIS_HANDLE MiniportDmaHandle,
434 IN PNDIS_BUFFER Buffer,
435 IN ULONG Offset,
436 IN ULONG Length,
437 IN BOOLEAN WriteToDevice)
438 {
439 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
440 NTSTATUS NtStatus;
441 PLOGICAL_ADAPTER Adapter;
442 KIRQL OldIrql;
443 PDMA_ADAPTER AdapterObject;
444 ULONG MapRegistersNeeded;
445
446 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n",
447 MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice));
448
449 Adapter = (PLOGICAL_ADAPTER)DmaBlock->Miniport;
450 AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
451
452 MapRegistersNeeded = (Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
453
454 KeFlushIoBuffers(Buffer, !WriteToDevice, TRUE);
455
456 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
457 {
458 NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(AdapterObject,
459 Adapter->NdisMiniportBlock.PhysicalDeviceObject,
460 MapRegistersNeeded,
461 NdisSubordinateMapRegisterCallback, Adapter);
462 }
463 KeLowerIrql(OldIrql);
464
465 if(!NT_SUCCESS(NtStatus))
466 {
467 NDIS_DbgPrint(MIN_TRACE, ("AllocateAdapterChannel failed: 0x%x\n", NtStatus));
468 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
469 *Status = NDIS_STATUS_RESOURCES;
470 return;
471 }
472
473 NtStatus = KeWaitForSingleObject(&DmaBlock->AllocationEvent, Executive, KernelMode, FALSE, 0);
474
475 if(!NT_SUCCESS(NtStatus))
476 {
477 NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus));
478 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
479 *Status = NDIS_STATUS_RESOURCES;
480 return;
481 }
482
483 /* We must throw away the return value of MapTransfer for a system DMA device */
484 AdapterObject->DmaOperations->MapTransfer(AdapterObject, Buffer,
485 DmaBlock->MapRegisterBase,
486 (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, &Length, WriteToDevice);
487
488 NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
489 *Status = NDIS_STATUS_SUCCESS;
490 }
491
492 /*
493 * @implemented
494 */
495 VOID
496 EXPORT
497 NdisSetupDmaTransfer(OUT PNDIS_STATUS Status,
498 IN PNDIS_HANDLE NdisDmaHandle,
499 IN PNDIS_BUFFER Buffer,
500 IN ULONG Offset,
501 IN ULONG Length,
502 IN BOOLEAN WriteToDevice)
503 /*
504 * FUNCTION:
505 * ARGUMENTS:
506 * NOTES:
507 * NDIS 4.0
508 */
509 {
510 NdisMSetupDmaTransfer(Status,
511 NdisDmaHandle,
512 Buffer,
513 Offset,
514 Length,
515 WriteToDevice);
516 }
517
518 /*
519 * @implemented
520 */
521 VOID
522 EXPORT
523 NdisMCompleteDmaTransfer(OUT PNDIS_STATUS Status,
524 IN NDIS_HANDLE MiniportDmaHandle,
525 IN PNDIS_BUFFER Buffer,
526 IN ULONG Offset,
527 IN ULONG Length,
528 IN BOOLEAN WriteToDevice)
529 {
530 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
531 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
532
533 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n",
534 MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice));
535
536 if (!AdapterObject->DmaOperations->FlushAdapterBuffers(AdapterObject,
537 Buffer,
538 DmaBlock->MapRegisterBase,
539 (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset,
540 Length,
541 WriteToDevice))
542 {
543 NDIS_DbgPrint(MIN_TRACE, ("FlushAdapterBuffers failed\n"));
544 *Status = NDIS_STATUS_FAILURE;
545 return;
546 }
547
548 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
549
550 NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
551 *Status = NDIS_STATUS_SUCCESS;
552 }
553
554 /*
555 * @implemented
556 */
557 VOID
558 EXPORT
559 NdisCompleteDmaTransfer(OUT PNDIS_STATUS Status,
560 IN PNDIS_HANDLE NdisDmaHandle,
561 IN PNDIS_BUFFER Buffer,
562 IN ULONG Offset,
563 IN ULONG Length,
564 IN BOOLEAN WriteToDevice)
565 {
566 NdisMCompleteDmaTransfer(Status,
567 NdisDmaHandle,
568 Buffer,
569 Offset,
570 Length,
571 WriteToDevice);
572 }
573
574 /*
575 * @implemented
576 */
577 VOID
578 EXPORT
579 NdisMStartBufferPhysicalMapping(
580 IN NDIS_HANDLE MiniportAdapterHandle,
581 IN PNDIS_BUFFER Buffer,
582 IN ULONG PhysicalMapRegister,
583 IN BOOLEAN WriteToDevice,
584 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,
585 OUT PUINT ArraySize)
586 /*
587 * FUNCTION: Sets up map registers for a bus-master DMA transfer
588 * ARGUMENTS:
589 * MiniportAdapterHandle: handle originally input to MiniportInitialize
590 * Buffer: data to be transferred
591 * PhysicalMapRegister: specifies the map register to set up
592 * WriteToDevice: if true, data is being written to the device; else it is being read
593 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
594 * ArraySize: number of elements in PhysicalAddressArray
595 * NOTES:
596 * - Must be called at IRQL <= DISPATCH_LEVEL
597 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes
598 * in order to map all of the virtual memory to physical memory readable
599 * by the device
600 * - The caller supplies storage for the physical address array.
601 */
602 {
603 PLOGICAL_ADAPTER Adapter;
604 PVOID CurrentVa;
605 ULONG TotalLength;
606 PHYSICAL_ADDRESS ReturnedAddress;
607 UINT LoopCount = 0;
608
609 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
610 ASSERT(MiniportAdapterHandle && Buffer && PhysicalAddressArray && ArraySize);
611
612 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
613 CurrentVa = MmGetMdlVirtualAddress(Buffer);
614 TotalLength = MmGetMdlByteCount(Buffer);
615
616 while(TotalLength)
617 {
618 ULONG Length = TotalLength;
619
620 ReturnedAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->MapTransfer(
621 Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer,
622 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister,
623 CurrentVa, &Length, WriteToDevice);
624
625 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice = WriteToDevice;
626
627 PhysicalAddressArray[LoopCount].PhysicalAddress = ReturnedAddress;
628 PhysicalAddressArray[LoopCount].Length = Length;
629
630 TotalLength -= Length;
631 CurrentVa = (PVOID)((ULONG_PTR)CurrentVa + Length);
632
633 LoopCount++;
634 }
635
636 *ArraySize = LoopCount;
637 }
638
639 /*
640 * @implemented
641 */
642 VOID
643 EXPORT
644 NdisMCompleteBufferPhysicalMapping(
645 IN NDIS_HANDLE MiniportAdapterHandle,
646 IN PNDIS_BUFFER Buffer,
647 IN ULONG PhysicalMapRegister)
648 /*
649 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
650 * ARGUMENTS:
651 * - MiniportAdapterHandle: handle originally input to MiniportInitialize
652 * - Buffer: NDIS_BUFFER to complete the mapping on
653 * - PhysicalMapRegister: the chosen map register
654 * NOTES:
655 * - May be called at IRQL <= DISPATCH_LEVEL
656 */
657 {
658 PLOGICAL_ADAPTER Adapter;
659 VOID *CurrentVa;
660 ULONG Length;
661
662 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
663 ASSERT(MiniportAdapterHandle && Buffer);
664
665 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
666 CurrentVa = MmGetMdlVirtualAddress(Buffer);
667 Length = MmGetMdlByteCount(Buffer);
668
669 Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->FlushAdapterBuffers(
670 Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer,
671 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister,
672 CurrentVa, Length,
673 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice);
674 }
675
676 /*
677 * @implemented
678 */
679 VOID
680 EXPORT
681 NdisMDeregisterDmaChannel(
682 IN NDIS_HANDLE MiniportDmaHandle)
683 {
684 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
685 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
686
687 if (AdapterObject == ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject)
688 ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject = NULL;
689
690 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
691
692 ExFreePool(DmaBlock);
693 }
694
695 /*
696 * @implemented
697 */
698 VOID
699 EXPORT
700 NdisMDeregisterInterrupt(
701 IN PNDIS_MINIPORT_INTERRUPT Interrupt)
702 /*
703 * FUNCTION: Releases an interrupt vector
704 * ARGUMENTS:
705 * Interrupt = Pointer to interrupt object
706 */
707 {
708 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
709 IoDisconnectInterrupt(Interrupt->InterruptObject);
710 Interrupt->Miniport->RegisteredInterrupts--;
711
712 if (Interrupt->Miniport->Interrupt == Interrupt)
713 Interrupt->Miniport->Interrupt = NULL;
714 }
715
716 /*
717 * @implemented
718 */
719 VOID
720 EXPORT
721 NdisMFreeMapRegisters(
722 IN NDIS_HANDLE MiniportAdapterHandle)
723 /*
724 * FUNCTION: Free previously allocated map registers
725 * ARGUMENTS:
726 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize
727 * NOTES:
728 */
729 {
730 KIRQL OldIrql;
731 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
732 PDMA_ADAPTER AdapterObject;
733 UINT MapRegistersPerBaseRegister;
734 UINT i;
735
736 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
737
738 ASSERT(Adapter);
739
740 /* only bus masters may call this routine */
741 if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER) ||
742 Adapter->NdisMiniportBlock.SystemAdapterObject == NULL) {
743 NDIS_DbgPrint(MIN_TRACE, ("Not bus master or bad adapter object\n"));
744 return;
745 }
746
747 MapRegistersPerBaseRegister = ((Adapter->NdisMiniportBlock.MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
748
749 AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
750
751 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
752 {
753 for(i = 0; i < Adapter->NdisMiniportBlock.BaseMapRegistersNeeded; i++)
754 {
755 AdapterObject->DmaOperations->FreeMapRegisters(
756 Adapter->NdisMiniportBlock.SystemAdapterObject,
757 Adapter->NdisMiniportBlock.MapRegisters[i].MapRegister,
758 MapRegistersPerBaseRegister);
759 }
760 }
761 KeLowerIrql(OldIrql);
762
763 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
764 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
765
766 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
767 }
768
769 /*
770 * @implemented
771 */
772 NDIS_STATUS
773 EXPORT
774 NdisMMapIoSpace(
775 OUT PVOID *VirtualAddress,
776 IN NDIS_HANDLE MiniportAdapterHandle,
777 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
778 IN UINT Length)
779 /*
780 * FUNCTION: Maps a bus-relative address to a system-wide virtual address
781 * ARGUMENTS:
782 * VirtualAddress: receives virtual address of mapping
783 * MiniportAdapterHandle: Handle originally input to MiniportInitialize
784 * PhysicalAddress: bus-relative address to map
785 * Length: Number of bytes to map
786 * RETURNS:
787 * NDIS_STATUS_SUCCESS: the operation completed successfully
788 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
789 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
790 * NDIS_STATUS_FAILURE: a general failure has occured
791 * NOTES:
792 * - Must be called at IRQL = PASSIVE_LEVEL
793 */
794 {
795 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
796 ULONG AddressSpace = 0; /* Memory Space */
797 NDIS_PHYSICAL_ADDRESS TranslatedAddress;
798
799 PAGED_CODE();
800 ASSERT(VirtualAddress && MiniportAdapterHandle);
801
802 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
803
804 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
805 PhysicalAddress, &AddressSpace, &TranslatedAddress))
806 {
807 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
808 return NDIS_STATUS_RESOURCES;
809 }
810
811 *VirtualAddress = MmMapIoSpace(TranslatedAddress, Length, MmNonCached);
812
813 if(!*VirtualAddress) {
814 NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n"));
815 return NDIS_STATUS_RESOURCES;
816 }
817
818 return NDIS_STATUS_SUCCESS;
819 }
820
821 /*
822 * @implemented
823 */
824 ULONG
825 EXPORT
826 NdisMReadDmaCounter(
827 IN NDIS_HANDLE MiniportDmaHandle)
828 {
829 /* NOTE: Unlike NdisMGetDmaAlignment() below, this is a handle to the DMA block */
830 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
831 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
832
833 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
834
835 return AdapterObject->DmaOperations->ReadDmaCounter(AdapterObject);
836 }
837
838 /*
839 * @implemented
840 */
841 ULONG
842 EXPORT
843 NdisMGetDmaAlignment(
844 IN NDIS_HANDLE MiniportAdapterHandle)
845 {
846 /* NOTE: Unlike NdisMReadDmaCounter() above, this is a handle to the NDIS miniport block */
847 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
848 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)Adapter->NdisMiniportBlock.SystemAdapterObject;
849
850 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
851
852 return AdapterObject->DmaOperations->GetDmaAlignment(AdapterObject);
853 }
854
855 /*
856 * @implemented
857 */
858 NDIS_STATUS
859 EXPORT
860 NdisMRegisterDmaChannel(
861 OUT PNDIS_HANDLE MiniportDmaHandle,
862 IN NDIS_HANDLE MiniportAdapterHandle,
863 IN UINT DmaChannel,
864 IN BOOLEAN Dma32BitAddresses,
865 IN PNDIS_DMA_DESCRIPTION DmaDescription,
866 IN ULONG MaximumLength)
867 {
868 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
869 DEVICE_DESCRIPTION DeviceDesc;
870 ULONG MapRegisters;
871 PNDIS_DMA_BLOCK DmaBlock;
872
873 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
874
875 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
876
877 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
878 DeviceDesc.Master = (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER);
879 DeviceDesc.ScatterGather = FALSE;
880 DeviceDesc.DemandMode = DmaDescription->DemandMode;
881 DeviceDesc.AutoInitialize = DmaDescription->AutoInitialize;
882 DeviceDesc.Dma32BitAddresses = Dma32BitAddresses;
883 DeviceDesc.Dma64BitAddresses = FALSE;
884 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
885 DeviceDesc.DmaChannel = DmaDescription->DmaChannel;
886 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
887 DeviceDesc.DmaWidth = DmaDescription->DmaWidth;
888 DeviceDesc.DmaSpeed = DmaDescription->DmaSpeed;
889 DeviceDesc.MaximumLength = MaximumLength;
890
891
892 DmaBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_DMA_BLOCK));
893 if (!DmaBlock) {
894 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
895 return NDIS_STATUS_RESOURCES;
896 }
897
898 DmaBlock->SystemAdapterObject = (PVOID)IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
899
900 if (!DmaBlock->SystemAdapterObject) {
901 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
902 ExFreePool(DmaBlock);
903 return NDIS_STATUS_RESOURCES;
904 }
905
906 Adapter->NdisMiniportBlock.SystemAdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
907
908 KeInitializeEvent(&DmaBlock->AllocationEvent, NotificationEvent, FALSE);
909
910 DmaBlock->Miniport = Adapter;
911
912 *MiniportDmaHandle = DmaBlock;
913
914 return NDIS_STATUS_SUCCESS;
915 }
916
917 /*
918 * @implemented
919 */
920 VOID
921 EXPORT
922 NdisAllocateDmaChannel(OUT PNDIS_STATUS Status,
923 OUT PNDIS_HANDLE NdisDmaHandle,
924 IN NDIS_HANDLE NdisAdapterHandle,
925 IN PNDIS_DMA_DESCRIPTION DmaDescription,
926 IN ULONG MaximumLength)
927 {
928 *Status = NdisMRegisterDmaChannel(NdisDmaHandle,
929 NdisAdapterHandle,
930 0,
931 FALSE,
932 DmaDescription,
933 MaximumLength);
934 }
935
936 /*
937 * @implemented
938 */
939 NDIS_STATUS
940 EXPORT
941 NdisMRegisterInterrupt(
942 OUT PNDIS_MINIPORT_INTERRUPT Interrupt,
943 IN NDIS_HANDLE MiniportAdapterHandle,
944 IN UINT InterruptVector,
945 IN UINT InterruptLevel,
946 IN BOOLEAN RequestIsr,
947 IN BOOLEAN SharedInterrupt,
948 IN NDIS_INTERRUPT_MODE InterruptMode)
949 /*
950 * FUNCTION: Claims access to an interrupt vector
951 * ARGUMENTS:
952 * Interrupt = Address of interrupt object to initialize
953 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
954 * InterruptVector = Specifies bus-relative vector to register
955 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
956 * RequestIsr = TRUE if MiniportISR should always be called
957 * SharedInterrupt = TRUE if other devices may use the same interrupt
958 * InterruptMode = Specifies type of interrupt
959 * RETURNS:
960 * Status of operation
961 */
962 {
963 NTSTATUS Status;
964 ULONG MappedIRQ;
965 KIRQL DIrql;
966 KAFFINITY Affinity;
967 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
968
969 NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
970 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
971 InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode));
972
973 RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT));
974
975 KeInitializeSpinLock(&Interrupt->DpcCountLock);
976
977 KeInitializeDpc(&Interrupt->InterruptDpc, HandleDeferredProcessing, Adapter);
978
979 KeInitializeEvent(&Interrupt->DpcsCompletedEvent, NotificationEvent, FALSE);
980
981 Interrupt->SharedInterrupt = SharedInterrupt;
982 Interrupt->IsrRequested = RequestIsr;
983 Interrupt->Miniport = &Adapter->NdisMiniportBlock;
984
985 MappedIRQ = HalGetInterruptVector(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
986 InterruptLevel, InterruptVector, &DIrql,
987 &Affinity);
988
989 NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ, Affinity));
990
991 Status = IoConnectInterrupt(&Interrupt->InterruptObject, ServiceRoutine, Interrupt, &Interrupt->DpcCountLock, MappedIRQ,
992 DIrql, DIrql, InterruptMode, SharedInterrupt, Affinity, FALSE);
993
994 NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
995
996 if (NT_SUCCESS(Status)) {
997 Adapter->NdisMiniportBlock.Interrupt = Interrupt;
998 Adapter->NdisMiniportBlock.RegisteredInterrupts++;
999 return NDIS_STATUS_SUCCESS;
1000 }
1001
1002 if (Status == STATUS_INSUFFICIENT_RESOURCES)
1003 {
1004 /* FIXME: Log error */
1005 NDIS_DbgPrint(MIN_TRACE, ("Resource conflict!\n"));
1006 return NDIS_STATUS_RESOURCE_CONFLICT;
1007 }
1008
1009 NDIS_DbgPrint(MIN_TRACE, ("Function failed. Status (0x%X).\n", Status));
1010 return NDIS_STATUS_FAILURE;
1011 }
1012
1013 /*
1014 * @implemented
1015 */
1016 NDIS_STATUS
1017 EXPORT
1018 NdisMRegisterIoPortRange(
1019 OUT PVOID *PortOffset,
1020 IN NDIS_HANDLE MiniportAdapterHandle,
1021 IN UINT InitialPort,
1022 IN UINT NumberOfPorts)
1023 /*
1024 * FUNCTION: Sets up driver access to device I/O ports
1025 * ARGUMENTS:
1026 * PortOffset = Address of buffer to place mapped base port address
1027 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
1028 * InitialPort = Bus-relative base port address of a range to be mapped
1029 * NumberOfPorts = Specifies number of ports to be mapped
1030 * RETURNS:
1031 * Status of operation
1032 */
1033 {
1034 PHYSICAL_ADDRESS PortAddress, TranslatedAddress;
1035 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1036 ULONG AddressSpace = 1; /* FIXME The HAL handles this wrong atm */
1037
1038 *PortOffset = 0;
1039
1040 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts));
1041
1042 memset(&PortAddress, 0, sizeof(PortAddress));
1043
1044 /*
1045 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
1046 * we don't have a way to get the I/O base address yet (see
1047 * NDIS_MINIPORT_BLOCK->AllocatedResources and
1048 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
1049 */
1050 if(InitialPort)
1051 PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
1052 else
1053 ASSERT(FALSE);
1054
1055 NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart));
1056
1057 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
1058 PortAddress, &AddressSpace, &TranslatedAddress))
1059 {
1060 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
1061 return NDIS_STATUS_RESOURCES;
1062 }
1063
1064 NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
1065 AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart));
1066
1067 if(AddressSpace)
1068 {
1069 ASSERT(TranslatedAddress.u.HighPart == 0);
1070 *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart;
1071 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset));
1072 return NDIS_STATUS_SUCCESS;
1073 }
1074
1075 NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n"));
1076
1077 *PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached);
1078 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset));
1079
1080 if(!*PortOffset) {
1081 NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n"));
1082 return NDIS_STATUS_RESOURCES;
1083 }
1084
1085 return NDIS_STATUS_SUCCESS;
1086 }
1087
1088 /*
1089 * @implemented
1090 */
1091 VOID
1092 EXPORT
1093 NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle,
1094 IN UINT InitialPort,
1095 IN UINT NumberOfPorts,
1096 IN PVOID PortOffset)
1097 /*
1098 * FUNCTION: Releases a register mapping to I/O ports
1099 * ARGUMENTS:
1100 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
1101 * InitialPort = Bus-relative base port address of a range to be mapped
1102 * NumberOfPorts = Specifies number of ports to be mapped
1103 * PortOffset = Pointer to mapped base port address
1104 */
1105 {
1106 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1107 PHYSICAL_ADDRESS PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
1108 PHYSICAL_ADDRESS TranslatedAddress;
1109 ULONG AddressSpace = 1;
1110
1111 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x, Port Offset 0x%x\n", InitialPort, NumberOfPorts, PortOffset));
1112
1113 /* Translate the initial port again to find the address space of the translated address */
1114 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
1115 PortAddress, &AddressSpace, &TranslatedAddress))
1116 {
1117 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
1118 return;
1119 }
1120
1121 /* Make sure we got the same translation as last time */
1122 ASSERT(TranslatedAddress.QuadPart == (ULONG_PTR)PortOffset);
1123
1124 /* Check if we're in memory space */
1125 if (!AddressSpace)
1126 {
1127 NDIS_DbgPrint(MAX_TRACE, ("Calling MmUnmapIoSpace\n"));
1128
1129 /* Unmap the memory */
1130 MmUnmapIoSpace(PortOffset, NumberOfPorts);
1131 }
1132 }
1133
1134 /*
1135 * @implemented
1136 */
1137 VOID
1138 EXPORT
1139 NdisMUnmapIoSpace(
1140 IN NDIS_HANDLE MiniportAdapterHandle,
1141 IN PVOID VirtualAddress,
1142 IN UINT Length)
1143 /*
1144 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
1145 * ARGUMENTS:
1146 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
1147 * VirtualAddress: Address to un-map
1148 * Length: length of the mapped memory space
1149 * NOTES:
1150 * - Must be called at IRQL = PASSIVE_LEVEL
1151 * - Must only be called from MiniportInitialize and MiniportHalt
1152 * - See also: NdisMMapIoSpace
1153 * BUGS:
1154 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
1155 */
1156 {
1157 PAGED_CODE();
1158
1159 ASSERT(MiniportAdapterHandle);
1160
1161 MmUnmapIoSpace(VirtualAddress, Length);
1162 }
1163
1164 /*
1165 * @implemented
1166 */
1167 NDIS_STATUS
1168 EXPORT
1169 NdisMInitializeScatterGatherDma(
1170 IN NDIS_HANDLE MiniportAdapterHandle,
1171 IN BOOLEAN Dma64BitAddresses,
1172 IN ULONG MaximumPhysicalMapping)
1173 /*
1174 * FUNCTION:
1175 * ARGUMENTS:
1176 * NOTES:
1177 * NDIS 5.0
1178 */
1179 {
1180 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1181 ULONG MapRegisters;
1182 DEVICE_DESCRIPTION DeviceDesc;
1183
1184 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1185
1186 if (!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) {
1187 NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n"));
1188 return NDIS_STATUS_NOT_SUPPORTED;
1189 }
1190
1191 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
1192
1193 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
1194 DeviceDesc.Master = TRUE;
1195 DeviceDesc.ScatterGather = TRUE;
1196 DeviceDesc.Dma32BitAddresses = TRUE; // All callers support 32-bit addresses
1197 DeviceDesc.Dma64BitAddresses = Dma64BitAddresses;
1198 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1199 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
1200 DeviceDesc.MaximumLength = MaximumPhysicalMapping;
1201
1202 Adapter->NdisMiniportBlock.SystemAdapterObject =
1203 IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
1204
1205 if (!Adapter->NdisMiniportBlock.SystemAdapterObject)
1206 return NDIS_STATUS_RESOURCES;
1207
1208 /* FIXME: Right now we just use this as a place holder */
1209 Adapter->NdisMiniportBlock.ScatterGatherListSize = 1;
1210
1211 return NDIS_STATUS_SUCCESS;
1212 }
1213
1214
1215 /*
1216 * @implemented
1217 */
1218 VOID
1219 EXPORT
1220 NdisMapIoSpace(
1221 OUT PNDIS_STATUS Status,
1222 OUT PVOID *VirtualAddress,
1223 IN NDIS_HANDLE NdisAdapterHandle,
1224 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
1225 IN UINT Length)
1226 /*
1227 * FUNCTION:
1228 * ARGUMENTS:
1229 * NOTES:
1230 * NDIS 4.0
1231 */
1232 {
1233 *Status = NdisMMapIoSpace(VirtualAddress,
1234 NdisAdapterHandle,
1235 PhysicalAddress,
1236 Length);
1237 }
1238
1239
1240 /*
1241 * @implemented
1242 */
1243 VOID
1244 EXPORT
1245 NdisFreeDmaChannel(
1246 IN PNDIS_HANDLE NdisDmaHandle)
1247 /*
1248 * FUNCTION:
1249 * ARGUMENTS:
1250 * NOTES:
1251 * NDIS 4.0
1252 */
1253 {
1254 NdisMDeregisterDmaChannel(NdisDmaHandle);
1255 }
1256
1257
1258
1259 /* EOF */