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> 7c2c66affSColin Finck */ 8c2c66affSColin Finck 98f44930fSDmitry Borisov #include "isapnp.h" 10c2c66affSColin Finck 11c2c66affSColin Finck #define NDEBUG 12c2c66affSColin Finck #include <debug.h> 13c2c66affSColin Finck 1489aff07aSHervé Poussineau NTSTATUS 1589aff07aSHervé Poussineau NTAPI 16e0607fceSHervé Poussineau IsaPnpDuplicateUnicodeString( 17e0607fceSHervé Poussineau IN ULONG Flags, 18e0607fceSHervé Poussineau IN PCUNICODE_STRING SourceString, 19e0607fceSHervé Poussineau OUT PUNICODE_STRING DestinationString) 20e0607fceSHervé Poussineau { 21e0607fceSHervé Poussineau if (SourceString == NULL || 22e0607fceSHervé Poussineau DestinationString == NULL || 23e0607fceSHervé Poussineau SourceString->Length > SourceString->MaximumLength || 24e0607fceSHervé Poussineau (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) || 25e0607fceSHervé Poussineau Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || 26e0607fceSHervé Poussineau Flags >= 4) 27e0607fceSHervé Poussineau { 28e0607fceSHervé Poussineau return STATUS_INVALID_PARAMETER; 29e0607fceSHervé Poussineau } 30e0607fceSHervé Poussineau 31e0607fceSHervé Poussineau if ((SourceString->Length == 0) && 32e0607fceSHervé Poussineau (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 33e0607fceSHervé Poussineau RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 34e0607fceSHervé Poussineau { 35e0607fceSHervé Poussineau DestinationString->Length = 0; 36e0607fceSHervé Poussineau DestinationString->MaximumLength = 0; 37e0607fceSHervé Poussineau DestinationString->Buffer = NULL; 38e0607fceSHervé Poussineau } 39e0607fceSHervé Poussineau else 40e0607fceSHervé Poussineau { 41e0607fceSHervé Poussineau USHORT DestMaxLength = SourceString->Length; 42e0607fceSHervé Poussineau 43e0607fceSHervé Poussineau if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 44e0607fceSHervé Poussineau DestMaxLength += sizeof(UNICODE_NULL); 45e0607fceSHervé Poussineau 46e0607fceSHervé Poussineau DestinationString->Buffer = ExAllocatePool(PagedPool, DestMaxLength); 47e0607fceSHervé Poussineau if (DestinationString->Buffer == NULL) 48e0607fceSHervé Poussineau return STATUS_NO_MEMORY; 49e0607fceSHervé Poussineau 50e0607fceSHervé Poussineau RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 51e0607fceSHervé Poussineau DestinationString->Length = SourceString->Length; 52e0607fceSHervé Poussineau DestinationString->MaximumLength = DestMaxLength; 53e0607fceSHervé Poussineau 54e0607fceSHervé Poussineau if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 55e0607fceSHervé Poussineau DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 56e0607fceSHervé Poussineau } 57e0607fceSHervé Poussineau 58e0607fceSHervé Poussineau return STATUS_SUCCESS; 59e0607fceSHervé Poussineau } 60e0607fceSHervé Poussineau 61e0607fceSHervé Poussineau static 62e0607fceSHervé Poussineau NTSTATUS 63e0607fceSHervé Poussineau NTAPI 64e0607fceSHervé Poussineau IsaFdoCreateDeviceIDs( 65e0607fceSHervé Poussineau IN PISAPNP_PDO_EXTENSION PdoExt) 66e0607fceSHervé Poussineau { 67e0607fceSHervé Poussineau PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 68e0607fceSHervé Poussineau UNICODE_STRING TempString; 69e0607fceSHervé Poussineau WCHAR TempBuffer[256]; 70e0607fceSHervé Poussineau PWCHAR End; 71e0607fceSHervé Poussineau NTSTATUS Status; 72e0607fceSHervé Poussineau USHORT i; 73e0607fceSHervé Poussineau 74e0607fceSHervé Poussineau TempString.Buffer = TempBuffer; 75e0607fceSHervé Poussineau TempString.MaximumLength = sizeof(TempBuffer); 76e0607fceSHervé Poussineau TempString.Length = 0; 77e0607fceSHervé Poussineau 78e0607fceSHervé Poussineau /* Device ID */ 79e0607fceSHervé Poussineau Status = RtlStringCbPrintfExW(TempString.Buffer, 80e0607fceSHervé Poussineau TempString.MaximumLength / sizeof(WCHAR), 81e0607fceSHervé Poussineau &End, 82e0607fceSHervé Poussineau NULL, 0, 83eb66324dSHervé Poussineau L"ISAPNP\\%.3S%04x", 84e0607fceSHervé Poussineau LogDev->VendorId, 85e0607fceSHervé Poussineau LogDev->ProdId); 86e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 87e0607fceSHervé Poussineau return Status; 887b1e28e7SHervé Poussineau TempString.Length = (USHORT)((End - TempString.Buffer) * sizeof(WCHAR)); 89e0607fceSHervé Poussineau Status = IsaPnpDuplicateUnicodeString( 90e0607fceSHervé Poussineau RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 91e0607fceSHervé Poussineau &TempString, 92e0607fceSHervé Poussineau &PdoExt->DeviceID); 93e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 94e0607fceSHervé Poussineau return Status; 95e0607fceSHervé Poussineau 96e0607fceSHervé Poussineau /* HardwareIDs */ 97e0607fceSHervé Poussineau Status = RtlStringCbPrintfExW(TempString.Buffer, 98e0607fceSHervé Poussineau TempString.MaximumLength / sizeof(WCHAR), 99e0607fceSHervé Poussineau &End, 100e0607fceSHervé Poussineau NULL, 0, 101eb66324dSHervé Poussineau L"ISAPNP\\%.3S%04x@" 102eb66324dSHervé Poussineau L"*%.3S%04x@", 103e0607fceSHervé Poussineau LogDev->VendorId, 104e0607fceSHervé Poussineau LogDev->ProdId, 105e0607fceSHervé Poussineau LogDev->VendorId, 106e0607fceSHervé Poussineau LogDev->ProdId); 107e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 108e0607fceSHervé Poussineau return Status; 1097b1e28e7SHervé Poussineau TempString.Length = (USHORT)((End - TempString.Buffer) * sizeof(WCHAR)); 110e0607fceSHervé Poussineau Status = IsaPnpDuplicateUnicodeString( 111e0607fceSHervé Poussineau RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 112e0607fceSHervé Poussineau &TempString, 113e0607fceSHervé Poussineau &PdoExt->HardwareIDs); 114e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 115e0607fceSHervé Poussineau return Status; 116e0607fceSHervé Poussineau for (i = 0; i < PdoExt->HardwareIDs.Length / sizeof(WCHAR); i++) 117e0607fceSHervé Poussineau if (PdoExt->HardwareIDs.Buffer[i] == '@') 118e0607fceSHervé Poussineau PdoExt->HardwareIDs.Buffer[i] = UNICODE_NULL; 119e0607fceSHervé Poussineau 120e0607fceSHervé Poussineau /* InstanceID */ 121e0607fceSHervé Poussineau Status = RtlStringCbPrintfExW(TempString.Buffer, 122e0607fceSHervé Poussineau TempString.MaximumLength / sizeof(WCHAR), 123e0607fceSHervé Poussineau &End, 124e0607fceSHervé Poussineau NULL, 0, 125e0607fceSHervé Poussineau L"%X", 126e0607fceSHervé Poussineau LogDev->SerialNumber); 127e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 128e0607fceSHervé Poussineau return Status; 1297b1e28e7SHervé Poussineau TempString.Length = (USHORT)((End - TempString.Buffer) * sizeof(WCHAR)); 130e0607fceSHervé Poussineau Status = IsaPnpDuplicateUnicodeString( 131e0607fceSHervé Poussineau RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 132e0607fceSHervé Poussineau &TempString, 133e0607fceSHervé Poussineau &PdoExt->InstanceID); 134e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 135e0607fceSHervé Poussineau return Status; 136e0607fceSHervé Poussineau 137e0607fceSHervé Poussineau return STATUS_SUCCESS; 138e0607fceSHervé Poussineau } 139e0607fceSHervé Poussineau 14067141abeSHervé Poussineau static 14167141abeSHervé Poussineau NTSTATUS 14267141abeSHervé Poussineau NTAPI 1438f44930fSDmitry Borisov IsaPnpCreateLogicalDeviceRequirements( 1448f44930fSDmitry Borisov _In_ PISAPNP_PDO_EXTENSION PdoExt) 14567141abeSHervé Poussineau { 14667141abeSHervé Poussineau PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 1478f44930fSDmitry Borisov RTL_BITMAP IrqBitmap[RTL_NUMBER_OF(LogDev->Irq)]; 1488f44930fSDmitry Borisov RTL_BITMAP DmaBitmap[RTL_NUMBER_OF(LogDev->Dma)]; 1498f44930fSDmitry Borisov ULONG IrqData[RTL_NUMBER_OF(LogDev->Irq)]; 1508f44930fSDmitry Borisov ULONG DmaData[RTL_NUMBER_OF(LogDev->Dma)]; 15167141abeSHervé Poussineau ULONG ResourceCount = 0; 15267141abeSHervé Poussineau ULONG ListSize, i, j; 1537cda1ed2SHervé Poussineau BOOLEAN FirstIrq = TRUE, FirstDma = TRUE; 15467141abeSHervé Poussineau PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 15567141abeSHervé Poussineau PIO_RESOURCE_DESCRIPTOR Descriptor; 15667141abeSHervé Poussineau 15767141abeSHervé Poussineau /* Count number of requirements */ 1588f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 15967141abeSHervé Poussineau { 16067141abeSHervé Poussineau if (!LogDev->Io[i].Description.Length) 16167141abeSHervé Poussineau break; 1628f44930fSDmitry Borisov 16367141abeSHervé Poussineau ResourceCount++; 16467141abeSHervé Poussineau } 1658f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 16667141abeSHervé Poussineau { 16767141abeSHervé Poussineau if (!LogDev->Irq[i].Description.Mask) 16867141abeSHervé Poussineau break; 1698f44930fSDmitry Borisov 17067141abeSHervé Poussineau IrqData[i] = LogDev->Irq[i].Description.Mask; 17167141abeSHervé Poussineau RtlInitializeBitMap(&IrqBitmap[i], &IrqData[i], 16); 17267141abeSHervé Poussineau ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]); 1738f44930fSDmitry Borisov 17467141abeSHervé Poussineau if (LogDev->Irq[i].Description.Information & 0x4) 17567141abeSHervé Poussineau { 17667141abeSHervé Poussineau /* Add room for level sensitive */ 17767141abeSHervé Poussineau ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]); 17867141abeSHervé Poussineau } 17967141abeSHervé Poussineau } 18067141abeSHervé Poussineau if (ResourceCount == 0) 18167141abeSHervé Poussineau return STATUS_SUCCESS; 1828f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 1837cda1ed2SHervé Poussineau { 1847cda1ed2SHervé Poussineau if (!LogDev->Dma[i].Description.Mask) 1857cda1ed2SHervé Poussineau break; 1868f44930fSDmitry Borisov 1877cda1ed2SHervé Poussineau DmaData[i] = LogDev->Dma[i].Description.Mask; 1887cda1ed2SHervé Poussineau RtlInitializeBitMap(&DmaBitmap[i], &DmaData[i], 8); 1897cda1ed2SHervé Poussineau ResourceCount += RtlNumberOfSetBits(&DmaBitmap[i]); 1907cda1ed2SHervé Poussineau } 19167141abeSHervé Poussineau 19267141abeSHervé Poussineau /* Allocate memory to store requirements */ 19367141abeSHervé Poussineau ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) 19467141abeSHervé Poussineau + ResourceCount * sizeof(IO_RESOURCE_DESCRIPTOR); 195*66c19575SDmitry Borisov RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 19667141abeSHervé Poussineau if (!RequirementsList) 19767141abeSHervé Poussineau return STATUS_NO_MEMORY; 19867141abeSHervé Poussineau 19967141abeSHervé Poussineau RequirementsList->ListSize = ListSize; 20067141abeSHervé Poussineau RequirementsList->InterfaceType = Isa; 20167141abeSHervé Poussineau RequirementsList->AlternativeLists = 1; 20267141abeSHervé Poussineau 20367141abeSHervé Poussineau RequirementsList->List[0].Version = 1; 20467141abeSHervé Poussineau RequirementsList->List[0].Revision = 1; 20567141abeSHervé Poussineau RequirementsList->List[0].Count = ResourceCount; 20667141abeSHervé Poussineau 20767141abeSHervé Poussineau /* Store requirements */ 20867141abeSHervé Poussineau Descriptor = RequirementsList->List[0].Descriptors; 2098f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 21067141abeSHervé Poussineau { 21167141abeSHervé Poussineau if (!LogDev->Io[i].Description.Length) 21267141abeSHervé Poussineau break; 2138f44930fSDmitry Borisov 21467141abeSHervé Poussineau DPRINT("Device.Io[%d].Information = 0x%02x\n", i, LogDev->Io[i].Description.Information); 21567141abeSHervé Poussineau DPRINT("Device.Io[%d].Minimum = 0x%02x\n", i, LogDev->Io[i].Description.Minimum); 21667141abeSHervé Poussineau DPRINT("Device.Io[%d].Maximum = 0x%02x\n", i, LogDev->Io[i].Description.Maximum); 21767141abeSHervé Poussineau DPRINT("Device.Io[%d].Alignment = 0x%02x\n", i, LogDev->Io[i].Description.Alignment); 21867141abeSHervé Poussineau DPRINT("Device.Io[%d].Length = 0x%02x\n", i, LogDev->Io[i].Description.Length); 2198f44930fSDmitry Borisov 22067141abeSHervé Poussineau Descriptor->Type = CmResourceTypePort; 22167141abeSHervé Poussineau Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 22267141abeSHervé Poussineau if (LogDev->Io[i].Description.Information & 0x1) 22367141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 22467141abeSHervé Poussineau else 22567141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE; 22667141abeSHervé Poussineau Descriptor->u.Port.Length = LogDev->Io[i].Description.Length; 22767141abeSHervé Poussineau Descriptor->u.Port.Alignment = LogDev->Io[i].Description.Alignment; 22867141abeSHervé Poussineau Descriptor->u.Port.MinimumAddress.LowPart = LogDev->Io[i].Description.Minimum; 2298f44930fSDmitry Borisov Descriptor->u.Port.MaximumAddress.LowPart = 2308f44930fSDmitry Borisov LogDev->Io[i].Description.Maximum + LogDev->Io[i].Description.Length - 1; 23167141abeSHervé Poussineau Descriptor++; 23267141abeSHervé Poussineau } 2338f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 23467141abeSHervé Poussineau { 23567141abeSHervé Poussineau if (!LogDev->Irq[i].Description.Mask) 23667141abeSHervé Poussineau break; 2378f44930fSDmitry Borisov 23867141abeSHervé Poussineau DPRINT("Device.Irq[%d].Mask = 0x%02x\n", i, LogDev->Irq[i].Description.Mask); 23967141abeSHervé Poussineau DPRINT("Device.Irq[%d].Information = 0x%02x\n", i, LogDev->Irq[i].Description.Information); 2408f44930fSDmitry Borisov 24167141abeSHervé Poussineau for (j = 0; j < 15; j++) 24267141abeSHervé Poussineau { 24367141abeSHervé Poussineau if (!RtlCheckBit(&IrqBitmap[i], j)) 24467141abeSHervé Poussineau continue; 2458f44930fSDmitry Borisov 24667141abeSHervé Poussineau if (FirstIrq) 24767141abeSHervé Poussineau FirstIrq = FALSE; 24867141abeSHervé Poussineau else 24967141abeSHervé Poussineau Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 25067141abeSHervé Poussineau Descriptor->Type = CmResourceTypeInterrupt; 25167141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 25267141abeSHervé Poussineau Descriptor->u.Interrupt.MinimumVector = Descriptor->u.Interrupt.MaximumVector = j; 25367141abeSHervé Poussineau Descriptor++; 2548f44930fSDmitry Borisov 25567141abeSHervé Poussineau if (LogDev->Irq[i].Description.Information & 0x4) 25667141abeSHervé Poussineau { 25767141abeSHervé Poussineau /* Level interrupt */ 25867141abeSHervé Poussineau Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 25967141abeSHervé Poussineau Descriptor->Type = CmResourceTypeInterrupt; 26067141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 26167141abeSHervé Poussineau Descriptor->u.Interrupt.MinimumVector = Descriptor->u.Interrupt.MaximumVector = j; 26267141abeSHervé Poussineau Descriptor++; 26367141abeSHervé Poussineau } 26467141abeSHervé Poussineau } 26567141abeSHervé Poussineau } 2668f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 2677cda1ed2SHervé Poussineau { 2687cda1ed2SHervé Poussineau if (!LogDev->Dma[i].Description.Mask) 2697cda1ed2SHervé Poussineau break; 2708f44930fSDmitry Borisov 2717cda1ed2SHervé Poussineau DPRINT("Device.Dma[%d].Mask = 0x%02x\n", i, LogDev->Dma[i].Description.Mask); 2727cda1ed2SHervé Poussineau DPRINT("Device.Dma[%d].Information = 0x%02x\n", i, LogDev->Dma[i].Description.Information); 2738f44930fSDmitry Borisov 2747cda1ed2SHervé Poussineau for (j = 0; j < 8; j++) 2757cda1ed2SHervé Poussineau { 2767cda1ed2SHervé Poussineau if (!RtlCheckBit(&DmaBitmap[i], j)) 2777cda1ed2SHervé Poussineau continue; 2788f44930fSDmitry Borisov 2797cda1ed2SHervé Poussineau if (FirstDma) 2807cda1ed2SHervé Poussineau FirstDma = FALSE; 2817cda1ed2SHervé Poussineau else 2827cda1ed2SHervé Poussineau Descriptor->Option = IO_RESOURCE_ALTERNATIVE; 2837cda1ed2SHervé Poussineau Descriptor->Type = CmResourceTypeDma; 2847cda1ed2SHervé Poussineau switch (LogDev->Dma[i].Description.Information & 0x3) 2857cda1ed2SHervé Poussineau { 2867cda1ed2SHervé Poussineau case 0x0: Descriptor->Flags |= CM_RESOURCE_DMA_8; break; 2877cda1ed2SHervé Poussineau case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break; 2887cda1ed2SHervé Poussineau case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_16; break; 2897cda1ed2SHervé Poussineau default: break; 2907cda1ed2SHervé Poussineau } 2917cda1ed2SHervé Poussineau if (LogDev->Dma[i].Description.Information & 0x4) 2927cda1ed2SHervé Poussineau Descriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER; 2937cda1ed2SHervé Poussineau switch ((LogDev->Dma[i].Description.Information >> 5) & 0x3) 2947cda1ed2SHervé Poussineau { 2957cda1ed2SHervé Poussineau case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break; 2967cda1ed2SHervé Poussineau case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break; 2977cda1ed2SHervé Poussineau case 0x3: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break; 2987cda1ed2SHervé Poussineau default: break; 2997cda1ed2SHervé Poussineau } 3007cda1ed2SHervé Poussineau Descriptor->u.Dma.MinimumChannel = Descriptor->u.Dma.MaximumChannel = j; 3017cda1ed2SHervé Poussineau Descriptor++; 3027cda1ed2SHervé Poussineau } 3037cda1ed2SHervé Poussineau } 30467141abeSHervé Poussineau 30567141abeSHervé Poussineau PdoExt->RequirementsList = RequirementsList; 30667141abeSHervé Poussineau return STATUS_SUCCESS; 30767141abeSHervé Poussineau } 30867141abeSHervé Poussineau 30967141abeSHervé Poussineau static 31067141abeSHervé Poussineau NTSTATUS 31167141abeSHervé Poussineau NTAPI 3128f44930fSDmitry Borisov IsaPnpCreateLogicalDeviceResources( 3138f44930fSDmitry Borisov _In_ PISAPNP_PDO_EXTENSION PdoExt) 31467141abeSHervé Poussineau { 31567141abeSHervé Poussineau PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; 31667141abeSHervé Poussineau ULONG ResourceCount = 0; 31767141abeSHervé Poussineau ULONG ListSize, i; 31867141abeSHervé Poussineau PCM_RESOURCE_LIST ResourceList; 31967141abeSHervé Poussineau PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 32067141abeSHervé Poussineau 32167141abeSHervé Poussineau /* Count number of required resources */ 3228f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 32367141abeSHervé Poussineau { 32467141abeSHervé Poussineau if (LogDev->Io[i].CurrentBase) 32567141abeSHervé Poussineau ResourceCount++; 32667141abeSHervé Poussineau else 32767141abeSHervé Poussineau break; 32867141abeSHervé Poussineau } 3298f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 33067141abeSHervé Poussineau { 33167141abeSHervé Poussineau if (LogDev->Irq[i].CurrentNo) 33267141abeSHervé Poussineau ResourceCount++; 33367141abeSHervé Poussineau else 33467141abeSHervé Poussineau break; 33567141abeSHervé Poussineau } 3368f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 3377cda1ed2SHervé Poussineau { 3387cda1ed2SHervé Poussineau if (LogDev->Dma[i].CurrentChannel != 4) 3397cda1ed2SHervé Poussineau ResourceCount++; 3407cda1ed2SHervé Poussineau else 3417cda1ed2SHervé Poussineau break; 3427cda1ed2SHervé Poussineau } 34367141abeSHervé Poussineau if (ResourceCount == 0) 34467141abeSHervé Poussineau return STATUS_SUCCESS; 34567141abeSHervé Poussineau 34667141abeSHervé Poussineau /* Allocate memory to store resources */ 34767141abeSHervé Poussineau ListSize = sizeof(CM_RESOURCE_LIST) 34867141abeSHervé Poussineau + (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 349*66c19575SDmitry Borisov ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 35067141abeSHervé Poussineau if (!ResourceList) 35167141abeSHervé Poussineau return STATUS_NO_MEMORY; 35267141abeSHervé Poussineau 35367141abeSHervé Poussineau ResourceList->Count = 1; 35467141abeSHervé Poussineau ResourceList->List[0].InterfaceType = Isa; 35567141abeSHervé Poussineau ResourceList->List[0].PartialResourceList.Version = 1; 35667141abeSHervé Poussineau ResourceList->List[0].PartialResourceList.Revision = 1; 35767141abeSHervé Poussineau ResourceList->List[0].PartialResourceList.Count = ResourceCount; 35867141abeSHervé Poussineau 35967141abeSHervé Poussineau /* Store resources */ 36067141abeSHervé Poussineau ResourceCount = 0; 3618f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) 36267141abeSHervé Poussineau { 36367141abeSHervé Poussineau if (!LogDev->Io[i].CurrentBase) 36467141abeSHervé Poussineau continue; 3658f44930fSDmitry Borisov 36667141abeSHervé Poussineau Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 36767141abeSHervé Poussineau Descriptor->Type = CmResourceTypePort; 36867141abeSHervé Poussineau Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 36967141abeSHervé Poussineau if (LogDev->Io[i].Description.Information & 0x1) 37067141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 37167141abeSHervé Poussineau else 37267141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE; 37367141abeSHervé Poussineau Descriptor->u.Port.Length = LogDev->Io[i].Description.Length; 37467141abeSHervé Poussineau Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase; 37567141abeSHervé Poussineau } 3768f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) 37767141abeSHervé Poussineau { 37867141abeSHervé Poussineau if (!LogDev->Irq[i].CurrentNo) 37967141abeSHervé Poussineau continue; 3808f44930fSDmitry Borisov 38167141abeSHervé Poussineau Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 38267141abeSHervé Poussineau Descriptor->Type = CmResourceTypeInterrupt; 38367141abeSHervé Poussineau Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 38467141abeSHervé Poussineau if (LogDev->Irq[i].CurrentType & 0x01) 38567141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 38667141abeSHervé Poussineau else 38767141abeSHervé Poussineau Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; 38867141abeSHervé Poussineau Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo; 38967141abeSHervé Poussineau Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo; 39067141abeSHervé Poussineau Descriptor->u.Interrupt.Affinity = -1; 39167141abeSHervé Poussineau } 3928f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) 3937cda1ed2SHervé Poussineau { 3947cda1ed2SHervé Poussineau if (LogDev->Dma[i].CurrentChannel == 4) 3957cda1ed2SHervé Poussineau continue; 3968f44930fSDmitry Borisov 3977cda1ed2SHervé Poussineau Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; 3987cda1ed2SHervé Poussineau Descriptor->Type = CmResourceTypeDma; 3997cda1ed2SHervé Poussineau Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 4007cda1ed2SHervé Poussineau switch (LogDev->Dma[i].Description.Information & 0x3) 4017cda1ed2SHervé Poussineau { 4027cda1ed2SHervé Poussineau case 0x0: Descriptor->Flags |= CM_RESOURCE_DMA_8; break; 4037cda1ed2SHervé Poussineau case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_8 | CM_RESOURCE_DMA_16; break; 4047cda1ed2SHervé Poussineau case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_16; break; 4057cda1ed2SHervé Poussineau default: break; 4067cda1ed2SHervé Poussineau } 4077cda1ed2SHervé Poussineau if (LogDev->Dma[i].Description.Information & 0x4) 4087cda1ed2SHervé Poussineau Descriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER; 4097cda1ed2SHervé Poussineau switch ((LogDev->Dma[i].Description.Information >> 5) & 0x3) 4107cda1ed2SHervé Poussineau { 4117cda1ed2SHervé Poussineau case 0x1: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break; 4127cda1ed2SHervé Poussineau case 0x2: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break; 4137cda1ed2SHervé Poussineau case 0x3: Descriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break; 4147cda1ed2SHervé Poussineau default: break; 4157cda1ed2SHervé Poussineau } 4167cda1ed2SHervé Poussineau Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel; 4177cda1ed2SHervé Poussineau } 41867141abeSHervé Poussineau 41967141abeSHervé Poussineau PdoExt->ResourceList = ResourceList; 42067141abeSHervé Poussineau PdoExt->ResourceListSize = ListSize; 42167141abeSHervé Poussineau return STATUS_SUCCESS; 42267141abeSHervé Poussineau } 42367141abeSHervé Poussineau 424e0607fceSHervé Poussineau NTSTATUS 425e0607fceSHervé Poussineau NTAPI 42689aff07aSHervé Poussineau IsaPnpFillDeviceRelations( 4278f44930fSDmitry Borisov _In_ PISAPNP_FDO_EXTENSION FdoExt, 4288f44930fSDmitry Borisov _Inout_ PIRP Irp, 4298f44930fSDmitry Borisov _In_ BOOLEAN IncludeDataPort) 43089aff07aSHervé Poussineau { 43189aff07aSHervé Poussineau PISAPNP_PDO_EXTENSION PdoExt; 43289aff07aSHervé Poussineau NTSTATUS Status = STATUS_SUCCESS; 43389aff07aSHervé Poussineau PLIST_ENTRY CurrentEntry; 43489aff07aSHervé Poussineau PISAPNP_LOGICAL_DEVICE IsaDevice; 43589aff07aSHervé Poussineau PDEVICE_RELATIONS DeviceRelations; 43689aff07aSHervé Poussineau ULONG i = 0; 43789aff07aSHervé Poussineau 43889aff07aSHervé Poussineau DeviceRelations = ExAllocatePool(NonPagedPool, 43989aff07aSHervé Poussineau sizeof(DEVICE_RELATIONS) + sizeof(DEVICE_OBJECT) * FdoExt->DeviceCount); 44089aff07aSHervé Poussineau if (!DeviceRelations) 44189aff07aSHervé Poussineau { 44289aff07aSHervé Poussineau return STATUS_NO_MEMORY; 44389aff07aSHervé Poussineau } 44489aff07aSHervé Poussineau 445c4813f73SHervé Poussineau if (IncludeDataPort) 446c4813f73SHervé Poussineau { 4478f44930fSDmitry Borisov DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo; 4488f44930fSDmitry Borisov ObReferenceObject(FdoExt->ReadPortPdo); 449c4813f73SHervé Poussineau } 450c4813f73SHervé Poussineau 45189aff07aSHervé Poussineau CurrentEntry = FdoExt->DeviceListHead.Flink; 45289aff07aSHervé Poussineau while (CurrentEntry != &FdoExt->DeviceListHead) 45389aff07aSHervé Poussineau { 4548f44930fSDmitry Borisov IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink); 45589aff07aSHervé Poussineau 45689aff07aSHervé Poussineau if (!IsaDevice->Pdo) 45789aff07aSHervé Poussineau { 45889aff07aSHervé Poussineau Status = IoCreateDevice(FdoExt->DriverObject, 45989aff07aSHervé Poussineau sizeof(ISAPNP_PDO_EXTENSION), 46089aff07aSHervé Poussineau NULL, 46189aff07aSHervé Poussineau FILE_DEVICE_CONTROLLER, 46289aff07aSHervé Poussineau FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME, 46389aff07aSHervé Poussineau FALSE, 46489aff07aSHervé Poussineau &IsaDevice->Pdo); 46589aff07aSHervé Poussineau if (!NT_SUCCESS(Status)) 46689aff07aSHervé Poussineau { 46789aff07aSHervé Poussineau break; 46889aff07aSHervé Poussineau } 46989aff07aSHervé Poussineau 47089aff07aSHervé Poussineau IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 47189aff07aSHervé Poussineau 47289aff07aSHervé Poussineau //Device->Pdo->Flags |= DO_POWER_PAGABLE; 47389aff07aSHervé Poussineau 4748f44930fSDmitry Borisov PdoExt = IsaDevice->Pdo->DeviceExtension; 47589aff07aSHervé Poussineau 47689aff07aSHervé Poussineau RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); 47789aff07aSHervé Poussineau 47889aff07aSHervé Poussineau PdoExt->Common.IsFdo = FALSE; 47989aff07aSHervé Poussineau PdoExt->Common.Self = IsaDevice->Pdo; 48089aff07aSHervé Poussineau PdoExt->Common.State = dsStopped; 48189aff07aSHervé Poussineau PdoExt->IsaPnpDevice = IsaDevice; 4822fe644dcSHervé Poussineau PdoExt->FdoExt = FdoExt; 483e0607fceSHervé Poussineau 484e0607fceSHervé Poussineau Status = IsaFdoCreateDeviceIDs(PdoExt); 48567141abeSHervé Poussineau 48667141abeSHervé Poussineau if (NT_SUCCESS(Status)) 4878f44930fSDmitry Borisov Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt); 48867141abeSHervé Poussineau 48967141abeSHervé Poussineau if (NT_SUCCESS(Status)) 4908f44930fSDmitry Borisov Status = IsaPnpCreateLogicalDeviceResources(PdoExt); 49167141abeSHervé Poussineau 492e0607fceSHervé Poussineau if (!NT_SUCCESS(Status)) 493e0607fceSHervé Poussineau { 494e0607fceSHervé Poussineau IoDeleteDevice(IsaDevice->Pdo); 495e0607fceSHervé Poussineau IsaDevice->Pdo = NULL; 496e0607fceSHervé Poussineau break; 497e0607fceSHervé Poussineau } 49889aff07aSHervé Poussineau } 49989aff07aSHervé Poussineau DeviceRelations->Objects[i++] = IsaDevice->Pdo; 50089aff07aSHervé Poussineau 50189aff07aSHervé Poussineau ObReferenceObject(IsaDevice->Pdo); 50289aff07aSHervé Poussineau 50389aff07aSHervé Poussineau CurrentEntry = CurrentEntry->Flink; 50489aff07aSHervé Poussineau } 50589aff07aSHervé Poussineau 50689aff07aSHervé Poussineau DeviceRelations->Count = i; 50789aff07aSHervé Poussineau 50889aff07aSHervé Poussineau Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 50989aff07aSHervé Poussineau 51089aff07aSHervé Poussineau return Status; 51189aff07aSHervé Poussineau } 51289aff07aSHervé Poussineau 513c2c66affSColin Finck static IO_COMPLETION_ROUTINE ForwardIrpCompletion; 514c2c66affSColin Finck 515c2c66affSColin Finck static 516c2c66affSColin Finck NTSTATUS 517c2c66affSColin Finck NTAPI 518c2c66affSColin Finck ForwardIrpCompletion( 519c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 520c2c66affSColin Finck IN PIRP Irp, 521c2c66affSColin Finck IN PVOID Context) 522c2c66affSColin Finck { 523c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceObject); 524c2c66affSColin Finck 525c2c66affSColin Finck if (Irp->PendingReturned) 526c2c66affSColin Finck KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 527c2c66affSColin Finck 528c2c66affSColin Finck return STATUS_MORE_PROCESSING_REQUIRED; 529c2c66affSColin Finck } 530c2c66affSColin Finck 531c2c66affSColin Finck NTSTATUS 532c2c66affSColin Finck NTAPI 533c2c66affSColin Finck IsaForwardIrpSynchronous( 534c2c66affSColin Finck IN PISAPNP_FDO_EXTENSION FdoExt, 535c2c66affSColin Finck IN PIRP Irp) 536c2c66affSColin Finck { 537c2c66affSColin Finck KEVENT Event; 538c2c66affSColin Finck NTSTATUS Status; 539c2c66affSColin Finck 540c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 541c2c66affSColin Finck IoCopyCurrentIrpStackLocationToNext(Irp); 542c2c66affSColin Finck 543c2c66affSColin Finck IoSetCompletionRoutine(Irp, ForwardIrpCompletion, &Event, TRUE, TRUE, TRUE); 544c2c66affSColin Finck 545c2c66affSColin Finck Status = IoCallDriver(FdoExt->Ldo, Irp); 546c2c66affSColin Finck if (Status == STATUS_PENDING) 547c2c66affSColin Finck { 548c2c66affSColin Finck Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 549c2c66affSColin Finck if (NT_SUCCESS(Status)) 550c2c66affSColin Finck Status = Irp->IoStatus.Status; 551c2c66affSColin Finck } 552c2c66affSColin Finck 553c2c66affSColin Finck return Status; 554c2c66affSColin Finck } 555c2c66affSColin Finck 5568f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_CREATE) 5578f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_CLOSE) 558c2c66affSColin Finck static DRIVER_DISPATCH IsaCreateClose; 559c2c66affSColin Finck 560c2c66affSColin Finck static 561c2c66affSColin Finck NTSTATUS 562c2c66affSColin Finck NTAPI 563c2c66affSColin Finck IsaCreateClose( 5648f44930fSDmitry Borisov _In_ PDEVICE_OBJECT DeviceObject, 5658f44930fSDmitry Borisov _Inout_ PIRP Irp) 566c2c66affSColin Finck { 567c2c66affSColin Finck Irp->IoStatus.Status = STATUS_SUCCESS; 568c2c66affSColin Finck Irp->IoStatus.Information = FILE_OPENED; 569c2c66affSColin Finck 570c2c66affSColin Finck DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); 571c2c66affSColin Finck 572c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 573c2c66affSColin Finck 574c2c66affSColin Finck return STATUS_SUCCESS; 575c2c66affSColin Finck } 576c2c66affSColin Finck 577c2c66affSColin Finck static DRIVER_DISPATCH IsaIoctl; 578c2c66affSColin Finck 579c2c66affSColin Finck static 580c2c66affSColin Finck NTSTATUS 581c2c66affSColin Finck NTAPI 582c2c66affSColin Finck IsaIoctl( 583c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 584c2c66affSColin Finck IN PIRP Irp) 585c2c66affSColin Finck { 586c2c66affSColin Finck PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 587c2c66affSColin Finck NTSTATUS Status; 588c2c66affSColin Finck 589c2c66affSColin Finck DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); 590c2c66affSColin Finck 591c2c66affSColin Finck switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) 592c2c66affSColin Finck { 593c2c66affSColin Finck default: 594c2c66affSColin Finck DPRINT1("Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); 595c2c66affSColin Finck Status = STATUS_NOT_SUPPORTED; 596c2c66affSColin Finck break; 597c2c66affSColin Finck } 598c2c66affSColin Finck 599c2c66affSColin Finck Irp->IoStatus.Status = Status; 600c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 601c2c66affSColin Finck 602c2c66affSColin Finck return Status; 603c2c66affSColin Finck } 604c2c66affSColin Finck 605c2c66affSColin Finck static DRIVER_DISPATCH IsaReadWrite; 606c2c66affSColin Finck 607c2c66affSColin Finck static 608c2c66affSColin Finck NTSTATUS 609c2c66affSColin Finck NTAPI 610c2c66affSColin Finck IsaReadWrite( 611c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 612c2c66affSColin Finck IN PIRP Irp) 613c2c66affSColin Finck { 614c2c66affSColin Finck DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); 615c2c66affSColin Finck 616c2c66affSColin Finck Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 617c2c66affSColin Finck Irp->IoStatus.Information = 0; 618c2c66affSColin Finck 619c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 620c2c66affSColin Finck 621c2c66affSColin Finck return STATUS_NOT_SUPPORTED; 622c2c66affSColin Finck } 623c2c66affSColin Finck 624c2c66affSColin Finck static 625c2c66affSColin Finck NTSTATUS 626c2c66affSColin Finck NTAPI 627debec8c9SHervé Poussineau IsaPnpCreateReadPortDORequirements( 6288f44930fSDmitry Borisov _In_ PISAPNP_PDO_EXTENSION PdoExt) 629debec8c9SHervé Poussineau { 630debec8c9SHervé Poussineau ULONG ListSize, i; 631debec8c9SHervé Poussineau PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 632debec8c9SHervé Poussineau PIO_RESOURCE_DESCRIPTOR Descriptor; 6338f44930fSDmitry Borisov const ULONG Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS, 6348f44930fSDmitry Borisov 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 }; 635debec8c9SHervé Poussineau 636debec8c9SHervé Poussineau ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) 6378f44930fSDmitry Borisov + 2 * RTL_NUMBER_OF(Ports) * sizeof(IO_RESOURCE_DESCRIPTOR); 638*66c19575SDmitry Borisov RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 639debec8c9SHervé Poussineau if (!RequirementsList) 640debec8c9SHervé Poussineau return STATUS_NO_MEMORY; 641debec8c9SHervé Poussineau 642debec8c9SHervé Poussineau RequirementsList->ListSize = ListSize; 643debec8c9SHervé Poussineau RequirementsList->AlternativeLists = 1; 644debec8c9SHervé Poussineau 645debec8c9SHervé Poussineau RequirementsList->List[0].Version = 1; 646debec8c9SHervé Poussineau RequirementsList->List[0].Revision = 1; 6478f44930fSDmitry Borisov RequirementsList->List[0].Count = 2 * RTL_NUMBER_OF(Ports); 648debec8c9SHervé Poussineau 6498f44930fSDmitry Borisov for (i = 0; i < 2 * RTL_NUMBER_OF(Ports); i += 2) 650debec8c9SHervé Poussineau { 651debec8c9SHervé Poussineau Descriptor = &RequirementsList->List[0].Descriptors[i]; 652debec8c9SHervé Poussineau 653debec8c9SHervé Poussineau /* Expected port */ 654debec8c9SHervé Poussineau Descriptor[0].Type = CmResourceTypePort; 655debec8c9SHervé Poussineau Descriptor[0].ShareDisposition = CmResourceShareDeviceExclusive; 656debec8c9SHervé Poussineau Descriptor[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 657debec8c9SHervé Poussineau Descriptor[0].u.Port.Length = Ports[i / 2] & 1 ? 0x01 : 0x04; 658debec8c9SHervé Poussineau Descriptor[0].u.Port.Alignment = 0x01; 659debec8c9SHervé Poussineau Descriptor[0].u.Port.MinimumAddress.LowPart = Ports[i / 2]; 660debec8c9SHervé Poussineau Descriptor[0].u.Port.MaximumAddress.LowPart = Ports[i / 2] + Descriptor[0].u.Port.Length - 1; 661debec8c9SHervé Poussineau 662debec8c9SHervé Poussineau /* ... but mark it as optional */ 663debec8c9SHervé Poussineau Descriptor[1].Option = IO_RESOURCE_ALTERNATIVE; 664debec8c9SHervé Poussineau Descriptor[1].Type = CmResourceTypePort; 665debec8c9SHervé Poussineau Descriptor[1].ShareDisposition = CmResourceShareDeviceExclusive; 666debec8c9SHervé Poussineau Descriptor[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 667debec8c9SHervé Poussineau Descriptor[1].u.Port.Alignment = 0x01; 668debec8c9SHervé Poussineau } 669debec8c9SHervé Poussineau 670debec8c9SHervé Poussineau PdoExt->RequirementsList = RequirementsList; 671debec8c9SHervé Poussineau return STATUS_SUCCESS; 672debec8c9SHervé Poussineau } 673debec8c9SHervé Poussineau 674debec8c9SHervé Poussineau static 675debec8c9SHervé Poussineau NTSTATUS 676debec8c9SHervé Poussineau NTAPI 67761c1079aSHervé Poussineau IsaPnpCreateReadPortDOResources( 6788f44930fSDmitry Borisov _In_ PISAPNP_PDO_EXTENSION PdoExt) 67961c1079aSHervé Poussineau { 6808f44930fSDmitry Borisov const USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS }; 68161c1079aSHervé Poussineau ULONG ListSize, i; 68261c1079aSHervé Poussineau PCM_RESOURCE_LIST ResourceList; 68361c1079aSHervé Poussineau PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 68461c1079aSHervé Poussineau 6858f44930fSDmitry Borisov ListSize = sizeof(CM_RESOURCE_LIST) + 6868f44930fSDmitry Borisov sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(Ports) - 1); 687*66c19575SDmitry Borisov ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); 68861c1079aSHervé Poussineau if (!ResourceList) 68961c1079aSHervé Poussineau return STATUS_NO_MEMORY; 69061c1079aSHervé Poussineau 69161c1079aSHervé Poussineau ResourceList->Count = 1; 69261c1079aSHervé Poussineau ResourceList->List[0].InterfaceType = Internal; 69361c1079aSHervé Poussineau ResourceList->List[0].PartialResourceList.Version = 1; 69461c1079aSHervé Poussineau ResourceList->List[0].PartialResourceList.Revision = 1; 6958f44930fSDmitry Borisov ResourceList->List[0].PartialResourceList.Count = RTL_NUMBER_OF(Ports); 69661c1079aSHervé Poussineau 6978f44930fSDmitry Borisov for (i = 0; i < RTL_NUMBER_OF(Ports); i++) 69861c1079aSHervé Poussineau { 69961c1079aSHervé Poussineau Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; 70061c1079aSHervé Poussineau Descriptor->Type = CmResourceTypePort; 70161c1079aSHervé Poussineau Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; 70261c1079aSHervé Poussineau Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE; 70361c1079aSHervé Poussineau Descriptor->u.Port.Length = 0x01; 70461c1079aSHervé Poussineau Descriptor->u.Port.Start.LowPart = Ports[i]; 70561c1079aSHervé Poussineau } 70661c1079aSHervé Poussineau 70761c1079aSHervé Poussineau PdoExt->ResourceList = ResourceList; 70861c1079aSHervé Poussineau PdoExt->ResourceListSize = ListSize; 70961c1079aSHervé Poussineau return STATUS_SUCCESS; 71061c1079aSHervé Poussineau } 71161c1079aSHervé Poussineau 71261c1079aSHervé Poussineau static 71361c1079aSHervé Poussineau NTSTATUS 71461c1079aSHervé Poussineau NTAPI 7158f44930fSDmitry Borisov IsaPnpCreateReadPortDO( 7168f44930fSDmitry Borisov _In_ PISAPNP_FDO_EXTENSION FdoExt) 717c4813f73SHervé Poussineau { 718c4813f73SHervé Poussineau UNICODE_STRING DeviceID = RTL_CONSTANT_STRING(L"ISAPNP\\ReadDataPort\0"); 719c4813f73SHervé Poussineau UNICODE_STRING HardwareIDs = RTL_CONSTANT_STRING(L"ISAPNP\\ReadDataPort\0\0"); 72042724f47SHervé Poussineau UNICODE_STRING CompatibleIDs = RTL_CONSTANT_STRING(L"\0\0"); 721c4813f73SHervé Poussineau UNICODE_STRING InstanceID = RTL_CONSTANT_STRING(L"0\0"); 722c4813f73SHervé Poussineau PISAPNP_PDO_EXTENSION PdoExt; 723c4813f73SHervé Poussineau NTSTATUS Status; 7248f44930fSDmitry Borisov 725c4813f73SHervé Poussineau Status = IoCreateDevice(FdoExt->DriverObject, 726c4813f73SHervé Poussineau sizeof(ISAPNP_PDO_EXTENSION), 727c4813f73SHervé Poussineau NULL, 728c4813f73SHervé Poussineau FILE_DEVICE_CONTROLLER, 729c4813f73SHervé Poussineau FILE_DEVICE_SECURE_OPEN, 730c4813f73SHervé Poussineau FALSE, 7318f44930fSDmitry Borisov &FdoExt->ReadPortPdo); 732c4813f73SHervé Poussineau if (!NT_SUCCESS(Status)) 733c4813f73SHervé Poussineau return Status; 7348f44930fSDmitry Borisov 7358f44930fSDmitry Borisov PdoExt = FdoExt->ReadPortPdo->DeviceExtension; 736c4813f73SHervé Poussineau RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION)); 737c4813f73SHervé Poussineau PdoExt->Common.IsFdo = FALSE; 7388f44930fSDmitry Borisov PdoExt->Common.Self = FdoExt->ReadPortPdo; 739c4813f73SHervé Poussineau PdoExt->Common.State = dsStopped; 7402fe644dcSHervé Poussineau PdoExt->FdoExt = FdoExt; 741c4813f73SHervé Poussineau 742c4813f73SHervé Poussineau Status = IsaPnpDuplicateUnicodeString(0, 743c4813f73SHervé Poussineau &DeviceID, 744c4813f73SHervé Poussineau &PdoExt->DeviceID); 745c4813f73SHervé Poussineau if (!NT_SUCCESS(Status)) 746c4813f73SHervé Poussineau return Status; 747c4813f73SHervé Poussineau 748c4813f73SHervé Poussineau Status = IsaPnpDuplicateUnicodeString(0, 749c4813f73SHervé Poussineau &HardwareIDs, 750c4813f73SHervé Poussineau &PdoExt->HardwareIDs); 751c4813f73SHervé Poussineau if (!NT_SUCCESS(Status)) 752c4813f73SHervé Poussineau return Status; 753c4813f73SHervé Poussineau 754c4813f73SHervé Poussineau Status = IsaPnpDuplicateUnicodeString(0, 75542724f47SHervé Poussineau &CompatibleIDs, 75642724f47SHervé Poussineau &PdoExt->CompatibleIDs); 75742724f47SHervé Poussineau if (!NT_SUCCESS(Status)) 75842724f47SHervé Poussineau return Status; 75942724f47SHervé Poussineau 76042724f47SHervé Poussineau Status = IsaPnpDuplicateUnicodeString(0, 761c4813f73SHervé Poussineau &InstanceID, 762c4813f73SHervé Poussineau &PdoExt->InstanceID); 763c4813f73SHervé Poussineau if (!NT_SUCCESS(Status)) 764c4813f73SHervé Poussineau return Status; 765c4813f73SHervé Poussineau 766debec8c9SHervé Poussineau Status = IsaPnpCreateReadPortDORequirements(PdoExt); 767debec8c9SHervé Poussineau if (!NT_SUCCESS(Status)) 768debec8c9SHervé Poussineau return Status; 769debec8c9SHervé Poussineau 77061c1079aSHervé Poussineau Status = IsaPnpCreateReadPortDOResources(PdoExt); 77161c1079aSHervé Poussineau if (!NT_SUCCESS(Status)) 77261c1079aSHervé Poussineau return Status; 77361c1079aSHervé Poussineau 774c4813f73SHervé Poussineau return Status; 775c4813f73SHervé Poussineau } 776c4813f73SHervé Poussineau 777c4813f73SHervé Poussineau static 778c4813f73SHervé Poussineau NTSTATUS 779c4813f73SHervé Poussineau NTAPI 780c2c66affSColin Finck IsaAddDevice( 7818f44930fSDmitry Borisov _In_ PDRIVER_OBJECT DriverObject, 7828f44930fSDmitry Borisov _In_ PDEVICE_OBJECT PhysicalDeviceObject) 783c2c66affSColin Finck { 784c2c66affSColin Finck PDEVICE_OBJECT Fdo; 785c2c66affSColin Finck PISAPNP_FDO_EXTENSION FdoExt; 786c2c66affSColin Finck NTSTATUS Status; 787c2c66affSColin Finck 788c2c66affSColin Finck DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject); 789c2c66affSColin Finck 790c2c66affSColin Finck Status = IoCreateDevice(DriverObject, 791c2c66affSColin Finck sizeof(*FdoExt), 792c2c66affSColin Finck NULL, 793c2c66affSColin Finck FILE_DEVICE_BUS_EXTENDER, 794c2c66affSColin Finck FILE_DEVICE_SECURE_OPEN, 795c2c66affSColin Finck TRUE, 796c2c66affSColin Finck &Fdo); 797c2c66affSColin Finck if (!NT_SUCCESS(Status)) 798c2c66affSColin Finck { 7998f44930fSDmitry Borisov DPRINT1("Failed to create FDO (0x%08lx)\n", Status); 800c2c66affSColin Finck return Status; 801c2c66affSColin Finck } 802c2c66affSColin Finck 803c2c66affSColin Finck FdoExt = Fdo->DeviceExtension; 804c2c66affSColin Finck RtlZeroMemory(FdoExt, sizeof(*FdoExt)); 805c2c66affSColin Finck 806c2c66affSColin Finck FdoExt->Common.Self = Fdo; 807c2c66affSColin Finck FdoExt->Common.IsFdo = TRUE; 808c2c66affSColin Finck FdoExt->Common.State = dsStopped; 8097a98d28dSHervé Poussineau FdoExt->DriverObject = DriverObject; 810c2c66affSColin Finck FdoExt->Pdo = PhysicalDeviceObject; 811c2c66affSColin Finck FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo, 812c2c66affSColin Finck PhysicalDeviceObject); 813c2c66affSColin Finck 814c2c66affSColin Finck InitializeListHead(&FdoExt->DeviceListHead); 815c2c66affSColin Finck KeInitializeSpinLock(&FdoExt->Lock); 816c2c66affSColin Finck 817c4813f73SHervé Poussineau Status = IsaPnpCreateReadPortDO(FdoExt); 818c4813f73SHervé Poussineau if (!NT_SUCCESS(Status)) 819c4813f73SHervé Poussineau return Status; 820c4813f73SHervé Poussineau 821c2c66affSColin Finck Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 8228f44930fSDmitry Borisov FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING; 823c2c66affSColin Finck 824c2c66affSColin Finck return STATUS_SUCCESS; 825c2c66affSColin Finck } 826c2c66affSColin Finck 8278f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_POWER) 8289df05ba4SHervé Poussineau DRIVER_DISPATCH IsaPower; 8298f44930fSDmitry Borisov 8309df05ba4SHervé Poussineau NTSTATUS 8319df05ba4SHervé Poussineau NTAPI 8329df05ba4SHervé Poussineau IsaPower( 8338f44930fSDmitry Borisov _In_ PDEVICE_OBJECT DeviceObject, 8348f44930fSDmitry Borisov _Inout_ PIRP Irp) 8359df05ba4SHervé Poussineau { 8369df05ba4SHervé Poussineau PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; 8379df05ba4SHervé Poussineau NTSTATUS Status; 8389df05ba4SHervé Poussineau 8399df05ba4SHervé Poussineau if (!DevExt->IsFdo) 8409df05ba4SHervé Poussineau { 8419df05ba4SHervé Poussineau Status = Irp->IoStatus.Status; 8429df05ba4SHervé Poussineau IoCompleteRequest(Irp, IO_NO_INCREMENT); 8439df05ba4SHervé Poussineau return Status; 8449df05ba4SHervé Poussineau } 8459df05ba4SHervé Poussineau 8469df05ba4SHervé Poussineau PoStartNextPowerIrp(Irp); 8479df05ba4SHervé Poussineau IoSkipCurrentIrpStackLocation(Irp); 8489df05ba4SHervé Poussineau return PoCallDriver(((PISAPNP_FDO_EXTENSION)DevExt)->Ldo, Irp); 8499df05ba4SHervé Poussineau } 8509df05ba4SHervé Poussineau 8518f44930fSDmitry Borisov _Dispatch_type_(IRP_MJ_PNP) 852c2c66affSColin Finck static DRIVER_DISPATCH IsaPnp; 853c2c66affSColin Finck 854c2c66affSColin Finck static 855c2c66affSColin Finck NTSTATUS 856c2c66affSColin Finck NTAPI 857c2c66affSColin Finck IsaPnp( 8588f44930fSDmitry Borisov _In_ PDEVICE_OBJECT DeviceObject, 8598f44930fSDmitry Borisov _Inout_ PIRP Irp) 860c2c66affSColin Finck { 861c2c66affSColin Finck PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 862c2c66affSColin Finck PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension; 863c2c66affSColin Finck 864c2c66affSColin Finck DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp); 865c2c66affSColin Finck 866c2c66affSColin Finck if (DevExt->IsFdo) 8678f44930fSDmitry Borisov return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp); 868c2c66affSColin Finck else 8698f44930fSDmitry Borisov return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp); 870c2c66affSColin Finck } 871c2c66affSColin Finck 872c2c66affSColin Finck NTSTATUS 873c2c66affSColin Finck NTAPI 874c2c66affSColin Finck DriverEntry( 8758f44930fSDmitry Borisov _In_ PDRIVER_OBJECT DriverObject, 8768f44930fSDmitry Borisov _In_ PUNICODE_STRING RegistryPath) 877c2c66affSColin Finck { 878c2c66affSColin Finck DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath); 879c2c66affSColin Finck 880c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose; 881c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose; 882c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_READ] = IsaReadWrite; 883c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_WRITE] = IsaReadWrite; 884c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaIoctl; 885c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp; 8869df05ba4SHervé Poussineau DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower; 887c2c66affSColin Finck DriverObject->DriverExtension->AddDevice = IsaAddDevice; 888c2c66affSColin Finck 889c2c66affSColin Finck return STATUS_SUCCESS; 890c2c66affSColin Finck } 891c2c66affSColin Finck 892c2c66affSColin Finck /* EOF */ 893