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
FstubTranslatorNull(PVOID Context)22 FstubTranslatorNull(PVOID Context)
23 {
24 PAGED_CODE();
25
26 /* Do nothing */
27 return;
28 }
29
30 /*
31 * @implemented
32 */
33 NTSTATUS
34 NTAPI
FstubTranslateResource(IN OUT PVOID Context OPTIONAL,IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,IN RESOURCE_TRANSLATION_DIRECTION Direction,IN ULONG AlternativesCount OPTIONAL,IN IO_RESOURCE_DESCRIPTOR Alternatives[],IN PDEVICE_OBJECT PhysicalDeviceObject,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target)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
FstubTranslateRequirement(IN OUT PVOID Context OPTIONAL,IN PIO_RESOURCE_DESCRIPTOR Source,IN PDEVICE_OBJECT PhysicalDeviceObject,OUT PULONG TargetCount,OUT PIO_RESOURCE_DESCRIPTOR * Target)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
xHalGetInterruptTranslator(IN INTERFACE_TYPE ParentInterfaceType,IN ULONG ParentBusNumber,IN INTERFACE_TYPE BridgeInterfaceType,IN USHORT Size,IN USHORT Version,OUT PTRANSLATOR_INTERFACE Translator,OUT PULONG BridgeBusNumber)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