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