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