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