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