xref: /reactos/drivers/bus/pcix/hookhal.c (revision 1734f297)
1 /*
2  * PROJECT:         ReactOS PCI Bus Driver
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            drivers/bus/pci/hookhal.c
5  * PURPOSE:         HAL Bus Handler Dispatch Routine Support
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <pci.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* GLOBALS ********************************************************************/
17 
18 pHalTranslateBusAddress PcipSavedTranslateBusAddress;
19 pHalAssignSlotResources PcipSavedAssignSlotResources;
20 
21 /* FUNCTIONS ******************************************************************/
22 
23 BOOLEAN
24 NTAPI
25 PciTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
26                        IN ULONG BusNumber,
27                        IN PHYSICAL_ADDRESS BusAddress,
28                        OUT PULONG AddressSpace,
29                        OUT PPHYSICAL_ADDRESS TranslatedAddress)
30 {
31     UNREFERENCED_PARAMETER(InterfaceType);
32     UNREFERENCED_PARAMETER(BusNumber);
33     UNREFERENCED_PARAMETER(AddressSpace);
34 
35     /* FIXME: Broken translation */
36     UNIMPLEMENTED;
37     TranslatedAddress->QuadPart = BusAddress.QuadPart;
38     return TRUE;
39 }
40 
41 PPCI_PDO_EXTENSION
42 NTAPI
43 PciFindPdoByLocation(IN ULONG BusNumber,
44                      IN ULONG SlotNumber)
45 {
46     PPCI_FDO_EXTENSION DeviceExtension;
47     PPCI_PDO_EXTENSION PdoExtension;
48     PCI_SLOT_NUMBER PciSlot;
49     PciSlot.u.AsULONG = SlotNumber;
50 
51     /* Acquire the global lock */
52     KeEnterCriticalRegion();
53     KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL);
54 
55     /* Now search for the extension */
56     DeviceExtension = (PPCI_FDO_EXTENSION)PciFdoExtensionListHead.Next;
57     while (DeviceExtension)
58     {
59         /* If we found it, break out */
60         if (DeviceExtension->BaseBus == BusNumber) break;
61 
62         /* Move to the next device */
63         DeviceExtension = (PPCI_FDO_EXTENSION)DeviceExtension->List.Next;
64     }
65 
66     /* Release the global lock */
67     KeSetEvent(&PciGlobalLock, IO_NO_INCREMENT, FALSE);
68     KeLeaveCriticalRegion();
69 
70     /* Check if the device extension for the bus was found */
71     if (!DeviceExtension)
72     {
73         /* It wasn't, bail out */
74         DPRINT1("Pci: Could not find PCI bus FDO. Bus Number = 0x%x\n", BusNumber);
75         return NULL;
76     }
77 
78     /* Acquire this device's lock */
79     KeEnterCriticalRegion();
80     KeWaitForSingleObject(&DeviceExtension->ChildListLock,
81                           Executive,
82                           KernelMode,
83                           FALSE,
84                           NULL);
85 
86     /* Loop every child PDO */
87     for (PdoExtension = DeviceExtension->ChildPdoList;
88          PdoExtension;
89          PdoExtension = PdoExtension->Next)
90     {
91         /* Check if the function number and header data matches */
92         if ((PdoExtension->Slot.u.bits.FunctionNumber == PciSlot.u.bits.FunctionNumber) &&
93             (PdoExtension->Slot.u.bits.DeviceNumber == PciSlot.u.bits.DeviceNumber))
94         {
95             /* This is considered to be the same PDO */
96             ASSERT(PdoExtension->Slot.u.AsULONG == PciSlot.u.AsULONG);
97             break;
98         }
99     }
100 
101     /* Release this device's lock */
102     KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE);
103     KeLeaveCriticalRegion();
104 
105     /* Check if we found something */
106     if (!PdoExtension)
107     {
108         /* Let the debugger know */
109         DPRINT1("Pci: Could not find PDO for device @ %x.%x.%x\n",
110                 BusNumber,
111                 PciSlot.u.bits.DeviceNumber,
112                 PciSlot.u.bits.FunctionNumber);
113     }
114 
115     /* If the search found something, this is non-NULL, otherwise it's NULL */
116     return PdoExtension;
117 }
118 
119 NTSTATUS
120 NTAPI
121 PciAssignSlotResources(IN PUNICODE_STRING RegistryPath,
122                        IN PUNICODE_STRING DriverClassName OPTIONAL,
123                        IN PDRIVER_OBJECT DriverObject,
124                        IN PDEVICE_OBJECT DeviceObject,
125                        IN INTERFACE_TYPE BusType,
126                        IN ULONG BusNumber,
127                        IN ULONG SlotNumber,
128                        IN OUT PCM_RESOURCE_LIST *AllocatedResources)
129 {
130     PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList = NULL;
131     PCM_RESOURCE_LIST Resources = NULL;
132     PCI_COMMON_HEADER PciData;
133     PPCI_PDO_EXTENSION PdoExtension;
134     NTSTATUS Status;
135     PDEVICE_OBJECT ExistingDeviceObject;
136     PAGED_CODE();
137     ASSERT(PcipSavedAssignSlotResources);
138     ASSERT(BusType == PCIBus);
139 
140     /* Assume no resources */
141     *AllocatedResources = NULL;
142 
143     /* Find the PDO for this slot and make sure it exists and is started */
144     PdoExtension = PciFindPdoByLocation(BusNumber, SlotNumber);
145     if (!PdoExtension) return STATUS_DEVICE_DOES_NOT_EXIST;
146     if (PdoExtension->DeviceState == PciNotStarted) return STATUS_INVALID_OWNER;
147 
148     /* Acquire the global lock while we attempt to assign resources */
149     KeEnterCriticalRegion();
150     KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL);
151     do
152     {
153         /* Make sure we're not on the PDO for some reason */
154         ASSERT(DeviceObject != PdoExtension->PhysicalDeviceObject);
155 
156         /* Read the PCI header and cache the routing information */
157         PciReadDeviceConfig(PdoExtension, &PciData, 0, PCI_COMMON_HDR_LENGTH);
158         Status = PciCacheLegacyDeviceRouting(DeviceObject,
159                                              BusNumber,
160                                              SlotNumber,
161                                              PciData.u.type0.InterruptLine,
162                                              PciData.u.type0.InterruptPin,
163                                              PciData.BaseClass,
164                                              PciData.SubClass,
165                                              PdoExtension->ParentFdoExtension->
166                                              PhysicalDeviceObject,
167                                              PdoExtension,
168                                              &ExistingDeviceObject);
169         if (NT_SUCCESS(Status))
170         {
171             /* Manually build the requirements for this device, and mark it legacy */
172             Status = PciBuildRequirementsList(PdoExtension,
173                                               &PciData,
174                                               &RequirementsList);
175             PdoExtension->LegacyDriver = TRUE;
176             if (NT_SUCCESS(Status))
177             {
178                 /* Now call the legacy Pnp function to actually assign resources */
179                 Status = IoAssignResources(RegistryPath,
180                                            DriverClassName,
181                                            DriverObject,
182                                            DeviceObject,
183                                            RequirementsList,
184                                            &Resources);
185                 if (NT_SUCCESS(Status))
186                 {
187                     /* Resources are ready, so enable all decodes */
188                     PdoExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE |
189                                                      PCI_ENABLE_MEMORY_SPACE |
190                                                      PCI_ENABLE_BUS_MASTER);
191 
192                     /* Compute new resource settings based on what PnP assigned */
193                     PciComputeNewCurrentSettings(PdoExtension, Resources);
194 
195                     /* Set these new resources on the device */
196                     Status = PciSetResources(PdoExtension, TRUE, TRUE);
197                     if (NT_SUCCESS(Status))
198                     {
199                         /* Some work needs to happen here to handle this */
200                         ASSERT(Resources->Count == 1);
201                         //ASSERT(PartialList->Count > 0);
202 
203                         UNIMPLEMENTED;
204 
205                         /* Return the allocated resources, and success */
206                         *AllocatedResources = Resources;
207                         Resources = NULL;
208                         Status = STATUS_SUCCESS;
209                     }
210                 }
211                 else
212                 {
213                     /* If assignment failed, no resources should exist */
214                     ASSERT(Resources == NULL);
215                 }
216 
217                 /* If assignment succeed, then we are done */
218                 if (NT_SUCCESS(Status)) break;
219             }
220 
221             /* Otherwise, cache the new routing */
222             PciCacheLegacyDeviceRouting(ExistingDeviceObject,
223                                         BusNumber,
224                                         SlotNumber,
225                                         PciData.u.type0.InterruptLine,
226                                         PciData.u.type0.InterruptPin,
227                                         PciData.BaseClass,
228                                         PciData.SubClass,
229                                         PdoExtension->ParentFdoExtension->
230                                         PhysicalDeviceObject,
231                                         PdoExtension,
232                                         NULL);
233         }
234     } while (0);
235 
236     /* Release the lock */
237     KeSetEvent(&PciGlobalLock, 0, 0);
238     KeLeaveCriticalRegion();
239 
240     /* Free any temporary resource data and return the status */
241     if (RequirementsList) ExFreePoolWithTag(RequirementsList, 0);
242     if (Resources) ExFreePoolWithTag(Resources, 0);
243     return Status;
244 }
245 
246 VOID
247 NTAPI
248 PciHookHal(VOID)
249 {
250     /* Save the old HAL routines */
251     ASSERT(PcipSavedAssignSlotResources == NULL);
252     ASSERT(PcipSavedTranslateBusAddress == NULL);
253     PcipSavedAssignSlotResources = HalPciAssignSlotResources;
254     PcipSavedTranslateBusAddress = HalPciTranslateBusAddress;
255 
256     /* Take over the HAL's Bus Handler functions */
257 //    HalPciAssignSlotResources = PciAssignSlotResources;
258     HalPciTranslateBusAddress = PciTranslateBusAddress;
259 }
260 
261 /* EOF */
262