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