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