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
IsUartFlowControlNode(IN UART_FLOW_CONTROL_DEVICE_PATH * FlowControl)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
ContainsFlowControl(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
InitializeWinNtSerialIo(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
WinNtSerialIoDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
WinNtSerialIoDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
WinNtSerialIoDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Handle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
WinNtSerialIoReset(IN EFI_SERIAL_IO_PROTOCOL * This)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
WinNtSerialIoSetAttributes(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT64 BaudRate,IN UINT32 ReceiveFifoDepth,IN UINT32 Timeout,IN EFI_PARITY_TYPE Parity,IN UINT8 DataBits,IN EFI_STOP_BITS_TYPE StopBits)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 < (sizeof (mBaudRateCurrentSupport) / sizeof (mBaudRateCurrentSupport[0])); 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
WinNtSerialIoSetControl(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT32 Control)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
WinNtSerialIoGetControl(IN EFI_SERIAL_IO_PROTOCOL * This,OUT UINT32 * Control)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
WinNtSerialIoWrite(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)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
WinNtSerialIoRead(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)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
IsaSerialFifoFull(IN SERIAL_DEV_FIFO * Fifo)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
IsaSerialFifoEmpty(IN SERIAL_DEV_FIFO * Fifo)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
IsaSerialFifoAdd(IN SERIAL_DEV_FIFO * Fifo,IN UINT8 Data)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
IsaSerialFifoRemove(IN SERIAL_DEV_FIFO * Fifo,OUT UINT8 * Data)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