]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
Clean up code
[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
77b91d89 86 NULL\r
6b88ceec
A
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
fa70a2c4 804 //\r
805 // For full handshake flow control, tell the peer to send data\r
806 // if receive buffer is available.\r
807 //\r
808 if (SerialDevice->HardwareFlowControl &&\r
77b91d89 809 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&&\r
fa70a2c4 810 !ReceiveFifoFull\r
811 ) {\r
812 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
813 Mcr.Bits.Rts = 1;\r
814 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
815 }\r
637ff819 816 do {\r
817 Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
818\r
637ff819 819 //\r
820 // Flush incomming data to prevent a an overrun during a long write\r
821 //\r
91c68197 822 if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {\r
637ff819 823 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);\r
824 if (!ReceiveFifoFull) {\r
91c68197 825 if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {\r
637ff819 826 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
827 EFI_ERROR_CODE,\r
828 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,\r
829 SerialDevice->DevicePath\r
830 );\r
91c68197 831 if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {\r
637ff819 832 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
833 continue;\r
834 }\r
835 }\r
637ff819 836\r
837 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
838\r
fa70a2c4 839 IsaSerialFifoAdd (&SerialDevice->Receive, Data);\r
840 \r
637ff819 841 //\r
fa70a2c4 842 // For full handshake flow control, if receive buffer full\r
843 // tell the peer to stop sending data.\r
637ff819 844 //\r
fa70a2c4 845 if (SerialDevice->HardwareFlowControl &&\r
77b91d89 846 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) &&\r
fa70a2c4 847 IsaSerialFifoFull (&SerialDevice->Receive)\r
848 ) {\r
849 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
850 Mcr.Bits.Rts = 0;\r
637ff819 851 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
852 }\r
853\r
637ff819 854\r
855 continue;\r
856 } else {\r
857 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
858 EFI_PROGRESS_CODE,\r
859 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,\r
860 SerialDevice->DevicePath\r
861 );\r
862 }\r
863 }\r
864 //\r
865 // Do the write\r
866 //\r
91c68197 867 if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {\r
637ff819 868 //\r
869 // Make sure the transmit data will not be missed\r
870 //\r
871 if (SerialDevice->HardwareFlowControl) {\r
872 //\r
fa70a2c4 873 // For half handshake flow control assert RTS before sending.\r
637ff819 874 //\r
77b91d89 875 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {\r
fa70a2c4 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
637ff819 880 //\r
881 // Wait for CTS\r
882 //\r
883 TimeOut = 0;\r
884 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
19bf20e1 885 while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {\r
637ff819 886 gBS->Stall (TIMEOUT_STALL_INTERVAL);\r
887 TimeOut++;\r
888 if (TimeOut > 5) {\r
889 break;\r
890 }\r
891\r
892 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
893 }\r
894\r
19bf20e1 895 if ((Msr.Bits.Dcd == 0) && ((Msr.Bits.Cts == 1) || FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {\r
637ff819 896 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
897 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
898 }\r
fa70a2c4 899\r
637ff819 900 //\r
fa70a2c4 901 // For half handshake flow control, tell DCE we are done.\r
637ff819 902 //\r
77b91d89 903 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {\r
fa70a2c4 904 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
905 Mcr.Bits.Rts = 1;\r
906 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
907 }\r
908 } else {\r
909 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);\r
910 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);\r
637ff819 911 }\r
912 }\r
91c68197 913 } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit));\r
637ff819 914 }\r
915\r
916 return EFI_SUCCESS;\r
917}\r
bcd70414 918\r
637ff819 919//\r
920// Interface Functions\r
921//\r
bcd70414 922/**\r
91c68197 923 Reset serial device.\r
bcd70414 924\r
91c68197 925 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
bcd70414 926\r
91c68197
LG
927 @retval EFI_SUCCESS Reset successfully\r
928 @retval EFI_DEVICE_ERROR Failed to reset\r
bcd70414 929\r
930**/\r
637ff819 931EFI_STATUS\r
932EFIAPI\r
933IsaSerialReset (\r
934 IN EFI_SERIAL_IO_PROTOCOL *This\r
935 )\r
637ff819 936{\r
937 EFI_STATUS Status;\r
938 SERIAL_DEV *SerialDevice;\r
939 SERIAL_PORT_LCR Lcr;\r
940 SERIAL_PORT_IER Ier;\r
941 SERIAL_PORT_MCR Mcr;\r
942 SERIAL_PORT_FCR Fcr;\r
943 EFI_TPL Tpl;\r
944\r
945 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
946\r
947 //\r
948 // Report the status code reset the serial\r
949 //\r
950 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
951 EFI_PROGRESS_CODE,\r
952 EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,\r
953 SerialDevice->DevicePath\r
954 );\r
955\r
956 Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
957\r
958 //\r
959 // Make sure DLAB is 0.\r
960 //\r
961 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197 962 Lcr.Bits.DLab = 0;\r
637ff819 963 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);\r
964\r
965 //\r
966 // Turn off all interrupts\r
967 //\r
968 Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197
LG
969 Ier.Bits.Ravie = 0;\r
970 Ier.Bits.Theie = 0;\r
971 Ier.Bits.Rie = 0;\r
972 Ier.Bits.Mie = 0;\r
637ff819 973 WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);\r
974\r
975 //\r
976 // Disable the FIFO.\r
977 //\r
91c68197 978 Fcr.Bits.TrFIFOE = 0;\r
637ff819 979 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
980\r
981 //\r
982 // Turn off loopback and disable device interrupt.\r
983 //\r
984 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);\r
91c68197
LG
985 Mcr.Bits.Out1 = 0;\r
986 Mcr.Bits.Out2 = 0;\r
987 Mcr.Bits.Lme = 0;\r
637ff819 988 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);\r
989\r
990 //\r
991 // Clear the scratch pad register\r
992 //\r
993 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);\r
994\r
995 //\r
996 // Go set the current attributes\r
997 //\r
998 Status = This->SetAttributes (\r
999 This,\r
1000 This->Mode->BaudRate,\r
1001 This->Mode->ReceiveFifoDepth,\r
1002 This->Mode->Timeout,\r
1003 (EFI_PARITY_TYPE) This->Mode->Parity,\r
1004 (UINT8) This->Mode->DataBits,\r
1005 (EFI_STOP_BITS_TYPE) This->Mode->StopBits\r
1006 );\r
1007\r
1008 if (EFI_ERROR (Status)) {\r
1009 gBS->RestoreTPL (Tpl);\r
1010 return EFI_DEVICE_ERROR;\r
1011 }\r
1012 //\r
1013 // Go set the current control bits\r
1014 //\r
1015 Status = This->SetControl (\r
1016 This,\r
1017 This->Mode->ControlMask\r
1018 );\r
1019\r
1020 if (EFI_ERROR (Status)) {\r
1021 gBS->RestoreTPL (Tpl);\r
1022 return EFI_DEVICE_ERROR;\r
1023 }\r
1024 //\r
1025 // for 16550A enable FIFO, 16550 disable FIFO\r
1026 //\r
91c68197
LG
1027 Fcr.Bits.TrFIFOE = 1;\r
1028 Fcr.Bits.ResetRF = 1;\r
1029 Fcr.Bits.ResetTF = 1;\r
637ff819 1030 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);\r
1031\r
1032 //\r
1033 // Reset the software FIFO\r
1034 //\r
1035 SerialDevice->Receive.First = 0;\r
1036 SerialDevice->Receive.Last = 0;\r
1037 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1038 SerialDevice->Transmit.First = 0;\r
1039 SerialDevice->Transmit.Last = 0;\r
1040 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
1041\r
1042 gBS->RestoreTPL (Tpl);\r
1043\r
1044 //\r
1045 // Device reset is complete\r
1046 //\r
1047 return EFI_SUCCESS;\r
1048}\r
1049\r
bcd70414 1050/**\r
91c68197 1051 Set new attributes to a serial device.\r
bcd70414 1052\r
91c68197
LG
1053 @param This Pointer to EFI_SERIAL_IO_PROTOCOL\r
1054 @param BaudRate The baudrate of the serial device\r
1055 @param ReceiveFifoDepth The depth of receive FIFO buffer\r
1056 @param Timeout The request timeout for a single char\r
1057 @param Parity The type of parity used in serial device\r
1058 @param DataBits Number of databits used in serial device\r
1059 @param StopBits Number of stopbits used in serial device\r
bcd70414 1060\r
91c68197
LG
1061 @retval EFI_SUCCESS The new attributes were set\r
1062 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value\r
1063 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6\r
1064 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)\r
bcd70414 1065\r
1066**/\r
637ff819 1067EFI_STATUS\r
1068EFIAPI\r
1069IsaSerialSetAttributes (\r
1070 IN EFI_SERIAL_IO_PROTOCOL *This,\r
1071 IN UINT64 BaudRate,\r
1072 IN UINT32 ReceiveFifoDepth,\r
1073 IN UINT32 Timeout,\r
1074 IN EFI_PARITY_TYPE Parity,\r
1075 IN UINT8 DataBits,\r
1076 IN EFI_STOP_BITS_TYPE StopBits\r
1077 )\r
637ff819 1078{\r
1079 EFI_STATUS Status;\r
1080 SERIAL_DEV *SerialDevice;\r
1081 UINT32 Divisor;\r
1082 UINT32 Remained;\r
1083 SERIAL_PORT_LCR Lcr;\r
1084 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1085 EFI_TPL Tpl;\r
1086\r
1087 SerialDevice = SERIAL_DEV_FROM_THIS (This);\r
1088\r
1089 //\r
1090 // Check for default settings and fill in actual values.\r
1091 //\r
1092 if (BaudRate == 0) {\r
6b88ceec 1093 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);\r
637ff819 1094 }\r
1095\r
1096 if (ReceiveFifoDepth == 0) {\r
1097 ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;\r
1098 }\r
1099\r
1100 if (Timeout == 0) {\r
1101 Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;\r
1102 }\r
1103\r
1104 if (Parity == DefaultParity) {\r
6bee1632 1105 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
637ff819 1106 }\r
1107\r
1108 if (DataBits == 0) {\r
6b88ceec 1109 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
637ff819 1110 }\r
1111\r
1112 if (StopBits == DefaultStopBits) {\r
6b88ceec 1113 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);\r
637ff819 1114 }\r
1115 //\r
1116 // 5 and 6 data bits can not be verified on a 16550A UART\r
1117 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.\r
1118 //\r
1119 if ((DataBits == 5) || (DataBits == 6)) {\r
1120 return EFI_INVALID_PARAMETER;\r
1121 }\r
1122 //\r
1123 // Make sure all parameters are valid\r
1124 //\r
1125 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
1126 return EFI_INVALID_PARAMETER;\r
1127 }\r
1128 //\r
1129 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,\r
1130 // 38400,57600,115200\r
1131 //\r
1132 if (BaudRate < 75) {\r
1133 BaudRate = 50;\r
1134 } else if (BaudRate < 110) {\r
1135 BaudRate = 75;\r
1136 } else if (BaudRate < 134) {\r
1137 BaudRate = 110;\r
1138 } else if (BaudRate < 150) {\r
1139 BaudRate = 134;\r
1140 } else if (BaudRate < 300) {\r
1141 BaudRate = 150;\r
1142 } else if (BaudRate < 600) {\r
1143 BaudRate = 300;\r
1144 } else if (BaudRate < 1200) {\r
1145 BaudRate = 600;\r
1146 } else if (BaudRate < 1800) {\r
1147 BaudRate = 1200;\r
1148 } else if (BaudRate < 2000) {\r
1149 BaudRate = 1800;\r
1150 } else if (BaudRate < 2400) {\r
1151 BaudRate = 2000;\r
1152 } else if (BaudRate < 3600) {\r
1153 BaudRate = 2400;\r
1154 } else if (BaudRate < 4800) {\r
1155 BaudRate = 3600;\r
1156 } else if (BaudRate < 7200) {\r
1157 BaudRate = 4800;\r
1158 } else if (BaudRate < 9600) {\r
1159 BaudRate = 7200;\r
1160 } else if (BaudRate < 19200) {\r
1161 BaudRate = 9600;\r
1162 } else if (BaudRate < 38400) {\r
1163 BaudRate = 19200;\r
1164 } else if (BaudRate < 57600) {\r
1165 BaudRate = 38400;\r
1166 } else if (BaudRate < 115200) {\r
1167 BaudRate = 57600;\r
1168 } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {\r
1169 BaudRate = 115200;\r
1170 }\r
1171\r
1172 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
1173 return EFI_INVALID_PARAMETER;\r
1174 }\r
1175\r
1176 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
1177 return EFI_INVALID_PARAMETER;\r
1178 }\r
1179\r
1180 if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
1181 return EFI_INVALID_PARAMETER;\r
1182 }\r
1183\r
1184 if ((DataBits < 5) || (DataBits > 8)) {\r
1185 return EFI_INVALID_PARAMETER;\r
1186 }\r
1187\r
1188 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
1189 return EFI_INVALID_PARAMETER;\r
1190 }\r
19bf20e1 1191\r
637ff819 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