87b9537ee97811308235327cb5da3ac011ba7e3d
[reactos.git] / reactos / 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 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
835 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
836
837 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
838
839 return AdapterObject->DmaOperations->ReadDmaCounter(AdapterObject);
840 }
841
842 \f
843 /*
844 * @implemented
845 */
846 ULONG
847 EXPORT
848 NdisMGetDmaAlignment(
849 IN NDIS_HANDLE MiniportDmaHandle)
850 {
851 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
852 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
853
854 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
855
856 return AdapterObject->DmaOperations->GetDmaAlignment(AdapterObject);
857 }
858
859 \f
860 /*
861 * @implemented
862 */
863 NDIS_STATUS
864 EXPORT
865 NdisMRegisterDmaChannel(
866 OUT PNDIS_HANDLE MiniportDmaHandle,
867 IN NDIS_HANDLE MiniportAdapterHandle,
868 IN UINT DmaChannel,
869 IN BOOLEAN Dma32BitAddresses,
870 IN PNDIS_DMA_DESCRIPTION DmaDescription,
871 IN ULONG MaximumLength)
872 {
873 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
874 DEVICE_DESCRIPTION DeviceDesc;
875 ULONG MapRegisters;
876 PNDIS_DMA_BLOCK DmaBlock;
877
878 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
879
880 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
881
882 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
883 DeviceDesc.Master = (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER);
884 DeviceDesc.ScatterGather = FALSE;
885 DeviceDesc.DemandMode = DmaDescription->DemandMode;
886 DeviceDesc.AutoInitialize = DmaDescription->AutoInitialize;
887 DeviceDesc.Dma32BitAddresses = Dma32BitAddresses;
888 DeviceDesc.Dma64BitAddresses = FALSE;
889 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
890 DeviceDesc.DmaChannel = DmaDescription->DmaChannel;
891 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
892 DeviceDesc.DmaWidth = DmaDescription->DmaWidth;
893 DeviceDesc.DmaSpeed = DmaDescription->DmaSpeed;
894 DeviceDesc.MaximumLength = MaximumLength;
895
896
897 DmaBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_DMA_BLOCK));
898 if (!DmaBlock) {
899 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
900 return NDIS_STATUS_RESOURCES;
901 }
902
903 DmaBlock->SystemAdapterObject = (PVOID)IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
904
905 if (!DmaBlock->SystemAdapterObject) {
906 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
907 ExFreePool(DmaBlock);
908 return NDIS_STATUS_RESOURCES;
909 }
910
911 Adapter->NdisMiniportBlock.SystemAdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
912
913 KeInitializeEvent(&DmaBlock->AllocationEvent, NotificationEvent, FALSE);
914
915 DmaBlock->Miniport = Adapter;
916
917 *MiniportDmaHandle = DmaBlock;
918
919 return NDIS_STATUS_SUCCESS;
920 }
921
922 /*
923 * @implemented
924 */
925 VOID
926 EXPORT
927 NdisAllocateDmaChannel(OUT PNDIS_STATUS Status,
928 OUT PNDIS_HANDLE NdisDmaHandle,
929 IN NDIS_HANDLE NdisAdapterHandle,
930 IN PNDIS_DMA_DESCRIPTION DmaDescription,
931 IN ULONG MaximumLength)
932 {
933 *Status = NdisMRegisterDmaChannel(NdisDmaHandle,
934 NdisAdapterHandle,
935 0,
936 FALSE,
937 DmaDescription,
938 MaximumLength);
939 }\f
940 /*
941 * @implemented
942 */
943 NDIS_STATUS
944 EXPORT
945 NdisMRegisterInterrupt(
946 OUT PNDIS_MINIPORT_INTERRUPT Interrupt,
947 IN NDIS_HANDLE MiniportAdapterHandle,
948 IN UINT InterruptVector,
949 IN UINT InterruptLevel,
950 IN BOOLEAN RequestIsr,
951 IN BOOLEAN SharedInterrupt,
952 IN NDIS_INTERRUPT_MODE InterruptMode)
953 /*
954 * FUNCTION: Claims access to an interrupt vector
955 * ARGUMENTS:
956 * Interrupt = Address of interrupt object to initialize
957 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
958 * InterruptVector = Specifies bus-relative vector to register
959 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt
960 * RequestIsr = TRUE if MiniportISR should always be called
961 * SharedInterrupt = TRUE if other devices may use the same interrupt
962 * InterruptMode = Specifies type of interrupt
963 * RETURNS:
964 * Status of operation
965 */
966 {
967 NTSTATUS Status;
968 ULONG MappedIRQ;
969 KIRQL DIrql;
970 KAFFINITY Affinity;
971 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
972
973 NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) "
974 "SharedInterrupt (%d) InterruptMode (0x%X)\n",
975 InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode));
976
977 RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT));
978
979 KeInitializeSpinLock(&Interrupt->DpcCountLock);
980
981 KeInitializeDpc(&Interrupt->InterruptDpc, HandleDeferredProcessing, Adapter);
982
983 KeInitializeEvent(&Interrupt->DpcsCompletedEvent, NotificationEvent, FALSE);
984
985 Interrupt->SharedInterrupt = SharedInterrupt;
986 Interrupt->IsrRequested = RequestIsr;
987 Interrupt->Miniport = &Adapter->NdisMiniportBlock;
988
989 MappedIRQ = HalGetInterruptVector(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
990 InterruptLevel, InterruptVector, &DIrql,
991 &Affinity);
992
993 NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ, Affinity));
994
995 Status = IoConnectInterrupt(&Interrupt->InterruptObject, ServiceRoutine, Interrupt, &Interrupt->DpcCountLock, MappedIRQ,
996 DIrql, DIrql, InterruptMode, SharedInterrupt, Affinity, FALSE);
997
998 NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
999
1000 if (NT_SUCCESS(Status)) {
1001 Adapter->NdisMiniportBlock.Interrupt = Interrupt;
1002 Adapter->NdisMiniportBlock.RegisteredInterrupts++;
1003 return NDIS_STATUS_SUCCESS;
1004 }
1005
1006 if (Status == STATUS_INSUFFICIENT_RESOURCES)
1007 {
1008 /* FIXME: Log error */
1009 NDIS_DbgPrint(MIN_TRACE, ("Resource conflict!\n"));
1010 return NDIS_STATUS_RESOURCE_CONFLICT;
1011 }
1012
1013 NDIS_DbgPrint(MIN_TRACE, ("Function failed. Status (0x%X).\n", Status));
1014 return NDIS_STATUS_FAILURE;
1015 }
1016
1017 \f
1018 /*
1019 * @implemented
1020 */
1021 NDIS_STATUS
1022 EXPORT
1023 NdisMRegisterIoPortRange(
1024 OUT PVOID *PortOffset,
1025 IN NDIS_HANDLE MiniportAdapterHandle,
1026 IN UINT InitialPort,
1027 IN UINT NumberOfPorts)
1028 /*
1029 * FUNCTION: Sets up driver access to device I/O ports
1030 * ARGUMENTS:
1031 * PortOffset = Address of buffer to place mapped base port address
1032 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
1033 * InitialPort = Bus-relative base port address of a range to be mapped
1034 * NumberOfPorts = Specifies number of ports to be mapped
1035 * RETURNS:
1036 * Status of operation
1037 */
1038 {
1039 PHYSICAL_ADDRESS PortAddress, TranslatedAddress;
1040 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1041 ULONG AddressSpace = 1; /* FIXME The HAL handles this wrong atm */
1042
1043 *PortOffset = 0;
1044
1045 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts));
1046
1047 memset(&PortAddress, 0, sizeof(PortAddress));
1048
1049 /*
1050 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
1051 * we don't have a way to get the I/O base address yet (see
1052 * NDIS_MINIPORT_BLOCK->AllocatedResources and
1053 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
1054 */
1055 if(InitialPort)
1056 PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
1057 else
1058 ASSERT(FALSE);
1059
1060 NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart));
1061
1062 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
1063 PortAddress, &AddressSpace, &TranslatedAddress))
1064 {
1065 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
1066 return NDIS_STATUS_RESOURCES;
1067 }
1068
1069 NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
1070 AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart));
1071
1072 if(AddressSpace)
1073 {
1074 ASSERT(TranslatedAddress.u.HighPart == 0);
1075 *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart;
1076 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset));
1077 return NDIS_STATUS_SUCCESS;
1078 }
1079
1080 NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n"));
1081
1082 *PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached);
1083 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset));
1084
1085 if(!*PortOffset) {
1086 NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n"));
1087 return NDIS_STATUS_RESOURCES;
1088 }
1089
1090 return NDIS_STATUS_SUCCESS;
1091 }
1092
1093 /*
1094 * @implemented
1095 */
1096 VOID
1097 EXPORT
1098 NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle,
1099 IN UINT InitialPort,
1100 IN UINT NumberOfPorts,
1101 IN PVOID PortOffset)
1102 /*
1103 * FUNCTION: Releases a register mapping to I/O ports
1104 * ARGUMENTS:
1105 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize
1106 * InitialPort = Bus-relative base port address of a range to be mapped
1107 * NumberOfPorts = Specifies number of ports to be mapped
1108 * PortOffset = Pointer to mapped base port address
1109 */
1110 {
1111 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1112 PHYSICAL_ADDRESS PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
1113 PHYSICAL_ADDRESS TranslatedAddress;
1114 ULONG AddressSpace = 1;
1115
1116 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x, Port Offset 0x%x\n", InitialPort, NumberOfPorts, PortOffset));
1117
1118 /* Translate the initial port again to find the address space of the translated address */
1119 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
1120 PortAddress, &AddressSpace, &TranslatedAddress))
1121 {
1122 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
1123 return;
1124 }
1125
1126 /* Make sure we got the same translation as last time */
1127 ASSERT(TranslatedAddress.QuadPart == (ULONG_PTR)PortOffset);
1128
1129 /* Check if we're in memory space */
1130 if (!AddressSpace)
1131 {
1132 NDIS_DbgPrint(MAX_TRACE, ("Calling MmUnmapIoSpace\n"));
1133
1134 /* Unmap the memory */
1135 MmUnmapIoSpace(PortOffset, NumberOfPorts);
1136 }
1137 }
1138
1139 /*
1140 * @implemented
1141 */
1142 VOID
1143 EXPORT
1144 NdisMUnmapIoSpace(
1145 IN NDIS_HANDLE MiniportAdapterHandle,
1146 IN PVOID VirtualAddress,
1147 IN UINT Length)
1148 /*
1149 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
1150 * ARGUMENTS:
1151 * MiniportAdapterHandle: handle originally passed into MiniportInitialize
1152 * VirtualAddress: Address to un-map
1153 * Length: length of the mapped memory space
1154 * NOTES:
1155 * - Must be called at IRQL = PASSIVE_LEVEL
1156 * - Must only be called from MiniportInitialize and MiniportHalt
1157 * - See also: NdisMMapIoSpace
1158 * BUGS:
1159 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
1160 */
1161 {
1162 PAGED_CODE();
1163
1164 ASSERT(MiniportAdapterHandle);
1165
1166 MmUnmapIoSpace(VirtualAddress, Length);
1167 }
1168
1169 /*
1170 * @implemented
1171 */
1172 NDIS_STATUS
1173 EXPORT
1174 NdisMInitializeScatterGatherDma(
1175 IN NDIS_HANDLE MiniportAdapterHandle,
1176 IN BOOLEAN Dma64BitAddresses,
1177 IN ULONG MaximumPhysicalMapping)
1178 /*
1179 * FUNCTION:
1180 * ARGUMENTS:
1181 * NOTES:
1182 * NDIS 5.0
1183 */
1184 {
1185 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
1186 ULONG MapRegisters;
1187 DEVICE_DESCRIPTION DeviceDesc;
1188
1189 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1190
1191 if (!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) {
1192 NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n"));
1193 return NDIS_STATUS_NOT_SUPPORTED;
1194 }
1195
1196 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
1197
1198 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
1199 DeviceDesc.Master = TRUE;
1200 DeviceDesc.ScatterGather = TRUE;
1201 DeviceDesc.Dma32BitAddresses = !Dma64BitAddresses;
1202 DeviceDesc.Dma64BitAddresses = Dma64BitAddresses;
1203 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1204 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
1205 DeviceDesc.MaximumLength = MaximumPhysicalMapping;
1206
1207 Adapter->NdisMiniportBlock.SystemAdapterObject =
1208 IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
1209
1210 if (!Adapter->NdisMiniportBlock.SystemAdapterObject)
1211 return NDIS_STATUS_RESOURCES;
1212
1213 /* FIXME: Right now we just use this as a place holder */
1214 Adapter->NdisMiniportBlock.ScatterGatherListSize = 1;
1215
1216 return NDIS_STATUS_SUCCESS;
1217 }
1218
1219
1220 /*
1221 * @implemented
1222 */
1223 VOID
1224 EXPORT
1225 NdisMapIoSpace(
1226 OUT PNDIS_STATUS Status,
1227 OUT PVOID *VirtualAddress,
1228 IN NDIS_HANDLE NdisAdapterHandle,
1229 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
1230 IN UINT Length)
1231 /*
1232 * FUNCTION:
1233 * ARGUMENTS:
1234 * NOTES:
1235 * NDIS 4.0
1236 */
1237 {
1238 *Status = NdisMMapIoSpace(VirtualAddress,
1239 NdisAdapterHandle,
1240 PhysicalAddress,
1241 Length);
1242 }
1243
1244
1245 /*
1246 * @implemented
1247 */
1248 VOID
1249 EXPORT
1250 NdisFreeDmaChannel(
1251 IN PNDIS_HANDLE NdisDmaHandle)
1252 /*
1253 * FUNCTION:
1254 * ARGUMENTS:
1255 * NOTES:
1256 * NDIS 4.0
1257 */
1258 {
1259 NdisMDeregisterDmaChannel(NdisDmaHandle);
1260 }
1261
1262
1263
1264 /* EOF */
1265