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