Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendma.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS kernel 00005 * FILE: ntoskrnl/hal/x86/dma.c 00006 * PURPOSE: DMA functions 00007 * PROGRAMMERS: David Welch (welch@mcmail.com) 00008 * Filip Navara (navaraf@reactos.com) 00009 * UPDATE HISTORY: 00010 * Created 22/05/98 00011 */ 00012 00072 /* INCLUDES *****************************************************************/ 00073 00074 #include <hal.h> 00075 #define NDEBUG 00076 #include <debug.h> 00077 00078 #define MAX_SG_ELEMENTS 0x10 00079 00080 #ifndef _MINIHAL_ 00081 static KEVENT HalpDmaLock; 00082 static LIST_ENTRY HalpDmaAdapterList; 00083 static PADAPTER_OBJECT HalpEisaAdapter[8]; 00084 #endif 00085 static BOOLEAN HalpEisaDma; 00086 #ifndef _MINIHAL_ 00087 static PADAPTER_OBJECT HalpMasterAdapter; 00088 #endif 00089 00090 static const ULONG_PTR HalpEisaPortPage[8] = { 00091 FIELD_OFFSET(DMA_PAGE, Channel0), 00092 FIELD_OFFSET(DMA_PAGE, Channel1), 00093 FIELD_OFFSET(DMA_PAGE, Channel2), 00094 FIELD_OFFSET(DMA_PAGE, Channel3), 00095 0, 00096 FIELD_OFFSET(DMA_PAGE, Channel5), 00097 FIELD_OFFSET(DMA_PAGE, Channel6), 00098 FIELD_OFFSET(DMA_PAGE, Channel7) 00099 }; 00100 00101 #ifndef _MINIHAL_ 00102 static DMA_OPERATIONS HalpDmaOperations = { 00103 sizeof(DMA_OPERATIONS), 00104 (PPUT_DMA_ADAPTER)HalPutDmaAdapter, 00105 (PALLOCATE_COMMON_BUFFER)HalAllocateCommonBuffer, 00106 (PFREE_COMMON_BUFFER)HalFreeCommonBuffer, 00107 NULL, /* Initialized in HalpInitDma() */ 00108 NULL, /* Initialized in HalpInitDma() */ 00109 NULL, /* Initialized in HalpInitDma() */ 00110 NULL, /* Initialized in HalpInitDma() */ 00111 NULL, /* Initialized in HalpInitDma() */ 00112 (PGET_DMA_ALIGNMENT)HalpDmaGetDmaAlignment, 00113 (PREAD_DMA_COUNTER)HalReadDmaCounter, 00114 /* FIXME: Implement the S/G funtions. */ 00115 (PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList, 00116 (PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList, 00117 NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/, 00118 NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/, 00119 NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/ 00120 }; 00121 #endif 00122 00123 #define MAX_MAP_REGISTERS 64 00124 00125 #define TAG_DMA ' AMD' 00126 00127 /* FUNCTIONS *****************************************************************/ 00128 00129 #ifndef _MINIHAL_ 00130 VOID 00131 INIT_FUNCTION 00132 HalpInitDma(VOID) 00133 { 00134 /* 00135 * Initialize the DMA Operation table 00136 */ 00137 HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel; 00138 HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers; 00139 HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel; 00140 HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters; 00141 HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer; 00142 00143 /* 00144 * Check if Extended DMA is available. We're just going to do a random 00145 * read and write. 00146 */ 00147 WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A); 00148 if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A) 00149 { 00150 HalpEisaDma = TRUE; 00151 } 00152 00153 /* 00154 * Intialize all the global variables and allocate master adapter with 00155 * first map buffers. 00156 */ 00157 InitializeListHead(&HalpDmaAdapterList); 00158 KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE); 00159 HalpMasterAdapter = HalpDmaAllocateMasterAdapter(); 00160 00161 /* 00162 * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's 00163 * used by IoGetDmaAdapter in the kernel. 00164 */ 00165 HalGetDmaAdapter = HalpGetDmaAdapter; 00166 } 00167 #endif 00168 00175 PHYSICAL_ADDRESS 00176 NTAPI 00177 HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject) 00178 { 00179 PHYSICAL_ADDRESS HighestAddress; 00180 00181 if (AdapterObject->MasterDevice) 00182 { 00183 if (AdapterObject->Dma64BitAddresses) 00184 { 00185 HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL; 00186 return HighestAddress; 00187 } 00188 else if (AdapterObject->Dma32BitAddresses) 00189 { 00190 HighestAddress.QuadPart = 0xFFFFFFFF; 00191 return HighestAddress; 00192 } 00193 } 00194 00195 HighestAddress.QuadPart = 0xFFFFFF; 00196 return HighestAddress; 00197 } 00198 00199 #ifndef _MINIHAL_ 00200 00211 BOOLEAN 00212 NTAPI 00213 HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, 00214 IN ULONG SizeOfMapBuffers) 00215 { 00216 PVOID VirtualAddress; 00217 PHYSICAL_ADDRESS PhysicalAddress; 00218 PHYSICAL_ADDRESS HighestAcceptableAddress; 00219 PHYSICAL_ADDRESS LowestAcceptableAddress; 00220 PHYSICAL_ADDRESS BoundryAddressMultiple; 00221 KIRQL OldIrql; 00222 ULONG MapRegisterCount; 00223 00224 /* Check if enough map register slots are available. */ 00225 MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers); 00226 if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS) 00227 { 00228 DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n", 00229 AdapterObject->NumberOfMapRegisters, 00230 MapRegisterCount, 00231 MAX_MAP_REGISTERS); 00232 return FALSE; 00233 } 00234 00235 /* 00236 * Allocate memory for the new map registers. For 32-bit adapters we use 00237 * two passes in order not to waste scare resource (low memory). 00238 */ 00239 HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); 00240 LowestAcceptableAddress.HighPart = 0; 00241 LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0; 00242 BoundryAddressMultiple.QuadPart = 0; 00243 00244 VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT, 00245 LowestAcceptableAddress, 00246 HighestAcceptableAddress, 00247 BoundryAddressMultiple, 00248 MmNonCached); 00249 if (!(VirtualAddress) && (LowestAcceptableAddress.LowPart)) 00250 { 00251 LowestAcceptableAddress.LowPart = 0; 00252 VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT, 00253 LowestAcceptableAddress, 00254 HighestAcceptableAddress, 00255 BoundryAddressMultiple, 00256 MmNonCached); 00257 } 00258 00259 if (!VirtualAddress) return FALSE; 00260 00261 PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); 00262 00263 /* 00264 * All the following must be done with the master adapter lock held 00265 * to prevent corruption. 00266 */ 00267 KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); 00268 00269 /* 00270 * Setup map register entries for the buffer allocated. Each entry has 00271 * a virtual and physical address and corresponds to PAGE_SIZE large 00272 * buffer. 00273 */ 00274 if (MapRegisterCount > 0) 00275 { 00276 PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry; 00277 00278 CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters; 00279 do 00280 { 00281 /* 00282 * Leave one entry free for every non-contiguous memory region 00283 * in the map register bitmap. This ensures that we can search 00284 * using RtlFindClearBits for contiguous map register regions. 00285 * 00286 * Also for non-EISA DMA leave one free entry for every 64Kb 00287 * break, because the DMA controller can handle only coniguous 00288 * 64Kb regions. 00289 */ 00290 if (CurrentEntry != AdapterObject->MapRegisterBase) 00291 { 00292 PreviousEntry = CurrentEntry - 1; 00293 if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart) 00294 { 00295 if (!HalpEisaDma) 00296 { 00297 if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000) 00298 { 00299 CurrentEntry++; 00300 AdapterObject->NumberOfMapRegisters++; 00301 } 00302 } 00303 } 00304 else 00305 { 00306 CurrentEntry++; 00307 AdapterObject->NumberOfMapRegisters++; 00308 } 00309 } 00310 00311 RtlClearBit(AdapterObject->MapRegisters, 00312 (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase)); 00313 CurrentEntry->VirtualAddress = VirtualAddress; 00314 CurrentEntry->PhysicalAddress = PhysicalAddress; 00315 00316 PhysicalAddress.LowPart += PAGE_SIZE; 00317 VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); 00318 00319 CurrentEntry++; 00320 AdapterObject->NumberOfMapRegisters++; 00321 MapRegisterCount--; 00322 } while (MapRegisterCount); 00323 } 00324 00325 KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); 00326 00327 return TRUE; 00328 } 00329 00338 PADAPTER_OBJECT 00339 NTAPI 00340 HalpDmaAllocateMasterAdapter(VOID) 00341 { 00342 PADAPTER_OBJECT MasterAdapter; 00343 ULONG Size, SizeOfBitmap; 00344 00345 SizeOfBitmap = MAX_MAP_REGISTERS; 00346 Size = sizeof(ADAPTER_OBJECT); 00347 Size += sizeof(RTL_BITMAP); 00348 Size += (SizeOfBitmap + 7) >> 3; 00349 00350 MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA); 00351 if (!MasterAdapter) return NULL; 00352 00353 RtlZeroMemory(MasterAdapter, Size); 00354 00355 KeInitializeSpinLock(&MasterAdapter->SpinLock); 00356 InitializeListHead(&MasterAdapter->AdapterQueue); 00357 00358 MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1); 00359 RtlInitializeBitMap(MasterAdapter->MapRegisters, 00360 (PULONG)(MasterAdapter->MapRegisters + 1), 00361 SizeOfBitmap); 00362 RtlSetAllBits(MasterAdapter->MapRegisters); 00363 MasterAdapter->NumberOfMapRegisters = 0; 00364 MasterAdapter->CommittedMapRegisters = 0; 00365 00366 MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool, 00367 SizeOfBitmap * 00368 sizeof(ROS_MAP_REGISTER_ENTRY), 00369 TAG_DMA); 00370 if (!MasterAdapter->MapRegisterBase) 00371 { 00372 ExFreePool(MasterAdapter); 00373 return NULL; 00374 } 00375 00376 RtlZeroMemory(MasterAdapter->MapRegisterBase, 00377 SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY)); 00378 if (!HalpGrowMapBuffers(MasterAdapter, 0x10000)) 00379 { 00380 ExFreePool(MasterAdapter); 00381 return NULL; 00382 } 00383 00384 return MasterAdapter; 00385 } 00386 00395 PADAPTER_OBJECT 00396 NTAPI 00397 HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters, 00398 IN PDEVICE_DESCRIPTION DeviceDescription) 00399 { 00400 PADAPTER_OBJECT AdapterObject; 00401 OBJECT_ATTRIBUTES ObjectAttributes; 00402 NTSTATUS Status; 00403 HANDLE Handle; 00404 00405 InitializeObjectAttributes(&ObjectAttributes, 00406 NULL, 00407 OBJ_KERNEL_HANDLE | OBJ_PERMANENT, 00408 NULL, 00409 NULL); 00410 00411 Status = ObCreateObject(KernelMode, 00412 IoAdapterObjectType, 00413 &ObjectAttributes, 00414 KernelMode, 00415 NULL, 00416 sizeof(ADAPTER_OBJECT), 00417 0, 00418 0, 00419 (PVOID)&AdapterObject); 00420 if (!NT_SUCCESS(Status)) return NULL; 00421 00422 Status = ObReferenceObjectByPointer(AdapterObject, 00423 FILE_READ_DATA | FILE_WRITE_DATA, 00424 IoAdapterObjectType, 00425 KernelMode); 00426 if (!NT_SUCCESS(Status)) return NULL; 00427 00428 RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT)); 00429 00430 Status = ObInsertObject(AdapterObject, 00431 NULL, 00432 FILE_READ_DATA | FILE_WRITE_DATA, 00433 0, 00434 NULL, 00435 &Handle); 00436 if (!NT_SUCCESS(Status)) return NULL; 00437 00438 ZwClose(Handle); 00439 00440 AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version; 00441 AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT); 00442 AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations; 00443 AdapterObject->MapRegistersPerChannel = 1; 00444 AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; 00445 AdapterObject->ChannelNumber = 0xFF; 00446 AdapterObject->MasterAdapter = HalpMasterAdapter; 00447 KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue); 00448 00449 return AdapterObject; 00450 } 00451 #endif 00452 00458 BOOLEAN 00459 NTAPI 00460 HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject, 00461 IN PDEVICE_DESCRIPTION DeviceDescription) 00462 { 00463 UCHAR Controller; 00464 DMA_MODE DmaMode = {{0 }}; 00465 DMA_EXTENDED_MODE ExtendedMode = {{ 0 }}; 00466 PVOID AdapterBaseVa; 00467 00468 Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1; 00469 00470 if (Controller == 1) 00471 { 00472 AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1); 00473 } 00474 else 00475 { 00476 AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2); 00477 } 00478 00479 AdapterObject->AdapterNumber = Controller; 00480 AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3); 00481 AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel]; 00482 AdapterObject->Width16Bits = FALSE; 00483 AdapterObject->AdapterBaseVa = AdapterBaseVa; 00484 00485 if (HalpEisaDma) 00486 { 00487 ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber; 00488 00489 switch (DeviceDescription->DmaSpeed) 00490 { 00491 case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break; 00492 case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break; 00493 case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break; 00494 case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break; 00495 default: 00496 return FALSE; 00497 } 00498 00499 switch (DeviceDescription->DmaWidth) 00500 { 00501 case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break; 00502 case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break; 00503 case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break; 00504 default: 00505 return FALSE; 00506 } 00507 00508 if (Controller == 1) 00509 { 00510 WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1), 00511 ExtendedMode.Byte); 00512 } 00513 else 00514 { 00515 WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2), 00516 ExtendedMode.Byte); 00517 } 00518 } 00519 else 00520 { 00521 /* 00522 * Validate setup for non-busmaster DMA adapter. Secondary controller 00523 * supports only 16-bit transfers and main controller supports only 00524 * 8-bit transfers. Anything else is invalid. 00525 */ 00526 if (!DeviceDescription->Master) 00527 { 00528 if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits)) 00529 { 00530 AdapterObject->Width16Bits = TRUE; 00531 } 00532 else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits)) 00533 { 00534 return FALSE; 00535 } 00536 } 00537 } 00538 00539 DmaMode.Channel = AdapterObject->ChannelNumber; 00540 DmaMode.AutoInitialize = DeviceDescription->AutoInitialize; 00541 00542 /* 00543 * Set the DMA request mode. 00544 * 00545 * For (E)ISA bus master devices just unmask (enable) the DMA channel 00546 * and set it to cascade mode. Otherwise just select the right one 00547 * bases on the passed device description. 00548 */ 00549 if (DeviceDescription->Master) 00550 { 00551 DmaMode.RequestMode = CASCADE_REQUEST_MODE; 00552 if (Controller == 1) 00553 { 00554 /* Set the Request Data */ 00555 WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte); 00556 00557 /* Unmask DMA Channel */ 00558 WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask, 00559 AdapterObject->ChannelNumber | DMA_CLEARMASK); 00560 } 00561 else 00562 { 00563 /* Set the Request Data */ 00564 WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte); 00565 00566 /* Unmask DMA Channel */ 00567 WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask, 00568 AdapterObject->ChannelNumber | DMA_CLEARMASK); 00569 } 00570 } 00571 else 00572 { 00573 if (DeviceDescription->DemandMode) 00574 { 00575 DmaMode.RequestMode = DEMAND_REQUEST_MODE; 00576 } 00577 else 00578 { 00579 DmaMode.RequestMode = SINGLE_REQUEST_MODE; 00580 } 00581 } 00582 00583 AdapterObject->AdapterMode = DmaMode; 00584 00585 return TRUE; 00586 } 00587 00588 #ifndef _MINIHAL_ 00589 00604 PADAPTER_OBJECT 00605 NTAPI 00606 HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, 00607 OUT PULONG NumberOfMapRegisters) 00608 { 00609 PADAPTER_OBJECT AdapterObject = NULL; 00610 BOOLEAN EisaAdapter; 00611 ULONG MapRegisters; 00612 ULONG MaximumLength; 00613 00614 /* Validate parameters in device description */ 00615 if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) return NULL; 00616 00617 /* 00618 * See if we're going to use ISA/EISA DMA adapter. These adapters are 00619 * special since they're reused. 00620 * 00621 * Also note that we check for channel number since there are only 8 DMA 00622 * channels on ISA, so any request above this requires new adapter. 00623 */ 00624 if (((DeviceDescription->InterfaceType == Eisa) || 00625 (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master)) 00626 { 00627 if (((DeviceDescription->InterfaceType == Isa) || 00628 (DeviceDescription->InterfaceType == Eisa)) && 00629 (DeviceDescription->DmaChannel >= 8)) 00630 { 00631 EisaAdapter = FALSE; 00632 } 00633 else 00634 { 00635 EisaAdapter = TRUE; 00636 } 00637 } 00638 else 00639 { 00640 EisaAdapter = FALSE; 00641 } 00642 00643 /* 00644 * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used 00645 * for cascading the controllers and it's not available for software use. 00646 */ 00647 if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL; 00648 00649 /* 00650 * Calculate the number of map registers. 00651 * 00652 * - For EISA and PCI scatter/gather no map registers are needed. 00653 * - For ISA slave scatter/gather one map register is needed. 00654 * - For all other cases the number of map registers depends on 00655 * DeviceDescription->MaximumLength. 00656 */ 00657 MaximumLength = DeviceDescription->MaximumLength & MAXLONG; 00658 if ((DeviceDescription->ScatterGather) && 00659 ((DeviceDescription->InterfaceType == Eisa) || 00660 (DeviceDescription->InterfaceType == PCIBus))) 00661 { 00662 MapRegisters = 0; 00663 } 00664 else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master)) 00665 { 00666 MapRegisters = 1; 00667 } 00668 else 00669 { 00670 /* 00671 * In the equation below the additional map register added by 00672 * the "+1" accounts for the case when a transfer does not start 00673 * at a page-aligned address. 00674 */ 00675 MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1; 00676 if (MapRegisters > 16) MapRegisters = 16; 00677 } 00678 00679 /* 00680 * Acquire the DMA lock that is used to protect adapter lists and 00681 * EISA adapter array. 00682 */ 00683 KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); 00684 00685 /* 00686 * Now we must get ahold of the adapter object. For first eight ISA/EISA 00687 * channels there are static adapter objects that are reused and updated 00688 * on succesive HalGetAdapter calls. In other cases a new adapter object 00689 * is always created and it's to the DMA adapter list (HalpDmaAdapterList). 00690 */ 00691 if (EisaAdapter) 00692 { 00693 AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel]; 00694 if (AdapterObject) 00695 { 00696 if ((AdapterObject->NeedsMapRegisters) && 00697 (MapRegisters > AdapterObject->MapRegistersPerChannel)) 00698 { 00699 AdapterObject->MapRegistersPerChannel = MapRegisters; 00700 } 00701 } 00702 } 00703 00704 if (AdapterObject == NULL) 00705 { 00706 AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription); 00707 if (AdapterObject == NULL) 00708 { 00709 KeSetEvent(&HalpDmaLock, 0, 0); 00710 return NULL; 00711 } 00712 00713 if (EisaAdapter) 00714 { 00715 HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject; 00716 } 00717 00718 if (MapRegisters > 0) 00719 { 00720 AdapterObject->NeedsMapRegisters = TRUE; 00721 AdapterObject->MapRegistersPerChannel = MapRegisters; 00722 } 00723 else 00724 { 00725 AdapterObject->NeedsMapRegisters = FALSE; 00726 if (DeviceDescription->Master) 00727 { 00728 AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1; 00729 } 00730 else 00731 { 00732 AdapterObject->MapRegistersPerChannel = 1; 00733 } 00734 } 00735 } 00736 00737 if (!EisaAdapter) InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList); 00738 00739 /* 00740 * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will 00741 * no longer be touched, so we don't need it. 00742 */ 00743 KeSetEvent(&HalpDmaLock, 0, 0); 00744 00745 /* 00746 * Setup the values in the adapter object that are common for all 00747 * types of buses. 00748 */ 00749 if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1) 00750 { 00751 AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount; 00752 } 00753 else 00754 { 00755 AdapterObject->IgnoreCount = 0; 00756 } 00757 00758 AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; 00759 AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses; 00760 AdapterObject->ScatterGather = DeviceDescription->ScatterGather; 00761 AdapterObject->MasterDevice = DeviceDescription->Master; 00762 *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel; 00763 00764 /* 00765 * For non-(E)ISA adapters we have already done all the work. On the 00766 * other hand for (E)ISA adapters we must still setup the DMA modes 00767 * and prepare the controller. 00768 */ 00769 if (EisaAdapter) 00770 { 00771 if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription)) 00772 { 00773 ObDereferenceObject(AdapterObject); 00774 return NULL; 00775 } 00776 } 00777 00778 return AdapterObject; 00779 } 00780 00789 PDMA_ADAPTER 00790 NTAPI 00791 HalpGetDmaAdapter(IN PVOID Context, 00792 IN PDEVICE_DESCRIPTION DeviceDescription, 00793 OUT PULONG NumberOfMapRegisters) 00794 { 00795 return &HalGetAdapter(DeviceDescription, NumberOfMapRegisters)->DmaHeader; 00796 } 00797 00806 VOID 00807 NTAPI 00808 HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject) 00809 { 00810 if (AdapterObject->ChannelNumber == 0xFF) 00811 { 00812 KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); 00813 RemoveEntryList(&AdapterObject->AdapterList); 00814 KeSetEvent(&HalpDmaLock, 0, 0); 00815 } 00816 00817 ObDereferenceObject(AdapterObject); 00818 } 00819 00845 PVOID 00846 NTAPI 00847 HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, 00848 IN ULONG Length, 00849 IN PPHYSICAL_ADDRESS LogicalAddress, 00850 IN BOOLEAN CacheEnabled) 00851 { 00852 PHYSICAL_ADDRESS LowestAcceptableAddress; 00853 PHYSICAL_ADDRESS HighestAcceptableAddress; 00854 PHYSICAL_ADDRESS BoundryAddressMultiple; 00855 PVOID VirtualAddress; 00856 00857 LowestAcceptableAddress.QuadPart = 0; 00858 HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); 00859 BoundryAddressMultiple.QuadPart = 0; 00860 00861 /* 00862 * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For 00863 * slave DMA devices the 64Kb boundary mustn't be crossed since the 00864 * controller wouldn't be able to handle it. 00865 */ 00866 if (AdapterObject->MasterDevice) 00867 { 00868 BoundryAddressMultiple.HighPart = 1; 00869 } 00870 else 00871 { 00872 BoundryAddressMultiple.LowPart = 0x10000; 00873 } 00874 00875 VirtualAddress = MmAllocateContiguousMemorySpecifyCache(Length, 00876 LowestAcceptableAddress, 00877 HighestAcceptableAddress, 00878 BoundryAddressMultiple, 00879 CacheEnabled ? MmCached : 00880 MmNonCached); 00881 if (VirtualAddress == NULL) return NULL; 00882 00883 *LogicalAddress = MmGetPhysicalAddress(VirtualAddress); 00884 00885 return VirtualAddress; 00886 } 00887 00897 VOID 00898 NTAPI 00899 HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, 00900 IN ULONG Length, 00901 IN PHYSICAL_ADDRESS LogicalAddress, 00902 IN PVOID VirtualAddress, 00903 IN BOOLEAN CacheEnabled) 00904 { 00905 MmFreeContiguousMemorySpecifyCache(VirtualAddress, 00906 Length, 00907 CacheEnabled ? MmCached : MmNonCached); 00908 } 00909 00910 typedef struct _SCATTER_GATHER_CONTEXT { 00911 PADAPTER_OBJECT AdapterObject; 00912 PMDL Mdl; 00913 PUCHAR CurrentVa; 00914 ULONG Length; 00915 PDRIVER_LIST_CONTROL AdapterListControlRoutine; 00916 PVOID AdapterListControlContext, MapRegisterBase; 00917 ULONG MapRegisterCount; 00918 BOOLEAN WriteToDevice; 00919 } SCATTER_GATHER_CONTEXT, *PSCATTER_GATHER_CONTEXT; 00920 00921 00922 IO_ALLOCATION_ACTION 00923 NTAPI 00924 HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject, 00925 IN PIRP Irp, 00926 IN PVOID MapRegisterBase, 00927 IN PVOID Context) 00928 { 00929 PSCATTER_GATHER_CONTEXT AdapterControlContext = Context; 00930 PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject; 00931 PSCATTER_GATHER_LIST ScatterGatherList; 00932 SCATTER_GATHER_ELEMENT TempElements[MAX_SG_ELEMENTS]; 00933 ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length; 00934 PUCHAR CurrentVa = AdapterControlContext->CurrentVa; 00935 00936 /* Store the map register base for later in HalPutScatterGatherList */ 00937 AdapterControlContext->MapRegisterBase = MapRegisterBase; 00938 00939 while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS) 00940 { 00941 TempElements[ElementCount].Length = RemainingLength; 00942 TempElements[ElementCount].Reserved = 0; 00943 TempElements[ElementCount].Address = IoMapTransfer(AdapterObject, 00944 AdapterControlContext->Mdl, 00945 MapRegisterBase, 00946 CurrentVa + (AdapterControlContext->Length - RemainingLength), 00947 &TempElements[ElementCount].Length, 00948 AdapterControlContext->WriteToDevice); 00949 if (TempElements[ElementCount].Length == 0) 00950 break; 00951 00952 DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n", 00953 TempElements[ElementCount].Address.QuadPart, 00954 TempElements[ElementCount].Length); 00955 00956 ASSERT(TempElements[ElementCount].Length <= RemainingLength); 00957 RemainingLength -= TempElements[ElementCount].Length; 00958 ElementCount++; 00959 } 00960 00961 if (RemainingLength > 0) 00962 { 00963 DPRINT1("Scatter/gather list construction failed!\n"); 00964 return DeallocateObject; 00965 } 00966 00967 ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool, 00968 sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount, 00969 TAG_DMA); 00970 ASSERT(ScatterGatherList); 00971 00972 ScatterGatherList->NumberOfElements = ElementCount; 00973 ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext; 00974 RtlCopyMemory(ScatterGatherList->Elements, 00975 TempElements, 00976 sizeof(SCATTER_GATHER_ELEMENT) * ElementCount); 00977 00978 DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount); 00979 00980 AdapterControlContext->AdapterListControlRoutine(DeviceObject, 00981 Irp, 00982 ScatterGatherList, 00983 AdapterControlContext->AdapterListControlContext); 00984 00985 return DeallocateObjectKeepRegisters; 00986 } 00987 01016 NTSTATUS 01017 NTAPI 01018 HalGetScatterGatherList(IN PADAPTER_OBJECT AdapterObject, 01019 IN PDEVICE_OBJECT DeviceObject, 01020 IN PMDL Mdl, 01021 IN PVOID CurrentVa, 01022 IN ULONG Length, 01023 IN PDRIVER_LIST_CONTROL ExecutionRoutine, 01024 IN PVOID Context, 01025 IN BOOLEAN WriteToDevice) 01026 { 01027 PSCATTER_GATHER_CONTEXT AdapterControlContext; 01028 01029 AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA); 01030 if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES; 01031 01032 AdapterControlContext->AdapterObject = AdapterObject; 01033 AdapterControlContext->Mdl = Mdl; 01034 AdapterControlContext->CurrentVa = CurrentVa; 01035 AdapterControlContext->Length = Length; 01036 AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT; 01037 AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine; 01038 AdapterControlContext->AdapterListControlContext = Context; 01039 AdapterControlContext->WriteToDevice = WriteToDevice; 01040 01041 return IoAllocateAdapterChannel(AdapterObject, 01042 DeviceObject, 01043 AdapterControlContext->MapRegisterCount, 01044 HalpScatterGatherAdapterControl, 01045 AdapterControlContext); 01046 } 01047 01066 VOID 01067 NTAPI 01068 HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject, 01069 IN PSCATTER_GATHER_LIST ScatterGather, 01070 IN BOOLEAN WriteToDevice) 01071 { 01072 PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved; 01073 ULONG i; 01074 01075 for (i = 0; i < ScatterGather->NumberOfElements; i++) 01076 { 01077 IoFlushAdapterBuffers(AdapterObject, 01078 AdapterControlContext->Mdl, 01079 AdapterControlContext->MapRegisterBase, 01080 AdapterControlContext->CurrentVa, 01081 ScatterGather->Elements[i].Length, 01082 AdapterControlContext->WriteToDevice); 01083 AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length; 01084 } 01085 01086 IoFreeMapRegisters(AdapterObject, 01087 AdapterControlContext->MapRegisterBase, 01088 AdapterControlContext->MapRegisterCount); 01089 01090 DPRINT("S/G DMA has finished!\n"); 01091 01092 ExFreePoolWithTag(AdapterControlContext, TAG_DMA); 01093 ExFreePoolWithTag(ScatterGather, TAG_DMA); 01094 } 01095 #endif 01096 01105 ULONG 01106 NTAPI 01107 HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject) 01108 { 01109 return 1; 01110 } 01111 01112 /* 01113 * @name HalReadDmaCounter 01114 * 01115 * Read DMA operation progress counter. 01116 * 01117 * @implemented 01118 */ 01119 ULONG 01120 NTAPI 01121 HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject) 01122 { 01123 KIRQL OldIrql; 01124 ULONG Count, OldCount; 01125 01126 ASSERT(!AdapterObject->MasterDevice); 01127 01128 /* 01129 * Acquire the master adapter lock since we're going to mess with the 01130 * system DMA controller registers and we really don't want anyone 01131 * to do the same at the same time. 01132 */ 01133 KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); 01134 01135 /* Send the request to the specific controller. */ 01136 if (AdapterObject->AdapterNumber == 1) 01137 { 01138 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; 01139 01140 Count = 0xffff00; 01141 do 01142 { 01143 OldCount = Count; 01144 01145 /* Send Reset */ 01146 WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); 01147 01148 /* Read Count */ 01149 Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount 01150 [AdapterObject->ChannelNumber].DmaBaseCount); 01151 Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount 01152 [AdapterObject->ChannelNumber].DmaBaseCount) << 8; 01153 } while (0xffff00 & (OldCount ^ Count)); 01154 } 01155 else 01156 { 01157 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; 01158 01159 Count = 0xffff00; 01160 do 01161 { 01162 OldCount = Count; 01163 01164 /* Send Reset */ 01165 WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); 01166 01167 /* Read Count */ 01168 Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount 01169 [AdapterObject->ChannelNumber].DmaBaseCount); 01170 Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount 01171 [AdapterObject->ChannelNumber].DmaBaseCount) << 8; 01172 } while (0xffff00 & (OldCount ^ Count)); 01173 } 01174 01175 KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); 01176 01177 Count++; 01178 Count &= 0xffff; 01179 if (AdapterObject->Width16Bits) Count *= 2; 01180 01181 return Count; 01182 } 01183 01184 #ifndef _MINIHAL_ 01185 01191 VOID 01192 NTAPI 01193 HalpGrowMapBufferWorker(IN PVOID DeferredContext) 01194 { 01195 PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext; 01196 KIRQL OldIrql; 01197 BOOLEAN Succeeded; 01198 01199 /* 01200 * Try to allocate new map registers for the adapter. 01201 * 01202 * NOTE: The NT implementation actually tries to allocate more map 01203 * registers than needed as an optimization. 01204 */ 01205 KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); 01206 Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter, 01207 WorkItem->NumberOfMapRegisters << PAGE_SHIFT); 01208 KeSetEvent(&HalpDmaLock, 0, 0); 01209 01210 if (Succeeded) 01211 { 01212 /* 01213 * Flush the adapter queue now that new map registers are ready. The 01214 * easiest way to do that is to call IoFreeMapRegisters to not free 01215 * any registers. Note that we use the magic (PVOID)2 map register 01216 * base to bypass the parameter checking. 01217 */ 01218 OldIrql = KfRaiseIrql(DISPATCH_LEVEL); 01219 IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0); 01220 KfLowerIrql(OldIrql); 01221 } 01222 01223 ExFreePool(WorkItem); 01224 } 01225 01250 NTSTATUS 01251 NTAPI 01252 HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, 01253 IN PWAIT_CONTEXT_BLOCK WaitContextBlock, 01254 IN ULONG NumberOfMapRegisters, 01255 IN PDRIVER_CONTROL ExecutionRoutine) 01256 { 01257 PADAPTER_OBJECT MasterAdapter; 01258 PGROW_WORK_ITEM WorkItem; 01259 ULONG Index = MAXULONG; 01260 ULONG Result; 01261 KIRQL OldIrql; 01262 01263 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 01264 01265 /* Set up the wait context block in case we can't run right away. */ 01266 WaitContextBlock->DeviceRoutine = ExecutionRoutine; 01267 WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters; 01268 01269 /* Returns true if queued, else returns false and sets the queue to busy */ 01270 if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, 01271 &WaitContextBlock->WaitQueueEntry)) 01272 { 01273 return STATUS_SUCCESS; 01274 } 01275 01276 MasterAdapter = AdapterObject->MasterAdapter; 01277 01278 AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters; 01279 AdapterObject->CurrentWcb = WaitContextBlock; 01280 01281 if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters)) 01282 { 01283 if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) 01284 { 01285 AdapterObject->NumberOfMapRegisters = 0; 01286 IoFreeAdapterChannel(AdapterObject); 01287 return STATUS_INSUFFICIENT_RESOURCES; 01288 } 01289 01290 /* 01291 * Get the map registers. This is partly complicated by the fact 01292 * that new map registers can only be allocated at PASSIVE_LEVEL 01293 * and we're currently at DISPATCH_LEVEL. The following code has 01294 * two code paths: 01295 * 01296 * - If there is no adapter queued for map register allocation, 01297 * try to see if enough contiguous map registers are present. 01298 * In case they're we can just get them and proceed further. 01299 * 01300 * - If some adapter is already present in the queue we must 01301 * respect the order of adapters asking for map registers and 01302 * so the fast case described above can't take place. 01303 * This case is also entered if not enough coniguous map 01304 * registers are present. 01305 * 01306 * A work queue item is allocated and queued, the adapter is 01307 * also queued into the master adapter queue. The worker 01308 * routine does the job of allocating the map registers at 01309 * PASSIVE_LEVEL and calling the ExecutionRoutine. 01310 */ 01311 01312 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); 01313 01314 if (IsListEmpty(&MasterAdapter->AdapterQueue)) 01315 { 01316 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0); 01317 if (Index != MAXULONG) 01318 { 01319 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; 01320 if (!AdapterObject->ScatterGather) 01321 { 01322 AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); 01323 } 01324 } 01325 } 01326 01327 if (Index == MAXULONG) 01328 { 01329 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); 01330 01331 WorkItem = ExAllocatePoolWithTag(NonPagedPool, 01332 sizeof(GROW_WORK_ITEM), 01333 TAG_DMA); 01334 if (WorkItem) 01335 { 01336 ExInitializeWorkItem(&WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem); 01337 WorkItem->AdapterObject = AdapterObject; 01338 WorkItem->NumberOfMapRegisters = NumberOfMapRegisters; 01339 01340 ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue); 01341 } 01342 01343 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01344 01345 return STATUS_SUCCESS; 01346 } 01347 01348 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01349 } 01350 else 01351 { 01352 AdapterObject->MapRegisterBase = NULL; 01353 AdapterObject->NumberOfMapRegisters = 0; 01354 } 01355 01356 AdapterObject->CurrentWcb = WaitContextBlock; 01357 01358 Result = ExecutionRoutine(WaitContextBlock->DeviceObject, 01359 WaitContextBlock->CurrentIrp, 01360 AdapterObject->MapRegisterBase, 01361 WaitContextBlock->DeviceContext); 01362 01363 /* 01364 * Possible return values: 01365 * 01366 * - KeepObject 01367 * Don't free any resources, the ADAPTER_OBJECT is still in use and 01368 * the caller will call IoFreeAdapterChannel later. 01369 * 01370 * - DeallocateObject 01371 * Deallocate the map registers and release the ADAPTER_OBJECT, so 01372 * someone else can use it. 01373 * 01374 * - DeallocateObjectKeepRegisters 01375 * Release the ADAPTER_OBJECT, but hang on to the map registers. The 01376 * client will later call IoFreeMapRegisters. 01377 * 01378 * NOTE: 01379 * IoFreeAdapterChannel runs the queue, so it must be called unless 01380 * the adapter object is not to be freed. 01381 */ 01382 if (Result == DeallocateObject) 01383 { 01384 IoFreeAdapterChannel(AdapterObject); 01385 } 01386 else if (Result == DeallocateObjectKeepRegisters) 01387 { 01388 AdapterObject->NumberOfMapRegisters = 0; 01389 IoFreeAdapterChannel(AdapterObject); 01390 } 01391 01392 return STATUS_SUCCESS; 01393 } 01394 01413 VOID 01414 NTAPI 01415 IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject) 01416 { 01417 PADAPTER_OBJECT MasterAdapter; 01418 PKDEVICE_QUEUE_ENTRY DeviceQueueEntry; 01419 PWAIT_CONTEXT_BLOCK WaitContextBlock; 01420 ULONG Index = MAXULONG; 01421 ULONG Result; 01422 KIRQL OldIrql; 01423 01424 MasterAdapter = AdapterObject->MasterAdapter; 01425 01426 for (;;) 01427 { 01428 /* 01429 * To keep map registers, call here with AdapterObject-> 01430 * NumberOfMapRegisters set to zero. This trick is used in 01431 * HalAllocateAdapterChannel for example. 01432 */ 01433 if (AdapterObject->NumberOfMapRegisters) 01434 { 01435 IoFreeMapRegisters(AdapterObject, 01436 AdapterObject->MapRegisterBase, 01437 AdapterObject->NumberOfMapRegisters); 01438 } 01439 01440 DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue); 01441 if (!DeviceQueueEntry) break; 01442 01443 WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry, 01444 WAIT_CONTEXT_BLOCK, 01445 WaitQueueEntry); 01446 01447 AdapterObject->CurrentWcb = WaitContextBlock; 01448 AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters; 01449 01450 if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter)) 01451 { 01452 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); 01453 01454 if (IsListEmpty(&MasterAdapter->AdapterQueue)) 01455 { 01456 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, 01457 WaitContextBlock->NumberOfMapRegisters, 01458 0); 01459 if (Index != MAXULONG) 01460 { 01461 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; 01462 if (!AdapterObject->ScatterGather) 01463 { 01464 AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); 01465 } 01466 } 01467 } 01468 01469 if (Index == MAXULONG) 01470 { 01471 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); 01472 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01473 break; 01474 } 01475 01476 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01477 } 01478 else 01479 { 01480 AdapterObject->MapRegisterBase = NULL; 01481 AdapterObject->NumberOfMapRegisters = 0; 01482 } 01483 01484 /* Call the adapter control routine. */ 01485 Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject, 01486 WaitContextBlock->CurrentIrp, 01487 AdapterObject->MapRegisterBase, 01488 WaitContextBlock->DeviceContext); 01489 switch (Result) 01490 { 01491 case KeepObject: 01492 /* 01493 * We're done until the caller manually calls IoFreeAdapterChannel 01494 * or IoFreeMapRegisters. 01495 */ 01496 return; 01497 01498 case DeallocateObjectKeepRegisters: 01499 /* 01500 * Hide the map registers so they aren't deallocated next time 01501 * around. 01502 */ 01503 AdapterObject->NumberOfMapRegisters = 0; 01504 break; 01505 01506 default: 01507 break; 01508 } 01509 } 01510 } 01511 01526 VOID 01527 NTAPI 01528 IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, 01529 IN PVOID MapRegisterBase, 01530 IN ULONG NumberOfMapRegisters) 01531 { 01532 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter; 01533 PLIST_ENTRY ListEntry; 01534 KIRQL OldIrql; 01535 ULONG Index; 01536 ULONG Result; 01537 01538 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 01539 01540 if (!(MasterAdapter) || !(MapRegisterBase)) return; 01541 01542 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); 01543 01544 if (NumberOfMapRegisters != 0) 01545 { 01546 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; 01547 01548 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); 01549 RtlClearBits(MasterAdapter->MapRegisters, 01550 (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase), 01551 NumberOfMapRegisters); 01552 } 01553 01554 /* 01555 * Now that we freed few map registers it's time to look at the master 01556 * adapter queue and see if there is someone waiting for map registers. 01557 */ 01558 while (!IsListEmpty(&MasterAdapter->AdapterQueue)) 01559 { 01560 ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue); 01561 AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue); 01562 01563 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, 01564 AdapterObject->NumberOfMapRegisters, 01565 0); 01566 if (Index == MAXULONG) 01567 { 01568 InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry); 01569 break; 01570 } 01571 01572 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01573 01574 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; 01575 if (!AdapterObject->ScatterGather) 01576 { 01577 AdapterObject->MapRegisterBase = 01578 (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); 01579 } 01580 01581 Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject, 01582 AdapterObject->CurrentWcb->CurrentIrp, 01583 AdapterObject->MapRegisterBase, 01584 AdapterObject->CurrentWcb->DeviceContext); 01585 switch (Result) 01586 { 01587 case DeallocateObjectKeepRegisters: 01588 AdapterObject->NumberOfMapRegisters = 0; 01589 /* fall through */ 01590 01591 case DeallocateObject: 01592 if (AdapterObject->NumberOfMapRegisters) 01593 { 01594 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); 01595 RtlClearBits(MasterAdapter->MapRegisters, 01596 (ULONG)(AdapterObject->MapRegisterBase - 01597 MasterAdapter->MapRegisterBase), 01598 AdapterObject->NumberOfMapRegisters); 01599 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01600 } 01601 01602 IoFreeAdapterChannel(AdapterObject); 01603 break; 01604 01605 default: 01606 break; 01607 } 01608 01609 KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); 01610 } 01611 01612 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); 01613 } 01614 01622 VOID 01623 NTAPI 01624 HalpCopyBufferMap(IN PMDL Mdl, 01625 IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, 01626 IN PVOID CurrentVa, 01627 IN ULONG Length, 01628 IN BOOLEAN WriteToDevice) 01629 { 01630 ULONG CurrentLength; 01631 ULONG_PTR CurrentAddress; 01632 ULONG ByteOffset; 01633 PVOID VirtualAddress; 01634 01635 VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority); 01636 if (!VirtualAddress) 01637 { 01638 /* 01639 * NOTE: On real NT a mechanism with reserved pages is implemented 01640 * to handle this case in a slow, but graceful non-fatal way. 01641 */ 01642 KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0); 01643 } 01644 01645 CurrentAddress = (ULONG_PTR)VirtualAddress + 01646 (ULONG_PTR)CurrentVa - 01647 (ULONG_PTR)MmGetMdlVirtualAddress(Mdl); 01648 01649 while (Length > 0) 01650 { 01651 ByteOffset = BYTE_OFFSET(CurrentAddress); 01652 CurrentLength = PAGE_SIZE - ByteOffset; 01653 if (CurrentLength > Length) CurrentLength = Length; 01654 01655 if (WriteToDevice) 01656 { 01657 RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), 01658 (PVOID)CurrentAddress, 01659 CurrentLength); 01660 } 01661 else 01662 { 01663 RtlCopyMemory((PVOID)CurrentAddress, 01664 (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), 01665 CurrentLength); 01666 } 01667 01668 Length -= CurrentLength; 01669 CurrentAddress += CurrentLength; 01670 MapRegisterBase++; 01671 } 01672 } 01673 01705 BOOLEAN 01706 NTAPI 01707 IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, 01708 IN PMDL Mdl, 01709 IN PVOID MapRegisterBase, 01710 IN PVOID CurrentVa, 01711 IN ULONG Length, 01712 IN BOOLEAN WriteToDevice) 01713 { 01714 BOOLEAN SlaveDma = FALSE; 01715 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; 01716 PHYSICAL_ADDRESS HighestAcceptableAddress; 01717 PHYSICAL_ADDRESS PhysicalAddress; 01718 PPFN_NUMBER MdlPagesPtr; 01719 01720 /* Sanity checks */ 01721 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); 01722 ASSERT(AdapterObject); 01723 01724 if (!AdapterObject->MasterDevice) 01725 { 01726 /* Mask out (disable) the DMA channel. */ 01727 if (AdapterObject->AdapterNumber == 1) 01728 { 01729 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; 01730 WRITE_PORT_UCHAR(&DmaControl1->SingleMask, 01731 AdapterObject->ChannelNumber | DMA_SETMASK); 01732 } 01733 else 01734 { 01735 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; 01736 WRITE_PORT_UCHAR(&DmaControl2->SingleMask, 01737 AdapterObject->ChannelNumber | DMA_SETMASK); 01738 } 01739 SlaveDma = TRUE; 01740 } 01741 01742 /* This can happen if the device supports hardware scatter/gather. */ 01743 if (MapRegisterBase == NULL) return TRUE; 01744 01745 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); 01746 01747 if (!WriteToDevice) 01748 { 01749 if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) 01750 { 01751 if (RealMapRegisterBase->Counter != MAXULONG) 01752 { 01753 if ((SlaveDma) && !(AdapterObject->IgnoreCount)) 01754 { 01755 Length -= HalReadDmaCounter(AdapterObject); 01756 } 01757 } 01758 HalpCopyBufferMap(Mdl, 01759 RealMapRegisterBase, 01760 CurrentVa, 01761 Length, 01762 FALSE); 01763 } 01764 else 01765 { 01766 MdlPagesPtr = MmGetMdlPfnArray(Mdl); 01767 MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; 01768 01769 PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; 01770 PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa); 01771 01772 HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); 01773 if ((PhysicalAddress.QuadPart + Length) > HighestAcceptableAddress.QuadPart) 01774 { 01775 HalpCopyBufferMap(Mdl, 01776 RealMapRegisterBase, 01777 CurrentVa, 01778 Length, 01779 FALSE); 01780 } 01781 } 01782 } 01783 01784 RealMapRegisterBase->Counter = 0; 01785 01786 return TRUE; 01787 } 01788 01820 PHYSICAL_ADDRESS 01821 NTAPI 01822 IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, 01823 IN PMDL Mdl, 01824 IN PVOID MapRegisterBase, 01825 IN PVOID CurrentVa, 01826 IN OUT PULONG Length, 01827 IN BOOLEAN WriteToDevice) 01828 { 01829 PPFN_NUMBER MdlPagesPtr; 01830 PFN_NUMBER MdlPage1, MdlPage2; 01831 ULONG ByteOffset; 01832 ULONG TransferOffset; 01833 ULONG TransferLength; 01834 BOOLEAN UseMapRegisters; 01835 PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; 01836 PHYSICAL_ADDRESS PhysicalAddress; 01837 PHYSICAL_ADDRESS HighestAcceptableAddress; 01838 ULONG Counter; 01839 DMA_MODE AdapterMode; 01840 KIRQL OldIrql; 01841 01842 /* 01843 * Precalculate some values that are used in all cases. 01844 * 01845 * ByteOffset is offset inside the page at which the transfer starts. 01846 * MdlPagesPtr is pointer inside the MDL page chain at the page where the 01847 * transfer start. 01848 * PhysicalAddress is physical address corresponding to the transfer 01849 * start page and offset. 01850 * TransferLength is the inital length of the transfer, which is reminder 01851 * of the first page. The actual value is calculated below. 01852 * 01853 * Note that all the variables can change during the processing which 01854 * takes place below. These are just initial values. 01855 */ 01856 ByteOffset = BYTE_OFFSET(CurrentVa); 01857 01858 MdlPagesPtr = MmGetMdlPfnArray(Mdl); 01859 MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; 01860 01861 PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; 01862 PhysicalAddress.QuadPart += ByteOffset; 01863 01864 TransferLength = PAGE_SIZE - ByteOffset; 01865 01866 /* 01867 * Special case for bus master adapters with S/G support. We can directly 01868 * use the buffer specified by the MDL, so not much work has to be done. 01869 * 01870 * Just return the passed VA's corresponding physical address and update 01871 * length to the number of physically contiguous bytes found. Also 01872 * pages crossing the 4Gb boundary aren't considered physically contiguous. 01873 */ 01874 if (MapRegisterBase == NULL) 01875 { 01876 while (TransferLength < *Length) 01877 { 01878 MdlPage1 = *MdlPagesPtr; 01879 MdlPage2 = *(MdlPagesPtr + 1); 01880 if (MdlPage1 + 1 != MdlPage2) break; 01881 if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break; 01882 TransferLength += PAGE_SIZE; 01883 MdlPagesPtr++; 01884 } 01885 01886 if (TransferLength < *Length) *Length = TransferLength; 01887 01888 return PhysicalAddress; 01889 } 01890 01891 /* 01892 * The code below applies to slave DMA adapters and bus master adapters 01893 * without hardward S/G support. 01894 */ 01895 RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); 01896 01897 /* 01898 * Try to calculate the size of the transfer. We can only transfer 01899 * pages that are physically contiguous and that don't cross the 01900 * 64Kb boundary (this limitation applies only for ISA controllers). 01901 */ 01902 while (TransferLength < *Length) 01903 { 01904 MdlPage1 = *MdlPagesPtr; 01905 MdlPage2 = *(MdlPagesPtr + 1); 01906 if (MdlPage1 + 1 != MdlPage2) break; 01907 if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break; 01908 TransferLength += PAGE_SIZE; 01909 MdlPagesPtr++; 01910 } 01911 01912 if (TransferLength > *Length) TransferLength = *Length; 01913 01914 /* 01915 * If we're about to simulate software S/G and not all the pages are 01916 * physically contiguous then we must use the map registers to store 01917 * the data and allow the whole transfer to proceed at once. 01918 */ 01919 if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length)) 01920 { 01921 UseMapRegisters = TRUE; 01922 PhysicalAddress = RealMapRegisterBase->PhysicalAddress; 01923 PhysicalAddress.QuadPart += ByteOffset; 01924 TransferLength = *Length; 01925 RealMapRegisterBase->Counter = MAXULONG; 01926 Counter = 0; 01927 } 01928 else 01929 { 01930 /* 01931 * This is ordinary DMA transfer, so just update the progress 01932 * counters. These are used by IoFlushAdapterBuffers to track 01933 * the transfer progress. 01934 */ 01935 UseMapRegisters = FALSE; 01936 Counter = RealMapRegisterBase->Counter; 01937 RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength); 01938 01939 /* 01940 * Check if the buffer doesn't exceed the highest physical address 01941 * limit of the device. In that case we must use the map registers to 01942 * store the data. 01943 */ 01944 HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); 01945 if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart) 01946 { 01947 UseMapRegisters = TRUE; 01948 PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress; 01949 PhysicalAddress.QuadPart += ByteOffset; 01950 if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) 01951 { 01952 RealMapRegisterBase->Counter = MAXULONG; 01953 Counter = 0; 01954 } 01955 } 01956 } 01957 01958 /* 01959 * If we decided to use the map registers (see above) and we're about 01960 * to transfer data to the device then copy the buffers into the map 01961 * register memory. 01962 */ 01963 if ((UseMapRegisters) && (WriteToDevice)) 01964 { 01965 HalpCopyBufferMap(Mdl, 01966 RealMapRegisterBase + Counter, 01967 CurrentVa, 01968 TransferLength, 01969 WriteToDevice); 01970 } 01971 01972 /* 01973 * Return the length of transfer that actually takes place. 01974 */ 01975 *Length = TransferLength; 01976 01977 /* 01978 * If we're doing slave (system) DMA then program the (E)ISA controller 01979 * to actually start the transfer. 01980 */ 01981 if ((AdapterObject) && !(AdapterObject->MasterDevice)) 01982 { 01983 AdapterMode = AdapterObject->AdapterMode; 01984 01985 if (WriteToDevice) 01986 { 01987 AdapterMode.TransferType = WRITE_TRANSFER; 01988 } 01989 else 01990 { 01991 AdapterMode.TransferType = READ_TRANSFER; 01992 if (AdapterObject->IgnoreCount) 01993 { 01994 RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset, 01995 TransferLength); 01996 } 01997 } 01998 01999 TransferOffset = PhysicalAddress.LowPart & 0xFFFF; 02000 if (AdapterObject->Width16Bits) 02001 { 02002 TransferLength >>= 1; 02003 TransferOffset >>= 1; 02004 } 02005 02006 KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); 02007 02008 if (AdapterObject->AdapterNumber == 1) 02009 { 02010 PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; 02011 02012 /* Reset Register */ 02013 WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); 02014 02015 /* Set the Mode */ 02016 WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte); 02017 02018 /* Set the Offset Register */ 02019 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 02020 (UCHAR)(TransferOffset)); 02021 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 02022 (UCHAR)(TransferOffset >> 8)); 02023 02024 /* Set the Page Register */ 02025 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), 02026 (UCHAR)(PhysicalAddress.LowPart >> 16)); 02027 if (HalpEisaDma) 02028 { 02029 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), 02030 0); 02031 } 02032 02033 /* Set the Length */ 02034 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, 02035 (UCHAR)(TransferLength - 1)); 02036 WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, 02037 (UCHAR)((TransferLength - 1) >> 8)); 02038 02039 /* Unmask the Channel */ 02040 WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); 02041 } 02042 else 02043 { 02044 PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; 02045 02046 /* Reset Register */ 02047 WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); 02048 02049 /* Set the Mode */ 02050 WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte); 02051 02052 /* Set the Offset Register */ 02053 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 02054 (UCHAR)(TransferOffset)); 02055 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 02056 (UCHAR)(TransferOffset >> 8)); 02057 02058 /* Set the Page Register */ 02059 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), 02060 (UCHAR)(PhysicalAddress.u.LowPart >> 16)); 02061 if (HalpEisaDma) 02062 { 02063 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), 02064 0); 02065 } 02066 02067 /* Set the Length */ 02068 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, 02069 (UCHAR)(TransferLength - 1)); 02070 WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, 02071 (UCHAR)((TransferLength - 1) >> 8)); 02072 02073 /* Unmask the Channel */ 02074 WRITE_PORT_UCHAR(&DmaControl2->SingleMask, 02075 AdapterObject->ChannelNumber | DMA_CLEARMASK); 02076 } 02077 02078 KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); 02079 } 02080 02081 /* 02082 * Return physical address of the buffer with data that is used for the 02083 * transfer. It can either point inside the Mdl that was passed by the 02084 * caller or into the map registers if the Mdl buffer can't be used 02085 * directly. 02086 */ 02087 return PhysicalAddress; 02088 } 02089 #endif 02090 02096 BOOLEAN 02097 NTAPI 02098 HalFlushCommonBuffer(IN PADAPTER_OBJECT AdapterObject, 02099 IN ULONG Length, 02100 IN PHYSICAL_ADDRESS LogicalAddress, 02101 IN PVOID VirtualAddress) 02102 { 02103 /* Function always returns true */ 02104 return TRUE; 02105 } 02106 02107 /* 02108 * @implemented 02109 */ 02110 PVOID 02111 NTAPI 02112 HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject, 02113 IN OUT PULONG NumberOfMapRegisters) 02114 { 02115 PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter; 02116 ULONG MapRegisterNumber; 02117 02118 /* Check if it needs map registers */ 02119 if (AdapterObject->NeedsMapRegisters) 02120 { 02121 /* Check if we have enough */ 02122 if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) 02123 { 02124 /* We don't, fail */ 02125 AdapterObject->NumberOfMapRegisters = 0; 02126 return NULL; 02127 } 02128 02129 /* Try to find free map registers */ 02130 MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, 02131 *NumberOfMapRegisters, 02132 0); 02133 02134 /* Check if nothing was found */ 02135 if (MapRegisterNumber == MAXULONG) 02136 { 02137 /* No free registers found, so use the base registers */ 02138 RtlSetBits(MasterAdapter->MapRegisters, 02139 0, 02140 *NumberOfMapRegisters); 02141 MapRegisterNumber = 0; 02142 } 02143 02144 /* Calculate the new base */ 02145 AdapterObject->MapRegisterBase = 02146 (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase + 02147 MapRegisterNumber); 02148 02149 /* Check if scatter gather isn't supported */ 02150 if (!AdapterObject->ScatterGather) 02151 { 02152 /* Set the flag */ 02153 AdapterObject->MapRegisterBase = 02154 (PROS_MAP_REGISTER_ENTRY) 02155 ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); 02156 } 02157 } 02158 else 02159 { 02160 AdapterObject->MapRegisterBase = NULL; 02161 AdapterObject->NumberOfMapRegisters = 0; 02162 } 02163 02164 /* Return the base */ 02165 return AdapterObject->MapRegisterBase; 02166 } 02167 02168 /* EOF */ Generated on Sat May 26 2012 04:26:35 for ReactOS by
1.7.6.1
|