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