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