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