From 1fe3441f75637f325b4bd6f329982a1267dfbb0a Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 21 Nov 2004 21:53:07 +0000 Subject: [PATCH] Hal DMA Patch: Implemented correct AdapterObject, updated some AdapterFunctions, which are much more complete and correct now. Implemented EISA structure for port access instead of hard-coded offsets. svn path=/trunk/; revision=11771 --- reactos/hal/hal/hal.c | 11 +- reactos/hal/halx86/adapter.c | 320 +++++++++++++++++++----- reactos/hal/halx86/dma.c | 417 ++++++++++++++++++++++++------- reactos/hal/halx86/include/hal.h | 339 ++++++++++++++++++++++++- reactos/hal/halx86/include/mps.h | 48 ++-- reactos/hal/halx86/irql.c | 6 +- reactos/ntoskrnl/io/iomgr.c | 16 +- reactos/ntoskrnl/ob/object.c | 18 +- 8 files changed, 967 insertions(+), 208 deletions(-) diff --git a/reactos/hal/hal/hal.c b/reactos/hal/hal/hal.c index b6590cadcbd..02bd939c08f 100644 --- a/reactos/hal/hal/hal.c +++ b/reactos/hal/hal/hal.c @@ -1,4 +1,4 @@ -/* $Id: hal.c,v 1.7 2004/10/23 23:43:23 ion Exp $ +/* $Id: hal.c,v 1.8 2004/11/21 21:53:06 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -139,12 +139,11 @@ HalAssignSlotResources( } -BOOLEAN +BOOLEAN STDCALL -HalBeginSystemInterrupt( - ULONG Vector, - KIRQL Irql, - PKIRQL OldIrql) +HalBeginSystemInterrupt (ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) { UNIMPLEMENTED; diff --git a/reactos/hal/halx86/adapter.c b/reactos/hal/halx86/adapter.c index 8c58a99f06e..23a4ce362f2 100644 --- a/reactos/hal/halx86/adapter.c +++ b/reactos/hal/halx86/adapter.c @@ -1,4 +1,4 @@ -/* $Id: adapter.c,v 1.12 2004/10/22 20:08:21 ekohl Exp $ +/* $Id: adapter.c,v 1.13 2004/11/21 21:53:06 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -15,6 +15,7 @@ #include #include +#define NDEBUG #include #include @@ -66,7 +67,7 @@ HalAllocateAdapterChannel( WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters; /* returns true if queued, else returns false and sets the queue to busy */ - if(KeInsertDeviceQueue(&AdapterObject->DeviceQueue, &WaitContextBlock->WaitQueueEntry)) + if(KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry)) return STATUS_SUCCESS; /* 24-bit max address due to 16-bit dma controllers */ @@ -95,7 +96,7 @@ HalAllocateAdapterChannel( if(!AdapterObject->MapRegisterBase) return STATUS_INSUFFICIENT_RESOURCES; - AdapterObject->AllocatedMapRegisters = NumberOfMapRegisters; + AdapterObject->CommittedMapRegisters = NumberOfMapRegisters; /* call the client's AdapterControl callback with its map registers and context */ Retval = ExecutionRoutine(WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp, @@ -119,7 +120,7 @@ HalAllocateAdapterChannel( else if(Retval == DeallocateObjectKeepRegisters) { /* don't free the allocated map registers - this is what IoFreeAdapterChannel checks */ - AdapterObject->AllocatedMapRegisters = 0; + AdapterObject->CommittedMapRegisters = 0; IoFreeAdapterChannel(AdapterObject); } @@ -131,6 +132,171 @@ HalAllocateAdapterChannel( return STATUS_SUCCESS; } + +BOOLEAN +HalpGrowMapBuffers( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG SizeOfMapBuffers) +/* + * FUNCTION: Allocate initial, or additional, map buffers for IO adapters. + * ARGUMENTS: + * AdapterObject: DMA adapter to allocate buffers for. + * SizeOfMapBuffers: Size of the map buffers to allocate + * NOTES: + * - Needs to be tested... + */ +{ + //ULONG PagesToAllocate = BYTES_TO_PAGES(SizeOfMapBuffers); + + /* TODO: Allocation */ + + return TRUE; +} + +PADAPTER_OBJECT STDCALL +HalpAllocateAdapterEx( + ULONG NumberOfMapRegisters, + BOOLEAN IsMaster, + BOOLEAN Dma32BitAddresses) +/* + * FUNCTION: Allocates an ADAPTER_OBJECT, optionally creates the Master Adapter. + * ARGUMENTS: + * - NumberOfMapRegisters: Number of map registers to allocate + * - IsMaster: Wether this is a Master Device or not + * - Dma32BitAddresses: Wether 32-bit Addresses are supported + * RETURNS: + * - Pointer to Adapter Object, or NULL if failure. + * BUGS: + * - Some stuff is unhandled/incomplete + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG ObjectSize; + ULONG BitmapSize; + NTSTATUS Status; + ULONG AllowedMapRegisters = 64; + PADAPTER_OBJECT AdapterObject; + HANDLE Handle; + + /* Allocate the Master Adapter if we haven't already + but make sure we're not asked to do it now, and also check if we need it */ + if ((MasterAdapter == NULL) && (!IsMaster) && (NumberOfMapRegisters)) { + + /* Allocate and Save */ + DPRINT("Allocating the Master Adapter Object\n"); + MasterAdapter = HalpAllocateAdapterEx(NumberOfMapRegisters, + TRUE, + Dma32BitAddresses); + + /* Cancel on Failure */ + DPRINT("Checking if Master Adapter was allocated properly\n"); + if (!MasterAdapter) return NULL; + } + + /* Initialize the Object Attributes for the Adapter Object */ + InitializeObjectAttributes(&ObjectAttributes, + NULL, + OBJ_PERMANENT, + NULL, + NULL); + + /* Check if this is the Master Adapter, in which case we need to allocate the bitmap */ + if (IsMaster) { + /* Size due to the Bitmap + Bytes in the Bitmap Buffer (8 bytes, 64 bits)*/ + BitmapSize = sizeof(RTL_BITMAP) + AllowedMapRegisters / 8; + + /* We will put the Bitmap Buffer after the Adapter Object for simplicity */ + ObjectSize = sizeof(ADAPTER_OBJECT) + BitmapSize; + } else { + ObjectSize = sizeof(ADAPTER_OBJECT); + } + + /* Create and Allocate the Object */ + DPRINT("Creating the Object\n"); + Status = ObCreateObject(KernelMode, + IoAdapterObjectType, + &ObjectAttributes, + KernelMode, + NULL, + ObjectSize, + 0, + 0, + (PVOID)&AdapterObject); + + if (!NT_SUCCESS(Status)) return NULL; + + /* Add a Reference */ + DPRINT("Referencing the Object\n"); + Status = ObReferenceObjectByPointer(AdapterObject, + FILE_READ_DATA | FILE_WRITE_DATA, + IoAdapterObjectType, + KernelMode); + + if (!NT_SUCCESS(Status)) return NULL; + + /* It's a Valid Object, so now we can play with the memory */ + RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT)); + + /* Insert it into the Object Table */ + DPRINT("Inserting the Object\n"); + Status = ObInsertObject(AdapterObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + &Handle); + + if (!NT_SUCCESS(Status)) return NULL; + + /* We don't want the handle */ + NtClose(Handle); + + /* Set up the Adapter Object fields */ + AdapterObject->MapRegistersPerChannel = 1; + + /* Set the Master if needed (master only needed if we use Map Registers) */ + if (NumberOfMapRegisters) AdapterObject->MasterAdapter = MasterAdapter; + + /* Initalize the Channel Wait queue, which every adapter has */ + DPRINT("Initializing the Device Queue of the Object\n"); + KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue); + + /* Initialize the SpinLock, Queue and Bitmap, which are kept in the Master Adapter only */ + if (IsMaster) { + + DPRINT("Initializing the Master Adapter Stuff\n"); + KeInitializeSpinLock(&AdapterObject->SpinLock); + InitializeListHead(&AdapterObject->AdapterQueue); + + /* As said previously, we put them here for simplicity */ + AdapterObject->MapRegisters = (PVOID)(AdapterObject + 1); + + /* Set up Bitmap */ + RtlInitializeBitMap(AdapterObject->MapRegisters, + (PULONG)(AdapterObject->MapRegisters + sizeof(RTL_BITMAP)), + 64); + + /* Reset the Bitmap */ + RtlSetAllBits(AdapterObject->MapRegisters); + AdapterObject->NumberOfMapRegisters = 0; + AdapterObject->CommittedMapRegisters = 0; + + /* Allocate Memory for the Map Registers */ + AdapterObject->MapRegisterBase = ExAllocatePool(NonPagedPool, + AllowedMapRegisters * sizeof(DWORD)); + + /* Clear them */ + RtlZeroMemory(AdapterObject->MapRegisterBase, AllowedMapRegisters * sizeof(DWORD)); + + /* Allocate the contigous memory */ + DPRINT("Allocating Buffers\n"); + HalpGrowMapBuffers(AdapterObject, 0x1000000); + } + + DPRINT("Adapter Object allocated\n"); + return AdapterObject; +} + BOOLEAN STDCALL IoFlushAdapterBuffers ( @@ -164,11 +330,21 @@ IoFlushAdapterBuffers ( return TRUE; /* mask out (disable) the dma channel */ - if (AdapterObject->Channel < 4) - WRITE_PORT_UCHAR( (PVOID)0x0A, (UCHAR)(AdapterObject->Channel | 0x4) ); - else - WRITE_PORT_UCHAR( (PVOID)0xD4, (UCHAR)((AdapterObject->Channel - 4) | 0x4) ); - + if (AdapterObject->AdapterNumber == 1) { + + /* Set this for Ease */ + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; + + /* Set Channel */ + WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK); + } else { + /* Set this for Ease */ + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; + + /* Set Channel */ + WRITE_PORT_UCHAR(&DmaControl2->SingleMask, (AdapterObject->ChannelNumber - 4) | DMA_SETMASK); + } + if(WriteToDevice) return TRUE; @@ -202,10 +378,10 @@ IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject) while(1) { /* To keep map registers, call here with the following set to 0 */ - if(AdapterObject->AllocatedMapRegisters) - IoFreeMapRegisters(AdapterObject, AdapterObject->MapRegisterBase, AdapterObject->AllocatedMapRegisters); + if(AdapterObject->CommittedMapRegisters) + IoFreeMapRegisters(AdapterObject, AdapterObject->MapRegisterBase, AdapterObject->CommittedMapRegisters); - if(!(WaitContextBlock = (PWAIT_CONTEXT_BLOCK)KeRemoveDeviceQueue(&AdapterObject->DeviceQueue))) + if(!(WaitContextBlock = (PWAIT_CONTEXT_BLOCK)KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue))) break; /* @@ -241,7 +417,7 @@ IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject) else if(Retval == DeallocateObjectKeepRegisters) { /* hide the map registers so they aren't deallocated next time around */ - AdapterObject->AllocatedMapRegisters = 0; + AdapterObject->CommittedMapRegisters = 0; } } } @@ -265,7 +441,7 @@ IoFreeMapRegisters ( * - needs to be improved to use a real map register implementation */ { - if( AdapterObject->AllocatedMapRegisters ) + if( AdapterObject->CommittedMapRegisters ) { MmFreeContiguousMemory(AdapterObject->MapRegisterBase); AdapterObject->MapRegisterBase = 0; @@ -302,9 +478,8 @@ IoMapTransfer ( */ { PHYSICAL_ADDRESS Address; - PVOID MaskReg, ClearReg, ModeReg; - UCHAR ModeMask, LengthShift; KIRQL OldIrql; + UCHAR Mode; #if defined(__GNUC__) Address.QuadPart = 0ULL; @@ -313,14 +488,8 @@ IoMapTransfer ( #endif /* Isa System (slave) DMA? */ - if (AdapterObject && AdapterObject->InterfaceType == Isa && !AdapterObject->Master) + if (MapRegisterBase && !AdapterObject->MasterDevice) { -#if 0 - /* channel 0 is reserved for DRAM refresh */ - ASSERT(AdapterObject->Channel != 0); - /* channel 4 is reserved for cascade */ - ASSERT(AdapterObject->Channel != 4); -#endif KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); @@ -341,56 +510,77 @@ IoMapTransfer ( * -- Filip Navara, 19/07/2004 */ + /* Get the mode for easier coding */ + Mode = AdapterObject->AdapterMode; + /* if it is a write to the device, copy the caller buffer to the low buffer */ - if( WriteToDevice && !AdapterObject->AutoInitialize ) + if ((WriteToDevice) && !((PDMA_MODE)&Mode)->AutoInitialize) { memcpy(MapRegisterBase, (char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)), *Length ); } - - // 16-bit DMA - if( AdapterObject->Channel >= 4 ) - { - MaskReg = (PVOID)0xD4; ClearReg = (PVOID)0xD8; ModeReg = (PVOID)0xD6; - LengthShift = 1; - } - else - { - MaskReg = (PVOID)0x0A; ClearReg = (PVOID)0x0C; ModeReg = (PVOID)0x0B; - LengthShift = 0; - } - // calculate the mask we will later set to the mode register - ModeMask = (AdapterObject->Channel & 3) | ( WriteToDevice ? 0x8 : 0x4 ); - // FIXME: if not demand mode, which mode to use? 0x40 for single mode - if (!AdapterObject->DemandMode) - ModeMask |= 0x40; - if (AdapterObject->AutoInitialize) - ModeMask |= 0x10; + /* Writer Adapter Mode, transfer type */ + ((PDMA_MODE)&Mode)->TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER); // program up the dma controller, and return - if (!AdapterObject->AutoInitialize) + if (!((PDMA_MODE)&Mode)->AutoInitialize) { Address = MmGetPhysicalAddress( MapRegisterBase ); - else + } else { Address = MmGetPhysicalAddress( CurrentVa ); - // disable and select the channel number - WRITE_PORT_UCHAR( MaskReg, (UCHAR)((AdapterObject->Channel & 3) | 0x4) ); - // write zero to the reset register - WRITE_PORT_UCHAR( ClearReg, 0 ); - // mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for auto initialize - WRITE_PORT_UCHAR( ModeReg, ModeMask); - // set the 64k page register for the channel - WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16) ); - // low, then high address byte, which is always 0 for us, because we have a 64k alligned address - WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); - WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); - // count is 1 less than length, low then high - WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)((*Length >> LengthShift) - 1) ); - WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)(((*Length >> LengthShift) - 1)>>8) ); - // unmask the channel to let it rip - WRITE_PORT_UCHAR( MaskReg, AdapterObject->Channel & 3 ); - + } + + /* 16-bit DMA has a shifted length */ + if (AdapterObject->Width16Bits) *Length = (*Length >> 1); + + /* Make the Transfer */ + if (AdapterObject->AdapterNumber == 1) { + + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */ + + /* Reset Register */ + WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); + + /* Set the Mode */ + WRITE_PORT_UCHAR(&DmaControl1->Mode, (UCHAR)(Mode)); + + /* Set the Page Register (apparently always 0 for us if I trust the previous comment) */ + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); + + /* Set the Length */ + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((*Length) - 1)); + WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((*Length) - 1) >> 8); + + /* Unmask the Channel */ + WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); + } else { + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */ + + /* Reset Register */ + WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); + + /* Set the Mode */ + WRITE_PORT_UCHAR(&DmaControl2->Mode, (UCHAR)(Mode)); + + /* Set the Page Register (apparently always 0 for us if I trust the previous comment) */ + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); + + /* Set the Length */ + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((*Length) - 1)); + WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, + (UCHAR)((*Length) - 1) >> 8); + + /* Unmask the Channel */ + WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + + /* Release Spinlock */ KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); /* @@ -409,7 +599,7 @@ IoMapTransfer ( being NULL is used to detect a s/g busmaster. */ if ((!AdapterObject && !MapRegisterBase) || - (AdapterObject && AdapterObject->Master && AdapterObject->ScatterGather)) + (AdapterObject && AdapterObject->MasterDevice && AdapterObject->ScatterGather)) { /* Just return the passed VA's corresponding phys. address. @@ -459,7 +649,7 @@ IoMapTransfer ( not being NULL is used to detect a non s/g busmaster. */ if ((!AdapterObject && MapRegisterBase) || - (AdapterObject && AdapterObject->Master && !AdapterObject->ScatterGather)) + (AdapterObject && AdapterObject->MasterDevice && !AdapterObject->ScatterGather)) { /* NOTE: Busmasters doing common-buffer DMA shouldn't call IoMapTransfer, but I don't @@ -476,7 +666,7 @@ IoMapTransfer ( return MmGetPhysicalAddress(MapRegisterBase); } - DPRINT1("IoMapTransfer: Unsupported operation\n"); + DPRINT("IoMapTransfer: Unsupported operation\n"); KEBUGCHECK(0); return Address; } diff --git a/reactos/hal/halx86/dma.c b/reactos/hal/halx86/dma.c index 652cf1d0e63..5d010b8b9b5 100644 --- a/reactos/hal/halx86/dma.c +++ b/reactos/hal/halx86/dma.c @@ -1,4 +1,4 @@ -/* $Id: dma.c,v 1.9 2004/07/22 18:49:18 navaraf Exp $ +/* $Id: dma.c,v 1.10 2004/11/21 21:53:06 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -12,42 +12,19 @@ /* INCLUDES *****************************************************************/ #include - +#define NDEBUG #include #include -/* XXX This initialization is out of date - ADAPTER_OBJECT has changed */ -/* NOTE: The following initializations have to be kept in synch with ADAPTER_OBJECT in hal.h */ -ADAPTER_OBJECT IsaSlaveAdapterObjects[] = { - { Isa, FALSE, 0, (PVOID)0x87, (PVOID)0x1, (PVOID)0x0, 0, NULL }, - { Isa, FALSE, 1, (PVOID)0x83, (PVOID)0x3, (PVOID)0x2, 0, NULL }, - { Isa, FALSE, 2, (PVOID)0x81, (PVOID)0x5, (PVOID)0x4, 0, NULL }, - { Isa, FALSE, 3, (PVOID)0x82, (PVOID)0x7, (PVOID)0x6, 0, NULL }, - /* 16-bit DMA */ - { Isa, FALSE, 4, (PVOID)0x8F, (PVOID)0xC2, (PVOID)0xC0, 0, NULL }, - { Isa, FALSE, 5, (PVOID)0x8B, (PVOID)0xC6, (PVOID)0xC4, 0, NULL }, - { Isa, FALSE, 6, (PVOID)0x89, (PVOID)0xCA, (PVOID)0xC8, 0, NULL }, - { Isa, FALSE, 7, (PVOID)0x8A, (PVOID)0xCE, (PVOID)0xCC, 0, NULL } }; - -ADAPTER_OBJECT PciBusMasterAdapterObjects[] = { - { PCIBus, TRUE, 0, (PVOID)0, (PVOID)0, (PVOID)0x0, 0, NULL } }; +/* Adapters for each channel */ +PADAPTER_OBJECT HalpEisaAdapter[8]; /* FUNCTIONS *****************************************************************/ VOID HalpInitDma (VOID) { - ULONG Index; - - KeInitializeDeviceQueue(&PciBusMasterAdapterObjects[0].DeviceQueue); - KeInitializeSpinLock(&PciBusMasterAdapterObjects[0].SpinLock); - PciBusMasterAdapterObjects[0].Inuse = FALSE; - for (Index = 0; Index < 8; Index++) - { - KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[Index].DeviceQueue); - KeInitializeSpinLock(&IsaSlaveAdapterObjects[Index].SpinLock); - IsaSlaveAdapterObjects[Index].Inuse = FALSE; - } + /* TODO: Initialize the first Map Buffer */ } PVOID STDCALL @@ -79,15 +56,11 @@ HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject, LowestAddress.QuadPart = 0; BoundryAddressMultiple.QuadPart = 0; HighestAddress.u.HighPart = 0; - if (AdapterObject->InterfaceType == Isa || - (AdapterObject->InterfaceType == MicroChannel && AdapterObject->Master == FALSE)) - { - HighestAddress.u.LowPart = 0x00FFFFFF; /* 24Bit: 16MB address range */ - } - else - { + if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice)) { HighestAddress.u.LowPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */ - } + } else { + HighestAddress.u.LowPart = 0x00FFFFFF; /* 24Bit: 16MB address range */ + } BaseAddress = MmAllocateContiguousAlignedMemory( Length, @@ -141,49 +114,284 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, * RETURNS: The allocated adapter object on success * NULL on failure * TODO: - * Honour all the fields in DeviceDescription structure. + * Testing */ { - PADAPTER_OBJECT AdapterObject; + PADAPTER_OBJECT AdapterObject; + DWORD ChannelSelect; + DWORD Controller; + ULONG MaximumLength; + BOOLEAN ChannelSetup; - /* Validate parameters in device description, and return a pointer to - the adapter object for the requested dma channel */ - if( DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION ) - return NULL; + DPRINT("Entered Function\n"); + + /* Validate parameters in device description, and return a pointer to + the adapter object for the requested dma channel */ + if(DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION) { + DPRINT("Invalid Adapter version!\n"); + return NULL; + } - switch (DeviceDescription->InterfaceType) - { - case PCIBus: - if (DeviceDescription->Master == FALSE) - return NULL; - return &PciBusMasterAdapterObjects[0]; + DPRINT("Checking Interface Type: %x \n", DeviceDescription->InterfaceType); + if (DeviceDescription->InterfaceType == PCIBus) { + if (DeviceDescription->Master == FALSE) { + DPRINT("Invalid request!\n"); + return NULL; + } + ChannelSetup = FALSE; + } + + /* There are only 8 DMA channels on ISA, so any request above this + should not get any channel setup */ + if (DeviceDescription->DmaChannel >= 8) { + ChannelSetup = FALSE; + } + + /* Channel 4 is Reserved for Chaining, so you cant use it */ + if (DeviceDescription->DmaChannel == 4 && ChannelSetup) { + DPRINT("Invalid request!\n"); + return NULL; + } + + /* Devices that support Scatter/Gather do not need Map Registers */ + if (DeviceDescription->ScatterGather && + (DeviceDescription->InterfaceType == Eisa || + DeviceDescription->InterfaceType == PCIBus)) { + *NumberOfMapRegisters = 0; + } + + /* Check if Extended DMA is available (we're just going to do a random read/write + I picked Channel 2 because it's the first Channel in the Register */ + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController1Pages.Channel2), 0x2A); + if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController1Pages.Channel2)) == 0x2A) { + HalpEisaDma = TRUE; + } + + /* Find out how many Map Registers we need */ + DPRINT("Setting up Adapter Settings!\n"); + MaximumLength = DeviceDescription->MaximumLength & 0x7FFFFFFF; + *NumberOfMapRegisters = BYTES_TO_PAGES(MaximumLength) + 1; + + /* Set the Channel Selection */ + ChannelSelect = DeviceDescription->DmaChannel & 0x03; + + /* Get the Controller Setup */ + Controller = (DeviceDescription->DmaChannel & 0x04) ? 1 : 2; + + /* Get the Adapter Object */ + if (HalpEisaAdapter[DeviceDescription->DmaChannel] != NULL) { + + /* Already allocated, return it */ + DPRINT("Getting an Adapter Object from the Cache\n"); + AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel]; + + /* Do we need more Map Registers this time? */ + if ((AdapterObject->NeedsMapRegisters) && + (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)) { + AdapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + } + + } else { + + /* We have to allocate a new object! How exciting! */ + DPRINT("Allocating a new Adapter Object\n"); + AdapterObject = HalpAllocateAdapterEx(*NumberOfMapRegisters, + FALSE, + DeviceDescription->Dma32BitAddresses); - case Isa: - /* There are only 8 DMA channels on ISA. */ - if (DeviceDescription->DmaChannel >= 8) - return NULL; - /* Channels 1-4 are for 8-bit transfers... */ - if (DeviceDescription->DmaWidth != Width8Bits && - DeviceDescription->DmaChannel < 4) - return NULL; - /* ...and the rest is for 16-bit transfers. */ - if (DeviceDescription->DmaWidth != Width16Bits && - DeviceDescription->DmaChannel >= 4) - return NULL; - AdapterObject = &IsaSlaveAdapterObjects[DeviceDescription->DmaChannel]; - AdapterObject->Master = DeviceDescription->Master; - AdapterObject->ScatterGather = DeviceDescription->ScatterGather; - AdapterObject->AutoInitialize = DeviceDescription->AutoInitialize; - AdapterObject->DemandMode = DeviceDescription->DemandMode; - AdapterObject->Buffer = 0; - /* FIXME: Is this correct? */ - *NumberOfMapRegisters = 16; - return AdapterObject; - - default: - /* Unsupported bus. */ - return NULL; - } + if (AdapterObject == NULL) return NULL; + + HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject; + + if (!*NumberOfMapRegisters) { + /* Easy case, no Map Registers needed */ + AdapterObject->NeedsMapRegisters = FALSE; + + /* If you're the master, you get all you want */ + if (DeviceDescription->Master) { + AdapterObject->MapRegistersPerChannel= *NumberOfMapRegisters; + } else { + AdapterObject->MapRegistersPerChannel = 1; + } + } else { + /* We Desire Registers */ + AdapterObject->NeedsMapRegisters = TRUE; + + /* The registers you want */ + AdapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + + /* Increase commitment */ + MasterAdapter->CommittedMapRegisters += *NumberOfMapRegisters; + } + } + + /* Set up DMA Structure */ + if (Controller == 1) { + AdapterObject->AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1); + } else { + AdapterObject->AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2); + } + + /* Set up Some Adapter Data */ + DPRINT("Setting up an Adapter Object\n"); + AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount; + AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; + AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses; + AdapterObject->ScatterGather = DeviceDescription->ScatterGather; + AdapterObject->MasterDevice = DeviceDescription->Master; + if (DeviceDescription->InterfaceType != PCIBus) AdapterObject->LegacyAdapter = TRUE; + + /* Everything below is not required if we don't need a channel */ + if (!ChannelSetup) { + DPRINT("Retuning Adapter Object without Channel Setup\n"); + return AdapterObject; + } + + AdapterObject->ChannelNumber = ChannelSelect; + + + /* Set up the Page Port */ + if (Controller == 1) { + switch (ChannelSelect) { + + case 0: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel0)); + break; + case 1: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel1)); + break; + case 2: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel2)); + break; + case 3: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel3)); + break; + } + + /* Set Controller Number */ + AdapterObject->AdapterNumber = 1; + } else { + switch (ChannelSelect) { + + case 1: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel5)); + break; + case 2: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel6)); + break; + case 3: + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel7)); + break; + } + + /* Set Controller Number */ + AdapterObject->AdapterNumber = 2; + } + + /* Set up the Extended Register */ + if (HalpEisaDma) { + DMA_EXTENDED_MODE ExtendedMode; + + ExtendedMode.ChannelNumber = ChannelSelect; + + 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 NULL; + } + + 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 NULL; + } + + if (Controller == 1) { + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1), + *((PUCHAR)&ExtendedMode)); + } else { + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2), + *((PUCHAR)&ExtendedMode)); + } + } + /* Do 8/16-bit validation */ + DPRINT("Validating an Adapter Object\n"); + if (!DeviceDescription->Master) { + if ((DeviceDescription->DmaWidth == Width8Bits) && (Controller != 1)) { + return NULL; /* 8-bit is only avalable on Controller 1 */ + } else if (DeviceDescription->DmaWidth == Width16Bits) { + if (Controller != 2) { + return NULL; /* 16-bit is only avalable on Controller 2 */ + } else { + AdapterObject->Width16Bits = TRUE; + } + } + } + UCHAR DmaMode; + DPRINT("Final DMA Request Mode Setting of the Adapter Object\n"); + /* Set the DMA Request Modes */ + if (DeviceDescription->Master) { + /* This is a cascade request */ + ((PDMA_MODE)&DmaMode)->RequestMode = CASCADE_REQUEST_MODE; + + /* Send the request */ + if (AdapterObject->AdapterNumber == 1) { + /* Set the Request Data */ + WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->Mode, + AdapterObject->AdapterMode); + + /* Unmask DMA Channel */ + WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask, + AdapterObject->ChannelNumber | DMA_CLEARMASK); + } else { + /* Set the Request Data */ + WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->Mode, + AdapterObject->AdapterMode); + + /* Unmask DMA Channel */ + WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask, + AdapterObject->ChannelNumber | DMA_CLEARMASK); + } + } else if (DeviceDescription->DemandMode) { + /* This is a Demand request */ + ((PDMA_MODE)&DmaMode)->RequestMode = DEMAND_REQUEST_MODE; + } else { + /* Normal Request */ + ((PDMA_MODE)&DmaMode)->RequestMode = SINGLE_REQUEST_MODE; + } + + /* Auto Initialize Enabled or Not*/ + ((PDMA_MODE)&DmaMode)->AutoInitialize = DeviceDescription->AutoInitialize; + AdapterObject->AdapterMode = DmaMode; + return AdapterObject; } ULONG STDCALL @@ -192,29 +400,46 @@ HalReadDmaCounter (PADAPTER_OBJECT AdapterObject) KIRQL OldIrql; ULONG Count; - if (AdapterObject && AdapterObject->InterfaceType == Isa && !AdapterObject->Master) - { - KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); + KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql); + + /* Send the Request to the specific controller */ + if (AdapterObject->AdapterNumber == 1) { + + /* Set this for Ease */ + PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; + + /* 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; + + } else { - /* Clear the flip/flop register */ - WRITE_PORT_UCHAR( AdapterObject->Channel < 4 ? (PVOID)0x0C : (PVOID)0xD8, 0 ); - /* Read the offset */ - Count = READ_PORT_UCHAR( AdapterObject->CountPort ); - Count |= READ_PORT_UCHAR( AdapterObject->CountPort ) << 8; - - KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); - - /* - * We must return twice the sound for channel >= 4 because it's the size - * of words (16-bit) and not bytes. - */ - if (AdapterObject->Channel < 4) - return Count; - else - return Count << 1; - } - - return 0; + /* Set this for Ease */ + PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; + + /* 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; + } + + /* Play around with the count (add bias and multiply by 2 if 16-bit DMA) */ + Count ++; + if (AdapterObject->Width16Bits) Count *=2 ; + + KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql); + + /* Return it */ + return Count; } /* EOF */ diff --git a/reactos/hal/halx86/include/hal.h b/reactos/hal/halx86/include/hal.h index 98b02087969..863594591b9 100644 --- a/reactos/hal/halx86/include/hal.h +++ b/reactos/hal/halx86/include/hal.h @@ -12,6 +12,9 @@ VOID FASTCALL HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock); VOID FASTCALL HalClearDisplay (UCHAR CharAttribute); +/* adapter.c */ +PADAPTER_OBJECT STDCALL HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses); + /* bus.c */ VOID HalpInitBusHandlers (VOID); @@ -30,16 +33,334 @@ VOID HalpStartEnumerator (VOID); /* dma.c */ VOID HalpInitDma (VOID); +/* DMA Page Register Structure + 080 DMA RESERVED + 081 DMA Page Register (channel 2) + 082 DMA Page Register (channel 3) + 083 DMA Page Register (channel 1) + 084 DMA RESERVED + 085 DMA RESERVED + 086 DMA RESERVED + 087 DMA Page Register (channel 0) + 088 DMA RESERVED + 089 PS/2-DMA Page Register (channel 6) + 08A PS/2-DMA Page Register (channel 7) + 08B PS/2-DMA Page Register (channel 5) + 08C PS/2-DMA RESERVED + 08D PS/2-DMA RESERVED + 08E PS/2-DMA RESERVED + 08F PS/2-DMA Page Register (channel 4) +*/ + typedef struct _DMA_PAGE{ + UCHAR Reserved1; + UCHAR Channel2; + UCHAR Channel3; + UCHAR Channel1; + UCHAR Reserved2[3]; + UCHAR Channel0; + UCHAR Reserved3; + UCHAR Channel6; + UCHAR Channel7; + UCHAR Channel5; + UCHAR Reserved4[3]; + UCHAR Channel4; +} DMA_PAGE, *PDMA_PAGE; + +/* DMA Channel Mask Register Structure + +MSB LSB + x x x x x x x x + ------------------- - ----- + | | | 00 - Select channel 0 mask bit + | | \---- 01 - Select channel 1 mask bit + | | 10 - Select channel 2 mask bit + | | 11 - Select channel 3 mask bit + | | + | \---------- 0 - Clear mask bit + | 1 - Set mask bit + | + \----------------------- xx - Reserved +*/ +typedef struct _DMA_CHANNEL_MASK { + UCHAR Channel : 2; + UCHAR SetMask : 1; + UCHAR Reserved : 5; +} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK; + +/* DMA Mask Register Structure + + MSB LSB + x x x x x x x x + \---/ - - ----- ----- + | | | | | 00 - Channel 0 select + | | | | \---- 01 - Channel 1 select + | | | | 10 - Channel 2 select + | | | | 11 - Channel 3 select + | | | | + | | | | 00 - Verify transfer + | | | \------------ 01 - Write transfer + | | | 10 - Read transfer + | | | + | | \-------------------- 0 - Autoinitialized + | | 1 - Non-autoinitialized + | | + | \------------------------ 0 - Address increment select + | + | 00 - Demand mode + \------------------------------ 01 - Single mode + 10 - Block mode + 11 - Cascade mode +*/ +typedef struct _DMA_MODE { + UCHAR Channel : 2; + UCHAR TransferType : 2; + UCHAR AutoInitialize : 1; + UCHAR AddressDecrement : 1; + UCHAR RequestMode : 2; +} DMA_MODE, *PDMA_MODE; + + +/* DMA Extended Mode Register Structure + + MSB LSB + x x x x x x x x + - - ----- ----- ----- + | | | | | 00 - Channel 0 select + | | | | \---- 01 - Channel 1 select + | | | | 10 - Channel 2 select + | | | | 11 - Channel 3 select + | | | | + | | | | 00 - 8-bit I/O, by bytes + | | | \------------ 01 - 16-bit I/O, by words, address shifted + | | | 10 - 32-bit I/O, by bytes + | | | 11 - 16-bit I/O, by bytes + | | | + | | \---------------------- 00 - Compatible + | | 01 - Type A + | | 10 - Type B + | | 11 - Burst + | | + | \---------------------------- 0 - Terminal Count is Output + | + \---------------------------------0 - Disable Stop Register + 1 - Enable Stop Register +*/ +typedef struct _DMA_EXTENDED_MODE { + UCHAR ChannelNumber : 2; + UCHAR TransferSize : 2; + UCHAR TimingMode : 2; + UCHAR TerminalCountIsOutput : 1; + UCHAR EnableStopRegister : 1; +}DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE; + +/* DMA Extended Mode Register Transfer Sizes */ +#define B_8BITS 0 +#define W_16BITS 1 +#define B_32BITS 2 +#define B_16BITS 3 + +/* DMA Extended Mode Register Timing */ +#define COMPATIBLE_TIMING 0 +#define TYPE_A_TIMING 1 +#define TYPE_B_TIMING 2 +#define BURST_TIMING 3 + +/* Channel Stop Registers for each Channel */ +typedef struct _DMA_CHANNEL_STOP { + UCHAR ChannelLow; + UCHAR ChannelMid; + UCHAR ChannelHigh; + UCHAR Reserved; +} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP; + +/* Transfer Types */ +#define VERIFY_TRANSFER 0x00 +#define READ_TRANSFER 0x01 +#define WRITE_TRANSFER 0x02 + +/* Request Modes */ +#define DEMAND_REQUEST_MODE 0x00 +#define SINGLE_REQUEST_MODE 0x01 +#define BLOCK_REQUEST_MODE 0x02 +#define CASCADE_REQUEST_MODE 0x03 + +#define DMA_SETMASK 4 +#define DMA_CLEARMASK 0 +#define DMA_READ 4 +#define DMA_WRITE 8 +#define DMA_SINGLE_TRANSFER 0x40 +#define DMA_AUTO_INIT 0x10 + +typedef struct _DMA1_ADDRESS_COUNT { + UCHAR DmaBaseAddress; + UCHAR DmaBaseCount; +} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT; + +typedef struct _DMA2_ADDRESS_COUNT { + UCHAR DmaBaseAddress; + UCHAR Reserved1; + UCHAR DmaBaseCount; + UCHAR Reserved2; +} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT; + +typedef struct _DMA1_CONTROL { + DMA1_ADDRESS_COUNT DmaAddressCount[4]; + UCHAR DmaStatus; + UCHAR DmaRequest; + UCHAR SingleMask; + UCHAR Mode; + UCHAR ClearBytePointer; + UCHAR MasterClear; + UCHAR ClearMask; + UCHAR AllMask; +} DMA1_CONTROL, *PDMA1_CONTROL; + +typedef struct _DMA2_CONTROL { + DMA2_ADDRESS_COUNT DmaAddressCount[4]; + UCHAR DmaStatus; + UCHAR Reserved1; + UCHAR DmaRequest; + UCHAR Reserved2; + UCHAR SingleMask; + UCHAR Reserved3; + UCHAR Mode; + UCHAR Reserved4; + UCHAR ClearBytePointer; + UCHAR Reserved5; + UCHAR MasterClear; + UCHAR Reserved6; + UCHAR ClearMask; + UCHAR Reserved7; + UCHAR AllMask; + UCHAR Reserved8; +} DMA2_CONTROL, *PDMA2_CONTROL; + +/* This Structure Defines the I/O Map of the 82537 Controller + I've only defined the registers which are likely to be useful to us */ +typedef struct _EISA_CONTROL { + /* DMA Controller 1 */ + DMA1_CONTROL DmaController1; /* 00h-0Fh */ + UCHAR Reserved1[16]; /* 0Fh-1Fh */ + + /* Interrupt Controller 1 (PIC) */ + UCHAR Pic1Operation; /* 20h */ + UCHAR Pic1Interrupt; /* 21h */ + UCHAR Reserved2[30]; /* 22h-3Fh */ + + /* Timer */ + UCHAR TimerCounter; /* 40h */ + UCHAR TimerMemoryRefresh; /* 41h */ + UCHAR Speaker; /* 42h */ + UCHAR TimerOperation; /* 43h */ + UCHAR TimerMisc; /* 44h */ + UCHAR Reserved3[2]; /* 45-46h */ + UCHAR TimerCounterControl; /* 47h */ + UCHAR TimerFailSafeCounter; /* 48h */ + UCHAR Reserved4; /* 49h */ + UCHAR TimerCounter2; /* 4Ah */ + UCHAR TimerOperation2; /* 4Bh */ + UCHAR Reserved5[20]; /* 4Ch-5Fh */ + + /* NMI / Keyboard / RTC */ + UCHAR Keyboard; /* 60h */ + UCHAR NmiStatus; /* 61h */ + UCHAR Reserved6[14]; /* 62h-6Fh */ + UCHAR NmiEnable; /* 70h */ + UCHAR Reserved7[15]; /* 71h-7Fh */ + + /* DMA Page Registers Controller 1 */ + DMA_PAGE DmaController1Pages; /* 80h-8Fh */ + UCHAR Reserved8[16]; /* 90h-9Fh */ + + /* Interrupt Controller 2 (PIC) */ + UCHAR Pic2Operation; /* 0A0h */ + UCHAR Pic2Interrupt; /* 0A1h */ + UCHAR Reserved9[30]; /* 0A2h-0BFh */ + + /* DMA Controller 2 */ + DMA1_CONTROL DmaController2; /* 0C0h-0DFh */ + + /* System Reserved Ports */ + UCHAR SystemReserved[800]; /* 0E0h-3FFh */ + + /* Extended DMA Registers, Controller 1 */ + UCHAR DmaHighByteCount1[8]; /* 400h-407h */ + UCHAR Reserved10[2]; /* 408h-409h */ + UCHAR DmaChainMode1; /* 40Ah */ + UCHAR DmaExtendedMode1; /* 40Bh */ + UCHAR DmaBufferControl; /* 40Ch */ + UCHAR Reserved11[84]; /* 40Dh-460h */ + UCHAR ExtendedNmiControl; /* 461h */ + UCHAR NmiCommand; /* 462h */ + UCHAR Reserved12; /* 463h */ + UCHAR BusMaster; /* 464h */ + UCHAR Reserved13[27]; /* 465h-47Fh */ + + /* DMA Page Registers Controller 2 */ + DMA_PAGE DmaController2Pages; /* 480h-48Fh */ + UCHAR Reserved14[48]; /* 490h-4BFh */ + + /* Extended DMA Registers, Controller 2 */ + UCHAR DmaHighByteCount2[16]; /* 4C0h-4CFh */ + + /* Edge/Level Control Registers */ + UCHAR Pic1EdgeLevel; /* 4D0h */ + UCHAR Pic2EdgeLevel; /* 4D1h */ + UCHAR Reserved15[2]; /* 4D2h-4D3h */ + + /* Extended DMA Registers, Controller 2 */ + UCHAR DmaChainMode2; /* 4D4h */ + UCHAR Reserved16; /* 4D5h */ + UCHAR DmaExtendedMode2; /* 4D6h */ + UCHAR Reserved17[9]; /* 4D7h-4DFh */ + + /* DMA Stop Registers */ + DMA_CHANNEL_STOP DmaChannelStop[8]; /* 4E0h-4FFh */ +} EISA_CONTROL, *PEISA_CONTROL; + +extern ULONG HalpEisaDma; +extern PADAPTER_OBJECT MasterAdapter; + +EXPORTED ULONG HalpEisaDma; +EXPORTED PADAPTER_OBJECT MasterAdapter; + /* * ADAPTER_OBJECT - Track a busmaster DMA adapter and its associated resources * * NOTES: - * - I have not found any documentation on this; if you have any, please - * fix this struct definition - * - Some of this is right and some of this is wrong; many of these fields - * are unused at this point because X86 doesn't have map registers and - * currently that's all ROS supports + * - I've updated this to the Windows Object Defintion. */ +struct _ADAPTER_OBJECT { + DMA_ADAPTER DmaHeader; + struct _ADAPTER_OBJECT *MasterAdapter; + ULONG MapRegistersPerChannel; + PVOID AdapterBaseVa; + PVOID MapRegisterBase; + ULONG NumberOfMapRegisters; + ULONG CommittedMapRegisters; + PWAIT_CONTEXT_BLOCK CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + ULONG SpinLock; + PRTL_BITMAP MapRegisters; + PUCHAR PagePort; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + USHORT DmaPortAddress; + UCHAR AdapterMode; + BOOLEAN NeedsMapRegisters; + BOOLEAN MasterDevice; + UCHAR Width16Bits; + UCHAR ScatterGather; + UCHAR IgnoreCount; + UCHAR Dma32BitAddresses; + UCHAR Dma64BitAddresses; + BOOLEAN LegacyAdapter; + LIST_ENTRY AdapterList; +}; + +/* struct _ADAPTER_OBJECT { INTERFACE_TYPE InterfaceType; BOOLEAN Master; @@ -56,16 +377,10 @@ struct _ADAPTER_OBJECT { PWAIT_CONTEXT_BLOCK WaitContextBlock; KDEVICE_QUEUE DeviceQueue; BOOLEAN ScatterGather; - - /* - * 18/07/04: Added these members. It's propably not the exact place where - * this should be stored, but I can't find better one. I haven't checked - * how Windows handles this. - * -- Filip Navara - */ BOOLEAN DemandMode; BOOLEAN AutoInitialize; }; +*/ /* sysinfo.c */ NTSTATUS STDCALL diff --git a/reactos/hal/halx86/include/mps.h b/reactos/hal/halx86/include/mps.h index 8a88ebb3781..519d88c0f24 100644 --- a/reactos/hal/halx86/include/mps.h +++ b/reactos/hal/halx86/include/mps.h @@ -5,8 +5,10 @@ * FIXME: This does not work if we have more than 24 IRQs (ie. more than one * I/O APIC) */ -#define IRQL2VECTOR(irql) IRQ2VECTOR(PROFILE_LEVEL - (irql)) -#define IRQL2TPR(irql) (((irql) == PASSIVE_LEVEL) ? 0 : ((irql) >= CLOCK1_LEVEL ? 0xff : IRQL2VECTOR(irql))) +#define VECTOR2IRQ(vector) (((vector) - FIRST_DEVICE_VECTOR) / 8) +#define IRQ2VECTOR(vector) ((vector * 8) + FIRST_DEVICE_VECTOR) +#define VECTOR2IRQL(vector) (DISPATCH_LEVEL /* 2 */ + 1 + VECTOR2IRQ(vector)) +#define IRQL2VECTOR(irql) (IRQ2VECTOR(irql - DISPATCH_LEVEL /* 2 */ - 1)) #define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ @@ -37,12 +39,11 @@ #define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */ #define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ -#define APIC_ID_MASK (0xF << 24) -#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) -#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) -#define APIC_VER_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x) & 0xFF) -#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) +#define APIC_ID_MASK (0xF << 24) +#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) +#define APIC_VER_MASK 0xFF00FF +#define GET_APIC_VERSION(x)((x) & 0xFF) +#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) #define APIC_TPR_PRI 0xFF #define APIC_TPR_INT 0xF0 @@ -206,21 +207,22 @@ typedef struct _IOAPIC_INFO * to work around the 'lost local interrupt if more than 2 IRQ * sources per level' errata. */ -#define LOCAL_TIMER_VECTOR 0xEF +#define LOCAL_TIMER_VECTOR 0xEF -#define CALL_FUNCTION_VECTOR 0xFB -#define RESCHEDULE_VECTOR 0xFC -#define INVALIDATE_TLB_VECTOR 0xFD -#define ERROR_VECTOR 0xFE -#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ +#define CALL_FUNCTION_VECTOR 0xFB +#define RESCHEDULE_VECTOR 0xFC +#define INVALIDATE_TLB_VECTOR 0xFD +#define ERROR_VECTOR 0xFE +#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ -#if 0 -/* This values are defined in halirql.h */ -#define FIRST_DEVICE_VECTOR 0x30 -#define FIRST_SYSTEM_VECTOR 0xEF -#endif - -#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) +/* + * First APIC vector available to drivers: (vectors 0x30-0xEE) + * we start at 0x31 to spread out vectors evenly between priority + * levels. + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xEF +#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) /* MP Floating Pointer Structure */ @@ -428,8 +430,8 @@ typedef enum { VOID HalpInitMPS(VOID); volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset); VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); -VOID IOAPICMaskIrq(ULONG Irq); -VOID IOAPICUnmaskIrq(ULONG Irq); +VOID IOAPICMaskIrq(ULONG Apic, ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Apic, ULONG Irq); volatile inline ULONG APICRead(ULONG Offset); inline VOID APICWrite(ULONG Offset, ULONG Value); inline VOID APICSendEOI(VOID); diff --git a/reactos/hal/halx86/irql.c b/reactos/hal/halx86/irql.c index 04ad9aa6d77..3a39a3322db 100644 --- a/reactos/hal/halx86/irql.c +++ b/reactos/hal/halx86/irql.c @@ -1,4 +1,4 @@ -/* $Id: irql.c,v 1.21 2004/11/14 19:04:42 hbirr Exp $ +/* $Id: irql.c,v 1.22 2004/11/21 21:53:06 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -21,6 +21,10 @@ /* GLOBALS ******************************************************************/ +/* + * FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS +*/ + typedef union { USHORT both; diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 8bf4e3fa396..274e5329af4 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -1,4 +1,4 @@ -/* $Id: iomgr.c,v 1.53 2004/11/06 04:12:59 ion Exp $ +/* $Id: iomgr.c,v 1.54 2004/11/21 21:53:07 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -19,6 +19,7 @@ #define TAG_DEVICE_TYPE TAG('D', 'E', 'V', 'T') #define TAG_FILE_TYPE TAG('F', 'I', 'L', 'E') +#define TAG_ADAPTER_TYPE TAG('A', 'D', 'P', 'T') /* DATA ********************************************************************/ @@ -442,6 +443,19 @@ IoInit (VOID) RtlRosInitUnicodeStringFromLiteral(&IoFileObjectType->TypeName, L"File"); ObpCreateTypeObject(IoFileObjectType); + + /* + * Register iomgr types: AdapterObjectType + */ + IoAdapterObjectType = ExAllocatePool (NonPagedPool, + sizeof (OBJECT_TYPE)); + RtlZeroMemory(IoAdapterObjectType, sizeof(OBJECT_TYPE)); + IoAdapterObjectType->Tag = TAG_ADAPTER_TYPE; + IoAdapterObjectType->MaxObjects = ULONG_MAX; + IoAdapterObjectType->MaxHandles = ULONG_MAX; + IoDeviceObjectType->Mapping = &IopFileMapping; + RtlRosInitUnicodeStringFromLiteral(&IoAdapterObjectType->TypeName, L"Adapter"); + ObpCreateTypeObject(IoAdapterObjectType); /* * Create the '\Driver' object directory diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index 38eacafca44..7722cbabee0 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -1,4 +1,4 @@ -/* $Id: object.c,v 1.84 2004/10/22 20:43:58 ekohl Exp $ +/* $Id: object.c,v 1.85 2004/11/21 21:53:07 ion Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -364,7 +364,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, NULL); if (!NT_SUCCESS(Status)) { - DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status); + DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status); return Status; } } @@ -376,11 +376,15 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool, OBJECT_ALLOC_SIZE(ObjectSize), Type->Tag); - if (Header == NULL) - return STATUS_INSUFFICIENT_RESOURCES; + if (Header == NULL) { + DPRINT1("Not enough memory!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize)); /* Initialize the object header */ + DPRINT("Initalizing header\n"); Header->HandleCount = 0; Header->RefCount = 1; Header->ObjectType = Type; @@ -406,6 +410,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, RtlInitUnicodeString(&(Header->Name),NULL); + DPRINT("Getting Parent and adding entry\n"); if (Parent != NULL) { ParentHeader = BODY_TO_HEADER(Parent); @@ -426,6 +431,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, ObjectAttached = TRUE; } + DPRINT("About to call Create Routine\n"); if (Header->ObjectType->Create != NULL) { DPRINT("Calling %x\n", Header->ObjectType->Create); @@ -446,6 +452,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, RtlFreeUnicodeString(&Header->Name); RtlFreeUnicodeString(&RemainingPath); ExFreePool(Header); + DPRINT("Create Failed\n"); return Status; } } @@ -453,6 +460,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, SeCaptureSubjectContext(&SubjectContext); + DPRINT("Security Assignment in progress\n"); /* Build the new security descriptor */ Status = SeAssignSecurity((ParentHeader != NULL) ? ParentHeader->SecurityDescriptor : NULL, (ObjectAttributes != NULL) ? ObjectAttributes->SecurityDescriptor : NULL, @@ -486,6 +494,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, SeDeassignSecurity(&NewSecurityDescriptor); } + DPRINT("Security Complete\n"); SeReleaseSubjectContext(&SubjectContext); if (Object != NULL) @@ -493,6 +502,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, *Object = HEADER_TO_BODY(Header); } + DPRINT("Sucess!\n"); return STATUS_SUCCESS; }