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