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