1 /** @file
2   Serial driver for standard UARTS on an ISA bus.
3 
4 Copyright (c) 2006 - 2015, 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
IsUartFlowControlNode(IN UART_FLOW_CONTROL_DEVICE_PATH * FlowControl)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
ContainsFlowControl(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
InitializeIsaSerial(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
SerialControllerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
SerialControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
SerialControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
IsaSerialFifoFull(IN SERIAL_DEV_FIFO * Fifo)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
IsaSerialFifoEmpty(IN SERIAL_DEV_FIFO * Fifo)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
IsaSerialFifoAdd(IN SERIAL_DEV_FIFO * Fifo,IN UINT8 Data)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
IsaSerialFifoRemove(IN SERIAL_DEV_FIFO * Fifo,OUT UINT8 * Data)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
IsaSerialReceiveTransmit(IN SERIAL_DEV * SerialDevice)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
IsaSerialReset(IN EFI_SERIAL_IO_PROTOCOL * This)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
IsaSerialSetAttributes(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT64 BaudRate,IN UINT32 ReceiveFifoDepth,IN UINT32 Timeout,IN EFI_PARITY_TYPE Parity,IN UINT8 DataBits,IN EFI_STOP_BITS_TYPE StopBits)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                        PcdGet32 (PcdSerialClockRate),
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 = PcdGet32 (PcdSerialClockRate) / 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
IsaSerialSetControl(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT32 Control)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
IsaSerialGetControl(IN EFI_SERIAL_IO_PROTOCOL * This,OUT UINT32 * Control)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
IsaSerialWrite(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)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
IsaSerialRead(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)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
IsaSerialPortPresent(IN SERIAL_DEV * SerialDevice)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
IsaSerialReadPort(IN EFI_ISA_IO_PROTOCOL * IsaIo,IN UINT16 BaseAddress,IN UINT32 Offset)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
IsaSerialWritePort(IN EFI_ISA_IO_PROTOCOL * IsaIo,IN UINT16 BaseAddress,IN UINT32 Offset,IN UINT8 Data)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 
2039