]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
Update Copyright header of IsaFloppyPei.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaSerialDxe / Serial.c
CommitLineData
637ff819 1/**@file\r
2 Serial driver for standard UARTS on an ISA bus.\r
3\r
4Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>\r
5This software and associated documentation (if any) is furnished\r
6under a license and may only be used or copied in accordance\r
7with the terms of the license. Except as permitted by such\r
8license, no part of this software or documentation may be\r
9reproduced, stored in a retrieval system, or transmitted in any\r
10form or by any means without the express written consent of\r
11Intel Corporation.\r
12\r
13**/\r
14\r
15#include "Serial.h"\r
16\r
17//\r
18// ISA Serial Driver Global Variables\r
19//\r
20EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {\r
21 SerialControllerDriverSupported,\r
22 SerialControllerDriverStart,\r
23 SerialControllerDriverStop,\r
24 0xa,\r
25 NULL,\r
26 NULL\r
27};\r
28\r
29\r
30/**\r
31 The user Entry Point for module IsaSerial. The user code starts with this function.\r
32\r
33 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
34 @param[in] SystemTable A pointer to the EFI System Table.\r
35 \r
36 @retval EFI_SUCCESS The entry point is executed successfully.\r
37 @retval other Some error occurs when executing this entry point.\r
38\r
39**/\r
40EFI_STATUS\r
41EFIAPI\r
42InitializeIsaSerial(\r
43 IN EFI_HANDLE ImageHandle,\r
44 IN EFI_SYSTEM_TABLE *SystemTable\r
45 )\r
46{\r
47 EFI_STATUS Status;\r
48\r
49 //\r
50 // Install driver model protocol(s).\r
51 //\r
52 Status = EfiLibInstallAllDriverProtocols (\r
53 ImageHandle,\r
54 SystemTable,\r
55 &gSerialControllerDriver,\r
56 ImageHandle,\r
57 &gIsaSerialComponentName,\r
58 NULL,\r
59 NULL\r
60 );\r
61 ASSERT_EFI_ERROR (Status);\r
62\r
63\r
64 return Status;\r
65}\r
66\r
67\r
68EFI_STATUS\r
69EFIAPI\r
70SerialControllerDriverSupported (\r
71 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
72 IN EFI_HANDLE Controller,\r
73 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
74 )\r
75/*++\r
76\r
77 Routine Description:\r
78\r
79 Check to see if this driver supports the given controller\r
80\r
81 Arguments:\r
82\r
83 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
84 Controller - The handle of the controller to test.\r
85 RemainingDevicePath - A pointer to the remaining portion of a device path.\r
86\r
87 Returns:\r
88\r
89 EFI_SUCCESS - This driver can support the given controller\r
90\r
91--*/\r
92{\r
93 EFI_STATUS Status;\r
94 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
95 EFI_ISA_IO_PROTOCOL *IsaIo;\r
96 UART_DEVICE_PATH UartNode;\r
97\r
98 //\r
99 // Ignore the RemainingDevicePath\r
100 //\r
101 //\r
102 // Open the IO Abstraction(s) needed to perform the supported test\r
103 //\r
104 Status = gBS->OpenProtocol (\r
105 Controller,\r
106 &gEfiDevicePathProtocolGuid,\r
107 (VOID **) &ParentDevicePath,\r
108 This->DriverBindingHandle,\r
109 Controller,\r
110 EFI_OPEN_PROTOCOL_BY_DRIVER\r
111 );\r
112 if (Status == EFI_ALREADY_STARTED) {\r
113 return EFI_SUCCESS;\r
114 }\r
115\r
116 if (EFI_ERROR (Status)) {\r
117 return Status;\r
118 }\r
119\r
120 gBS->CloseProtocol (\r
121 Controller,\r
122 &gEfiDevicePathProtocolGuid,\r
123 This->DriverBindingHandle,\r
124 Controller\r
125 );\r
126\r
127 Status = gBS->OpenProtocol (\r
128 Controller,\r
129 &gEfiIsaIoProtocolGuid,\r
130 (VOID **) &IsaIo,\r
131 This->DriverBindingHandle,\r
132 Controller,\r
133 EFI_OPEN_PROTOCOL_BY_DRIVER\r
134 );\r
135\r
136 if (Status == EFI_ALREADY_STARTED) {\r
137 return EFI_SUCCESS;\r
138 }\r
139\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
143 //\r
144 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that\r
145 // can be managed by this driver.\r
146 //\r
147 Status = EFI_SUCCESS;\r
148 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) {\r
149 Status = EFI_UNSUPPORTED;\r
150 goto Error;\r
151 }\r
152 //\r
153 // Make sure RemainingDevicePath is valid\r
154 //\r
155 if (RemainingDevicePath != NULL) {\r
156 Status = EFI_UNSUPPORTED;\r
157 CopyMem (\r
158 &UartNode,\r
159 (UART_DEVICE_PATH *) RemainingDevicePath,\r
160 sizeof (UART_DEVICE_PATH)\r
161 );\r
162 if (UartNode.Header.Type != MESSAGING_DEVICE_PATH ||\r
163 UartNode.Header.SubType != MSG_UART_DP ||\r
164 sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode)\r
165 ) {\r
166 goto Error;\r
167 }\r
168\r
169 if (UartNode.BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {\r
170 goto Error;\r
171 }\r
172\r
173 if (UartNode.Parity < NoParity || UartNode.Parity > SpaceParity) {\r
174 goto Error;\r
175 }\r
176\r
177 if (UartNode.DataBits < 5 || UartNode.DataBits > 8) {\r
178 goto Error;\r
179 }\r
180\r
181 if (UartNode.StopBits < OneStopBit || UartNode.StopBits > TwoStopBits) {\r
182 goto Error;\r
183 }\r
184\r
185 if ((UartNode.DataBits == 5) && (UartNode.StopBits == TwoStopBits)) {\r
186 goto Error;\r
187 }\r
188\r
189 if ((UartNode.DataBits >= 6) && (UartNode.DataBits <= 8) && (UartNode.StopBits == OneFiveStopBits)) {\r
190 goto Error;\r
191 }\r
192\r
193 Status = EFI_SUCCESS;\r
194 }\r
195\r
196Error:\r
197 //\r
198 // Close the I/O Abstraction(s) used to perform the supported test\r
199 //\r
200 gBS->CloseProtocol (\r
201 Controller,\r
202 &gEfiIsaIoProtocolGuid,\r
203 This->DriverBindingHandle,\r
204 Controller\r
205 );\r
206\r
207 return Status;\r
208}\r
209\r
210EFI_STATUS\r
211EFIAPI\r
212SerialControllerDriverStart (\r
213 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
214 IN EFI_HANDLE Controller,\r
215 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
216 )\r
217/*++\r
218\r
219 Routine Description:\r
220\r
221 Start to management the controller passed in\r
222\r
223 Arguments:\r
224\r
225 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
226 Controller - The handle of the controller to test.\r
227 RemainingDevicePath - A pointer to the remaining portion of a device path.\r
228\r
229 Returns:\r
230\r
231 EFI_SUCCESS - Driver is started successfully\r
232\r
233--*/\r
234{\r
235 EFI_STATUS Status;\r
236 EFI_ISA_IO_PROTOCOL *IsaIo;\r
237 SERIAL_DEV *SerialDevice;\r
238 UINTN Index;\r
239 UART_DEVICE_PATH Node;\r
240 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
241 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
242 UINTN EntryCount;\r
243 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
244\r
245 SerialDevice = NULL;\r
246 //\r
247 // Get the Parent Device Path\r
248 //\r
249 Status = gBS->OpenProtocol (\r
250 Controller,\r
251 &gEfiDevicePathProtocolGuid,\r
252 (VOID **) &ParentDevicePath,\r
253 This->DriverBindingHandle,\r
254 Controller,\r
255 EFI_OPEN_PROTOCOL_BY_DRIVER\r
256 );\r
257 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
258 return Status;\r
259 }\r
260 //\r
261 // Report status code enable the serial\r
262 //\r
263 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
264 EFI_PROGRESS_CODE,\r
265 EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,\r
266 ParentDevicePath\r
267 );\r
268\r
269 //\r
270 // Grab the IO abstraction we need to get any work done\r
271 //\r
272 Status = gBS->OpenProtocol (\r
273 Controller,\r
274 &gEfiIsaIoProtocolGuid,\r
275 (VOID **) &IsaIo,\r
276 This->DriverBindingHandle,\r
277 Controller,\r
278 EFI_OPEN_PROTOCOL_BY_DRIVER\r
279 );\r
280 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
281 goto Error;\r
282 }\r
283\r
284 if (Status == EFI_ALREADY_STARTED) {\r
285\r
286 if (RemainingDevicePath == NULL) {\r
287 return EFI_SUCCESS;\r
288 }\r
289 //\r
290 // Make sure a child handle does not already exist. This driver can only\r
291 // produce one child per serial port.\r
292 //\r
293 Status = gBS->OpenProtocolInformation (\r
294 Controller,\r
295 &gEfiIsaIoProtocolGuid,\r
296 &OpenInfoBuffer,\r
297 &EntryCount\r
298 );\r
299 if (EFI_ERROR (Status)) {\r
300 return Status;\r
301 }\r
302\r
303 Status = EFI_ALREADY_STARTED;\r
304 for (Index = 0; Index < EntryCount; Index++) {\r
305 if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
306 Status = gBS->OpenProtocol (\r
307 OpenInfoBuffer[Index].ControllerHandle,\r
308 &gEfiSerialIoProtocolGuid,\r
309 (VOID **) &SerialIo,\r
310 This->DriverBindingHandle,\r
311 Controller,\r
312 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
313 );\r
314 if (!EFI_ERROR (Status)) {\r
315 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
316 Status = SerialIo->SetAttributes (\r
317 SerialIo,\r
318 Node.BaudRate,\r
319 SerialIo->Mode->ReceiveFifoDepth,\r
320 SerialIo->Mode->Timeout,\r
321 (EFI_PARITY_TYPE) Node.Parity,\r
322 Node.DataBits,\r
323 (EFI_STOP_BITS_TYPE) Node.StopBits\r
324 );\r
325 }\r
326 break;\r
327 }\r
328 }\r
329\r
330 gBS->FreePool (OpenInfoBuffer);\r
331 return Status;\r
332 }\r
333 //\r
334 // Initialize the serial device instance\r
335 //\r
336 SerialDevice = AllocatePool (sizeof (SERIAL_DEV));\r
337 if (SerialDevice == NULL) {\r
338 Status = EFI_OUT_OF_RESOURCES;\r
339 goto Error;\r
340 }\r
341\r
342 ZeroMem (SerialDevice, sizeof (SERIAL_DEV));\r
343\r
344 SerialDevice->IsaIo = IsaIo;\r
345 SerialDevice->ParentDevicePath = ParentDevicePath;\r
346 SerialDevice->ControllerNameTable = NULL;\r
347\r
348 ADD_SERIAL_NAME (SerialDevice, IsaIo);\r
349\r
350 for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {\r
351 if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {\r
352 SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange;\r
353 }\r
354 }\r
355 //\r
356 // Report status code the serial present\r
357 //\r
358 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
359 EFI_PROGRESS_CODE,\r
360 EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,\r
361 ParentDevicePath\r
362 );\r
363\r
364 if (!IsaSerialPortPresent (SerialDevice)) {\r
365 Status = EFI_DEVICE_ERROR;\r
366 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
367 EFI_ERROR_CODE,\r
368 EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT,\r
369 ParentDevicePath\r
370 );\r
371 goto Error;\r
372 }\r
373\r
374 SerialDevice->Signature = SERIAL_DEV_SIGNATURE;\r
375 SerialDevice->Type = UART16550A;\r
376 SerialDevice->SoftwareLoopbackEnable = FALSE;\r
377 SerialDevice->HardwareFlowControl = FALSE;\r
378 SerialDevice->Handle = NULL;\r
379 SerialDevice->Receive.First = 0;\r
380 SerialDevice->Receive.Last = 0;\r
381 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
382 SerialDevice->Transmit.First = 0;\r
383 SerialDevice->Transmit.Last = 0;\r
384 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
385\r
386 //\r
387 // Serial I/O\r
388 //\r
389 SerialDevice->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION;\r
390 SerialDevice->SerialIo.Reset = IsaSerialReset;\r
391 SerialDevice->SerialIo.SetAttributes = IsaSerialSetAttributes;\r
392 SerialDevice->SerialIo.SetControl = IsaSerialSetControl;\r
393 SerialDevice->SerialIo.GetControl = IsaSerialGetControl;\r
394 SerialDevice->SerialIo.Write = IsaSerialWrite;\r
395 SerialDevice->SerialIo.Read = IsaSerialRead;\r
396 SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);\r
397\r
398 if (RemainingDevicePath != NULL) {\r
399 //\r
400 // Match the configuration of the RemainingDevicePath. IsHandleSupported()\r
401 // already checked to make sure the RemainingDevicePath contains settings\r
402 // that we can support.\r
403 //\r
404 CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
405 } else {\r
406 //\r
407 // Build the device path by appending the UART node to the ParentDevicePath\r
408 // from the WinNtIo handle. The Uart setings are zero here, since\r
409 // SetAttribute() will update them to match the default setings.\r
410 //\r
411 ZeroMem (&SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));\r
412 SerialDevice->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH;\r
413 SerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;\r
414 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));\r
415 }\r
416 //\r
417 // Build the device path by appending the UART node to the ParentDevicePath\r
418 // from the WinNtIo handle. The Uart setings are zero here, since\r
419 // SetAttribute() will update them to match the current setings.\r
420 //\r
421 SerialDevice->DevicePath = AppendDevicePathNode (\r
422 ParentDevicePath,\r
423 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath\r
424 );\r
425\r
426 if (SerialDevice->DevicePath == NULL) {\r
427 Status = EFI_DEVICE_ERROR;\r
428 goto Error;\r
429 }\r
430 //\r
431 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.\r
432 //\r
433 SerialDevice->SerialMode.ControlMask = SERIAL_PORT_DEFAULT_CONTROL_MASK;\r
434 SerialDevice->SerialMode.Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;\r
435 SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;\r
436 SerialDevice->SerialMode.ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;\r
437 SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;\r
438 SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;\r
439 SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;\r
440\r
441 //\r
442 // Issue a reset to initialize the COM port\r
443 //\r
444 Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);\r
445 if (EFI_ERROR (Status)) {\r
446 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
447 EFI_ERROR_CODE,\r
448 EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
449 ParentDevicePath\r
450 );\r
451 goto Error;\r
452 }\r
453 //\r
454 // Install protocol interfaces for the serial device.\r
455 //\r
456 Status = gBS->InstallMultipleProtocolInterfaces (\r
457 &SerialDevice->Handle,\r
458 &gEfiDevicePathProtocolGuid,\r
459 SerialDevice->DevicePath,\r
460 &gEfiSerialIoProtocolGuid,\r
461 &SerialDevice->SerialIo,\r
462 NULL\r
463 );\r
464 if (EFI_ERROR (Status)) {\r
465 goto Error;\r
466 }\r
467 //\r
468 // Open For Child Device\r
469 //\r
470 Status = gBS->OpenProtocol (\r
471 Controller,\r
472 &gEfiIsaIoProtocolGuid,\r
473 (VOID **) &IsaIo,\r
474 This->DriverBindingHandle,\r
475 SerialDevice->Handle,\r
476 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
477 );\r
478\r
479Error:\r
480 if (EFI_ERROR (Status)) {\r
481 gBS->CloseProtocol (\r
482 Controller,\r
483 &gEfiDevicePathProtocolGuid,\r
484 This->DriverBindingHandle,\r
485 Controller\r
486 );\r
487 gBS->CloseProtocol (\r
488 Controller,\r
489 &gEfiIsaIoProtocolGuid,\r
490 This->DriverBindingHandle,\r
491 Controller\r
492 );\r
493 if (SerialDevice) {\r
494 if (SerialDevice->DevicePath) {\r
495 gBS->FreePool (SerialDevice->DevicePath);\r
496 }\r
497\r
498 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);\r
499 gBS->FreePool (SerialDevice);\r
500 }\r
501 }\r
502\r
503 return Status;\r
504}\r
505\r
506EFI_STATUS\r
507EFIAPI\r
508SerialControllerDriverStop (\r
509 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
510 IN EFI_HANDLE Controller,\r
511 IN UINTN NumberOfChildren,\r
512 IN EFI_HANDLE *ChildHandleBuffer\r
513 )\r
514/*++\r
515\r
516 Routine Description:\r
517\r
518 Disconnect this driver with the controller, uninstall related protocol instance\r
519\r
520 Arguments:\r
521\r
522 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
523 Controller - The handle of the controller to test.\r
524 NumberOfChildren - Number of child device.\r
525 RemainingDevicePath - A pointer to the remaining portion of a device path.\r
526\r
527 Returns:\r
528\r
529 EFI_SUCCESS - Operation successfully\r
530 EFI_DEVICE_ERROR - Cannot stop the driver successfully\r
531\r
532--*/\r
533{\r
534 EFI_STATUS Status;\r
535 UINTN Index;\r
536 BOOLEAN AllChildrenStopped;\r
537 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
538 SERIAL_DEV *SerialDevice;\r
539 EFI_ISA_IO_PROTOCOL *IsaIo;\r
540 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
541\r
542 Status = gBS->HandleProtocol (\r
543 Controller,\r
544 &gEfiDevicePathProtocolGuid,\r
545 (VOID **) &DevicePath\r
546 );\r
547\r
548 //\r
549 // Report the status code disable the serial\r
550 //\r
551 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
552 EFI_PROGRESS_CODE,\r
553 EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,\r
554 DevicePath\r
555 );\r
556\r
557 //\r
558 // Complete all outstanding transactions to Controller.\r
559 // Don't allow any new transaction to Controller to be started.\r
560 //\r
561 if (NumberOfChildren == 0) {\r
562 //\r
563 // Close the bus driver\r
564 //\r
565 Status = gBS->CloseProtocol (\r
566 Controller,\r
567 &gEfiIsaIoProtocolGuid,\r
568 This->DriverBindingHandle,\r
569 Controller\r
570 );\r
571\r
572 Status = gBS->CloseProtocol (\r
573 Controller,\r
574 &gEfiDevicePathProtocolGuid,\r
575 This->DriverBindingHandle,\r
576 Controller\r
577 );\r
578 return Status;\r
579 }\r
580\r
581 AllChildrenStopped = TRUE;\r
582\r
583 for (Index = 0; Index < NumberOfChildren; Index++) {\r
584\r
585 Status = gBS->OpenProtocol (\r
586 ChildHandleBuffer[Index],\r
587 &gEfiSerialIoProtocolGuid,\r
588 (VOID **) &SerialIo,\r
589 This->DriverBindingHandle,\r
590 Controller,\r
591 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
592 );\r
593 if (!EFI_ERROR (Status)) {\r
594\r
595 SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);\r
596\r
597 Status = gBS->CloseProtocol (\r
598 Controller,\r
599 &gEfiIsaIoProtocolGuid,\r
600 This->DriverBindingHandle,\r
601 ChildHandleBuffer[Index]\r
602 );\r
603\r
604 Status = gBS->UninstallMultipleProtocolInterfaces (\r
605 ChildHandleBuffer[Index],\r
606 &gEfiDevicePathProtocolGuid,\r
607 SerialDevice->DevicePath,\r
608 &gEfiSerialIoProtocolGuid,\r
609 &SerialDevice->SerialIo,\r
610 NULL\r
611 );\r
612 if (EFI_ERROR (Status)) {\r
613 gBS->OpenProtocol (\r
614 Controller,\r
615 &gEfiIsaIoProtocolGuid,\r
616 (VOID **) &IsaIo,\r
617 This->DriverBindingHandle,\r
618 ChildHandleBuffer[Index],\r
619 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
620 );\r
621 } else {\r
622 if (SerialDevice->DevicePath) {\r
623 gBS->FreePool (SerialDevice->DevicePath);\r
624 }\r
625\r
626 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);\r
627 gBS->FreePool (SerialDevice);\r
628 }\r
629 }\r
630\r
631 if (EFI_ERROR (Status)) {\r
632 AllChildrenStopped = FALSE;\r
633 }\r
634 }\r
635\r
636 if (!AllChildrenStopped) {\r
637 return EFI_DEVICE_ERROR;\r
638 }\r
639\r
640 return EFI_SUCCESS;\r
641}\r
642\r
643BOOLEAN\r
644IsaSerialFifoFull (\r
645 IN SERIAL_DEV_FIFO *Fifo\r
646 )\r
647/*++\r
648\r
649 Routine Description:\r
650\r
651 Detect whether specific FIFO is full or not\r
652\r
653 Arguments:\r
654\r
655 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
656\r
657 Returns:\r
658\r
659 TRUE - the FIFO is full\r
660 FALSE - the FIFO is not full\r
661\r
662--*/\r
663{\r
664 if (Fifo->Surplus == 0) {\r
665 return TRUE;\r
666 }\r
667\r
668 return FALSE;\r
669}\r
670\r
671BOOLEAN\r
672IsaSerialFifoEmpty (\r
673 IN SERIAL_DEV_FIFO *Fifo\r
674 )\r
675/*++\r
676\r
677 Routine Description:\r
678\r
679 Detect whether specific FIFO is empty or not\r
680\r
681 Arguments:\r
682\r
683 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
684\r
685 Returns:\r
686\r
687 TRUE - the FIFO is empty\r
688 FALSE - the FIFO is not empty\r
689\r
690--*/\r
691{\r
692 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {\r
693 return TRUE;\r
694 }\r
695\r
696 return FALSE;\r
697}\r
698\r
699EFI_STATUS\r
700IsaSerialFifoAdd (\r
701 IN SERIAL_DEV_FIFO *Fifo,\r
702 IN UINT8 Data\r
703 )\r
704/*++\r
705\r
706 Routine Description:\r
707\r
708 Add data to specific FIFO\r
709\r
710 Arguments:\r
711\r
712 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
713 Data - the data added to FIFO\r
714\r
715 Returns:\r
716\r
717 EFI_SUCCESS - Add data to specific FIFO successfully\r
718 EFI_OUT_OF_RESOURCE - Failed to add data because FIFO is already full\r
719\r
720--*/\r
721{\r
722 //\r
723 // if FIFO full can not add data\r
724 //\r
725 if (IsaSerialFifoFull (Fifo)) {\r
726 return EFI_OUT_OF_RESOURCES;\r
727 }\r
728 //\r
729 // FIFO is not full can add data\r
730 //\r
731 Fifo->Data[Fifo->Last] = Data;\r
732 Fifo->Surplus--;\r
733 Fifo->Last++;\r
734 if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {\r
735 Fifo->Last = 0;\r
736 }\r
737\r
738 return EFI_SUCCESS;\r
739}\r
740\r
741EFI_STATUS\r
742IsaSerialFifoRemove (\r
743 IN SERIAL_DEV_FIFO *Fifo,\r
744 OUT UINT8 *Data\r
745 )\r
746/*++\r
747\r
748 Routine Description:\r
749\r
750 Remove data from specific FIFO\r
751\r
752 Arguments:\r
753\r
754 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO\r
755 Data - the data removed from FIFO\r
756\r
757 Returns:\r
758 EFI_SUCCESS - Remove data from specific FIFO successfully\r
759 EFI_OUT_OF_RESOURCE - Failed to remove data because FIFO is empty\r
760\r
761--*/\r
762{\r
763 //\r
764 // if FIFO is empty, no data can remove\r
765 //\r
766 if (IsaSerialFifoEmpty (Fifo)) {\r
767 return EFI_OUT_OF_RESOURCES;\r
768 }\r
769 //\r
770 // FIFO is not empty, can remove data\r
771 //\r
772 *Data = Fifo->Data[Fifo->First];\r
773 Fifo->Surplus++;\r
774 Fifo->First++;\r
775 if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {\r
776 Fifo->First = 0;\r
777 }\r
778\r
779 return EFI_SUCCESS;\r
780}\r
781\r
782EFI_STATUS\r
783IsaSerialReceiveTransmit (\r
784 IN SERIAL_DEV *SerialDevice\r
785 )\r
786/*++\r
787\r
788 Routine Description:\r
789\r
790 Reads and writes all avaliable data.\r
791\r
792 Arguments:\r
793\r
794 SerialDevice - The device to flush\r
795\r
796 Returns:\r
797\r
798 EFI_SUCCESS - Data was read/written successfully.\r
799 EFI_OUT_OF_RESOURCE - Failed because software receive FIFO is full. Note, when\r
800 this happens, pending writes are not done.\r
801\r
802--*/\r
803{\r
804 SERIAL_PORT_LSR Lsr;\r
805 UINT8 Data;\r
806 BOOLEAN ReceiveFifoFull;\r
807 SERIAL_PORT_MSR Msr;\r
808 SERIAL_PORT_MCR Mcr;\r
809 UINTN TimeOut;\r
810\r
811 Data = 0;\r
812\r
813 //\r
814 // Begin the read or write\r
815 //\r
816 if (SerialDevice->SoftwareLoopbackEnable) {\r
817 do {\r
818 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
819 if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
820 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
821 if (ReceiveFifoFull) {\r
822 return EFI_OUT_OF_RESOURCES;\r
823 }\r
824\r
825 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
826 }\r
827 } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
828 } else {\r
829 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
830 do {\r
831 Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
832\r
833 if (FeaturePcdGet (PcdNtEmulatorEnable)) {\r
834 //\r
835 // This is required for NT to avoid a forever-spin...\r
836 // This would be better if READ_LSR was a polling operation\r
837 // that would timeout.\r
838 //\r
839 Lsr.Bits.THRE = 1;\r
840 }\r
841 //\r
842 // Flush incomming data to prevent a an overrun during a long write\r
843 //\r
844 if (Lsr.Bits.DR && !ReceiveFifoFull) {\r
845 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
846 if (!ReceiveFifoFull) {\r
847 if (Lsr.Bits.FIFOE || Lsr.Bits.OE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {\r
848 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
849 EFI_ERROR_CODE,\r
850 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
851 SerialDevice->DevicePath\r
852 );\r
853 if (Lsr.Bits.FIFOE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {\r
854 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
855 continue;\r
856 }\r
857 }\r
858 //\r
859 // Make sure the receive data will not be missed, Assert DTR\r
860 //\r
861 if (SerialDevice->HardwareFlowControl) {\r
862 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
863 Mcr.Bits.DTRC &= 0;\r
864 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
865 }\r
866\r
867 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
868\r
869 //\r
870 // Deassert DTR\r
871 //\r
872 if (SerialDevice->HardwareFlowControl) {\r
873 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
874 Mcr.Bits.DTRC |= 1;\r
875 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
876 }\r
877\r
878 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
879\r
880 continue;\r
881 } else {\r
882 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
883 EFI_PROGRESS_CODE,\r
884 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,\r
885 SerialDevice->DevicePath\r
886 );\r
887 }\r
888 }\r
889 //\r
890 // Do the write\r
891 //\r
892 if (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
893 //\r
894 // Make sure the transmit data will not be missed\r
895 //\r
896 if (SerialDevice->HardwareFlowControl) {\r
897 //\r
898 // Send RTS\r
899 //\r
900 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
901 Mcr.Bits.RTS |= 1;\r
902 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
903 //\r
904 // Wait for CTS\r
905 //\r
906 TimeOut = 0;\r
907 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
908 while (!Msr.Bits.CTS) {\r
909 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
910 TimeOut++;\r
911 if (TimeOut > 5) {\r
912 break;\r
913 }\r
914\r
915 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
916 }\r
917\r
918 if (Msr.Bits.CTS) {\r
919 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
920 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
921 }\r
922 }\r
923 //\r
924 // write the data out\r
925 //\r
926 if (!SerialDevice->HardwareFlowControl) {\r
927 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
928 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
929 }\r
930 //\r
931 // Make sure the transmit data will not be missed\r
932 //\r
933 if (SerialDevice->HardwareFlowControl) {\r
934 //\r
935 // Assert RTS\r
936 //\r
937 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
938 Mcr.Bits.RTS &= 0;\r
939 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
940 }\r
941 }\r
942 } while (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
943 }\r
944\r
945 return EFI_SUCCESS;\r
946}\r
947//\r
948// Interface Functions\r
949//\r
950EFI_STATUS\r
951EFIAPI\r
952IsaSerialReset (\r
953 IN EFI_SERIAL_IO_PROTOCOL *This\r
954 )\r
955/*++\r
956\r
957 Routine Description:\r
958\r
959 Reset serial device\r
960\r
961 Arguments:\r
962\r
963 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
964\r
965 Returns:\r
966\r
967 EFI_SUCCESS - Reset successfully\r
968 EFI_DEVICE_ERROR - Failed to reset\r
969\r
970--*/\r
971{\r
972 EFI_STATUS Status;\r
973 SERIAL_DEV *SerialDevice;\r
974 SERIAL_PORT_LCR Lcr;\r
975 SERIAL_PORT_IER Ier;\r
976 SERIAL_PORT_MCR Mcr;\r
977 SERIAL_PORT_FCR Fcr;\r
978 EFI_TPL Tpl;\r
979\r
980 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
981\r
982 //\r
983 // Report the status code reset the serial\r
984 //\r
985 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
986 EFI_PROGRESS_CODE,\r
987 EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,\r
988 SerialDevice->DevicePath\r
989 );\r
990\r
991 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
992\r
993 //\r
994 // Make sure DLAB is 0.\r
995 //\r
996 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
997 Lcr.Bits.DLAB = 0;\r
998 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
999\r
1000 //\r
1001 // Turn off all interrupts\r
1002 //\r
1003 Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1004 Ier.Bits.RAVIE = 0;\r
1005 Ier.Bits.THEIE = 0;\r
1006 Ier.Bits.RIE = 0;\r
1007 Ier.Bits.MIE = 0;\r
1008 WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);\r
1009\r
1010 //\r
1011 // Disable the FIFO.\r
1012 //\r
1013 Fcr.Bits.TRFIFOE = 0;\r
1014 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
1015\r
1016 //\r
1017 // Turn off loopback and disable device interrupt.\r
1018 //\r
1019 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1020 Mcr.Bits.OUT1 = 0;\r
1021 Mcr.Bits.OUT2 = 0;\r
1022 Mcr.Bits.LME = 0;\r
1023 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
1024\r
1025 //\r
1026 // Clear the scratch pad register\r
1027 //\r
1028 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);\r
1029\r
1030 //\r
1031 // Go set the current attributes\r
1032 //\r
1033 Status = This->SetAttributes (\r
1034 This,\r
1035 This->Mode->BaudRate,\r
1036 This->Mode->ReceiveFifoDepth,\r
1037 This->Mode->Timeout,\r
1038 (EFI_PARITY_TYPE) This->Mode->Parity,\r
1039 (UINT8) This->Mode->DataBits,\r
1040 (EFI_STOP_BITS_TYPE) This->Mode->StopBits\r
1041 );\r
1042\r
1043 if (EFI_ERROR (Status)) {\r
1044 gBS->RestoreTPL (Tpl);\r
1045 return EFI_DEVICE_ERROR;\r
1046 }\r
1047 //\r
1048 // Go set the current control bits\r
1049 //\r
1050 Status = This->SetControl (\r
1051 This,\r
1052 This->Mode->ControlMask\r
1053 );\r
1054\r
1055 if (EFI_ERROR (Status)) {\r
1056 gBS->RestoreTPL (Tpl);\r
1057 return EFI_DEVICE_ERROR;\r
1058 }\r
1059 //\r
1060 // for 16550A enable FIFO, 16550 disable FIFO\r
1061 //\r
1062 Fcr.Bits.TRFIFOE = 1;\r
1063 Fcr.Bits.RESETRF = 1;\r
1064 Fcr.Bits.RESETTF = 1;\r
1065 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
1066\r
1067 //\r
1068 // Reset the software FIFO\r
1069 //\r
1070 SerialDevice->Receive.First = 0;\r
1071 SerialDevice->Receive.Last = 0;\r
1072 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1073 SerialDevice->Transmit.First = 0;\r
1074 SerialDevice->Transmit.Last = 0;\r
1075 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1076\r
1077 gBS->RestoreTPL (Tpl);\r
1078\r
1079 //\r
1080 // Device reset is complete\r
1081 //\r
1082 return EFI_SUCCESS;\r
1083}\r
1084\r
1085EFI_STATUS\r
1086EFIAPI\r
1087IsaSerialSetAttributes (\r
1088 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1089 IN UINT64 BaudRate,\r
1090 IN UINT32 ReceiveFifoDepth,\r
1091 IN UINT32 Timeout,\r
1092 IN EFI_PARITY_TYPE Parity,\r
1093 IN UINT8 DataBits,\r
1094 IN EFI_STOP_BITS_TYPE StopBits\r
1095 )\r
1096/*++\r
1097\r
1098 Routine Description:\r
1099\r
1100 Set new attributes to a serial device\r
1101\r
1102 Arguments:\r
1103\r
1104 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1105 BaudRate - The baudrate of the serial device\r
1106 ReceiveFifoDepth - The depth of receive FIFO buffer\r
1107 Timeout - The request timeout for a single char\r
1108 Parity - The type of parity used in serial device\r
1109 DataBits - Number of databits used in serial device\r
1110 StopBits - Number of stopbits used in serial device\r
1111\r
1112 Returns:\r
1113\r
1114 EFI_SUCCESS - The new attributes were set\r
1115 EFI_INVALID_PARAMETERS - One or more attributes have an unsupported value\r
1116 EFI_UNSUPPORTED - Data Bits can not set to 5 or 6\r
1117 EFI_DEVICE_ERROR - The serial device is not functioning correctly (no return)\r
1118\r
1119--*/\r
1120{\r
1121 EFI_STATUS Status;\r
1122 SERIAL_DEV *SerialDevice;\r
1123 UINT32 Divisor;\r
1124 UINT32 Remained;\r
1125 SERIAL_PORT_LCR Lcr;\r
1126 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1127 EFI_TPL Tpl;\r
1128\r
1129 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1130\r
1131 //\r
1132 // Check for default settings and fill in actual values.\r
1133 //\r
1134 if (BaudRate == 0) {\r
1135 BaudRate = SERIAL_PORT_DEFAULT_BAUD_RATE;\r
1136 }\r
1137\r
1138 if (ReceiveFifoDepth == 0) {\r
1139 ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;\r
1140 }\r
1141\r
1142 if (Timeout == 0) {\r
1143 Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;\r
1144 }\r
1145\r
1146 if (Parity == DefaultParity) {\r
1147 Parity = SERIAL_PORT_DEFAULT_PARITY;\r
1148 }\r
1149\r
1150 if (DataBits == 0) {\r
1151 DataBits = SERIAL_PORT_DEFAULT_DATA_BITS;\r
1152 }\r
1153\r
1154 if (StopBits == DefaultStopBits) {\r
1155 StopBits = (EFI_STOP_BITS_TYPE) SERIAL_PORT_DEFAULT_STOP_BITS;\r
1156 }\r
1157 //\r
1158 // 5 and 6 data bits can not be verified on a 16550A UART\r
1159 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.\r
1160 //\r
1161 if ((DataBits == 5) || (DataBits == 6)) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164 //\r
1165 // Make sure all parameters are valid\r
1166 //\r
1167 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
1168 return EFI_INVALID_PARAMETER;\r
1169 }\r
1170 //\r
1171 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,\r
1172 // 38400,57600,115200\r
1173 //\r
1174 if (BaudRate < 75) {\r
1175 BaudRate = 50;\r
1176 } else if (BaudRate < 110) {\r
1177 BaudRate = 75;\r
1178 } else if (BaudRate < 134) {\r
1179 BaudRate = 110;\r
1180 } else if (BaudRate < 150) {\r
1181 BaudRate = 134;\r
1182 } else if (BaudRate < 300) {\r
1183 BaudRate = 150;\r
1184 } else if (BaudRate < 600) {\r
1185 BaudRate = 300;\r
1186 } else if (BaudRate < 1200) {\r
1187 BaudRate = 600;\r
1188 } else if (BaudRate < 1800) {\r
1189 BaudRate = 1200;\r
1190 } else if (BaudRate < 2000) {\r
1191 BaudRate = 1800;\r
1192 } else if (BaudRate < 2400) {\r
1193 BaudRate = 2000;\r
1194 } else if (BaudRate < 3600) {\r
1195 BaudRate = 2400;\r
1196 } else if (BaudRate < 4800) {\r
1197 BaudRate = 3600;\r
1198 } else if (BaudRate < 7200) {\r
1199 BaudRate = 4800;\r
1200 } else if (BaudRate < 9600) {\r
1201 BaudRate = 7200;\r
1202 } else if (BaudRate < 19200) {\r
1203 BaudRate = 9600;\r
1204 } else if (BaudRate < 38400) {\r
1205 BaudRate = 19200;\r
1206 } else if (BaudRate < 57600) {\r
1207 BaudRate = 38400;\r
1208 } else if (BaudRate < 115200) {\r
1209 BaudRate = 57600;\r
1210 } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {\r
1211 BaudRate = 115200;\r
1212 }\r
1213\r
1214 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
1215 return EFI_INVALID_PARAMETER;\r
1216 }\r
1217\r
1218 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
1219 return EFI_INVALID_PARAMETER;\r
1220 }\r
1221\r
1222 if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
1223 return EFI_INVALID_PARAMETER;\r
1224 }\r
1225\r
1226 if ((DataBits < 5) || (DataBits > 8)) {\r
1227 return EFI_INVALID_PARAMETER;\r
1228 }\r
1229\r
1230 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
1231 return EFI_INVALID_PARAMETER;\r
1232 }\r
1233 //\r
1234 // for DataBits = 5, StopBits can not set TwoStopBits\r
1235 //\r
1236 // if ((DataBits == 5) && (StopBits == TwoStopBits)) {\r
1237 // return EFI_INVALID_PARAMETER;\r
1238 // }\r
1239 //\r
1240 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits\r
1241 //\r
1242 if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {\r
1243 return EFI_INVALID_PARAMETER;\r
1244 }\r
1245\r
1246 //\r
1247 // Compute divisor use to program the baud rate using a round determination\r
1248 //\r
1249 Divisor = (UINT32) DivU64x32Remainder (\r
1250 SERIAL_PORT_INPUT_CLOCK,\r
1251 ((UINT32) BaudRate * 16),\r
1252 &Remained\r
1253 );\r
1254 if (Remained) {\r
1255 Divisor += 1;\r
1256 }\r
1257\r
1258 if ((Divisor == 0) || (Divisor & 0xffff0000)) {\r
1259 return EFI_INVALID_PARAMETER;\r
1260 }\r
1261\r
1262 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1263\r
1264 //\r
1265 // Compute the actual baud rate that the serial port will be programmed for.\r
1266 //\r
1267 BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;\r
1268\r
1269 //\r
1270 // Put serial port on Divisor Latch Mode\r
1271 //\r
1272 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1273 Lcr.Bits.DLAB = 1;\r
1274 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1275\r
1276 //\r
1277 // Write the divisor to the serial port\r
1278 //\r
1279 WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));\r
1280 WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));\r
1281\r
1282 //\r
1283 // Put serial port back in normal mode and set remaining attributes.\r
1284 //\r
1285 Lcr.Bits.DLAB = 0;\r
1286\r
1287 switch (Parity) {\r
1288 case NoParity:\r
1289 Lcr.Bits.PAREN = 0;\r
1290 Lcr.Bits.EVENPAR = 0;\r
1291 Lcr.Bits.STICPAR = 0;\r
1292 break;\r
1293\r
1294 case EvenParity:\r
1295 Lcr.Bits.PAREN = 1;\r
1296 Lcr.Bits.EVENPAR = 1;\r
1297 Lcr.Bits.STICPAR = 0;\r
1298 break;\r
1299\r
1300 case OddParity:\r
1301 Lcr.Bits.PAREN = 1;\r
1302 Lcr.Bits.EVENPAR = 0;\r
1303 Lcr.Bits.STICPAR = 0;\r
1304 break;\r
1305\r
1306 case SpaceParity:\r
1307 Lcr.Bits.PAREN = 1;\r
1308 Lcr.Bits.EVENPAR = 1;\r
1309 Lcr.Bits.STICPAR = 1;\r
1310 break;\r
1311\r
1312 case MarkParity:\r
1313 Lcr.Bits.PAREN = 1;\r
1314 Lcr.Bits.EVENPAR = 0;\r
1315 Lcr.Bits.STICPAR = 1;\r
1316 break;\r
1317\r
1318 default:\r
1319 break;\r
1320 }\r
1321\r
1322 switch (StopBits) {\r
1323 case OneStopBit:\r
1324 Lcr.Bits.STOPB = 0;\r
1325 break;\r
1326\r
1327 case OneFiveStopBits:\r
1328 case TwoStopBits:\r
1329 Lcr.Bits.STOPB = 1;\r
1330 break;\r
1331\r
1332 default:\r
1333 break;\r
1334 }\r
1335 //\r
1336 // DataBits\r
1337 //\r
1338 Lcr.Bits.SERIALDB = (UINT8) ((DataBits - 5) & 0x03);\r
1339 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1340\r
1341 //\r
1342 // Set the Serial I/O mode\r
1343 //\r
1344 This->Mode->BaudRate = BaudRate;\r
1345 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;\r
1346 This->Mode->Timeout = Timeout;\r
1347 This->Mode->Parity = Parity;\r
1348 This->Mode->DataBits = DataBits;\r
1349 This->Mode->StopBits = StopBits;\r
1350\r
1351 //\r
1352 // See if Device Path Node has actually changed\r
1353 //\r
1354 if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&\r
1355 SerialDevice->UartDevicePath.DataBits == DataBits &&\r
1356 SerialDevice->UartDevicePath.Parity == Parity &&\r
1357 SerialDevice->UartDevicePath.StopBits == StopBits\r
1358 ) {\r
1359 gBS->RestoreTPL (Tpl);\r
1360 return EFI_SUCCESS;\r
1361 }\r
1362 //\r
1363 // Update the device path\r
1364 //\r
1365 SerialDevice->UartDevicePath.BaudRate = BaudRate;\r
1366 SerialDevice->UartDevicePath.DataBits = DataBits;\r
1367 SerialDevice->UartDevicePath.Parity = (UINT8) Parity;\r
1368 SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;\r
1369\r
1370 NewDevicePath = AppendDevicePathNode (\r
1371 SerialDevice->ParentDevicePath,\r
1372 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath\r
1373 );\r
1374 if (NewDevicePath == NULL) {\r
1375 gBS->RestoreTPL (Tpl);\r
1376 return EFI_DEVICE_ERROR;\r
1377 }\r
1378\r
1379 if (SerialDevice->Handle != NULL) {\r
1380 Status = gBS->ReinstallProtocolInterface (\r
1381 SerialDevice->Handle,\r
1382 &gEfiDevicePathProtocolGuid,\r
1383 SerialDevice->DevicePath,\r
1384 NewDevicePath\r
1385 );\r
1386 if (EFI_ERROR (Status)) {\r
1387 gBS->RestoreTPL (Tpl);\r
1388 return Status;\r
1389 }\r
1390 }\r
1391\r
1392 if (SerialDevice->DevicePath) {\r
1393 gBS->FreePool (SerialDevice->DevicePath);\r
1394 }\r
1395\r
1396 SerialDevice->DevicePath = NewDevicePath;\r
1397\r
1398 gBS->RestoreTPL (Tpl);\r
1399\r
1400 return EFI_SUCCESS;\r
1401}\r
1402\r
1403EFI_STATUS\r
1404EFIAPI\r
1405IsaSerialSetControl (\r
1406 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1407 IN UINT32 Control\r
1408 )\r
1409/*++\r
1410\r
1411 Routine Description:\r
1412\r
1413 Set Control Bits\r
1414\r
1415 Arguments:\r
1416\r
1417 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1418 Control - Control bits that can be settable\r
1419\r
1420 Returns:\r
1421\r
1422 EFI_SUCCESS - New Control bits were set successfully\r
1423 EFI_UNSUPPORTED - The Control bits wanted to set are not supported\r
1424\r
1425--*/\r
1426{\r
1427 SERIAL_DEV *SerialDevice;\r
1428 SERIAL_PORT_MCR Mcr;\r
1429 EFI_TPL Tpl;\r
1430\r
1431 //\r
1432 // The control bits that can be set are :\r
1433 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO\r
1434 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO\r
1435 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW\r
1436 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW\r
1437 //\r
1438 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1439\r
1440 //\r
1441 // first determine the parameter is invalid\r
1442 //\r
1443 if (Control & 0xffff8ffc) {\r
1444 return EFI_UNSUPPORTED;\r
1445 }\r
1446\r
1447 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1448\r
1449 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1450 Mcr.Bits.DTRC = 0;\r
1451 Mcr.Bits.RTS = 0;\r
1452 Mcr.Bits.LME = 0;\r
1453 SerialDevice->SoftwareLoopbackEnable = FALSE;\r
1454 SerialDevice->HardwareFlowControl = FALSE;\r
1455\r
1456 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {\r
1457 Mcr.Bits.DTRC = 1;\r
1458 }\r
1459\r
1460 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {\r
1461 Mcr.Bits.RTS = 1;\r
1462 }\r
1463\r
1464 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {\r
1465 Mcr.Bits.LME = 1;\r
1466 }\r
1467\r
1468 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
1469 SerialDevice->HardwareFlowControl = TRUE;\r
1470 }\r
1471\r
1472 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
1473\r
1474 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {\r
1475 SerialDevice->SoftwareLoopbackEnable = TRUE;\r
1476 }\r
1477\r
1478 gBS->RestoreTPL (Tpl);\r
1479\r
1480 return EFI_SUCCESS;\r
1481}\r
1482\r
1483EFI_STATUS\r
1484EFIAPI\r
1485IsaSerialGetControl (\r
1486 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1487 OUT UINT32 *Control\r
1488 )\r
1489/*++\r
1490\r
1491 Routine Description:\r
1492\r
1493 Get ControlBits\r
1494\r
1495 Arguments:\r
1496\r
1497 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1498 Control - Control signals of the serial device\r
1499\r
1500 Returns:\r
1501\r
1502 EFI_SUCCESS - Get Control signals successfully\r
1503\r
1504--*/\r
1505{\r
1506 SERIAL_DEV *SerialDevice;\r
1507 SERIAL_PORT_MSR Msr;\r
1508 SERIAL_PORT_MCR Mcr;\r
1509 EFI_TPL Tpl;\r
1510\r
1511 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1512\r
1513 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1514\r
1515 *Control = 0;\r
1516\r
1517 //\r
1518 // Read the Modem Status Register\r
1519 //\r
1520 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1521\r
1522 if (Msr.Bits.CTS) {\r
1523 *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
1524 }\r
1525\r
1526 if (Msr.Bits.DSR) {\r
1527 *Control |= EFI_SERIAL_DATA_SET_READY;\r
1528 }\r
1529\r
1530 if (Msr.Bits.RI) {\r
1531 *Control |= EFI_SERIAL_RING_INDICATE;\r
1532 }\r
1533\r
1534 if (Msr.Bits.DCD) {\r
1535 *Control |= EFI_SERIAL_CARRIER_DETECT;\r
1536 }\r
1537 //\r
1538 // Read the Modem Control Register\r
1539 //\r
1540 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1541\r
1542 if (Mcr.Bits.DTRC) {\r
1543 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
1544 }\r
1545\r
1546 if (Mcr.Bits.RTS) {\r
1547 *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
1548 }\r
1549\r
1550 if (Mcr.Bits.LME) {\r
1551 *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
1552 }\r
1553\r
1554 if (SerialDevice->HardwareFlowControl) {\r
1555 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
1556 }\r
1557 //\r
1558 // See if the Transmit FIFO is empty\r
1559 //\r
1560 IsaSerialReceiveTransmit (SerialDevice);\r
1561\r
1562 if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1563 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
1564 }\r
1565 //\r
1566 // See if the Receive FIFO is empty.\r
1567 //\r
1568 IsaSerialReceiveTransmit (SerialDevice);\r
1569\r
1570 if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {\r
1571 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
1572 }\r
1573\r
1574 if (SerialDevice->SoftwareLoopbackEnable) {\r
1575 *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
1576 }\r
1577\r
1578 gBS->RestoreTPL (Tpl);\r
1579\r
1580 return EFI_SUCCESS;\r
1581}\r
1582\r
1583EFI_STATUS\r
1584EFIAPI\r
1585IsaSerialWrite (\r
1586 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1587 IN OUT UINTN *BufferSize,\r
1588 IN VOID *Buffer\r
1589 )\r
1590/*++\r
1591\r
1592 Routine Description:\r
1593\r
1594 Write the specified number of bytes to serial device\r
1595\r
1596 Arguments:\r
1597\r
1598 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1599 BufferSize - On input the size of Buffer, on output the amount of\r
1600 data actually written\r
1601 Buffer - The buffer of data to write\r
1602\r
1603 Returns:\r
1604\r
1605 EFI_SUCCESS - The data were written successfully\r
1606 EFI_DEVICE_ERROR - The device reported an error\r
1607 EFI_TIMEOUT - The write operation was stopped due to timeout\r
1608\r
1609--*/\r
1610{\r
1611 SERIAL_DEV *SerialDevice;\r
1612 UINT8 *CharBuffer;\r
1613 UINT32 Index;\r
1614 UINTN Elapsed;\r
1615 UINTN ActualWrite;\r
1616 EFI_TPL Tpl;\r
1617\r
1618 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1619 Elapsed = 0;\r
1620 ActualWrite = 0;\r
1621\r
1622 if (*BufferSize == 0) {\r
1623 return EFI_SUCCESS;\r
1624 }\r
1625\r
1626 if (!Buffer) {\r
1627 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1628 EFI_ERROR_CODE,\r
1629 EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1630 SerialDevice->DevicePath\r
1631 );\r
1632\r
1633 return EFI_DEVICE_ERROR;\r
1634 }\r
1635\r
1636 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1637\r
1638 CharBuffer = (UINT8 *) Buffer;\r
1639\r
1640 for (Index = 0; Index < *BufferSize; Index++) {\r
1641 IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);\r
1642\r
1643 while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1644 //\r
1645 // Unsuccessful write so check if timeout has expired, if not,\r
1646 // stall for a bit, increment time elapsed, and try again\r
1647 //\r
1648 if (Elapsed >= This->Mode->Timeout) {\r
1649 *BufferSize = ActualWrite;\r
1650 gBS->RestoreTPL (Tpl);\r
1651 return EFI_TIMEOUT;\r
1652 }\r
1653\r
1654 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1655\r
1656 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1657 }\r
1658\r
1659 ActualWrite++;\r
1660 //\r
1661 // Successful write so reset timeout\r
1662 //\r
1663 Elapsed = 0;\r
1664 }\r
1665\r
1666 gBS->RestoreTPL (Tpl);\r
1667\r
1668 return EFI_SUCCESS;\r
1669}\r
1670\r
1671EFI_STATUS\r
1672EFIAPI\r
1673IsaSerialRead (\r
1674 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1675 IN OUT UINTN *BufferSize,\r
1676 OUT VOID *Buffer\r
1677 )\r
1678/*++\r
1679\r
1680 Routine Description:\r
1681\r
1682 Read the specified number of bytes from serial device\r
1683\r
1684 Arguments:\r
1685\r
1686 This - Pointer to EFI_SERIAL_IO_PROTOCOL\r
1687 BufferSize - On input the size of Buffer, on output the amount of\r
1688 data returned in buffer\r
1689 Buffer - The buffer to return the data into\r
1690\r
1691 Returns:\r
1692\r
1693 EFI_SUCCESS - The data were read successfully\r
1694 EFI_DEVICE_ERROR - The device reported an error\r
1695 EFI_TIMEOUT - The read operation was stopped due to timeout\r
1696\r
1697--*/\r
1698{\r
1699 SERIAL_DEV *SerialDevice;\r
1700 UINT32 Index;\r
1701 UINT8 *CharBuffer;\r
1702 UINTN Elapsed;\r
1703 EFI_STATUS Status;\r
1704 EFI_TPL Tpl;\r
1705\r
1706 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1707 Elapsed = 0;\r
1708\r
1709 if (*BufferSize == 0) {\r
1710 return EFI_SUCCESS;\r
1711 }\r
1712\r
1713 if (!Buffer) {\r
1714 return EFI_DEVICE_ERROR;\r
1715 }\r
1716\r
1717 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1718\r
1719 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1720\r
1721 if (EFI_ERROR (Status)) {\r
1722 *BufferSize = 0;\r
1723\r
1724 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1725 EFI_ERROR_CODE,\r
1726 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1727 SerialDevice->DevicePath\r
1728 );\r
1729\r
1730 gBS->RestoreTPL (Tpl);\r
1731\r
1732 return EFI_DEVICE_ERROR;\r
1733 }\r
1734\r
1735 CharBuffer = (UINT8 *) Buffer;\r
1736 for (Index = 0; Index < *BufferSize; Index++) {\r
1737 while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {\r
1738 //\r
1739 // Unsuccessful read so check if timeout has expired, if not,\r
1740 // stall for a bit, increment time elapsed, and try again\r
1741 // Need this time out to get conspliter to work.\r
1742 //\r
1743 if (Elapsed >= This->Mode->Timeout) {\r
1744 *BufferSize = Index;\r
1745 gBS->RestoreTPL (Tpl);\r
1746 return EFI_TIMEOUT;\r
1747 }\r
1748\r
1749 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1750 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1751\r
1752 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1753 if (Status == EFI_DEVICE_ERROR) {\r
1754 *BufferSize = Index;\r
1755 gBS->RestoreTPL (Tpl);\r
1756 return EFI_DEVICE_ERROR;\r
1757 }\r
1758 }\r
1759 //\r
1760 // Successful read so reset timeout\r
1761 //\r
1762 Elapsed = 0;\r
1763 }\r
1764\r
1765 IsaSerialReceiveTransmit (SerialDevice);\r
1766\r
1767 gBS->RestoreTPL (Tpl);\r
1768\r
1769 return EFI_SUCCESS;\r
1770}\r
1771\r
1772BOOLEAN\r
1773IsaSerialPortPresent (\r
1774 IN SERIAL_DEV *SerialDevice\r
1775 )\r
1776/*++\r
1777\r
1778 Routine Description:\r
1779\r
1780 Use scratchpad register to test if this serial port is present\r
1781\r
1782 Arguments:\r
1783\r
1784 SerialDevice - Pointer to serial device structure\r
1785\r
1786 Returns:\r
1787\r
1788 TRUE - The serial port is present\r
1789 FALSE - The serial port is NOT present\r
1790\r
1791--*/\r
1792{\r
1793 UINT8 Temp;\r
1794 BOOLEAN Status;\r
1795\r
1796 Status = TRUE;\r
1797\r
1798 //\r
1799 // Save SCR reg\r
1800 //\r
1801 Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1802 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);\r
1803\r
1804 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA)\r
1805 {\r
1806 if (!FeaturePcdGet (PcdNtEmulatorEnable)) {\r
1807 Status = FALSE;\r
1808 }\r
1809 }\r
1810\r
1811 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);\r
1812\r
1813 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55)\r
1814 {\r
1815 if (!FeaturePcdGet (PcdNtEmulatorEnable)) {\r
1816 Status = FALSE;\r
1817 }\r
1818 }\r
1819 //\r
1820 // Restore SCR\r
1821 //\r
1822 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);\r
1823 return Status;\r
1824}\r
1825\r
1826UINT8\r
1827IsaSerialReadPort (\r
1828 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1829 IN UINT16 BaseAddress,\r
1830 IN UINT32 Offset\r
1831 )\r
1832/*++\r
1833\r
1834 Routine Description:\r
1835\r
1836 Use IsaIo protocol to read serial port\r
1837\r
1838 Arguments:\r
1839\r
1840 IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance\r
1841 BaseAddress - Serial port register group base address\r
1842 Offset - Offset in register group\r
1843\r
1844 Returns:\r
1845\r
1846 Data read from serial port\r
1847\r
1848--*/\r
1849{\r
1850 UINT8 Data;\r
1851\r
1852 //\r
1853 // Use IsaIo to access IO\r
1854 //\r
1855 IsaIo->Io.Read (\r
1856 IsaIo,\r
1857 EfiIsaIoWidthUint8,\r
1858 BaseAddress + Offset,\r
1859 1,\r
1860 &Data\r
1861 );\r
1862 return Data;\r
1863}\r
1864\r
1865VOID\r
1866IsaSerialWritePort (\r
1867 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1868 IN UINT16 BaseAddress,\r
1869 IN UINT32 Offset,\r
1870 IN UINT8 Data\r
1871 )\r
1872/*++\r
1873\r
1874 Routine Description:\r
1875\r
1876 Use IsaIo protocol to write serial port\r
1877\r
1878 Arguments:\r
1879\r
1880 IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance\r
1881 BaseAddress - Serial port register group base address\r
1882 Offset - Offset in register group\r
1883 Data - data which is to be written to some serial port register\r
1884\r
1885 Returns:\r
1886\r
1887 None\r
1888\r
1889--*/\r
1890{\r
1891 //\r
1892 // Use IsaIo to access IO\r
1893 //\r
1894 IsaIo->Io.Write (\r
1895 IsaIo,\r
1896 EfiIsaIoWidthUint8,\r
1897 BaseAddress + Offset,\r
1898 1,\r
1899 &Data\r
1900 );\r
1901}\r
1902\r