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