WinNtSerialIo.c revision af4a63857cd189964cc2c6b53b54483efaba78a3
1/**@file 2 3Copyright (c) 2006 - 2009, Intel Corporation 4All rights reserved. This program and the accompanying materials 5are licensed and made available under the terms and conditions of the BSD License 6which accompanies this distribution. The full text of the license may be found at 7http://opensource.org/licenses/bsd-license.php 8 9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12Module Name: 13 14 WinNtSerialIo.c 15 16Abstract: 17 18 Our DriverBinding member functions operate on the handles 19 created by the NT Bus driver. 20 21 Handle(1) - WinNtIo - DevicePath(1) 22 23 If a serial port is added to the system this driver creates a new handle. 24 The new handle is required, since the serial device must add an UART device 25 pathnode. 26 27 Handle(2) - SerialIo - DevicePath(1)\UART 28 29 The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1). 30 The instance data for this protocol is the private data used to create 31 Handle(2). 32 33 Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort 34 35 If the driver is unloaded Handle(2) is removed from the system and 36 gEfiWinNtSerialPortGuid is removed from Handle(1). 37 38 Note: Handle(1) is any handle created by the Win NT Bus driver that is passed 39 into the DriverBinding member functions of this driver. This driver requires 40 a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and 41 the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid. 42 43 If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is 44 loaded on the device. 45 46**/ 47 48#include "WinNtSerialIo.h" 49 50EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = { 51 WinNtSerialIoDriverBindingSupported, 52 WinNtSerialIoDriverBindingStart, 53 WinNtSerialIoDriverBindingStop, 54 0xa, 55 NULL, 56 NULL 57}; 58 59// 60// List of supported baud rate 61// 62UINT64 mBaudRateCurrentSupport[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE + 1}; 63 64/** 65 The user Entry Point for module WinNtSerialIo. The user code starts with this function. 66 67 @param[in] ImageHandle The firmware allocated handle for the EFI image. 68 @param[in] SystemTable A pointer to the EFI System Table. 69 70 @retval EFI_SUCCESS The entry point is executed successfully. 71 @retval other Some error occurs when executing this entry point. 72 73**/ 74EFI_STATUS 75EFIAPI 76InitializeWinNtSerialIo( 77 IN EFI_HANDLE ImageHandle, 78 IN EFI_SYSTEM_TABLE *SystemTable 79 ) 80{ 81 EFI_STATUS Status; 82 83 // 84 // Install driver model protocol(s). 85 // 86 Status = EfiLibInstallDriverBindingComponentName2 ( 87 ImageHandle, 88 SystemTable, 89 &gWinNtSerialIoDriverBinding, 90 ImageHandle, 91 &gWinNtSerialIoComponentName, 92 &gWinNtSerialIoComponentName2 93 ); 94 ASSERT_EFI_ERROR (Status); 95 96 97 return Status; 98} 99 100EFI_STATUS 101EFIAPI 102WinNtSerialIoDriverBindingSupported ( 103 IN EFI_DRIVER_BINDING_PROTOCOL *This, 104 IN EFI_HANDLE Handle, 105 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 106 ) 107/*++ 108 109Routine Description: 110 111Arguments: 112 113Returns: 114 115 None 116 117--*/ 118// TODO: This - add argument and description to function comment 119// TODO: Handle - add argument and description to function comment 120// TODO: RemainingDevicePath - add argument and description to function comment 121// TODO: EFI_SUCCESS - add return value to function comment 122// TODO: EFI_SUCCESS - add return value to function comment 123{ 124 EFI_STATUS Status; 125 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 126 EFI_WIN_NT_IO_PROTOCOL *WinNtIo; 127 UART_DEVICE_PATH *UartNode; 128 129 // 130 // Check RemainingDevicePath validation 131 // 132 if (RemainingDevicePath != NULL) { 133 // 134 // Check if RemainingDevicePath is the End of Device Path Node, 135 // if yes, go on checking other conditions 136 // 137 if (!IsDevicePathEnd (RemainingDevicePath)) { 138 // 139 // If RemainingDevicePath isn't the End of Device Path Node, 140 // check its validation 141 // 142 Status = EFI_UNSUPPORTED; 143 144 UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; 145 if (UartNode->Header.Type != MESSAGING_DEVICE_PATH || 146 UartNode->Header.SubType != MSG_UART_DP || 147 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) { 148 goto Error; 149 } 150 if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) { 151 goto Error; 152 } 153 if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) { 154 goto Error; 155 } 156 if (UartNode->DataBits < 5 || UartNode->DataBits > 8) { 157 goto Error; 158 } 159 if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) { 160 goto Error; 161 } 162 if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) { 163 goto Error; 164 } 165 if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) { 166 goto Error; 167 } 168 } 169 } 170 171 // 172 // Open the IO Abstraction(s) needed to perform the supported test 173 // 174 Status = gBS->OpenProtocol ( 175 Handle, 176 &gEfiWinNtIoProtocolGuid, 177 (VOID **) &WinNtIo, 178 This->DriverBindingHandle, 179 Handle, 180 EFI_OPEN_PROTOCOL_BY_DRIVER 181 ); 182 if (Status == EFI_ALREADY_STARTED) { 183 return EFI_SUCCESS; 184 } 185 186 if (EFI_ERROR (Status)) { 187 return Status; 188 } 189 190 // 191 // Close the I/O Abstraction(s) used to perform the supported test 192 // 193 gBS->CloseProtocol ( 194 Handle, 195 &gEfiWinNtIoProtocolGuid, 196 This->DriverBindingHandle, 197 Handle 198 ); 199 200 // 201 // Open the EFI Device Path protocol needed to perform the supported test 202 // 203 Status = gBS->OpenProtocol ( 204 Handle, 205 &gEfiDevicePathProtocolGuid, 206 (VOID **) &ParentDevicePath, 207 This->DriverBindingHandle, 208 Handle, 209 EFI_OPEN_PROTOCOL_BY_DRIVER 210 ); 211 if (Status == EFI_ALREADY_STARTED) { 212 return EFI_SUCCESS; 213 } 214 215 if (EFI_ERROR (Status)) { 216 return Status; 217 } 218 219 // 220 // Close protocol, don't use device path protocol in the Support() function 221 // 222 gBS->CloseProtocol ( 223 Handle, 224 &gEfiDevicePathProtocolGuid, 225 This->DriverBindingHandle, 226 Handle 227 ); 228 229 // 230 // Make sure that the WinNt Thunk Protocol is valid 231 // 232 if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { 233 Status = EFI_UNSUPPORTED; 234 goto Error; 235 } 236 237 // 238 // Check the GUID to see if this is a handle type the driver supports 239 // 240 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) { 241 Status = EFI_UNSUPPORTED; 242 goto Error; 243 } 244 245 return EFI_SUCCESS; 246 247Error: 248 return Status; 249} 250 251EFI_STATUS 252EFIAPI 253WinNtSerialIoDriverBindingStart ( 254 IN EFI_DRIVER_BINDING_PROTOCOL *This, 255 IN EFI_HANDLE Handle, 256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 257 ) 258/*++ 259 260Routine Description: 261 262Arguments: 263 264Returns: 265 266 None 267 268--*/ 269// TODO: This - add argument and description to function comment 270// TODO: Handle - add argument and description to function comment 271// TODO: RemainingDevicePath - add argument and description to function comment 272// TODO: EFI_SUCCESS - add return value to function comment 273// TODO: EFI_SUCCESS - add return value to function comment 274{ 275 EFI_STATUS Status; 276 EFI_WIN_NT_IO_PROTOCOL *WinNtIo; 277 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 278 HANDLE NtHandle; 279 UART_DEVICE_PATH Node; 280 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 281 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; 282 UINTN EntryCount; 283 UINTN Index; 284 EFI_SERIAL_IO_PROTOCOL *SerialIo; 285 UART_DEVICE_PATH *UartNode; 286 287 Private = NULL; 288 NtHandle = INVALID_HANDLE_VALUE; 289 290 // 291 // Grab the protocols we need 292 // 293 Status = gBS->OpenProtocol ( 294 Handle, 295 &gEfiDevicePathProtocolGuid, 296 (VOID **) &ParentDevicePath, 297 This->DriverBindingHandle, 298 Handle, 299 EFI_OPEN_PROTOCOL_BY_DRIVER 300 ); 301 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 302 return Status; 303 } 304 305 // 306 // Grab the IO abstraction we need to get any work done 307 // 308 Status = gBS->OpenProtocol ( 309 Handle, 310 &gEfiWinNtIoProtocolGuid, 311 (VOID **) &WinNtIo, 312 This->DriverBindingHandle, 313 Handle, 314 EFI_OPEN_PROTOCOL_BY_DRIVER 315 ); 316 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 317 gBS->CloseProtocol ( 318 Handle, 319 &gEfiDevicePathProtocolGuid, 320 This->DriverBindingHandle, 321 Handle 322 ); 323 return Status; 324 } 325 326 if (Status == EFI_ALREADY_STARTED) { 327 328 if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { 329 // 330 // If RemainingDevicePath is NULL or is the End of Device Path Node 331 // 332 return EFI_SUCCESS; 333 } 334 335 // 336 // Make sure a child handle does not already exist. This driver can only 337 // produce one child per serial port. 338 // 339 Status = gBS->OpenProtocolInformation ( 340 Handle, 341 &gEfiWinNtIoProtocolGuid, 342 &OpenInfoBuffer, 343 &EntryCount 344 ); 345 if (EFI_ERROR (Status)) { 346 return Status; 347 } 348 349 Status = EFI_ALREADY_STARTED; 350 for (Index = 0; Index < EntryCount; Index++) { 351 if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { 352 Status = gBS->OpenProtocol ( 353 OpenInfoBuffer[Index].ControllerHandle, 354 &gEfiSerialIoProtocolGuid, 355 (VOID **) &SerialIo, 356 This->DriverBindingHandle, 357 Handle, 358 EFI_OPEN_PROTOCOL_GET_PROTOCOL 359 ); 360 if (!EFI_ERROR (Status)) { 361 UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; 362 Status = SerialIo->SetAttributes ( 363 SerialIo, 364 UartNode->BaudRate, 365 SerialIo->Mode->ReceiveFifoDepth, 366 SerialIo->Mode->Timeout, 367 (EFI_PARITY_TYPE)UartNode->Parity, 368 UartNode->DataBits, 369 (EFI_STOP_BITS_TYPE)UartNode->StopBits 370 ); 371 } 372 break; 373 } 374 } 375 FreePool (OpenInfoBuffer); 376 377 if (Index < EntryCount) { 378 // 379 // If gEfiWinNtIoProtocolGuid is opened by one child device, return 380 // 381 return Status; 382 } 383 // 384 // If gEfiWinNtIoProtocolGuid is not opened by any child device, 385 // go further to create child device handle based on RemainingDevicePath 386 // 387 } 388 389 if (RemainingDevicePath == NULL) { 390 // 391 // Build the device path by appending the UART node to the ParentDevicePath 392 // from the WinNtIo handle. The Uart setings are zero here, since 393 // SetAttribute() will update them to match the default setings. 394 // 395 ZeroMem (&Node, sizeof (UART_DEVICE_PATH)); 396 Node.Header.Type = MESSAGING_DEVICE_PATH; 397 Node.Header.SubType = MSG_UART_DP; 398 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Node, sizeof (UART_DEVICE_PATH)); 399 400 } else if (!IsDevicePathEnd (RemainingDevicePath)) { 401 // 402 // If RemainingDevicePath isn't the End of Device Path Node, 403 // only scan the specified device by RemainingDevicePath 404 // 405 // 406 // Match the configuration of the RemainingDevicePath. IsHandleSupported() 407 // already checked to make sure the RemainingDevicePath contains settings 408 // that we can support. 409 // 410 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); 411 412 } else { 413 // 414 // If RemainingDevicePath is the End of Device Path Node, 415 // skip enumerate any device and return EFI_SUCESSS 416 // 417 return EFI_SUCCESS; 418 } 419 420 // 421 // Check to see if we can access the hardware device. If it's Open in NT we 422 // will not get access. 423 // 424 NtHandle = WinNtIo->WinNtThunk->CreateFile ( 425 WinNtIo->EnvString, 426 GENERIC_READ | GENERIC_WRITE, 427 0, 428 NULL, 429 OPEN_EXISTING, 430 0, 431 NULL 432 ); 433 if (NtHandle == INVALID_HANDLE_VALUE) { 434 Status = EFI_DEVICE_ERROR; 435 goto Error; 436 } 437 438 // 439 // Construct Private data 440 // 441 Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA)); 442 if (Private == NULL) { 443 goto Error; 444 } 445 446 // 447 // This signature must be valid before any member function is called 448 // 449 Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE; 450 Private->NtHandle = NtHandle; 451 Private->ControllerHandle = Handle; 452 Private->Handle = NULL; 453 Private->WinNtThunk = WinNtIo->WinNtThunk; 454 Private->ParentDevicePath = ParentDevicePath; 455 Private->ControllerNameTable = NULL; 456 457 Private->SoftwareLoopbackEnable = FALSE; 458 Private->HardwareLoopbackEnable = FALSE; 459 Private->HardwareFlowControl = FALSE; 460 Private->Fifo.First = 0; 461 Private->Fifo.Last = 0; 462 Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; 463 464 CopyMem (&Private->UartDevicePath, &Node, sizeof (UART_DEVICE_PATH)); 465 466 AddUnicodeString2 ( 467 "eng", 468 gWinNtSerialIoComponentName.SupportedLanguages, 469 &Private->ControllerNameTable, 470 WinNtIo->EnvString, 471 TRUE 472 ); 473 AddUnicodeString2 ( 474 "en", 475 gWinNtSerialIoComponentName2.SupportedLanguages, 476 &Private->ControllerNameTable, 477 WinNtIo->EnvString, 478 FALSE 479 ); 480 481 482 Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION; 483 Private->SerialIo.Reset = WinNtSerialIoReset; 484 Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes; 485 Private->SerialIo.SetControl = WinNtSerialIoSetControl; 486 Private->SerialIo.GetControl = WinNtSerialIoGetControl; 487 Private->SerialIo.Write = WinNtSerialIoWrite; 488 Private->SerialIo.Read = WinNtSerialIoRead; 489 Private->SerialIo.Mode = &Private->SerialIoMode; 490 491 // 492 // Build the device path by appending the UART node to the ParentDevicePath 493 // from the WinNtIo handle. The Uart setings are zero here, since 494 // SetAttribute() will update them to match the current setings. 495 // 496 Private->DevicePath = AppendDevicePathNode ( 497 ParentDevicePath, 498 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath 499 ); 500 if (Private->DevicePath == NULL) { 501 Status = EFI_OUT_OF_RESOURCES; 502 goto Error; 503 } 504 505 // 506 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. 507 // 508 Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK; 509 Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT; 510 Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate; 511 Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; 512 Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits; 513 Private->SerialIoMode.Parity = Private->UartDevicePath.Parity; 514 Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits; 515 516 // 517 // Issue a reset to initialize the COM port 518 // 519 Status = Private->SerialIo.Reset (&Private->SerialIo); 520 if (EFI_ERROR (Status)) { 521 goto Error; 522 } 523 524 // 525 // Create new child handle 526 // 527 Status = gBS->InstallMultipleProtocolInterfaces ( 528 &Private->Handle, 529 &gEfiSerialIoProtocolGuid, 530 &Private->SerialIo, 531 &gEfiDevicePathProtocolGuid, 532 Private->DevicePath, 533 NULL 534 ); 535 if (EFI_ERROR (Status)) { 536 goto Error; 537 } 538 539 // 540 // Open For Child Device 541 // 542 Status = gBS->OpenProtocol ( 543 Handle, 544 &gEfiWinNtIoProtocolGuid, 545 (VOID **) &WinNtIo, 546 This->DriverBindingHandle, 547 Private->Handle, 548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 549 ); 550 if (EFI_ERROR (Status)) { 551 goto Error; 552 } 553 554 return EFI_SUCCESS; 555 556Error: 557 // 558 // Use the Stop() function to free all resources allocated in Start() 559 // 560 if (Private != NULL) { 561 if (Private->Handle != NULL) { 562 This->Stop (This, Handle, 1, &Private->Handle); 563 } else { 564 if (NtHandle != INVALID_HANDLE_VALUE) { 565 Private->WinNtThunk->CloseHandle (NtHandle); 566 } 567 568 if (Private->DevicePath != NULL) { 569 FreePool (Private->DevicePath); 570 } 571 572 FreeUnicodeStringTable (Private->ControllerNameTable); 573 574 FreePool (Private); 575 } 576 } 577 578 This->Stop (This, Handle, 0, NULL); 579 580 return Status; 581} 582 583EFI_STATUS 584EFIAPI 585WinNtSerialIoDriverBindingStop ( 586 IN EFI_DRIVER_BINDING_PROTOCOL *This, 587 IN EFI_HANDLE Handle, 588 IN UINTN NumberOfChildren, 589 IN EFI_HANDLE *ChildHandleBuffer 590 ) 591/*++ 592 593Routine Description: 594 595 TODO: Add function description 596 597Arguments: 598 599 This - TODO: add argument description 600 Handle - TODO: add argument description 601 NumberOfChildren - TODO: add argument description 602 ChildHandleBuffer - TODO: add argument description 603 604Returns: 605 606 EFI_DEVICE_ERROR - TODO: Add description for return value 607 EFI_SUCCESS - TODO: Add description for return value 608 609--*/ 610{ 611 EFI_STATUS Status; 612 UINTN Index; 613 BOOLEAN AllChildrenStopped; 614 EFI_SERIAL_IO_PROTOCOL *SerialIo; 615 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 616 EFI_WIN_NT_IO_PROTOCOL *WinNtIo; 617 618 // 619 // Complete all outstanding transactions to Controller. 620 // Don't allow any new transaction to Controller to be started. 621 // 622 623 if (NumberOfChildren == 0) { 624 // 625 // Close the bus driver 626 // 627 Status = gBS->CloseProtocol ( 628 Handle, 629 &gEfiWinNtIoProtocolGuid, 630 This->DriverBindingHandle, 631 Handle 632 ); 633 Status = gBS->CloseProtocol ( 634 Handle, 635 &gEfiDevicePathProtocolGuid, 636 This->DriverBindingHandle, 637 Handle 638 ); 639 return Status; 640 } 641 642 AllChildrenStopped = TRUE; 643 644 for (Index = 0; Index < NumberOfChildren; Index++) { 645 Status = gBS->OpenProtocol ( 646 ChildHandleBuffer[Index], 647 &gEfiSerialIoProtocolGuid, 648 (VOID **) &SerialIo, 649 This->DriverBindingHandle, 650 Handle, 651 EFI_OPEN_PROTOCOL_GET_PROTOCOL 652 ); 653 if (!EFI_ERROR (Status)) { 654 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo); 655 656 ASSERT (Private->Handle == ChildHandleBuffer[Index]); 657 658 Status = gBS->CloseProtocol ( 659 Handle, 660 &gEfiWinNtIoProtocolGuid, 661 This->DriverBindingHandle, 662 ChildHandleBuffer[Index] 663 ); 664 665 Status = gBS->UninstallMultipleProtocolInterfaces ( 666 ChildHandleBuffer[Index], 667 &gEfiSerialIoProtocolGuid, 668 &Private->SerialIo, 669 &gEfiDevicePathProtocolGuid, 670 Private->DevicePath, 671 NULL 672 ); 673 674 if (EFI_ERROR (Status)) { 675 gBS->OpenProtocol ( 676 Handle, 677 &gEfiWinNtIoProtocolGuid, 678 (VOID **) &WinNtIo, 679 This->DriverBindingHandle, 680 ChildHandleBuffer[Index], 681 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 682 ); 683 } else { 684 Private->WinNtThunk->CloseHandle (Private->NtHandle); 685 686 FreePool (Private->DevicePath); 687 688 FreeUnicodeStringTable (Private->ControllerNameTable); 689 690 FreePool (Private); 691 } 692 } 693 694 if (EFI_ERROR (Status)) { 695 AllChildrenStopped = FALSE; 696 } 697 } 698 699 if (!AllChildrenStopped) { 700 return EFI_DEVICE_ERROR; 701 } 702 703 return EFI_SUCCESS; 704} 705 706// 707// Serial IO Protocol member functions 708// 709 710EFI_STATUS 711EFIAPI 712WinNtSerialIoReset ( 713 IN EFI_SERIAL_IO_PROTOCOL *This 714 ) 715/*++ 716 717Routine Description: 718 719 TODO: Add function description 720 721Arguments: 722 723 This - TODO: add argument description 724 725Returns: 726 727 TODO: add return values 728 729--*/ 730{ 731 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 732 EFI_TPL Tpl; 733 734 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 735 736 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 737 738 Private->WinNtThunk->PurgeComm ( 739 Private->NtHandle, 740 PURGE_TXCLEAR | PURGE_RXCLEAR 741 ); 742 743 gBS->RestoreTPL (Tpl); 744 745 return This->SetAttributes ( 746 This, 747 This->Mode->BaudRate, 748 This->Mode->ReceiveFifoDepth, 749 This->Mode->Timeout, 750 (EFI_PARITY_TYPE)This->Mode->Parity, 751 (UINT8) This->Mode->DataBits, 752 (EFI_STOP_BITS_TYPE)This->Mode->StopBits 753 ); 754} 755 756EFI_STATUS 757EFIAPI 758WinNtSerialIoSetAttributes ( 759 IN EFI_SERIAL_IO_PROTOCOL *This, 760 IN UINT64 BaudRate, 761 IN UINT32 ReceiveFifoDepth, 762 IN UINT32 Timeout, 763 IN EFI_PARITY_TYPE Parity, 764 IN UINT8 DataBits, 765 IN EFI_STOP_BITS_TYPE StopBits 766 ) 767/*++ 768 769Routine Description: 770 771 This function is used to set the attributes. 772 773Arguments: 774 775 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue. 776 BaudRate - The Baud rate of the serial device. 777 ReceiveFifoDepth - The request depth of fifo on receive side. 778 Timeout - the request timeout for a single charact. 779 Parity - The type of parity used in serial device. 780 DataBits - Number of deata bits used in serial device. 781 StopBits - Number of stop bits used in serial device. 782 783Returns: 784 Status code 785 786 None 787 788--*/ 789// TODO: EFI_SUCCESS - add return value to function comment 790// TODO: EFI_DEVICE_ERROR - add return value to function comment 791// TODO: EFI_DEVICE_ERROR - add return value to function comment 792// TODO: EFI_DEVICE_ERROR - add return value to function comment 793// TODO: EFI_SUCCESS - add return value to function comment 794// TODO: EFI_DEVICE_ERROR - add return value to function comment 795// TODO: EFI_SUCCESS - add return value to function comment 796{ 797 EFI_STATUS Status; 798 UINTN Index; 799 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 800 COMMTIMEOUTS PortTimeOuts; 801 DWORD ConvertedTime; 802 BOOL Result; 803 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; 804 EFI_TPL Tpl; 805 806 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 807 808 // 809 // Some of our arguments have defaults if a null value is passed in, and 810 // we must set the default values if a null argument is passed in. 811 // 812 if (BaudRate == 0) { 813 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate); 814 } 815 816 if (ReceiveFifoDepth == 0) { 817 ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; 818 } 819 820 if (Timeout == 0) { 821 Timeout = SERIAL_TIMEOUT_DEFAULT; 822 } 823 824 if (Parity == DefaultParity) { 825 Parity = (EFI_PARITY_TYPE) (FixedPcdGet8 (PcdUartDefaultParity)); 826 } 827 828 if (DataBits == 0) { 829 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); 830 } 831 832 if (StopBits == DefaultStopBits) { 833 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits); 834 } 835 836 // 837 // Make sure all parameters are valid 838 // 839 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) { 840 return EFI_INVALID_PARAMETER; 841 } 842 843 // 844 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter 845 // 846 847 for (Index = 1; Index < (sizeof (mBaudRateCurrentSupport) / sizeof (mBaudRateCurrentSupport[0])); Index++) { 848 if (BaudRate < mBaudRateCurrentSupport[Index]) { 849 BaudRate = mBaudRateCurrentSupport[Index-1]; 850 break; 851 } 852 } 853 854 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) { 855 return EFI_INVALID_PARAMETER; 856 } 857 858 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) { 859 return EFI_INVALID_PARAMETER; 860 } 861 862 if ((Parity < NoParity) || (Parity > SpaceParity)) { 863 return EFI_INVALID_PARAMETER; 864 } 865 866 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) { 867 return EFI_INVALID_PARAMETER; 868 } 869 870 // 871 // Now we only support DataBits=7,8. 872 // 873 if ((DataBits < 7) || (DataBits > 8)) { 874 return EFI_INVALID_PARAMETER; 875 } 876 877 // 878 // Now we only support DataBits=7,8. 879 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits. 880 // 881 if (StopBits == OneFiveStopBits) { 882 return EFI_INVALID_PARAMETER; 883 } 884 885 // 886 // See if the new attributes already match the current attributes 887 // 888 if (Private->UartDevicePath.BaudRate == BaudRate && 889 Private->UartDevicePath.DataBits == DataBits && 890 Private->UartDevicePath.Parity == Parity && 891 Private->UartDevicePath.StopBits == StopBits && 892 Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth && 893 Private->SerialIoMode.Timeout == Timeout ) { 894 return EFI_SUCCESS; 895 } 896 897 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 898 899 // 900 // Get current values from NT 901 // 902 ZeroMem (&Private->NtDCB, sizeof (DCB)); 903 Private->NtDCB.DCBlength = sizeof (DCB); 904 905 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) { 906 Private->NtError = Private->WinNtThunk->GetLastError (); 907 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError)); 908 gBS->RestoreTPL (Tpl); 909 return EFI_DEVICE_ERROR; 910 } 911 912 // 913 // Map EFI com setting to NT 914 // 915 Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate); 916 Private->NtDCB.ByteSize = ConvertData2Nt (DataBits); 917 Private->NtDCB.Parity = ConvertParity2Nt (Parity); 918 Private->NtDCB.StopBits = ConvertStop2Nt (StopBits); 919 920 Private->NtDCB.fBinary = TRUE; 921 Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE; 922 Private->NtDCB.fOutxCtsFlow = FALSE; 923 Private->NtDCB.fOutxDsrFlow = FALSE; 924 Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE; 925 Private->NtDCB.fDsrSensitivity = FALSE; 926 Private->NtDCB.fOutX = FALSE; 927 Private->NtDCB.fInX = FALSE; 928 Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE; 929 Private->NtDCB.fNull = FALSE; 930 931 // 932 // Set new values 933 // 934 Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB); 935 if (!Result) { 936 Private->NtError = Private->WinNtThunk->GetLastError (); 937 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError)); 938 gBS->RestoreTPL (Tpl); 939 return EFI_DEVICE_ERROR; 940 } 941 942 // 943 // Set com port read/write timeout values 944 // 945 ConvertedTime = ConvertTime2Nt (Timeout); 946 PortTimeOuts.ReadIntervalTimeout = MAXDWORD; 947 PortTimeOuts.ReadTotalTimeoutMultiplier = 0; 948 PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime; 949 PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime; 950 PortTimeOuts.WriteTotalTimeoutConstant = 0; 951 952 if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) { 953 Private->NtError = Private->WinNtThunk->GetLastError (); 954 DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError)); 955 gBS->RestoreTPL (Tpl); 956 return EFI_DEVICE_ERROR; 957 } 958 959 // 960 // Update mode 961 // 962 Private->SerialIoMode.BaudRate = BaudRate; 963 Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth; 964 Private->SerialIoMode.Timeout = Timeout; 965 Private->SerialIoMode.Parity = Parity; 966 Private->SerialIoMode.DataBits = DataBits; 967 Private->SerialIoMode.StopBits = StopBits; 968 969 // 970 // See if Device Path Node has actually changed 971 // 972 if (Private->UartDevicePath.BaudRate == BaudRate && 973 Private->UartDevicePath.DataBits == DataBits && 974 Private->UartDevicePath.Parity == Parity && 975 Private->UartDevicePath.StopBits == StopBits ) { 976 gBS->RestoreTPL(Tpl); 977 return EFI_SUCCESS; 978 } 979 980 // 981 // Update the device path 982 // 983 Private->UartDevicePath.BaudRate = BaudRate; 984 Private->UartDevicePath.DataBits = DataBits; 985 Private->UartDevicePath.Parity = (UINT8) Parity; 986 Private->UartDevicePath.StopBits = (UINT8) StopBits; 987 988 NewDevicePath = AppendDevicePathNode ( 989 Private->ParentDevicePath, 990 (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath 991 ); 992 if (NewDevicePath == NULL) { 993 gBS->RestoreTPL (Tpl); 994 return EFI_DEVICE_ERROR; 995 } 996 997 if (Private->Handle != NULL) { 998 Status = gBS->ReinstallProtocolInterface ( 999 Private->Handle, 1000 &gEfiDevicePathProtocolGuid, 1001 Private->DevicePath, 1002 NewDevicePath 1003 ); 1004 if (EFI_ERROR (Status)) { 1005 gBS->RestoreTPL (Tpl); 1006 return Status; 1007 } 1008 } 1009 1010 if (Private->DevicePath != NULL) { 1011 FreePool (Private->DevicePath); 1012 } 1013 1014 Private->DevicePath = NewDevicePath; 1015 1016 gBS->RestoreTPL (Tpl); 1017 1018 return EFI_SUCCESS; 1019} 1020 1021EFI_STATUS 1022EFIAPI 1023WinNtSerialIoSetControl ( 1024 IN EFI_SERIAL_IO_PROTOCOL *This, 1025 IN UINT32 Control 1026 ) 1027/*++ 1028 1029Routine Description: 1030 1031 TODO: Add function description 1032 1033Arguments: 1034 1035 This - TODO: add argument description 1036 Control - TODO: add argument description 1037 1038Returns: 1039 1040 EFI_DEVICE_ERROR - TODO: Add description for return value 1041 EFI_DEVICE_ERROR - TODO: Add description for return value 1042 EFI_SUCCESS - TODO: Add description for return value 1043 1044--*/ 1045{ 1046 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 1047 BOOL Result; 1048 DCB Dcb; 1049 EFI_TPL Tpl; 1050 1051 // 1052 // first determine the parameter is invalid 1053 // 1054 if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | 1055 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | 1056 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) { 1057 return EFI_UNSUPPORTED; 1058 } 1059 1060 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 1061 1062 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 1063 1064 Result = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb); 1065 1066 if (!Result) { 1067 Private->NtError = Private->WinNtThunk->GetLastError (); 1068 DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError)); 1069 gBS->RestoreTPL (Tpl); 1070 return EFI_DEVICE_ERROR; 1071 } 1072 1073 Dcb.fRtsControl = RTS_CONTROL_DISABLE; 1074 Dcb.fDtrControl = DTR_CONTROL_DISABLE; 1075 Private->HardwareFlowControl = FALSE; 1076 Private->SoftwareLoopbackEnable = FALSE; 1077 Private->HardwareLoopbackEnable = FALSE; 1078 1079 if (Control & EFI_SERIAL_REQUEST_TO_SEND) { 1080 Dcb.fRtsControl = RTS_CONTROL_ENABLE; 1081 } 1082 1083 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) { 1084 Dcb.fDtrControl = DTR_CONTROL_ENABLE; 1085 } 1086 1087 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) { 1088 Private->HardwareFlowControl = TRUE; 1089 } 1090 1091 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) { 1092 Private->SoftwareLoopbackEnable = TRUE; 1093 } 1094 1095 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) { 1096 Private->HardwareLoopbackEnable = TRUE; 1097 } 1098 1099 Result = Private->WinNtThunk->SetCommState ( 1100 Private->NtHandle, 1101 &Dcb 1102 ); 1103 1104 if (!Result) { 1105 Private->NtError = Private->WinNtThunk->GetLastError (); 1106 DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError)); 1107 gBS->RestoreTPL (Tpl); 1108 return EFI_DEVICE_ERROR; 1109 } 1110 1111 gBS->RestoreTPL (Tpl); 1112 1113 return EFI_SUCCESS; 1114} 1115 1116EFI_STATUS 1117EFIAPI 1118WinNtSerialIoGetControl ( 1119 IN EFI_SERIAL_IO_PROTOCOL *This, 1120 OUT UINT32 *Control 1121 ) 1122/*++ 1123 1124Routine Description: 1125 1126 TODO: Add function description 1127 1128Arguments: 1129 1130 This - TODO: add argument description 1131 Control - TODO: add argument description 1132 1133Returns: 1134 1135 EFI_DEVICE_ERROR - TODO: Add description for return value 1136 EFI_DEVICE_ERROR - TODO: Add description for return value 1137 EFI_DEVICE_ERROR - TODO: Add description for return value 1138 EFI_SUCCESS - TODO: Add description for return value 1139 1140--*/ 1141{ 1142 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 1143 DWORD ModemStatus; 1144 DWORD Errors; 1145 UINT32 Bits; 1146 DCB Dcb; 1147 EFI_TPL Tpl; 1148 1149 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 1150 1151 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 1152 1153 // 1154 // Get modem status 1155 // 1156 if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) { 1157 Private->NtError = Private->WinNtThunk->GetLastError (); 1158 gBS->RestoreTPL (Tpl); 1159 return EFI_DEVICE_ERROR; 1160 } 1161 1162 Bits = 0; 1163 if (ModemStatus & MS_CTS_ON) { 1164 Bits |= EFI_SERIAL_CLEAR_TO_SEND; 1165 } 1166 1167 if (ModemStatus & MS_DSR_ON) { 1168 Bits |= EFI_SERIAL_DATA_SET_READY; 1169 } 1170 1171 if (ModemStatus & MS_RING_ON) { 1172 Bits |= EFI_SERIAL_RING_INDICATE; 1173 } 1174 1175 if (ModemStatus & MS_RLSD_ON) { 1176 Bits |= EFI_SERIAL_CARRIER_DETECT; 1177 } 1178 1179 // 1180 // Get ctrl status 1181 // 1182 if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) { 1183 Private->NtError = Private->WinNtThunk->GetLastError (); 1184 DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError)); 1185 gBS->RestoreTPL (Tpl); 1186 return EFI_DEVICE_ERROR; 1187 } 1188 1189 if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) { 1190 Bits |= EFI_SERIAL_DATA_TERMINAL_READY; 1191 } 1192 1193 if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) { 1194 Bits |= EFI_SERIAL_REQUEST_TO_SEND; 1195 } 1196 1197 if (Private->HardwareFlowControl) { 1198 Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; 1199 } 1200 1201 if (Private->SoftwareLoopbackEnable) { 1202 Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; 1203 } 1204 1205 if (Private->HardwareLoopbackEnable) { 1206 Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE; 1207 } 1208 1209 // 1210 // Get input buffer status 1211 // 1212 if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) { 1213 Private->NtError = Private->WinNtThunk->GetLastError (); 1214 DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError)); 1215 gBS->RestoreTPL (Tpl); 1216 return EFI_DEVICE_ERROR; 1217 } 1218 1219 if (Private->NtComStatus.cbInQue == 0) { 1220 Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY; 1221 } 1222 1223 *Control = Bits; 1224 1225 gBS->RestoreTPL (Tpl); 1226 1227 return EFI_SUCCESS; 1228} 1229 1230EFI_STATUS 1231EFIAPI 1232WinNtSerialIoWrite ( 1233 IN EFI_SERIAL_IO_PROTOCOL *This, 1234 IN OUT UINTN *BufferSize, 1235 IN VOID *Buffer 1236 ) 1237/*++ 1238 1239Routine Description: 1240 1241 TODO: Add function description 1242 1243Arguments: 1244 1245 This - TODO: add argument description 1246 BufferSize - TODO: add argument description 1247 Buffer - TODO: add argument description 1248 1249Returns: 1250 1251 EFI_DEVICE_ERROR - TODO: Add description for return value 1252 EFI_SUCCESS - TODO: Add description for return value 1253 1254--*/ 1255{ 1256 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 1257 UINT8 *ByteBuffer; 1258 UINTN TotalBytesWritten; 1259 DWORD BytesToGo; 1260 DWORD BytesWritten; 1261 BOOL Result; 1262 UINT32 Index; 1263 UINT32 Control; 1264 EFI_TPL Tpl; 1265 1266 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 1267 1268 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 1269 1270 ByteBuffer = (UINT8 *) Buffer; 1271 TotalBytesWritten = 0; 1272 1273 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) { 1274 for (Index = 0; Index < *BufferSize; Index++) { 1275 if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) { 1276 TotalBytesWritten++; 1277 } else { 1278 break; 1279 } 1280 } 1281 } else { 1282 BytesToGo = (DWORD) (*BufferSize); 1283 1284 do { 1285 if (Private->HardwareFlowControl) { 1286 // 1287 // Send RTS 1288 // 1289 WinNtSerialIoGetControl (&Private->SerialIo, &Control); 1290 Control |= EFI_SERIAL_REQUEST_TO_SEND; 1291 WinNtSerialIoSetControl (&Private->SerialIo, Control); 1292 } 1293 1294 // 1295 // Do the write 1296 // 1297 Result = Private->WinNtThunk->WriteFile ( 1298 Private->NtHandle, 1299 &ByteBuffer[TotalBytesWritten], 1300 BytesToGo, 1301 &BytesWritten, 1302 NULL 1303 ); 1304 1305 if (Private->HardwareFlowControl) { 1306 // 1307 // Assert RTS 1308 // 1309 WinNtSerialIoGetControl (&Private->SerialIo, &Control); 1310 Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND; 1311 WinNtSerialIoSetControl (&Private->SerialIo, Control); 1312 } 1313 1314 TotalBytesWritten += BytesWritten; 1315 BytesToGo -= BytesWritten; 1316 if (!Result) { 1317 Private->NtError = Private->WinNtThunk->GetLastError (); 1318 DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError)); 1319 *BufferSize = TotalBytesWritten; 1320 gBS->RestoreTPL (Tpl); 1321 return EFI_DEVICE_ERROR; 1322 } 1323 } while (BytesToGo > 0); 1324 } 1325 1326 *BufferSize = TotalBytesWritten; 1327 1328 gBS->RestoreTPL (Tpl); 1329 1330 return EFI_SUCCESS; 1331} 1332 1333EFI_STATUS 1334EFIAPI 1335WinNtSerialIoRead ( 1336 IN EFI_SERIAL_IO_PROTOCOL *This, 1337 IN OUT UINTN *BufferSize, 1338 OUT VOID *Buffer 1339 ) 1340/*++ 1341 1342Routine Description: 1343 1344 TODO: Add function description 1345 1346Arguments: 1347 1348 This - TODO: add argument description 1349 BufferSize - TODO: add argument description 1350 Buffer - TODO: add argument description 1351 1352Returns: 1353 1354 EFI_DEVICE_ERROR - TODO: Add description for return value 1355 1356--*/ 1357{ 1358 WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; 1359 BOOL Result; 1360 DWORD BytesRead; 1361 EFI_STATUS Status; 1362 UINT32 Index; 1363 UINT8 Data; 1364 UINT32 Control; 1365 EFI_TPL Tpl; 1366 1367 Tpl = gBS->RaiseTPL (TPL_NOTIFY); 1368 1369 Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); 1370 1371 // 1372 // Do the read 1373 // 1374 if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) { 1375 for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) { 1376 if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) { 1377 ((UINT8 *) Buffer)[Index] = Data; 1378 BytesRead++; 1379 } else { 1380 break; 1381 } 1382 } 1383 } else { 1384 if (Private->HardwareFlowControl) { 1385 WinNtSerialIoGetControl (&Private->SerialIo, &Control); 1386 Control |= EFI_SERIAL_DATA_TERMINAL_READY; 1387 WinNtSerialIoSetControl (&Private->SerialIo, Control); 1388 } 1389 1390 Result = Private->WinNtThunk->ReadFile ( 1391 Private->NtHandle, 1392 Buffer, 1393 (DWORD) *BufferSize, 1394 &BytesRead, 1395 NULL 1396 ); 1397 1398 if (Private->HardwareFlowControl) { 1399 WinNtSerialIoGetControl (&Private->SerialIo, &Control); 1400 Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY; 1401 WinNtSerialIoSetControl (&Private->SerialIo, Control); 1402 } 1403 1404 if (!Result) { 1405 Private->NtError = Private->WinNtThunk->GetLastError (); 1406 gBS->RestoreTPL (Tpl); 1407 return EFI_DEVICE_ERROR; 1408 } 1409 } 1410 1411 if (BytesRead != *BufferSize) { 1412 Status = EFI_TIMEOUT; 1413 } else { 1414 Status = EFI_SUCCESS; 1415 } 1416 1417 *BufferSize = (UINTN) BytesRead; 1418 1419 gBS->RestoreTPL (Tpl); 1420 1421 return Status; 1422} 1423 1424BOOLEAN 1425IsaSerialFifoFull ( 1426 IN SERIAL_DEV_FIFO *Fifo 1427 ) 1428/*++ 1429 1430 Routine Description: 1431 Detect whether specific FIFO is full or not 1432 1433 Arguments: 1434 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO 1435 1436 Returns: 1437 TRUE: the FIFO is full 1438 FALSE: the FIFO is not full 1439 1440--*/ 1441{ 1442 if (Fifo->Surplus == 0) { 1443 return TRUE; 1444 } 1445 1446 return FALSE; 1447} 1448 1449BOOLEAN 1450IsaSerialFifoEmpty ( 1451 IN SERIAL_DEV_FIFO *Fifo 1452 ) 1453/*++ 1454 1455 Routine Description: 1456 Detect whether specific FIFO is empty or not 1457 1458 Arguments: 1459 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO 1460 1461 Returns: 1462 TRUE: the FIFO is empty 1463 FALSE: the FIFO is not empty 1464 1465--*/ 1466{ 1467 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) { 1468 return TRUE; 1469 } 1470 1471 return FALSE; 1472} 1473 1474EFI_STATUS 1475IsaSerialFifoAdd ( 1476 IN SERIAL_DEV_FIFO *Fifo, 1477 IN UINT8 Data 1478 ) 1479/*++ 1480 1481 Routine Description: 1482 Add data to specific FIFO 1483 1484 Arguments: 1485 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO 1486 Data UINT8: the data added to FIFO 1487 1488 Returns: 1489 EFI_SUCCESS: Add data to specific FIFO successfully 1490 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full 1491 1492--*/ 1493// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment 1494{ 1495 // 1496 // if FIFO full can not add data 1497 // 1498 if (IsaSerialFifoFull (Fifo)) { 1499 return EFI_OUT_OF_RESOURCES; 1500 } 1501 1502 // 1503 // FIFO is not full can add data 1504 // 1505 Fifo->Data[Fifo->Last] = Data; 1506 Fifo->Surplus--; 1507 Fifo->Last++; 1508 if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) { 1509 Fifo->Last = 0; 1510 } 1511 1512 return EFI_SUCCESS; 1513} 1514 1515EFI_STATUS 1516IsaSerialFifoRemove ( 1517 IN SERIAL_DEV_FIFO *Fifo, 1518 OUT UINT8 *Data 1519 ) 1520/*++ 1521 1522 Routine Description: 1523 Remove data from specific FIFO 1524 1525 Arguments: 1526 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO 1527 Data UINT8*: the data removed from FIFO 1528 1529 Returns: 1530 EFI_SUCCESS: Remove data from specific FIFO successfully 1531 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty 1532 1533--*/ 1534// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment 1535{ 1536 // 1537 // if FIFO is empty, no data can remove 1538 // 1539 if (IsaSerialFifoEmpty (Fifo)) { 1540 return EFI_OUT_OF_RESOURCES; 1541 } 1542 1543 // 1544 // FIFO is not empty, can remove data 1545 // 1546 *Data = Fifo->Data[Fifo->First]; 1547 Fifo->Surplus++; 1548 Fifo->First++; 1549 if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) { 1550 Fifo->First = 0; 1551 } 1552 1553 return EFI_SUCCESS; 1554} 1555