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