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