]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
Update code style.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaSerialDxe / Serial.c
CommitLineData
91c68197 1/** @file\r
bcd70414 2 Serial driver for standard UARTS on an ISA bus.\r
637ff819 3\r
91c68197
LG
4Copyright (c) 2006 - 2009, 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
366565e0 9\r
91c68197
LG
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
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
91c68197 85 Uart16550A,\r
6b88ceec
A
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
91c68197
LG
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
91c68197 132 @return EFI_SUCCESS This driver can support the given controller\r
bcd70414 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
91c68197
LG
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
bcd70414 267\r
91c68197 268 @return EFI_SUCCESS Driver is started successfully\r
bcd70414 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
91c68197 391 AddName (SerialDevice, IsaIo);\r
637ff819 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
91c68197
LG
504 if (SerialDevice != NULL) {\r
505 if (SerialDevice->DevicePath != NULL) {\r
637ff819 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
91c68197
LG
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
523 @param ChildHandleBuffer A pointer to the remaining portion of a device path.\r
bcd70414 524\r
91c68197
LG
525 @retval EFI_SUCCESS Operation successfully\r
526 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully\r
bcd70414 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
91c68197 627 if (SerialDevice->DevicePath != NULL) {\r
637ff819 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
91c68197 649 Detect whether specific FIFO is full or not.\r
bcd70414 650\r
91c68197 651 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO\r
bcd70414 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
91c68197 670 Detect whether specific FIFO is empty or not.\r
bcd70414 671 \r
91c68197 672 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO\r
bcd70414 673\r
674 @return whether specific FIFO is empty or not\r
675\r
676**/\r
637ff819 677BOOLEAN\r
678IsaSerialFifoEmpty (\r
679 IN SERIAL_DEV_FIFO *Fifo\r
680 )\r
637ff819 681\r
637ff819 682{\r
683 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {\r
684 return TRUE;\r
685 }\r
686\r
687 return FALSE;\r
688}\r
689\r
bcd70414 690/**\r
91c68197 691 Add data to specific FIFO.\r
bcd70414 692\r
91c68197
LG
693 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO\r
694 @param Data the data added to FIFO\r
bcd70414 695\r
91c68197
LG
696 @retval EFI_SUCCESS Add data to specific FIFO successfully\r
697 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full\r
bcd70414 698\r
699**/\r
637ff819 700EFI_STATUS\r
701IsaSerialFifoAdd (\r
702 IN SERIAL_DEV_FIFO *Fifo,\r
703 IN UINT8 Data\r
704 )\r
637ff819 705\r
637ff819 706{\r
707 //\r
708 // if FIFO full can not add data\r
709 //\r
710 if (IsaSerialFifoFull (Fifo)) {\r
711 return EFI_OUT_OF_RESOURCES;\r
712 }\r
713 //\r
714 // FIFO is not full can add data\r
715 //\r
716 Fifo->Data[Fifo->Last] = Data;\r
717 Fifo->Surplus--;\r
718 Fifo->Last++;\r
719 if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {\r
720 Fifo->Last = 0;\r
721 }\r
722\r
723 return EFI_SUCCESS;\r
724}\r
725\r
bcd70414 726/**\r
91c68197 727 Remove data from specific FIFO.\r
bcd70414 728\r
91c68197
LG
729 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO\r
730 @param Data the data removed from FIFO\r
bcd70414 731\r
91c68197
LG
732 @retval EFI_SUCCESS Remove data from specific FIFO successfully\r
733 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty\r
bcd70414 734\r
735**/\r
637ff819 736EFI_STATUS\r
737IsaSerialFifoRemove (\r
738 IN SERIAL_DEV_FIFO *Fifo,\r
739 OUT UINT8 *Data\r
740 )\r
637ff819 741\r
637ff819 742{\r
743 //\r
744 // if FIFO is empty, no data can remove\r
745 //\r
746 if (IsaSerialFifoEmpty (Fifo)) {\r
747 return EFI_OUT_OF_RESOURCES;\r
748 }\r
749 //\r
750 // FIFO is not empty, can remove data\r
751 //\r
752 *Data = Fifo->Data[Fifo->First];\r
753 Fifo->Surplus++;\r
754 Fifo->First++;\r
755 if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {\r
756 Fifo->First = 0;\r
757 }\r
758\r
759 return EFI_SUCCESS;\r
760}\r
761\r
bcd70414 762/**\r
763 Reads and writes all avaliable data.\r
764\r
91c68197 765 @param SerialDevice The device to flush\r
bcd70414 766\r
91c68197
LG
767 @retval EFI_SUCCESS Data was read/written successfully.\r
768 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when\r
bcd70414 769 this happens, pending writes are not done.\r
770\r
771**/\r
637ff819 772EFI_STATUS\r
773IsaSerialReceiveTransmit (\r
774 IN SERIAL_DEV *SerialDevice\r
775 )\r
637ff819 776\r
637ff819 777{\r
778 SERIAL_PORT_LSR Lsr;\r
779 UINT8 Data;\r
780 BOOLEAN ReceiveFifoFull;\r
781 SERIAL_PORT_MSR Msr;\r
782 SERIAL_PORT_MCR Mcr;\r
783 UINTN TimeOut;\r
784\r
785 Data = 0;\r
786\r
787 //\r
788 // Begin the read or write\r
789 //\r
790 if (SerialDevice->SoftwareLoopbackEnable) {\r
791 do {\r
792 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
793 if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
794 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
795 if (ReceiveFifoFull) {\r
796 return EFI_OUT_OF_RESOURCES;\r
797 }\r
798\r
799 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
800 }\r
801 } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
802 } else {\r
803 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
804 do {\r
805 Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
806\r
637ff819 807 //\r
808 // Flush incomming data to prevent a an overrun during a long write\r
809 //\r
91c68197 810 if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {\r
637ff819 811 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
812 if (!ReceiveFifoFull) {\r
91c68197 813 if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {\r
637ff819 814 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
815 EFI_ERROR_CODE,\r
816 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
817 SerialDevice->DevicePath\r
818 );\r
91c68197 819 if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {\r
637ff819 820 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
821 continue;\r
822 }\r
823 }\r
824 //\r
825 // Make sure the receive data will not be missed, Assert DTR\r
826 //\r
827 if (SerialDevice->HardwareFlowControl) {\r
828 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 829 Mcr.Bits.DtrC &= 0;\r
637ff819 830 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
831 }\r
832\r
833 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
834\r
835 //\r
836 // Deassert DTR\r
837 //\r
838 if (SerialDevice->HardwareFlowControl) {\r
839 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 840 Mcr.Bits.DtrC |= 1;\r
637ff819 841 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
842 }\r
843\r
844 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
845\r
846 continue;\r
847 } else {\r
848 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
849 EFI_PROGRESS_CODE,\r
850 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,\r
851 SerialDevice->DevicePath\r
852 );\r
853 }\r
854 }\r
855 //\r
856 // Do the write\r
857 //\r
91c68197 858 if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
637ff819 859 //\r
860 // Make sure the transmit data will not be missed\r
861 //\r
862 if (SerialDevice->HardwareFlowControl) {\r
863 //\r
864 // Send RTS\r
865 //\r
866 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 867 Mcr.Bits.Rts |= 1;\r
637ff819 868 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
869 //\r
870 // Wait for CTS\r
871 //\r
872 TimeOut = 0;\r
873 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 874 while (Msr.Bits.Cts == 0) {\r
637ff819 875 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
876 TimeOut++;\r
877 if (TimeOut > 5) {\r
878 break;\r
879 }\r
880\r
881 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
882 }\r
883\r
91c68197 884 if (Msr.Bits.Cts == 1) {\r
637ff819 885 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
886 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
887 }\r
888 }\r
889 //\r
890 // write the data out\r
891 //\r
892 if (!SerialDevice->HardwareFlowControl) {\r
893 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
894 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
895 }\r
896 //\r
897 // Make sure the transmit data will not be missed\r
898 //\r
899 if (SerialDevice->HardwareFlowControl) {\r
900 //\r
901 // Assert RTS\r
902 //\r
903 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 904 Mcr.Bits.Rts &= 0;\r
637ff819 905 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
906 }\r
907 }\r
91c68197 908 } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
637ff819 909 }\r
910\r
911 return EFI_SUCCESS;\r
912}\r
bcd70414 913\r
637ff819 914//\r
915// Interface Functions\r
916//\r
bcd70414 917/**\r
91c68197 918 Reset serial device.\r
bcd70414 919\r
91c68197 920 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
bcd70414 921\r
91c68197
LG
922 @retval EFI_SUCCESS Reset successfully\r
923 @retval EFI_DEVICE_ERROR Failed to reset\r
bcd70414 924\r
925**/\r
637ff819 926EFI_STATUS\r
927EFIAPI\r
928IsaSerialReset (\r
929 IN EFI_SERIAL_IO_PROTOCOL *This\r
930 )\r
637ff819 931{\r
932 EFI_STATUS Status;\r
933 SERIAL_DEV *SerialDevice;\r
934 SERIAL_PORT_LCR Lcr;\r
935 SERIAL_PORT_IER Ier;\r
936 SERIAL_PORT_MCR Mcr;\r
937 SERIAL_PORT_FCR Fcr;\r
938 EFI_TPL Tpl;\r
939\r
940 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
941\r
942 //\r
943 // Report the status code reset the serial\r
944 //\r
945 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
946 EFI_PROGRESS_CODE,\r
947 EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,\r
948 SerialDevice->DevicePath\r
949 );\r
950\r
951 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
952\r
953 //\r
954 // Make sure DLAB is 0.\r
955 //\r
956 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 957 Lcr.Bits.DLab = 0;\r
637ff819 958 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
959\r
960 //\r
961 // Turn off all interrupts\r
962 //\r
963 Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197
LG
964 Ier.Bits.Ravie = 0;\r
965 Ier.Bits.Theie = 0;\r
966 Ier.Bits.Rie = 0;\r
967 Ier.Bits.Mie = 0;\r
637ff819 968 WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);\r
969\r
970 //\r
971 // Disable the FIFO.\r
972 //\r
91c68197 973 Fcr.Bits.TrFIFOE = 0;\r
637ff819 974 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
975\r
976 //\r
977 // Turn off loopback and disable device interrupt.\r
978 //\r
979 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197
LG
980 Mcr.Bits.Out1 = 0;\r
981 Mcr.Bits.Out2 = 0;\r
982 Mcr.Bits.Lme = 0;\r
637ff819 983 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
984\r
985 //\r
986 // Clear the scratch pad register\r
987 //\r
988 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);\r
989\r
990 //\r
991 // Go set the current attributes\r
992 //\r
993 Status = This->SetAttributes (\r
994 This,\r
995 This->Mode->BaudRate,\r
996 This->Mode->ReceiveFifoDepth,\r
997 This->Mode->Timeout,\r
998 (EFI_PARITY_TYPE) This->Mode->Parity,\r
999 (UINT8) This->Mode->DataBits,\r
1000 (EFI_STOP_BITS_TYPE) This->Mode->StopBits\r
1001 );\r
1002\r
1003 if (EFI_ERROR (Status)) {\r
1004 gBS->RestoreTPL (Tpl);\r
1005 return EFI_DEVICE_ERROR;\r
1006 }\r
1007 //\r
1008 // Go set the current control bits\r
1009 //\r
1010 Status = This->SetControl (\r
1011 This,\r
1012 This->Mode->ControlMask\r
1013 );\r
1014\r
1015 if (EFI_ERROR (Status)) {\r
1016 gBS->RestoreTPL (Tpl);\r
1017 return EFI_DEVICE_ERROR;\r
1018 }\r
1019 //\r
1020 // for 16550A enable FIFO, 16550 disable FIFO\r
1021 //\r
91c68197
LG
1022 Fcr.Bits.TrFIFOE = 1;\r
1023 Fcr.Bits.ResetRF = 1;\r
1024 Fcr.Bits.ResetTF = 1;\r
637ff819 1025 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
1026\r
1027 //\r
1028 // Reset the software FIFO\r
1029 //\r
1030 SerialDevice->Receive.First = 0;\r
1031 SerialDevice->Receive.Last = 0;\r
1032 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1033 SerialDevice->Transmit.First = 0;\r
1034 SerialDevice->Transmit.Last = 0;\r
1035 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1036\r
1037 gBS->RestoreTPL (Tpl);\r
1038\r
1039 //\r
1040 // Device reset is complete\r
1041 //\r
1042 return EFI_SUCCESS;\r
1043}\r
1044\r
bcd70414 1045/**\r
91c68197 1046 Set new attributes to a serial device.\r
bcd70414 1047\r
91c68197
LG
1048 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1049 @param BaudRate The baudrate of the serial device\r
1050 @param ReceiveFifoDepth The depth of receive FIFO buffer\r
1051 @param Timeout The request timeout for a single char\r
1052 @param Parity The type of parity used in serial device\r
1053 @param DataBits Number of databits used in serial device\r
1054 @param StopBits Number of stopbits used in serial device\r
bcd70414 1055\r
91c68197
LG
1056 @retval EFI_SUCCESS The new attributes were set\r
1057 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value\r
1058 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6\r
1059 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)\r
bcd70414 1060\r
1061**/\r
637ff819 1062EFI_STATUS\r
1063EFIAPI\r
1064IsaSerialSetAttributes (\r
1065 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1066 IN UINT64 BaudRate,\r
1067 IN UINT32 ReceiveFifoDepth,\r
1068 IN UINT32 Timeout,\r
1069 IN EFI_PARITY_TYPE Parity,\r
1070 IN UINT8 DataBits,\r
1071 IN EFI_STOP_BITS_TYPE StopBits\r
1072 )\r
637ff819 1073{\r
1074 EFI_STATUS Status;\r
1075 SERIAL_DEV *SerialDevice;\r
1076 UINT32 Divisor;\r
1077 UINT32 Remained;\r
1078 SERIAL_PORT_LCR Lcr;\r
1079 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1080 EFI_TPL Tpl;\r
1081\r
1082 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1083\r
1084 //\r
1085 // Check for default settings and fill in actual values.\r
1086 //\r
1087 if (BaudRate == 0) {\r
6b88ceec 1088 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);\r
637ff819 1089 }\r
1090\r
1091 if (ReceiveFifoDepth == 0) {\r
1092 ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;\r
1093 }\r
1094\r
1095 if (Timeout == 0) {\r
1096 Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;\r
1097 }\r
1098\r
1099 if (Parity == DefaultParity) {\r
6bee1632 1100 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
637ff819 1101 }\r
1102\r
1103 if (DataBits == 0) {\r
6b88ceec 1104 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
637ff819 1105 }\r
1106\r
1107 if (StopBits == DefaultStopBits) {\r
6b88ceec 1108 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);\r
637ff819 1109 }\r
1110 //\r
1111 // 5 and 6 data bits can not be verified on a 16550A UART\r
1112 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.\r
1113 //\r
1114 if ((DataBits == 5) || (DataBits == 6)) {\r
1115 return EFI_INVALID_PARAMETER;\r
1116 }\r
1117 //\r
1118 // Make sure all parameters are valid\r
1119 //\r
1120 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
1121 return EFI_INVALID_PARAMETER;\r
1122 }\r
1123 //\r
1124 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,\r
1125 // 38400,57600,115200\r
1126 //\r
1127 if (BaudRate < 75) {\r
1128 BaudRate = 50;\r
1129 } else if (BaudRate < 110) {\r
1130 BaudRate = 75;\r
1131 } else if (BaudRate < 134) {\r
1132 BaudRate = 110;\r
1133 } else if (BaudRate < 150) {\r
1134 BaudRate = 134;\r
1135 } else if (BaudRate < 300) {\r
1136 BaudRate = 150;\r
1137 } else if (BaudRate < 600) {\r
1138 BaudRate = 300;\r
1139 } else if (BaudRate < 1200) {\r
1140 BaudRate = 600;\r
1141 } else if (BaudRate < 1800) {\r
1142 BaudRate = 1200;\r
1143 } else if (BaudRate < 2000) {\r
1144 BaudRate = 1800;\r
1145 } else if (BaudRate < 2400) {\r
1146 BaudRate = 2000;\r
1147 } else if (BaudRate < 3600) {\r
1148 BaudRate = 2400;\r
1149 } else if (BaudRate < 4800) {\r
1150 BaudRate = 3600;\r
1151 } else if (BaudRate < 7200) {\r
1152 BaudRate = 4800;\r
1153 } else if (BaudRate < 9600) {\r
1154 BaudRate = 7200;\r
1155 } else if (BaudRate < 19200) {\r
1156 BaudRate = 9600;\r
1157 } else if (BaudRate < 38400) {\r
1158 BaudRate = 19200;\r
1159 } else if (BaudRate < 57600) {\r
1160 BaudRate = 38400;\r
1161 } else if (BaudRate < 115200) {\r
1162 BaudRate = 57600;\r
1163 } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {\r
1164 BaudRate = 115200;\r
1165 }\r
1166\r
1167 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
1168 return EFI_INVALID_PARAMETER;\r
1169 }\r
1170\r
1171 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
1172 return EFI_INVALID_PARAMETER;\r
1173 }\r
1174\r
1175 if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
1176 return EFI_INVALID_PARAMETER;\r
1177 }\r
1178\r
1179 if ((DataBits < 5) || (DataBits > 8)) {\r
1180 return EFI_INVALID_PARAMETER;\r
1181 }\r
1182\r
1183 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
1184 return EFI_INVALID_PARAMETER;\r
1185 }\r
1186 //\r
1187 // for DataBits = 5, StopBits can not set TwoStopBits\r
1188 //\r
1189 // if ((DataBits == 5) && (StopBits == TwoStopBits)) {\r
1190 // return EFI_INVALID_PARAMETER;\r
1191 // }\r
1192 //\r
1193 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits\r
1194 //\r
1195 if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {\r
1196 return EFI_INVALID_PARAMETER;\r
1197 }\r
1198\r
1199 //\r
1200 // Compute divisor use to program the baud rate using a round determination\r
1201 //\r
1202 Divisor = (UINT32) DivU64x32Remainder (\r
1203 SERIAL_PORT_INPUT_CLOCK,\r
1204 ((UINT32) BaudRate * 16),\r
1205 &Remained\r
1206 );\r
91c68197 1207 if (Remained != 0) {\r
637ff819 1208 Divisor += 1;\r
1209 }\r
1210\r
91c68197 1211 if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) {\r
637ff819 1212 return EFI_INVALID_PARAMETER;\r
1213 }\r
1214\r
1215 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1216\r
1217 //\r
1218 // Compute the actual baud rate that the serial port will be programmed for.\r
1219 //\r
1220 BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;\r
1221\r
1222 //\r
1223 // Put serial port on Divisor Latch Mode\r
1224 //\r
1225 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 1226 Lcr.Bits.DLab = 1;\r
637ff819 1227 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1228\r
1229 //\r
1230 // Write the divisor to the serial port\r
1231 //\r
1232 WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));\r
1233 WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));\r
1234\r
1235 //\r
1236 // Put serial port back in normal mode and set remaining attributes.\r
1237 //\r
91c68197 1238 Lcr.Bits.DLab = 0;\r
637ff819 1239\r
1240 switch (Parity) {\r
1241 case NoParity:\r
91c68197
LG
1242 Lcr.Bits.ParEn = 0;\r
1243 Lcr.Bits.EvenPar = 0;\r
1244 Lcr.Bits.SticPar = 0;\r
637ff819 1245 break;\r
1246\r
1247 case EvenParity:\r
91c68197
LG
1248 Lcr.Bits.ParEn = 1;\r
1249 Lcr.Bits.EvenPar = 1;\r
1250 Lcr.Bits.SticPar = 0;\r
637ff819 1251 break;\r
1252\r
1253 case OddParity:\r
91c68197
LG
1254 Lcr.Bits.ParEn = 1;\r
1255 Lcr.Bits.EvenPar = 0;\r
1256 Lcr.Bits.SticPar = 0;\r
637ff819 1257 break;\r
1258\r
1259 case SpaceParity:\r
91c68197
LG
1260 Lcr.Bits.ParEn = 1;\r
1261 Lcr.Bits.EvenPar = 1;\r
1262 Lcr.Bits.SticPar = 1;\r
637ff819 1263 break;\r
1264\r
1265 case MarkParity:\r
91c68197
LG
1266 Lcr.Bits.ParEn = 1;\r
1267 Lcr.Bits.EvenPar = 0;\r
1268 Lcr.Bits.SticPar = 1;\r
637ff819 1269 break;\r
1270\r
1271 default:\r
1272 break;\r
1273 }\r
1274\r
1275 switch (StopBits) {\r
1276 case OneStopBit:\r
91c68197 1277 Lcr.Bits.StopB = 0;\r
637ff819 1278 break;\r
1279\r
1280 case OneFiveStopBits:\r
1281 case TwoStopBits:\r
91c68197 1282 Lcr.Bits.StopB = 1;\r
637ff819 1283 break;\r
1284\r
1285 default:\r
1286 break;\r
1287 }\r
1288 //\r
1289 // DataBits\r
1290 //\r
91c68197 1291 Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03);\r
637ff819 1292 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
1293\r
1294 //\r
1295 // Set the Serial I/O mode\r
1296 //\r
1297 This->Mode->BaudRate = BaudRate;\r
1298 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;\r
1299 This->Mode->Timeout = Timeout;\r
1300 This->Mode->Parity = Parity;\r
1301 This->Mode->DataBits = DataBits;\r
1302 This->Mode->StopBits = StopBits;\r
1303\r
1304 //\r
1305 // See if Device Path Node has actually changed\r
1306 //\r
1307 if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&\r
1308 SerialDevice->UartDevicePath.DataBits == DataBits &&\r
1309 SerialDevice->UartDevicePath.Parity == Parity &&\r
1310 SerialDevice->UartDevicePath.StopBits == StopBits\r
1311 ) {\r
1312 gBS->RestoreTPL (Tpl);\r
1313 return EFI_SUCCESS;\r
1314 }\r
1315 //\r
1316 // Update the device path\r
1317 //\r
1318 SerialDevice->UartDevicePath.BaudRate = BaudRate;\r
1319 SerialDevice->UartDevicePath.DataBits = DataBits;\r
1320 SerialDevice->UartDevicePath.Parity = (UINT8) Parity;\r
1321 SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;\r
1322\r
1323 NewDevicePath = AppendDevicePathNode (\r
1324 SerialDevice->ParentDevicePath,\r
1325 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath\r
1326 );\r
1327 if (NewDevicePath == NULL) {\r
1328 gBS->RestoreTPL (Tpl);\r
1329 return EFI_DEVICE_ERROR;\r
1330 }\r
1331\r
1332 if (SerialDevice->Handle != NULL) {\r
1333 Status = gBS->ReinstallProtocolInterface (\r
1334 SerialDevice->Handle,\r
1335 &gEfiDevicePathProtocolGuid,\r
1336 SerialDevice->DevicePath,\r
1337 NewDevicePath\r
1338 );\r
1339 if (EFI_ERROR (Status)) {\r
1340 gBS->RestoreTPL (Tpl);\r
1341 return Status;\r
1342 }\r
1343 }\r
1344\r
91c68197 1345 if (SerialDevice->DevicePath != NULL) {\r
637ff819 1346 gBS->FreePool (SerialDevice->DevicePath);\r
1347 }\r
1348\r
1349 SerialDevice->DevicePath = NewDevicePath;\r
1350\r
1351 gBS->RestoreTPL (Tpl);\r
1352\r
1353 return EFI_SUCCESS;\r
1354}\r
1355\r
bcd70414 1356/**\r
91c68197 1357 Set Control Bits.\r
bcd70414 1358\r
91c68197
LG
1359 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1360 @param Control Control bits that can be settable\r
bcd70414 1361\r
91c68197
LG
1362 @retval EFI_SUCCESS New Control bits were set successfully\r
1363 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported\r
bcd70414 1364\r
1365**/\r
637ff819 1366EFI_STATUS\r
1367EFIAPI\r
1368IsaSerialSetControl (\r
1369 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1370 IN UINT32 Control\r
1371 )\r
637ff819 1372{\r
1373 SERIAL_DEV *SerialDevice;\r
1374 SERIAL_PORT_MCR Mcr;\r
1375 EFI_TPL Tpl;\r
1376\r
1377 //\r
1378 // The control bits that can be set are :\r
1379 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO\r
1380 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO\r
1381 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW\r
1382 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW\r
1383 //\r
1384 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1385\r
1386 //\r
1387 // first determine the parameter is invalid\r
1388 //\r
91c68197 1389 if ((Control & 0xffff8ffc) != 0) {\r
637ff819 1390 return EFI_UNSUPPORTED;\r
1391 }\r
1392\r
1393 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1394\r
1395 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197
LG
1396 Mcr.Bits.DtrC = 0;\r
1397 Mcr.Bits.Rts = 0;\r
1398 Mcr.Bits.Lme = 0;\r
637ff819 1399 SerialDevice->SoftwareLoopbackEnable = FALSE;\r
1400 SerialDevice->HardwareFlowControl = FALSE;\r
1401\r
91c68197
LG
1402 if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {\r
1403 Mcr.Bits.DtrC = 1;\r
637ff819 1404 }\r
1405\r
91c68197
LG
1406 if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {\r
1407 Mcr.Bits.Rts = 1;\r
637ff819 1408 }\r
1409\r
91c68197
LG
1410 if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {\r
1411 Mcr.Bits.Lme = 1;\r
637ff819 1412 }\r
1413\r
91c68197 1414 if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
637ff819 1415 SerialDevice->HardwareFlowControl = TRUE;\r
1416 }\r
1417\r
1418 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
1419\r
91c68197 1420 if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {\r
637ff819 1421 SerialDevice->SoftwareLoopbackEnable = TRUE;\r
1422 }\r
1423\r
1424 gBS->RestoreTPL (Tpl);\r
1425\r
1426 return EFI_SUCCESS;\r
1427}\r
1428\r
bcd70414 1429/**\r
91c68197 1430 Get ControlBits.\r
bcd70414 1431\r
91c68197
LG
1432 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1433 @param Control Control signals of the serial device\r
bcd70414 1434\r
91c68197 1435 @retval EFI_SUCCESS Get Control signals successfully\r
bcd70414 1436\r
1437**/\r
637ff819 1438EFI_STATUS\r
1439EFIAPI\r
1440IsaSerialGetControl (\r
1441 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1442 OUT UINT32 *Control\r
1443 )\r
637ff819 1444{\r
1445 SERIAL_DEV *SerialDevice;\r
1446 SERIAL_PORT_MSR Msr;\r
1447 SERIAL_PORT_MCR Mcr;\r
1448 EFI_TPL Tpl;\r
1449\r
1450 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1451\r
1452 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1453\r
1454 *Control = 0;\r
1455\r
1456 //\r
1457 // Read the Modem Status Register\r
1458 //\r
1459 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1460\r
91c68197 1461 if (Msr.Bits.Cts == 1) {\r
637ff819 1462 *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
1463 }\r
1464\r
91c68197 1465 if (Msr.Bits.Dsr == 1) {\r
637ff819 1466 *Control |= EFI_SERIAL_DATA_SET_READY;\r
1467 }\r
1468\r
91c68197 1469 if (Msr.Bits.Ri == 1) {\r
637ff819 1470 *Control |= EFI_SERIAL_RING_INDICATE;\r
1471 }\r
1472\r
91c68197 1473 if (Msr.Bits.Dcd == 1) {\r
637ff819 1474 *Control |= EFI_SERIAL_CARRIER_DETECT;\r
1475 }\r
1476 //\r
1477 // Read the Modem Control Register\r
1478 //\r
1479 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1480\r
91c68197 1481 if (Mcr.Bits.DtrC == 1) {\r
637ff819 1482 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
1483 }\r
1484\r
91c68197 1485 if (Mcr.Bits.Rts == 1) {\r
637ff819 1486 *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
1487 }\r
1488\r
91c68197 1489 if (Mcr.Bits.Lme == 1) {\r
637ff819 1490 *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
1491 }\r
1492\r
1493 if (SerialDevice->HardwareFlowControl) {\r
1494 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
1495 }\r
1496 //\r
1497 // See if the Transmit FIFO is empty\r
1498 //\r
1499 IsaSerialReceiveTransmit (SerialDevice);\r
1500\r
1501 if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1502 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
1503 }\r
1504 //\r
1505 // See if the Receive FIFO is empty.\r
1506 //\r
1507 IsaSerialReceiveTransmit (SerialDevice);\r
1508\r
1509 if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {\r
1510 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
1511 }\r
1512\r
1513 if (SerialDevice->SoftwareLoopbackEnable) {\r
1514 *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
1515 }\r
1516\r
1517 gBS->RestoreTPL (Tpl);\r
1518\r
1519 return EFI_SUCCESS;\r
1520}\r
1521\r
bcd70414 1522/**\r
91c68197 1523 Write the specified number of bytes to serial device.\r
bcd70414 1524\r
91c68197
LG
1525 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1526 @param BufferSize On input the size of Buffer, on output the amount of\r
bcd70414 1527 data actually written\r
91c68197 1528 @param Buffer The buffer of data to write\r
bcd70414 1529\r
91c68197
LG
1530 @retval EFI_SUCCESS The data were written successfully\r
1531 @retval EFI_DEVICE_ERROR The device reported an error\r
1532 @retval EFI_TIMEOUT The write operation was stopped due to timeout\r
bcd70414 1533\r
1534**/\r
637ff819 1535EFI_STATUS\r
1536EFIAPI\r
1537IsaSerialWrite (\r
1538 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1539 IN OUT UINTN *BufferSize,\r
1540 IN VOID *Buffer\r
1541 )\r
637ff819 1542{\r
1543 SERIAL_DEV *SerialDevice;\r
1544 UINT8 *CharBuffer;\r
1545 UINT32 Index;\r
1546 UINTN Elapsed;\r
1547 UINTN ActualWrite;\r
1548 EFI_TPL Tpl;\r
1549\r
1550 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1551 Elapsed = 0;\r
1552 ActualWrite = 0;\r
1553\r
1554 if (*BufferSize == 0) {\r
1555 return EFI_SUCCESS;\r
1556 }\r
1557\r
91c68197 1558 if (Buffer == NULL) {\r
637ff819 1559 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1560 EFI_ERROR_CODE,\r
1561 EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1562 SerialDevice->DevicePath\r
1563 );\r
1564\r
1565 return EFI_DEVICE_ERROR;\r
1566 }\r
1567\r
1568 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1569\r
1570 CharBuffer = (UINT8 *) Buffer;\r
1571\r
1572 for (Index = 0; Index < *BufferSize; Index++) {\r
1573 IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);\r
1574\r
1575 while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
1576 //\r
1577 // Unsuccessful write so check if timeout has expired, if not,\r
1578 // stall for a bit, increment time elapsed, and try again\r
1579 //\r
1580 if (Elapsed >= This->Mode->Timeout) {\r
1581 *BufferSize = ActualWrite;\r
1582 gBS->RestoreTPL (Tpl);\r
1583 return EFI_TIMEOUT;\r
1584 }\r
1585\r
1586 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1587\r
1588 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1589 }\r
1590\r
1591 ActualWrite++;\r
1592 //\r
1593 // Successful write so reset timeout\r
1594 //\r
1595 Elapsed = 0;\r
1596 }\r
1597\r
1598 gBS->RestoreTPL (Tpl);\r
1599\r
1600 return EFI_SUCCESS;\r
1601}\r
1602\r
bcd70414 1603/**\r
91c68197 1604 Read the specified number of bytes from serial device.\r
bcd70414 1605\r
91c68197
LG
1606 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1607 @param BufferSize On input the size of Buffer, on output the amount of\r
1608 data returned in buffer\r
1609 @param Buffer The buffer to return the data into\r
bcd70414 1610\r
91c68197
LG
1611 @retval EFI_SUCCESS The data were read successfully\r
1612 @retval EFI_DEVICE_ERROR The device reported an error\r
1613 @retval EFI_TIMEOUT The read operation was stopped due to timeout\r
bcd70414 1614\r
1615**/\r
637ff819 1616EFI_STATUS\r
1617EFIAPI\r
1618IsaSerialRead (\r
1619 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1620 IN OUT UINTN *BufferSize,\r
1621 OUT VOID *Buffer\r
1622 )\r
637ff819 1623{\r
1624 SERIAL_DEV *SerialDevice;\r
1625 UINT32 Index;\r
1626 UINT8 *CharBuffer;\r
1627 UINTN Elapsed;\r
1628 EFI_STATUS Status;\r
1629 EFI_TPL Tpl;\r
1630\r
1631 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1632 Elapsed = 0;\r
1633\r
1634 if (*BufferSize == 0) {\r
1635 return EFI_SUCCESS;\r
1636 }\r
1637\r
91c68197 1638 if (Buffer == NULL) {\r
637ff819 1639 return EFI_DEVICE_ERROR;\r
1640 }\r
1641\r
1642 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1643\r
1644 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1645\r
1646 if (EFI_ERROR (Status)) {\r
1647 *BufferSize = 0;\r
1648\r
1649 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1650 EFI_ERROR_CODE,\r
1651 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
1652 SerialDevice->DevicePath\r
1653 );\r
1654\r
1655 gBS->RestoreTPL (Tpl);\r
1656\r
1657 return EFI_DEVICE_ERROR;\r
1658 }\r
1659\r
1660 CharBuffer = (UINT8 *) Buffer;\r
1661 for (Index = 0; Index < *BufferSize; Index++) {\r
1662 while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {\r
1663 //\r
1664 // Unsuccessful read so check if timeout has expired, if not,\r
1665 // stall for a bit, increment time elapsed, and try again\r
1666 // Need this time out to get conspliter to work.\r
1667 //\r
1668 if (Elapsed >= This->Mode->Timeout) {\r
1669 *BufferSize = Index;\r
1670 gBS->RestoreTPL (Tpl);\r
1671 return EFI_TIMEOUT;\r
1672 }\r
1673\r
1674 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
1675 Elapsed += TIMEOUT_STALL_INTERVAL;\r
1676\r
1677 Status = IsaSerialReceiveTransmit (SerialDevice);\r
1678 if (Status == EFI_DEVICE_ERROR) {\r
1679 *BufferSize = Index;\r
1680 gBS->RestoreTPL (Tpl);\r
1681 return EFI_DEVICE_ERROR;\r
1682 }\r
1683 }\r
1684 //\r
1685 // Successful read so reset timeout\r
1686 //\r
1687 Elapsed = 0;\r
1688 }\r
1689\r
1690 IsaSerialReceiveTransmit (SerialDevice);\r
1691\r
1692 gBS->RestoreTPL (Tpl);\r
1693\r
1694 return EFI_SUCCESS;\r
1695}\r
1696\r
bcd70414 1697/**\r
91c68197 1698 Use scratchpad register to test if this serial port is present.\r
bcd70414 1699\r
91c68197 1700 @param SerialDevice Pointer to serial device structure\r
bcd70414 1701\r
1702 @return if this serial port is present\r
1703**/\r
637ff819 1704BOOLEAN\r
1705IsaSerialPortPresent (\r
1706 IN SERIAL_DEV *SerialDevice\r
1707 )\r
637ff819 1708\r
637ff819 1709{\r
1710 UINT8 Temp;\r
1711 BOOLEAN Status;\r
1712\r
1713 Status = TRUE;\r
1714\r
1715 //\r
1716 // Save SCR reg\r
1717 //\r
1718 Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
1719 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);\r
1720\r
6b88ceec 1721 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) {\r
ea2d9086 1722 Status = FALSE;\r
637ff819 1723 }\r
1724\r
1725 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);\r
1726\r
6b88ceec 1727 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) {\r
ea2d9086 1728 Status = FALSE;\r
637ff819 1729 }\r
1730 //\r
1731 // Restore SCR\r
1732 //\r
1733 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);\r
1734 return Status;\r
1735}\r
1736\r
bcd70414 1737/**\r
91c68197 1738 Use IsaIo protocol to read serial port.\r
bcd70414 1739\r
91c68197
LG
1740 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance\r
1741 @param BaseAddress Serial port register group base address\r
1742 @param Offset Offset in register group\r
bcd70414 1743\r
1744 @return Data read from serial port\r
1745\r
1746**/\r
637ff819 1747UINT8\r
1748IsaSerialReadPort (\r
1749 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1750 IN UINT16 BaseAddress,\r
1751 IN UINT32 Offset\r
1752 )\r
637ff819 1753{\r
1754 UINT8 Data;\r
1755\r
1756 //\r
1757 // Use IsaIo to access IO\r
1758 //\r
1759 IsaIo->Io.Read (\r
1760 IsaIo,\r
1761 EfiIsaIoWidthUint8,\r
1762 BaseAddress + Offset,\r
1763 1,\r
1764 &Data\r
1765 );\r
1766 return Data;\r
1767}\r
1768\r
bcd70414 1769/**\r
91c68197 1770 Use IsaIo protocol to write serial port.\r
bcd70414 1771\r
91c68197
LG
1772 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance\r
1773 @param BaseAddress Serial port register group base address\r
1774 @param Offset Offset in register group\r
1775 @param Data data which is to be written to some serial port register\r
bcd70414 1776\r
1777**/\r
637ff819 1778VOID\r
1779IsaSerialWritePort (\r
1780 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
1781 IN UINT16 BaseAddress,\r
1782 IN UINT32 Offset,\r
1783 IN UINT8 Data\r
1784 )\r
637ff819 1785{\r
1786 //\r
1787 // Use IsaIo to access IO\r
1788 //\r
1789 IsaIo->Io.Write (\r
1790 IsaIo,\r
1791 EfiIsaIoWidthUint8,\r
1792 BaseAddress + Offset,\r
1793 1,\r
1794 &Data\r
1795 );\r
1796}\r
1797\r