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