xref: /reactos/ntoskrnl/fstub/translate.c (revision 8a978a17)
1 /*
2 * PROJECT:         ReactOS Kernel
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            ntoskrnl/fstub/translate.c
5 * PURPOSE:         Interrupt Translator Routines
6 * PROGRAMMERS:     Pierre Schweitzer (pierre.schweitzer@reactos.org)
7 */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* PRIVATE FUNCTIONS *********************************************************/
16 
17 /*
18  * @implemented
19  */
20 VOID
21 NTAPI
22 FstubTranslatorNull(PVOID Context)
23 {
24     PAGED_CODE();
25 
26     /* Do nothing */
27     return;
28 }
29 
30 /*
31  * @implemented
32  */
33 NTSTATUS
34 NTAPI
35 FstubTranslateResource(IN OUT PVOID Context OPTIONAL,
36                        IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
37                        IN RESOURCE_TRANSLATION_DIRECTION Direction,
38                        IN ULONG AlternativesCount OPTIONAL,
39                        IN IO_RESOURCE_DESCRIPTOR Alternatives[],
40                        IN PDEVICE_OBJECT PhysicalDeviceObject,
41                        OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target)
42 {
43     KIRQL Irql;
44     KAFFINITY Affinity;
45     ULONG MinimumVector, Vector, k;
46     PIO_RESOURCE_DESCRIPTOR Alternative;
47     NTSTATUS Status = STATUS_UNSUCCESSFUL;
48     PAGED_CODE();
49 
50     ASSERT(Source->Type == CmResourceTypeInterrupt);
51 
52     /* Copy common information */
53     Target->Type = Source->Type;
54     Target->ShareDisposition = Source->ShareDisposition;
55     Target->Flags = Source->Flags;
56 
57     if (Direction == TranslateChildToParent)
58     {
59         /* Get IRQL, affinity & system vector for the device vector */
60         Target->u.Interrupt.Vector = HalGetInterruptVector((INTERFACE_TYPE)Context, 0,
61                                                            Source->u.Interrupt.Vector,
62                                                            Source->u.Interrupt.Vector,
63                                                            &Irql, &Affinity);
64         Target->u.Interrupt.Level = Irql;
65         Target->u.Interrupt.Affinity = Affinity;
66         Status = STATUS_TRANSLATION_COMPLETE;
67     }
68     else if (Direction == TranslateParentToChild)
69     {
70         /* Browse all the resources */
71         for (k = 0; k < AlternativesCount; k++)
72         {
73             Alternative = &(Alternatives[k]);
74 
75             ASSERT(Alternative->Type == CmResourceTypeInterrupt);
76 
77             /* Try to find the device vector, proceeding by trial & error
78              * We try a vector, and translate it
79              */
80             MinimumVector = Alternative->u.Interrupt.MinimumVector;
81             while (MinimumVector <= Alternative->u.Interrupt.MaximumVector)
82             {
83                 /* Translate the vector */
84                 Vector = HalGetInterruptVector((INTERFACE_TYPE)Context, 0,
85                                                MinimumVector,
86                                                MinimumVector,
87                                                &Irql, &Affinity);
88 
89                 /* If the translated vector is matching the given translated vector */
90                 if (Vector == Source->u.Interrupt.Vector)
91                 {
92                     /* We are done, send back device vector */
93                     Target->u.Interrupt.Affinity = -1;
94                     Target->u.Interrupt.Vector = MinimumVector;
95                     Target->u.Interrupt.Level = MinimumVector;
96 
97                     return STATUS_SUCCESS;
98                 }
99 
100                 MinimumVector++;
101             }
102         }
103     }
104 
105     return Status;
106 }
107 
108 /*
109  * @implemented
110  */
111 NTSTATUS
112 NTAPI
113 FstubTranslateRequirement(IN OUT PVOID Context OPTIONAL,
114                           IN PIO_RESOURCE_DESCRIPTOR Source,
115                           IN PDEVICE_OBJECT PhysicalDeviceObject,
116                           OUT PULONG TargetCount,
117                           OUT PIO_RESOURCE_DESCRIPTOR *Target)
118 {
119     KIRQL Irql;
120     KAFFINITY Affinity;
121     PAGED_CODE();
122 
123     ASSERT(Source->Type == CmResourceTypeInterrupt);
124 
125     /* Allocate output buffer */
126     *Target = ExAllocatePoolWithTag(PagedPool, sizeof(IO_RESOURCE_DESCRIPTOR), 'btsF');
127     if (!*Target)
128     {
129         return STATUS_INSUFFICIENT_RESOURCES;
130     }
131 
132     /* Zero & set out count to 1 */
133     RtlZeroMemory(*Target, sizeof(IO_RESOURCE_DESCRIPTOR));
134     *TargetCount = 1;
135 
136     /* Translate minimum interrupt vector */
137     (*Target)->u.Interrupt.MinimumVector = HalGetInterruptVector((INTERFACE_TYPE)Context, 0,
138                                                                  Source->u.Interrupt.MinimumVector,
139                                                                  Source->u.Interrupt.MinimumVector,
140                                                                  &Irql, &Affinity);
141 
142     /* Translate maximum interrupt vector */
143     (*Target)->u.Interrupt.MaximumVector = HalGetInterruptVector((INTERFACE_TYPE)Context, 0,
144                                                                  Source->u.Interrupt.MaximumVector,
145                                                                  Source->u.Interrupt.MaximumVector,
146                                                                  &Irql, &Affinity);
147 
148     return STATUS_TRANSLATION_COMPLETE;
149 }
150 
151 /*
152  * @implemented
153  */
154 NTSTATUS
155 NTAPI
156 xHalGetInterruptTranslator(IN INTERFACE_TYPE ParentInterfaceType,
157                            IN ULONG ParentBusNumber,
158                            IN INTERFACE_TYPE BridgeInterfaceType,
159                            IN USHORT Size,
160                            IN USHORT Version,
161                            OUT PTRANSLATOR_INTERFACE Translator,
162                            OUT PULONG BridgeBusNumber)
163 {
164     PAGED_CODE();
165 
166     ASSERT(Version == HAL_IRQ_TRANSLATOR_VERSION);
167     ASSERT(Size >= sizeof(TRANSLATOR_INTERFACE));
168 
169     /* Only (E)ISA interfaces are supported */
170     if (BridgeInterfaceType == Internal || BridgeInterfaceType >= MicroChannel)
171     {
172         return STATUS_NOT_IMPLEMENTED;
173     }
174 
175     /* Fill in output struct */
176     Translator->Size = sizeof(TRANSLATOR_INTERFACE);
177     Translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
178     /* In case caller set interface to undefined, faulty it to ISA */
179     Translator->Context = UlongToPtr((BridgeInterfaceType == InterfaceTypeUndefined) ? Isa : BridgeInterfaceType);
180     Translator->InterfaceReference = FstubTranslatorNull;
181     Translator->InterfaceDereference = FstubTranslatorNull;
182     Translator->TranslateResources = FstubTranslateResource;
183     Translator->TranslateResourceRequirements = FstubTranslateRequirement;
184 
185     return STATUS_SUCCESS;
186 }
187