]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8668 6f19259b...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaSerialDxe / Serial.c
CommitLineData
637ff819 1/**@file\r
bcd70414 2 Serial driver for standard UARTS on an ISA bus.\r
637ff819 3\r
366565e0 4 Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
637ff819 12\r
13**/\r
14\r
15#include "Serial.h"\r
16\r
17//\r
18// ISA Serial Driver Global Variables\r
19//\r
20EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {\r
21 SerialControllerDriverSupported,\r
22 SerialControllerDriverStart,\r
23 SerialControllerDriverStop,\r
24 0xa,\r
25 NULL,\r
26 NULL\r
27};\r
28\r
29\r
6b88ceec
A
30SERIAL_DEV gSerialDevTempate = {\r
31 SERIAL_DEV_SIGNATURE,\r
32 NULL,\r
33 { // SerialIo\r
34 SERIAL_IO_INTERFACE_REVISION,\r
35 IsaSerialReset,\r
36 IsaSerialSetAttributes,\r
37 IsaSerialSetControl,\r
38 IsaSerialGetControl,\r
39 IsaSerialWrite,\r
40 IsaSerialRead,\r
41 NULL\r
42 },\r
43 { // SerialMode\r
44 SERIAL_PORT_DEFAULT_CONTROL_MASK,\r
45 SERIAL_PORT_DEFAULT_TIMEOUT,\r
46 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
47 SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,\r
48 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
49 FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
50 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
51 },\r
52 NULL,\r
53 NULL,\r
54 { // UartDevicePath\r
55 {\r
56 MESSAGING_DEVICE_PATH,\r
57 MSG_UART_DP,\r
a02c7e15 58 {\r
59 (UINT8) (sizeof (UART_DEVICE_PATH)),\r
60 (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)\r
61 }\r
6b88ceec
A
62 },\r
63 0,\r
64 FixedPcdGet64 (PcdUartDefaultBaudRate), \r
65 FixedPcdGet8 (PcdUartDefaultDataBits),\r
66 FixedPcdGet8 (PcdUartDefaultParity),\r
67 FixedPcdGet8 (PcdUartDefaultStopBits)\r
68 },\r
69 NULL,\r
70 0, //BaseAddress\r
71 {\r
72 0,\r
73 0,\r
74 SERIAL_MAX_BUFFER_SIZE,\r
75 { 0 }\r
76 },\r
77 {\r
78 0,\r
79 0,\r
80 SERIAL_MAX_BUFFER_SIZE,\r
81 { 0 }\r
82 },\r
83 FALSE,\r
84 FALSE,\r
85 UART16550A,\r
86 NULL\r
87};\r
88\r
637ff819 89/**\r
90 The user Entry Point for module IsaSerial. The user code starts with this function.\r
91\r
92 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
93 @param[in] SystemTable A pointer to the EFI System Table.\r
94 \r
95 @retval EFI_SUCCESS The entry point is executed successfully.\r
96 @retval other Some error occurs when executing this entry point.\r
97\r
98**/\r
99EFI_STATUS\r
100EFIAPI\r
6b88ceec 101InitializeIsaSerial (\r
637ff819 102 IN EFI_HANDLE ImageHandle,\r
103 IN EFI_SYSTEM_TABLE *SystemTable\r
104 )\r
105{\r
106 EFI_STATUS Status;\r
107\r
108 //\r
109 // Install driver model protocol(s).\r
110 //\r
f3d08ccf 111 Status = EfiLibInstallDriverBindingComponentName2 (\r
637ff819 112 ImageHandle,\r
113 SystemTable,\r
114 &gSerialControllerDriver,\r
115 ImageHandle,\r
116 &gIsaSerialComponentName,\r
f3d08ccf 117 &gIsaSerialComponentName2\r
637ff819 118 );\r
119 ASSERT_EFI_ERROR (Status);\r
120\r
121\r
122 return Status;\r
123}\r
124\r
bcd70414 125/**\r
126 Check to see if this driver supports the given controller\r
127\r
128 @param This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
129 @param Controller - The handle of the controller to test.\r
130 @param RemainingDevicePath - A pointer to the remaining portion of a device path.\r
637ff819 131\r
bcd70414 132 @return EFI_SUCCESS - This driver can support the given controller\r
133\r
134**/\r
637ff819 135EFI_STATUS\r
136EFIAPI\r
137SerialControllerDriverSupported (\r
138 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
139 IN EFI_HANDLE Controller,\r
140 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
141 )\r
637ff819 142\r
637ff819 143{\r
144 EFI_STATUS Status;\r
145 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
146 EFI_ISA_IO_PROTOCOL *IsaIo;\r
147 UART_DEVICE_PATH UartNode;\r
148\r
149 //\r
150 // Ignore the RemainingDevicePath\r
151 //\r
152 //\r
153 // Open the IO Abstraction(s) needed to perform the supported test\r
154 //\r
155 Status = gBS->OpenProtocol (\r
156 Controller,\r
157 &gEfiDevicePathProtocolGuid,\r
158 (VOID **) &ParentDevicePath,\r
159 This->DriverBindingHandle,\r
160 Controller,\r
161 EFI_OPEN_PROTOCOL_BY_DRIVER\r
162 );\r
163 if (Status == EFI_ALREADY_STARTED) {\r
164 return EFI_SUCCESS;\r
165 }\r
166\r
167 if (EFI_ERROR (Status)) {\r
168 return Status;\r
169 }\r
170\r
171 gBS->CloseProtocol (\r
172 Controller,\r
173 &gEfiDevicePathProtocolGuid,\r
174 This->DriverBindingHandle,\r
175 Controller\r
176 );\r
177\r
178 Status = gBS->OpenProtocol (\r
179 Controller,\r
180 &gEfiIsaIoProtocolGuid,\r
181 (VOID **) &IsaIo,\r
182 This->DriverBindingHandle,\r
183 Controller,\r
184 EFI_OPEN_PROTOCOL_BY_DRIVER\r
185 );\r
186\r
187 if (Status == EFI_ALREADY_STARTED) {\r
188 return EFI_SUCCESS;\r
189 }\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 return Status;\r
193 }\r
194 //\r
195 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that\r
196 // can be managed by this driver.\r
197 //\r
198 Status = EFI_SUCCESS;\r
199 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) {\r
200 Status = EFI_UNSUPPORTED;\r
201 goto Error;\r
202 }\r
203 //\r
204 // Make sure RemainingDevicePath is valid\r
205 //\r
206 if (RemainingDevicePath != NULL) {\r
207 Status = EFI_UNSUPPORTED;\r
208 CopyMem (\r
209 &UartNode,\r
210 (UART_DEVICE_PATH *) RemainingDevicePath,\r
211 sizeof (UART_DEVICE_PATH)\r
212 );\r
213 if (UartNode.Header.Type != MESSAGING_DEVICE_PATH ||\r
214 UartNode.Header.SubType != MSG_UART_DP ||\r
215 sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode)\r
216 ) {\r
217 goto Error;\r
218 }\r
219\r
220 if (UartNode.BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {\r
221 goto Error;\r
222 }\r
223\r
224 if (UartNode.Parity < NoParity || UartNode.Parity > SpaceParity) {\r
225 goto Error;\r
226 }\r
227\r
228 if (UartNode.DataBits < 5 || UartNode.DataBits > 8) {\r
229 goto Error;\r
230 }\r
231\r
232 if (UartNode.StopBits < OneStopBit || UartNode.StopBits > TwoStopBits) {\r
233 goto Error;\r
234 }\r
235\r
236 if ((UartNode.DataBits == 5) && (UartNode.StopBits == TwoStopBits)) {\r
237 goto Error;\r
238 }\r
239\r
240 if ((UartNode.DataBits >= 6) && (UartNode.DataBits <= 8) && (UartNode.StopBits == OneFiveStopBits)) {\r
241 goto Error;\r
242 }\r
243\r
244 Status = EFI_SUCCESS;\r
245 }\r
246\r
247Error:\r
248 //\r
249 // Close the I/O Abstraction(s) used to perform the supported test\r
250 //\r
251 gBS->CloseProtocol (\r
252 Controller,\r
253 &gEfiIsaIoProtocolGuid,\r
254 This->DriverBindingHandle,\r
255 Controller\r
256 );\r
257\r
258 return Status;\r
259}\r
260\r
bcd70414 261/**\r
262 Start to management the controller passed in\r
263\r
264 @param This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
265 @param Controller - The handle of the controller to test.\r
266 @param RemainingDevicePath - A pointer to the remaining portion of a device path.\r
267\r
268 @return EFI_SUCCESS - Driver is started successfully\r
269\r
270**/\r
637ff819 271EFI_STATUS\r
272EFIAPI\r
273SerialControllerDriverStart (\r
274 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
275 IN EFI_HANDLE Controller,\r
276 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
277 )\r
637ff819 278\r
637ff819 279{\r
280 EFI_STATUS Status;\r
281 EFI_ISA_IO_PROTOCOL *IsaIo;\r
282 SERIAL_DEV *SerialDevice;\r
283 UINTN Index;\r
284 UART_DEVICE_PATH Node;\r
285 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
286 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
287 UINTN EntryCount;\r
288 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
289\r
290 SerialDevice = NULL;\r
291 //\r
292 // Get the Parent Device Path\r
293 //\r
294 Status = gBS->OpenProtocol (\r
295 Controller,\r
296 &gEfiDevicePathProtocolGuid,\r
297 (VOID **) &ParentDevicePath,\r
298 This->DriverBindingHandle,\r
299 Controller,\r
300 EFI_OPEN_PROTOCOL_BY_DRIVER\r
301 );\r
302 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
303 return Status;\r
304 }\r
305 //\r
306 // Report status code enable the serial\r
307 //\r
308 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
309 EFI_PROGRESS_CODE,\r
310 EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,\r
311 ParentDevicePath\r
312 );\r
313\r
314 //\r
315 // Grab the IO abstraction we need to get any work done\r
316 //\r
317 Status = gBS->OpenProtocol (\r
318 Controller,\r
319 &gEfiIsaIoProtocolGuid,\r
320 (VOID **) &IsaIo,\r
321 This->DriverBindingHandle,\r
322 Controller,\r
323 EFI_OPEN_PROTOCOL_BY_DRIVER\r
324 );\r
325 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
326 goto Error;\r
327 }\r
328\r
329 if (Status == EFI_ALREADY_STARTED) {\r
330\r
331 if (RemainingDevicePath == NULL) {\r
332 return EFI_SUCCESS;\r
333 }\r
334 //\r
335 // Make sure a child handle does not already exist. This driver can only\r
336 // produce one child per serial port.\r
337 //\r
338 Status = gBS->OpenProtocolInformation (\r
339 Controller,\r
340 &gEfiIsaIoProtocolGuid,\r
341 &OpenInfoBuffer,\r
342 &EntryCount\r
343 );\r
344 if (EFI_ERROR (Status)) {\r
345 return Status;\r
346 }\r
347\r
348 Status = EFI_ALREADY_STARTED;\r
349 for (Index = 0; Index < EntryCount; Index++) {\r
350 if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
351 Status = gBS->OpenProtocol (\r
352 OpenInfoBuffer[Index].ControllerHandle,\r
353 &gEfiSerialIoProtocolGuid,\r
354 (VOID **) &SerialIo,\r
355 This->DriverBindingHandle,\r
356 Controller,\r
357 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
358 );\r
359 if (!EFI_ERROR (Status)) {\r
360 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
361 Status = SerialIo->SetAttributes (\r
362 SerialIo,\r
363 Node.BaudRate,\r
364 SerialIo->Mode->ReceiveFifoDepth,\r
365 SerialIo->Mode->Timeout,\r
366 (EFI_PARITY_TYPE) Node.Parity,\r
367 Node.DataBits,\r
368 (EFI_STOP_BITS_TYPE) Node.StopBits\r
369 );\r
370 }\r
371 break;\r
372 }\r
373 }\r
374\r
375 gBS->FreePool (OpenInfoBuffer);\r
376 return Status;\r
377 }\r
378 //\r
379 // Initialize the serial device instance\r
380 //\r
6b88ceec 381 SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate);\r
637ff819 382 if (SerialDevice == NULL) {\r
383 Status = EFI_OUT_OF_RESOURCES;\r
384 goto Error;\r
385 }\r
386\r
6b88ceec 387 SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);\r
637ff819 388 SerialDevice->IsaIo = IsaIo;\r
389 SerialDevice->ParentDevicePath = ParentDevicePath;\r
637ff819 390\r
391 ADD_SERIAL_NAME (SerialDevice, IsaIo);\r
392\r
393 for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {\r
394 if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {\r
395 SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange;\r
396 }\r
397 }\r
398 //\r
399 // Report status code the serial present\r
400 //\r
401 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
402 EFI_PROGRESS_CODE,\r
403 EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,\r
404 ParentDevicePath\r
405 );\r
406\r
407 if (!IsaSerialPortPresent (SerialDevice)) {\r
408 Status = EFI_DEVICE_ERROR;\r
409 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
410 EFI_ERROR_CODE,\r
411 EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT,\r
412 ParentDevicePath\r
413 );\r
414 goto Error;\r
415 }\r
416\r
637ff819 417 if (RemainingDevicePath != NULL) {\r
418 //\r
419 // Match the configuration of the RemainingDevicePath. IsHandleSupported()\r
420 // already checked to make sure the RemainingDevicePath contains settings\r
421 // that we can support.\r
422 //\r
423 CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
424 } else {\r
425 //\r
6b88ceec
A
426 // Use the values from the gSerialDevTempate as no remaining device path was\r
427 // passed in.\r
637ff819 428 //\r
637ff819 429 }\r
430 //\r
431 // Build the device path by appending the UART node to the ParentDevicePath\r
432 // from the WinNtIo handle. The Uart setings are zero here, since\r
433 // SetAttribute() will update them to match the current setings.\r
434 //\r
435 SerialDevice->DevicePath = AppendDevicePathNode (\r
436 ParentDevicePath,\r
6b88ceec 437 (EFI_DEVICE_PATH_PROTOCOL *)&SerialDevice->UartDevicePath\r
637ff819 438 );\r
637ff819 439 if (SerialDevice->DevicePath == NULL) {\r
440 Status = EFI_DEVICE_ERROR;\r
441 goto Error;\r
442 }\r
6b88ceec 443\r
637ff819 444 //\r
445 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.\r
446 //\r
637ff819 447 SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;\r
637ff819 448 SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;\r
449 SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;\r
450 SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;\r
451\r
452 //\r
453 // Issue a reset to initialize the COM port\r
454 //\r
455 Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);\r
456 if (EFI_ERROR (Status)) {\r
457 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
458 EFI_ERROR_CODE,\r
459 EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
460 ParentDevicePath\r
461 );\r
462 goto Error;\r
463 }\r
464 //\r
465 // Install protocol interfaces for the serial device.\r
466 //\r
467 Status = gBS->InstallMultipleProtocolInterfaces (\r
468 &SerialDevice->Handle,\r
469 &gEfiDevicePathProtocolGuid,\r
470 SerialDevice->DevicePath,\r
471 &gEfiSerialIoProtocolGuid,\r
472 &SerialDevice->SerialIo,\r
473 NULL\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 goto Error;\r
477 }\r
478 //\r
479 // Open For Child Device\r
480 //\r
481 Status = gBS->OpenProtocol (\r
482 Controller,\r
483 &gEfiIsaIoProtocolGuid,\r
484 (VOID **) &IsaIo,\r
485 This->DriverBindingHandle,\r
486 SerialDevice->Handle,\r
487 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
488 );\r
489\r
490Error:\r
491 if (EFI_ERROR (Status)) {\r
492 gBS->CloseProtocol (\r
493 Controller,\r
494 &gEfiDevicePathProtocolGuid,\r
495 This->DriverBindingHandle,\r
496 Controller\r
497 );\r
498 gBS->CloseProtocol (\r
499 Controller,\r
500 &gEfiIsaIoProtocolGuid,\r
501 This->DriverBindingHandle,\r
502 Controller\r
503 );\r
504 if (SerialDevice) {\r
505 if (SerialDevice->DevicePath) {\r
506 gBS->FreePool (SerialDevice->DevicePath);\r
507 }\r
508\r
509 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);\r
510 gBS->FreePool (SerialDevice);\r
511 }\r
512 }\r
513\r
514 return Status;\r
515}\r
516\r
bcd70414 517/**\r
518 Disconnect this driver with the controller, uninstall related protocol instance\r
519\r
520 @param This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
521 @param Controller - The handle of the controller to test.\r
522 @param NumberOfChildren - Number of child device.\r
fdb05fa3 523 @param ChildHandleBuffer - A pointer to the remaining portion of a device path.\r
bcd70414 524\r
525 @retval EFI_SUCCESS - Operation successfully\r
526 @retval EFI_DEVICE_ERROR - Cannot stop the driver successfully\r
527\r
528**/\r
637ff819 529EFI_STATUS\r
530EFIAPI\r
531SerialControllerDriverStop (\r
532 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
533 IN EFI_HANDLE Controller,\r
534 IN UINTN NumberOfChildren,\r
535 IN EFI_HANDLE *ChildHandleBuffer\r
536 )\r
637ff819 537\r
637ff819 538{\r
539 EFI_STATUS Status;\r
540 UINTN Index;\r
541 BOOLEAN AllChildrenStopped;\r
542 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
543 SERIAL_DEV *SerialDevice;\r
544 EFI_ISA_IO_PROTOCOL *IsaIo;\r
545 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
546\r
547 Status = gBS->HandleProtocol (\r
548 Controller,\r
549 &gEfiDevicePathProtocolGuid,\r
550 (VOID **) &DevicePath\r
551 );\r
552\r
553 //\r
554 // Report the status code disable the serial\r
555 //\r
556 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
557 EFI_PROGRESS_CODE,\r
558 EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,\r
559 DevicePath\r
560 );\r
561\r
562 //\r
563 // Complete all outstanding transactions to Controller.\r
564 // Don't allow any new transaction to Controller to be started.\r
565 //\r
566 if (NumberOfChildren == 0) {\r
567 //\r
568 // Close the bus driver\r
569 //\r
570 Status = gBS->CloseProtocol (\r
571 Controller,\r
572 &gEfiIsaIoProtocolGuid,\r
573 This->DriverBindingHandle,\r
574 Controller\r
575 );\r
576\r
577 Status = gBS->CloseProtocol (\r
578 Controller,\r
579 &gEfiDevicePathProtocolGuid,\r
580 This->DriverBindingHandle,\r
581 Controller\r
582 );\r
583 return Status;\r
584 }\r
585\r
586 AllChildrenStopped = TRUE;\r
587\r
588 for (Index = 0; Index < NumberOfChildren; Index++) {\r
589\r
590 Status = gBS->OpenProtocol (\r
591 ChildHandleBuffer[Index],\r
592 &gEfiSerialIoProtocolGuid,\r
593 (VOID **) &SerialIo,\r
594 This->DriverBindingHandle,\r
595 Controller,\r
596 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
597 );\r
598 if (!EFI_ERROR (Status)) {\r
599\r
600 SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);\r
601\r
602 Status = gBS->CloseProtocol (\r
603 Controller,\r
604 &gEfiIsaIoProtocolGuid,\r
605 This->DriverBindingHandle,\r
606 ChildHandleBuffer[Index]\r
607 );\r
608\r
609 Status = gBS->UninstallMultipleProtocolInterfaces (\r
610 ChildHandleBuffer[Index],\r
611 &gEfiDevicePathProtocolGuid,\r
612 SerialDevice->DevicePath,\r
613 &gEfiSerialIoProtocolGuid,\r
614 &SerialDevice->SerialIo,\r
615 NULL\r
616 );\r
617 if (EFI_ERROR (Status)) {\r
618 gBS->OpenProtocol (\r
619 Controller,\r
620 &gEfiIsaIoProtocolGuid,\r
621 (VOID **) &IsaIo,\r
622 This->DriverBindingHandle,\r
623 ChildHandleBuffer[Index],\r
624 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
625 );\r
626 } else {\r
627 if (SerialDevice->DevicePath) {\r
628 gBS->FreePool (SerialDevice->DevicePath);\r
629 }\r
630\r
631 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);\r
632 gBS->FreePool (SerialDevice);\r
633 }\r
634 }\r
635\r
636 if (EFI_ERROR (Status)) {\r
637 AllChildrenStopped = FALSE;\r
638 }\r
639 }\r
640\r
641 if (!AllChildrenStopped) {\r
642 return EFI_DEVICE_ERROR;\r
643 }\r
644\r
645 return EFI_SUCCESS;\r
646}\r
647\r
bcd70414 648/**\r
649 Detect whether specific FIFO is full or not\r
650\r
651 @param Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
652\r
653 @return whether specific FIFO is full or not\r
654\r
655**/\r
637ff819 656BOOLEAN\r
657IsaSerialFifoFull (\r
658 IN SERIAL_DEV_FIFO *Fifo\r
659 )\r
637ff819 660\r
637ff819 661{\r
662 if (Fifo->Surplus == 0) {\r
663 return TRUE;\r
664 }\r
665\r
666 return FALSE;\r
667}\r
668\r
bcd70414 669/**\r
670 Detect whether specific FIFO is empty or not\r
671\r
672 \r
673 @param Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
674\r
675 @return whether specific FIFO is empty or not\r
676\r
677**/\r
637ff819 678BOOLEAN\r
679IsaSerialFifoEmpty (\r
680 IN SERIAL_DEV_FIFO *Fifo\r
681 )\r
637ff819 682\r
637ff819 683{\r
684 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {\r
685 return TRUE;\r
686 }\r
687\r
688 return FALSE;\r
689}\r
690\r
bcd70414 691/**\r
692 Add data to specific FIFO\r
693\r
694 @param Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
695 @param Data - the data added to FIFO\r
696\r
697 @retval EFI_SUCCESS - Add data to specific FIFO successfully\r
698 @retval EFI_OUT_OF_RESOURCE - Failed to add data because FIFO is already full\r
699\r
700**/\r
637ff819 701EFI_STATUS\r
702IsaSerialFifoAdd (\r
703 IN SERIAL_DEV_FIFO *Fifo,\r
704 IN UINT8 Data\r
705 )\r
637ff819 706\r
637ff819 707{\r
708 //\r
709 // if FIFO full can not add data\r
710 //\r
711 if (IsaSerialFifoFull (Fifo)) {\r
712 return EFI_OUT_OF_RESOURCES;\r
713 }\r
714 //\r
715 // FIFO is not full can add data\r
716 //\r
717 Fifo->Data[Fifo->Last] = Data;\r
718 Fifo->Surplus--;\r
719 Fifo->Last++;\r
720 if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {\r
721 Fifo->Last = 0;\r
722 }\r
723\r
724 return EFI_SUCCESS;\r
725}\r
726\r
bcd70414 727/**\r
728 Remove data from specific FIFO\r
729\r
730 @param Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
731 @param Data - the data removed from FIFO\r
732\r
733 @retval EFI_SUCCESS - Remove data from specific FIFO successfully\r
734 @retval EFI_OUT_OF_RESOURCE - Failed to remove data because FIFO is empty\r
735\r
736**/\r
637ff819 737EFI_STATUS\r
738IsaSerialFifoRemove (\r
739 IN SERIAL_DEV_FIFO *Fifo,\r
740 OUT UINT8 *Data\r
741 )\r
637ff819 742\r
637ff819 743{\r
744 //\r
745 // if FIFO is empty, no data can remove\r
746 //\r
747 if (IsaSerialFifoEmpty (Fifo)) {\r
748 return EFI_OUT_OF_RESOURCES;\r
749 }\r
750 //\r
751 // FIFO is not empty, can remove data\r
752 //\r
753 *Data = Fifo->Data[Fifo->First];\r
754 Fifo->Surplus++;\r
755 Fifo->First++;\r
756 if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {\r
757 Fifo->First = 0;\r
758 }\r
759\r
760 return EFI_SUCCESS;\r
761}\r
762\r
bcd70414 763/**\r
764 Reads and writes all avaliable data.\r
765\r
766 @param SerialDevice - The device to flush\r
767\r
768 @retval EFI_SUCCESS - Data was read/written successfully.\r
769 @retval EFI_OUT_OF_RESOURCE - Failed because software receive FIFO is full. Note, when\r
770 this happens, pending writes are not done.\r
771\r
772**/\r
637ff819 773EFI_STATUS\r
774IsaSerialReceiveTransmit (\r
775 IN SERIAL_DEV *SerialDevice\r
776 )\r
637ff819 777\r
637ff819 778{\r
779 SERIAL_PORT_LSR Lsr;\r
780 UINT8 Data;\r
781 BOOLEAN ReceiveFifoFull;\r
782 SERIAL_PORT_MSR Msr;\r
783 SERIAL_PORT_MCR Mcr;\r
784 UINTN TimeOut;\r
785\r
786 Data = 0;\r
787\r
788 //\r
789 // Begin the read or write\r
790 //\r
791 if (SerialDevice->SoftwareLoopbackEnable) {\r
792 do {\r
793 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
794 if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
795 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
796 if (ReceiveFifoFull) {\r
797 return EFI_OUT_OF_RESOURCES;\r
798 }\r
799\r
800 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
801 }\r
802 } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
803 } else {\r
804 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
805 do {\r
806 Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
807\r
637ff819 808 //\r
809 // Flush incomming data to prevent a an overrun during a long write\r
810 //\r
811 if (Lsr.Bits.DR && !ReceiveFifoFull) {\r
812 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
813 if (!ReceiveFifoFull) {\r
814 if (Lsr.Bits.FIFOE || Lsr.Bits.OE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {\r
815 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
816 EFI_ERROR_CODE,\r
817 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
818 SerialDevice->DevicePath\r
819 );\r
820 if (Lsr.Bits.FIFOE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {\r
821 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
822 continue;\r
823 }\r
824 }\r
825 //\r
826 // Make sure the receive data will not be missed, Assert DTR\r
827 //\r
828 if (SerialDevice->HardwareFlowControl) {\r
829 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
830 Mcr.Bits.DTRC &= 0;\r
831 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
832 }\r
833\r
834 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
835\r
836 //\r
837 // Deassert DTR\r
838 //\r
839 if (SerialDevice->HardwareFlowControl) {\r
840 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
841 Mcr.Bits.DTRC |= 1;\r
842 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
843 }\r
844\r
845 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
846\r
847 continue;\r
848 } else {\r
849 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
850 EFI_PROGRESS_CODE,\r
851 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,\r
852 SerialDevice->DevicePath\r
853 );\r
854 }\r
855 }\r
856 //\r
857 // Do the write\r
858 //\r
859 if (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
860 //\r
861 // Make sure the transmit data will not be missed\r
862 //\r
863 if (SerialDevice->HardwareFlowControl) {\r
864 //\r
865 // Send RTS\r
866 //\r
867 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
868 Mcr.Bits.RTS |= 1;\r
869 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
870 //\r
871 // Wait for CTS\r
872 //\r
873 TimeOut = 0;\r
874 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
875 while (!Msr.Bits.CTS) {\r
876 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
877 TimeOut++;\r
878 if (TimeOut > 5) {\r
879 break;\r
880 }\r
881\r
882 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
883 }\r
884\r
885 if (Msr.Bits.CTS) {\r
886 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
887 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
888 }\r
889 }\r
890 //\r
891 // write the data out\r
892 //\r
893 if (!SerialDevice->HardwareFlowControl) {\r
894 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
895 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
896 }\r
897 //\r
898 // Make sure the transmit data will not be missed\r
899 //\r
900 if (SerialDevice->HardwareFlowControl) {\r
901 //\r
902 // Assert RTS\r
903 //\r
904 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
905 Mcr.Bits.RTS &= 0;\r
906 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
907 }\r
908 }\r
909 } while (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
910 }\r
911\r
912 return EFI_SUCCESS;\r
913}\r
bcd70414 914\r
637ff819 915//\r
916// Interface Functions\r
917//\r
bcd70414 918/**\r
919 Reset serial device\r
920\r
921 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
922\r
923 @retval EFI_SUCCESS - Reset successfully\r
924 @retval EFI_DEVICE_ERROR - Failed to reset\r
925\r
926**/\r
637ff819 927EFI_STATUS\r
928EFIAPI\r
929IsaSerialReset (\r
930 IN EFI_SERIAL_IO_PROTOCOL *This\r
931 )\r
637ff819 932{\r
933 EFI_STATUS Status;\r
934 SERIAL_DEV *SerialDevice;\r
935 SERIAL_PORT_LCR Lcr;\r
936 SERIAL_PORT_IER Ier;\r
937 SERIAL_PORT_MCR Mcr;\r
938 SERIAL_PORT_FCR Fcr;\r
939 EFI_TPL Tpl;\r
940\r
941 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
942\r
943 //\r
944 // Report the status code reset the serial\r
945 //\r
946 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
947 EFI_PROGRESS_CODE,\r
948 EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,\r
949 SerialDevice->DevicePath\r
950 );\r
951\r
952 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
953\r
954 //\r
955 // Make sure DLAB is 0.\r
956 //\r
957 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
958 Lcr.Bits.DLAB = 0;\r
959 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
960\r
961 //\r
962 // Turn off all interrupts\r
963 //\r
964 Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
965 Ier.Bits.RAVIE = 0;\r
966 Ier.Bits.THEIE = 0;\r
967 Ier.Bits.RIE = 0;\r
968 Ier.Bits.MIE = 0;\r
969 WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);\r
970\r
971 //\r
972 // Disable the FIFO.\r
973 //\r
974 Fcr.Bits.TRFIFOE = 0;\r
975 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
976\r
977 //\r
978 // Turn off loopback and disable device interrupt.\r
979 //\r
980 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
981 Mcr.Bits.OUT1 = 0;\r
982 Mcr.Bits.OUT2 = 0;\r
983 Mcr.Bits.LME = 0;\r
984 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
985\r
986 //\r
987 // Clear the scratch pad register\r
988 //\r
989 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);\r
990\r
991 //\r
992 // Go set the current attributes\r
993 //\r
994 Status = This->SetAttributes (\r
995 This,\r
996 This->Mode->BaudRate,\r
997 This->Mode->ReceiveFifoDepth,\r
998 This->Mode->Timeout,\r
999 (EFI_PARITY_TYPE) This->Mode->Parity,\r
1000 (UINT8) This->Mode->DataBits,\r
1001 (EFI_STOP_BITS_TYPE) This->Mode->StopBits\r
1002 );\r
1003\r
1004 if (EFI_ERROR (Status)) {\r
1005 gBS->RestoreTPL (Tpl);\r
1006 return EFI_DEVICE_ERROR;\r
1007 }\r
1008 //\r
1009 // Go set the current control bits\r
1010 //\r
1011 Status = This->SetControl (\r
1012 This,\r
1013 This->Mode->ControlMask\r
1014 );\r
1015\r
1016 if (EFI_ERROR (Status)) {\r
1017 gBS->RestoreTPL (Tpl);\r
1018 return EFI_DEVICE_ERROR;\r
1019 }\r
1020 //\r
1021 // for 16550A enable FIFO, 16550 disable FIFO\r
1022 //\r
1023 Fcr.Bits.TRFIFOE = 1;\r
1024 Fcr.Bits.RESETRF = 1;\r
1025 Fcr.Bits.RESETTF = 1;\r
1026 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
1027\r
1028 //\r
1029 // Reset the software FIFO\r
1030 //\r
1031 SerialDevice->Receive.First = 0;\r
1032 SerialDevice->Receive.Last = 0;\r
1033 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1034 SerialDevice->Transmit.First = 0;\r
1035 SerialDevice->Transmit.Last = 0;\r
1036 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1037\r
1038 gBS->RestoreTPL (Tpl);\r
1039\r
1040 //\r
1041 // Device reset is complete\r
1042 //\r
1043 return EFI_SUCCESS;\r
1044}\r
1045\r
bcd70414 1046/**\r
1047 Set new attributes to a serial device\r
1048\r
1049 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1050 @param BaudRate - The baudrate of the serial device\r
1051 @param ReceiveFifoDepth - The depth of receive FIFO buffer\r
1052 @param Timeout - The request timeout for a single char\r
1053 @param Parity - The type of parity used in serial device\r
1054 @param DataBits - Number of databits used in serial device\r
1055 @param StopBits - Number of stopbits used in serial device\r
1056\r
1057 @retval EFI_SUCCESS - The new attributes were set\r
1058 @retval EFI_INVALID_PARAMETERS - One or more attributes have an unsupported value\r
1059 @retval EFI_UNSUPPORTED - Data Bits can not set to 5 or 6\r
1060 @retval EFI_DEVICE_ERROR - The serial device is not functioning correctly (no return)\r
1061\r
1062**/\r
637ff819 1063EFI_STATUS\r
1064EFIAPI\r
1065IsaSerialSetAttributes (\r
1066 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1067 IN UINT64 BaudRate,\r
1068 IN UINT32 ReceiveFifoDepth,\r
1069 IN UINT32 Timeout,\r
1070 IN EFI_PARITY_TYPE Parity,\r
1071 IN UINT8 DataBits,\r
1072 IN EFI_STOP_BITS_TYPE StopBits\r
1073 )\r
637ff819 1074{\r
1075 EFI_STATUS Status;\r
1076 SERIAL_DEV *SerialDevice;\r
1077 UINT32 Divisor;\r
1078 UINT32 Remained;\r
1079 SERIAL_PORT_LCR Lcr;\r
1080 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1081 EFI_TPL Tpl;\r
1082\r
1083 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1084\r
1085 //\r
1086 // Check for default settings and fill in actual values.\r
1087 //\r
1088 if (BaudRate == 0) {\r
6b88ceec 1089 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);\r
637ff819 1090 }\r
1091\r
1092 if (ReceiveFifoDepth == 0) {\r
1093 ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;\r
1094 }\r
1095\r
1096 if (Timeout == 0) {\r
1097 Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;\r
1098 }\r
1099\r
1100 if (Parity == DefaultParity) {\r
6bee1632 1101 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
637ff819 1102 }\r
1103\r
1104 if (DataBits == 0) {\r
6b88ceec 1105 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
637ff819 1106 }\r
1107\r
1108 if (StopBits == DefaultStopBits) {\r
6b88ceec 1109 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);\r
637ff819 1110 }\r
1111 //\r
1112 // 5 and 6 data bits can not be verified on a 16550A UART\r
1113 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.\r
1114 //\r
1115 if ((DataBits == 5) || (DataBits == 6)) {\r
1116 return EFI_INVALID_PARAMETER;\r
1117 }\r
1118 //\r
1119 // Make sure all parameters are valid\r
1120 //\r
1121 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
1122 return EFI_INVALID_PARAMETER;\r
1123 }\r
1124 //\r
1125 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,\r
1126 // 38400,57600,115200\r
1127 //\r
1128 if (BaudRate < 75) {\r
1129 BaudRate = 50;\r
1130 } else if (BaudRate < 110) {\r
1131 BaudRate = 75;\r
1132 } else if (BaudRate < 134) {\r
1133 BaudRate = 110;\r
1134 } else if (BaudRate < 150) {\r
1135 BaudRate = 134;\r
1136 } else if (BaudRate < 300) {\r
1137 BaudRate = 150;\r
1138 } else if (BaudRate < 600) {\r
1139 BaudRate = 300;\r
1140 } else if (BaudRate < 1200) {\r
1141 BaudRate = 600;\r
1142 } else if (BaudRate < 1800) {\r
1143 BaudRate = 1200;\r
1144 } else if (BaudRate < 2000) {\r
1145 BaudRate = 1800;\r
1146 } else if (BaudRate < 2400) {\r
1147 BaudRate = 2000;\r
1148 } else if (BaudRate < 3600) {\r
1149 BaudRate = 2400;\r
1150 } else if (BaudRate < 4800) {\r
1151 BaudRate = 3600;\r
1152 } else if (BaudRate < 7200) {\r
1153 BaudRate = 4800;\r
1154 } else if (BaudRate < 9600) {\r
1155 BaudRate = 7200;\r
1156 } else if (BaudRate < 19200) {\r
1157 BaudRate = 9600;\r
1158 } else if (BaudRate < 38400) {\r
1159 BaudRate = 19200;\r
1160 } else if (BaudRate < 57600) {\r
1161 BaudRate = 38400;\r
1162 } else if (BaudRate < 115200) {\r
1163 BaudRate = 57600;\r
1164 } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {\r
1165 BaudRate = 115200;\r
1166 }\r
1167\r
1168 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
1169 return EFI_INVALID_PARAMETER;\r
1170 }\r
1171\r
1172 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
1173 return EFI_INVALID_PARAMETER;\r
1174 }\r
1175\r
1176 if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
1177 return EFI_INVALID_PARAMETER;\r
1178 }\r
1179\r
1180 if ((DataBits < 5) || (DataBits > 8)) {\r
1181 return EFI_INVALID_PARAMETER;\r
1182 }\r
1183\r
1184 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
1185 return EFI_INVALID_PARAMETER;\r
1186 }\r
1187 //\r
1188 // for DataBits = 5, StopBits can not set TwoStopBits\r
1189 //\r
1190 // if ((DataBits == 5) && (StopBits == TwoStopBits)) {\r
1191 // return EFI_INVALID_PARAMETER;\r
1192 // }\r
1193 //\r
1194 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits\r
1195 //\r
1196 if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {\r
1197 return EFI_INVALID_PARAMETER;\r
1198 }\r
1199\r
1200 //\r
1201 // Compute divisor use to program the baud rate using a round determination\r
1202 //\r
1203 Divisor = (UINT32) DivU64x32Remainder (\r
1204 SERIAL_PORT_INPUT_CLOCK,\r
1205 ((UINT32) BaudRate * 16),\r
1206 &Remained\r
1207 );\r
1208 if (Remained) {\r
1209 Divisor += 1;\r
1210 }\r
1211\r
1212 if ((Divisor == 0) || (Divisor & 0xffff0000)) {\r
1213 return EFI_INVALID_PARAMETER;\r
1214 }\r
1215\r
1216 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1217\r
1218 //\r
1219 // Compute the actual baud rate that the serial port will be programmed for.\r
1220 //\r
1221 BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;\r
1222\r
1223 //\r
1224 // Put serial port on Divisor Latch Mode\r
1225 //\r
1226 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1227 Lcr.Bits.DLAB = 1;\r
1228 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1229\r
1230 //\r
1231 // Write the divisor to the serial port\r
1232 //\r
1233 WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));\r
1234 WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));\r
1235\r
1236 //\r
1237 // Put serial port back in normal mode and set remaining attributes.\r
1238 //\r
1239 Lcr.Bits.DLAB = 0;\r
1240\r
1241 switch (Parity) {\r
1242 case NoParity:\r
1243 Lcr.Bits.PAREN = 0;\r
1244 Lcr.Bits.EVENPAR = 0;\r
1245 Lcr.Bits.STICPAR = 0;\r
1246 break;\r
1247\r
1248 case EvenParity:\r
1249 Lcr.Bits.PAREN = 1;\r
1250 Lcr.Bits.EVENPAR = 1;\r
1251 Lcr.Bits.STICPAR = 0;\r
1252 break;\r
1253\r
1254 case OddParity:\r
1255 Lcr.Bits.PAREN = 1;\r
1256 Lcr.Bits.EVENPAR = 0;\r
1257 Lcr.Bits.STICPAR = 0;\r
1258 break;\r
1259\r
1260 case SpaceParity:\r
1261 Lcr.Bits.PAREN = 1;\r
1262 Lcr.Bits.EVENPAR = 1;\r
1263 Lcr.Bits.STICPAR = 1;\r
1264 break;\r
1265\r
1266 case MarkParity:\r
1267 Lcr.Bits.PAREN = 1;\r
1268 Lcr.Bits.EVENPAR = 0;\r
1269 Lcr.Bits.STICPAR = 1;\r
1270 break;\r
1271\r
1272 default:\r
1273 break;\r
1274 }\r
1275\r
1276 switch (StopBits) {\r
1277 case OneStopBit:\r
1278 Lcr.Bits.STOPB = 0;\r
1279 break;\r
1280\r
1281 case OneFiveStopBits:\r
1282 case TwoStopBits:\r
1283 Lcr.Bits.STOPB = 1;\r
1284 break;\r
1285\r
1286 default:\r
1287 break;\r
1288 }\r
1289 //\r
1290 // DataBits\r
1291 //\r
1292 Lcr.Bits.SERIALDB = (UINT8) ((DataBits - 5) & 0x03);\r
1293 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1294\r
1295 //\r
1296 // Set the Serial I/O mode\r
1297 //\r
1298 This->Mode->BaudRate = BaudRate;\r
1299 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;\r
1300 This->Mode->Timeout = Timeout;\r
1301 This->Mode->Parity = Parity;\r
1302 This->Mode->DataBits = DataBits;\r
1303 This->Mode->StopBits = StopBits;\r
1304\r
1305 //\r
1306 // See if Device Path Node has actually changed\r
1307 //\r
1308 if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&\r
1309 SerialDevice->UartDevicePath.DataBits == DataBits &&\r
1310 SerialDevice->UartDevicePath.Parity == Parity &&\r
1311 SerialDevice->UartDevicePath.StopBits == StopBits\r
1312 ) {\r
1313 gBS->RestoreTPL (Tpl);\r
1314 return EFI_SUCCESS;\r
1315 }\r
1316 //\r
1317 // Update the device path\r
1318 //\r
1319 SerialDevice->UartDevicePath.BaudRate = BaudRate;\r
1320 SerialDevice->UartDevicePath.DataBits = DataBits;\r
1321 SerialDevice->UartDevicePath.Parity = (UINT8) Parity;\r
1322 SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;\r
1323\r
1324 NewDevicePath = AppendDevicePathNode (\r
1325 SerialDevice->ParentDevicePath,\r
1326 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath\r
1327 );\r
1328 if (NewDevicePath == NULL) {\r
1329 gBS->RestoreTPL (Tpl);\r
1330 return EFI_DEVICE_ERROR;\r
1331 }\r
1332\r
1333 if (SerialDevice->Handle != NULL) {\r
1334 Status = gBS->ReinstallProtocolInterface (\r
1335 SerialDevice->Handle,\r
1336 &gEfiDevicePathProtocolGuid,\r
1337 SerialDevice->DevicePath,\r
1338 NewDevicePath\r
1339 );\r
1340 if (EFI_ERROR (Status)) {\r
1341 gBS->RestoreTPL (Tpl);\r
1342 return Status;\r
1343 }\r
1344 }\r
1345\r
1346 if (SerialDevice->DevicePath) {\r
1347 gBS->FreePool (SerialDevice->DevicePath);\r
1348 }\r
1349\r
1350 SerialDevice->DevicePath = NewDevicePath;\r
1351\r
1352 gBS->RestoreTPL (Tpl);\r
1353\r
1354 return EFI_SUCCESS;\r
1355}\r
1356\r
bcd70414 1357/**\r
1358 Set Control Bits\r
1359\r
1360 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1361 @param Control - Control bits that can be settable\r
1362\r
1363 @retval EFI_SUCCESS - New Control bits were set successfully\r
1364 @retval EFI_UNSUPPORTED - The Control bits wanted to set are not supported\r
1365\r
1366**/\r
637ff819 1367EFI_STATUS\r
1368EFIAPI\r
1369IsaSerialSetControl (\r
1370 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1371 IN UINT32 Control\r
1372 )\r
637ff819 1373{\r
1374 SERIAL_DEV *SerialDevice;\r
1375 SERIAL_PORT_MCR Mcr;\r
1376 EFI_TPL Tpl;\r
1377\r
1378 //\r
1379 // The control bits that can be set are :\r
1380 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO\r
1381 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO\r
1382 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW\r
1383 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW\r
1384 //\r
1385 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1386\r
1387 //\r
1388 // first determine the parameter is invalid\r
1389 //\r
1390 if (Control & 0xffff8ffc) {\r
1391 return EFI_UNSUPPORTED;\r
1392 }\r
1393\r
1394 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1395\r
1396 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1397 Mcr.Bits.DTRC = 0;\r
1398 Mcr.Bits.RTS = 0;\r
1399 Mcr.Bits.LME = 0;\r
1400 SerialDevice->SoftwareLoopbackEnable = FALSE;\r
1401 SerialDevice->HardwareFlowControl = FALSE;\r
1402\r
1403 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {\r
1404 Mcr.Bits.DTRC = 1;\r
1405 }\r
1406\r
1407 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {\r
1408 Mcr.Bits.RTS = 1;\r
1409 }\r
1410\r
1411 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {\r
1412 Mcr.Bits.LME = 1;\r
1413 }\r
1414\r
1415 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
1416 SerialDevice->HardwareFlowControl = TRUE;\r
1417 }\r
1418\r
1419 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
1420\r
1421 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {\r
1422 SerialDevice->SoftwareLoopbackEnable = TRUE;\r
1423 }\r
1424\r
1425 gBS->RestoreTPL (Tpl);\r
1426\r
1427 return EFI_SUCCESS;\r
1428}\r
1429\r
bcd70414 1430/**\r
1431 Get ControlBits\r
1432\r
1433 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1434 @param Control - Control signals of the serial device\r
1435\r
1436 @retval EFI_SUCCESS - Get Control signals successfully\r
1437\r
1438**/\r
637ff819 1439EFI_STATUS\r
1440EFIAPI\r
1441IsaSerialGetControl (\r
1442 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1443 OUT UINT32 *Control\r
1444 )\r
637ff819 1445{\r
1446 SERIAL_DEV *SerialDevice;\r
1447 SERIAL_PORT_MSR Msr;\r
1448 SERIAL_PORT_MCR Mcr;\r
1449 EFI_TPL Tpl;\r
1450\r
1451 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1452\r
1453 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1454\r
1455 *Control = 0;\r
1456\r
1457 //\r
1458 // Read the Modem Status Register\r
1459 //\r
1460 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1461\r
1462 if (Msr.Bits.CTS) {\r
1463 *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
1464 }\r
1465\r
1466 if (Msr.Bits.DSR) {\r
1467 *Control |= EFI_SERIAL_DATA_SET_READY;\r
1468 }\r
1469\r
1470 if (Msr.Bits.RI) {\r
1471 *Control |= EFI_SERIAL_RING_INDICATE;\r
1472 }\r
1473\r
1474 if (Msr.Bits.DCD) {\r
1475 *Control |= EFI_SERIAL_CARRIER_DETECT;\r
1476 }\r
1477 //\r
1478 // Read the Modem Control Register\r
1479 //\r
1480 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1481\r
1482 if (Mcr.Bits.DTRC) {\r
1483 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
1484 }\r
1485\r
1486 if (Mcr.Bits.RTS) {\r
1487 *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
1488 }\r
1489\r
1490 if (Mcr.Bits.LME) {\r
1491 *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
1492 }\r
1493\r
1494 if (SerialDevice->HardwareFlowControl) {\r
1495 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
1496 }\r
1497 //\r
1498 // See if the Transmit FIFO is empty\r
1499 //\r
1500 IsaSerialReceiveTransmit (SerialDevice);\r
1501\r
1502 if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1503 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
1504 }\r
1505 //\r
1506 // See if the Receive FIFO is empty.\r
1507 //\r
1508 IsaSerialReceiveTransmit (SerialDevice);\r
1509\r
1510 if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {\r
1511 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
1512 }\r
1513\r
1514 if (SerialDevice->SoftwareLoopbackEnable) {\r
1515 *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
1516 }\r
1517\r
1518 gBS->RestoreTPL (Tpl);\r
1519\r
1520 return EFI_SUCCESS;\r
1521}\r
1522\r
bcd70414 1523/**\r
1524 Write the specified number of bytes to serial device\r
1525\r
1526 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1527 @param BufferSize - On input the size of Buffer, on output the amount of\r
1528 data actually written\r
1529 @param Buffer - The buffer of data to write\r
1530\r
1531 @retval EFI_SUCCESS - The data were written successfully\r
1532 @retval EFI_DEVICE_ERROR - The device reported an error\r
1533 @retval EFI_TIMEOUT - The write operation was stopped due to timeout\r
1534\r
1535**/\r
637ff819 1536EFI_STATUS\r
1537EFIAPI\r
1538IsaSerialWrite (\r
1539 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1540 IN OUT UINTN *BufferSize,\r
1541 IN VOID *Buffer\r
1542 )\r
637ff819 1543{\r
1544 SERIAL_DEV *SerialDevice;\r
1545 UINT8 *CharBuffer;\r
1546 UINT32 Index;\r
1547 UINTN Elapsed;\r
1548 UINTN ActualWrite;\r
1549 EFI_TPL Tpl;\r
1550\r
1551 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1552 Elapsed = 0;\r
1553 ActualWrite = 0;\r
1554\r
1555 if (*BufferSize == 0) {\r
1556 return EFI_SUCCESS;\r
1557 }\r
1558\r
1559 if (!Buffer) {\r
1560 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1561 EFI_ERROR_CODE,\r
1562 EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1563 SerialDevice->DevicePath\r
1564 );\r
1565\r
1566 return EFI_DEVICE_ERROR;\r
1567 }\r
1568\r
1569 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1570\r
1571 CharBuffer = (UINT8 *) Buffer;\r
1572\r
1573 for (Index = 0; Index < *BufferSize; Index++) {\r
1574 IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);\r
1575\r
1576 while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1577 //\r
1578 // Unsuccessful write so check if timeout has expired, if not,\r
1579 // stall for a bit, increment time elapsed, and try again\r
1580 //\r
1581 if (Elapsed >= This->Mode->Timeout) {\r
1582 *BufferSize = ActualWrite;\r
1583 gBS->RestoreTPL (Tpl);\r
1584 return EFI_TIMEOUT;\r
1585 }\r
1586\r
1587 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1588\r
1589 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1590 }\r
1591\r
1592 ActualWrite++;\r
1593 //\r
1594 // Successful write so reset timeout\r
1595 //\r
1596 Elapsed = 0;\r
1597 }\r
1598\r
1599 gBS->RestoreTPL (Tpl);\r
1600\r
1601 return EFI_SUCCESS;\r
1602}\r
1603\r
bcd70414 1604/**\r
1605 Read the specified number of bytes from serial device\r
1606\r
1607 @param This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1608 @param BufferSize - On input the size of Buffer, on output the amount of\r
1609 data returned in buffer\r
1610 @param Buffer - The buffer to return the data into\r
1611\r
1612 @retval EFI_SUCCESS - The data were read successfully\r
1613 @retval EFI_DEVICE_ERROR - The device reported an error\r
1614 @retval EFI_TIMEOUT - The read operation was stopped due to timeout\r
1615\r
1616**/\r
637ff819 1617EFI_STATUS\r
1618EFIAPI\r
1619IsaSerialRead (\r
1620 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1621 IN OUT UINTN *BufferSize,\r
1622 OUT VOID *Buffer\r
1623 )\r
637ff819 1624{\r
1625 SERIAL_DEV *SerialDevice;\r
1626 UINT32 Index;\r
1627 UINT8 *CharBuffer;\r
1628 UINTN Elapsed;\r
1629 EFI_STATUS Status;\r
1630 EFI_TPL Tpl;\r
1631\r
1632 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1633 Elapsed = 0;\r
1634\r
1635 if (*BufferSize == 0) {\r
1636 return EFI_SUCCESS;\r
1637 }\r
1638\r
1639 if (!Buffer) {\r
1640 return EFI_DEVICE_ERROR;\r
1641 }\r
1642\r
1643 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1644\r
1645 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1646\r
1647 if (EFI_ERROR (Status)) {\r
1648 *BufferSize = 0;\r
1649\r
1650 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1651 EFI_ERROR_CODE,\r
1652 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1653 SerialDevice->DevicePath\r
1654 );\r
1655\r
1656 gBS->RestoreTPL (Tpl);\r
1657\r
1658 return EFI_DEVICE_ERROR;\r
1659 }\r
1660\r
1661 CharBuffer = (UINT8 *) Buffer;\r
1662 for (Index = 0; Index < *BufferSize; Index++) {\r
1663 while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {\r
1664 //\r
1665 // Unsuccessful read so check if timeout has expired, if not,\r
1666 // stall for a bit, increment time elapsed, and try again\r
1667 // Need this time out to get conspliter to work.\r
1668 //\r
1669 if (Elapsed >= This->Mode->Timeout) {\r
1670 *BufferSize = Index;\r
1671 gBS->RestoreTPL (Tpl);\r
1672 return EFI_TIMEOUT;\r
1673 }\r
1674\r
1675 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1676 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1677\r
1678 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1679 if (Status == EFI_DEVICE_ERROR) {\r
1680 *BufferSize = Index;\r
1681 gBS->RestoreTPL (Tpl);\r
1682 return EFI_DEVICE_ERROR;\r
1683 }\r
1684 }\r
1685 //\r
1686 // Successful read so reset timeout\r
1687 //\r
1688 Elapsed = 0;\r
1689 }\r
1690\r
1691 IsaSerialReceiveTransmit (SerialDevice);\r
1692\r
1693 gBS->RestoreTPL (Tpl);\r
1694\r
1695 return EFI_SUCCESS;\r
1696}\r
1697\r
bcd70414 1698/**\r
1699 Use scratchpad register to test if this serial port is present\r
1700\r
1701 @param SerialDevice - Pointer to serial device structure\r
1702\r
1703 @return if this serial port is present\r
1704**/\r
637ff819 1705BOOLEAN\r
1706IsaSerialPortPresent (\r
1707 IN SERIAL_DEV *SerialDevice\r
1708 )\r
637ff819 1709\r
637ff819 1710{\r
1711 UINT8 Temp;\r
1712 BOOLEAN Status;\r
1713\r
1714 Status = TRUE;\r
1715\r
1716 //\r
1717 // Save SCR reg\r
1718 //\r
1719 Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1720 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);\r
1721\r
6b88ceec 1722 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) {\r
ea2d9086 1723 Status = FALSE;\r
637ff819 1724 }\r
1725\r
1726 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);\r
1727\r
6b88ceec 1728 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) {\r
ea2d9086 1729 Status = FALSE;\r
637ff819 1730 }\r
1731 //\r
1732 // Restore SCR\r
1733 //\r
1734 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);\r
1735 return Status;\r
1736}\r
1737\r
bcd70414 1738/**\r
1739 Use IsaIo protocol to read serial port\r
1740\r
1741 @param IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance\r
1742 @param BaseAddress - Serial port register group base address\r
1743 @param Offset - Offset in register group\r
1744\r
1745 @return Data read from serial port\r
1746\r
1747**/\r
637ff819 1748UINT8\r
1749IsaSerialReadPort (\r
1750 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1751 IN UINT16 BaseAddress,\r
1752 IN UINT32 Offset\r
1753 )\r
637ff819 1754{\r
1755 UINT8 Data;\r
1756\r
1757 //\r
1758 // Use IsaIo to access IO\r
1759 //\r
1760 IsaIo->Io.Read (\r
1761 IsaIo,\r
1762 EfiIsaIoWidthUint8,\r
1763 BaseAddress + Offset,\r
1764 1,\r
1765 &Data\r
1766 );\r
1767 return Data;\r
1768}\r
1769\r
bcd70414 1770/**\r
1771 Use IsaIo protocol to write serial port\r
1772\r
1773 @param IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance\r
1774 @param BaseAddress - Serial port register group base address\r
1775 @param Offset - Offset in register group\r
1776 @param Data - data which is to be written to some serial port register\r
1777\r
1778**/\r
637ff819 1779VOID\r
1780IsaSerialWritePort (\r
1781 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1782 IN UINT16 BaseAddress,\r
1783 IN UINT32 Offset,\r
1784 IN UINT8 Data\r
1785 )\r
637ff819 1786{\r
1787 //\r
1788 // Use IsaIo to access IO\r
1789 //\r
1790 IsaIo->Io.Write (\r
1791 IsaIo,\r
1792 EfiIsaIoWidthUint8,\r
1793 BaseAddress + Offset,\r
1794 1,\r
1795 &Data\r
1796 );\r
1797}\r
1798\r