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