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