Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenio.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS NDIS library 00004 * FILE: ndis/io.c 00005 * PURPOSE: I/O related routines 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Vizzini (vizzini@plasmic.com) 00008 * REVISIONS: 00009 * CSH 01/08-2000 Created 00010 * 20 Aug 2003 Vizzini - DMA support 00011 * 3 Oct 2003 Vizzini - Formatting and minor bugfixes 00012 */ 00013 00014 #include "ndissys.h" 00015 00016 00017 VOID NTAPI HandleDeferredProcessing( 00018 IN PKDPC Dpc, 00019 IN PVOID DeferredContext, 00020 IN PVOID SystemArgument1, 00021 IN PVOID SystemArgument2) 00022 /* 00023 * FUNCTION: Deferred interrupt processing routine 00024 * ARGUMENTS: 00025 * Dpc = Pointer to DPC object 00026 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER) 00027 * SystemArgument1 = Unused 00028 * SystemArgument2 = Unused 00029 */ 00030 { 00031 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext); 00032 00033 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00034 00035 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00036 00037 /* Call the deferred interrupt service handler for this adapter */ 00038 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HandleInterruptHandler)( 00039 Adapter->NdisMiniportBlock.MiniportAdapterContext); 00040 00041 /* re-enable the interrupt */ 00042 NDIS_DbgPrint(MAX_TRACE, ("re-enabling the interrupt\n")); 00043 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler) 00044 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler)( 00045 Adapter->NdisMiniportBlock.MiniportAdapterContext); 00046 00047 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); 00048 } 00049 00050 00051 BOOLEAN NTAPI ServiceRoutine( 00052 IN PKINTERRUPT Interrupt, 00053 IN PVOID ServiceContext) 00054 /* 00055 * FUNCTION: Interrupt service routine 00056 * ARGUMENTS: 00057 * Interrupt = Pointer to interrupt object 00058 * ServiceContext = Pointer to context information (PNDIS_MINIPORT_INTERRUPT) 00059 * RETURNS 00060 * TRUE if a miniport controlled device generated the interrupt 00061 */ 00062 { 00063 BOOLEAN InterruptRecognized = FALSE; 00064 BOOLEAN QueueMiniportHandleInterrupt = FALSE; 00065 PNDIS_MINIPORT_INTERRUPT NdisInterrupt = ServiceContext; 00066 PNDIS_MINIPORT_BLOCK NdisMiniportBlock = NdisInterrupt->Miniport; 00067 00068 NDIS_DbgPrint(MAX_TRACE, ("Called. Interrupt (0x%X)\n", NdisInterrupt)); 00069 00070 if (NdisInterrupt->IsrRequested) { 00071 NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportISR\n")); 00072 (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.ISRHandler)( 00073 &InterruptRecognized, 00074 &QueueMiniportHandleInterrupt, 00075 NdisMiniportBlock->MiniportAdapterContext); 00076 00077 } else if (NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler) { 00078 NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportDisableInterrupt\n")); 00079 (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler)( 00080 NdisMiniportBlock->MiniportAdapterContext); 00081 QueueMiniportHandleInterrupt = TRUE; 00082 InterruptRecognized = TRUE; 00083 } 00084 00085 00086 if (QueueMiniportHandleInterrupt) 00087 { 00088 NDIS_DbgPrint(MAX_TRACE, ("Queuing DPC.\n")); 00089 KeInsertQueueDpc(&NdisInterrupt->InterruptDpc, NULL, NULL); 00090 } 00091 00092 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); 00093 00094 return InterruptRecognized; 00095 } 00096 00097 00098 /* 00099 * @implemented 00100 */ 00101 VOID 00102 EXPORT 00103 NdisImmediateReadPortUchar( 00104 IN NDIS_HANDLE WrapperConfigurationContext, 00105 IN ULONG Port, 00106 OUT PUCHAR Data) 00107 { 00108 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00109 *Data = READ_PORT_UCHAR(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? 00110 } 00111 00112 00113 /* 00114 * @implemented 00115 */ 00116 VOID 00117 EXPORT 00118 NdisImmediateReadPortUlong( 00119 IN NDIS_HANDLE WrapperConfigurationContext, 00120 IN ULONG Port, 00121 OUT PULONG Data) 00122 { 00123 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00124 *Data = READ_PORT_ULONG(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? 00125 } 00126 00127 00128 /* 00129 * @implemented 00130 */ 00131 VOID 00132 EXPORT 00133 NdisImmediateReadPortUshort( 00134 IN NDIS_HANDLE WrapperConfigurationContext, 00135 IN ULONG Port, 00136 OUT PUSHORT Data) 00137 { 00138 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00139 *Data = READ_PORT_USHORT(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? 00140 } 00141 00142 00143 /* 00144 * @implemented 00145 */ 00146 VOID 00147 EXPORT 00148 NdisImmediateWritePortUchar( 00149 IN NDIS_HANDLE WrapperConfigurationContext, 00150 IN ULONG Port, 00151 IN UCHAR Data) 00152 { 00153 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00154 WRITE_PORT_UCHAR(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? 00155 } 00156 00157 00158 /* 00159 * @implemented 00160 */ 00161 VOID 00162 EXPORT 00163 NdisImmediateWritePortUlong( 00164 IN NDIS_HANDLE WrapperConfigurationContext, 00165 IN ULONG Port, 00166 IN ULONG Data) 00167 { 00168 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00169 WRITE_PORT_ULONG(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? 00170 } 00171 00172 00173 /* 00174 * @implemented 00175 */ 00176 VOID 00177 EXPORT 00178 NdisImmediateWritePortUshort( 00179 IN NDIS_HANDLE WrapperConfigurationContext, 00180 IN ULONG Port, 00181 IN USHORT Data) 00182 { 00183 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00184 WRITE_PORT_USHORT(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? 00185 } 00186 00187 IO_ALLOCATION_ACTION NTAPI NdisSubordinateMapRegisterCallback ( 00188 IN PDEVICE_OBJECT DeviceObject, 00189 IN PIRP Irp, 00190 IN PVOID MapRegisterBase, 00191 IN PVOID Context) 00192 /* 00193 * FUNCTION: Called back during reservation of map registers 00194 * ARGUMENTS: 00195 * DeviceObject: Device object of the deivce setting up DMA 00196 * Irp: Reserved; must be ignored 00197 * MapRegisterBase: Map registers assigned for transfer 00198 * Context: LOGICAL_ADAPTER object of the requesting miniport 00199 * NOTES: 00200 * - Called at IRQL = DISPATCH_LEVEL 00201 */ 00202 { 00203 PNDIS_DMA_BLOCK DmaBlock = Context; 00204 00205 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00206 00207 DmaBlock->MapRegisterBase = MapRegisterBase; 00208 00209 NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n")); 00210 00211 KeSetEvent(&DmaBlock->AllocationEvent, 0, FALSE); 00212 00213 /* We have to hold the object open to keep our lock on the system DMA controller */ 00214 return KeepObject; 00215 } 00216 IO_ALLOCATION_ACTION NTAPI NdisBusMasterMapRegisterCallback ( 00217 IN PDEVICE_OBJECT DeviceObject, 00218 IN PIRP Irp, 00219 IN PVOID MapRegisterBase, 00220 IN PVOID Context) 00221 /* 00222 * FUNCTION: Called back during reservation of map registers 00223 * ARGUMENTS: 00224 * DeviceObject: Device object of the deivce setting up DMA 00225 * Irp: Reserved; must be ignored 00226 * MapRegisterBase: Map registers assigned for transfer 00227 * Context: LOGICAL_ADAPTER object of the requesting miniport 00228 * NOTES: 00229 * - Called once per BaseMapRegister (see NdisMAllocateMapRegisters) 00230 * - Called at IRQL = DISPATCH_LEVEL 00231 */ 00232 { 00233 PLOGICAL_ADAPTER Adapter = Context; 00234 00235 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00236 00237 Adapter->NdisMiniportBlock.MapRegisters[Adapter->NdisMiniportBlock.CurrentMapRegister].MapRegister = MapRegisterBase; 00238 00239 NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n")); 00240 00241 KeSetEvent(Adapter->NdisMiniportBlock.AllocationEvent, 0, FALSE); 00242 00243 /* We're a bus master so we can go ahead and deallocate the object now */ 00244 return DeallocateObjectKeepRegisters; 00245 } 00246 /* 00247 * @implemented 00248 */ 00249 NDIS_STATUS 00250 EXPORT 00251 NdisMAllocateMapRegisters( 00252 IN NDIS_HANDLE MiniportAdapterHandle, 00253 IN UINT DmaChannel, 00254 IN NDIS_DMA_SIZE DmaSize, 00255 IN ULONG BaseMapRegistersNeeded, 00256 IN ULONG MaximumBufferSize) 00257 /* 00258 * FUNCTION: Allocate map registers for use in DMA transfers 00259 * ARGUMENTS: 00260 * MiniportAdapterHandle: Passed in to MiniportInitialize 00261 * DmaChannel: DMA channel to use 00262 * DmaSize: bit width of DMA transfers 00263 * BaseMapRegistersNeeded: number of base map registers requested 00264 * MaximumBufferSize: largest single buffer transferred 00265 * RETURNS: 00266 * NDIS_STATUS_SUCCESS on success 00267 * NDIS_STATUS_RESOURCES on failure 00268 * NOTES: 00269 * - the win2k ddk and the nt4 ddk have conflicting prototypes for this. 00270 * I'm implementing the 2k one. 00271 * - do not confuse a "base map register" with a "map register" - they 00272 * are different. Only NDIS seems to use the base concept. The idea 00273 * is that a miniport supplies the number of base map registers it will 00274 * need, which is equal to the number of DMA send buffers it manages. 00275 * NDIS then allocates a number of map registers to go with each base 00276 * map register, so that a driver just has to send the base map register 00277 * number during dma operations and NDIS can find the group of real 00278 * map registers that represent the transfer. 00279 * - Because of the above sillyness, you can only specify a few base map 00280 * registers at most. a 1514-byte packet is two map registers at 4k 00281 * page size. 00282 * - NDIS limits the total number of allocated map registers to 64, 00283 * which (in the case of the above example) limits the number of base 00284 * map registers to 32. 00285 */ 00286 { 00287 DEVICE_DESCRIPTION Description; 00288 PDMA_ADAPTER AdapterObject = 0; 00289 UINT MapRegistersPerBaseRegister = 0; 00290 ULONG AvailableMapRegisters; 00291 NTSTATUS NtStatus; 00292 PLOGICAL_ADAPTER Adapter; 00293 PDEVICE_OBJECT DeviceObject = 0; 00294 KEVENT AllocationEvent; 00295 KIRQL OldIrql; 00296 00297 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n", 00298 MiniportAdapterHandle, DmaChannel, DmaSize, BaseMapRegistersNeeded, MaximumBufferSize)); 00299 00300 memset(&Description,0,sizeof(Description)); 00301 00302 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00303 00304 ASSERT(Adapter); 00305 00306 /* only bus masters may call this routine */ 00307 if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) { 00308 NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n")); 00309 return NDIS_STATUS_NOT_SUPPORTED; 00310 } 00311 00312 DeviceObject = Adapter->NdisMiniportBlock.DeviceObject; 00313 00314 KeInitializeEvent(&AllocationEvent, NotificationEvent, FALSE); 00315 Adapter->NdisMiniportBlock.AllocationEvent = &AllocationEvent; 00316 00317 /* 00318 * map registers correlate to physical pages. ndis documents a 00319 * maximum of 64 map registers that it will return. 00320 * at 4k pages, a 1514-byte buffer can span not more than 2 pages. 00321 * 00322 * the number of registers required for a given physical mapping 00323 * is (first register + last register + one per page size), 00324 * given that physical mapping is > 2. 00325 */ 00326 00327 /* unhandled corner case: {1,2}-byte max buffer size */ 00328 ASSERT(MaximumBufferSize > 2); 00329 MapRegistersPerBaseRegister = ((MaximumBufferSize-2) / (2*PAGE_SIZE)) + 2; 00330 00331 Description.Version = DEVICE_DESCRIPTION_VERSION; 00332 Description.Master = TRUE; /* implied by calling this function */ 00333 Description.ScatterGather = TRUE; /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */ 00334 Description.BusNumber = Adapter->NdisMiniportBlock.BusNumber; 00335 Description.InterfaceType = Adapter->NdisMiniportBlock.BusType; 00336 Description.DmaChannel = DmaChannel; 00337 Description.MaximumLength = MaximumBufferSize; 00338 00339 if(DmaSize == NDIS_DMA_64BITS) 00340 Description.Dma64BitAddresses = TRUE; 00341 else if(DmaSize == NDIS_DMA_32BITS) 00342 Description.Dma32BitAddresses = TRUE; 00343 00344 AdapterObject = IoGetDmaAdapter( 00345 Adapter->NdisMiniportBlock.PhysicalDeviceObject, &Description, &AvailableMapRegisters); 00346 00347 if(!AdapterObject) 00348 { 00349 NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate an adapter object; bailing out\n")); 00350 return NDIS_STATUS_RESOURCES; 00351 } 00352 00353 Adapter->NdisMiniportBlock.SystemAdapterObject = AdapterObject; 00354 00355 if(AvailableMapRegisters < MapRegistersPerBaseRegister) 00356 { 00357 NDIS_DbgPrint(MIN_TRACE, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n", 00358 MapRegistersPerBaseRegister, AvailableMapRegisters)); 00359 00360 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00361 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL; 00362 return NDIS_STATUS_RESOURCES; 00363 } 00364 00365 /* allocate & zero space in the miniport block for the registers */ 00366 Adapter->NdisMiniportBlock.MapRegisters = ExAllocatePool(NonPagedPool, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY)); 00367 if(!Adapter->NdisMiniportBlock.MapRegisters) 00368 { 00369 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n")); 00370 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00371 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL; 00372 return NDIS_STATUS_RESOURCES; 00373 } 00374 00375 memset(Adapter->NdisMiniportBlock.MapRegisters, 0, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY)); 00376 Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = (USHORT)BaseMapRegistersNeeded; 00377 00378 while(BaseMapRegistersNeeded) 00379 { 00380 NDIS_DbgPrint(MAX_TRACE, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded)); 00381 00382 BaseMapRegistersNeeded--; 00383 Adapter->NdisMiniportBlock.CurrentMapRegister = (USHORT)BaseMapRegistersNeeded; 00384 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00385 { 00386 NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel( 00387 AdapterObject, DeviceObject, MapRegistersPerBaseRegister, 00388 NdisBusMasterMapRegisterCallback, Adapter); 00389 } 00390 KeLowerIrql(OldIrql); 00391 00392 if(!NT_SUCCESS(NtStatus)) 00393 { 00394 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus)); 00395 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters); 00396 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00397 Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0; 00398 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL; 00399 return NDIS_STATUS_RESOURCES; 00400 } 00401 00402 NDIS_DbgPrint(MAX_TRACE, ("waiting on event\n")); 00403 00404 NtStatus = KeWaitForSingleObject(&AllocationEvent, Executive, KernelMode, FALSE, 0); 00405 00406 if(!NT_SUCCESS(NtStatus)) 00407 { 00408 NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus)); 00409 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters); 00410 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00411 Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0; 00412 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL; 00413 return NDIS_STATUS_RESOURCES; 00414 } 00415 00416 NDIS_DbgPrint(MAX_TRACE, ("resetting event\n")); 00417 00418 KeResetEvent(&AllocationEvent); 00419 } 00420 00421 NDIS_DbgPrint(MAX_TRACE, ("returning success\n")); 00422 return NDIS_STATUS_SUCCESS; 00423 } 00424 00425 00426 /* 00427 * @implemented 00428 */ 00429 VOID 00430 EXPORT 00431 NdisMSetupDmaTransfer(OUT PNDIS_STATUS Status, 00432 IN NDIS_HANDLE MiniportDmaHandle, 00433 IN PNDIS_BUFFER Buffer, 00434 IN ULONG Offset, 00435 IN ULONG Length, 00436 IN BOOLEAN WriteToDevice) 00437 { 00438 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; 00439 NTSTATUS NtStatus; 00440 PLOGICAL_ADAPTER Adapter; 00441 KIRQL OldIrql; 00442 PDMA_ADAPTER AdapterObject; 00443 ULONG MapRegistersNeeded; 00444 00445 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n", 00446 MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice)); 00447 00448 Adapter = (PLOGICAL_ADAPTER)DmaBlock->Miniport; 00449 AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; 00450 00451 MapRegistersNeeded = (Length + (PAGE_SIZE - 1)) / PAGE_SIZE; 00452 00453 KeFlushIoBuffers(Buffer, !WriteToDevice, TRUE); 00454 00455 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00456 { 00457 NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(AdapterObject, 00458 Adapter->NdisMiniportBlock.PhysicalDeviceObject, 00459 MapRegistersNeeded, 00460 NdisSubordinateMapRegisterCallback, Adapter); 00461 } 00462 KeLowerIrql(OldIrql); 00463 00464 if(!NT_SUCCESS(NtStatus)) 00465 { 00466 NDIS_DbgPrint(MIN_TRACE, ("AllocateAdapterChannel failed: 0x%x\n", NtStatus)); 00467 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); 00468 *Status = NDIS_STATUS_RESOURCES; 00469 return; 00470 } 00471 00472 NtStatus = KeWaitForSingleObject(&DmaBlock->AllocationEvent, Executive, KernelMode, FALSE, 0); 00473 00474 if(!NT_SUCCESS(NtStatus)) 00475 { 00476 NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus)); 00477 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); 00478 *Status = NDIS_STATUS_RESOURCES; 00479 return; 00480 } 00481 00482 /* We must throw away the return value of MapTransfer for a system DMA device */ 00483 AdapterObject->DmaOperations->MapTransfer(AdapterObject, Buffer, 00484 DmaBlock->MapRegisterBase, 00485 (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, &Length, WriteToDevice); 00486 00487 NDIS_DbgPrint(MAX_TRACE, ("returning success\n")); 00488 *Status = NDIS_STATUS_SUCCESS; 00489 } 00490 00491 /* 00492 * @implemented 00493 */ 00494 VOID 00495 EXPORT 00496 NdisSetupDmaTransfer(OUT PNDIS_STATUS Status, 00497 IN PNDIS_HANDLE NdisDmaHandle, 00498 IN PNDIS_BUFFER Buffer, 00499 IN ULONG Offset, 00500 IN ULONG Length, 00501 IN BOOLEAN WriteToDevice) 00502 /* 00503 * FUNCTION: 00504 * ARGUMENTS: 00505 * NOTES: 00506 * NDIS 4.0 00507 */ 00508 { 00509 NdisMSetupDmaTransfer(Status, 00510 NdisDmaHandle, 00511 Buffer, 00512 Offset, 00513 Length, 00514 WriteToDevice); 00515 } 00516 00517 /* 00518 * @implemented 00519 */ 00520 VOID 00521 EXPORT 00522 NdisMCompleteDmaTransfer(OUT PNDIS_STATUS Status, 00523 IN NDIS_HANDLE MiniportDmaHandle, 00524 IN PNDIS_BUFFER Buffer, 00525 IN ULONG Offset, 00526 IN ULONG Length, 00527 IN BOOLEAN WriteToDevice) 00528 { 00529 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; 00530 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; 00531 00532 NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n", 00533 MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice)); 00534 00535 if (!AdapterObject->DmaOperations->FlushAdapterBuffers(AdapterObject, 00536 Buffer, 00537 DmaBlock->MapRegisterBase, 00538 (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, 00539 Length, 00540 WriteToDevice)) 00541 { 00542 NDIS_DbgPrint(MIN_TRACE, ("FlushAdapterBuffers failed\n")); 00543 *Status = NDIS_STATUS_FAILURE; 00544 return; 00545 } 00546 00547 AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); 00548 00549 NDIS_DbgPrint(MAX_TRACE, ("returning success\n")); 00550 *Status = NDIS_STATUS_SUCCESS; 00551 } 00552 00553 /* 00554 * @implemented 00555 */ 00556 VOID 00557 EXPORT 00558 NdisCompleteDmaTransfer(OUT PNDIS_STATUS Status, 00559 IN PNDIS_HANDLE NdisDmaHandle, 00560 IN PNDIS_BUFFER Buffer, 00561 IN ULONG Offset, 00562 IN ULONG Length, 00563 IN BOOLEAN WriteToDevice) 00564 { 00565 NdisMCompleteDmaTransfer(Status, 00566 NdisDmaHandle, 00567 Buffer, 00568 Offset, 00569 Length, 00570 WriteToDevice); 00571 } 00572 00573 /* 00574 * @implemented 00575 */ 00576 VOID 00577 EXPORT 00578 NdisMStartBufferPhysicalMapping( 00579 IN NDIS_HANDLE MiniportAdapterHandle, 00580 IN PNDIS_BUFFER Buffer, 00581 IN ULONG PhysicalMapRegister, 00582 IN BOOLEAN WriteToDevice, 00583 OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray, 00584 OUT PUINT ArraySize) 00585 /* 00586 * FUNCTION: Sets up map registers for a bus-master DMA transfer 00587 * ARGUMENTS: 00588 * MiniportAdapterHandle: handle originally input to MiniportInitialize 00589 * Buffer: data to be transferred 00590 * PhysicalMapRegister: specifies the map register to set up 00591 * WriteToDevice: if true, data is being written to the device; else it is being read 00592 * PhysicalAddressArray: list of mapped ranges suitable for DMA with the device 00593 * ArraySize: number of elements in PhysicalAddressArray 00594 * NOTES: 00595 * - Must be called at IRQL <= DISPATCH_LEVEL 00596 * - The basic idea: call IoMapTransfer() in a loop as many times as it takes 00597 * in order to map all of the virtual memory to physical memoroy readable 00598 * by the device 00599 * - The caller supplies storage for the physical address array. 00600 */ 00601 { 00602 PLOGICAL_ADAPTER Adapter; 00603 PVOID CurrentVa; 00604 ULONG TotalLength; 00605 PHYSICAL_ADDRESS ReturnedAddress; 00606 UINT LoopCount = 0; 00607 00608 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00609 ASSERT(MiniportAdapterHandle && Buffer && PhysicalAddressArray && ArraySize); 00610 00611 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00612 CurrentVa = MmGetMdlVirtualAddress(Buffer); 00613 TotalLength = MmGetMdlByteCount(Buffer); 00614 00615 while(TotalLength) 00616 { 00617 ULONG Length = TotalLength; 00618 00619 ReturnedAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->MapTransfer( 00620 Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer, 00621 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister, 00622 CurrentVa, &Length, WriteToDevice); 00623 00624 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice = WriteToDevice; 00625 00626 PhysicalAddressArray[LoopCount].PhysicalAddress = ReturnedAddress; 00627 PhysicalAddressArray[LoopCount].Length = Length; 00628 00629 TotalLength -= Length; 00630 CurrentVa = (PVOID)((ULONG_PTR)CurrentVa + Length); 00631 00632 LoopCount++; 00633 } 00634 00635 *ArraySize = LoopCount; 00636 } 00637 00638 00639 /* 00640 * @implemented 00641 */ 00642 VOID 00643 EXPORT 00644 NdisMCompleteBufferPhysicalMapping( 00645 IN NDIS_HANDLE MiniportAdapterHandle, 00646 IN PNDIS_BUFFER Buffer, 00647 IN ULONG PhysicalMapRegister) 00648 /* 00649 * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping 00650 * ARGUMENTS: 00651 * - MiniportAdapterHandle: handle originally input to MiniportInitialize 00652 * - Buffer: NDIS_BUFFER to complete the mapping on 00653 * - PhyscialMapRegister: the chosen map register 00654 * NOTES: 00655 * - May be called at IRQL <= DISPATCH_LEVEL 00656 */ 00657 { 00658 PLOGICAL_ADAPTER Adapter; 00659 VOID *CurrentVa; 00660 ULONG Length; 00661 00662 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00663 ASSERT(MiniportAdapterHandle && Buffer); 00664 00665 Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00666 CurrentVa = MmGetMdlVirtualAddress(Buffer); 00667 Length = MmGetMdlByteCount(Buffer); 00668 00669 Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->FlushAdapterBuffers( 00670 Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer, 00671 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister, 00672 CurrentVa, Length, 00673 Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice); 00674 } 00675 00676 00677 /* 00678 * @implemented 00679 */ 00680 VOID 00681 EXPORT 00682 NdisMDeregisterDmaChannel( 00683 IN NDIS_HANDLE MiniportDmaHandle) 00684 { 00685 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; 00686 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; 00687 00688 if (AdapterObject == ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject) 00689 ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject = NULL; 00690 00691 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00692 00693 ExFreePool(DmaBlock); 00694 } 00695 00696 00697 /* 00698 * @implemented 00699 */ 00700 VOID 00701 EXPORT 00702 NdisMDeregisterInterrupt( 00703 IN PNDIS_MINIPORT_INTERRUPT Interrupt) 00704 /* 00705 * FUNCTION: Releases an interrupt vector 00706 * ARGUMENTS: 00707 * Interrupt = Pointer to interrupt object 00708 */ 00709 { 00710 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00711 IoDisconnectInterrupt(Interrupt->InterruptObject); 00712 Interrupt->Miniport->RegisteredInterrupts--; 00713 00714 if (Interrupt->Miniport->Interrupt == Interrupt) 00715 Interrupt->Miniport->Interrupt = NULL; 00716 } 00717 00718 00719 /* 00720 * @implemented 00721 */ 00722 VOID 00723 EXPORT 00724 NdisMFreeMapRegisters( 00725 IN NDIS_HANDLE MiniportAdapterHandle) 00726 /* 00727 * FUNCTION: Free previously allocated map registers 00728 * ARGUMENTS: 00729 * MiniportAdapterHandle: Handle originally passed in to MiniportInitialize 00730 * NOTES: 00731 */ 00732 { 00733 KIRQL OldIrql; 00734 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00735 PDMA_ADAPTER AdapterObject; 00736 UINT MapRegistersPerBaseRegister; 00737 UINT i; 00738 00739 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00740 00741 ASSERT(Adapter); 00742 00743 /* only bus masters may call this routine */ 00744 if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER) || 00745 Adapter->NdisMiniportBlock.SystemAdapterObject == NULL) { 00746 NDIS_DbgPrint(MIN_TRACE, ("Not bus master or bad adapter object\n")); 00747 return; 00748 } 00749 00750 MapRegistersPerBaseRegister = ((Adapter->NdisMiniportBlock.MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2; 00751 00752 AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject; 00753 00754 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00755 { 00756 for(i = 0; i < Adapter->NdisMiniportBlock.BaseMapRegistersNeeded; i++) 00757 { 00758 AdapterObject->DmaOperations->FreeMapRegisters( 00759 Adapter->NdisMiniportBlock.SystemAdapterObject, 00760 Adapter->NdisMiniportBlock.MapRegisters[i].MapRegister, 00761 MapRegistersPerBaseRegister); 00762 } 00763 } 00764 KeLowerIrql(OldIrql); 00765 00766 AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject); 00767 Adapter->NdisMiniportBlock.SystemAdapterObject = NULL; 00768 00769 ExFreePool(Adapter->NdisMiniportBlock.MapRegisters); 00770 } 00771 00772 00773 /* 00774 * @implemented 00775 */ 00776 NDIS_STATUS 00777 EXPORT 00778 NdisMMapIoSpace( 00779 OUT PVOID *VirtualAddress, 00780 IN NDIS_HANDLE MiniportAdapterHandle, 00781 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, 00782 IN UINT Length) 00783 /* 00784 * FUNCTION: Maps a bus-relative address to a system-wide virtual address 00785 * ARGUMENTS: 00786 * VirtualAddress: receives virtual address of mapping 00787 * MiniportAdapterHandle: Handle originally input to MiniportInitialize 00788 * PhysicalAddress: bus-relative address to map 00789 * Length: Number of bytes to map 00790 * RETURNS: 00791 * NDIS_STATUS_SUCCESS: the operation completed successfully 00792 * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed 00793 * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping 00794 * NDIS_STATUS_FAILURE: a general failure has occured 00795 * NOTES: 00796 * - Must be called at IRQL = PASSIVE_LEVEL 00797 */ 00798 { 00799 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle; 00800 ULONG AddressSpace = 0; /* Memory Space */ 00801 NDIS_PHYSICAL_ADDRESS TranslatedAddress; 00802 00803 PAGED_CODE(); 00804 ASSERT(VirtualAddress && MiniportAdapterHandle); 00805 00806 NDIS_DbgPrint(MAX_TRACE, ("Called\n")); 00807 00808 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, 00809 PhysicalAddress, &AddressSpace, &TranslatedAddress)) 00810 { 00811 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); 00812 return NDIS_STATUS_RESOURCES; 00813 } 00814 00815 *VirtualAddress = MmMapIoSpace(TranslatedAddress, Length, MmNonCached); 00816 00817 if(!*VirtualAddress) { 00818 NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n")); 00819 return NDIS_STATUS_RESOURCES; 00820 } 00821 00822 return NDIS_STATUS_SUCCESS; 00823 } 00824 00825 00826 /* 00827 * @implemented 00828 */ 00829 ULONG 00830 EXPORT 00831 NdisMReadDmaCounter( 00832 IN NDIS_HANDLE MiniportDmaHandle) 00833 { 00834 /* NOTE: Unlike NdisMGetDmaAlignment() below, this is a handle to the DMA block */ 00835 PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; 00836 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; 00837 00838 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00839 00840 return AdapterObject->DmaOperations->ReadDmaCounter(AdapterObject); 00841 } 00842 00843 00844 /* 00845 * @implemented 00846 */ 00847 ULONG 00848 EXPORT 00849 NdisMGetDmaAlignment( 00850 IN NDIS_HANDLE MiniportAdapterHandle) 00851 { 00852 /* NOTE: Unlike NdisMReadDmaCounter() above, this is a handle to the NDIS miniport block */ 00853 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle; 00854 PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)Adapter->NdisMiniportBlock.SystemAdapterObject; 00855 00856 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00857 00858 return AdapterObject->DmaOperations->GetDmaAlignment(AdapterObject); 00859 } 00860 00861 00862 /* 00863 * @implemented 00864 */ 00865 NDIS_STATUS 00866 EXPORT 00867 NdisMRegisterDmaChannel( 00868 OUT PNDIS_HANDLE MiniportDmaHandle, 00869 IN NDIS_HANDLE MiniportAdapterHandle, 00870 IN UINT DmaChannel, 00871 IN BOOLEAN Dma32BitAddresses, 00872 IN PNDIS_DMA_DESCRIPTION DmaDescription, 00873 IN ULONG MaximumLength) 00874 { 00875 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00876 DEVICE_DESCRIPTION DeviceDesc; 00877 ULONG MapRegisters; 00878 PNDIS_DMA_BLOCK DmaBlock; 00879 00880 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00881 00882 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION)); 00883 00884 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION; 00885 DeviceDesc.Master = (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER); 00886 DeviceDesc.ScatterGather = FALSE; 00887 DeviceDesc.DemandMode = DmaDescription->DemandMode; 00888 DeviceDesc.AutoInitialize = DmaDescription->AutoInitialize; 00889 DeviceDesc.Dma32BitAddresses = Dma32BitAddresses; 00890 DeviceDesc.Dma64BitAddresses = FALSE; 00891 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber; 00892 DeviceDesc.DmaChannel = DmaDescription->DmaChannel; 00893 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType; 00894 DeviceDesc.DmaWidth = DmaDescription->DmaWidth; 00895 DeviceDesc.DmaSpeed = DmaDescription->DmaSpeed; 00896 DeviceDesc.MaximumLength = MaximumLength; 00897 00898 00899 DmaBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_DMA_BLOCK)); 00900 if (!DmaBlock) { 00901 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00902 return NDIS_STATUS_RESOURCES; 00903 } 00904 00905 DmaBlock->SystemAdapterObject = (PVOID)IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters); 00906 00907 if (!DmaBlock->SystemAdapterObject) { 00908 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00909 ExFreePool(DmaBlock); 00910 return NDIS_STATUS_RESOURCES; 00911 } 00912 00913 Adapter->NdisMiniportBlock.SystemAdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; 00914 00915 KeInitializeEvent(&DmaBlock->AllocationEvent, NotificationEvent, FALSE); 00916 00917 DmaBlock->Miniport = Adapter; 00918 00919 *MiniportDmaHandle = DmaBlock; 00920 00921 return NDIS_STATUS_SUCCESS; 00922 } 00923 00924 /* 00925 * @implemented 00926 */ 00927 VOID 00928 EXPORT 00929 NdisAllocateDmaChannel(OUT PNDIS_STATUS Status, 00930 OUT PNDIS_HANDLE NdisDmaHandle, 00931 IN NDIS_HANDLE NdisAdapterHandle, 00932 IN PNDIS_DMA_DESCRIPTION DmaDescription, 00933 IN ULONG MaximumLength) 00934 { 00935 *Status = NdisMRegisterDmaChannel(NdisDmaHandle, 00936 NdisAdapterHandle, 00937 0, 00938 FALSE, 00939 DmaDescription, 00940 MaximumLength); 00941 } 00942 /* 00943 * @implemented 00944 */ 00945 NDIS_STATUS 00946 EXPORT 00947 NdisMRegisterInterrupt( 00948 OUT PNDIS_MINIPORT_INTERRUPT Interrupt, 00949 IN NDIS_HANDLE MiniportAdapterHandle, 00950 IN UINT InterruptVector, 00951 IN UINT InterruptLevel, 00952 IN BOOLEAN RequestIsr, 00953 IN BOOLEAN SharedInterrupt, 00954 IN NDIS_INTERRUPT_MODE InterruptMode) 00955 /* 00956 * FUNCTION: Claims access to an interrupt vector 00957 * ARGUMENTS: 00958 * Interrupt = Address of interrupt object to initialize 00959 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize 00960 * InterruptVector = Specifies bus-relative vector to register 00961 * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt 00962 * RequestIsr = TRUE if MiniportISR should always be called 00963 * SharedInterrupt = TRUE if other devices may use the same interrupt 00964 * InterruptMode = Specifies type of interrupt 00965 * RETURNS: 00966 * Status of operation 00967 */ 00968 { 00969 NTSTATUS Status; 00970 ULONG MappedIRQ; 00971 KIRQL DIrql; 00972 KAFFINITY Affinity; 00973 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 00974 00975 NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) " 00976 "SharedInterrupt (%d) InterruptMode (0x%X)\n", 00977 InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode)); 00978 00979 RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT)); 00980 00981 KeInitializeSpinLock(&Interrupt->DpcCountLock); 00982 00983 KeInitializeDpc(&Interrupt->InterruptDpc, HandleDeferredProcessing, Adapter); 00984 00985 KeInitializeEvent(&Interrupt->DpcsCompletedEvent, NotificationEvent, FALSE); 00986 00987 Interrupt->SharedInterrupt = SharedInterrupt; 00988 Interrupt->IsrRequested = RequestIsr; 00989 Interrupt->Miniport = &Adapter->NdisMiniportBlock; 00990 00991 MappedIRQ = HalGetInterruptVector(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, 00992 InterruptLevel, InterruptVector, &DIrql, 00993 &Affinity); 00994 00995 NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ, Affinity)); 00996 00997 Status = IoConnectInterrupt(&Interrupt->InterruptObject, ServiceRoutine, Interrupt, &Interrupt->DpcCountLock, MappedIRQ, 00998 DIrql, DIrql, InterruptMode, SharedInterrupt, Affinity, FALSE); 00999 01000 NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status)); 01001 01002 if (NT_SUCCESS(Status)) { 01003 Adapter->NdisMiniportBlock.Interrupt = Interrupt; 01004 Adapter->NdisMiniportBlock.RegisteredInterrupts++; 01005 return NDIS_STATUS_SUCCESS; 01006 } 01007 01008 if (Status == STATUS_INSUFFICIENT_RESOURCES) 01009 { 01010 /* FIXME: Log error */ 01011 NDIS_DbgPrint(MIN_TRACE, ("Resource conflict!\n")); 01012 return NDIS_STATUS_RESOURCE_CONFLICT; 01013 } 01014 01015 NDIS_DbgPrint(MIN_TRACE, ("Function failed. Status (0x%X).\n", Status)); 01016 return NDIS_STATUS_FAILURE; 01017 } 01018 01019 01020 /* 01021 * @implemented 01022 */ 01023 NDIS_STATUS 01024 EXPORT 01025 NdisMRegisterIoPortRange( 01026 OUT PVOID *PortOffset, 01027 IN NDIS_HANDLE MiniportAdapterHandle, 01028 IN UINT InitialPort, 01029 IN UINT NumberOfPorts) 01030 /* 01031 * FUNCTION: Sets up driver access to device I/O ports 01032 * ARGUMENTS: 01033 * PortOffset = Address of buffer to place mapped base port address 01034 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize 01035 * InitialPort = Bus-relative base port address of a range to be mapped 01036 * NumberOfPorts = Specifies number of ports to be mapped 01037 * RETURNS: 01038 * Status of operation 01039 */ 01040 { 01041 PHYSICAL_ADDRESS PortAddress, TranslatedAddress; 01042 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 01043 ULONG AddressSpace = 1; /* FIXME The HAL handles this wrong atm */ 01044 01045 *PortOffset = 0; 01046 01047 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts)); 01048 01049 memset(&PortAddress, 0, sizeof(PortAddress)); 01050 01051 /* 01052 * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but 01053 * we don't have a way to get the I/O base address yet (see 01054 * NDIS_MINIPORT_BLOCK->AllocatedResources and 01055 * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated). 01056 */ 01057 if(InitialPort) 01058 PortAddress = RtlConvertUlongToLargeInteger(InitialPort); 01059 else 01060 ASSERT(FALSE); 01061 01062 NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart)); 01063 01064 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, 01065 PortAddress, &AddressSpace, &TranslatedAddress)) 01066 { 01067 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); 01068 return NDIS_STATUS_RESOURCES; 01069 } 01070 01071 NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n", 01072 AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart)); 01073 01074 if(AddressSpace) 01075 { 01076 ASSERT(TranslatedAddress.u.HighPart == 0); 01077 *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart; 01078 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset)); 01079 return NDIS_STATUS_SUCCESS; 01080 } 01081 01082 NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n")); 01083 01084 *PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached); 01085 NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset)); 01086 01087 if(!*PortOffset) { 01088 NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n")); 01089 return NDIS_STATUS_RESOURCES; 01090 } 01091 01092 return NDIS_STATUS_SUCCESS; 01093 } 01094 01095 /* 01096 * @implemented 01097 */ 01098 VOID 01099 EXPORT 01100 NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle, 01101 IN UINT InitialPort, 01102 IN UINT NumberOfPorts, 01103 IN PVOID PortOffset) 01104 /* 01105 * FUNCTION: Releases a register mapping to I/O ports 01106 * ARGUMENTS: 01107 * MiniportAdapterHandle = Specifies handle input to MiniportInitialize 01108 * InitialPort = Bus-relative base port address of a range to be mapped 01109 * NumberOfPorts = Specifies number of ports to be mapped 01110 * PortOffset = Pointer to mapped base port address 01111 */ 01112 { 01113 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 01114 PHYSICAL_ADDRESS PortAddress = RtlConvertUlongToLargeInteger(InitialPort); 01115 PHYSICAL_ADDRESS TranslatedAddress; 01116 ULONG AddressSpace = 1; 01117 01118 NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x, Port Offset 0x%x\n", InitialPort, NumberOfPorts, PortOffset)); 01119 01120 /* Translate the initial port again to find the address space of the translated address */ 01121 if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, 01122 PortAddress, &AddressSpace, &TranslatedAddress)) 01123 { 01124 NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); 01125 return; 01126 } 01127 01128 /* Make sure we got the same translation as last time */ 01129 ASSERT(TranslatedAddress.QuadPart == (ULONG_PTR)PortOffset); 01130 01131 /* Check if we're in memory space */ 01132 if (!AddressSpace) 01133 { 01134 NDIS_DbgPrint(MAX_TRACE, ("Calling MmUnmapIoSpace\n")); 01135 01136 /* Unmap the memory */ 01137 MmUnmapIoSpace(PortOffset, NumberOfPorts); 01138 } 01139 } 01140 01141 /* 01142 * @implemented 01143 */ 01144 VOID 01145 EXPORT 01146 NdisMUnmapIoSpace( 01147 IN NDIS_HANDLE MiniportAdapterHandle, 01148 IN PVOID VirtualAddress, 01149 IN UINT Length) 01150 /* 01151 * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace 01152 * ARGUMENTS: 01153 * MiniportAdapterHandle: handle originally passed into MiniportInitialize 01154 * VirtualAddress: Address to un-map 01155 * Length: length of the mapped memory space 01156 * NOTES: 01157 * - Must be called at IRQL = PASSIVE_LEVEL 01158 * - Must only be called from MiniportInitialize and MiniportHalt 01159 * - See also: NdisMMapIoSpace 01160 * BUGS: 01161 * - Depends on MmUnmapIoSpace to Do The Right Thing in all cases 01162 */ 01163 { 01164 PAGED_CODE(); 01165 01166 ASSERT(MiniportAdapterHandle); 01167 01168 MmUnmapIoSpace(VirtualAddress, Length); 01169 } 01170 01171 /* 01172 * @implemented 01173 */ 01174 NDIS_STATUS 01175 EXPORT 01176 NdisMInitializeScatterGatherDma( 01177 IN NDIS_HANDLE MiniportAdapterHandle, 01178 IN BOOLEAN Dma64BitAddresses, 01179 IN ULONG MaximumPhysicalMapping) 01180 /* 01181 * FUNCTION: 01182 * ARGUMENTS: 01183 * NOTES: 01184 * NDIS 5.0 01185 */ 01186 { 01187 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; 01188 ULONG MapRegisters; 01189 DEVICE_DESCRIPTION DeviceDesc; 01190 01191 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01192 01193 if (!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) { 01194 NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n")); 01195 return NDIS_STATUS_NOT_SUPPORTED; 01196 } 01197 01198 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION)); 01199 01200 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION; 01201 DeviceDesc.Master = TRUE; 01202 DeviceDesc.ScatterGather = TRUE; 01203 DeviceDesc.Dma32BitAddresses = !Dma64BitAddresses; 01204 DeviceDesc.Dma64BitAddresses = Dma64BitAddresses; 01205 DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber; 01206 DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType; 01207 DeviceDesc.MaximumLength = MaximumPhysicalMapping; 01208 01209 Adapter->NdisMiniportBlock.SystemAdapterObject = 01210 IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters); 01211 01212 if (!Adapter->NdisMiniportBlock.SystemAdapterObject) 01213 return NDIS_STATUS_RESOURCES; 01214 01215 /* FIXME: Right now we just use this as a place holder */ 01216 Adapter->NdisMiniportBlock.ScatterGatherListSize = 1; 01217 01218 return NDIS_STATUS_SUCCESS; 01219 } 01220 01221 01222 /* 01223 * @implemented 01224 */ 01225 VOID 01226 EXPORT 01227 NdisMapIoSpace( 01228 OUT PNDIS_STATUS Status, 01229 OUT PVOID *VirtualAddress, 01230 IN NDIS_HANDLE NdisAdapterHandle, 01231 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, 01232 IN UINT Length) 01233 /* 01234 * FUNCTION: 01235 * ARGUMENTS: 01236 * NOTES: 01237 * NDIS 4.0 01238 */ 01239 { 01240 *Status = NdisMMapIoSpace(VirtualAddress, 01241 NdisAdapterHandle, 01242 PhysicalAddress, 01243 Length); 01244 } 01245 01246 01247 /* 01248 * @implemented 01249 */ 01250 VOID 01251 EXPORT 01252 NdisFreeDmaChannel( 01253 IN PNDIS_HANDLE NdisDmaHandle) 01254 /* 01255 * FUNCTION: 01256 * ARGUMENTS: 01257 * NOTES: 01258 * NDIS 4.0 01259 */ 01260 { 01261 NdisMDeregisterDmaChannel(NdisDmaHandle); 01262 } 01263 01264 01265 01266 /* EOF */ 01267 Generated on Sun May 27 2012 04:27:44 for ReactOS by
1.7.6.1
|