]>
Commit | Line | Data |
---|---|---|
a5cc178a HW |
1 | /** @file\r |
2 | The SioBusDxe driver is used to create child devices on the ISA bus and\r | |
3 | installs the Super I/O protocols on them.\r | |
4 | \r | |
5 | Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r | |
6 | \r | |
b26f0cf9 | 7 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
a5cc178a HW |
8 | \r |
9 | **/\r | |
10 | \r | |
11 | #include "SioBusDxe.h"\r | |
12 | \r | |
13 | //\r | |
14 | // Super I/O Protocol interfaces\r | |
15 | //\r | |
ac0a286f | 16 | EFI_SIO_PROTOCOL mSioInterface = {\r |
a5cc178a HW |
17 | SioRegisterAccess,\r |
18 | SioGetResources,\r | |
19 | SioSetResources,\r | |
20 | SioPossibleResources,\r | |
21 | SioModify\r | |
22 | };\r | |
23 | \r | |
24 | //\r | |
25 | // COM 1 UART Controller\r | |
26 | //\r | |
27 | GLOBAL_REMOVE_IF_UNREFERENCED\r | |
ac0a286f MK |
28 | SIO_RESOURCES_IO mCom1Resources = {\r |
29 | {\r | |
30 | { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x3F8, 8\r | |
31 | },\r | |
32 | { ACPI_END_TAG_DESCRIPTOR, 0 }\r | |
a5cc178a HW |
33 | };\r |
34 | \r | |
35 | //\r | |
36 | // COM 2 UART Controller\r | |
37 | //\r | |
38 | GLOBAL_REMOVE_IF_UNREFERENCED\r | |
ac0a286f MK |
39 | SIO_RESOURCES_IO mCom2Resources = {\r |
40 | {\r | |
41 | { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x2F8, 8\r | |
42 | },\r | |
43 | { ACPI_END_TAG_DESCRIPTOR, 0 }\r | |
a5cc178a HW |
44 | };\r |
45 | \r | |
46 | //\r | |
47 | // PS/2 Keyboard Controller\r | |
48 | //\r | |
49 | GLOBAL_REMOVE_IF_UNREFERENCED\r | |
ac0a286f MK |
50 | SIO_RESOURCES_IO mPs2KeyboardDeviceResources = {\r |
51 | {\r | |
52 | { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x60, 5\r | |
53 | },\r | |
54 | { ACPI_END_TAG_DESCRIPTOR, 0 }\r | |
a5cc178a HW |
55 | };\r |
56 | \r | |
57 | //\r | |
58 | // Table of SIO Controllers\r | |
59 | //\r | |
60 | GLOBAL_REMOVE_IF_UNREFERENCED\r | |
ac0a286f | 61 | SIO_DEVICE_INFO mDevicesInfo[] = {\r |
a5cc178a HW |
62 | {\r |
63 | EISA_PNP_ID (0x501),\r | |
64 | 0,\r | |
ac0a286f | 65 | { (ACPI_SMALL_RESOURCE_HEADER *)&mCom1Resources }\r |
a5cc178a HW |
66 | }, // COM 1 UART Controller\r |
67 | {\r | |
68 | EISA_PNP_ID (0x501),\r | |
69 | 1,\r | |
ac0a286f | 70 | { (ACPI_SMALL_RESOURCE_HEADER *)&mCom2Resources }\r |
a5cc178a HW |
71 | }, // COM 2 UART Controller\r |
72 | {\r | |
ac0a286f | 73 | EISA_PNP_ID (0x303),\r |
a5cc178a | 74 | 0,\r |
ac0a286f | 75 | { (ACPI_SMALL_RESOURCE_HEADER *)&mPs2KeyboardDeviceResources }\r |
a5cc178a HW |
76 | } // PS/2 Keyboard Controller\r |
77 | };\r | |
78 | \r | |
79 | //\r | |
80 | // ACPI Device Path Node template\r | |
81 | //\r | |
82 | GLOBAL_REMOVE_IF_UNREFERENCED\r | |
ac0a286f | 83 | ACPI_HID_DEVICE_PATH mAcpiDeviceNodeTemplate = {\r |
a5cc178a HW |
84 | { // Header\r |
85 | ACPI_DEVICE_PATH,\r | |
86 | ACPI_DP,\r | |
87 | {\r | |
ac0a286f MK |
88 | (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),\r |
89 | (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r | |
a5cc178a HW |
90 | }\r |
91 | },\r | |
92 | 0x0, // HID\r | |
93 | 0x0 // UID\r | |
94 | };\r | |
95 | \r | |
a5cc178a HW |
96 | /**\r |
97 | Provides a low level access to the registers for the Super I/O.\r | |
98 | \r | |
99 | @param[in] This Indicates a pointer to the calling context.\r | |
100 | @param[in] Write Specifies the type of the register operation.\r | |
101 | If this parameter is TRUE, Value is interpreted\r | |
102 | as an input parameter and the operation is a\r | |
103 | register write. If this parameter is FALSE,\r | |
104 | Value is interpreted as an output parameter and\r | |
105 | the operation is a register read.\r | |
106 | @param[in] ExitCfgMode Exit Configuration Mode Indicator. If this\r | |
107 | parameter is set to TRUE, the Super I/O driver\r | |
108 | will turn off configuration mode of the Super\r | |
109 | I/O prior to returning from this function. If\r | |
110 | this parameter is set to FALSE, the Super I/O\r | |
111 | driver will leave Super I/O in the\r | |
112 | configuration mode. The Super I/O driver must\r | |
113 | track the current state of the Super I/O and\r | |
114 | enable the configuration mode of Super I/O if\r | |
115 | necessary prior to register access.\r | |
116 | @param[in] Register Register number.\r | |
117 | @param[in,out] Value If Write is TRUE, Value is a pointer to the\r | |
118 | buffer containing the byte of data to be\r | |
119 | written to the Super I/O register. If Write is\r | |
120 | FALSE, Value is a pointer to the destination\r | |
121 | buffer for the byte of data to be read from the\r | |
122 | Super I/O register.\r | |
123 | \r | |
124 | @retval EFI_SUCCESS The operation completed successfully.\r | |
125 | @retval EFI_INVALID_PARAMETER The Value is NULL.\r | |
126 | @retval EFI_INVALID_PARAMETER Invalid Register number.\r | |
127 | \r | |
128 | **/\r | |
129 | EFI_STATUS\r | |
130 | EFIAPI\r | |
131 | SioRegisterAccess (\r | |
ac0a286f MK |
132 | IN CONST EFI_SIO_PROTOCOL *This,\r |
133 | IN BOOLEAN Write,\r | |
134 | IN BOOLEAN ExitCfgMode,\r | |
135 | IN UINT8 Register,\r | |
136 | IN OUT UINT8 *Value\r | |
a5cc178a HW |
137 | )\r |
138 | {\r | |
139 | return EFI_SUCCESS;\r | |
140 | }\r | |
141 | \r | |
142 | /**\r | |
143 | Provides an interface to get a list of the current resources consumed by the\r | |
144 | device in the ACPI Resource Descriptor format.\r | |
145 | \r | |
146 | GetResources() returns a list of resources currently consumed by the device.\r | |
147 | The ResourceList is a pointer to the buffer containing resource descriptors\r | |
148 | for the device. The descriptors are in the format of Small or Large ACPI\r | |
149 | resource descriptor as defined by ACPI specification (2.0 & 3.0). The buffer\r | |
150 | of resource descriptors is terminated with the 'End tag' resource descriptor.\r | |
151 | \r | |
152 | @param[in] This Indicates a pointer to the calling context.\r | |
153 | @param[out] ResourceList A pointer to an ACPI resource descriptor list\r | |
154 | that defines the current resources used by the\r | |
155 | device.\r | |
156 | \r | |
157 | @retval EFI_SUCCESS The operation completed successfully.\r | |
158 | @retval EFI_INVALID_PARAMETER ResourceList is NULL.\r | |
159 | \r | |
160 | **/\r | |
161 | EFI_STATUS\r | |
162 | EFIAPI\r | |
163 | SioGetResources (\r | |
ac0a286f MK |
164 | IN CONST EFI_SIO_PROTOCOL *This,\r |
165 | OUT ACPI_RESOURCE_HEADER_PTR *ResourceList\r | |
a5cc178a HW |
166 | )\r |
167 | {\r | |
ac0a286f | 168 | SIO_DEV *SioDevice;\r |
a5cc178a HW |
169 | \r |
170 | if (ResourceList == NULL) {\r | |
171 | return EFI_INVALID_PARAMETER;\r | |
172 | }\r | |
173 | \r | |
174 | SioDevice = SIO_DEV_FROM_SIO (This);\r | |
175 | if (SioDevice->DeviceIndex < ARRAY_SIZE (mDevicesInfo)) {\r | |
176 | *ResourceList = mDevicesInfo[SioDevice->DeviceIndex].Resources;\r | |
177 | }\r | |
178 | \r | |
179 | return EFI_SUCCESS;\r | |
180 | }\r | |
181 | \r | |
182 | /**\r | |
183 | Sets the resources for the device.\r | |
184 | \r | |
185 | @param[in] This Indicates a pointer to the calling context.\r | |
186 | @param[in] ResourceList Pointer to the ACPI resource descriptor list.\r | |
187 | \r | |
188 | @retval EFI_SUCCESS The operation completed successfully.\r | |
189 | @retval EFI_INVALID_PARAMETER ResourceList is invalid.\r | |
190 | @retval EFI_ACCESS_DENIED Some of the resources in ResourceList are in\r | |
191 | use.\r | |
192 | \r | |
193 | **/\r | |
194 | EFI_STATUS\r | |
195 | EFIAPI\r | |
196 | SioSetResources (\r | |
ac0a286f MK |
197 | IN CONST EFI_SIO_PROTOCOL *This,\r |
198 | IN ACPI_RESOURCE_HEADER_PTR ResourceList\r | |
a5cc178a HW |
199 | )\r |
200 | {\r | |
201 | return EFI_SUCCESS;\r | |
202 | }\r | |
203 | \r | |
204 | /**\r | |
205 | Provides a collection of resource descriptor lists. Each resource descriptor\r | |
206 | list in the collection defines a combination of resources that can\r | |
207 | potentially be used by the device.\r | |
208 | \r | |
209 | @param[in] This Indicates a pointer to the calling context.\r | |
210 | @param[out] ResourceCollection Collection of the resource descriptor\r | |
211 | lists.\r | |
212 | \r | |
213 | @retval EFI_SUCCESS The operation completed successfully.\r | |
214 | @retval EFI_INVALID_PARAMETER ResourceCollection is NULL.\r | |
215 | \r | |
216 | **/\r | |
217 | EFI_STATUS\r | |
218 | EFIAPI\r | |
219 | SioPossibleResources (\r | |
ac0a286f MK |
220 | IN CONST EFI_SIO_PROTOCOL *This,\r |
221 | OUT ACPI_RESOURCE_HEADER_PTR *ResourceCollection\r | |
a5cc178a HW |
222 | )\r |
223 | {\r | |
224 | return EFI_SUCCESS;\r | |
225 | }\r | |
226 | \r | |
227 | /**\r | |
228 | Provides an interface for a table based programming of the Super I/O\r | |
229 | registers.\r | |
230 | \r | |
231 | The Modify() function provides an interface for table based programming of\r | |
232 | the Super I/O registers. This function can be used to perform programming of\r | |
233 | multiple Super I/O registers with a single function call. For each table\r | |
234 | entry, the Register is read, its content is bitwise ANDed with AndMask, and\r | |
235 | then ORed with OrMask before being written back to the Register. The Super\r | |
236 | I/O driver must track the current state of the Super I/O and enable the\r | |
237 | configuration mode of Super I/O if necessary prior to table processing. Once\r | |
238 | the table is processed, the Super I/O device has to be returned to the\r | |
239 | original state.\r | |
240 | \r | |
241 | @param[in] This Indicates a pointer to the calling context.\r | |
242 | @param[in] Command A pointer to an array of NumberOfCommands\r | |
243 | EFI_SIO_REGISTER_MODIFY structures. Each\r | |
244 | structure specifies a single Super I/O register\r | |
245 | modify operation.\r | |
246 | @param[in] NumberOfCommands Number of elements in the Command array.\r | |
247 | \r | |
248 | @retval EFI_SUCCESS The operation completed successfully.\r | |
249 | @retval EFI_INVALID_PARAMETER Command is NULL.\r | |
250 | \r | |
251 | **/\r | |
252 | EFI_STATUS\r | |
253 | EFIAPI\r | |
254 | SioModify (\r | |
ac0a286f MK |
255 | IN CONST EFI_SIO_PROTOCOL *This,\r |
256 | IN CONST EFI_SIO_REGISTER_MODIFY *Command,\r | |
257 | IN UINTN NumberOfCommands\r | |
a5cc178a HW |
258 | )\r |
259 | {\r | |
260 | return EFI_SUCCESS;\r | |
261 | }\r | |
262 | \r | |
263 | /**\r | |
264 | Create the child device with a given device index.\r | |
265 | \r | |
266 | @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance.\r | |
267 | @param[in] Controller The handle of ISA bus controller.\r | |
268 | @param[in] PciIo The pointer to the PCI protocol.\r | |
269 | @param[in] ParentDevicePath Device path of the ISA bus controller.\r | |
270 | @param[in] DeviceIndex Index of the device supported by this driver.\r | |
271 | \r | |
272 | @retval EFI_SUCCESS The child device has been created successfully.\r | |
60835c96 | 273 | @retval Others Error occurred during the child device creation.\r |
a5cc178a HW |
274 | \r |
275 | **/\r | |
276 | EFI_STATUS\r | |
277 | SioCreateChildDevice (\r | |
278 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r | |
279 | IN EFI_HANDLE Controller,\r | |
280 | IN EFI_PCI_IO_PROTOCOL *PciIo,\r | |
281 | IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r | |
282 | IN UINT32 DeviceIndex\r | |
283 | )\r | |
284 | {\r | |
ac0a286f MK |
285 | EFI_STATUS Status;\r |
286 | SIO_DEV *SioDevice;\r | |
a5cc178a HW |
287 | \r |
288 | //\r | |
289 | // Initialize the SIO_DEV structure\r | |
290 | //\r | |
291 | SioDevice = AllocateZeroPool (sizeof (SIO_DEV));\r | |
292 | if (SioDevice == NULL) {\r | |
293 | return EFI_OUT_OF_RESOURCES;\r | |
294 | }\r | |
295 | \r | |
ac0a286f MK |
296 | SioDevice->Signature = SIO_DEV_SIGNATURE;\r |
297 | SioDevice->Handle = NULL;\r | |
298 | SioDevice->PciIo = PciIo;\r | |
a5cc178a HW |
299 | \r |
300 | //\r | |
301 | // Construct the child device path\r | |
302 | //\r | |
303 | mAcpiDeviceNodeTemplate.HID = mDevicesInfo[DeviceIndex].Hid;\r | |
304 | mAcpiDeviceNodeTemplate.UID = mDevicesInfo[DeviceIndex].Uid;\r | |
ac0a286f MK |
305 | SioDevice->DevicePath = AppendDevicePathNode (\r |
306 | ParentDevicePath,\r | |
307 | (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiDeviceNodeTemplate\r | |
308 | );\r | |
a5cc178a HW |
309 | if (SioDevice->DevicePath == NULL) {\r |
310 | Status = EFI_OUT_OF_RESOURCES;\r | |
311 | goto Done;\r | |
312 | }\r | |
313 | \r | |
314 | CopyMem (&SioDevice->Sio, &mSioInterface, sizeof (EFI_SIO_PROTOCOL));\r | |
315 | SioDevice->DeviceIndex = DeviceIndex;\r | |
316 | \r | |
317 | //\r | |
318 | // Create a child handle and install Device Path and Super I/O protocols\r | |
319 | //\r | |
320 | Status = gBS->InstallMultipleProtocolInterfaces (\r | |
321 | &SioDevice->Handle,\r | |
322 | &gEfiDevicePathProtocolGuid,\r | |
323 | SioDevice->DevicePath,\r | |
324 | &gEfiSioProtocolGuid,\r | |
325 | &SioDevice->Sio,\r | |
326 | NULL\r | |
327 | );\r | |
328 | if (EFI_ERROR (Status)) {\r | |
329 | goto Done;\r | |
330 | }\r | |
331 | \r | |
332 | Status = gBS->OpenProtocol (\r | |
333 | Controller,\r | |
334 | &gEfiPciIoProtocolGuid,\r | |
ac0a286f | 335 | (VOID **)&PciIo,\r |
a5cc178a HW |
336 | This->DriverBindingHandle,\r |
337 | SioDevice->Handle,\r | |
338 | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r | |
339 | );\r | |
340 | if (EFI_ERROR (Status)) {\r | |
341 | gBS->UninstallMultipleProtocolInterfaces (\r | |
342 | SioDevice->Handle,\r | |
343 | &gEfiDevicePathProtocolGuid,\r | |
344 | SioDevice->DevicePath,\r | |
345 | &gEfiSioProtocolGuid,\r | |
346 | &SioDevice->Sio,\r | |
347 | NULL\r | |
348 | );\r | |
349 | }\r | |
350 | \r | |
351 | Done:\r | |
352 | if (EFI_ERROR (Status)) {\r | |
353 | if (SioDevice->DevicePath != NULL) {\r | |
354 | FreePool (SioDevice->DevicePath);\r | |
355 | }\r | |
356 | \r | |
357 | FreePool (SioDevice);\r | |
358 | }\r | |
359 | \r | |
360 | return Status;\r | |
361 | }\r | |
362 | \r | |
363 | /**\r | |
364 | Create all the ISA child devices on the ISA bus controller (PCI to ISA\r | |
365 | bridge).\r | |
366 | \r | |
367 | @param[in] This The EFI_DRIVER_BINDING_PROTOCOL instance.\r | |
368 | @param[in] Controller The handle of ISA bus controller.\r | |
369 | @param[in] PciIo The pointer to the PCI protocol.\r | |
370 | @param[in] ParentDevicePath Device path of the ISA bus controller.\r | |
371 | \r | |
372 | @retval The number of child device that is successfully created.\r | |
373 | \r | |
374 | **/\r | |
375 | UINT32\r | |
376 | SioCreateAllChildDevices (\r | |
377 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r | |
378 | IN EFI_HANDLE Controller,\r | |
379 | IN EFI_PCI_IO_PROTOCOL *PciIo,\r | |
380 | IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r | |
381 | )\r | |
382 | {\r | |
ac0a286f MK |
383 | UINT32 Index;\r |
384 | UINT32 ChildDeviceNumber;\r | |
385 | EFI_STATUS Status;\r | |
a5cc178a HW |
386 | \r |
387 | ChildDeviceNumber = 0;\r | |
388 | \r | |
389 | for (Index = 0; Index < ARRAY_SIZE (mDevicesInfo); Index++) {\r | |
390 | Status = SioCreateChildDevice (\r | |
391 | This,\r | |
392 | Controller,\r | |
393 | PciIo,\r | |
394 | ParentDevicePath,\r | |
395 | Index\r | |
396 | );\r | |
397 | if (!EFI_ERROR (Status)) {\r | |
398 | ChildDeviceNumber++;\r | |
399 | }\r | |
400 | }\r | |
401 | \r | |
402 | return ChildDeviceNumber;\r | |
403 | }\r |