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