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