1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Precompiled header for isapnp_unittest
5  * COPYRIGHT:   Copyright 2024 Dmitry Borisov <di.sean@protonmail.com>
6  */
7 
8 #pragma once
9 
10 #include <apitest.h>
11 
12 #define WIN32_NO_STATUS
13 #include <ndk/rtlfuncs.h>
14 
15 typedef PVOID PDEVICE_OBJECT;
16 
17 #define UNIT_TEST
18 #include <isapnphw.h>
19 #include <isapnpres.h>
20 
21 /* KERNEL DEFINITIONS (MOCK) **************************************************/
22 
23 #define PAGED_CODE()
24 #define CODE_SEG(segment)
25 #define DPRINT(...)  do { if (0) { trace(__VA_ARGS__); } } while (0)
26 #define DPRINT1(...) do { if (0) { trace(__VA_ARGS__); } } while (0)
27 #define KeStallExecutionProcessor(MicroSeconds)
28 
29 FORCEINLINE
30 PVOID
ExAllocatePoolWithTag(ULONG PoolType,SIZE_T NumberOfBytes,ULONG Tag)31 ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
32 {
33     PULONG_PTR Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID));
34     if (Mem == NULL)
35         return NULL;
36 
37     Mem[0] = NumberOfBytes;
38     Mem[1] = Tag;
39 
40     return (PVOID)(Mem + 2);
41 }
42 
43 FORCEINLINE
44 PVOID
ExAllocatePoolZero(ULONG PoolType,SIZE_T NumberOfBytes,ULONG Tag)45 ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
46 {
47     PVOID Result = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
48 
49     if (Result != NULL)
50         RtlZeroMemory(Result, NumberOfBytes);
51 
52     return Result;
53 }
54 
55 FORCEINLINE
56 VOID
ExFreePoolWithTag(PVOID MemPtr,ULONG Tag)57 ExFreePoolWithTag(PVOID MemPtr, ULONG Tag)
58 {
59     PULONG_PTR Mem = MemPtr;
60 
61     Mem -= 2;
62     ok(Mem[1] == Tag, "Tag is %lx, expected %lx\n", Tag, Mem[1]);
63     HeapFree(GetProcessHeap(), 0, Mem);
64 }
65 
66 FORCEINLINE
67 SIZE_T
GetPoolAllocSize(PVOID MemPtr)68 GetPoolAllocSize(PVOID MemPtr)
69 {
70     PVOID* Mem = MemPtr;
71 
72     Mem -= 2;
73     return (SIZE_T)Mem[0];
74 }
75 
76 /* ISAPNP DRIVER DEFINITIONS (MOCK) *******************************************/
77 
78 #define TAG_ISAPNP 'pasI'
79 
80 typedef struct _ISAPNP_FDO_EXTENSION
81 {
82     LIST_ENTRY DeviceListHead;
83     ULONG DeviceCount;
84     ULONG Cards;
85     PUCHAR ReadDataPort;
86 } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
87 
88 typedef struct _ISAPNP_PDO_EXTENSION
89 {
90     PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
91 
92     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
93 
94     PCM_RESOURCE_LIST ResourceList;
95     ULONG ResourceListSize;
96 } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
97 
98 /* TEST DEFINITIONS ***********************************************************/
99 
100 typedef enum _ISAPNP_STATE
101 {
102     IsaWaitForKey = 0,
103     IsaSleep = 1,
104     IsaIsolation = 2,
105     IsaConfgure = 3
106 } ISAPNP_STATE;
107 
108 typedef struct _ISAPNP_CARD_LOGICAL_DEVICE
109 {
110     UCHAR Registers[0xFF];
111 } ISAPNP_CARD_LOGICAL_DEVICE, *PISAPNP_CARD_LOGICAL_DEVICE;
112 
113 #define TEST_MAX_SUPPORTED_DEVICES     7
114 
115 typedef struct _ISAPNP_CARD
116 {
117     ISAPNP_STATE State;
118     UCHAR LfsrCount;
119     UCHAR Lfsr;
120     UCHAR SelectNumberReg;
121     UCHAR DeviceNumberReg;
122     UCHAR SerialIsolationIdx;
123     UCHAR SerialIdResponse;
124     UCHAR IsolationRead;
125     PUCHAR PnpRom;
126     PUCHAR ReadDataPort;
127     ULONG RomIdx;
128     ULONG RomSize;
129     ULONG LogicalDevices;
130     ISAPNP_CARD_LOGICAL_DEVICE LogDev[TEST_MAX_SUPPORTED_DEVICES];
131 } ISAPNP_CARD, *PISAPNP_CARD;
132 
133 UCHAR
134 NTAPI
135 READ_PORT_UCHAR(
136     _In_ PUCHAR Port);
137 
138 VOID
139 NTAPI
140 WRITE_PORT_UCHAR(
141     _In_ PUCHAR Port,
142     _In_ UCHAR Value);
143 
144 VOID
145 IsaBusCreateCard(
146     _Inout_ PISAPNP_CARD Card,
147     _In_ PVOID PnpRom,
148     _In_ ULONG RomSize,
149     _In_ ULONG LogicalDevices);
150 
151 VOID
152 DrvCreateCard1(
153     _In_ PISAPNP_CARD Card);
154 
155 VOID
156 DrvTestCard1Dev1Resources(
157     _In_ PCM_RESOURCE_LIST ResourceList,
158     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
159 
160 VOID
161 DrvTestCard1Dev2Resources(
162     _In_ PCM_RESOURCE_LIST ResourceList,
163     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
164 
165 VOID
166 DrvTestCard1Dev3Resources(
167     _In_ PCM_RESOURCE_LIST ResourceList,
168     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
169 
170 VOID
171 DrvTestCard1Dev4Resources(
172     _In_ PCM_RESOURCE_LIST ResourceList,
173     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
174 
175 VOID
176 DrvTestCard1Dev5Resources(
177     _In_ PCM_RESOURCE_LIST ResourceList,
178     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
179 
180 VOID
181 DrvTestCard1Dev6Resources(
182     _In_ PCM_RESOURCE_LIST ResourceList,
183     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
184 
185 VOID
186 DrvTestCard1Dev7Resources(
187     _In_ PCM_RESOURCE_LIST ResourceList,
188     _In_ PIO_RESOURCE_REQUIREMENTS_LIST ReqList);
189 
190 PCM_RESOURCE_LIST
191 DrvTestCard1Dev6CreateConfigurationResources(VOID);
192 
193 VOID
194 DrvTestCard1Dev6ConfigurationResult(
195     _In_ PISAPNP_CARD_LOGICAL_DEVICE LogDev);
196 
197 VOID
198 DrvCreateCard2(
199     _In_ PISAPNP_CARD Card);
200 
201 #define expect_resource_list_header(ResourceList, ExpectedIface, ExpectedCount)       \
202     do {                                                                              \
203     ok_eq_int((ResourceList)->List[0].InterfaceType, (ExpectedIface));                \
204     ok_eq_ulong((ResourceList)->List[0].BusNumber, 0UL);                              \
205     ok_eq_int((ResourceList)->List[0].PartialResourceList.Version, 1); /* 0 */        \
206     ok_eq_int((ResourceList)->List[0].PartialResourceList.Revision, 1); /* 0x3000 */  \
207     ok_eq_ulong((ResourceList)->List[0].PartialResourceList.Count, (ExpectedCount));  \
208     } while (0)
209 
210 #define expect_requirements_list_header(ReqList, ExpectedIface, ExpectedCount)       \
211     do {                                                                             \
212     ok_eq_int((ReqList)->InterfaceType, (ExpectedIface));                            \
213     ok_eq_ulong((ReqList)->BusNumber, 0UL);                                          \
214     ok_eq_ulong((ReqList)->SlotNumber, 0UL);                                         \
215     ok_eq_ulong((ReqList)->AlternativeLists, (ExpectedCount));                       \
216     } while (0)
217 
218 #define expect_alt_list_header(AltList, ExpectedCount)  \
219     do {                                                \
220     ok_eq_int((AltList)->Version, 1);                   \
221     ok_eq_int((AltList)->Revision, 1);                  \
222     ok_eq_ulong((AltList)->Count, (ExpectedCount));     \
223     } while (0)
224 
225 #define expect_port_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare,      \
226                         ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax) \
227     do {                                                                         \
228     ok((Desc)->Type == CmResourceTypePort,                                       \
229        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypePort);      \
230     ok((Desc)->Option == (ExpectedOption),                                       \
231        "Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption));    \
232     ok((Desc)->Flags == (ExpectedFlags),                                         \
233        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));       \
234     ok((Desc)->ShareDisposition == (ExpectedShare),                              \
235        "Desc->ShareDisposition = %u, expected %u\n",                             \
236        (Desc)->ShareDisposition, (ExpectedShare));                               \
237     ok((Desc)->u.Port.Length == (ExpectedLength),                                \
238        "Desc->u.Port.Length = %lx, expected %lx\n",                              \
239        (Desc)->u.Port.Length, (ExpectedLength));                                 \
240     ok((Desc)->u.Port.Alignment == (ExpectedAlign),                              \
241        "Desc->u.Port.Alignment = %lu, expected %lu\n",                           \
242        (Desc)->u.Port.Alignment, (ExpectedAlign));                               \
243     ok((Desc)->u.Port.MinimumAddress.QuadPart == (ExpectedMin),                  \
244        "Desc->u.Port.MinimumAddress = 0x%I64x, expected 0x%I64x\n",              \
245        (Desc)->u.Port.MinimumAddress.QuadPart, (ExpectedMin));                   \
246     ok((Desc)->u.Port.MaximumAddress.QuadPart == (ExpectedMax),                  \
247        "Desc->u.Port.MaximumAddress = 0x%I64x, expected 0x%I64x\n",              \
248        (Desc)->u.Port.MaximumAddress.QuadPart, (ExpectedMax));                   \
249     } while (0)
250 
251 #define expect_irq_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare,       \
252                        ExpectedMin, ExpectedMax)                                 \
253     do {                                                                         \
254     ok((Desc)->Type == CmResourceTypeInterrupt,                                  \
255        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeInterrupt); \
256     ok((Desc)->Option == (ExpectedOption),                                       \
257        "Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption));    \
258     ok((Desc)->Flags == (ExpectedFlags),                                         \
259        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));       \
260     ok((Desc)->ShareDisposition == (ExpectedShare),                              \
261        "Desc->ShareDisposition = %u, expected %u\n",                             \
262        (Desc)->ShareDisposition, (ExpectedShare));                               \
263     ok((Desc)->u.Interrupt.MinimumVector == (ExpectedMin),                       \
264        "Desc->u.Interrupt.MinimumVector = %lu, expected %lu\n",                  \
265        (Desc)->u.Interrupt.MinimumVector, (ExpectedMin));                        \
266     ok((Desc)->u.Interrupt.MaximumVector == (ExpectedMax),                       \
267        "Desc->u.Interrupt.MaximumVector = %lu, expected %lu\n",                  \
268        (Desc)->u.Interrupt.MaximumVector, (ExpectedMax));                        \
269     } while (0)
270 
271 #define expect_dma_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare,       \
272                        ExpectedMin, ExpectedMax)                                 \
273     do {                                                                         \
274     ok((Desc)->Type == CmResourceTypeDma,                                        \
275        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeDma);       \
276     ok((Desc)->Option == (ExpectedOption),                                       \
277        "Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption));    \
278     ok((Desc)->Flags == (ExpectedFlags),                                         \
279        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));       \
280     ok((Desc)->ShareDisposition == (ExpectedShare),                              \
281        "Desc->ShareDisposition = %u, expected %u\n",                             \
282        (Desc)->ShareDisposition, (ExpectedShare));                               \
283     ok((Desc)->u.Dma.MinimumChannel == (ExpectedMin),                            \
284        "Desc->u.Dma.MinimumChannel = %lu, expected %lu\n",                       \
285        (Desc)->u.Dma.MinimumChannel, (ExpectedMin));                             \
286     ok((Desc)->u.Dma.MaximumChannel == (ExpectedMax),                            \
287        "Desc->u.Dma.MaximumChannel = %lu, expected %lu\n",                       \
288        (Desc)->u.Dma.MaximumChannel, (ExpectedMax));                             \
289     } while (0)
290 
291 #define expect_mem_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare,       \
292                        ExpectedLength, ExpectedAlign, ExpectedMin, ExpectedMax)  \
293     do {                                                                         \
294     ok((Desc)->Type == CmResourceTypeMemory,                                     \
295        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeMemory);    \
296     ok((Desc)->Option == (ExpectedOption),                                       \
297        "Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption));    \
298     ok((Desc)->Flags == (ExpectedFlags),                                         \
299        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));       \
300     ok((Desc)->ShareDisposition == (ExpectedShare),                              \
301        "Desc->ShareDisposition = %u, expected %u\n",                             \
302        (Desc)->ShareDisposition, (ExpectedShare));                               \
303     ok((Desc)->u.Memory.Length == (ExpectedLength),                              \
304        "Desc->u.Memory.Length = %lx, expected %lx\n",                            \
305        (Desc)->u.Memory.Length, (ExpectedLength));                               \
306     ok((Desc)->u.Memory.Alignment == (ExpectedAlign),                            \
307        "Desc->u.Memory.Alignment = %lx, expected %lx\n",                         \
308        (Desc)->u.Memory.Alignment, (ExpectedAlign));                             \
309     ok((Desc)->u.Memory.MinimumAddress.QuadPart == (ExpectedMin),                \
310        "Desc->u.Memory.MinimumAddress = 0x%I64x, expected 0x%I64x\n",            \
311        (Desc)->u.Memory.MinimumAddress.QuadPart, (ExpectedMin));                 \
312     ok((Desc)->u.Memory.MaximumAddress.QuadPart == (ExpectedMax),                \
313        "Desc->u.Memory.MaximumAddress = 0x%I64x, expected 0x%I64x\n",            \
314        (Desc)->u.Memory.MaximumAddress.QuadPart, (ExpectedMax));                 \
315     } while (0)
316 
317 #define expect_cfg_req(Desc, ExpectedOption, ExpectedFlags, ExpectedShare,        \
318                        ExpectedPriority, ExpectedRes1, ExpectedRes2)              \
319     do {                                                                          \
320     ok((Desc)->Type == CmResourceTypeConfigData,                                  \
321        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeConfigData); \
322     ok((Desc)->Option == (ExpectedOption),                                        \
323        "Desc->Option = %u, expected %u\n", (Desc)->Option, (ExpectedOption));     \
324     ok((Desc)->Flags == (ExpectedFlags),                                          \
325        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));        \
326     ok((Desc)->ShareDisposition == (ExpectedShare),                               \
327        "Desc->ShareDisposition = %u, expected %u\n",                              \
328        (Desc)->ShareDisposition, (ExpectedShare));                                \
329     ok((Desc)->u.ConfigData.Priority == (ExpectedPriority),                       \
330        "Desc->u.ConfigData.Priority = %lx, expected %lx\n",                       \
331        (Desc)->u.ConfigData.Priority, (ExpectedPriority));                        \
332     ok((Desc)->u.ConfigData.Reserved1 == (ExpectedRes1),                          \
333        "Desc->u.ConfigData.Reserved1 = %lx, expected %lx\n",                      \
334        (Desc)->u.ConfigData.Reserved2, (ExpectedRes1));                           \
335     ok((Desc)->u.ConfigData.Reserved2 == (ExpectedRes2),                          \
336        "Desc->u.ConfigData.Reserved2 = %lx, expected %lx\n",                      \
337        (Desc)->u.ConfigData.Reserved2, (ExpectedRes2));                           \
338     } while (0)
339 
340 #define expect_port_res(Desc, ExpectedFlags, ExpectedShare, ExpectedLength, ExpectedStart) \
341     do {                                                                                   \
342     ok((Desc)->Type == CmResourceTypePort,                                                 \
343        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypePort);                \
344     ok((Desc)->Flags == (ExpectedFlags),                                                   \
345        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));                 \
346     ok((Desc)->ShareDisposition == (ExpectedShare),                                        \
347        "Desc->ShareDisposition = %u, expected %u\n",                                       \
348        (Desc)->ShareDisposition, (ExpectedShare));                                         \
349     ok((Desc)->u.Port.Length == (ExpectedLength),                                          \
350        "Desc->u.Port.Length = %lx, expected %lx\n",                                        \
351        (Desc)->u.Port.Length, (ExpectedLength));                                           \
352     ok((Desc)->u.Port.Start.QuadPart == (ExpectedStart),                                   \
353        "Desc->u.Port.Start = 0x%I64x, expected 0x%I64x\n",                                 \
354        (Desc)->u.Port.Start.QuadPart, (ExpectedStart));                                    \
355     } while (0)
356 
357 #define expect_irq_res(Desc, ExpectedFlags, ExpectedShare,                                 \
358                        ExpectedLevel, ExpectedVector, ExpectedAffinity)                    \
359     do {                                                                                   \
360     ok((Desc)->Type == CmResourceTypeInterrupt,                                            \
361        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeInterrupt);           \
362     ok((Desc)->Flags == (ExpectedFlags),                                                   \
363        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));                 \
364     ok((Desc)->ShareDisposition == (ExpectedShare),                                        \
365        "Desc->ShareDisposition = %u, expected %u\n",                                       \
366        (Desc)->ShareDisposition, (ExpectedShare));                                         \
367     ok((Desc)->u.Interrupt.Level == (ExpectedLevel),                                       \
368        "Desc->u.Interrupt.Level = %lu\n", (Desc)->u.Interrupt.Level);                      \
369     ok((Desc)->u.Interrupt.Vector == (ExpectedVector),                                     \
370        "Desc->u.Interrupt.Vector = %lu\n", (Desc)->u.Interrupt.Vector);                    \
371     ok((Desc)->u.Interrupt.Affinity == (ExpectedAffinity),                                 \
372        "Desc->u.Interrupt.Affinity = %Ix\n", (Desc)->u.Interrupt.Affinity);                \
373     } while (0)
374 
375 #define expect_dma_res(Desc, ExpectedFlags, ExpectedShare, ExpectedChannel)                \
376     do {                                                                                   \
377     ok((Desc)->Type == CmResourceTypeDma,                                                  \
378        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeDma);                 \
379     ok((Desc)->Flags == (ExpectedFlags),                                                   \
380        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));                 \
381     ok((Desc)->ShareDisposition == (ExpectedShare),                                        \
382        "Desc->ShareDisposition = %u, expected %u\n",                                       \
383        (Desc)->ShareDisposition, (ExpectedShare));                                         \
384     ok((Desc)->u.Dma.Channel == (ExpectedChannel),                                         \
385        "Desc->u.Dma.Channel = %lu, expected %lu\n",                                        \
386        (Desc)->u.Dma.Channel, (ExpectedChannel));                                          \
387     ok((Desc)->u.Dma.Port == 0ul,                                                          \
388        "Desc->u.Dma.Port = %lu, expected %lu\n",                                           \
389        (Desc)->u.Dma.Port, 0ul);                                                           \
390     ok((Desc)->u.Dma.Reserved1 == 0ul,                                                     \
391        "Desc->u.Dma.Reserved1 = %lx, expected 0\n", (Desc)->u.Dma.Reserved1);              \
392     } while (0)
393 
394 #define expect_mem_res(Desc, ExpectedFlags, ExpectedShare, ExpectedLength, ExpectedStart)  \
395     do {                                                                                   \
396     ok((Desc)->Type == CmResourceTypeMemory,                                               \
397        "Desc->Type = %u, expected %u\n", (Desc)->Type, CmResourceTypeMemory);              \
398     ok((Desc)->Flags == (ExpectedFlags),                                                   \
399        "Desc->Flags = %x, expected %x\n", (Desc)->Flags, (ExpectedFlags));                 \
400     ok((Desc)->ShareDisposition == (ExpectedShare),                                        \
401        "Desc->ShareDisposition = %u, expected %u\n",                                       \
402        (Desc)->ShareDisposition, (ExpectedShare));                                         \
403     ok((Desc)->u.Memory.Length == (ExpectedLength),                                        \
404        "Desc->u.Memory.Length = %lx, expected %lx\n",                                      \
405        (Desc)->u.Memory.Length, (ExpectedLength));                                         \
406     ok((Desc)->u.Memory.Start.QuadPart == (ExpectedStart),                                 \
407        "Desc->u.Memory.Start = 0x%I64x, expected 0x%I64x\n",                               \
408        (Desc)->u.Memory.Start.QuadPart, (ExpectedStart));                                  \
409     } while (0)
410