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
HandleDeferredProcessing(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)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
ServiceRoutine(IN PKINTERRUPT Interrupt,IN PVOID ServiceContext)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
NdisImmediateReadPortUchar(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,OUT PUCHAR Data)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
NdisImmediateReadPortUlong(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,OUT PULONG Data)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
NdisImmediateReadPortUshort(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,OUT PUSHORT Data)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
NdisImmediateWritePortUchar(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,IN UCHAR Data)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
NdisImmediateWritePortUlong(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,IN ULONG Data)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
NdisImmediateWritePortUshort(IN NDIS_HANDLE WrapperConfigurationContext,IN ULONG Port,IN USHORT Data)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
NdisSubordinateMapRegisterCallback(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID MapRegisterBase,IN PVOID Context)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
NdisBusMasterMapRegisterCallback(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID MapRegisterBase,IN PVOID Context)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
NdisMAllocateMapRegisters(IN NDIS_HANDLE MiniportAdapterHandle,IN UINT DmaChannel,IN NDIS_DMA_SIZE DmaSize,IN ULONG BaseMapRegistersNeeded,IN ULONG MaximumBufferSize)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
NdisMSetupDmaTransfer(OUT PNDIS_STATUS Status,IN NDIS_HANDLE MiniportDmaHandle,IN PNDIS_BUFFER Buffer,IN ULONG Offset,IN ULONG Length,IN BOOLEAN WriteToDevice)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
NdisSetupDmaTransfer(OUT PNDIS_STATUS Status,IN PNDIS_HANDLE NdisDmaHandle,IN PNDIS_BUFFER Buffer,IN ULONG Offset,IN ULONG Length,IN BOOLEAN WriteToDevice)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
NdisMCompleteDmaTransfer(OUT PNDIS_STATUS Status,IN NDIS_HANDLE MiniportDmaHandle,IN PNDIS_BUFFER Buffer,IN ULONG Offset,IN ULONG Length,IN BOOLEAN WriteToDevice)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
NdisCompleteDmaTransfer(OUT PNDIS_STATUS Status,IN PNDIS_HANDLE NdisDmaHandle,IN PNDIS_BUFFER Buffer,IN ULONG Offset,IN ULONG Length,IN BOOLEAN WriteToDevice)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
NdisMStartBufferPhysicalMapping(IN NDIS_HANDLE MiniportAdapterHandle,IN PNDIS_BUFFER Buffer,IN ULONG PhysicalMapRegister,IN BOOLEAN WriteToDevice,OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,OUT PUINT ArraySize)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
NdisMCompleteBufferPhysicalMapping(IN NDIS_HANDLE MiniportAdapterHandle,IN PNDIS_BUFFER Buffer,IN ULONG PhysicalMapRegister)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
NdisMDeregisterDmaChannel(IN NDIS_HANDLE MiniportDmaHandle)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
NdisMDeregisterInterrupt(IN PNDIS_MINIPORT_INTERRUPT Interrupt)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
NdisMFreeMapRegisters(IN NDIS_HANDLE MiniportAdapterHandle)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
NdisMMapIoSpace(OUT PVOID * VirtualAddress,IN NDIS_HANDLE MiniportAdapterHandle,IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,IN UINT Length)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
NdisMReadDmaCounter(IN NDIS_HANDLE MiniportDmaHandle)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
NdisMGetDmaAlignment(IN NDIS_HANDLE MiniportAdapterHandle)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
NdisMRegisterDmaChannel(OUT PNDIS_HANDLE MiniportDmaHandle,IN NDIS_HANDLE MiniportAdapterHandle,IN UINT DmaChannel,IN BOOLEAN Dma32BitAddresses,IN PNDIS_DMA_DESCRIPTION DmaDescription,IN ULONG MaximumLength)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
NdisAllocateDmaChannel(OUT PNDIS_STATUS Status,OUT PNDIS_HANDLE NdisDmaHandle,IN NDIS_HANDLE NdisAdapterHandle,IN PNDIS_DMA_DESCRIPTION DmaDescription,IN ULONG MaximumLength)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
NdisMRegisterInterrupt(OUT PNDIS_MINIPORT_INTERRUPT Interrupt,IN NDIS_HANDLE MiniportAdapterHandle,IN UINT InterruptVector,IN UINT InterruptLevel,IN BOOLEAN RequestIsr,IN BOOLEAN SharedInterrupt,IN NDIS_INTERRUPT_MODE InterruptMode)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
NdisMRegisterIoPortRange(OUT PVOID * PortOffset,IN NDIS_HANDLE MiniportAdapterHandle,IN UINT InitialPort,IN UINT NumberOfPorts)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
NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle,IN UINT InitialPort,IN UINT NumberOfPorts,IN PVOID PortOffset)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
NdisMUnmapIoSpace(IN NDIS_HANDLE MiniportAdapterHandle,IN PVOID VirtualAddress,IN UINT Length)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
NdisMInitializeScatterGatherDma(IN NDIS_HANDLE MiniportAdapterHandle,IN BOOLEAN Dma64BitAddresses,IN ULONG MaximumPhysicalMapping)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
NdisMapIoSpace(OUT PNDIS_STATUS Status,OUT PVOID * VirtualAddress,IN NDIS_HANDLE NdisAdapterHandle,IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,IN UINT Length)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
NdisFreeDmaChannel(IN PNDIS_HANDLE NdisDmaHandle)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 */
1260