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