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