2 * PROJECT: ReactOS ISA PnP Bus driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Driver entry
5 * COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
6 * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
7 * Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
10 /* INCLUDES *******************************************************************/
19 /* GLOBALS ********************************************************************/
23 _Guarded_by_(BusSyncEvent
)
24 BOOLEAN ReadPortCreated
= FALSE
;
26 _Guarded_by_(BusSyncEvent
)
27 LIST_ENTRY BusListHead
;
29 static PUCHAR Priority
;
31 /* FUNCTIONS ******************************************************************/
43 return Priority
[*(PUCHAR
)A
] - Priority
[*(PUCHAR
)B
];
49 IsaDetermineBestConfig(
50 _Out_writes_all_(ISAPNP_MAX_ALTERNATIVES
) PUCHAR BestConfig
,
51 _In_ PISAPNP_ALTERNATIVES Alternatives
)
57 for (i
= 0; i
< ISAPNP_MAX_ALTERNATIVES
; i
++)
62 Priority
= Alternatives
->Priority
;
72 IsaConvertIoRequirement(
73 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor
,
74 _In_ PISAPNP_IO_DESCRIPTION Description
)
78 Descriptor
->Type
= CmResourceTypePort
;
79 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
80 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
81 if (Description
->Information
& 0x1)
82 Descriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
84 Descriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
85 Descriptor
->u
.Port
.Length
= Description
->Length
;
86 Descriptor
->u
.Port
.Alignment
= Description
->Alignment
;
87 Descriptor
->u
.Port
.MinimumAddress
.LowPart
= Description
->Minimum
;
88 Descriptor
->u
.Port
.MaximumAddress
.LowPart
= Description
->Maximum
+
89 Description
->Length
- 1;
95 IsaConvertIrqRequirement(
96 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor
,
97 _In_ PISAPNP_IRQ_DESCRIPTION Description
,
99 _In_ BOOLEAN FirstDescriptor
)
103 if (!FirstDescriptor
)
104 Descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
105 Descriptor
->Type
= CmResourceTypeInterrupt
;
106 if (Description
->Information
& 0xC)
108 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
;
109 Descriptor
->ShareDisposition
= CmResourceShareShared
;
113 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
114 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
116 Descriptor
->u
.Interrupt
.MinimumVector
=
117 Descriptor
->u
.Interrupt
.MaximumVector
= Vector
;
123 IsaConvertDmaRequirement(
124 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor
,
125 _In_ PISAPNP_DMA_DESCRIPTION Description
,
127 _In_ BOOLEAN FirstDescriptor
)
129 UNREFERENCED_PARAMETER(Description
);
133 if (!FirstDescriptor
)
134 Descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
135 Descriptor
->Type
= CmResourceTypeDma
;
136 Descriptor
->ShareDisposition
= CmResourceShareUndetermined
;
137 Descriptor
->Flags
= CM_RESOURCE_DMA_8
; /* Ignore information byte for compatibility */
138 Descriptor
->u
.Dma
.MinimumChannel
=
139 Descriptor
->u
.Dma
.MaximumChannel
= Channel
;
145 IsaConvertMemRangeRequirement(
146 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor
,
147 _In_ PISAPNP_MEMRANGE_DESCRIPTION Description
)
151 Descriptor
->Type
= CmResourceTypeMemory
;
152 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
153 Descriptor
->Flags
= CM_RESOURCE_MEMORY_24
;
154 if ((Description
->Information
& 0x40) || !(Description
->Information
& 0x01))
155 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_ONLY
;
157 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
158 Descriptor
->u
.Memory
.Length
= Description
->Length
<< 8;
159 if (Description
->Alignment
== 0)
160 Descriptor
->u
.Memory
.Alignment
= 0x10000;
162 Descriptor
->u
.Memory
.Alignment
= Description
->Alignment
;
163 Descriptor
->u
.Memory
.MinimumAddress
.LowPart
= Description
->Minimum
<< 8;
164 Descriptor
->u
.Memory
.MaximumAddress
.LowPart
= (Description
->Maximum
<< 8) +
165 (Description
->Length
<< 8) - 1;
171 IsaConvertMemRange32Requirement(
172 _Out_ PIO_RESOURCE_DESCRIPTOR Descriptor
,
173 _In_ PISAPNP_MEMRANGE32_DESCRIPTION Description
)
177 Descriptor
->Type
= CmResourceTypeMemory
;
178 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
179 Descriptor
->Flags
= CM_RESOURCE_MEMORY_24
;
180 if ((Description
->Information
& 0x40) || !(Description
->Information
& 0x01))
181 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_ONLY
;
183 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
184 Descriptor
->u
.Memory
.Length
= Description
->Length
;
185 Descriptor
->u
.Memory
.Alignment
= Description
->Alignment
;
186 Descriptor
->u
.Memory
.MinimumAddress
.LowPart
= Description
->Minimum
;
187 Descriptor
->u
.Memory
.MaximumAddress
.LowPart
= Description
->Maximum
+
188 Description
->Length
- 1;
194 IsaPnpCreateLogicalDeviceRequirements(
195 _In_ PISAPNP_PDO_EXTENSION PdoExt
)
197 PISAPNP_LOGICAL_DEVICE LogDev
= PdoExt
->IsaPnpDevice
;
198 RTL_BITMAP TempBitmap
;
200 ULONG ResourceCount
= 0, AltCount
= 0, AltOptionalCount
= 0;
201 ULONG ListSize
, i
, j
;
202 BOOLEAN FirstDescriptor
;
203 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
204 PIO_RESOURCE_DESCRIPTOR Descriptor
;
205 PISAPNP_ALTERNATIVES Alternatives
= LogDev
->Alternatives
;
209 /* Count number of requirements */
210 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Io
); i
++)
213 * Use the continue statement to count the number of requirements.
214 * We handle a possible gap because depedent function can appear at
215 * any position in the logical device's requirements list.
217 if (!LogDev
->Io
[i
].Description
.Length
)
222 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Irq
); i
++)
224 if (!LogDev
->Irq
[i
].Description
.Mask
)
227 TempBuffer
= LogDev
->Irq
[i
].Description
.Mask
;
228 RtlInitializeBitMap(&TempBitmap
,
230 RTL_BITS_OF(LogDev
->Irq
[i
].Description
.Mask
));
231 ResourceCount
+= RtlNumberOfSetBits(&TempBitmap
);
233 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Dma
); i
++)
235 if (!LogDev
->Dma
[i
].Description
.Mask
)
238 TempBuffer
= LogDev
->Dma
[i
].Description
.Mask
;
239 RtlInitializeBitMap(&TempBitmap
,
241 RTL_BITS_OF(LogDev
->Dma
[i
].Description
.Mask
));
242 ResourceCount
+= RtlNumberOfSetBits(&TempBitmap
);
244 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange
); i
++)
246 if (!LogDev
->MemRange
[i
].Description
.Length
)
251 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange32
); i
++)
253 if (!LogDev
->MemRange32
[i
].Description
.Length
)
262 if (HasIoAlternatives(Alternatives
))
264 if (HasIrqAlternatives(Alternatives
))
266 if (HasDmaAlternatives(Alternatives
))
268 if (HasMemoryAlternatives(Alternatives
))
270 if (HasMemory32Alternatives(Alternatives
))
272 ResourceCount
+= AltCount
;
274 if (HasIrqAlternatives(Alternatives
))
276 for (i
= 0; i
< Alternatives
->Count
; i
++)
278 TempBuffer
= Alternatives
->Irq
[i
].Mask
;
279 RtlInitializeBitMap(&TempBitmap
,
281 RTL_BITS_OF(Alternatives
->Irq
[i
].Mask
));
282 BitCount
= RtlNumberOfSetBits(&TempBitmap
);
285 AltOptionalCount
+= BitCount
- 1;
288 if (HasDmaAlternatives(Alternatives
))
290 for (i
= 0; i
< Alternatives
->Count
; i
++)
292 TempBuffer
= Alternatives
->Dma
[i
].Mask
;
293 RtlInitializeBitMap(&TempBitmap
,
295 RTL_BITS_OF(Alternatives
->Dma
[i
].Mask
));
296 BitCount
= RtlNumberOfSetBits(&TempBitmap
);
299 AltOptionalCount
+= BitCount
- 1;
303 if (ResourceCount
== 0)
304 return STATUS_SUCCESS
;
306 /* Allocate memory to store requirements */
307 ListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
);
310 ListSize
+= sizeof(IO_RESOURCE_DESCRIPTOR
) * (ResourceCount
- 1) * Alternatives
->Count
311 + sizeof(IO_RESOURCE_LIST
) * (Alternatives
->Count
- 1)
312 + sizeof(IO_RESOURCE_DESCRIPTOR
) * AltOptionalCount
;
316 ListSize
+= sizeof(IO_RESOURCE_DESCRIPTOR
) * (ResourceCount
- 1);
318 RequirementsList
= ExAllocatePoolZero(PagedPool
, ListSize
, TAG_ISAPNP
);
319 if (!RequirementsList
)
320 return STATUS_NO_MEMORY
;
322 RequirementsList
->ListSize
= ListSize
;
323 RequirementsList
->InterfaceType
= Isa
;
324 RequirementsList
->AlternativeLists
= Alternatives
? Alternatives
->Count
: 1;
326 RequirementsList
->List
[0].Version
= 1;
327 RequirementsList
->List
[0].Revision
= 1;
328 RequirementsList
->List
[0].Count
= ResourceCount
;
330 /* Store requirements */
331 Descriptor
= RequirementsList
->List
[0].Descriptors
;
332 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Io
); i
++)
334 if (!LogDev
->Io
[i
].Description
.Length
)
337 IsaConvertIoRequirement(Descriptor
++, &LogDev
->Io
[i
].Description
);
339 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Irq
); i
++)
341 if (!LogDev
->Irq
[i
].Description
.Mask
)
344 FirstDescriptor
= TRUE
;
346 for (j
= 0; j
< RTL_BITS_OF(LogDev
->Irq
[i
].Description
.Mask
); j
++)
348 if (!(LogDev
->Irq
[i
].Description
.Mask
& (1 << j
)))
351 IsaConvertIrqRequirement(Descriptor
++,
352 &LogDev
->Irq
[i
].Description
,
357 FirstDescriptor
= FALSE
;
360 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Dma
); i
++)
362 if (!LogDev
->Dma
[i
].Description
.Mask
)
365 FirstDescriptor
= TRUE
;
367 for (j
= 0; j
< RTL_BITS_OF(LogDev
->Dma
[i
].Description
.Mask
); j
++)
369 if (!(LogDev
->Dma
[i
].Description
.Mask
& (1 << j
)))
372 IsaConvertDmaRequirement(Descriptor
++,
373 &LogDev
->Dma
[i
].Description
,
378 FirstDescriptor
= FALSE
;
381 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange
); i
++)
383 if (!LogDev
->MemRange
[i
].Description
.Length
)
386 IsaConvertMemRangeRequirement(Descriptor
++,
387 &LogDev
->MemRange
[i
].Description
);
389 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange32
); i
++)
391 if (!LogDev
->MemRange32
[i
].Description
.Length
)
394 IsaConvertMemRange32Requirement(Descriptor
++,
395 &LogDev
->MemRange32
[i
].Description
);
399 UCHAR BestConfig
[ISAPNP_MAX_ALTERNATIVES
];
400 PIO_RESOURCE_LIST AltList
= &RequirementsList
->List
[0];
401 PIO_RESOURCE_LIST NextList
= AltList
;
403 IsaDetermineBestConfig(BestConfig
, Alternatives
);
405 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
407 RtlMoveMemory(NextList
, AltList
, sizeof(IO_RESOURCE_LIST
));
409 /* Just because the 'NextList->Count++' correction */
410 NextList
->Count
= ResourceCount
;
412 * For example, the ROM
413 * 0x15, ... // Logical device ID
415 * 0x22, 0x04, 0x00 // IRQ
417 * 0x22, 0xC0, 0x00 // IRQ
419 * 0x2A, 0x20, 0x3A // DMA
420 * 0x22, 0x00, 0x08 // IRQ
423 * will be represented as the following resource requirements list:
424 * Interface 1 Bus 0 Slot 0 AlternativeLists 2
425 * AltList 1, AltList->Count 3
426 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B
427 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5
428 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2
430 * AltList 2, AltList->Count 4
431 * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B
432 * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5
433 * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6
434 * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7
438 /* Propagate the fixed resources to our new list */
439 for (j
= 0; j
< AltList
->Count
- AltCount
; j
++)
441 RtlMoveMemory(&NextList
->Descriptors
[j
],
442 &AltList
->Descriptors
[j
],
443 sizeof(IO_RESOURCE_DESCRIPTOR
));
446 Descriptor
= &NextList
->Descriptors
[NextList
->Count
- AltCount
];
449 * Append alternatives.
450 * NOTE: To keep it simple, we append these to the end of the list.
452 if (HasIoAlternatives(Alternatives
))
454 IsaConvertIoRequirement(Descriptor
++,
455 &Alternatives
->Io
[BestConfig
[i
]]);
457 if (HasIrqAlternatives(Alternatives
))
459 FirstDescriptor
= TRUE
;
461 for (j
= 0; j
< RTL_BITS_OF(Alternatives
->Irq
[BestConfig
[i
]].Mask
); j
++)
463 if (!(Alternatives
->Irq
[BestConfig
[i
]].Mask
& (1 << j
)))
466 IsaConvertIrqRequirement(Descriptor
++,
467 &Alternatives
->Irq
[BestConfig
[i
]],
472 FirstDescriptor
= FALSE
;
477 if (HasDmaAlternatives(Alternatives
))
479 FirstDescriptor
= TRUE
;
481 for (j
= 0; j
< RTL_BITS_OF(Alternatives
->Dma
[BestConfig
[i
]].Mask
); j
++)
483 if (!(Alternatives
->Dma
[BestConfig
[i
]].Mask
& (1 << j
)))
486 IsaConvertDmaRequirement(Descriptor
++,
487 &Alternatives
->Dma
[BestConfig
[i
]],
492 FirstDescriptor
= FALSE
;
497 if (HasMemoryAlternatives(Alternatives
))
499 IsaConvertMemRangeRequirement(Descriptor
++,
500 &Alternatives
->MemRange
[BestConfig
[i
]]);
502 if (HasMemory32Alternatives(Alternatives
))
504 IsaConvertMemRange32Requirement(Descriptor
++,
505 &Alternatives
->MemRange32
[BestConfig
[i
]]);
508 NextList
= (PIO_RESOURCE_LIST
)(NextList
->Descriptors
+ NextList
->Count
);
512 PdoExt
->RequirementsList
= RequirementsList
;
513 return STATUS_SUCCESS
;
519 _In_ PISAPNP_LOGICAL_DEVICE LogDevice
,
521 _In_ ULONG RangeStart
,
523 _Out_opt_ PUCHAR Information
,
524 _Out_opt_ PULONG Length
,
525 _Out_opt_ PUCHAR WriteOrder
)
529 PISAPNP_IO_DESCRIPTION Description
;
533 for (i
= 0; i
< RTL_NUMBER_OF(LogDevice
->Io
); i
++)
535 Description
= &LogDevice
->Io
[i
].Description
;
537 Match
= Base
? (Base
>= Description
->Minimum
) && (Base
<= Description
->Maximum
)
538 : (RangeStart
>= Description
->Minimum
) &&
539 (RangeEnd
<= (ULONG
)(Description
->Maximum
+ Description
->Length
- 1));
544 *Information
= Description
->Information
;
546 *Length
= Description
->Length
;
548 *WriteOrder
= LogDevice
->Io
[i
].Index
;
554 if (!LogDevice
->Alternatives
)
557 for (i
= 0; i
< LogDevice
->Alternatives
->Count
; i
++)
559 Description
= &LogDevice
->Alternatives
->Io
[i
];
561 Match
= Base
? (Base
>= Description
->Minimum
) && (Base
<= Description
->Maximum
)
562 : (RangeStart
>= Description
->Minimum
) &&
563 (RangeEnd
<= (ULONG
)(Description
->Maximum
+ Description
->Length
- 1));
568 *Information
= Description
->Information
;
570 *Length
= Description
->Length
;
572 *WriteOrder
= LogDevice
->Alternatives
->IoIndex
;
584 _In_ PISAPNP_LOGICAL_DEVICE LogDevice
,
586 _Out_opt_ PUCHAR WriteOrder
)
589 PISAPNP_IRQ_DESCRIPTION Description
;
593 for (i
= 0; i
< RTL_NUMBER_OF(LogDevice
->Irq
); i
++)
595 Description
= &LogDevice
->Irq
[i
].Description
;
597 for (j
= 0; j
< RTL_BITS_OF(Description
->Mask
); j
++)
599 if (Description
->Mask
& (1 << j
))
604 *WriteOrder
= LogDevice
->Irq
[i
].Index
;
612 if (!LogDevice
->Alternatives
)
615 for (i
= 0; i
< LogDevice
->Alternatives
->Count
; i
++)
617 Description
= &LogDevice
->Alternatives
->Irq
[i
];
619 for (j
= 0; j
< RTL_BITS_OF(Description
->Mask
); j
++)
621 if (Description
->Mask
& (1 << j
))
626 *WriteOrder
= LogDevice
->Alternatives
->IrqIndex
;
640 _In_ PISAPNP_LOGICAL_DEVICE LogDevice
,
642 _Out_opt_ PUCHAR WriteOrder
)
645 PISAPNP_DMA_DESCRIPTION Description
;
649 for (i
= 0; i
< RTL_NUMBER_OF(LogDevice
->Dma
); i
++)
651 Description
= &LogDevice
->Dma
[i
].Description
;
653 for (j
= 0; j
< RTL_BITS_OF(Description
->Mask
); j
++)
655 if (Description
->Mask
& (1 << j
))
660 *WriteOrder
= LogDevice
->Dma
[i
].Index
;
668 if (!LogDevice
->Alternatives
)
671 for (i
= 0; i
< LogDevice
->Alternatives
->Count
; i
++)
673 Description
= &LogDevice
->Alternatives
->Dma
[i
];
675 for (j
= 0; j
< RTL_BITS_OF(Description
->Mask
); j
++)
677 if (Description
->Mask
& (1 << j
))
682 *WriteOrder
= LogDevice
->Alternatives
->DmaIndex
;
695 FindMemoryDescriptor(
696 _In_ PISAPNP_LOGICAL_DEVICE LogDevice
,
697 _In_ ULONG RangeStart
,
699 _Out_opt_ PBOOLEAN Memory32
,
700 _Out_opt_ PUCHAR Information
,
701 _Out_opt_ PUCHAR WriteOrder
)
704 PISAPNP_MEMRANGE_DESCRIPTION Description
;
705 PISAPNP_MEMRANGE32_DESCRIPTION Description32
;
709 for (i
= 0; i
< RTL_NUMBER_OF(LogDevice
->MemRange
); i
++)
711 Description
= &LogDevice
->MemRange
[i
].Description
;
713 if ((RangeStart
>= (ULONG
)(Description
->Minimum
<< 8)) &&
714 (RangeEnd
<= (ULONG
)((Description
->Maximum
<< 8) + (Description
->Length
<< 8) - 1)))
719 *Information
= Description
->Information
;
721 *WriteOrder
= LogDevice
->MemRange
[i
].Index
;
726 for (i
= 0; i
< RTL_NUMBER_OF(LogDevice
->MemRange32
); i
++)
728 Description32
= &LogDevice
->MemRange32
[i
].Description
;
730 if ((RangeStart
>= Description32
->Minimum
) &&
731 (RangeEnd
<= (Description32
->Maximum
+ Description32
->Length
- 1)))
736 *Information
= Description32
->Information
;
738 *WriteOrder
= LogDevice
->MemRange32
[i
].Index
;
744 if (!LogDevice
->Alternatives
)
747 for (i
= 0; i
< LogDevice
->Alternatives
->Count
; i
++)
749 Description
= &LogDevice
->Alternatives
->MemRange
[i
];
751 if ((RangeStart
>= (ULONG
)(Description
->Minimum
<< 8)) &&
752 (RangeEnd
<= (ULONG
)((Description
->Maximum
<< 8) + (Description
->Length
<< 8) - 1)))
757 *Information
= Description
->Information
;
759 *WriteOrder
= LogDevice
->Alternatives
->MemRangeIndex
;
764 for (i
= 0; i
< LogDevice
->Alternatives
->Count
; i
++)
766 Description32
= &LogDevice
->Alternatives
->MemRange32
[i
];
768 if ((RangeStart
>= Description32
->Minimum
) &&
769 (RangeEnd
<= (Description32
->Maximum
+ Description32
->Length
- 1)))
774 *Information
= Description32
->Information
;
776 *WriteOrder
= LogDevice
->Alternatives
->MemRange32Index
;
788 IsaPnpCreateLogicalDeviceResources(
789 _In_ PISAPNP_PDO_EXTENSION PdoExt
)
791 PISAPNP_LOGICAL_DEVICE LogDev
= PdoExt
->IsaPnpDevice
;
792 ULONG ResourceCount
= 0;
795 PCM_RESOURCE_LIST ResourceList
;
796 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
800 if (!(LogDev
->Flags
& ISAPNP_HAS_RESOURCES
))
801 return STATUS_SUCCESS
;
803 /* Count number of required resources */
804 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Io
); i
++)
806 if (LogDev
->Io
[i
].CurrentBase
)
811 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Irq
); i
++)
813 if (LogDev
->Irq
[i
].CurrentNo
)
818 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Dma
); i
++)
820 if (LogDev
->Dma
[i
].CurrentChannel
!= 4)
825 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange
); i
++)
827 if (LogDev
->MemRange
[i
].CurrentBase
)
832 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange32
); i
++)
834 if (LogDev
->MemRange32
[i
].CurrentBase
)
839 if (ResourceCount
== 0)
840 return STATUS_SUCCESS
;
842 /* Allocate memory to store resources */
843 ListSize
= sizeof(CM_RESOURCE_LIST
)
844 + (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
845 ResourceList
= ExAllocatePoolZero(PagedPool
, ListSize
, TAG_ISAPNP
);
847 return STATUS_NO_MEMORY
;
849 ResourceList
->Count
= 1;
850 ResourceList
->List
[0].InterfaceType
= Isa
;
851 ResourceList
->List
[0].PartialResourceList
.Version
= 1;
852 ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
853 ResourceList
->List
[0].PartialResourceList
.Count
= ResourceCount
;
855 /* Store resources */
857 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Io
); i
++)
861 if (!LogDev
->Io
[i
].CurrentBase
)
864 if (!FindIoDescriptor(LogDev
,
865 LogDev
->Io
[i
].CurrentBase
,
872 goto InvalidBiosResources
;
875 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
++];
876 Descriptor
->Type
= CmResourceTypePort
;
877 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
878 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
879 if (Information
& 0x1)
880 Descriptor
->Flags
|= CM_RESOURCE_PORT_16_BIT_DECODE
;
882 Descriptor
->Flags
|= CM_RESOURCE_PORT_10_BIT_DECODE
;
883 Descriptor
->u
.Port
.Length
= CurrentLength
;
884 Descriptor
->u
.Port
.Start
.LowPart
= LogDev
->Io
[i
].CurrentBase
;
886 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Irq
); i
++)
888 if (!LogDev
->Irq
[i
].CurrentNo
)
891 if (!FindIrqDescriptor(LogDev
, LogDev
->Irq
[i
].CurrentNo
, NULL
))
892 goto InvalidBiosResources
;
894 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
++];
895 Descriptor
->Type
= CmResourceTypeInterrupt
;
896 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
897 if (LogDev
->Irq
[i
].CurrentType
& 0x01)
898 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
;
900 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LATCHED
;
901 Descriptor
->u
.Interrupt
.Level
= LogDev
->Irq
[i
].CurrentNo
;
902 Descriptor
->u
.Interrupt
.Vector
= LogDev
->Irq
[i
].CurrentNo
;
903 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
905 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->Dma
); i
++)
907 if (LogDev
->Dma
[i
].CurrentChannel
== 4)
910 if (!FindDmaDescriptor(LogDev
, LogDev
->Dma
[i
].CurrentChannel
, NULL
))
911 goto InvalidBiosResources
;
913 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
++];
914 Descriptor
->Type
= CmResourceTypeDma
;
915 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
916 Descriptor
->Flags
= CM_RESOURCE_DMA_8
; /* Ignore information byte for compatibility */
917 Descriptor
->u
.Dma
.Channel
= LogDev
->Dma
[i
].CurrentChannel
;
919 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange
); i
++)
921 if (!LogDev
->MemRange
[i
].CurrentBase
)
924 if (!FindMemoryDescriptor(LogDev
,
925 LogDev
->MemRange
[i
].CurrentBase
,
926 LogDev
->MemRange
[i
].CurrentLength
,
931 goto InvalidBiosResources
;
934 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
++];
935 Descriptor
->Type
= CmResourceTypeMemory
;
936 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
937 Descriptor
->Flags
= CM_RESOURCE_MEMORY_24
;
938 if ((Information
& 0x40) || !(Information
& 0x01))
939 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_ONLY
;
941 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
942 Descriptor
->u
.Memory
.Length
= LogDev
->MemRange
[i
].Description
.Length
;
943 Descriptor
->u
.Memory
.Start
.QuadPart
= LogDev
->MemRange
[i
].CurrentBase
;
945 for (i
= 0; i
< RTL_NUMBER_OF(LogDev
->MemRange32
); i
++)
947 if (!LogDev
->MemRange32
[i
].CurrentBase
)
950 if (!FindMemoryDescriptor(LogDev
,
951 LogDev
->MemRange32
[i
].CurrentBase
,
952 LogDev
->MemRange32
[i
].CurrentLength
,
957 goto InvalidBiosResources
;
960 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
++];
961 Descriptor
->Type
= CmResourceTypeMemory
;
962 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
963 Descriptor
->Flags
= CM_RESOURCE_MEMORY_24
;
964 if ((Information
& 0x40) || !(Information
& 0x01))
965 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_ONLY
;
967 Descriptor
->Flags
|= CM_RESOURCE_MEMORY_READ_WRITE
;
968 Descriptor
->u
.Memory
.Length
= LogDev
->MemRange32
[i
].Description
.Length
;
969 Descriptor
->u
.Memory
.Start
.QuadPart
= LogDev
->MemRange32
[i
].CurrentBase
;
972 PdoExt
->ResourceList
= ResourceList
;
973 PdoExt
->ResourceListSize
= ListSize
;
974 return STATUS_SUCCESS
;
976 InvalidBiosResources
:
977 DPRINT("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev
->CSN
, LogDev
->LDN
);
979 LogDev
->Flags
&= ~ISAPNP_HAS_RESOURCES
;
980 ExFreePoolWithTag(ResourceList
, TAG_ISAPNP
);
981 return STATUS_SUCCESS
;
984 _Dispatch_type_(IRP_MJ_CREATE
)
985 _Dispatch_type_(IRP_MJ_CLOSE
)
986 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose
;
993 _In_ PDEVICE_OBJECT DeviceObject
,
998 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1000 DPRINT("%s(%p, %p)\n", __FUNCTION__
, DeviceObject
, Irp
);
1002 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1004 return STATUS_SUCCESS
;
1007 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL
)
1008 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL
)
1009 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore
;
1016 _In_ PDEVICE_OBJECT DeviceObject
,
1019 PISAPNP_COMMON_EXTENSION CommonExt
= DeviceObject
->DeviceExtension
;
1023 DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__
, DeviceObject
, Irp
,
1024 IoGetCurrentIrpStackLocation(Irp
)->MinorFunction
);
1026 if (CommonExt
->Signature
== IsaPnpBus
)
1028 IoSkipCurrentIrpStackLocation(Irp
);
1029 return IoCallDriver(((PISAPNP_FDO_EXTENSION
)CommonExt
)->Ldo
, Irp
);
1033 NTSTATUS Status
= Irp
->IoStatus
.Status
;
1035 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1042 IsaPnpCreateReadPortDORequirements(
1043 _In_ PISAPNP_PDO_EXTENSION PdoExt
,
1044 _In_opt_ ULONG SelectedReadPort
)
1046 ULONG ResourceCount
, ListSize
, i
;
1047 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
1048 PIO_RESOURCE_DESCRIPTOR Descriptor
;
1049 const ULONG Ports
[] = { ISAPNP_WRITE_DATA
, ISAPNP_ADDRESS
};
1050 const ULONG ReadPorts
[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
1054 if (SelectedReadPort
)
1057 * [IO descriptor: ISAPNP_WRITE_DATA, required]
1058 * [IO descriptor: ISAPNP_WRITE_DATA, optional]
1059 * [IO descriptor: ISAPNP_ADDRESS, required]
1060 * [IO descriptor: ISAPNP_ADDRESS, optional]
1061 * [IO descriptor: Selected Read Port, required]
1062 * [IO descriptor: Read Port 1, optional]
1063 * [IO descriptor: Read Port 2, optional]
1065 * [IO descriptor: Read Port X - 1, optional]
1067 ResourceCount
= RTL_NUMBER_OF(Ports
) * 2 + RTL_NUMBER_OF(ReadPorts
);
1072 * [IO descriptor: ISAPNP_WRITE_DATA, required]
1073 * [IO descriptor: ISAPNP_WRITE_DATA, optional]
1074 * [IO descriptor: ISAPNP_ADDRESS, required]
1075 * [IO descriptor: ISAPNP_ADDRESS, optional]
1076 * [IO descriptor: Read Port 1, required]
1077 * [IO descriptor: Read Port 1, optional]
1078 * [IO descriptor: Read Port 2, required]
1079 * [IO descriptor: Read Port 2, optional]
1081 * [IO descriptor: Read Port X, required]
1082 * [IO descriptor: Read Port X, optional]
1084 ResourceCount
= (RTL_NUMBER_OF(Ports
) + RTL_NUMBER_OF(ReadPorts
)) * 2;
1086 ListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) +
1087 sizeof(IO_RESOURCE_DESCRIPTOR
) * (ResourceCount
- 1);
1088 RequirementsList
= ExAllocatePoolZero(PagedPool
, ListSize
, TAG_ISAPNP
);
1089 if (!RequirementsList
)
1090 return STATUS_NO_MEMORY
;
1092 RequirementsList
->ListSize
= ListSize
;
1093 RequirementsList
->AlternativeLists
= 1;
1095 RequirementsList
->List
[0].Version
= 1;
1096 RequirementsList
->List
[0].Revision
= 1;
1097 RequirementsList
->List
[0].Count
= ResourceCount
;
1099 Descriptor
= &RequirementsList
->List
[0].Descriptors
[0];
1101 /* Store the Data port and the Address port */
1102 for (i
= 0; i
< RTL_NUMBER_OF(Ports
) * 2; i
++)
1107 Descriptor
->Type
= CmResourceTypePort
;
1108 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1109 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1110 Descriptor
->u
.Port
.Length
= 0x01;
1111 Descriptor
->u
.Port
.Alignment
= 0x01;
1112 Descriptor
->u
.Port
.MinimumAddress
.LowPart
=
1113 Descriptor
->u
.Port
.MaximumAddress
.LowPart
= Ports
[i
/ 2];
1117 /* ... but mark it as optional */
1118 Descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
1119 Descriptor
->Type
= CmResourceTypePort
;
1120 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1121 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1122 Descriptor
->u
.Port
.Alignment
= 0x01;
1128 /* Store the Read Ports */
1129 if (SelectedReadPort
)
1131 BOOLEAN Selected
= FALSE
;
1133 DBG_UNREFERENCED_LOCAL_VARIABLE(Selected
);
1135 for (i
= 0; i
< RTL_NUMBER_OF(ReadPorts
); i
++)
1137 if (ReadPorts
[i
] != SelectedReadPort
)
1138 Descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
1141 Descriptor
->Type
= CmResourceTypePort
;
1142 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1143 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1144 Descriptor
->u
.Port
.Length
= 0x04;
1145 Descriptor
->u
.Port
.Alignment
= 0x01;
1146 Descriptor
->u
.Port
.MinimumAddress
.LowPart
= ReadPorts
[i
];
1147 Descriptor
->u
.Port
.MaximumAddress
.LowPart
= ReadPorts
[i
] +
1148 Descriptor
->u
.Port
.Length
- 1;
1153 ASSERT(Selected
== TRUE
);
1157 for (i
= 0; i
< RTL_NUMBER_OF(ReadPorts
) * 2; i
++)
1162 Descriptor
->Type
= CmResourceTypePort
;
1163 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1164 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1165 Descriptor
->u
.Port
.Length
= 0x04;
1166 Descriptor
->u
.Port
.Alignment
= 0x01;
1167 Descriptor
->u
.Port
.MinimumAddress
.LowPart
= ReadPorts
[i
/ 2];
1168 Descriptor
->u
.Port
.MaximumAddress
.LowPart
= ReadPorts
[i
/ 2] +
1169 Descriptor
->u
.Port
.Length
- 1;
1173 /* ... but mark it as optional */
1174 Descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
1175 Descriptor
->Type
= CmResourceTypePort
;
1176 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1177 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1178 Descriptor
->u
.Port
.Alignment
= 0x01;
1185 PdoExt
->RequirementsList
= RequirementsList
;
1186 return STATUS_SUCCESS
;
1192 IsaPnpCreateReadPortDOResources(
1193 _In_ PISAPNP_PDO_EXTENSION PdoExt
)
1195 const USHORT Ports
[] = { ISAPNP_WRITE_DATA
, ISAPNP_ADDRESS
};
1197 PCM_RESOURCE_LIST ResourceList
;
1198 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
1202 ListSize
= sizeof(CM_RESOURCE_LIST
) +
1203 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) * (RTL_NUMBER_OF(Ports
) - 1);
1204 ResourceList
= ExAllocatePoolZero(PagedPool
, ListSize
, TAG_ISAPNP
);
1206 return STATUS_NO_MEMORY
;
1208 ResourceList
->Count
= 1;
1209 ResourceList
->List
[0].InterfaceType
= Internal
;
1210 ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1211 ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1212 ResourceList
->List
[0].PartialResourceList
.Count
= RTL_NUMBER_OF(Ports
);
1214 Descriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[0];
1215 for (i
= 0; i
< RTL_NUMBER_OF(Ports
); i
++)
1217 Descriptor
->Type
= CmResourceTypePort
;
1218 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
1219 Descriptor
->Flags
= CM_RESOURCE_PORT_16_BIT_DECODE
;
1220 Descriptor
->u
.Port
.Length
= 0x01;
1221 Descriptor
->u
.Port
.Start
.LowPart
= Ports
[i
];
1226 PdoExt
->ResourceList
= ResourceList
;
1227 PdoExt
->ResourceListSize
= ListSize
;
1228 return STATUS_SUCCESS
;
1234 IsaPnpCreateReadPortDO(
1235 _In_ PISAPNP_FDO_EXTENSION FdoExt
)
1237 PISAPNP_PDO_EXTENSION PdoExt
;
1241 ASSERT(ReadPortCreated
== FALSE
);
1243 DPRINT("Creating Read Port\n");
1245 Status
= IoCreateDevice(FdoExt
->DriverObject
,
1246 sizeof(ISAPNP_PDO_EXTENSION
),
1248 FILE_DEVICE_CONTROLLER
,
1249 FILE_DEVICE_SECURE_OPEN
| FILE_AUTOGENERATED_DEVICE_NAME
,
1251 &FdoExt
->ReadPortPdo
);
1252 if (!NT_SUCCESS(Status
))
1255 PdoExt
= FdoExt
->ReadPortPdo
->DeviceExtension
;
1256 RtlZeroMemory(PdoExt
, sizeof(ISAPNP_PDO_EXTENSION
));
1257 PdoExt
->Common
.Signature
= IsaPnpReadDataPort
;
1258 PdoExt
->Common
.Self
= FdoExt
->ReadPortPdo
;
1259 PdoExt
->Common
.State
= dsStopped
;
1260 PdoExt
->FdoExt
= FdoExt
;
1262 Status
= IsaPnpCreateReadPortDORequirements(PdoExt
, 0);
1263 if (!NT_SUCCESS(Status
))
1266 Status
= IsaPnpCreateReadPortDOResources(PdoExt
);
1267 if (!NT_SUCCESS(Status
))
1270 FdoExt
->ReadPortPdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1275 IsaPnpRemoveReadPortDO(FdoExt
->ReadPortPdo
);
1277 FdoExt
->ReadPortPdo
= NULL
;
1284 IsaPnpRemoveReadPortDO(
1285 _In_ PDEVICE_OBJECT Pdo
)
1287 PISAPNP_PDO_EXTENSION ReadPortExt
= Pdo
->DeviceExtension
;
1291 DPRINT("Removing Read Port\n");
1293 if (ReadPortExt
->RequirementsList
)
1294 ExFreePoolWithTag(ReadPortExt
->RequirementsList
, TAG_ISAPNP
);
1296 if (ReadPortExt
->ResourceList
)
1297 ExFreePoolWithTag(ReadPortExt
->ResourceList
, TAG_ISAPNP
);
1299 IoDeleteDevice(Pdo
);
1304 IsaPnpFillDeviceRelations(
1305 _In_ PISAPNP_FDO_EXTENSION FdoExt
,
1307 _In_ BOOLEAN IncludeDataPort
)
1309 NTSTATUS Status
= STATUS_SUCCESS
;
1310 PLIST_ENTRY CurrentEntry
;
1311 PISAPNP_LOGICAL_DEVICE IsaDevice
;
1312 PDEVICE_RELATIONS DeviceRelations
;
1313 ULONG PdoCount
, i
= 0;
1317 IsaPnpAcquireBusDataLock();
1319 /* Try to claim the Read Port for our FDO */
1320 if (!ReadPortCreated
)
1322 Status
= IsaPnpCreateReadPortDO(FdoExt
);
1323 if (!NT_SUCCESS(Status
))
1326 ReadPortCreated
= TRUE
;
1329 IsaPnpReleaseBusDataLock();
1331 /* Inactive ISA bus */
1332 if (!FdoExt
->ReadPortPdo
)
1333 IncludeDataPort
= FALSE
;
1335 IsaPnpAcquireDeviceDataLock(FdoExt
);
1337 /* If called from the FDO dispatch routine && Active bus */
1338 if (IncludeDataPort
&& FdoExt
->ReadPortPdo
)
1340 PISAPNP_PDO_EXTENSION ReadPortExt
= FdoExt
->ReadPortPdo
->DeviceExtension
;
1342 if ((ReadPortExt
->Flags
& ISAPNP_READ_PORT_ALLOW_FDO_SCAN
) &&
1343 !(ReadPortExt
->Flags
& ISAPNP_SCANNED_BY_READ_PORT
))
1345 DPRINT("Rescan ISA PnP bus\n");
1347 /* Run the isolation protocol */
1348 FdoExt
->Cards
= IsaHwTryReadDataPort(FdoExt
->ReadDataPort
);
1350 /* Card identification */
1351 if (FdoExt
->Cards
> 0)
1352 (VOID
)IsaHwFillDeviceList(FdoExt
);
1357 ReadPortExt
->Flags
&= ~ISAPNP_SCANNED_BY_READ_PORT
;
1360 PdoCount
= FdoExt
->DeviceCount
;
1361 if (IncludeDataPort
)
1364 CurrentEntry
= FdoExt
->DeviceListHead
.Flink
;
1365 while (CurrentEntry
!= &FdoExt
->DeviceListHead
)
1367 IsaDevice
= CONTAINING_RECORD(CurrentEntry
, ISAPNP_LOGICAL_DEVICE
, DeviceLink
);
1369 if (!(IsaDevice
->Flags
& ISAPNP_PRESENT
))
1372 CurrentEntry
= CurrentEntry
->Flink
;
1375 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1376 FIELD_OFFSET(DEVICE_RELATIONS
, Objects
[PdoCount
]),
1378 if (!DeviceRelations
)
1380 IsaPnpReleaseDeviceDataLock(FdoExt
);
1381 return STATUS_NO_MEMORY
;
1384 if (IncludeDataPort
)
1386 PISAPNP_PDO_EXTENSION ReadPortExt
= FdoExt
->ReadPortPdo
->DeviceExtension
;
1388 DeviceRelations
->Objects
[i
++] = FdoExt
->ReadPortPdo
;
1389 ObReferenceObject(FdoExt
->ReadPortPdo
);
1391 /* The Read Port PDO can only be removed by FDO */
1392 ReadPortExt
->Flags
|= ISAPNP_ENUMERATED
;
1395 CurrentEntry
= FdoExt
->DeviceListHead
.Flink
;
1396 while (CurrentEntry
!= &FdoExt
->DeviceListHead
)
1398 PISAPNP_PDO_EXTENSION PdoExt
;
1400 IsaDevice
= CONTAINING_RECORD(CurrentEntry
, ISAPNP_LOGICAL_DEVICE
, DeviceLink
);
1402 if (!(IsaDevice
->Flags
& ISAPNP_PRESENT
))
1405 if (!IsaDevice
->Pdo
)
1407 Status
= IoCreateDevice(FdoExt
->DriverObject
,
1408 sizeof(ISAPNP_PDO_EXTENSION
),
1410 FILE_DEVICE_CONTROLLER
,
1411 FILE_DEVICE_SECURE_OPEN
| FILE_AUTOGENERATED_DEVICE_NAME
,
1414 if (!NT_SUCCESS(Status
))
1417 IsaDevice
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1418 /* The power pagable flag is always unset */
1420 PdoExt
= IsaDevice
->Pdo
->DeviceExtension
;
1422 RtlZeroMemory(PdoExt
, sizeof(ISAPNP_PDO_EXTENSION
));
1423 PdoExt
->Common
.Signature
= IsaPnpLogicalDevice
;
1424 PdoExt
->Common
.Self
= IsaDevice
->Pdo
;
1425 PdoExt
->Common
.State
= dsStopped
;
1426 PdoExt
->IsaPnpDevice
= IsaDevice
;
1427 PdoExt
->FdoExt
= FdoExt
;
1429 if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt
)) ||
1430 !NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt
)))
1432 if (PdoExt
->RequirementsList
)
1434 ExFreePoolWithTag(PdoExt
->RequirementsList
, TAG_ISAPNP
);
1435 PdoExt
->RequirementsList
= NULL
;
1438 if (PdoExt
->ResourceList
)
1440 ExFreePoolWithTag(PdoExt
->ResourceList
, TAG_ISAPNP
);
1441 PdoExt
->ResourceList
= NULL
;
1444 IoDeleteDevice(IsaDevice
->Pdo
);
1445 IsaDevice
->Pdo
= NULL
;
1451 PdoExt
= IsaDevice
->Pdo
->DeviceExtension
;
1453 DeviceRelations
->Objects
[i
++] = IsaDevice
->Pdo
;
1454 ObReferenceObject(IsaDevice
->Pdo
);
1456 PdoExt
->Flags
|= ISAPNP_ENUMERATED
;
1458 CurrentEntry
= CurrentEntry
->Flink
;
1464 PdoExt
= IsaDevice
->Pdo
->DeviceExtension
;
1467 PdoExt
->Flags
&= ~ISAPNP_ENUMERATED
;
1470 CurrentEntry
= CurrentEntry
->Flink
;
1473 IsaPnpReleaseDeviceDataLock(FdoExt
);
1475 DeviceRelations
->Count
= i
;
1477 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1482 static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaAddDevice
;
1489 _In_ PDRIVER_OBJECT DriverObject
,
1490 _In_ PDEVICE_OBJECT PhysicalDeviceObject
)
1493 PISAPNP_FDO_EXTENSION FdoExt
;
1495 static ULONG BusNumber
= 0;
1499 DPRINT("%s(%p, %p)\n", __FUNCTION__
, DriverObject
, PhysicalDeviceObject
);
1501 Status
= IoCreateDevice(DriverObject
,
1504 FILE_DEVICE_BUS_EXTENDER
,
1505 FILE_DEVICE_SECURE_OPEN
,
1508 if (!NT_SUCCESS(Status
))
1510 DPRINT1("Failed to create FDO (0x%08lx)\n", Status
);
1514 FdoExt
= Fdo
->DeviceExtension
;
1515 RtlZeroMemory(FdoExt
, sizeof(*FdoExt
));
1517 FdoExt
->Common
.Self
= Fdo
;
1518 FdoExt
->Common
.Signature
= IsaPnpBus
;
1519 FdoExt
->Common
.State
= dsStopped
;
1520 FdoExt
->DriverObject
= DriverObject
;
1521 FdoExt
->BusNumber
= BusNumber
++;
1522 FdoExt
->Pdo
= PhysicalDeviceObject
;
1523 FdoExt
->Ldo
= IoAttachDeviceToDeviceStack(Fdo
,
1524 PhysicalDeviceObject
);
1527 IoDeleteDevice(Fdo
);
1528 return STATUS_DEVICE_REMOVED
;
1531 InitializeListHead(&FdoExt
->DeviceListHead
);
1532 KeInitializeEvent(&FdoExt
->DeviceSyncEvent
, SynchronizationEvent
, TRUE
);
1534 IsaPnpAcquireBusDataLock();
1535 InsertTailList(&BusListHead
, &FdoExt
->BusLink
);
1536 IsaPnpReleaseBusDataLock();
1538 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1540 return STATUS_SUCCESS
;
1543 _Dispatch_type_(IRP_MJ_POWER
)
1544 static DRIVER_DISPATCH_RAISED IsaPower
;
1550 _In_ PDEVICE_OBJECT DeviceObject
,
1553 PISAPNP_COMMON_EXTENSION DevExt
= DeviceObject
->DeviceExtension
;
1556 if (DevExt
->Signature
!= IsaPnpBus
)
1558 switch (IoGetCurrentIrpStackLocation(Irp
)->MinorFunction
)
1560 case IRP_MN_SET_POWER
:
1561 case IRP_MN_QUERY_POWER
:
1562 Status
= STATUS_SUCCESS
;
1563 Irp
->IoStatus
.Status
= Status
;
1567 Status
= Irp
->IoStatus
.Status
;
1571 PoStartNextPowerIrp(Irp
);
1572 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1576 PoStartNextPowerIrp(Irp
);
1577 IoSkipCurrentIrpStackLocation(Irp
);
1578 return PoCallDriver(((PISAPNP_FDO_EXTENSION
)DevExt
)->Ldo
, Irp
);
1581 _Dispatch_type_(IRP_MJ_PNP
)
1582 static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaPnp
;
1589 _In_ PDEVICE_OBJECT DeviceObject
,
1592 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1593 PISAPNP_COMMON_EXTENSION DevExt
= DeviceObject
->DeviceExtension
;
1597 if (DevExt
->Signature
== IsaPnpBus
)
1598 return IsaFdoPnp((PISAPNP_FDO_EXTENSION
)DevExt
, Irp
, IrpSp
);
1600 return IsaPdoPnp((PISAPNP_PDO_EXTENSION
)DevExt
, Irp
, IrpSp
);
1607 _In_ PDRIVER_OBJECT DriverObject
,
1608 _In_ PUNICODE_STRING RegistryPath
)
1610 DPRINT("%s(%p, %wZ)\n", __FUNCTION__
, DriverObject
, RegistryPath
);
1612 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = IsaCreateClose
;
1613 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = IsaCreateClose
;
1614 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = IsaForwardOrIgnore
;
1615 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = IsaForwardOrIgnore
;
1616 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = IsaPnp
;
1617 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IsaPower
;
1618 DriverObject
->DriverExtension
->AddDevice
= IsaAddDevice
;
1620 /* FIXME: Fix SDK headers */
1622 _No_competing_thread_begin_
1625 KeInitializeEvent(&BusSyncEvent
, SynchronizationEvent
, TRUE
);
1626 InitializeListHead(&BusListHead
);
1628 /* FIXME: Fix SDK headers */
1630 _No_competing_thread_end_
1633 return STATUS_SUCCESS
;