From da2a2649db836790a963ce57d3c7905174259c0b Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sun, 31 Jan 2010 20:35:06 +0000 Subject: [PATCH] [FORMATTING] - Reformat dma.c, no code change. svn path=/trunk/; revision=45363 --- reactos/hal/halx86/generic/dma.c | 2935 +++++++++++++++--------------- 1 file changed, 1442 insertions(+), 1493 deletions(-) diff --git a/reactos/hal/halx86/generic/dma.c b/reactos/hal/halx86/generic/dma.c index 498fa340570..0b7b7f34827 100644 --- a/reactos/hal/halx86/generic/dma.c +++ b/reactos/hal/halx86/generic/dma.c @@ -121,40 +121,38 @@ static DMA_OPERATIONS HalpDmaOperations = { VOID HalpInitDma(VOID) { - /* - * Initialize the DMA Operation table - */ - HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel; - HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers; - HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel; - HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters; - HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer; - - /* - * Check if Extended DMA is available. We're just going to do a random - * read and write. - */ - - WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A); - if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A) - HalpEisaDma = TRUE; - - /* - * Intialize all the global variables and allocate master adapter with - * first map buffers. - */ - - InitializeListHead(&HalpDmaAdapterList); - KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE); - - HalpMasterAdapter = HalpDmaAllocateMasterAdapter(); - - /* - * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's - * used by IoGetDmaAdapter in the kernel. - */ - - HalGetDmaAdapter = HalpGetDmaAdapter; + /* + * Initialize the DMA Operation table + */ + HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel; + HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers; + HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel; + HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters; + HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer; + + /* + * Check if Extended DMA is available. We're just going to do a random + * read and write. + */ + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A); + if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A) + { + HalpEisaDma = TRUE; + } + + /* + * Intialize all the global variables and allocate master adapter with + * first map buffers. + */ + InitializeListHead(&HalpDmaAdapterList); + KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE); + HalpMasterAdapter = HalpDmaAllocateMasterAdapter(); + + /* + * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's + * used by IoGetDmaAdapter in the kernel. + */ + HalGetDmaAdapter = HalpGetDmaAdapter; } /** @@ -163,29 +161,28 @@ HalpInitDma(VOID) * Get the maximum physical address acceptable by the device represented * by the passed DMA adapter. */ - -PHYSICAL_ADDRESS NTAPI -HalpGetAdapterMaximumPhysicalAddress( - IN PADAPTER_OBJECT AdapterObject) +PHYSICAL_ADDRESS +NTAPI +HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject) { - PHYSICAL_ADDRESS HighestAddress; - - if (AdapterObject->MasterDevice) - { - if (AdapterObject->Dma64BitAddresses) - { - HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL; - return HighestAddress; - } - else if (AdapterObject->Dma32BitAddresses) - { - HighestAddress.QuadPart = 0xFFFFFFFF; - return HighestAddress; - } - } - - HighestAddress.QuadPart = 0xFFFFFF; - return HighestAddress; + PHYSICAL_ADDRESS HighestAddress; + + if (AdapterObject->MasterDevice) + { + if (AdapterObject->Dma64BitAddresses) + { + HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL; + return HighestAddress; + } + else if (AdapterObject->Dma32BitAddresses) + { + HighestAddress.QuadPart = 0xFFFFFFFF; + return HighestAddress; + } + } + + HighestAddress.QuadPart = 0xFFFFFF; + return HighestAddress; } /** @@ -199,125 +196,115 @@ HalpGetAdapterMaximumPhysicalAddress( * Size of the map buffers to allocate (not including the size * already allocated). */ - -BOOLEAN NTAPI -HalpGrowMapBuffers( - IN PADAPTER_OBJECT AdapterObject, - IN ULONG SizeOfMapBuffers) +BOOLEAN +NTAPI +HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject, + IN ULONG SizeOfMapBuffers) { - PVOID VirtualAddress; - PHYSICAL_ADDRESS PhysicalAddress; - PHYSICAL_ADDRESS HighestAcceptableAddress; - PHYSICAL_ADDRESS LowestAcceptableAddress; - PHYSICAL_ADDRESS BoundryAddressMultiple; - KIRQL OldIrql; - ULONG MapRegisterCount; - - /* FIXME: Check if enough map register slots are available. */ - - MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers); - - /* - * Allocate memory for the new map registers. For 32-bit adapters we use - * two passes in order not to waste scare resource (low memory). - */ - - HighestAcceptableAddress = - HalpGetAdapterMaximumPhysicalAddress(AdapterObject); - LowestAcceptableAddress.HighPart = 0; - LowestAcceptableAddress.LowPart = - HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0; - BoundryAddressMultiple.QuadPart = 0; - - VirtualAddress = MmAllocateContiguousMemorySpecifyCache( - MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress, - HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached); - - if (VirtualAddress == NULL && LowestAcceptableAddress.LowPart != 0) - { - LowestAcceptableAddress.LowPart = 0; - VirtualAddress = MmAllocateContiguousMemorySpecifyCache( - MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress, - HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached); - } - - if (VirtualAddress == NULL) - return FALSE; - - PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); - - /* - * All the following must be done with the master adapter lock held - * to prevent corruption. - */ - - KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); - - /* - * Setup map register entries for the buffer allocated. Each entry has - * a virtual and physical address and corresponds to PAGE_SIZE large - * buffer. - */ - - if (MapRegisterCount > 0) - { - PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry; - - CurrentEntry = AdapterObject->MapRegisterBase + - AdapterObject->NumberOfMapRegisters; - do - { - /* - * Leave one entry free for every non-contiguous memory region - * in the map register bitmap. This ensures that we can search - * using RtlFindClearBits for contiguous map register regions. - * - * Also for non-EISA DMA leave one free entry for every 64Kb - * break, because the DMA controller can handle only coniguous - * 64Kb regions. - */ - - if (CurrentEntry != AdapterObject->MapRegisterBase) - { - PreviousEntry = CurrentEntry - 1; - if (PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE == - PhysicalAddress.LowPart) - { - if (!HalpEisaDma) - { - if ((PreviousEntry->PhysicalAddress.LowPart ^ - PhysicalAddress.LowPart) & 0xFFFF0000) - { - CurrentEntry++; - AdapterObject->NumberOfMapRegisters++; - } - } - } - else + PVOID VirtualAddress; + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS HighestAcceptableAddress; + PHYSICAL_ADDRESS LowestAcceptableAddress; + PHYSICAL_ADDRESS BoundryAddressMultiple; + KIRQL OldIrql; + ULONG MapRegisterCount; + + /* FIXME: Check if enough map register slots are available. */ + MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers); + + /* + * Allocate memory for the new map registers. For 32-bit adapters we use + * two passes in order not to waste scare resource (low memory). + */ + HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); + LowestAcceptableAddress.HighPart = 0; + LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0; + BoundryAddressMultiple.QuadPart = 0; + + VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT, + LowestAcceptableAddress, + HighestAcceptableAddress, + BoundryAddressMultiple, + MmNonCached); + if (!(VirtualAddress) && (LowestAcceptableAddress.LowPart)) + { + LowestAcceptableAddress.LowPart = 0; + VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT, + LowestAcceptableAddress, + HighestAcceptableAddress, + BoundryAddressMultiple, + MmNonCached); + } + + if (!VirtualAddress) return FALSE; + + PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); + + /* + * All the following must be done with the master adapter lock held + * to prevent corruption. + */ + KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); + + /* + * Setup map register entries for the buffer allocated. Each entry has + * a virtual and physical address and corresponds to PAGE_SIZE large + * buffer. + */ + if (MapRegisterCount > 0) + { + PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry; + + CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters; + do + { + /* + * Leave one entry free for every non-contiguous memory region + * in the map register bitmap. This ensures that we can search + * using RtlFindClearBits for contiguous map register regions. + * + * Also for non-EISA DMA leave one free entry for every 64Kb + * break, because the DMA controller can handle only coniguous + * 64Kb regions. + */ + if (CurrentEntry != AdapterObject->MapRegisterBase) { - CurrentEntry++; - AdapterObject->NumberOfMapRegisters++; + PreviousEntry = CurrentEntry - 1; + if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart) + { + if (!HalpEisaDma) + { + if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000) + { + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + } + } + } + else + { + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + } } - } - RtlClearBit(AdapterObject->MapRegisters, - CurrentEntry - AdapterObject->MapRegisterBase); - CurrentEntry->VirtualAddress = VirtualAddress; - CurrentEntry->PhysicalAddress = PhysicalAddress; + RtlClearBit(AdapterObject->MapRegisters, + CurrentEntry - AdapterObject->MapRegisterBase); + CurrentEntry->VirtualAddress = VirtualAddress; + CurrentEntry->PhysicalAddress = PhysicalAddress; - PhysicalAddress.LowPart += PAGE_SIZE; - VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); + PhysicalAddress.LowPart += PAGE_SIZE; + VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); - CurrentEntry++; - AdapterObject->NumberOfMapRegisters++; - MapRegisterCount--; - } - while (MapRegisterCount != 0); - } + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + MapRegisterCount--; + } while (MapRegisterCount); + } - KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); + KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); - return TRUE; + return TRUE; } /** @@ -328,55 +315,53 @@ HalpGrowMapBuffers( * * @see HalpInitDma */ - -PADAPTER_OBJECT NTAPI +PADAPTER_OBJECT +NTAPI HalpDmaAllocateMasterAdapter(VOID) { - PADAPTER_OBJECT MasterAdapter; - ULONG Size, SizeOfBitmap; - - SizeOfBitmap = MAX_MAP_REGISTERS; - Size = sizeof(ADAPTER_OBJECT); - Size += sizeof(RTL_BITMAP); - Size += (SizeOfBitmap + 7) >> 3; - - MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA); - if (MasterAdapter == NULL) - return NULL; - - RtlZeroMemory(MasterAdapter, Size); - - KeInitializeSpinLock(&MasterAdapter->SpinLock); - InitializeListHead(&MasterAdapter->AdapterQueue); - - MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1); - RtlInitializeBitMap( - MasterAdapter->MapRegisters, - (PULONG)(MasterAdapter->MapRegisters + 1), - SizeOfBitmap); - RtlSetAllBits(MasterAdapter->MapRegisters); - MasterAdapter->NumberOfMapRegisters = 0; - MasterAdapter->CommittedMapRegisters = 0; - - MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag( - NonPagedPool, - SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY), - TAG_DMA); - if (MasterAdapter->MapRegisterBase == NULL) - { - ExFreePool(MasterAdapter); - return NULL; - } - - RtlZeroMemory(MasterAdapter->MapRegisterBase, - SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY)); - if (!HalpGrowMapBuffers(MasterAdapter, 0x10000)) - { - ExFreePool(MasterAdapter); - return NULL; - } - - return MasterAdapter; + PADAPTER_OBJECT MasterAdapter; + ULONG Size, SizeOfBitmap; + + SizeOfBitmap = MAX_MAP_REGISTERS; + Size = sizeof(ADAPTER_OBJECT); + Size += sizeof(RTL_BITMAP); + Size += (SizeOfBitmap + 7) >> 3; + + MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA); + if (!MasterAdapter) return NULL; + + RtlZeroMemory(MasterAdapter, Size); + + KeInitializeSpinLock(&MasterAdapter->SpinLock); + InitializeListHead(&MasterAdapter->AdapterQueue); + + MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1); + RtlInitializeBitMap(MasterAdapter->MapRegisters, + (PULONG)(MasterAdapter->MapRegisters + 1), + SizeOfBitmap); + RtlSetAllBits(MasterAdapter->MapRegisters); + MasterAdapter->NumberOfMapRegisters = 0; + MasterAdapter->CommittedMapRegisters = 0; + + MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool, + SizeOfBitmap * + sizeof(ROS_MAP_REGISTER_ENTRY), + TAG_DMA); + if (!MasterAdapter->MapRegisterBase) + { + ExFreePool(MasterAdapter); + return NULL; + } + + RtlZeroMemory(MasterAdapter->MapRegisterBase, + SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY)); + if (!HalpGrowMapBuffers(MasterAdapter, 0x10000)) + { + ExFreePool(MasterAdapter); + return NULL; + } + + return MasterAdapter; } /** @@ -387,69 +372,61 @@ HalpDmaAllocateMasterAdapter(VOID) * * @see HalGetAdapter */ - -PADAPTER_OBJECT NTAPI -HalpDmaAllocateChildAdapter( - ULONG NumberOfMapRegisters, - PDEVICE_DESCRIPTION DeviceDescription) +PADAPTER_OBJECT +NTAPI +HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters, + IN PDEVICE_DESCRIPTION DeviceDescription) { - PADAPTER_OBJECT AdapterObject; - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - HANDLE Handle; - - InitializeObjectAttributes( - &ObjectAttributes, - NULL, - OBJ_KERNEL_HANDLE | OBJ_PERMANENT, - NULL, - NULL); - - Status = ObCreateObject( - KernelMode, - IoAdapterObjectType, - &ObjectAttributes, - KernelMode, - NULL, - sizeof(ADAPTER_OBJECT), - 0, - 0, - (PVOID)&AdapterObject); - if (!NT_SUCCESS(Status)) - return NULL; - - Status = ObReferenceObjectByPointer( - AdapterObject, - FILE_READ_DATA | FILE_WRITE_DATA, - IoAdapterObjectType, - KernelMode); - if (!NT_SUCCESS(Status)) - return NULL; - - RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT)); - - Status = ObInsertObject( - AdapterObject, - NULL, - FILE_READ_DATA | FILE_WRITE_DATA, - 0, - NULL, - &Handle); - if (!NT_SUCCESS(Status)) - return NULL; - - ZwClose(Handle); - - AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version; - AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT); - AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations; - AdapterObject->MapRegistersPerChannel = 1; - AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; - AdapterObject->ChannelNumber = 0xFF; - AdapterObject->MasterAdapter = HalpMasterAdapter; - KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue); - - return AdapterObject; + PADAPTER_OBJECT AdapterObject; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE Handle; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + OBJ_KERNEL_HANDLE | OBJ_PERMANENT, + NULL, + NULL); + + Status = ObCreateObject(KernelMode, + IoAdapterObjectType, + &ObjectAttributes, + KernelMode, + NULL, + sizeof(ADAPTER_OBJECT), + 0, + 0, + (PVOID)&AdapterObject); + if (!NT_SUCCESS(Status)) return NULL; + + Status = ObReferenceObjectByPointer(AdapterObject, + FILE_READ_DATA | FILE_WRITE_DATA, + IoAdapterObjectType, + KernelMode); + if (!NT_SUCCESS(Status)) return NULL; + + RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT)); + + Status = ObInsertObject(AdapterObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + &Handle); + if (!NT_SUCCESS(Status)) return NULL; + + ZwClose(Handle); + + AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version; + AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT); + AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations; + AdapterObject->MapRegistersPerChannel = 1; + AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; + AdapterObject->ChannelNumber = 0xFF; + AdapterObject->MasterAdapter = HalpMasterAdapter; + KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue); + + return AdapterObject; } /** @@ -457,119 +434,134 @@ HalpDmaAllocateChildAdapter( * * Setup DMA modes and extended modes for (E)ISA DMA adapter object. */ - -BOOLEAN NTAPI -HalpDmaInitializeEisaAdapter( - PADAPTER_OBJECT AdapterObject, - PDEVICE_DESCRIPTION DeviceDescription) +BOOLEAN +NTAPI +HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject, + IN PDEVICE_DESCRIPTION DeviceDescription) { - UCHAR Controller; - DMA_MODE DmaMode = {{0 }}; - DMA_EXTENDED_MODE ExtendedMode = {{ 0 }}; - PVOID AdapterBaseVa; - - Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1; - - if (Controller == 1) - AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1); - else - AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2); - - AdapterObject->AdapterNumber = Controller; - AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3); - AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel]; - AdapterObject->Width16Bits = FALSE; - AdapterObject->AdapterBaseVa = AdapterBaseVa; - - if (HalpEisaDma) - { - ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber; - - switch (DeviceDescription->DmaSpeed) - { - case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break; - case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break; - case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break; - case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break; - default: - return FALSE; - } - - switch (DeviceDescription->DmaWidth) - { - case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break; - case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break; - case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break; - default: - return FALSE; - } - - if (Controller == 1) - WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1), - ExtendedMode.Byte); - else - WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2), - ExtendedMode.Byte); - } - else - { - /* - * Validate setup for non-busmaster DMA adapter. Secondary controller - * supports only 16-bit transfers and main controller supports only - * 8-bit transfers. Anything else is invalid. - */ - - if (!DeviceDescription->Master) - { - if (Controller == 2 && DeviceDescription->DmaWidth == Width16Bits) - AdapterObject->Width16Bits = TRUE; - else if (Controller != 1 || DeviceDescription->DmaWidth != Width8Bits) - return FALSE; - } - } - - DmaMode.Channel = AdapterObject->ChannelNumber; - DmaMode.AutoInitialize = DeviceDescription->AutoInitialize; - - /* - * Set the DMA request mode. - * - * For (E)ISA bus master devices just unmask (enable) the DMA channel - * and set it to cascade mode. Otherwise just select the right one - * bases on the passed device description. - */ - - if (DeviceDescription->Master) - { - DmaMode.RequestMode = CASCADE_REQUEST_MODE; - if (Controller == 1) - { - /* Set the Request Data */ - WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, - DmaMode.Byte); - /* Unmask DMA Channel */ - WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask, - AdapterObject->ChannelNumber | DMA_CLEARMASK); - } else { - /* Set the Request Data */ - WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, - DmaMode.Byte); - /* Unmask DMA Channel */ - WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask, - AdapterObject->ChannelNumber | DMA_CLEARMASK); - } - } - else - { - if (DeviceDescription->DemandMode) - DmaMode.RequestMode = DEMAND_REQUEST_MODE; - else - DmaMode.RequestMode = SINGLE_REQUEST_MODE; - } - - AdapterObject->AdapterMode = DmaMode; - - return TRUE; + UCHAR Controller; + DMA_MODE DmaMode = {{0 }}; + DMA_EXTENDED_MODE ExtendedMode = {{ 0 }}; + PVOID AdapterBaseVa; + + Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1; + + if (Controller == 1) + { + AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1); + } + else + { + AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2); + } + + AdapterObject->AdapterNumber = Controller; + AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3); + AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel]; + AdapterObject->Width16Bits = FALSE; + AdapterObject->AdapterBaseVa = AdapterBaseVa; + + if (HalpEisaDma) + { + ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber; + + switch (DeviceDescription->DmaSpeed) + { + case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break; + case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break; + case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break; + case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break; + default: + return FALSE; + } + + switch (DeviceDescription->DmaWidth) + { + case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break; + case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break; + case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break; + default: + return FALSE; + } + + if (Controller == 1) + { + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1), + ExtendedMode.Byte); + } + else + { + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2), + ExtendedMode.Byte); + } + } + else + { + /* + * Validate setup for non-busmaster DMA adapter. Secondary controller + * supports only 16-bit transfers and main controller supports only + * 8-bit transfers. Anything else is invalid. + */ + if (!DeviceDescription->Master) + { + if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits)) + { + AdapterObject->Width16Bits = TRUE; + } + else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits)) + { + return FALSE; + } + } + } + + DmaMode.Channel = AdapterObject->ChannelNumber; + DmaMode.AutoInitialize = DeviceDescription->AutoInitialize; + + /* + * Set the DMA request mode. + * + * For (E)ISA bus master devices just unmask (enable) the DMA channel + * and set it to cascade mode. Otherwise just select the right one + * bases on the passed device description. + */ + if (DeviceDescription->Master) + { + DmaMode.RequestMode = CASCADE_REQUEST_MODE; + if (Controller == 1) + { + /* Set the Request Data */ + WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte); + + /* Unmask DMA Channel */ + WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask, + AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + else + { + /* Set the Request Data */ + WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte); + + /* Unmask DMA Channel */ + WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask, + AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + } + else + { + if (DeviceDescription->DemandMode) + { + DmaMode.RequestMode = DEMAND_REQUEST_MODE; + } + else + { + DmaMode.RequestMode = SINGLE_REQUEST_MODE; + } + } + + AdapterObject->AdapterMode = DmaMode; + + return TRUE; } /** @@ -587,195 +579,193 @@ HalpDmaInitializeEisaAdapter( * * @implemented */ - -PADAPTER_OBJECT NTAPI -HalGetAdapter( - PDEVICE_DESCRIPTION DeviceDescription, - PULONG NumberOfMapRegisters) +PADAPTER_OBJECT +NTAPI +HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription, + OUT PULONG NumberOfMapRegisters) { - PADAPTER_OBJECT AdapterObject = NULL; - PADAPTER_OBJECT MasterAdapter; - BOOLEAN EisaAdapter; - ULONG MapRegisters; - ULONG MaximumLength; - - /* Validate parameters in device description */ - if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) - return NULL; - - /* - * See if we're going to use ISA/EISA DMA adapter. These adapters are - * special since they're reused. - * - * Also note that we check for channel number since there are only 8 DMA - * channels on ISA, so any request above this requires new adapter. - */ - - if (DeviceDescription->InterfaceType == Isa || !DeviceDescription->Master) - { - if (DeviceDescription->InterfaceType == Isa && - DeviceDescription->DmaChannel >= 8) - EisaAdapter = FALSE; - else - EisaAdapter = TRUE; - } - else - { - EisaAdapter = FALSE; - } - - /* - * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used - * for cascading the controllers and it's not available for software use. - */ - - if (EisaAdapter && DeviceDescription->DmaChannel == 4) - return NULL; - - /* - * Calculate the number of map registers. - * - * - For EISA and PCI scatter/gather no map registers are needed. - * - For ISA slave scatter/gather one map register is needed. - * - For all other cases the number of map registers depends on - * DeviceDescription->MaximumLength. - */ - - MaximumLength = DeviceDescription->MaximumLength & MAXLONG; - if (DeviceDescription->ScatterGather && - (DeviceDescription->InterfaceType == Eisa || - DeviceDescription->InterfaceType == PCIBus)) - { - MapRegisters = 0; - } - else if (DeviceDescription->ScatterGather && - !DeviceDescription->Master) - { - MapRegisters = 1; - } - else - { - /* - * In the equation below the additional map register added by - * the "+1" accounts for the case when a transfer does not start - * at a page-aligned address. - */ - MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1; - if (MapRegisters > 16) - MapRegisters = 16; - } - - /* - * Acquire the DMA lock that is used to protect adapter lists and - * EISA adapter array. - */ - - KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, - FALSE, NULL); - - /* - * Now we must get ahold of the adapter object. For first eight ISA/EISA - * channels there are static adapter objects that are reused and updated - * on succesive HalGetAdapter calls. In other cases a new adapter object - * is always created and it's to the DMA adapter list (HalpDmaAdapterList). - */ - - if (EisaAdapter) - { - AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel]; - if (AdapterObject != NULL) - { - if (AdapterObject->NeedsMapRegisters && - MapRegisters > AdapterObject->MapRegistersPerChannel) + PADAPTER_OBJECT AdapterObject = NULL; + PADAPTER_OBJECT MasterAdapter; + BOOLEAN EisaAdapter; + ULONG MapRegisters; + ULONG MaximumLength; + + /* Validate parameters in device description */ + if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) return NULL; + + /* + * See if we're going to use ISA/EISA DMA adapter. These adapters are + * special since they're reused. + * + * Also note that we check for channel number since there are only 8 DMA + * channels on ISA, so any request above this requires new adapter. + */ + if ((DeviceDescription->InterfaceType == Isa) || !(DeviceDescription->Master)) + { + if ((DeviceDescription->InterfaceType == Isa) && (DeviceDescription->DmaChannel >= 8)) + { + EisaAdapter = FALSE; + } + else + { + EisaAdapter = TRUE; + } + } + else + { + EisaAdapter = FALSE; + } + + /* + * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used + * for cascading the controllers and it's not available for software use. + */ + if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL; + + /* + * Calculate the number of map registers. + * + * - For EISA and PCI scatter/gather no map registers are needed. + * - For ISA slave scatter/gather one map register is needed. + * - For all other cases the number of map registers depends on + * DeviceDescription->MaximumLength. + */ + MaximumLength = DeviceDescription->MaximumLength & MAXLONG; + if ((DeviceDescription->ScatterGather) && + ((DeviceDescription->InterfaceType == Eisa) || + (DeviceDescription->InterfaceType == PCIBus))) + { + MapRegisters = 0; + } + else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master)) + { + MapRegisters = 1; + } + else + { + /* + * In the equation below the additional map register added by + * the "+1" accounts for the case when a transfer does not start + * at a page-aligned address. + */ + MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1; + if (MapRegisters > 16) MapRegisters = 16; + } + + /* + * Acquire the DMA lock that is used to protect adapter lists and + * EISA adapter array. + */ + KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); + + /* + * Now we must get ahold of the adapter object. For first eight ISA/EISA + * channels there are static adapter objects that are reused and updated + * on succesive HalGetAdapter calls. In other cases a new adapter object + * is always created and it's to the DMA adapter list (HalpDmaAdapterList). + */ + if (EisaAdapter) + { + AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel]; + if (AdapterObject) + { + if ((AdapterObject->NeedsMapRegisters) && + (MapRegisters > AdapterObject->MapRegistersPerChannel)) + { + AdapterObject->MapRegistersPerChannel = MapRegisters; + } + } + } + + if (AdapterObject == NULL) + { + AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription); + if (AdapterObject == NULL) + { + KeSetEvent(&HalpDmaLock, 0, 0); + return NULL; + } + + if (EisaAdapter) + { + HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject; + } + + if (MapRegisters > 0) + { + AdapterObject->NeedsMapRegisters = TRUE; + MasterAdapter = HalpMasterAdapter; AdapterObject->MapRegistersPerChannel = MapRegisters; - } - } - - if (AdapterObject == NULL) - { - AdapterObject = HalpDmaAllocateChildAdapter( - MapRegisters, DeviceDescription); - if (AdapterObject == NULL) - { - KeSetEvent(&HalpDmaLock, 0, 0); - return NULL; - } - - if (EisaAdapter) - { - HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject; - } - - if (MapRegisters > 0) - { - AdapterObject->NeedsMapRegisters = TRUE; - MasterAdapter = HalpMasterAdapter; - AdapterObject->MapRegistersPerChannel = MapRegisters; - - /* - * FIXME: Verify that the following makes sense. Actually - * MasterAdapter->NumberOfMapRegisters contains even the number - * of gaps, so this will not work correctly all the time. It - * doesn't matter much since it's only optimization to avoid - * queuing work items in HalAllocateAdapterChannel. - */ - - MasterAdapter->CommittedMapRegisters += MapRegisters; - if (MasterAdapter->CommittedMapRegisters > MasterAdapter->NumberOfMapRegisters) - HalpGrowMapBuffers(MasterAdapter, 0x10000); - } - else - { - AdapterObject->NeedsMapRegisters = FALSE; - if (DeviceDescription->Master) - AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1; - else - AdapterObject->MapRegistersPerChannel = 1; - } - } - - if (!EisaAdapter) - InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList); - - /* - * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will - * no longer be touched, so we don't need it. - */ - - KeSetEvent(&HalpDmaLock, 0, 0); - - /* - * Setup the values in the adapter object that are common for all - * types of buses. - */ - - if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1) - AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount; - else - AdapterObject->IgnoreCount = 0; - - AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; - AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses; - AdapterObject->ScatterGather = DeviceDescription->ScatterGather; - AdapterObject->MasterDevice = DeviceDescription->Master; - *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel; - - /* - * For non-(E)ISA adapters we have already done all the work. On the - * other hand for (E)ISA adapters we must still setup the DMA modes - * and prepare the controller. - */ - - if (EisaAdapter) - { - if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription)) - { - ObDereferenceObject(AdapterObject); - return NULL; - } - } - - return AdapterObject; + + /* + * FIXME: Verify that the following makes sense. Actually + * MasterAdapter->NumberOfMapRegisters contains even the number + * of gaps, so this will not work correctly all the time. It + * doesn't matter much since it's only optimization to avoid + * queuing work items in HalAllocateAdapterChannel. + */ + MasterAdapter->CommittedMapRegisters += MapRegisters; + if (MasterAdapter->CommittedMapRegisters > MasterAdapter->NumberOfMapRegisters) + { + HalpGrowMapBuffers(MasterAdapter, 0x10000); + } + } + else + { + AdapterObject->NeedsMapRegisters = FALSE; + if (DeviceDescription->Master) + { + AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1; + } + else + { + AdapterObject->MapRegistersPerChannel = 1; + } + } + } + + if (!EisaAdapter) InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList); + + /* + * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will + * no longer be touched, so we don't need it. + */ + KeSetEvent(&HalpDmaLock, 0, 0); + + /* + * Setup the values in the adapter object that are common for all + * types of buses. + */ + if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1) + { + AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount; + } + else + { + AdapterObject->IgnoreCount = 0; + } + + AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; + AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses; + AdapterObject->ScatterGather = DeviceDescription->ScatterGather; + AdapterObject->MasterDevice = DeviceDescription->Master; + *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel; + + /* + * For non-(E)ISA adapters we have already done all the work. On the + * other hand for (E)ISA adapters we must still setup the DMA modes + * and prepare the controller. + */ + if (EisaAdapter) + { + if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription)) + { + ObDereferenceObject(AdapterObject); + return NULL; + } + } + + return AdapterObject; } /** @@ -786,14 +776,13 @@ HalGetAdapter( * * @see HalGetAdapter */ - -PDMA_ADAPTER NTAPI -HalpGetDmaAdapter( - IN PVOID Context, - IN PDEVICE_DESCRIPTION DeviceDescription, - OUT PULONG NumberOfMapRegisters) +PDMA_ADAPTER +NTAPI +HalpGetDmaAdapter(IN PVOID Context, + IN PDEVICE_DESCRIPTION DeviceDescription, + OUT PULONG NumberOfMapRegisters) { - return &HalGetAdapter(DeviceDescription, NumberOfMapRegisters)->DmaHeader; + return &HalGetAdapter(DeviceDescription, NumberOfMapRegisters)->DmaHeader; } /** @@ -804,20 +793,18 @@ HalpGetDmaAdapter( * * @see HalGetAdapter */ - -VOID NTAPI -HalPutDmaAdapter( - PADAPTER_OBJECT AdapterObject) +VOID +NTAPI +HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject) { - if (AdapterObject->ChannelNumber == 0xFF) - { - KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, - FALSE, NULL); - RemoveEntryList(&AdapterObject->AdapterList); - KeSetEvent(&HalpDmaLock, 0, 0); - } - - ObDereferenceObject(AdapterObject); + if (AdapterObject->ChannelNumber == 0xFF) + { + KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); + RemoveEntryList(&AdapterObject->AdapterList); + KeSetEvent(&HalpDmaLock, 0, 0); + } + + ObDereferenceObject(AdapterObject); } /** @@ -845,44 +832,47 @@ HalPutDmaAdapter( * * @implemented */ - -PVOID NTAPI -HalAllocateCommonBuffer( - PADAPTER_OBJECT AdapterObject, - ULONG Length, - PPHYSICAL_ADDRESS LogicalAddress, - BOOLEAN CacheEnabled) +PVOID +NTAPI +HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PPHYSICAL_ADDRESS LogicalAddress, + IN BOOLEAN CacheEnabled) { - PHYSICAL_ADDRESS LowestAcceptableAddress; - PHYSICAL_ADDRESS HighestAcceptableAddress; - PHYSICAL_ADDRESS BoundryAddressMultiple; - PVOID VirtualAddress; - - LowestAcceptableAddress.QuadPart = 0; - HighestAcceptableAddress = - HalpGetAdapterMaximumPhysicalAddress(AdapterObject); - BoundryAddressMultiple.QuadPart = 0; - - /* - * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For - * slave DMA devices the 64Kb boundary mustn't be crossed since the - * controller wouldn't be able to handle it. - */ - - if (AdapterObject->MasterDevice) - BoundryAddressMultiple.HighPart = 1; - else - BoundryAddressMultiple.LowPart = 0x10000; - - VirtualAddress = MmAllocateContiguousMemorySpecifyCache( - Length, LowestAcceptableAddress, HighestAcceptableAddress, - BoundryAddressMultiple, CacheEnabled ? MmCached : MmNonCached); - if (VirtualAddress == NULL) - return NULL; - - *LogicalAddress = MmGetPhysicalAddress(VirtualAddress); - - return VirtualAddress; + PHYSICAL_ADDRESS LowestAcceptableAddress; + PHYSICAL_ADDRESS HighestAcceptableAddress; + PHYSICAL_ADDRESS BoundryAddressMultiple; + PVOID VirtualAddress; + + LowestAcceptableAddress.QuadPart = 0; + HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); + BoundryAddressMultiple.QuadPart = 0; + + /* + * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For + * slave DMA devices the 64Kb boundary mustn't be crossed since the + * controller wouldn't be able to handle it. + */ + if (AdapterObject->MasterDevice) + { + BoundryAddressMultiple.HighPart = 1; + } + else + { + BoundryAddressMultiple.LowPart = 0x10000; + } + + VirtualAddress = MmAllocateContiguousMemorySpecifyCache(Length, + LowestAcceptableAddress, + HighestAcceptableAddress, + BoundryAddressMultiple, + CacheEnabled ? MmCached : + MmNonCached); + if (VirtualAddress == NULL) return NULL; + + *LogicalAddress = MmGetPhysicalAddress(VirtualAddress); + + return VirtualAddress; } /** @@ -894,18 +884,17 @@ HalAllocateCommonBuffer( * * @implemented */ - -VOID NTAPI -HalFreeCommonBuffer( - PADAPTER_OBJECT AdapterObject, - ULONG Length, - PHYSICAL_ADDRESS LogicalAddress, - PVOID VirtualAddress, - BOOLEAN CacheEnabled) +VOID +NTAPI +HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PHYSICAL_ADDRESS LogicalAddress, + IN PVOID VirtualAddress, + IN BOOLEAN CacheEnabled) { - MmFreeContiguousMemorySpecifyCache(VirtualAddress, - Length, - CacheEnabled ? MmCached : MmNonCached); + MmFreeContiguousMemorySpecifyCache(VirtualAddress, + Length, + CacheEnabled ? MmCached : MmNonCached); } /** @@ -916,12 +905,11 @@ HalFreeCommonBuffer( * * @see HalGetAdapter */ - -ULONG NTAPI -HalpDmaGetDmaAlignment( - PADAPTER_OBJECT AdapterObject) +ULONG +NTAPI +HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject) { - return 1; + return 1; } /* @@ -931,70 +919,69 @@ HalpDmaGetDmaAlignment( * * @implemented */ - -ULONG NTAPI -HalReadDmaCounter( - PADAPTER_OBJECT AdapterObject) +ULONG +NTAPI +HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject) { - KIRQL OldIrql; - ULONG Count, OldCount; - - ASSERT(!AdapterObject->MasterDevice); - - /* - * Acquire the master adapter lock since we're going to mess with the - * system DMA controller registers and we really don't want anyone - * to do the same at the same time. - */ - - KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); - - /* Send the request to the specific controller. */ - if (AdapterObject->AdapterNumber == 1) - { - PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; - - Count = 0xffff00; - do - { - OldCount = Count; - /* Send Reset */ - WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); - /* Read Count */ - Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount - [AdapterObject->ChannelNumber].DmaBaseCount); - Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount - [AdapterObject->ChannelNumber].DmaBaseCount) << 8; - } - while (0xffff00 & (OldCount ^ Count)); - } - else - { - PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; - - Count = 0xffff00; - do - { - OldCount = Count; - /* Send Reset */ - WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); - /* Read Count */ - Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount - [AdapterObject->ChannelNumber].DmaBaseCount); - Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount - [AdapterObject->ChannelNumber].DmaBaseCount) << 8; - } - while (0xffff00 & (OldCount ^ Count)); - } - - KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); - - Count++; - Count &= 0xffff; - if (AdapterObject->Width16Bits) - Count *= 2; - - return Count; + KIRQL OldIrql; + ULONG Count, OldCount; + + ASSERT(!AdapterObject->MasterDevice); + + /* + * Acquire the master adapter lock since we're going to mess with the + * system DMA controller registers and we really don't want anyone + * to do the same at the same time. + */ + KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); + + /* Send the request to the specific controller. */ + if (AdapterObject->AdapterNumber == 1) + { + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; + + Count = 0xffff00; + do + { + OldCount = Count; + + /* Send Reset */ + WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); + + /* Read Count */ + Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount + [AdapterObject->ChannelNumber].DmaBaseCount); + Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount + [AdapterObject->ChannelNumber].DmaBaseCount) << 8; + } while (0xffff00 & (OldCount ^ Count)); + } + else + { + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; + + Count = 0xffff00; + do + { + OldCount = Count; + + /* Send Reset */ + WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); + + /* Read Count */ + Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount + [AdapterObject->ChannelNumber].DmaBaseCount); + Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount + [AdapterObject->ChannelNumber].DmaBaseCount) << 8; + } while (0xffff00 & (OldCount ^ Count)); + } + + KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); + + Count++; + Count &= 0xffff; + if (AdapterObject->Width16Bits) Count *= 2; + + return Count; } /** @@ -1003,42 +990,39 @@ HalReadDmaCounter( * Helper routine of HalAllocateAdapterChannel for allocating map registers * at PASSIVE_LEVEL in work item. */ - -VOID NTAPI -HalpGrowMapBufferWorker(PVOID DeferredContext) +VOID +NTAPI +HalpGrowMapBufferWorker(IN PVOID DeferredContext) { - PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext; - KIRQL OldIrql; - BOOLEAN Succeeded; - - /* - * Try to allocate new map registers for the adapter. - * - * NOTE: The NT implementation actually tries to allocate more map - * registers than needed as an optimization. - */ - - KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, - FALSE, NULL); - Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter, - WorkItem->NumberOfMapRegisters); - KeSetEvent(&HalpDmaLock, 0, 0); - - if (Succeeded) - { - /* - * Flush the adapter queue now that new map registers are ready. The - * easiest way to do that is to call IoFreeMapRegisters to not free - * any registers. Note that we use the magic (PVOID)2 map register - * base to bypass the parameter checking. - */ - - OldIrql = KfRaiseIrql(DISPATCH_LEVEL); - IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0); - KfLowerIrql(OldIrql); - } - - ExFreePool(WorkItem); + PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext; + KIRQL OldIrql; + BOOLEAN Succeeded; + + /* + * Try to allocate new map registers for the adapter. + * + * NOTE: The NT implementation actually tries to allocate more map + * registers than needed as an optimization. + */ + KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL); + Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter, + WorkItem->NumberOfMapRegisters); + KeSetEvent(&HalpDmaLock, 0, 0); + + if (Succeeded) + { + /* + * Flush the adapter queue now that new map registers are ready. The + * easiest way to do that is to call IoFreeMapRegisters to not free + * any registers. Note that we use the magic (PVOID)2 map register + * base to bypass the parameter checking. + */ + OldIrql = KfRaiseIrql(DISPATCH_LEVEL); + IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0); + KfLowerIrql(OldIrql); + } + + ExFreePool(WorkItem); } /** @@ -1065,157 +1049,154 @@ HalpGrowMapBufferWorker(PVOID DeferredContext) * * @implemented */ - -NTSTATUS NTAPI -HalAllocateAdapterChannel( - PADAPTER_OBJECT AdapterObject, - PWAIT_CONTEXT_BLOCK WaitContextBlock, - ULONG NumberOfMapRegisters, - PDRIVER_CONTROL ExecutionRoutine) +NTSTATUS +NTAPI +HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, + IN PWAIT_CONTEXT_BLOCK WaitContextBlock, + IN ULONG NumberOfMapRegisters, + IN PDRIVER_CONTROL ExecutionRoutine) { - PADAPTER_OBJECT MasterAdapter; - PGROW_WORK_ITEM WorkItem; - ULONG Index = MAXULONG; - ULONG Result; - KIRQL OldIrql; - - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - - /* Set up the wait context block in case we can't run right away. */ - WaitContextBlock->DeviceRoutine = ExecutionRoutine; - WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters; - - /* Returns true if queued, else returns false and sets the queue to busy */ - if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry)) - return STATUS_SUCCESS; - - MasterAdapter = AdapterObject->MasterAdapter; - - AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters; - AdapterObject->CurrentWcb = WaitContextBlock; - - if (NumberOfMapRegisters && AdapterObject->NeedsMapRegisters) - { - if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) - { - AdapterObject->NumberOfMapRegisters = 0; - IoFreeAdapterChannel(AdapterObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* - * Get the map registers. This is partly complicated by the fact - * that new map registers can only be allocated at PASSIVE_LEVEL - * and we're currently at DISPATCH_LEVEL. The following code has - * two code paths: - * - * - If there is no adapter queued for map register allocation, - * try to see if enough contiguous map registers are present. - * In case they're we can just get them and proceed further. - * - * - If some adapter is already present in the queue we must - * respect the order of adapters asking for map registers and - * so the fast case described above can't take place. - * This case is also entered if not enough coniguous map - * registers are present. - * - * A work queue item is allocated and queued, the adapter is - * also queued into the master adapter queue. The worker - * routine does the job of allocating the map registers at - * PASSIVE_LEVEL and calling the ExecutionRoutine. - */ - - KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); - - if (IsListEmpty(&MasterAdapter->AdapterQueue)) - { - Index = RtlFindClearBitsAndSet( - MasterAdapter->MapRegisters, NumberOfMapRegisters, 0); - if (Index != MAXULONG) - { - AdapterObject->MapRegisterBase = - MasterAdapter->MapRegisterBase + Index; - if (!AdapterObject->ScatterGather) - { - AdapterObject->MapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)( - (ULONG_PTR)AdapterObject->MapRegisterBase | - MAP_BASE_SW_SG); - } - } - } - - if (Index == MAXULONG) - { - WorkItem = ExAllocatePoolWithTag( - NonPagedPool, sizeof(GROW_WORK_ITEM), TAG_DMA); - if (WorkItem == NULL) - { - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + PADAPTER_OBJECT MasterAdapter; + PGROW_WORK_ITEM WorkItem; + ULONG Index = MAXULONG; + ULONG Result; + KIRQL OldIrql; + + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Set up the wait context block in case we can't run right away. */ + WaitContextBlock->DeviceRoutine = ExecutionRoutine; + WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters; + + /* Returns true if queued, else returns false and sets the queue to busy */ + if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, + &WaitContextBlock->WaitQueueEntry)) + { + return STATUS_SUCCESS; + } + + MasterAdapter = AdapterObject->MasterAdapter; + + AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters; + AdapterObject->CurrentWcb = WaitContextBlock; + + if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters)) + { + if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) + { AdapterObject->NumberOfMapRegisters = 0; IoFreeAdapterChannel(AdapterObject); return STATUS_INSUFFICIENT_RESOURCES; - } - - InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); - - ExInitializeWorkItem( - &WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem); - WorkItem->AdapterObject = AdapterObject; - WorkItem->NumberOfMapRegisters = NumberOfMapRegisters; - - ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue); - - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - - return STATUS_SUCCESS; - } - - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - } - else - { - AdapterObject->MapRegisterBase = NULL; - AdapterObject->NumberOfMapRegisters = 0; - } - - AdapterObject->CurrentWcb = WaitContextBlock; - - Result = ExecutionRoutine( - WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp, - AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext); - - /* - * Possible return values: - * - * - KeepObject - * Don't free any resources, the ADAPTER_OBJECT is still in use and - * the caller will call IoFreeAdapterChannel later. - * - * - DeallocateObject - * Deallocate the map registers and release the ADAPTER_OBJECT, so - * someone else can use it. - * - * - DeallocateObjectKeepRegisters - * Release the ADAPTER_OBJECT, but hang on to the map registers. The - * client will later call IoFreeMapRegisters. - * - * NOTE: - * IoFreeAdapterChannel runs the queue, so it must be called unless - * the adapter object is not to be freed. - */ - - if (Result == DeallocateObject) - { - IoFreeAdapterChannel(AdapterObject); - } - else if (Result == DeallocateObjectKeepRegisters) - { - AdapterObject->NumberOfMapRegisters = 0; - IoFreeAdapterChannel(AdapterObject); - } - - return STATUS_SUCCESS; + } + + /* + * Get the map registers. This is partly complicated by the fact + * that new map registers can only be allocated at PASSIVE_LEVEL + * and we're currently at DISPATCH_LEVEL. The following code has + * two code paths: + * + * - If there is no adapter queued for map register allocation, + * try to see if enough contiguous map registers are present. + * In case they're we can just get them and proceed further. + * + * - If some adapter is already present in the queue we must + * respect the order of adapters asking for map registers and + * so the fast case described above can't take place. + * This case is also entered if not enough coniguous map + * registers are present. + * + * A work queue item is allocated and queued, the adapter is + * also queued into the master adapter queue. The worker + * routine does the job of allocating the map registers at + * PASSIVE_LEVEL and calling the ExecutionRoutine. + */ + + KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); + + if (IsListEmpty(&MasterAdapter->AdapterQueue)) + { + Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0); + if (Index != MAXULONG) + { + AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; + if (!AdapterObject->ScatterGather) + { + AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); + } + } + } + + if (Index == MAXULONG) + { + WorkItem = ExAllocatePoolWithTag(NonPagedPool, + sizeof(GROW_WORK_ITEM), + TAG_DMA); + if (!WorkItem) + { + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); + + ExInitializeWorkItem(&WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem); + WorkItem->AdapterObject = AdapterObject; + WorkItem->NumberOfMapRegisters = NumberOfMapRegisters; + + ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue); + + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + + return STATUS_SUCCESS; + } + + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + } + else + { + AdapterObject->MapRegisterBase = NULL; + AdapterObject->NumberOfMapRegisters = 0; + } + + AdapterObject->CurrentWcb = WaitContextBlock; + + Result = ExecutionRoutine(WaitContextBlock->DeviceObject, + WaitContextBlock->CurrentIrp, + AdapterObject->MapRegisterBase, + WaitContextBlock->DeviceContext); + + /* + * Possible return values: + * + * - KeepObject + * Don't free any resources, the ADAPTER_OBJECT is still in use and + * the caller will call IoFreeAdapterChannel later. + * + * - DeallocateObject + * Deallocate the map registers and release the ADAPTER_OBJECT, so + * someone else can use it. + * + * - DeallocateObjectKeepRegisters + * Release the ADAPTER_OBJECT, but hang on to the map registers. The + * client will later call IoFreeMapRegisters. + * + * NOTE: + * IoFreeAdapterChannel runs the queue, so it must be called unless + * the adapter object is not to be freed. + */ + if (Result == DeallocateObject) + { + IoFreeAdapterChannel(AdapterObject); + } + else if (Result == DeallocateObjectKeepRegisters) + { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + } + + return STATUS_SUCCESS; } /** @@ -1236,114 +1217,103 @@ HalAllocateAdapterChannel( * * @implemented */ - -VOID NTAPI -IoFreeAdapterChannel( - PADAPTER_OBJECT AdapterObject) +VOID +NTAPI +IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject) { - PADAPTER_OBJECT MasterAdapter; - PKDEVICE_QUEUE_ENTRY DeviceQueueEntry; - PWAIT_CONTEXT_BLOCK WaitContextBlock; - ULONG Index = MAXULONG; - ULONG Result; - KIRQL OldIrql; - - MasterAdapter = AdapterObject->MasterAdapter; - - for (;;) - { - /* - * To keep map registers, call here with AdapterObject-> - * NumberOfMapRegisters set to zero. This trick is used in - * HalAllocateAdapterChannel for example. - */ - if (AdapterObject->NumberOfMapRegisters) - { - IoFreeMapRegisters( - AdapterObject, - AdapterObject->MapRegisterBase, - AdapterObject->NumberOfMapRegisters); - } - - DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue); - if (DeviceQueueEntry == NULL) - { - break; - } - - WaitContextBlock = CONTAINING_RECORD( - DeviceQueueEntry, - WAIT_CONTEXT_BLOCK, - WaitQueueEntry); - - AdapterObject->CurrentWcb = WaitContextBlock; - AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters; - - if (WaitContextBlock->NumberOfMapRegisters && - AdapterObject->MasterAdapter) - { - KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); - - if (IsListEmpty(&MasterAdapter->AdapterQueue)) - { - Index = RtlFindClearBitsAndSet( - MasterAdapter->MapRegisters, - WaitContextBlock->NumberOfMapRegisters, 0); - if (Index != MAXULONG) + PADAPTER_OBJECT MasterAdapter; + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry; + PWAIT_CONTEXT_BLOCK WaitContextBlock; + ULONG Index = MAXULONG; + ULONG Result; + KIRQL OldIrql; + + MasterAdapter = AdapterObject->MasterAdapter; + + for (;;) + { + /* + * To keep map registers, call here with AdapterObject-> + * NumberOfMapRegisters set to zero. This trick is used in + * HalAllocateAdapterChannel for example. + */ + if (AdapterObject->NumberOfMapRegisters) + { + IoFreeMapRegisters(AdapterObject, + AdapterObject->MapRegisterBase, + AdapterObject->NumberOfMapRegisters); + } + + DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue); + if (!DeviceQueueEntry) break; + + WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry, + WAIT_CONTEXT_BLOCK, + WaitQueueEntry); + + AdapterObject->CurrentWcb = WaitContextBlock; + AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters; + + if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter)) + { + KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); + + if (IsListEmpty(&MasterAdapter->AdapterQueue)) { - AdapterObject->MapRegisterBase = - MasterAdapter->MapRegisterBase + Index; - if (!AdapterObject->ScatterGather) - { - AdapterObject->MapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)( - (ULONG_PTR)AdapterObject->MapRegisterBase | - MAP_BASE_SW_SG); - } + Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, + WaitContextBlock->NumberOfMapRegisters, + 0); + if (Index != MAXULONG) + { + AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; + if (!AdapterObject->ScatterGather) + { + AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); + } + } } - } - if (Index == MAXULONG) - { - InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - break; - } - - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - } - else - { - AdapterObject->MapRegisterBase = NULL; - AdapterObject->NumberOfMapRegisters = 0; - } - - /* Call the adapter control routine. */ - Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)( - WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp, - AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext); - - switch (Result) - { - case KeepObject: - /* - * We're done until the caller manually calls IoFreeAdapterChannel - * or IoFreeMapRegisters. - */ - return; + if (Index == MAXULONG) + { + InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue); + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + break; + } - case DeallocateObjectKeepRegisters: - /* - * Hide the map registers so they aren't deallocated next time - * around. - */ + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + } + else + { + AdapterObject->MapRegisterBase = NULL; AdapterObject->NumberOfMapRegisters = 0; - break; + } - default: - break; - } - } + /* Call the adapter control routine. */ + Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject, + WaitContextBlock->CurrentIrp, + AdapterObject->MapRegisterBase, + WaitContextBlock->DeviceContext); + switch (Result) + { + case KeepObject: + /* + * We're done until the caller manually calls IoFreeAdapterChannel + * or IoFreeMapRegisters. + */ + return; + + case DeallocateObjectKeepRegisters: + /* + * Hide the map registers so they aren't deallocated next time + * around. + */ + AdapterObject->NumberOfMapRegisters = 0; + break; + + default: + break; + } + } } /** @@ -1360,103 +1330,93 @@ IoFreeAdapterChannel( * * @implemented */ - -VOID NTAPI -IoFreeMapRegisters( - IN PADAPTER_OBJECT AdapterObject, - IN PVOID MapRegisterBase, - IN ULONG NumberOfMapRegisters) +VOID +NTAPI +IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject, + IN PVOID MapRegisterBase, + IN ULONG NumberOfMapRegisters) { - PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter; - PLIST_ENTRY ListEntry; - KIRQL OldIrql; - ULONG Index; - ULONG Result; - - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - - if (MasterAdapter == NULL || MapRegisterBase == NULL) - return; - - KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); - - if (NumberOfMapRegisters != 0) - { - PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; - - RealMapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); - RtlClearBits(MasterAdapter->MapRegisters, - RealMapRegisterBase - MasterAdapter->MapRegisterBase, - NumberOfMapRegisters); - } - - /* - * Now that we freed few map registers it's time to look at the master - * adapter queue and see if there is someone waiting for map registers. - */ - - while (!IsListEmpty(&MasterAdapter->AdapterQueue)) - { - ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue); - AdapterObject = CONTAINING_RECORD( - ListEntry, struct _ADAPTER_OBJECT, AdapterQueue); - - Index = RtlFindClearBitsAndSet( - MasterAdapter->MapRegisters, - AdapterObject->NumberOfMapRegisters, - MasterAdapter->NumberOfMapRegisters); - if (Index == MAXULONG) - { - InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry); - break; - } - - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - - AdapterObject->MapRegisterBase = - MasterAdapter->MapRegisterBase + Index; - if (!AdapterObject->ScatterGather) - { - AdapterObject->MapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)( - (ULONG_PTR)AdapterObject->MapRegisterBase | - MAP_BASE_SW_SG); - } - - Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)( - AdapterObject->CurrentWcb->DeviceObject, - AdapterObject->CurrentWcb->CurrentIrp, - AdapterObject->MapRegisterBase, - AdapterObject->CurrentWcb->DeviceContext); - - switch (Result) - { - case DeallocateObjectKeepRegisters: - AdapterObject->NumberOfMapRegisters = 0; - /* fall through */ + PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter; + PLIST_ENTRY ListEntry; + KIRQL OldIrql; + ULONG Index; + ULONG Result; - case DeallocateObject: - if (AdapterObject->NumberOfMapRegisters) - { - KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); - RtlClearBits(MasterAdapter->MapRegisters, - AdapterObject->MapRegisterBase - - MasterAdapter->MapRegisterBase, - AdapterObject->NumberOfMapRegisters); - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); - } - IoFreeAdapterChannel(AdapterObject); - break; + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - default: + if (!(MasterAdapter) || !(MapRegisterBase)) return; + + KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); + + if (NumberOfMapRegisters != 0) + { + PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; + + RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); + RtlClearBits(MasterAdapter->MapRegisters, + RealMapRegisterBase - MasterAdapter->MapRegisterBase, + NumberOfMapRegisters); + } + + /* + * Now that we freed few map registers it's time to look at the master + * adapter queue and see if there is someone waiting for map registers. + */ + while (!IsListEmpty(&MasterAdapter->AdapterQueue)) + { + ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue); + AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue); + + Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, + AdapterObject->NumberOfMapRegisters, + MasterAdapter->NumberOfMapRegisters); + if (Index == MAXULONG) + { + InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry); break; - } + } + + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + + AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index; + if (!AdapterObject->ScatterGather) + { + AdapterObject->MapRegisterBase = + (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG); + } - KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); - } + Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject, + AdapterObject->CurrentWcb->CurrentIrp, + AdapterObject->MapRegisterBase, + AdapterObject->CurrentWcb->DeviceContext); + switch (Result) + { + case DeallocateObjectKeepRegisters: + AdapterObject->NumberOfMapRegisters = 0; + /* fall through */ + + case DeallocateObject: + if (AdapterObject->NumberOfMapRegisters) + { + KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); + RtlClearBits(MasterAdapter->MapRegisters, + AdapterObject->MapRegisterBase - + MasterAdapter->MapRegisterBase, + AdapterObject->NumberOfMapRegisters); + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + } + + IoFreeAdapterChannel(AdapterObject); + break; + + default: + break; + } - KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); + KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql); + } + + KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql); } /** @@ -1466,60 +1426,56 @@ IoFreeMapRegisters( * * @see IoFlushAdapterBuffers, IoMapTransfer */ - -VOID NTAPI -HalpCopyBufferMap( - PMDL Mdl, - PROS_MAP_REGISTER_ENTRY MapRegisterBase, - PVOID CurrentVa, - ULONG Length, - BOOLEAN WriteToDevice) +VOID +NTAPI +HalpCopyBufferMap(IN PMDL Mdl, + IN PROS_MAP_REGISTER_ENTRY MapRegisterBase, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice) { - ULONG CurrentLength; - ULONG_PTR CurrentAddress; - ULONG ByteOffset; - PVOID VirtualAddress; - - VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority); - if (VirtualAddress == NULL) - { - /* - * NOTE: On real NT a mechanism with reserved pages is implemented - * to handle this case in a slow, but graceful non-fatal way. - */ - KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0); - } - - CurrentAddress = (ULONG_PTR)VirtualAddress + - (ULONG_PTR)CurrentVa - - (ULONG_PTR)MmGetMdlVirtualAddress(Mdl); - - while (Length > 0) - { - ByteOffset = BYTE_OFFSET(CurrentAddress); - CurrentLength = PAGE_SIZE - ByteOffset; - if (CurrentLength > Length) - CurrentLength = Length; - - if (WriteToDevice) - { - RtlCopyMemory( - (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), - (PVOID)CurrentAddress, - CurrentLength); - } - else - { - RtlCopyMemory( - (PVOID)CurrentAddress, - (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), - CurrentLength); - } - - Length -= CurrentLength; - CurrentAddress += CurrentLength; - MapRegisterBase++; - } + ULONG CurrentLength; + ULONG_PTR CurrentAddress; + ULONG ByteOffset; + PVOID VirtualAddress; + + VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority); + if (!VirtualAddress) + { + /* + * NOTE: On real NT a mechanism with reserved pages is implemented + * to handle this case in a slow, but graceful non-fatal way. + */ + KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0); + } + + CurrentAddress = (ULONG_PTR)VirtualAddress + + (ULONG_PTR)CurrentVa - + (ULONG_PTR)MmGetMdlVirtualAddress(Mdl); + + while (Length > 0) + { + ByteOffset = BYTE_OFFSET(CurrentAddress); + CurrentLength = PAGE_SIZE - ByteOffset; + if (CurrentLength > Length) CurrentLength = Length; + + if (WriteToDevice) + { + RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), + (PVOID)CurrentAddress, + CurrentLength); + } + else + { + RtlCopyMemory((PVOID)CurrentAddress, + (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset), + CurrentLength); + } + + Length -= CurrentLength; + CurrentAddress += CurrentLength; + MapRegisterBase++; + } } /** @@ -1553,82 +1509,88 @@ HalpCopyBufferMap( * * @unimplemented. */ - -BOOLEAN NTAPI -IoFlushAdapterBuffers( - PADAPTER_OBJECT AdapterObject, - PMDL Mdl, - PVOID MapRegisterBase, - PVOID CurrentVa, - ULONG Length, - BOOLEAN WriteToDevice) +BOOLEAN +NTAPI +IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice) { - BOOLEAN SlaveDma = FALSE; - PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; - PHYSICAL_ADDRESS HighestAcceptableAddress; - PHYSICAL_ADDRESS PhysicalAddress; - PPFN_NUMBER MdlPagesPtr; - - /* Sanity checks */ - ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); - ASSERT(AdapterObject); - - if (!AdapterObject->MasterDevice) - { - /* Mask out (disable) the DMA channel. */ - if (AdapterObject->AdapterNumber == 1) - { - PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; - WRITE_PORT_UCHAR(&DmaControl1->SingleMask, - AdapterObject->ChannelNumber | DMA_SETMASK); - } - else - { - PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; - WRITE_PORT_UCHAR(&DmaControl2->SingleMask, - AdapterObject->ChannelNumber | DMA_SETMASK); - } - SlaveDma = TRUE; - } - - /* This can happen if the device supports hardware scatter/gather. */ - if (MapRegisterBase == NULL) - return TRUE; - - RealMapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); - - if (!WriteToDevice) - { - if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) - { - if (RealMapRegisterBase->Counter != MAXULONG) - { - if (SlaveDma && !AdapterObject->IgnoreCount) - Length -= HalReadDmaCounter(AdapterObject); - } - HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, FALSE); - } - else - { - MdlPagesPtr = MmGetMdlPfnArray(Mdl); - MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; - - PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; - PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa); - - HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); - if (PhysicalAddress.QuadPart + Length > - HighestAcceptableAddress.QuadPart) - { - HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, FALSE); - } - } - } - - RealMapRegisterBase->Counter = 0; - - return TRUE; + BOOLEAN SlaveDma = FALSE; + PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; + PHYSICAL_ADDRESS HighestAcceptableAddress; + PHYSICAL_ADDRESS PhysicalAddress; + PPFN_NUMBER MdlPagesPtr; + + /* Sanity checks */ + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + ASSERT(AdapterObject); + + if (!AdapterObject->MasterDevice) + { + /* Mask out (disable) the DMA channel. */ + if (AdapterObject->AdapterNumber == 1) + { + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; + WRITE_PORT_UCHAR(&DmaControl1->SingleMask, + AdapterObject->ChannelNumber | DMA_SETMASK); + } + else + { + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; + WRITE_PORT_UCHAR(&DmaControl2->SingleMask, + AdapterObject->ChannelNumber | DMA_SETMASK); + } + SlaveDma = TRUE; + } + + /* This can happen if the device supports hardware scatter/gather. */ + if (MapRegisterBase == NULL) return TRUE; + + RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); + + if (!WriteToDevice) + { + if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) + { + if (RealMapRegisterBase->Counter != MAXULONG) + { + if ((SlaveDma) && !(AdapterObject->IgnoreCount)) + { + Length -= HalReadDmaCounter(AdapterObject); + } + } + HalpCopyBufferMap(Mdl, + RealMapRegisterBase, + CurrentVa, + Length, + FALSE); + } + else + { + MdlPagesPtr = MmGetMdlPfnArray(Mdl); + MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; + + PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; + PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa); + + HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); + if ((PhysicalAddress.QuadPart + Length) > HighestAcceptableAddress.QuadPart) + { + HalpCopyBufferMap(Mdl, + RealMapRegisterBase, + CurrentVa, + Length, + FALSE); + } + } + } + + RealMapRegisterBase->Counter = 0; + + return TRUE; } /** @@ -1662,287 +1624,274 @@ IoFlushAdapterBuffers( * * @implemented */ - -PHYSICAL_ADDRESS NTAPI -IoMapTransfer( - IN PADAPTER_OBJECT AdapterObject, - IN PMDL Mdl, - IN PVOID MapRegisterBase, - IN PVOID CurrentVa, - IN OUT PULONG Length, - IN BOOLEAN WriteToDevice) +PHYSICAL_ADDRESS +NTAPI +IoMapTransfer(IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN OUT PULONG Length, + IN BOOLEAN WriteToDevice) { - PPFN_NUMBER MdlPagesPtr; - PFN_NUMBER MdlPage1, MdlPage2; - ULONG ByteOffset; - ULONG TransferOffset; - ULONG TransferLength; - BOOLEAN UseMapRegisters; - PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; - PHYSICAL_ADDRESS PhysicalAddress; - PHYSICAL_ADDRESS HighestAcceptableAddress; - ULONG Counter; - DMA_MODE AdapterMode; - KIRQL OldIrql; - - /* - * Precalculate some values that are used in all cases. - * - * ByteOffset is offset inside the page at which the transfer starts. - * MdlPagesPtr is pointer inside the MDL page chain at the page where the - * transfer start. - * PhysicalAddress is physical address corresponding to the transfer - * start page and offset. - * TransferLength is the inital length of the transfer, which is reminder - * of the first page. The actual value is calculated below. - * - * Note that all the variables can change during the processing which - * takes place below. These are just initial values. - */ - - ByteOffset = BYTE_OFFSET(CurrentVa); - - MdlPagesPtr = MmGetMdlPfnArray(Mdl); - MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; - - PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; - PhysicalAddress.QuadPart += ByteOffset; - - TransferLength = PAGE_SIZE - ByteOffset; - - /* - * Special case for bus master adapters with S/G support. We can directly - * use the buffer specified by the MDL, so not much work has to be done. - * - * Just return the passed VA's corresponding physical address and update - * length to the number of physically contiguous bytes found. Also - * pages crossing the 4Gb boundary aren't considered physically contiguous. - */ - - if (MapRegisterBase == NULL) - { - while (TransferLength < *Length) - { - MdlPage1 = *MdlPagesPtr; - MdlPage2 = *(MdlPagesPtr + 1); - if (MdlPage1 + 1 != MdlPage2) - break; - if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) - break; - TransferLength += PAGE_SIZE; - MdlPagesPtr++; - } - - if (TransferLength < *Length) - *Length = TransferLength; - - return PhysicalAddress; - } - - /* - * The code below applies to slave DMA adapters and bus master adapters - * without hardward S/G support. - */ - - RealMapRegisterBase = - (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); - - /* - * Try to calculate the size of the transfer. We can only transfer - * pages that are physically contiguous and that don't cross the - * 64Kb boundary (this limitation applies only for ISA controllers). - */ - - while (TransferLength < *Length) - { - MdlPage1 = *MdlPagesPtr; - MdlPage2 = *(MdlPagesPtr + 1); - if (MdlPage1 + 1 != MdlPage2) - break; - if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) - break; - TransferLength += PAGE_SIZE; - MdlPagesPtr++; - } - - if (TransferLength > *Length) - TransferLength = *Length; - - /* - * If we're about to simulate software S/G and not all the pages are - * physically contiguous then we must use the map registers to store - * the data and allow the whole transfer to proceed at once. - */ - - if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG && - TransferLength < *Length) - { - UseMapRegisters = TRUE; - PhysicalAddress = RealMapRegisterBase->PhysicalAddress; - PhysicalAddress.QuadPart += ByteOffset; - TransferLength = *Length; - RealMapRegisterBase->Counter = MAXULONG; - Counter = 0; - } - else - { - /* - * This is ordinary DMA transfer, so just update the progress - * counters. These are used by IoFlushAdapterBuffers to track - * the transfer progress. - */ - - UseMapRegisters = FALSE; - Counter = RealMapRegisterBase->Counter; - RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength); - - /* - * Check if the buffer doesn't exceed the highest physical address - * limit of the device. In that case we must use the map registers to - * store the data. - */ - - HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); - if (PhysicalAddress.QuadPart + TransferLength > - HighestAcceptableAddress.QuadPart) - { - UseMapRegisters = TRUE; - PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress; - PhysicalAddress.QuadPart += ByteOffset; - if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) - { - RealMapRegisterBase->Counter = MAXULONG; - Counter = 0; - } - } - } - - /* - * If we decided to use the map registers (see above) and we're about - * to transfer data to the device then copy the buffers into the map - * register memory. - */ - - if (UseMapRegisters && WriteToDevice) - { - HalpCopyBufferMap(Mdl, RealMapRegisterBase + Counter, - CurrentVa, TransferLength, WriteToDevice); - } - - /* - * Return the length of transfer that actually takes place. - */ - - *Length = TransferLength; - - /* - * If we're doing slave (system) DMA then program the (E)ISA controller - * to actually start the transfer. - */ - - if (AdapterObject != NULL && !AdapterObject->MasterDevice) - { - AdapterMode = AdapterObject->AdapterMode; - - if (WriteToDevice) - { - AdapterMode.TransferType = WRITE_TRANSFER; - } - else - { - AdapterMode.TransferType = READ_TRANSFER; - if (AdapterObject->IgnoreCount) - { - RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + - ByteOffset, TransferLength); - } - } - - TransferOffset = PhysicalAddress.LowPart & 0xFFFF; - if (AdapterObject->Width16Bits) - { - TransferLength >>= 1; - TransferOffset >>= 1; - } - - KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); - - if (AdapterObject->AdapterNumber == 1) - { - PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; - - /* Reset Register */ - WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); - /* Set the Mode */ - WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte); - /* Set the Offset Register */ - WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, - (UCHAR)(TransferOffset)); - WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, - (UCHAR)(TransferOffset >> 8)); - /* Set the Page Register */ - WRITE_PORT_UCHAR(AdapterObject->PagePort + - FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), - (UCHAR)(PhysicalAddress.LowPart >> 16)); - if (HalpEisaDma) - { - WRITE_PORT_UCHAR(AdapterObject->PagePort + - FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), - 0); - } - /* Set the Length */ - WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)(TransferLength - 1)); - WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((TransferLength - 1) >> 8)); - /* Unmask the Channel */ - WRITE_PORT_UCHAR(&DmaControl1->SingleMask, - AdapterObject->ChannelNumber | DMA_CLEARMASK); - } - else - { - PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; - - /* Reset Register */ - WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); - /* Set the Mode */ - WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte); - /* Set the Offset Register */ - WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, - (UCHAR)(TransferOffset)); - WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, - (UCHAR)(TransferOffset >> 8)); - /* Set the Page Register */ - WRITE_PORT_UCHAR(AdapterObject->PagePort + - FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), - (UCHAR)(PhysicalAddress.u.LowPart >> 16)); - if (HalpEisaDma) - { - WRITE_PORT_UCHAR(AdapterObject->PagePort + - FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), - 0); - } - /* Set the Length */ - WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)(TransferLength - 1)); - WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((TransferLength - 1) >> 8)); - /* Unmask the Channel */ - WRITE_PORT_UCHAR(&DmaControl2->SingleMask, - AdapterObject->ChannelNumber | DMA_CLEARMASK); - } - - KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); - } - - /* - * Return physical address of the buffer with data that is used for the - * transfer. It can either point inside the Mdl that was passed by the - * caller or into the map registers if the Mdl buffer can't be used - * directly. - */ - - return PhysicalAddress; + PPFN_NUMBER MdlPagesPtr; + PFN_NUMBER MdlPage1, MdlPage2; + ULONG ByteOffset; + ULONG TransferOffset; + ULONG TransferLength; + BOOLEAN UseMapRegisters; + PROS_MAP_REGISTER_ENTRY RealMapRegisterBase; + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS HighestAcceptableAddress; + ULONG Counter; + DMA_MODE AdapterMode; + KIRQL OldIrql; + + /* + * Precalculate some values that are used in all cases. + * + * ByteOffset is offset inside the page at which the transfer starts. + * MdlPagesPtr is pointer inside the MDL page chain at the page where the + * transfer start. + * PhysicalAddress is physical address corresponding to the transfer + * start page and offset. + * TransferLength is the inital length of the transfer, which is reminder + * of the first page. The actual value is calculated below. + * + * Note that all the variables can change during the processing which + * takes place below. These are just initial values. + */ + ByteOffset = BYTE_OFFSET(CurrentVa); + + MdlPagesPtr = MmGetMdlPfnArray(Mdl); + MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT; + + PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT; + PhysicalAddress.QuadPart += ByteOffset; + + TransferLength = PAGE_SIZE - ByteOffset; + + /* + * Special case for bus master adapters with S/G support. We can directly + * use the buffer specified by the MDL, so not much work has to be done. + * + * Just return the passed VA's corresponding physical address and update + * length to the number of physically contiguous bytes found. Also + * pages crossing the 4Gb boundary aren't considered physically contiguous. + */ + if (MapRegisterBase == NULL) + { + while (TransferLength < *Length) + { + MdlPage1 = *MdlPagesPtr; + MdlPage2 = *(MdlPagesPtr + 1); + if (MdlPage1 + 1 != MdlPage2) break; + if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break; + TransferLength += PAGE_SIZE; + MdlPagesPtr++; + } + + if (TransferLength < *Length) *Length = TransferLength; + + return PhysicalAddress; + } + + /* + * The code below applies to slave DMA adapters and bus master adapters + * without hardward S/G support. + */ + RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG); + + /* + * Try to calculate the size of the transfer. We can only transfer + * pages that are physically contiguous and that don't cross the + * 64Kb boundary (this limitation applies only for ISA controllers). + */ + while (TransferLength < *Length) + { + MdlPage1 = *MdlPagesPtr; + MdlPage2 = *(MdlPagesPtr + 1); + if (MdlPage1 + 1 != MdlPage2) break; + if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break; + TransferLength += PAGE_SIZE; + MdlPagesPtr++; + } + + if (TransferLength > *Length) TransferLength = *Length; + + /* + * If we're about to simulate software S/G and not all the pages are + * physically contiguous then we must use the map registers to store + * the data and allow the whole transfer to proceed at once. + */ + if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length)) + { + UseMapRegisters = TRUE; + PhysicalAddress = RealMapRegisterBase->PhysicalAddress; + PhysicalAddress.QuadPart += ByteOffset; + TransferLength = *Length; + RealMapRegisterBase->Counter = MAXULONG; + Counter = 0; + } + else + { + /* + * This is ordinary DMA transfer, so just update the progress + * counters. These are used by IoFlushAdapterBuffers to track + * the transfer progress. + */ + UseMapRegisters = FALSE; + Counter = RealMapRegisterBase->Counter; + RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength); + + /* + * Check if the buffer doesn't exceed the highest physical address + * limit of the device. In that case we must use the map registers to + * store the data. + */ + HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject); + if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart) + { + UseMapRegisters = TRUE; + PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress; + PhysicalAddress.QuadPart += ByteOffset; + if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) + { + RealMapRegisterBase->Counter = MAXULONG; + Counter = 0; + } + } + } + + /* + * If we decided to use the map registers (see above) and we're about + * to transfer data to the device then copy the buffers into the map + * register memory. + */ + if ((UseMapRegisters) && (WriteToDevice)) + { + HalpCopyBufferMap(Mdl, + RealMapRegisterBase + Counter, + CurrentVa, + TransferLength, + WriteToDevice); + } + + /* + * Return the length of transfer that actually takes place. + */ + *Length = TransferLength; + + /* + * If we're doing slave (system) DMA then program the (E)ISA controller + * to actually start the transfer. + */ + if ((AdapterObject) && !(AdapterObject->MasterDevice)) + { + AdapterMode = AdapterObject->AdapterMode; + + if (WriteToDevice) + { + AdapterMode.TransferType = WRITE_TRANSFER; + } + else + { + AdapterMode.TransferType = READ_TRANSFER; + if (AdapterObject->IgnoreCount) + { + RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset, + TransferLength); + } + } + + TransferOffset = PhysicalAddress.LowPart & 0xFFFF; + if (AdapterObject->Width16Bits) + { + TransferLength >>= 1; + TransferOffset >>= 1; + } + + KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); + + if (AdapterObject->AdapterNumber == 1) + { + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; + + /* Reset Register */ + WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); + + /* Set the Mode */ + WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte); + + /* Set the Offset Register */ + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, + (UCHAR)(TransferOffset)); + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, + (UCHAR)(TransferOffset >> 8)); + + /* Set the Page Register */ + WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), + (UCHAR)(PhysicalAddress.LowPart >> 16)); + if (HalpEisaDma) + { + WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), + 0); + } + + /* Set the Length */ + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)(TransferLength - 1)); + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((TransferLength - 1) >> 8)); + + /* Unmask the Channel */ + WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + else + { + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; + + /* Reset Register */ + WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); + + /* Set the Mode */ + WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte); + + /* Set the Offset Register */ + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, + (UCHAR)(TransferOffset)); + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, + (UCHAR)(TransferOffset >> 8)); + + /* Set the Page Register */ + WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages), + (UCHAR)(PhysicalAddress.u.LowPart >> 16)); + if (HalpEisaDma) + { + WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages), + 0); + } + + /* Set the Length */ + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)(TransferLength - 1)); + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((TransferLength - 1) >> 8)); + + /* Unmask the Channel */ + WRITE_PORT_UCHAR(&DmaControl2->SingleMask, + AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + + KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); + } + + /* + * Return physical address of the buffer with data that is used for the + * transfer. It can either point inside the Mdl that was passed by the + * caller or into the map registers if the Mdl buffer can't be used + * directly. + */ + return PhysicalAddress; } /** -- 2.17.1