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