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 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 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 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 2039