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