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