xref: /reactos/drivers/bus/isapnp/isapnp.c (revision 10b08aa2)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS ISA PnP Bus driver
38f44930fSDmitry Borisov  * LICENSE:         GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4c2c66affSColin Finck  * PURPOSE:         Driver entry
58f44930fSDmitry Borisov  * COPYRIGHT:       Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
68f44930fSDmitry Borisov  *                  Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
7f15de155SDmitry Borisov  *                  Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10f15de155SDmitry Borisov /* INCLUDES *******************************************************************/
11f15de155SDmitry Borisov 
12b36d9bd9SDmitry Borisov #ifndef UNIT_TEST
1376ec8411SDmitry Borisov 
148f44930fSDmitry Borisov #include "isapnp.h"
15b36d9bd9SDmitry Borisov 
16c2c66affSColin Finck #define NDEBUG
17c2c66affSColin Finck #include <debug.h>
18c2c66affSColin Finck 
19f15de155SDmitry Borisov /* GLOBALS ********************************************************************/
20f15de155SDmitry Borisov 
21f15de155SDmitry Borisov KEVENT BusSyncEvent;
22f15de155SDmitry Borisov 
23f15de155SDmitry Borisov _Guarded_by_(BusSyncEvent)
2421514e47SDmitry Borisov BOOLEAN ReadPortCreated = FALSE;
2521514e47SDmitry Borisov 
26f15de155SDmitry Borisov _Guarded_by_(BusSyncEvent)
27f15de155SDmitry Borisov LIST_ENTRY BusListHead;
28f15de155SDmitry Borisov 
29b36d9bd9SDmitry Borisov #endif /* UNIT_TEST */
30b36d9bd9SDmitry Borisov 
31*10b08aa2SDmitry Borisov extern ULONG IsaConfigPorts[2];
32*10b08aa2SDmitry Borisov 
33f15de155SDmitry Borisov /* FUNCTIONS ******************************************************************/
34f15de155SDmitry Borisov 
3567141abeSHervé Poussineau static
3670ba96f1SDmitry Borisov CODE_SEG("PAGE")
378ed43b69SDmitry Borisov VOID
IsaConvertIoRequirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,_In_ PISAPNP_IO_DESCRIPTION Description)388ed43b69SDmitry Borisov IsaConvertIoRequirement(
398ed43b69SDmitry Borisov     _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
408ed43b69SDmitry Borisov     _In_ PISAPNP_IO_DESCRIPTION Description)
418ed43b69SDmitry Borisov {
428ed43b69SDmitry Borisov     PAGED_CODE();
438ed43b69SDmitry Borisov 
448ed43b69SDmitry Borisov     Descriptor->Type = CmResourceTypePort;
458ed43b69SDmitry Borisov     Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
468ed43b69SDmitry Borisov     Descriptor->Flags = CM_RESOURCE_PORT_IO;
478ed43b69SDmitry Borisov     if (Description->Information & 0x1)
488ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
498ed43b69SDmitry Borisov     else
508ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
518ed43b69SDmitry Borisov     Descriptor->u.Port.Length = Description->Length;
528ed43b69SDmitry Borisov     Descriptor->u.Port.Alignment = Description->Alignment;
538ed43b69SDmitry Borisov     Descriptor->u.Port.MinimumAddress.LowPart = Description->Minimum;
548ed43b69SDmitry Borisov     Descriptor->u.Port.MaximumAddress.LowPart = Description->Maximum +
558ed43b69SDmitry Borisov                                                 Description->Length - 1;
568ed43b69SDmitry Borisov }
578ed43b69SDmitry Borisov 
588ed43b69SDmitry Borisov static
598ed43b69SDmitry Borisov CODE_SEG("PAGE")
608ed43b69SDmitry Borisov VOID
IsaConvertIrqRequirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,_In_ PISAPNP_IRQ_DESCRIPTION Description,_In_ ULONG Vector,_In_ BOOLEAN FirstDescriptor)618ed43b69SDmitry Borisov IsaConvertIrqRequirement(
628ed43b69SDmitry Borisov     _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
638ed43b69SDmitry Borisov     _In_ PISAPNP_IRQ_DESCRIPTION Description,
648ed43b69SDmitry Borisov     _In_ ULONG Vector,
658ed43b69SDmitry Borisov     _In_ BOOLEAN FirstDescriptor)
668ed43b69SDmitry Borisov {
678ed43b69SDmitry Borisov     PAGED_CODE();
688ed43b69SDmitry Borisov 
698ed43b69SDmitry Borisov     if (!FirstDescriptor)
708ed43b69SDmitry Borisov         Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
718ed43b69SDmitry Borisov     Descriptor->Type = CmResourceTypeInterrupt;
728ed43b69SDmitry Borisov     if (Description->Information & 0xC)
738ed43b69SDmitry Borisov     {
748ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
758ed43b69SDmitry Borisov         Descriptor->ShareDisposition = CmResourceShareShared;
768ed43b69SDmitry Borisov     }
778ed43b69SDmitry Borisov     else
788ed43b69SDmitry Borisov     {
798ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
808ed43b69SDmitry Borisov         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
818ed43b69SDmitry Borisov     }
828ed43b69SDmitry Borisov     Descriptor->u.Interrupt.MinimumVector =
838ed43b69SDmitry Borisov     Descriptor->u.Interrupt.MaximumVector = Vector;
848ed43b69SDmitry Borisov }
858ed43b69SDmitry Borisov 
868ed43b69SDmitry Borisov static
878ed43b69SDmitry Borisov CODE_SEG("PAGE")
888ed43b69SDmitry Borisov VOID
IsaConvertDmaRequirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,_In_ PISAPNP_DMA_DESCRIPTION Description,_In_ ULONG Channel,_In_ BOOLEAN FirstDescriptor)898ed43b69SDmitry Borisov IsaConvertDmaRequirement(
908ed43b69SDmitry Borisov     _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
918ed43b69SDmitry Borisov     _In_ PISAPNP_DMA_DESCRIPTION Description,
928ed43b69SDmitry Borisov     _In_ ULONG Channel,
938ed43b69SDmitry Borisov     _In_ BOOLEAN FirstDescriptor)
948ed43b69SDmitry Borisov {
958ed43b69SDmitry Borisov     UNREFERENCED_PARAMETER(Description);
968ed43b69SDmitry Borisov 
978ed43b69SDmitry Borisov     PAGED_CODE();
988ed43b69SDmitry Borisov 
998ed43b69SDmitry Borisov     if (!FirstDescriptor)
1008ed43b69SDmitry Borisov         Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
1018ed43b69SDmitry Borisov     Descriptor->Type = CmResourceTypeDma;
1028ed43b69SDmitry Borisov     Descriptor->ShareDisposition = CmResourceShareUndetermined;
1038ed43b69SDmitry Borisov     Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */
1048ed43b69SDmitry Borisov     Descriptor->u.Dma.MinimumChannel =
1058ed43b69SDmitry Borisov     Descriptor->u.Dma.MaximumChannel = Channel;
1068ed43b69SDmitry Borisov }
1078ed43b69SDmitry Borisov 
1088ed43b69SDmitry Borisov static
1098ed43b69SDmitry Borisov CODE_SEG("PAGE")
1108ed43b69SDmitry Borisov VOID
IsaConvertMemRangeRequirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,_In_ PISAPNP_MEMRANGE_DESCRIPTION Description)1118ed43b69SDmitry Borisov IsaConvertMemRangeRequirement(
1128ed43b69SDmitry Borisov     _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
1138ed43b69SDmitry Borisov     _In_ PISAPNP_MEMRANGE_DESCRIPTION Description)
1148ed43b69SDmitry Borisov {
1158ed43b69SDmitry Borisov     PAGED_CODE();
1168ed43b69SDmitry Borisov 
1178ed43b69SDmitry Borisov     Descriptor->Type = CmResourceTypeMemory;
1188ed43b69SDmitry Borisov     Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1198ed43b69SDmitry Borisov     Descriptor->Flags = CM_RESOURCE_MEMORY_24;
1208ed43b69SDmitry Borisov     if ((Description->Information & 0x40) || !(Description->Information & 0x01))
1218ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1228ed43b69SDmitry Borisov     else
1238ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1248ed43b69SDmitry Borisov     Descriptor->u.Memory.Length = Description->Length << 8;
1258ed43b69SDmitry Borisov     if (Description->Alignment == 0)
1268ed43b69SDmitry Borisov         Descriptor->u.Memory.Alignment = 0x10000;
1278ed43b69SDmitry Borisov     else
1288ed43b69SDmitry Borisov         Descriptor->u.Memory.Alignment = Description->Alignment;
1298ed43b69SDmitry Borisov     Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum << 8;
1308ed43b69SDmitry Borisov     Descriptor->u.Memory.MaximumAddress.LowPart = (Description->Maximum << 8) +
1318ed43b69SDmitry Borisov                                                   (Description->Length << 8) - 1;
1328ed43b69SDmitry Borisov }
1338ed43b69SDmitry Borisov 
1348ed43b69SDmitry Borisov static
1358ed43b69SDmitry Borisov CODE_SEG("PAGE")
1368ed43b69SDmitry Borisov VOID
IsaConvertMemRange32Requirement(_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,_In_ PISAPNP_MEMRANGE32_DESCRIPTION Description)1378ed43b69SDmitry Borisov IsaConvertMemRange32Requirement(
1388ed43b69SDmitry Borisov     _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
1398ed43b69SDmitry Borisov     _In_ PISAPNP_MEMRANGE32_DESCRIPTION Description)
1408ed43b69SDmitry Borisov {
1418ed43b69SDmitry Borisov     PAGED_CODE();
1428ed43b69SDmitry Borisov 
1438ed43b69SDmitry Borisov     Descriptor->Type = CmResourceTypeMemory;
1448ed43b69SDmitry Borisov     Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1458ed43b69SDmitry Borisov     Descriptor->Flags = CM_RESOURCE_MEMORY_24;
1468ed43b69SDmitry Borisov     if ((Description->Information & 0x40) || !(Description->Information & 0x01))
1478ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
1488ed43b69SDmitry Borisov     else
1498ed43b69SDmitry Borisov         Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
1508ed43b69SDmitry Borisov     Descriptor->u.Memory.Length = Description->Length;
1518ed43b69SDmitry Borisov     Descriptor->u.Memory.Alignment = Description->Alignment;
1528ed43b69SDmitry Borisov     Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum;
1538ed43b69SDmitry Borisov     Descriptor->u.Memory.MaximumAddress.LowPart = Description->Maximum +
1548ed43b69SDmitry Borisov                                                   Description->Length - 1;
1558ed43b69SDmitry Borisov }
1568ed43b69SDmitry Borisov 
15776ec8411SDmitry Borisov /*
15876ec8411SDmitry Borisov  * For example, the PnP ROM
15976ec8411SDmitry Borisov  * 0x15, 0x04, ...                                 // Logical device ID
16076ec8411SDmitry Borisov  * 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, // IO 330, len 4, align 4
16176ec8411SDmitry Borisov  * 0x30,                                           // **** Start DF ****
16276ec8411SDmitry Borisov  * 0x22, 0x04, 0x00,                               // IRQ 2
16376ec8411SDmitry Borisov  * 0x31, 0x02,                                     // **** Start DF ****
16476ec8411SDmitry Borisov  * 0x22, 0xC0, 0x00,                               // IRQ 6 or 7
16576ec8411SDmitry Borisov  * 0x38,                                           // **** End DF ******
16676ec8411SDmitry Borisov  * 0x2A, 0x20, 0x3A,                               // DMA 5
16776ec8411SDmitry Borisov  * 0x22, 0x00, 0x08,                               // IRQ 12
16876ec8411SDmitry Borisov  * 0x79, 0x00,                                     // END
16976ec8411SDmitry Borisov  *
17076ec8411SDmitry Borisov  * becomes the following resource requirements list:
17176ec8411SDmitry Borisov  * Interface 1 Bus 0 Slot 0 AlternativeLists 2
17276ec8411SDmitry Borisov  *
17376ec8411SDmitry Borisov  * AltList #0, AltList->Count 4
17476ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4
17576ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 1]  INT: Min 2 Max 2
17676ec8411SDmitry Borisov  * [Option 0, ShareDisposition 0, Flags 0]  DMA: Min 5 Max 5
17776ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 1]  INT: Min B Max B
17876ec8411SDmitry Borisov  *
17976ec8411SDmitry Borisov  * AltList #1, AltList->Count 5
18076ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4
18176ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 1]  INT: Min 6 Max 6
18276ec8411SDmitry Borisov  * [Option 8, ShareDisposition 1, Flags 1]  INT: Min 7 Max 7
18376ec8411SDmitry Borisov  * [Option 0, ShareDisposition 0, Flags 0]  DMA: Min 5 Max 5
18476ec8411SDmitry Borisov  * [Option 0, ShareDisposition 1, Flags 1]  INT: Min B Max B
18576ec8411SDmitry Borisov  */
1868ed43b69SDmitry Borisov static
1878ed43b69SDmitry Borisov CODE_SEG("PAGE")
18867141abeSHervé Poussineau NTSTATUS
IsaPnpCreateLogicalDeviceRequirements(_In_ PISAPNP_PDO_EXTENSION PdoExt)1898f44930fSDmitry Borisov IsaPnpCreateLogicalDeviceRequirements(
1908f44930fSDmitry Borisov     _In_ PISAPNP_PDO_EXTENSION PdoExt)
19167141abeSHervé Poussineau {
19267141abeSHervé Poussineau     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
19367141abeSHervé Poussineau     PIO_RESOURCE_DESCRIPTOR Descriptor;
19476ec8411SDmitry Borisov     ISAPNP_DEPENDENT_FUNCTION_STATE DfState;
19576ec8411SDmitry Borisov     ULONG FirstFixedDescriptors, LastFixedDescriptors;
19676ec8411SDmitry Borisov     ULONG ResourceCount, AltListCount, ListSize, i;
19776ec8411SDmitry Borisov     BOOLEAN IsFirstAltList, IsFirstDescriptor;
19876ec8411SDmitry Borisov     PIO_RESOURCE_LIST AltList;
19976ec8411SDmitry Borisov     PISAPNP_RESOURCE Resource;
20067141abeSHervé Poussineau 
20170ba96f1SDmitry Borisov     PAGED_CODE();
20270ba96f1SDmitry Borisov 
20376ec8411SDmitry Borisov     /* Count the number of requirements */
20476ec8411SDmitry Borisov     DfState = dfNotStarted;
20576ec8411SDmitry Borisov     FirstFixedDescriptors = 0;
20676ec8411SDmitry Borisov     LastFixedDescriptors = 0;
20776ec8411SDmitry Borisov     ResourceCount = 0;
20876ec8411SDmitry Borisov     AltListCount = 1;
20976ec8411SDmitry Borisov     Resource = PdoExt->IsaPnpDevice->Resources;
21076ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
21167141abeSHervé Poussineau     {
21276ec8411SDmitry Borisov         switch (Resource->Type)
21376ec8411SDmitry Borisov         {
21476ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_START_DEPENDENT:
21576ec8411SDmitry Borisov             {
21676ec8411SDmitry Borisov                 if (DfState == dfStarted)
21776ec8411SDmitry Borisov                     ++AltListCount;
2188f44930fSDmitry Borisov 
21976ec8411SDmitry Borisov                 DfState = dfStarted;
22076ec8411SDmitry Borisov                 break;
22167141abeSHervé Poussineau             }
2228f44930fSDmitry Borisov 
22376ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_END_DEPENDENT:
22467141abeSHervé Poussineau             {
22576ec8411SDmitry Borisov                 DfState = dfDone;
22676ec8411SDmitry Borisov                 break;
22776ec8411SDmitry Borisov             }
2288ed43b69SDmitry Borisov 
22976ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_IRQ:
23076ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_DMA:
2318ed43b69SDmitry Borisov             {
23276ec8411SDmitry Borisov                 RTL_BITMAP ResourceBitmap;
23376ec8411SDmitry Borisov                 ULONG BitmapSize, BitmapBuffer, BitCount;
2348ed43b69SDmitry Borisov 
23576ec8411SDmitry Borisov                 if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ)
2368ed43b69SDmitry Borisov                 {
23776ec8411SDmitry Borisov                     BitmapSize = RTL_BITS_OF(Resource->IrqDescription.Mask);
23876ec8411SDmitry Borisov                     BitmapBuffer = Resource->IrqDescription.Mask;
2398ed43b69SDmitry Borisov                 }
2408ed43b69SDmitry Borisov                 else
2418ed43b69SDmitry Borisov                 {
24276ec8411SDmitry Borisov                     BitmapSize = RTL_BITS_OF(Resource->DmaDescription.Mask);
24376ec8411SDmitry Borisov                     BitmapBuffer = Resource->DmaDescription.Mask;
2448ed43b69SDmitry Borisov                 }
24576ec8411SDmitry Borisov                 RtlInitializeBitMap(&ResourceBitmap, &BitmapBuffer, BitmapSize);
24676ec8411SDmitry Borisov 
24776ec8411SDmitry Borisov                 BitCount = RtlNumberOfSetBits(&ResourceBitmap);
24876ec8411SDmitry Borisov                 switch (DfState)
24976ec8411SDmitry Borisov                 {
25076ec8411SDmitry Borisov                     case dfNotStarted:
25176ec8411SDmitry Borisov                         FirstFixedDescriptors += BitCount;
25276ec8411SDmitry Borisov                         break;
25376ec8411SDmitry Borisov 
25476ec8411SDmitry Borisov                     case dfStarted:
25576ec8411SDmitry Borisov                         ResourceCount += BitCount;
25676ec8411SDmitry Borisov                         break;
25776ec8411SDmitry Borisov 
25876ec8411SDmitry Borisov                     case dfDone:
25976ec8411SDmitry Borisov                         LastFixedDescriptors += BitCount;
26076ec8411SDmitry Borisov                         break;
26176ec8411SDmitry Borisov 
26276ec8411SDmitry Borisov                     DEFAULT_UNREACHABLE;
26376ec8411SDmitry Borisov                 }
26476ec8411SDmitry Borisov 
26576ec8411SDmitry Borisov                 break;
26676ec8411SDmitry Borisov             }
26776ec8411SDmitry Borisov 
26876ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_IO:
26976ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE:
27076ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
27176ec8411SDmitry Borisov             {
27276ec8411SDmitry Borisov                 switch (DfState)
27376ec8411SDmitry Borisov                 {
27476ec8411SDmitry Borisov                     case dfNotStarted:
27576ec8411SDmitry Borisov                         ++FirstFixedDescriptors;
27676ec8411SDmitry Borisov                         break;
27776ec8411SDmitry Borisov 
27876ec8411SDmitry Borisov                     case dfStarted:
27976ec8411SDmitry Borisov                         ++ResourceCount;
28076ec8411SDmitry Borisov                         break;
28176ec8411SDmitry Borisov 
28276ec8411SDmitry Borisov                     case dfDone:
28376ec8411SDmitry Borisov                         ++LastFixedDescriptors;
28476ec8411SDmitry Borisov                         break;
28576ec8411SDmitry Borisov 
28676ec8411SDmitry Borisov                     DEFAULT_UNREACHABLE;
28776ec8411SDmitry Borisov                 }
28876ec8411SDmitry Borisov                 break;
28976ec8411SDmitry Borisov             }
29076ec8411SDmitry Borisov 
29176ec8411SDmitry Borisov             default:
29276ec8411SDmitry Borisov                 ASSERT(FALSE);
29376ec8411SDmitry Borisov                 UNREACHABLE;
29476ec8411SDmitry Borisov                 break;
29576ec8411SDmitry Borisov         }
29676ec8411SDmitry Borisov 
29776ec8411SDmitry Borisov         ++Resource;
29876ec8411SDmitry Borisov     }
29976ec8411SDmitry Borisov 
30076ec8411SDmitry Borisov     /* This logical device has no resource requirements */
30176ec8411SDmitry Borisov     if ((ResourceCount == 0) && (FirstFixedDescriptors == 0) && (LastFixedDescriptors == 0))
30276ec8411SDmitry Borisov         return STATUS_SUCCESS;
30376ec8411SDmitry Borisov 
30476ec8411SDmitry Borisov     /* Allocate memory to store requirements */
30576ec8411SDmitry Borisov     ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
30676ec8411SDmitry Borisov                FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) * AltListCount +
30776ec8411SDmitry Borisov                sizeof(IO_RESOURCE_DESCRIPTOR) * ResourceCount +
30876ec8411SDmitry Borisov                sizeof(IO_RESOURCE_DESCRIPTOR) * AltListCount *
30976ec8411SDmitry Borisov                (FirstFixedDescriptors + LastFixedDescriptors);
31066c19575SDmitry Borisov     RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
31167141abeSHervé Poussineau     if (!RequirementsList)
31267141abeSHervé Poussineau         return STATUS_NO_MEMORY;
31367141abeSHervé Poussineau 
31467141abeSHervé Poussineau     RequirementsList->ListSize = ListSize;
31567141abeSHervé Poussineau     RequirementsList->InterfaceType = Isa;
31676ec8411SDmitry Borisov     RequirementsList->AlternativeLists = AltListCount;
31767141abeSHervé Poussineau 
31867141abeSHervé Poussineau     RequirementsList->List[0].Version = 1;
31967141abeSHervé Poussineau     RequirementsList->List[0].Revision = 1;
32067141abeSHervé Poussineau 
32167141abeSHervé Poussineau     /* Store requirements */
32276ec8411SDmitry Borisov     IsFirstAltList = TRUE;
32376ec8411SDmitry Borisov     AltList = &RequirementsList->List[0];
32476ec8411SDmitry Borisov     Descriptor = &RequirementsList->List[0].Descriptors[0];
32576ec8411SDmitry Borisov     Resource = PdoExt->IsaPnpDevice->Resources;
32676ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
32767141abeSHervé Poussineau     {
32876ec8411SDmitry Borisov         switch (Resource->Type)
32967141abeSHervé Poussineau         {
33076ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_START_DEPENDENT:
33167141abeSHervé Poussineau             {
33276ec8411SDmitry Borisov                 if (!IsFirstAltList)
3337cda1ed2SHervé Poussineau                 {
33476ec8411SDmitry Borisov                     /* Add room for the fixed descriptors */
33576ec8411SDmitry Borisov                     AltList->Count += LastFixedDescriptors;
3368f44930fSDmitry Borisov 
33776ec8411SDmitry Borisov                     /* Move on to the next list */
33876ec8411SDmitry Borisov                     AltList = (PIO_RESOURCE_LIST)(AltList->Descriptors + AltList->Count);
33976ec8411SDmitry Borisov                     AltList->Version = 1;
34076ec8411SDmitry Borisov                     AltList->Revision = 1;
3418ed43b69SDmitry Borisov 
3428ed43b69SDmitry Borisov                     /* Propagate the fixed resources to our new list */
34376ec8411SDmitry Borisov                     RtlCopyMemory(&AltList->Descriptors,
34476ec8411SDmitry Borisov                                   RequirementsList->List[0].Descriptors,
34576ec8411SDmitry Borisov                                   sizeof(IO_RESOURCE_DESCRIPTOR) * FirstFixedDescriptors);
34676ec8411SDmitry Borisov                     AltList->Count += FirstFixedDescriptors;
34776ec8411SDmitry Borisov 
34876ec8411SDmitry Borisov                     Descriptor = &AltList->Descriptors[FirstFixedDescriptors];
3498ed43b69SDmitry Borisov                 }
3508ed43b69SDmitry Borisov 
35176ec8411SDmitry Borisov                 IsFirstAltList = FALSE;
35276ec8411SDmitry Borisov                 break;
3538ed43b69SDmitry Borisov             }
3548ed43b69SDmitry Borisov 
35576ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_END_DEPENDENT:
35676ec8411SDmitry Borisov                 break;
35776ec8411SDmitry Borisov 
35876ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_IO:
3598ed43b69SDmitry Borisov             {
36076ec8411SDmitry Borisov                 IsaConvertIoRequirement(Descriptor++, &Resource->IoDescription);
36176ec8411SDmitry Borisov 
36276ec8411SDmitry Borisov                 ++AltList->Count;
36376ec8411SDmitry Borisov                 break;
36476ec8411SDmitry Borisov             }
36576ec8411SDmitry Borisov 
36676ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_IRQ:
36776ec8411SDmitry Borisov             {
36876ec8411SDmitry Borisov                 IsFirstDescriptor = TRUE;
36976ec8411SDmitry Borisov 
37076ec8411SDmitry Borisov                 for (i = 0; i < RTL_BITS_OF(Resource->IrqDescription.Mask); i++)
37176ec8411SDmitry Borisov                 {
37276ec8411SDmitry Borisov                     if (!(Resource->IrqDescription.Mask & (1 << i)))
3738ed43b69SDmitry Borisov                         continue;
3748ed43b69SDmitry Borisov 
3758ed43b69SDmitry Borisov                     IsaConvertIrqRequirement(Descriptor++,
37676ec8411SDmitry Borisov                                              &Resource->IrqDescription,
37776ec8411SDmitry Borisov                                              i,
37876ec8411SDmitry Borisov                                              IsFirstDescriptor);
37976ec8411SDmitry Borisov                     ++AltList->Count;
3808ed43b69SDmitry Borisov 
38176ec8411SDmitry Borisov                     IsFirstDescriptor = FALSE;
3827cda1ed2SHervé Poussineau                 }
3838ed43b69SDmitry Borisov 
38476ec8411SDmitry Borisov                 break;
38576ec8411SDmitry Borisov             }
38676ec8411SDmitry Borisov 
38776ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_DMA:
3888ed43b69SDmitry Borisov             {
38976ec8411SDmitry Borisov                 IsFirstDescriptor = TRUE;
39076ec8411SDmitry Borisov 
39176ec8411SDmitry Borisov                 for (i = 0; i < RTL_BITS_OF(Resource->DmaDescription.Mask); i++)
39276ec8411SDmitry Borisov                 {
39376ec8411SDmitry Borisov                     if (!(Resource->DmaDescription.Mask & (1 << i)))
3948ed43b69SDmitry Borisov                         continue;
3958ed43b69SDmitry Borisov 
3968ed43b69SDmitry Borisov                     IsaConvertDmaRequirement(Descriptor++,
39776ec8411SDmitry Borisov                                              &Resource->DmaDescription,
39876ec8411SDmitry Borisov                                              i,
39976ec8411SDmitry Borisov                                              IsFirstDescriptor);
40076ec8411SDmitry Borisov                     ++AltList->Count;
4018ed43b69SDmitry Borisov 
40276ec8411SDmitry Borisov                     IsFirstDescriptor = FALSE;
4038ed43b69SDmitry Borisov                 }
40476ec8411SDmitry Borisov 
40576ec8411SDmitry Borisov                 break;
4068ed43b69SDmitry Borisov             }
40776ec8411SDmitry Borisov 
40876ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE:
4098ed43b69SDmitry Borisov             {
41076ec8411SDmitry Borisov                 IsaConvertMemRangeRequirement(Descriptor++, &Resource->MemRangeDescription);
41176ec8411SDmitry Borisov 
41276ec8411SDmitry Borisov                 ++AltList->Count;
41376ec8411SDmitry Borisov                 break;
4148ed43b69SDmitry Borisov             }
41576ec8411SDmitry Borisov 
41676ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
4178ed43b69SDmitry Borisov             {
41876ec8411SDmitry Borisov                 IsaConvertMemRange32Requirement(Descriptor++, &Resource->MemRange32Description);
41976ec8411SDmitry Borisov 
42076ec8411SDmitry Borisov                 ++AltList->Count;
42176ec8411SDmitry Borisov                 break;
4228ed43b69SDmitry Borisov             }
4238ed43b69SDmitry Borisov 
42476ec8411SDmitry Borisov             default:
42576ec8411SDmitry Borisov                 ASSERT(FALSE);
42676ec8411SDmitry Borisov                 UNREACHABLE;
42776ec8411SDmitry Borisov                 break;
42876ec8411SDmitry Borisov         }
42976ec8411SDmitry Borisov 
43076ec8411SDmitry Borisov         ++Resource;
43176ec8411SDmitry Borisov     }
43276ec8411SDmitry Borisov 
43376ec8411SDmitry Borisov     /* Append the fixed resources */
43476ec8411SDmitry Borisov     if (LastFixedDescriptors)
43576ec8411SDmitry Borisov     {
43676ec8411SDmitry Borisov         PIO_RESOURCE_LIST NextList = &RequirementsList->List[0];
43776ec8411SDmitry Borisov 
43876ec8411SDmitry Borisov         /* Make the descriptor point to the fixed resources */
43976ec8411SDmitry Borisov         Descriptor -= LastFixedDescriptors;
44076ec8411SDmitry Borisov 
44176ec8411SDmitry Borisov         /* Propagate the fixed resources onto previous lists */
44276ec8411SDmitry Borisov         AltListCount = RequirementsList->AlternativeLists - 1;
44376ec8411SDmitry Borisov         for (i = 0; i < AltListCount; i++)
44476ec8411SDmitry Borisov         {
44576ec8411SDmitry Borisov             RtlCopyMemory(&NextList->Descriptors[NextList->Count - LastFixedDescriptors],
44676ec8411SDmitry Borisov                           Descriptor,
44776ec8411SDmitry Borisov                           sizeof(IO_RESOURCE_DESCRIPTOR) * LastFixedDescriptors);
44876ec8411SDmitry Borisov 
4498ed43b69SDmitry Borisov             NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count);
4507cda1ed2SHervé Poussineau         }
4517cda1ed2SHervé Poussineau     }
45267141abeSHervé Poussineau 
45367141abeSHervé Poussineau     PdoExt->RequirementsList = RequirementsList;
45467141abeSHervé Poussineau     return STATUS_SUCCESS;
45567141abeSHervé Poussineau }
45667141abeSHervé Poussineau 
4578ed43b69SDmitry Borisov CODE_SEG("PAGE")
4588ed43b69SDmitry Borisov BOOLEAN
FindIoDescriptor(_In_ PISAPNP_LOGICAL_DEVICE LogDevice,_In_opt_ ULONG Base,_In_ ULONG RangeStart,_In_ ULONG RangeEnd,_Out_opt_ PUCHAR Information,_Out_opt_ PULONG Length)4598ed43b69SDmitry Borisov FindIoDescriptor(
4608ed43b69SDmitry Borisov     _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
4618ed43b69SDmitry Borisov     _In_opt_ ULONG Base,
4628ed43b69SDmitry Borisov     _In_ ULONG RangeStart,
4638ed43b69SDmitry Borisov     _In_ ULONG RangeEnd,
4648ed43b69SDmitry Borisov     _Out_opt_ PUCHAR Information,
46576ec8411SDmitry Borisov     _Out_opt_ PULONG Length)
4668ed43b69SDmitry Borisov {
46776ec8411SDmitry Borisov     PISAPNP_RESOURCE Resource;
4688ed43b69SDmitry Borisov 
4698ed43b69SDmitry Borisov     PAGED_CODE();
4708ed43b69SDmitry Borisov 
47176ec8411SDmitry Borisov     Resource = LogDevice->Resources;
47276ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
4738ed43b69SDmitry Borisov     {
47476ec8411SDmitry Borisov         if (Resource->Type == ISAPNP_RESOURCE_TYPE_IO)
47576ec8411SDmitry Borisov         {
47676ec8411SDmitry Borisov             PISAPNP_IO_DESCRIPTION Description = &Resource->IoDescription;
47776ec8411SDmitry Borisov             BOOLEAN Match;
4788ed43b69SDmitry Borisov 
47976ec8411SDmitry Borisov             if (Base)
48076ec8411SDmitry Borisov             {
48176ec8411SDmitry Borisov                 Match = (Base >= Description->Minimum) && (Base <= Description->Maximum);
48276ec8411SDmitry Borisov             }
48376ec8411SDmitry Borisov             else
48476ec8411SDmitry Borisov             {
48576ec8411SDmitry Borisov                 Match = (RangeStart >= Description->Minimum) &&
4868ed43b69SDmitry Borisov                         (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1));
48776ec8411SDmitry Borisov             }
4888ed43b69SDmitry Borisov 
4898ed43b69SDmitry Borisov             if (Match)
4908ed43b69SDmitry Borisov             {
4918ed43b69SDmitry Borisov                 if (Information)
4928ed43b69SDmitry Borisov                     *Information = Description->Information;
4938ed43b69SDmitry Borisov                 if (Length)
4948ed43b69SDmitry Borisov                     *Length = Description->Length;
4958ed43b69SDmitry Borisov 
4968ed43b69SDmitry Borisov                 return TRUE;
4978ed43b69SDmitry Borisov             }
4988ed43b69SDmitry Borisov         }
4998ed43b69SDmitry Borisov 
50076ec8411SDmitry Borisov         ++Resource;
5018ed43b69SDmitry Borisov     }
5028ed43b69SDmitry Borisov 
5038ed43b69SDmitry Borisov     return FALSE;
5048ed43b69SDmitry Borisov }
5058ed43b69SDmitry Borisov 
5068ed43b69SDmitry Borisov CODE_SEG("PAGE")
5078ed43b69SDmitry Borisov BOOLEAN
FindIrqDescriptor(_In_ PISAPNP_LOGICAL_DEVICE LogDevice,_In_ ULONG Vector)5088ed43b69SDmitry Borisov FindIrqDescriptor(
5098ed43b69SDmitry Borisov     _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
51076ec8411SDmitry Borisov     _In_ ULONG Vector)
5118ed43b69SDmitry Borisov {
51276ec8411SDmitry Borisov     PISAPNP_RESOURCE Resource;
5138ed43b69SDmitry Borisov 
5148ed43b69SDmitry Borisov     PAGED_CODE();
5158ed43b69SDmitry Borisov 
51676ec8411SDmitry Borisov     Resource = LogDevice->Resources;
51776ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
5188ed43b69SDmitry Borisov     {
51976ec8411SDmitry Borisov         if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ)
52076ec8411SDmitry Borisov         {
52176ec8411SDmitry Borisov             PISAPNP_IRQ_DESCRIPTION Description = &Resource->IrqDescription;
5228ed43b69SDmitry Borisov 
52376ec8411SDmitry Borisov             if (Description->Mask & (1 << Vector))
5248ed43b69SDmitry Borisov                 return TRUE;
5258ed43b69SDmitry Borisov         }
5268ed43b69SDmitry Borisov 
52776ec8411SDmitry Borisov         ++Resource;
5288ed43b69SDmitry Borisov     }
5298ed43b69SDmitry Borisov 
5308ed43b69SDmitry Borisov     return FALSE;
5318ed43b69SDmitry Borisov }
5328ed43b69SDmitry Borisov 
5338ed43b69SDmitry Borisov CODE_SEG("PAGE")
5348ed43b69SDmitry Borisov BOOLEAN
FindDmaDescriptor(_In_ PISAPNP_LOGICAL_DEVICE LogDevice,_In_ ULONG Channel)5358ed43b69SDmitry Borisov FindDmaDescriptor(
5368ed43b69SDmitry Borisov     _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
53776ec8411SDmitry Borisov     _In_ ULONG Channel)
5388ed43b69SDmitry Borisov {
53976ec8411SDmitry Borisov     PISAPNP_RESOURCE Resource;
5408ed43b69SDmitry Borisov 
5418ed43b69SDmitry Borisov     PAGED_CODE();
5428ed43b69SDmitry Borisov 
54376ec8411SDmitry Borisov     Resource = LogDevice->Resources;
54476ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
5458ed43b69SDmitry Borisov     {
54676ec8411SDmitry Borisov         if (Resource->Type == ISAPNP_RESOURCE_TYPE_DMA)
54776ec8411SDmitry Borisov         {
54876ec8411SDmitry Borisov             PISAPNP_DMA_DESCRIPTION Description = &Resource->DmaDescription;
5498ed43b69SDmitry Borisov 
55076ec8411SDmitry Borisov             if (Description->Mask & (1 << Channel))
5518ed43b69SDmitry Borisov                 return TRUE;
5528ed43b69SDmitry Borisov         }
5538ed43b69SDmitry Borisov 
55476ec8411SDmitry Borisov         ++Resource;
5558ed43b69SDmitry Borisov     }
5568ed43b69SDmitry Borisov 
5578ed43b69SDmitry Borisov     return FALSE;
5588ed43b69SDmitry Borisov }
5598ed43b69SDmitry Borisov 
5608ed43b69SDmitry Borisov CODE_SEG("PAGE")
5618ed43b69SDmitry Borisov BOOLEAN
FindMemoryDescriptor(_In_ PISAPNP_LOGICAL_DEVICE LogDevice,_In_ ULONG RangeStart,_In_ ULONG RangeEnd,_Out_opt_ PUCHAR Information)5628ed43b69SDmitry Borisov FindMemoryDescriptor(
5638ed43b69SDmitry Borisov     _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
5648ed43b69SDmitry Borisov     _In_ ULONG RangeStart,
5658ed43b69SDmitry Borisov     _In_ ULONG RangeEnd,
56676ec8411SDmitry Borisov     _Out_opt_ PUCHAR Information)
5678ed43b69SDmitry Borisov {
56876ec8411SDmitry Borisov     PISAPNP_RESOURCE Resource;
5698ed43b69SDmitry Borisov 
5708ed43b69SDmitry Borisov     PAGED_CODE();
5718ed43b69SDmitry Borisov 
57276ec8411SDmitry Borisov     Resource = LogDevice->Resources;
57376ec8411SDmitry Borisov     while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
5748ed43b69SDmitry Borisov     {
57576ec8411SDmitry Borisov         switch (Resource->Type)
57676ec8411SDmitry Borisov         {
57776ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE:
57876ec8411SDmitry Borisov             {
57976ec8411SDmitry Borisov                 PISAPNP_MEMRANGE_DESCRIPTION Description;
58076ec8411SDmitry Borisov 
58176ec8411SDmitry Borisov                 Description = &Resource->MemRangeDescription;
5828ed43b69SDmitry Borisov 
5838ed43b69SDmitry Borisov                 if ((RangeStart >= (ULONG)(Description->Minimum << 8)) &&
58476ec8411SDmitry Borisov                     (RangeEnd <= (ULONG)((Description->Maximum << 8) +
58576ec8411SDmitry Borisov                                          (Description->Length << 8) - 1)))
5868ed43b69SDmitry Borisov                 {
5878ed43b69SDmitry Borisov                     if (Information)
5888ed43b69SDmitry Borisov                         *Information = Description->Information;
5898ed43b69SDmitry Borisov 
5908ed43b69SDmitry Borisov                     return TRUE;
5918ed43b69SDmitry Borisov                 }
59276ec8411SDmitry Borisov                 break;
5938ed43b69SDmitry Borisov             }
59476ec8411SDmitry Borisov 
59576ec8411SDmitry Borisov             case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
5968ed43b69SDmitry Borisov             {
59776ec8411SDmitry Borisov                 PISAPNP_MEMRANGE32_DESCRIPTION Description32;
59876ec8411SDmitry Borisov 
59976ec8411SDmitry Borisov                 Description32 = &Resource->MemRange32Description;
6008ed43b69SDmitry Borisov 
6018ed43b69SDmitry Borisov                 if ((RangeStart >= Description32->Minimum) &&
6028ed43b69SDmitry Borisov                     (RangeEnd <= (Description32->Maximum + Description32->Length - 1)))
6038ed43b69SDmitry Borisov                 {
6048ed43b69SDmitry Borisov                     if (Information)
6058ed43b69SDmitry Borisov                         *Information = Description32->Information;
6068ed43b69SDmitry Borisov 
6078ed43b69SDmitry Borisov                     return TRUE;
6088ed43b69SDmitry Borisov                 }
60976ec8411SDmitry Borisov                 break;
6108ed43b69SDmitry Borisov             }
6118ed43b69SDmitry Borisov 
61276ec8411SDmitry Borisov             default:
61376ec8411SDmitry Borisov                 break;
6148ed43b69SDmitry Borisov         }
6158ed43b69SDmitry Borisov 
61676ec8411SDmitry Borisov         ++Resource;
6178ed43b69SDmitry Borisov     }
6188ed43b69SDmitry Borisov 
6198ed43b69SDmitry Borisov     return FALSE;
6208ed43b69SDmitry Borisov }
6218ed43b69SDmitry Borisov 
62267141abeSHervé Poussineau static
62370ba96f1SDmitry Borisov CODE_SEG("PAGE")
62467141abeSHervé Poussineau NTSTATUS
IsaPnpCreateLogicalDeviceResources(_In_ PISAPNP_PDO_EXTENSION PdoExt)6258f44930fSDmitry Borisov IsaPnpCreateLogicalDeviceResources(
6268f44930fSDmitry Borisov     _In_ PISAPNP_PDO_EXTENSION PdoExt)
62767141abeSHervé Poussineau {
62867141abeSHervé Poussineau     PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
62967141abeSHervé Poussineau     ULONG ResourceCount = 0;
6308ed43b69SDmitry Borisov     UCHAR Information;
63167141abeSHervé Poussineau     ULONG ListSize, i;
63267141abeSHervé Poussineau     PCM_RESOURCE_LIST ResourceList;
63367141abeSHervé Poussineau     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
63467141abeSHervé Poussineau 
63570ba96f1SDmitry Borisov     PAGED_CODE();
63670ba96f1SDmitry Borisov 
6378ed43b69SDmitry Borisov     if (!(LogDev->Flags & ISAPNP_HAS_RESOURCES))
6388ed43b69SDmitry Borisov         return STATUS_SUCCESS;
6398ed43b69SDmitry Borisov 
64067141abeSHervé Poussineau     /* Count number of required resources */
6418f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++)
64267141abeSHervé Poussineau     {
64367141abeSHervé Poussineau         if (LogDev->Io[i].CurrentBase)
64467141abeSHervé Poussineau             ResourceCount++;
64567141abeSHervé Poussineau         else
64667141abeSHervé Poussineau             break;
64767141abeSHervé Poussineau     }
6488f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++)
64967141abeSHervé Poussineau     {
65067141abeSHervé Poussineau         if (LogDev->Irq[i].CurrentNo)
65167141abeSHervé Poussineau             ResourceCount++;
65267141abeSHervé Poussineau         else
65367141abeSHervé Poussineau             break;
65467141abeSHervé Poussineau     }
6558f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
6567cda1ed2SHervé Poussineau     {
6572981e63aSDmitry Borisov         if (LogDev->Dma[i].CurrentChannel != DMACHANNEL_NONE)
6587cda1ed2SHervé Poussineau             ResourceCount++;
6597cda1ed2SHervé Poussineau         else
6607cda1ed2SHervé Poussineau             break;
6617cda1ed2SHervé Poussineau     }
6628ed43b69SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++)
6638ed43b69SDmitry Borisov     {
6648ed43b69SDmitry Borisov         if (LogDev->MemRange[i].CurrentBase)
6658ed43b69SDmitry Borisov             ResourceCount++;
6668ed43b69SDmitry Borisov         else
6678ed43b69SDmitry Borisov             break;
6688ed43b69SDmitry Borisov     }
6698ed43b69SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++)
6708ed43b69SDmitry Borisov     {
6718ed43b69SDmitry Borisov         if (LogDev->MemRange32[i].CurrentBase)
6728ed43b69SDmitry Borisov             ResourceCount++;
6738ed43b69SDmitry Borisov         else
6748ed43b69SDmitry Borisov             break;
6758ed43b69SDmitry Borisov     }
67667141abeSHervé Poussineau     if (ResourceCount == 0)
67767141abeSHervé Poussineau         return STATUS_SUCCESS;
67867141abeSHervé Poussineau 
67967141abeSHervé Poussineau     /* Allocate memory to store resources */
68067141abeSHervé Poussineau     ListSize = sizeof(CM_RESOURCE_LIST)
68167141abeSHervé Poussineau                + (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
68266c19575SDmitry Borisov     ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
68367141abeSHervé Poussineau     if (!ResourceList)
68467141abeSHervé Poussineau         return STATUS_NO_MEMORY;
68567141abeSHervé Poussineau 
68667141abeSHervé Poussineau     ResourceList->Count = 1;
68767141abeSHervé Poussineau     ResourceList->List[0].InterfaceType = Isa;
68867141abeSHervé Poussineau     ResourceList->List[0].PartialResourceList.Version = 1;
68967141abeSHervé Poussineau     ResourceList->List[0].PartialResourceList.Revision = 1;
69067141abeSHervé Poussineau     ResourceList->List[0].PartialResourceList.Count = ResourceCount;
69167141abeSHervé Poussineau 
69267141abeSHervé Poussineau     /* Store resources */
69367141abeSHervé Poussineau     ResourceCount = 0;
6948f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++)
69567141abeSHervé Poussineau     {
6968ed43b69SDmitry Borisov         ULONG CurrentLength;
6978ed43b69SDmitry Borisov 
69867141abeSHervé Poussineau         if (!LogDev->Io[i].CurrentBase)
6998f36dee6SDmitry Borisov             break;
7008f44930fSDmitry Borisov 
7018ed43b69SDmitry Borisov         if (!FindIoDescriptor(LogDev,
7028ed43b69SDmitry Borisov                               LogDev->Io[i].CurrentBase,
7038ed43b69SDmitry Borisov                               0,
7048ed43b69SDmitry Borisov                               0,
7058ed43b69SDmitry Borisov                               &Information,
70676ec8411SDmitry Borisov                               &CurrentLength))
7078ed43b69SDmitry Borisov         {
70876ec8411SDmitry Borisov             DPRINT1("I/O entry #%lu %x not found\n", i, LogDev->Io[i].CurrentBase);
7098ed43b69SDmitry Borisov             goto InvalidBiosResources;
7108ed43b69SDmitry Borisov         }
7118ed43b69SDmitry Borisov 
71267141abeSHervé Poussineau         Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
71367141abeSHervé Poussineau         Descriptor->Type = CmResourceTypePort;
71467141abeSHervé Poussineau         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
7158ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_PORT_IO;
7168ed43b69SDmitry Borisov         if (Information & 0x1)
7178ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
71867141abeSHervé Poussineau         else
7198ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
7208ed43b69SDmitry Borisov         Descriptor->u.Port.Length = CurrentLength;
72167141abeSHervé Poussineau         Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase;
72267141abeSHervé Poussineau     }
7238f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++)
72467141abeSHervé Poussineau     {
72567141abeSHervé Poussineau         if (!LogDev->Irq[i].CurrentNo)
7268f36dee6SDmitry Borisov             break;
7278f44930fSDmitry Borisov 
72867141abeSHervé Poussineau         Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
72967141abeSHervé Poussineau         Descriptor->Type = CmResourceTypeInterrupt;
73067141abeSHervé Poussineau         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
73167141abeSHervé Poussineau         if (LogDev->Irq[i].CurrentType & 0x01)
73267141abeSHervé Poussineau             Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
73367141abeSHervé Poussineau         else
73467141abeSHervé Poussineau             Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
73567141abeSHervé Poussineau         Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo;
73667141abeSHervé Poussineau         Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo;
73776ec8411SDmitry Borisov         Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
73867141abeSHervé Poussineau     }
7398f44930fSDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
7407cda1ed2SHervé Poussineau     {
7412981e63aSDmitry Borisov         if (LogDev->Dma[i].CurrentChannel == DMACHANNEL_NONE)
7428f36dee6SDmitry Borisov             break;
7438f44930fSDmitry Borisov 
7447cda1ed2SHervé Poussineau         Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
7457cda1ed2SHervé Poussineau         Descriptor->Type = CmResourceTypeDma;
7467cda1ed2SHervé Poussineau         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
7478ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */
7487cda1ed2SHervé Poussineau         Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel;
7497cda1ed2SHervé Poussineau     }
7508ed43b69SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++)
7518ed43b69SDmitry Borisov     {
7528ed43b69SDmitry Borisov         if (!LogDev->MemRange[i].CurrentBase)
7538ed43b69SDmitry Borisov             break;
7548ed43b69SDmitry Borisov 
7558ed43b69SDmitry Borisov         if (!FindMemoryDescriptor(LogDev,
7568ed43b69SDmitry Borisov                                   LogDev->MemRange[i].CurrentBase,
7578ed43b69SDmitry Borisov                                   LogDev->MemRange[i].CurrentLength,
75876ec8411SDmitry Borisov                                   &Information))
7598ed43b69SDmitry Borisov         {
76076ec8411SDmitry Borisov             DPRINT1("MEM entry #%lu %lx %lx not found\n",
76176ec8411SDmitry Borisov                     i,
76276ec8411SDmitry Borisov                     LogDev->MemRange[i].CurrentBase,
76376ec8411SDmitry Borisov                     LogDev->MemRange[i].CurrentLength);
7648ed43b69SDmitry Borisov             goto InvalidBiosResources;
7658ed43b69SDmitry Borisov         }
7668ed43b69SDmitry Borisov 
7678ed43b69SDmitry Borisov         Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
7688ed43b69SDmitry Borisov         Descriptor->Type = CmResourceTypeMemory;
7698ed43b69SDmitry Borisov         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
7708ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_MEMORY_24;
7718ed43b69SDmitry Borisov         if ((Information & 0x40) || !(Information & 0x01))
7728ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
7738ed43b69SDmitry Borisov         else
7748ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
775c1d70873SDmitry Borisov         Descriptor->u.Memory.Length = LogDev->MemRange[i].CurrentLength;
7768ed43b69SDmitry Borisov         Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange[i].CurrentBase;
7778ed43b69SDmitry Borisov     }
7788ed43b69SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++)
7798ed43b69SDmitry Borisov     {
7808ed43b69SDmitry Borisov         if (!LogDev->MemRange32[i].CurrentBase)
7818ed43b69SDmitry Borisov             break;
7828ed43b69SDmitry Borisov 
7838ed43b69SDmitry Borisov         if (!FindMemoryDescriptor(LogDev,
7848ed43b69SDmitry Borisov                                   LogDev->MemRange32[i].CurrentBase,
7858ed43b69SDmitry Borisov                                   LogDev->MemRange32[i].CurrentLength,
78676ec8411SDmitry Borisov                                   &Information))
7878ed43b69SDmitry Borisov         {
78876ec8411SDmitry Borisov             DPRINT1("MEM32 entry #%lu %lx %lx not found\n",
78976ec8411SDmitry Borisov                     i,
79076ec8411SDmitry Borisov                     LogDev->MemRange32[i].CurrentBase,
79176ec8411SDmitry Borisov                     LogDev->MemRange32[i].CurrentLength);
7928ed43b69SDmitry Borisov             goto InvalidBiosResources;
7938ed43b69SDmitry Borisov         }
7948ed43b69SDmitry Borisov 
7958ed43b69SDmitry Borisov         Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
7968ed43b69SDmitry Borisov         Descriptor->Type = CmResourceTypeMemory;
7978ed43b69SDmitry Borisov         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
7988ed43b69SDmitry Borisov         Descriptor->Flags = CM_RESOURCE_MEMORY_24;
7998ed43b69SDmitry Borisov         if ((Information & 0x40) || !(Information & 0x01))
8008ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
8018ed43b69SDmitry Borisov         else
8028ed43b69SDmitry Borisov             Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
803c1d70873SDmitry Borisov         Descriptor->u.Memory.Length = LogDev->MemRange32[i].CurrentLength;
8048ed43b69SDmitry Borisov         Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange32[i].CurrentBase;
8058ed43b69SDmitry Borisov     }
80667141abeSHervé Poussineau 
80767141abeSHervé Poussineau     PdoExt->ResourceList = ResourceList;
80867141abeSHervé Poussineau     PdoExt->ResourceListSize = ListSize;
80967141abeSHervé Poussineau     return STATUS_SUCCESS;
8108ed43b69SDmitry Borisov 
8118ed43b69SDmitry Borisov InvalidBiosResources:
81276ec8411SDmitry Borisov     DPRINT1("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN);
8138ed43b69SDmitry Borisov 
8148ed43b69SDmitry Borisov     LogDev->Flags &= ~ISAPNP_HAS_RESOURCES;
8158ed43b69SDmitry Borisov     ExFreePoolWithTag(ResourceList, TAG_ISAPNP);
8168ed43b69SDmitry Borisov     return STATUS_SUCCESS;
81767141abeSHervé Poussineau }
81867141abeSHervé Poussineau 
81970ba96f1SDmitry Borisov CODE_SEG("PAGE")
8204ba8a8b5SDmitry Borisov PIO_RESOURCE_REQUIREMENTS_LIST
IsaPnpCreateReadPortDORequirements(_In_opt_ ULONG SelectedReadPort)821debec8c9SHervé Poussineau IsaPnpCreateReadPortDORequirements(
822c4b6330bSDmitry Borisov     _In_opt_ ULONG SelectedReadPort)
823debec8c9SHervé Poussineau {
824c4b6330bSDmitry Borisov     ULONG ResourceCount, ListSize, i;
825debec8c9SHervé Poussineau     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
826debec8c9SHervé Poussineau     PIO_RESOURCE_DESCRIPTOR Descriptor;
827c4b6330bSDmitry Borisov     const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
828debec8c9SHervé Poussineau 
82970ba96f1SDmitry Borisov     PAGED_CODE();
83070ba96f1SDmitry Borisov 
831c4b6330bSDmitry Borisov     if (SelectedReadPort)
832c4b6330bSDmitry Borisov     {
833c4b6330bSDmitry Borisov         /*
834c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_WRITE_DATA, required]
835c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_WRITE_DATA, optional]
836c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_ADDRESS, required]
837c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_ADDRESS, optional]
838c4b6330bSDmitry Borisov          * [IO descriptor: Selected Read Port, required]
839c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 1, optional]
840c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 2, optional]
841c4b6330bSDmitry Borisov          * [...]
842c4b6330bSDmitry Borisov          * [IO descriptor: Read Port X - 1, optional]
843c4b6330bSDmitry Borisov          */
844*10b08aa2SDmitry Borisov         ResourceCount = RTL_NUMBER_OF(IsaConfigPorts) * 2 + RTL_NUMBER_OF(ReadPorts);
845c4b6330bSDmitry Borisov     }
846c4b6330bSDmitry Borisov     else
847c4b6330bSDmitry Borisov     {
848c4b6330bSDmitry Borisov         /*
849c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_WRITE_DATA, required]
850c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_WRITE_DATA, optional]
851c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_ADDRESS, required]
852c4b6330bSDmitry Borisov          * [IO descriptor: ISAPNP_ADDRESS, optional]
853c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 1, required]
854c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 1, optional]
855c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 2, required]
856c4b6330bSDmitry Borisov          * [IO descriptor: Read Port 2, optional]
857c4b6330bSDmitry Borisov          * [...]
858c4b6330bSDmitry Borisov          * [IO descriptor: Read Port X, required]
859c4b6330bSDmitry Borisov          * [IO descriptor: Read Port X, optional]
860c4b6330bSDmitry Borisov          */
861*10b08aa2SDmitry Borisov         ResourceCount = (RTL_NUMBER_OF(IsaConfigPorts) + RTL_NUMBER_OF(ReadPorts)) * 2;
862c4b6330bSDmitry Borisov     }
863c4b6330bSDmitry Borisov     ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
864c4b6330bSDmitry Borisov                sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1);
86566c19575SDmitry Borisov     RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
866debec8c9SHervé Poussineau     if (!RequirementsList)
8674ba8a8b5SDmitry Borisov         return NULL;
868debec8c9SHervé Poussineau 
869debec8c9SHervé Poussineau     RequirementsList->ListSize = ListSize;
870debec8c9SHervé Poussineau     RequirementsList->AlternativeLists = 1;
871debec8c9SHervé Poussineau 
872debec8c9SHervé Poussineau     RequirementsList->List[0].Version = 1;
873debec8c9SHervé Poussineau     RequirementsList->List[0].Revision = 1;
874c4b6330bSDmitry Borisov     RequirementsList->List[0].Count = ResourceCount;
875debec8c9SHervé Poussineau 
876c4b6330bSDmitry Borisov     Descriptor = &RequirementsList->List[0].Descriptors[0];
877c4b6330bSDmitry Borisov 
878c4b6330bSDmitry Borisov     /* Store the Data port and the Address port */
879*10b08aa2SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts) * 2; i++)
880debec8c9SHervé Poussineau     {
881c4b6330bSDmitry Borisov         if ((i % 2) == 0)
882c4b6330bSDmitry Borisov         {
883debec8c9SHervé Poussineau             /* Expected port */
884c4b6330bSDmitry Borisov             Descriptor->Type = CmResourceTypePort;
885c4b6330bSDmitry Borisov             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
886c4b6330bSDmitry Borisov             Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
887c4b6330bSDmitry Borisov             Descriptor->u.Port.Length = 0x01;
888c4b6330bSDmitry Borisov             Descriptor->u.Port.Alignment = 0x01;
889c4b6330bSDmitry Borisov             Descriptor->u.Port.MinimumAddress.LowPart =
890*10b08aa2SDmitry Borisov             Descriptor->u.Port.MaximumAddress.LowPart = IsaConfigPorts[i / 2];
891c4b6330bSDmitry Borisov         }
892c4b6330bSDmitry Borisov         else
893c4b6330bSDmitry Borisov         {
894debec8c9SHervé Poussineau             /* ... but mark it as optional */
895c4b6330bSDmitry Borisov             Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
896c4b6330bSDmitry Borisov             Descriptor->Type = CmResourceTypePort;
897c4b6330bSDmitry Borisov             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
898c4b6330bSDmitry Borisov             Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
899c4b6330bSDmitry Borisov             Descriptor->u.Port.Alignment = 0x01;
900c4b6330bSDmitry Borisov         }
901c4b6330bSDmitry Borisov 
902c4b6330bSDmitry Borisov         Descriptor++;
903c4b6330bSDmitry Borisov     }
904c4b6330bSDmitry Borisov 
905c4b6330bSDmitry Borisov     /* Store the Read Ports */
906c4b6330bSDmitry Borisov     if (SelectedReadPort)
907c4b6330bSDmitry Borisov     {
908c4b6330bSDmitry Borisov         BOOLEAN Selected = FALSE;
909c4b6330bSDmitry Borisov 
910c4b6330bSDmitry Borisov         DBG_UNREFERENCED_LOCAL_VARIABLE(Selected);
911c4b6330bSDmitry Borisov 
912c4b6330bSDmitry Borisov         for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++)
913c4b6330bSDmitry Borisov         {
914c4b6330bSDmitry Borisov             if (ReadPorts[i] != SelectedReadPort)
915c4b6330bSDmitry Borisov                 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
916c4b6330bSDmitry Borisov             else
917c4b6330bSDmitry Borisov                 Selected = TRUE;
918c4b6330bSDmitry Borisov             Descriptor->Type = CmResourceTypePort;
919c4b6330bSDmitry Borisov             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
920c4b6330bSDmitry Borisov             Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
921c4b6330bSDmitry Borisov             Descriptor->u.Port.Length = 0x04;
922c4b6330bSDmitry Borisov             Descriptor->u.Port.Alignment = 0x01;
923c4b6330bSDmitry Borisov             Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i];
924c4b6330bSDmitry Borisov             Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] +
925c4b6330bSDmitry Borisov                                                         Descriptor->u.Port.Length - 1;
926c4b6330bSDmitry Borisov 
927c4b6330bSDmitry Borisov             Descriptor++;
928c4b6330bSDmitry Borisov         }
929c4b6330bSDmitry Borisov 
930c4b6330bSDmitry Borisov         ASSERT(Selected == TRUE);
931c4b6330bSDmitry Borisov     }
932c4b6330bSDmitry Borisov     else
933c4b6330bSDmitry Borisov     {
934c4b6330bSDmitry Borisov         for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++)
935c4b6330bSDmitry Borisov         {
936c4b6330bSDmitry Borisov             if ((i % 2) == 0)
937c4b6330bSDmitry Borisov             {
938c4b6330bSDmitry Borisov                 /* Expected port */
939c4b6330bSDmitry Borisov                 Descriptor->Type = CmResourceTypePort;
940c4b6330bSDmitry Borisov                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
941c4b6330bSDmitry Borisov                 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
942c4b6330bSDmitry Borisov                 Descriptor->u.Port.Length = 0x04;
943c4b6330bSDmitry Borisov                 Descriptor->u.Port.Alignment = 0x01;
944c4b6330bSDmitry Borisov                 Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2];
945c4b6330bSDmitry Borisov                 Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] +
946c4b6330bSDmitry Borisov                                                             Descriptor->u.Port.Length - 1;
947c4b6330bSDmitry Borisov             }
948c4b6330bSDmitry Borisov             else
949c4b6330bSDmitry Borisov             {
950c4b6330bSDmitry Borisov                 /* ... but mark it as optional */
951c4b6330bSDmitry Borisov                 Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
952c4b6330bSDmitry Borisov                 Descriptor->Type = CmResourceTypePort;
953c4b6330bSDmitry Borisov                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
954c4b6330bSDmitry Borisov                 Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
955c4b6330bSDmitry Borisov                 Descriptor->u.Port.Alignment = 0x01;
956c4b6330bSDmitry Borisov             }
957c4b6330bSDmitry Borisov 
958c4b6330bSDmitry Borisov             Descriptor++;
959c4b6330bSDmitry Borisov         }
960debec8c9SHervé Poussineau     }
961debec8c9SHervé Poussineau 
9624ba8a8b5SDmitry Borisov     return RequirementsList;
963debec8c9SHervé Poussineau }
964debec8c9SHervé Poussineau 
96570ba96f1SDmitry Borisov CODE_SEG("PAGE")
9664ba8a8b5SDmitry Borisov PCM_RESOURCE_LIST
IsaPnpCreateReadPortDOResources(VOID)9674ba8a8b5SDmitry Borisov IsaPnpCreateReadPortDOResources(VOID)
96861c1079aSHervé Poussineau {
96961c1079aSHervé Poussineau     ULONG ListSize, i;
97061c1079aSHervé Poussineau     PCM_RESOURCE_LIST ResourceList;
97161c1079aSHervé Poussineau     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
97261c1079aSHervé Poussineau 
97370ba96f1SDmitry Borisov     PAGED_CODE();
97470ba96f1SDmitry Borisov 
9758f44930fSDmitry Borisov     ListSize = sizeof(CM_RESOURCE_LIST) +
976*10b08aa2SDmitry Borisov                sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(IsaConfigPorts) - 1);
97766c19575SDmitry Borisov     ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
97861c1079aSHervé Poussineau     if (!ResourceList)
9794ba8a8b5SDmitry Borisov         return NULL;
98061c1079aSHervé Poussineau 
98161c1079aSHervé Poussineau     ResourceList->Count = 1;
98261c1079aSHervé Poussineau     ResourceList->List[0].InterfaceType = Internal;
98361c1079aSHervé Poussineau     ResourceList->List[0].PartialResourceList.Version = 1;
98461c1079aSHervé Poussineau     ResourceList->List[0].PartialResourceList.Revision = 1;
985*10b08aa2SDmitry Borisov     ResourceList->List[0].PartialResourceList.Count = RTL_NUMBER_OF(IsaConfigPorts);
98661c1079aSHervé Poussineau 
9878ed43b69SDmitry Borisov     Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
988*10b08aa2SDmitry Borisov     for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts); i++)
98961c1079aSHervé Poussineau     {
99061c1079aSHervé Poussineau         Descriptor->Type = CmResourceTypePort;
99161c1079aSHervé Poussineau         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
99261c1079aSHervé Poussineau         Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
99361c1079aSHervé Poussineau         Descriptor->u.Port.Length = 0x01;
994*10b08aa2SDmitry Borisov         Descriptor->u.Port.Start.LowPart = IsaConfigPorts[i];
9958ed43b69SDmitry Borisov 
9968ed43b69SDmitry Borisov         Descriptor++;
99761c1079aSHervé Poussineau     }
99861c1079aSHervé Poussineau 
9994ba8a8b5SDmitry Borisov     return ResourceList;
100061c1079aSHervé Poussineau }
100161c1079aSHervé Poussineau 
1002b36d9bd9SDmitry Borisov #ifndef UNIT_TEST
1003b36d9bd9SDmitry Borisov 
100461c1079aSHervé Poussineau static
100570ba96f1SDmitry Borisov CODE_SEG("PAGE")
100661c1079aSHervé Poussineau NTSTATUS
IsaPnpCreateReadPortDO(_In_ PISAPNP_FDO_EXTENSION FdoExt)10078f44930fSDmitry Borisov IsaPnpCreateReadPortDO(
10088f44930fSDmitry Borisov     _In_ PISAPNP_FDO_EXTENSION FdoExt)
1009c4813f73SHervé Poussineau {
1010c4813f73SHervé Poussineau     PISAPNP_PDO_EXTENSION PdoExt;
1011c4813f73SHervé Poussineau     NTSTATUS Status;
10128f44930fSDmitry Borisov 
101370ba96f1SDmitry Borisov     PAGED_CODE();
101421514e47SDmitry Borisov     ASSERT(ReadPortCreated == FALSE);
101521514e47SDmitry Borisov 
101621514e47SDmitry Borisov     DPRINT("Creating Read Port\n");
101770ba96f1SDmitry Borisov 
1018c4813f73SHervé Poussineau     Status = IoCreateDevice(FdoExt->DriverObject,
1019c4813f73SHervé Poussineau                             sizeof(ISAPNP_PDO_EXTENSION),
1020c4813f73SHervé Poussineau                             NULL,
1021c4813f73SHervé Poussineau                             FILE_DEVICE_CONTROLLER,
1022ac13f37dSHervé Poussineau                             FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
1023c4813f73SHervé Poussineau                             FALSE,
10248f44930fSDmitry Borisov                             &FdoExt->ReadPortPdo);
1025c4813f73SHervé Poussineau     if (!NT_SUCCESS(Status))
1026c4813f73SHervé Poussineau         return Status;
10278f44930fSDmitry Borisov 
10288f44930fSDmitry Borisov     PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
1029c4813f73SHervé Poussineau     RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
1030f15de155SDmitry Borisov     PdoExt->Common.Signature = IsaPnpReadDataPort;
10318f44930fSDmitry Borisov     PdoExt->Common.Self = FdoExt->ReadPortPdo;
1032c4813f73SHervé Poussineau     PdoExt->Common.State = dsStopped;
10332fe644dcSHervé Poussineau     PdoExt->FdoExt = FdoExt;
1034c4813f73SHervé Poussineau 
103521514e47SDmitry Borisov     FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING;
103621514e47SDmitry Borisov 
103761c1079aSHervé Poussineau     return Status;
103821514e47SDmitry Borisov }
103921514e47SDmitry Borisov 
104021514e47SDmitry Borisov CODE_SEG("PAGE")
1041f15de155SDmitry Borisov VOID
IsaPnpRemoveReadPortDO(_In_ PDEVICE_OBJECT Pdo)1042f15de155SDmitry Borisov IsaPnpRemoveReadPortDO(
1043f15de155SDmitry Borisov     _In_ PDEVICE_OBJECT Pdo)
1044f15de155SDmitry Borisov {
1045f15de155SDmitry Borisov     PAGED_CODE();
1046f15de155SDmitry Borisov 
1047f15de155SDmitry Borisov     DPRINT("Removing Read Port\n");
1048f15de155SDmitry Borisov 
1049f15de155SDmitry Borisov     IoDeleteDevice(Pdo);
1050f15de155SDmitry Borisov }
1051f15de155SDmitry Borisov 
1052f15de155SDmitry Borisov CODE_SEG("PAGE")
105321514e47SDmitry Borisov NTSTATUS
IsaPnpFillDeviceRelations(_In_ PISAPNP_FDO_EXTENSION FdoExt,_Inout_ PIRP Irp,_In_ BOOLEAN IncludeDataPort)105421514e47SDmitry Borisov IsaPnpFillDeviceRelations(
105521514e47SDmitry Borisov     _In_ PISAPNP_FDO_EXTENSION FdoExt,
105621514e47SDmitry Borisov     _Inout_ PIRP Irp,
105721514e47SDmitry Borisov     _In_ BOOLEAN IncludeDataPort)
105821514e47SDmitry Borisov {
105921514e47SDmitry Borisov     NTSTATUS Status = STATUS_SUCCESS;
106021514e47SDmitry Borisov     PLIST_ENTRY CurrentEntry;
106121514e47SDmitry Borisov     PISAPNP_LOGICAL_DEVICE IsaDevice;
106221514e47SDmitry Borisov     PDEVICE_RELATIONS DeviceRelations;
106321514e47SDmitry Borisov     ULONG PdoCount, i = 0;
106421514e47SDmitry Borisov 
106521514e47SDmitry Borisov     PAGED_CODE();
106621514e47SDmitry Borisov 
1067f15de155SDmitry Borisov     IsaPnpAcquireBusDataLock();
1068f15de155SDmitry Borisov 
106921514e47SDmitry Borisov     /* Try to claim the Read Port for our FDO */
107021514e47SDmitry Borisov     if (!ReadPortCreated)
107121514e47SDmitry Borisov     {
107221514e47SDmitry Borisov         Status = IsaPnpCreateReadPortDO(FdoExt);
107321514e47SDmitry Borisov         if (!NT_SUCCESS(Status))
107421514e47SDmitry Borisov             return Status;
107521514e47SDmitry Borisov 
107621514e47SDmitry Borisov         ReadPortCreated = TRUE;
107721514e47SDmitry Borisov     }
107821514e47SDmitry Borisov 
1079f15de155SDmitry Borisov     IsaPnpReleaseBusDataLock();
1080f15de155SDmitry Borisov 
108121514e47SDmitry Borisov     /* Inactive ISA bus */
108221514e47SDmitry Borisov     if (!FdoExt->ReadPortPdo)
108321514e47SDmitry Borisov         IncludeDataPort = FALSE;
108421514e47SDmitry Borisov 
1085f15de155SDmitry Borisov     IsaPnpAcquireDeviceDataLock(FdoExt);
1086f15de155SDmitry Borisov 
1087f15de155SDmitry Borisov     /* If called from the FDO dispatch routine && Active bus */
1088f15de155SDmitry Borisov     if (IncludeDataPort && FdoExt->ReadPortPdo)
1089f15de155SDmitry Borisov     {
1090f15de155SDmitry Borisov         PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
1091f15de155SDmitry Borisov 
1092f15de155SDmitry Borisov         if ((ReadPortExt->Flags & ISAPNP_READ_PORT_ALLOW_FDO_SCAN) &&
1093f15de155SDmitry Borisov             !(ReadPortExt->Flags & ISAPNP_SCANNED_BY_READ_PORT))
1094f15de155SDmitry Borisov         {
1095f15de155SDmitry Borisov             DPRINT("Rescan ISA PnP bus\n");
1096f15de155SDmitry Borisov 
1097f15de155SDmitry Borisov             /* Run the isolation protocol */
1098ca42de9cSDmitry Borisov             FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort);
1099ca42de9cSDmitry Borisov 
1100f15de155SDmitry Borisov             /* Card identification */
1101ca42de9cSDmitry Borisov             if (FdoExt->Cards > 0)
1102f15de155SDmitry Borisov                 (VOID)IsaHwFillDeviceList(FdoExt);
1103367f4b15SDmitry Borisov 
1104367f4b15SDmitry Borisov             IsaHwWaitForKey();
1105f15de155SDmitry Borisov         }
1106f15de155SDmitry Borisov 
1107f15de155SDmitry Borisov         ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;
1108f15de155SDmitry Borisov     }
1109f15de155SDmitry Borisov 
111021514e47SDmitry Borisov     PdoCount = FdoExt->DeviceCount;
111121514e47SDmitry Borisov     if (IncludeDataPort)
111221514e47SDmitry Borisov         ++PdoCount;
111321514e47SDmitry Borisov 
1114f15de155SDmitry Borisov     CurrentEntry = FdoExt->DeviceListHead.Flink;
1115f15de155SDmitry Borisov     while (CurrentEntry != &FdoExt->DeviceListHead)
1116f15de155SDmitry Borisov     {
1117f15de155SDmitry Borisov         IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
1118f15de155SDmitry Borisov 
1119f15de155SDmitry Borisov         if (!(IsaDevice->Flags & ISAPNP_PRESENT))
1120f15de155SDmitry Borisov             --PdoCount;
1121f15de155SDmitry Borisov 
1122f15de155SDmitry Borisov         CurrentEntry = CurrentEntry->Flink;
1123f15de155SDmitry Borisov     }
1124f15de155SDmitry Borisov 
112521514e47SDmitry Borisov     DeviceRelations = ExAllocatePoolWithTag(PagedPool,
112621514e47SDmitry Borisov                                             FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]),
112721514e47SDmitry Borisov                                             TAG_ISAPNP);
112821514e47SDmitry Borisov     if (!DeviceRelations)
112921514e47SDmitry Borisov     {
1130f15de155SDmitry Borisov         IsaPnpReleaseDeviceDataLock(FdoExt);
113121514e47SDmitry Borisov         return STATUS_NO_MEMORY;
113221514e47SDmitry Borisov     }
113321514e47SDmitry Borisov 
113421514e47SDmitry Borisov     if (IncludeDataPort)
113521514e47SDmitry Borisov     {
1136f15de155SDmitry Borisov         PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
1137f15de155SDmitry Borisov 
113821514e47SDmitry Borisov         DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
113921514e47SDmitry Borisov         ObReferenceObject(FdoExt->ReadPortPdo);
1140f15de155SDmitry Borisov 
1141f15de155SDmitry Borisov         /* The Read Port PDO can only be removed by FDO */
1142f15de155SDmitry Borisov         ReadPortExt->Flags |= ISAPNP_ENUMERATED;
114321514e47SDmitry Borisov     }
114421514e47SDmitry Borisov 
114521514e47SDmitry Borisov     CurrentEntry = FdoExt->DeviceListHead.Flink;
114621514e47SDmitry Borisov     while (CurrentEntry != &FdoExt->DeviceListHead)
114721514e47SDmitry Borisov     {
114821514e47SDmitry Borisov         PISAPNP_PDO_EXTENSION PdoExt;
114921514e47SDmitry Borisov 
115021514e47SDmitry Borisov         IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
115121514e47SDmitry Borisov 
1152f15de155SDmitry Borisov         if (!(IsaDevice->Flags & ISAPNP_PRESENT))
1153f15de155SDmitry Borisov             goto SkipPdo;
1154f15de155SDmitry Borisov 
115521514e47SDmitry Borisov         if (!IsaDevice->Pdo)
115621514e47SDmitry Borisov         {
115721514e47SDmitry Borisov             Status = IoCreateDevice(FdoExt->DriverObject,
115821514e47SDmitry Borisov                                     sizeof(ISAPNP_PDO_EXTENSION),
115921514e47SDmitry Borisov                                     NULL,
116021514e47SDmitry Borisov                                     FILE_DEVICE_CONTROLLER,
116121514e47SDmitry Borisov                                     FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
116221514e47SDmitry Borisov                                     FALSE,
116321514e47SDmitry Borisov                                     &IsaDevice->Pdo);
116421514e47SDmitry Borisov             if (!NT_SUCCESS(Status))
1165f15de155SDmitry Borisov                 goto SkipPdo;
116621514e47SDmitry Borisov 
116721514e47SDmitry Borisov             IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
1168f15de155SDmitry Borisov             /* The power pagable flag is always unset */
116921514e47SDmitry Borisov 
117021514e47SDmitry Borisov             PdoExt = IsaDevice->Pdo->DeviceExtension;
117121514e47SDmitry Borisov 
117221514e47SDmitry Borisov             RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
1173f15de155SDmitry Borisov             PdoExt->Common.Signature = IsaPnpLogicalDevice;
117421514e47SDmitry Borisov             PdoExt->Common.Self = IsaDevice->Pdo;
117521514e47SDmitry Borisov             PdoExt->Common.State = dsStopped;
117621514e47SDmitry Borisov             PdoExt->IsaPnpDevice = IsaDevice;
117721514e47SDmitry Borisov             PdoExt->FdoExt = FdoExt;
117821514e47SDmitry Borisov 
1179f15de155SDmitry Borisov             if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) ||
1180f15de155SDmitry Borisov                 !NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt)))
118121514e47SDmitry Borisov             {
1182f15de155SDmitry Borisov                 if (PdoExt->RequirementsList)
1183f15de155SDmitry Borisov                 {
1184f15de155SDmitry Borisov                     ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
1185f15de155SDmitry Borisov                     PdoExt->RequirementsList = NULL;
1186f15de155SDmitry Borisov                 }
1187f15de155SDmitry Borisov 
1188f15de155SDmitry Borisov                 if (PdoExt->ResourceList)
1189f15de155SDmitry Borisov                 {
1190f15de155SDmitry Borisov                     ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
1191f15de155SDmitry Borisov                     PdoExt->ResourceList = NULL;
1192f15de155SDmitry Borisov                 }
1193f15de155SDmitry Borisov 
119421514e47SDmitry Borisov                 IoDeleteDevice(IsaDevice->Pdo);
119521514e47SDmitry Borisov                 IsaDevice->Pdo = NULL;
1196f15de155SDmitry Borisov                 goto SkipPdo;
119721514e47SDmitry Borisov             }
119821514e47SDmitry Borisov         }
1199f15de155SDmitry Borisov         else
1200f15de155SDmitry Borisov         {
1201f15de155SDmitry Borisov             PdoExt = IsaDevice->Pdo->DeviceExtension;
1202f15de155SDmitry Borisov         }
120321514e47SDmitry Borisov         DeviceRelations->Objects[i++] = IsaDevice->Pdo;
120421514e47SDmitry Borisov         ObReferenceObject(IsaDevice->Pdo);
120521514e47SDmitry Borisov 
1206f15de155SDmitry Borisov         PdoExt->Flags |= ISAPNP_ENUMERATED;
1207f15de155SDmitry Borisov 
1208f15de155SDmitry Borisov         CurrentEntry = CurrentEntry->Flink;
1209f15de155SDmitry Borisov         continue;
1210f15de155SDmitry Borisov 
1211f15de155SDmitry Borisov SkipPdo:
1212f15de155SDmitry Borisov         if (IsaDevice->Pdo)
1213f15de155SDmitry Borisov         {
1214f15de155SDmitry Borisov             PdoExt = IsaDevice->Pdo->DeviceExtension;
1215f15de155SDmitry Borisov 
1216f15de155SDmitry Borisov             if (PdoExt)
1217f15de155SDmitry Borisov                 PdoExt->Flags &= ~ISAPNP_ENUMERATED;
1218f15de155SDmitry Borisov         }
1219f15de155SDmitry Borisov 
122021514e47SDmitry Borisov         CurrentEntry = CurrentEntry->Flink;
122121514e47SDmitry Borisov     }
122221514e47SDmitry Borisov 
1223f15de155SDmitry Borisov     IsaPnpReleaseDeviceDataLock(FdoExt);
1224f15de155SDmitry Borisov 
122521514e47SDmitry Borisov     DeviceRelations->Count = i;
122621514e47SDmitry Borisov 
122721514e47SDmitry Borisov     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
122821514e47SDmitry Borisov 
1229c4813f73SHervé Poussineau     return Status;
1230c4813f73SHervé Poussineau }
1231c4813f73SHervé Poussineau 
123270ba96f1SDmitry Borisov static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaAddDevice;
123370ba96f1SDmitry Borisov 
1234c4813f73SHervé Poussineau static
123570ba96f1SDmitry Borisov CODE_SEG("PAGE")
1236c4813f73SHervé Poussineau NTSTATUS
1237c4813f73SHervé Poussineau NTAPI
IsaAddDevice(_In_ PDRIVER_OBJECT DriverObject,_In_ PDEVICE_OBJECT PhysicalDeviceObject)1238c2c66affSColin Finck IsaAddDevice(
12398f44930fSDmitry Borisov     _In_ PDRIVER_OBJECT DriverObject,
12408f44930fSDmitry Borisov     _In_ PDEVICE_OBJECT PhysicalDeviceObject)
1241c2c66affSColin Finck {
1242c2c66affSColin Finck     PDEVICE_OBJECT Fdo;
1243c2c66affSColin Finck     PISAPNP_FDO_EXTENSION FdoExt;
1244c2c66affSColin Finck     NTSTATUS Status;
1245e1959557SDmitry Borisov     static ULONG BusNumber = 0;
1246c2c66affSColin Finck 
124770ba96f1SDmitry Borisov     PAGED_CODE();
124870ba96f1SDmitry Borisov 
1249c2c66affSColin Finck     DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject);
1250c2c66affSColin Finck 
1251c2c66affSColin Finck     Status = IoCreateDevice(DriverObject,
1252c2c66affSColin Finck                             sizeof(*FdoExt),
1253c2c66affSColin Finck                             NULL,
1254c2c66affSColin Finck                             FILE_DEVICE_BUS_EXTENDER,
1255c2c66affSColin Finck                             FILE_DEVICE_SECURE_OPEN,
1256f15de155SDmitry Borisov                             FALSE,
1257c2c66affSColin Finck                             &Fdo);
1258c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1259c2c66affSColin Finck     {
12608f44930fSDmitry Borisov         DPRINT1("Failed to create FDO (0x%08lx)\n", Status);
1261c2c66affSColin Finck         return Status;
1262c2c66affSColin Finck     }
1263c2c66affSColin Finck 
1264c2c66affSColin Finck     FdoExt = Fdo->DeviceExtension;
1265c2c66affSColin Finck     RtlZeroMemory(FdoExt, sizeof(*FdoExt));
1266c2c66affSColin Finck 
1267c2c66affSColin Finck     FdoExt->Common.Self = Fdo;
1268f15de155SDmitry Borisov     FdoExt->Common.Signature = IsaPnpBus;
1269c2c66affSColin Finck     FdoExt->Common.State = dsStopped;
12707a98d28dSHervé Poussineau     FdoExt->DriverObject = DriverObject;
1271e1959557SDmitry Borisov     FdoExt->BusNumber = BusNumber++;
1272c2c66affSColin Finck     FdoExt->Pdo = PhysicalDeviceObject;
1273c2c66affSColin Finck     FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
1274c2c66affSColin Finck                                               PhysicalDeviceObject);
1275f15de155SDmitry Borisov     if (!FdoExt->Ldo)
1276f15de155SDmitry Borisov     {
1277f15de155SDmitry Borisov         IoDeleteDevice(Fdo);
1278f15de155SDmitry Borisov         return STATUS_DEVICE_REMOVED;
1279f15de155SDmitry Borisov     }
1280c2c66affSColin Finck 
1281c2c66affSColin Finck     InitializeListHead(&FdoExt->DeviceListHead);
128270ba96f1SDmitry Borisov     KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE);
1283c2c66affSColin Finck 
1284f15de155SDmitry Borisov     IsaPnpAcquireBusDataLock();
1285f15de155SDmitry Borisov     InsertTailList(&BusListHead, &FdoExt->BusLink);
1286f15de155SDmitry Borisov     IsaPnpReleaseBusDataLock();
1287f15de155SDmitry Borisov 
1288c2c66affSColin Finck     Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
1289c2c66affSColin Finck 
1290c2c66affSColin Finck     return STATUS_SUCCESS;
1291c2c66affSColin Finck }
1292c2c66affSColin Finck 
_Dispatch_type_(IRP_MJ_POWER)12938f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_POWER)
129470ba96f1SDmitry Borisov static DRIVER_DISPATCH_RAISED IsaPower;
12958f44930fSDmitry Borisov 
129670ba96f1SDmitry Borisov static
12979df05ba4SHervé Poussineau NTSTATUS
12989df05ba4SHervé Poussineau NTAPI
12999df05ba4SHervé Poussineau IsaPower(
13008f44930fSDmitry Borisov     _In_ PDEVICE_OBJECT DeviceObject,
13018f44930fSDmitry Borisov     _Inout_ PIRP Irp)
13029df05ba4SHervé Poussineau {
13039df05ba4SHervé Poussineau     PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
13049df05ba4SHervé Poussineau     NTSTATUS Status;
13059df05ba4SHervé Poussineau 
1306f15de155SDmitry Borisov     if (DevExt->Signature != IsaPnpBus)
13079df05ba4SHervé Poussineau     {
1308f15de155SDmitry Borisov         switch (IoGetCurrentIrpStackLocation(Irp)->MinorFunction)
1309f15de155SDmitry Borisov         {
1310f15de155SDmitry Borisov             case IRP_MN_SET_POWER:
1311f15de155SDmitry Borisov             case IRP_MN_QUERY_POWER:
1312f15de155SDmitry Borisov                 Status = STATUS_SUCCESS;
1313f15de155SDmitry Borisov                 Irp->IoStatus.Status = Status;
1314f15de155SDmitry Borisov                 break;
1315f15de155SDmitry Borisov 
1316f15de155SDmitry Borisov             default:
13179df05ba4SHervé Poussineau                 Status = Irp->IoStatus.Status;
1318f15de155SDmitry Borisov                 break;
1319f15de155SDmitry Borisov         }
1320f15de155SDmitry Borisov 
1321f15de155SDmitry Borisov         PoStartNextPowerIrp(Irp);
13229df05ba4SHervé Poussineau         IoCompleteRequest(Irp, IO_NO_INCREMENT);
13239df05ba4SHervé Poussineau         return Status;
13249df05ba4SHervé Poussineau     }
13259df05ba4SHervé Poussineau 
13269df05ba4SHervé Poussineau     PoStartNextPowerIrp(Irp);
13279df05ba4SHervé Poussineau     IoSkipCurrentIrpStackLocation(Irp);
13289df05ba4SHervé Poussineau     return PoCallDriver(((PISAPNP_FDO_EXTENSION)DevExt)->Ldo, Irp);
13299df05ba4SHervé Poussineau }
13309df05ba4SHervé Poussineau 
13318f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_PNP)
133270ba96f1SDmitry Borisov static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaPnp;
1333c2c66affSColin Finck 
1334c2c66affSColin Finck static
133570ba96f1SDmitry Borisov CODE_SEG("PAGE")
1336c2c66affSColin Finck NTSTATUS
1337c2c66affSColin Finck NTAPI
IsaPnp(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)1338c2c66affSColin Finck IsaPnp(
13398f44930fSDmitry Borisov     _In_ PDEVICE_OBJECT DeviceObject,
13408f44930fSDmitry Borisov     _Inout_ PIRP Irp)
1341c2c66affSColin Finck {
1342c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
1343c2c66affSColin Finck     PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
1344c2c66affSColin Finck 
134570ba96f1SDmitry Borisov     PAGED_CODE();
134670ba96f1SDmitry Borisov 
1347f15de155SDmitry Borisov     if (DevExt->Signature == IsaPnpBus)
13488f44930fSDmitry Borisov         return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
1349c2c66affSColin Finck     else
13508f44930fSDmitry Borisov         return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
1351c2c66affSColin Finck }
1352c2c66affSColin Finck 
1353016d01e5SDmitry Borisov _Dispatch_type_(IRP_MJ_CREATE)
1354016d01e5SDmitry Borisov _Dispatch_type_(IRP_MJ_CLOSE)
1355016d01e5SDmitry Borisov static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose;
1356016d01e5SDmitry Borisov 
1357016d01e5SDmitry Borisov static
1358016d01e5SDmitry Borisov CODE_SEG("PAGE")
1359016d01e5SDmitry Borisov NTSTATUS
1360016d01e5SDmitry Borisov NTAPI
IsaCreateClose(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)1361016d01e5SDmitry Borisov IsaCreateClose(
1362016d01e5SDmitry Borisov     _In_ PDEVICE_OBJECT DeviceObject,
1363016d01e5SDmitry Borisov     _Inout_ PIRP Irp)
1364016d01e5SDmitry Borisov {
1365016d01e5SDmitry Borisov     PAGED_CODE();
1366016d01e5SDmitry Borisov 
1367016d01e5SDmitry Borisov     Irp->IoStatus.Status = STATUS_SUCCESS;
1368016d01e5SDmitry Borisov 
1369016d01e5SDmitry Borisov     DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
1370016d01e5SDmitry Borisov 
1371016d01e5SDmitry Borisov     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1372016d01e5SDmitry Borisov 
1373016d01e5SDmitry Borisov     return STATUS_SUCCESS;
1374016d01e5SDmitry Borisov }
1375016d01e5SDmitry Borisov 
1376016d01e5SDmitry Borisov _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
1377016d01e5SDmitry Borisov _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
1378016d01e5SDmitry Borisov static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore;
1379016d01e5SDmitry Borisov 
1380016d01e5SDmitry Borisov static
1381016d01e5SDmitry Borisov CODE_SEG("PAGE")
1382016d01e5SDmitry Borisov NTSTATUS
1383016d01e5SDmitry Borisov NTAPI
IsaForwardOrIgnore(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp)1384016d01e5SDmitry Borisov IsaForwardOrIgnore(
1385016d01e5SDmitry Borisov     _In_ PDEVICE_OBJECT DeviceObject,
1386016d01e5SDmitry Borisov     _Inout_ PIRP Irp)
1387016d01e5SDmitry Borisov {
1388016d01e5SDmitry Borisov     PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
1389016d01e5SDmitry Borisov 
1390016d01e5SDmitry Borisov     PAGED_CODE();
1391016d01e5SDmitry Borisov 
1392016d01e5SDmitry Borisov     DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp,
1393016d01e5SDmitry Borisov            IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
1394016d01e5SDmitry Borisov 
1395016d01e5SDmitry Borisov     if (CommonExt->Signature == IsaPnpBus)
1396016d01e5SDmitry Borisov     {
1397016d01e5SDmitry Borisov         IoSkipCurrentIrpStackLocation(Irp);
1398016d01e5SDmitry Borisov         return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
1399016d01e5SDmitry Borisov     }
1400016d01e5SDmitry Borisov     else
1401016d01e5SDmitry Borisov     {
1402016d01e5SDmitry Borisov         NTSTATUS Status = Irp->IoStatus.Status;
1403016d01e5SDmitry Borisov 
1404016d01e5SDmitry Borisov         IoCompleteRequest(Irp, IO_NO_INCREMENT);
1405016d01e5SDmitry Borisov         return Status;
1406016d01e5SDmitry Borisov     }
1407016d01e5SDmitry Borisov }
1408016d01e5SDmitry Borisov 
140970ba96f1SDmitry Borisov CODE_SEG("INIT")
1410c2c66affSColin Finck NTSTATUS
1411c2c66affSColin Finck NTAPI
DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath)1412c2c66affSColin Finck DriverEntry(
14138f44930fSDmitry Borisov     _In_ PDRIVER_OBJECT DriverObject,
14148f44930fSDmitry Borisov     _In_ PUNICODE_STRING RegistryPath)
1415c2c66affSColin Finck {
1416c2c66affSColin Finck     DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath);
1417c2c66affSColin Finck 
1418*10b08aa2SDmitry Borisov     if (IsNEC_98)
1419*10b08aa2SDmitry Borisov     {
1420*10b08aa2SDmitry Borisov         IsaConfigPorts[0] = ISAPNP_WRITE_DATA_PC98;
1421*10b08aa2SDmitry Borisov         IsaConfigPorts[1] = ISAPNP_ADDRESS_PC98;
1422*10b08aa2SDmitry Borisov     }
1423*10b08aa2SDmitry Borisov 
1424c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose;
1425c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose;
1426f15de155SDmitry Borisov     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore;
1427f15de155SDmitry Borisov     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore;
1428c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp;
14299df05ba4SHervé Poussineau     DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower;
1430c2c66affSColin Finck     DriverObject->DriverExtension->AddDevice = IsaAddDevice;
1431c2c66affSColin Finck 
1432f15de155SDmitry Borisov     /* FIXME: Fix SDK headers */
1433f15de155SDmitry Borisov #if 0
1434f15de155SDmitry Borisov     _No_competing_thread_begin_
1435f15de155SDmitry Borisov #endif
1436f15de155SDmitry Borisov 
1437f15de155SDmitry Borisov     KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE);
1438f15de155SDmitry Borisov     InitializeListHead(&BusListHead);
1439f15de155SDmitry Borisov 
1440f15de155SDmitry Borisov     /* FIXME: Fix SDK headers */
1441f15de155SDmitry Borisov #if 0
1442f15de155SDmitry Borisov     _No_competing_thread_end_
1443f15de155SDmitry Borisov #endif
1444f15de155SDmitry Borisov 
1445c2c66affSColin Finck     return STATUS_SUCCESS;
1446c2c66affSColin Finck }
1447c2c66affSColin Finck 
1448b36d9bd9SDmitry Borisov #endif /* UNIT_TEST */
1449b36d9bd9SDmitry Borisov 
1450c2c66affSColin Finck /* EOF */
1451