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