TianoCore EDK2 master
Loading...
Searching...
No Matches
BaseSerialPortLib16550.c
Go to the documentation of this file.
1
13#include <Base.h>
16#include <Library/PcdLib.h>
17#include <Library/IoLib.h>
18#include <Library/PciLib.h>
20#include <Library/BaseLib.h>
21
22//
23// PCI Defintions.
24//
25#define PCI_BRIDGE_32_BIT_IO_SPACE 0x01
26
27//
28// 16550 UART register offsets and bitfields
29//
30#define R_UART_RXBUF 0 // LCR_DLAB = 0
31#define R_UART_TXBUF 0 // LCR_DLAB = 0
32#define R_UART_BAUD_LOW 0 // LCR_DLAB = 1
33#define R_UART_BAUD_HIGH 1 // LCR_DLAB = 1
34#define R_UART_IER 1 // LCR_DLAB = 0
35#define R_UART_FCR 2
36#define B_UART_FCR_FIFOE BIT0
37#define B_UART_FCR_FIFO64 BIT5
38#define R_UART_LCR 3
39#define B_UART_LCR_DLAB BIT7
40#define R_UART_MCR 4
41#define B_UART_MCR_DTRC BIT0
42#define B_UART_MCR_RTS BIT1
43#define R_UART_LSR 5
44#define B_UART_LSR_RXRDY BIT0
45#define B_UART_LSR_TXRDY BIT5
46#define B_UART_LSR_TEMT BIT6
47#define R_UART_MSR 6
48#define B_UART_MSR_CTS BIT4
49#define B_UART_MSR_DSR BIT5
50#define B_UART_MSR_RI BIT6
51#define B_UART_MSR_DCD BIT7
52
53//
54// 4-byte structure for each PCI node in PcdSerialPciDeviceInfo
55//
56typedef struct {
57 UINT8 Device;
58 UINT8 Function;
59 UINT16 PowerManagementStatusAndControlRegister;
61
75UINT8
77 UINTN Base,
78 UINTN Offset
79 )
80{
81 if (PcdGetBool (PcdSerialUseMmio)) {
82 if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
83 return (UINT8)MmioRead32 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
84 }
85
86 return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
87 } else {
88 return IoRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride));
89 }
90}
91
106UINT8
108 UINTN Base,
109 UINTN Offset,
110 UINT8 Value
111 )
112{
113 if (PcdGetBool (PcdSerialUseMmio)) {
114 if (PcdGet8 (PcdSerialRegisterAccessWidth) == 32) {
115 return (UINT8)MmioWrite32 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), (UINT8)Value);
116 }
117
118 return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value);
119 } else {
120 return IoWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value);
121 }
122}
123
137UINT16
139 UINTN PciAddress,
140 UINT16 Value,
141 UINT16 Mask
142 )
143{
144 UINT16 CurrentValue;
145
146 CurrentValue = PciRead16 (PciAddress) & Mask;
147 if (CurrentValue != 0) {
148 return CurrentValue;
149 }
150
151 return PciWrite16 (PciAddress, Value & Mask);
152}
153
169UINT32
171 UINTN PciAddress,
172 UINT32 Value,
173 UINT32 Mask
174 )
175{
176 UINT32 CurrentValue;
177
178 CurrentValue = PciRead32 (PciAddress) & Mask;
179 if (CurrentValue != 0) {
180 return CurrentValue;
181 }
182
183 return PciWrite32 (PciAddress, Value & Mask);
184}
185
195UINTN
197 VOID
198 )
199{
200 UINTN PciLibAddress;
201 UINTN BusNumber;
202 UINTN SubordinateBusNumber;
203 UINT32 ParentIoBase;
204 UINT32 ParentIoLimit;
205 UINT16 ParentMemoryBase;
206 UINT16 ParentMemoryLimit;
207 UINT32 IoBase;
208 UINT32 IoLimit;
209 UINT16 MemoryBase;
210 UINT16 MemoryLimit;
211 UINTN SerialRegisterBase;
212 UINTN BarIndex;
213 UINT32 RegisterBaseMask;
214 PCI_UART_DEVICE_INFO *DeviceInfo;
215
216 //
217 // Get PCI Device Info
218 //
219 DeviceInfo = (PCI_UART_DEVICE_INFO *)PcdGetPtr (PcdSerialPciDeviceInfo);
220
221 //
222 // If PCI Device Info is empty, then assume fixed address UART and return PcdSerialRegisterBase
223 //
224 if (DeviceInfo->Device == 0xff) {
225 return (UINTN)PcdGet64 (PcdSerialRegisterBase);
226 }
227
228 //
229 // Assume PCI Bus 0 I/O window is 0-64KB and MMIO windows is 0-4GB
230 //
231 ParentMemoryBase = 0 >> 16;
232 ParentMemoryLimit = 0xfff00000 >> 16;
233 ParentIoBase = 0 >> 12;
234 ParentIoLimit = 0xf000 >> 12;
235
236 //
237 // Enable I/O and MMIO in PCI Bridge
238 // Assume Root Bus Numer is Zero.
239 //
240 for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) {
241 //
242 // Compute PCI Lib Address to PCI to PCI Bridge
243 //
244 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);
245
246 //
247 // Retrieve and verify the bus numbers in the PCI to PCI Bridge
248 //
249 BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
250 SubordinateBusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
251 if ((BusNumber == 0) || (BusNumber > SubordinateBusNumber)) {
252 return 0;
253 }
254
255 //
256 // Retrieve and verify the I/O or MMIO decode window in the PCI to PCI Bridge
257 //
258 if (PcdGetBool (PcdSerialUseMmio)) {
259 MemoryLimit = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xfff0;
260 MemoryBase = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xfff0;
261
262 //
263 // If PCI Bridge MMIO window is disabled, then return 0
264 //
265 if (MemoryLimit < MemoryBase) {
266 return 0;
267 }
268
269 //
270 // If PCI Bridge MMIO window is not in the address range decoded by the parent PCI Bridge, then return 0
271 //
272 if ((MemoryBase < ParentMemoryBase) || (MemoryBase > ParentMemoryLimit) || (MemoryLimit > ParentMemoryLimit)) {
273 return 0;
274 }
275
276 ParentMemoryBase = MemoryBase;
277 ParentMemoryLimit = MemoryLimit;
278 } else {
279 IoLimit = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));
280 if ((IoLimit & PCI_BRIDGE_32_BIT_IO_SPACE) == 0) {
281 IoLimit = IoLimit >> 4;
282 } else {
283 IoLimit = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimitUpper16)) << 4) | (IoLimit >> 4);
284 }
285
286 IoBase = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));
287 if ((IoBase & PCI_BRIDGE_32_BIT_IO_SPACE) == 0) {
288 IoBase = IoBase >> 4;
289 } else {
290 IoBase = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16)) << 4) | (IoBase >> 4);
291 }
292
293 //
294 // If PCI Bridge I/O window is disabled, then return 0
295 //
296 if (IoLimit < IoBase) {
297 return 0;
298 }
299
300 //
301 // If PCI Bridge I/O window is not in the address range decoded by the parent PCI Bridge, then return 0
302 //
303 if ((IoBase < ParentIoBase) || (IoBase > ParentIoLimit) || (IoLimit > ParentIoLimit)) {
304 return 0;
305 }
306
307 ParentIoBase = IoBase;
308 ParentIoLimit = IoLimit;
309 }
310 }
311
312 //
313 // Compute PCI Lib Address to PCI UART
314 //
315 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);
316
317 //
318 // Find the first IO or MMIO BAR
319 //
320 RegisterBaseMask = 0xFFFFFFF0;
321 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
322 SerialRegisterBase = PciRead32 (PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4);
323 if (PcdGetBool (PcdSerialUseMmio) && ((SerialRegisterBase & BIT0) == 0)) {
324 //
325 // MMIO BAR is found
326 //
327 RegisterBaseMask = 0xFFFFFFF0;
328 break;
329 }
330
331 if ((!PcdGetBool (PcdSerialUseMmio)) && ((SerialRegisterBase & BIT0) != 0)) {
332 //
333 // IO BAR is found
334 //
335 RegisterBaseMask = 0xFFFFFFF8;
336 break;
337 }
338 }
339
340 //
341 // MMIO or IO BAR is not found.
342 //
343 if (BarIndex == PCI_MAX_BAR) {
344 return 0;
345 }
346
347 //
348 // Program UART BAR
349 //
350 SerialRegisterBase = SerialPortLibUpdatePciRegister32 (
351 PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4,
352 (UINT32)PcdGet64 (PcdSerialRegisterBase),
353 RegisterBaseMask
354 );
355
356 //
357 // Verify that the UART BAR is in the address range decoded by the parent PCI Bridge
358 //
359 if (PcdGetBool (PcdSerialUseMmio)) {
360 if ((((SerialRegisterBase >> 16) & 0xfff0) < ParentMemoryBase) || (((SerialRegisterBase >> 16) & 0xfff0) > ParentMemoryLimit)) {
361 return 0;
362 }
363 } else {
364 if (((SerialRegisterBase >> 12) < ParentIoBase) || ((SerialRegisterBase >> 12) > ParentIoLimit)) {
365 return 0;
366 }
367 }
368
369 //
370 // Enable I/O and MMIO in PCI UART Device if they are not already enabled
371 //
372 PciOr16 (
373 PciLibAddress + PCI_COMMAND_OFFSET,
375 );
376
377 //
378 // Force D0 state if a Power Management and Status Register is specified
379 //
380 if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) {
381 if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) {
382 PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16) ~(BIT0 | BIT1));
383 //
384 // If PCI UART was not in D0, then make sure FIFOs are enabled, but do not reset FIFOs
385 //
386 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)));
387 }
388 }
389
390 //
391 // Get PCI Device Info
392 //
393 DeviceInfo = (PCI_UART_DEVICE_INFO *)PcdGetPtr (PcdSerialPciDeviceInfo);
394
395 //
396 // Enable I/O or MMIO in PCI Bridge
397 // Assume Root Bus Numer is Zero.
398 //
399 for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) {
400 //
401 // Compute PCI Lib Address to PCI to PCI Bridge
402 //
403 PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0);
404
405 //
406 // Enable the I/O or MMIO decode windows in the PCI to PCI Bridge
407 //
408 PciOr16 (
409 PciLibAddress + PCI_COMMAND_OFFSET,
411 );
412
413 //
414 // Force D0 state if a Power Management and Status Register is specified
415 //
416 if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) {
417 if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) {
418 PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16) ~(BIT0 | BIT1));
419 }
420 }
421
422 BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
423 }
424
425 return SerialRegisterBase;
426}
427
436BOOLEAN
438 UINTN SerialRegisterBase
439 )
440{
441 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
442 if (PcdGetBool (PcdSerialDetectCable)) {
443 //
444 // Wait for both DSR and CTS to be set
445 // DSR is set if a cable is connected.
446 // CTS is set if it is ok to transmit data
447 //
448 // DSR CTS Description Action
449 // === === ======================================== ========
450 // 0 0 No cable connected. Wait
451 // 0 1 No cable connected. Wait
452 // 1 0 Cable connected, but not clear to send. Wait
453 // 1 1 Cable connected, and clear to send. Transmit
454 //
455 return (BOOLEAN)((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS));
456 } else {
457 //
458 // Wait for both DSR and CTS to be set OR for DSR to be clear.
459 // DSR is set if a cable is connected.
460 // CTS is set if it is ok to transmit data
461 //
462 // DSR CTS Description Action
463 // === === ======================================== ========
464 // 0 0 No cable connected. Transmit
465 // 0 1 No cable connected. Transmit
466 // 1 0 Cable connected, but not clear to send. Wait
467 // 1 1 Cable connected, and clar to send. Transmit
468 //
469 return (BOOLEAN)((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR));
470 }
471 }
472
473 return TRUE;
474}
475
487RETURN_STATUS
488EFIAPI
490 VOID
491 )
492{
493 RETURN_STATUS Status;
494 UINTN SerialRegisterBase;
495 UINT32 Divisor;
496 UINT32 CurrentDivisor;
497 BOOLEAN Initialized;
498
499 //
500 // Perform platform specific initialization required to enable use of the 16550 device
501 // at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase.
502 //
504 if (RETURN_ERROR (Status)) {
505 return Status;
506 }
507
508 //
509 // Calculate divisor for baud generator
510 // Ref_Clk_Rate / Baud_Rate / 16
511 //
512 Divisor = PcdGet32 (PcdSerialClockRate) / (PcdGet32 (PcdSerialBaudRate) * 16);
513 if ((PcdGet32 (PcdSerialClockRate) % (PcdGet32 (PcdSerialBaudRate) * 16)) >= PcdGet32 (PcdSerialBaudRate) * 8) {
514 Divisor++;
515 }
516
517 //
518 // Get the base address of the serial port in either I/O or MMIO space
519 //
520 SerialRegisterBase = GetSerialRegisterBase ();
521 if (SerialRegisterBase == 0) {
522 return RETURN_DEVICE_ERROR;
523 }
524
525 //
526 // See if the serial port is already initialized
527 //
528 Initialized = TRUE;
529 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
530 Initialized = FALSE;
531 }
532
533 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) | B_UART_LCR_DLAB));
534 CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH) << 8;
535 CurrentDivisor |= (UINT32)SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW);
536 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & ~B_UART_LCR_DLAB));
537 if (CurrentDivisor != Divisor) {
538 Initialized = FALSE;
539 }
540
541 if (Initialized) {
542 return RETURN_SUCCESS;
543 }
544
545 //
546 // Wait for the serial port to be ready.
547 // Verify that both the transmit FIFO and the shift register are empty.
548 //
549 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
550 }
551
552 //
553 // Configure baud rate
554 //
555 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);
556 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8));
557 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff));
558
559 //
560 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
561 // Strip reserved bits from PcdSerialLineControl
562 //
563 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F));
564
565 //
566 // Enable and reset FIFOs
567 // Strip reserved bits from PcdSerialFifoControl
568 //
569 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00);
570 SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)));
571
572 //
573 // Set FIFO Polled Mode by clearing IER after setting FCR
574 //
575 SerialPortWriteRegister (SerialRegisterBase, R_UART_IER, 0x00);
576
577 //
578 // Put Modem Control Register(MCR) into its reset state of 0x00.
579 //
580 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, 0x00);
581
582 return RETURN_SUCCESS;
583}
584
604UINTN
605EFIAPI
607 IN UINT8 *Buffer,
608 IN UINTN NumberOfBytes
609 )
610{
611 UINTN SerialRegisterBase;
612 UINTN Result;
613 UINTN Index;
614 UINTN FifoSize;
615
616 if (Buffer == NULL) {
617 return 0;
618 }
619
620 SerialRegisterBase = GetSerialRegisterBase ();
621 if (SerialRegisterBase == 0) {
622 return 0;
623 }
624
625 if (NumberOfBytes == 0) {
626 //
627 // Flush the hardware
628 //
629
630 //
631 // Wait for both the transmit FIFO and shift register empty.
632 //
633 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
634 }
635
636 //
637 // Wait for the hardware flow control signal
638 //
639 while (!SerialPortWritable (SerialRegisterBase)) {
640 }
641
642 return 0;
643 }
644
645 //
646 // Compute the maximum size of the Tx FIFO
647 //
648 FifoSize = 1;
649 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {
650 if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {
651 FifoSize = 16;
652 } else {
653 FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize);
654 }
655 }
656
657 Result = NumberOfBytes;
658 while (NumberOfBytes != 0) {
659 //
660 // Wait for the serial port to be ready, to make sure both the transmit FIFO
661 // and shift register empty.
662 //
663 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
664 }
665
666 //
667 // Fill then entire Tx FIFO
668 //
669 for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {
670 //
671 // Wait for the hardware flow control signal
672 //
673 while (!SerialPortWritable (SerialRegisterBase)) {
674 }
675
676 //
677 // Write byte to the transmit buffer.
678 //
679 SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer);
680 }
681 }
682
683 return Result;
684}
685
697UINTN
698EFIAPI
700 OUT UINT8 *Buffer,
701 IN UINTN NumberOfBytes
702 )
703{
704 UINTN SerialRegisterBase;
705 UINTN Result;
706 UINT8 Mcr;
707
708 if (NULL == Buffer) {
709 return 0;
710 }
711
712 SerialRegisterBase = GetSerialRegisterBase ();
713 if (SerialRegisterBase == 0) {
714 return 0;
715 }
716
717 Mcr = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS);
718
719 for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {
720 //
721 // Wait for the serial port to have some data.
722 //
723 while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) == 0) {
724 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
725 //
726 // Set RTS to let the peer send some data
727 //
728 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS));
729 }
730 }
731
732 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
733 //
734 // Clear RTS to prevent peer from sending data
735 //
736 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);
737 }
738
739 //
740 // Read byte from the receive buffer.
741 //
742 *Buffer = SerialPortReadRegister (SerialRegisterBase, R_UART_RXBUF);
743 }
744
745 return Result;
746}
747
759BOOLEAN
760EFIAPI
762 VOID
763 )
764{
765 UINTN SerialRegisterBase;
766
767 SerialRegisterBase = GetSerialRegisterBase ();
768 if (SerialRegisterBase == 0) {
769 return FALSE;
770 }
771
772 //
773 // Read the serial port status
774 //
775 if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) != 0) {
776 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
777 //
778 // Clear RTS to prevent peer from sending data
779 //
780 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS));
781 }
782
783 return TRUE;
784 }
785
786 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
787 //
788 // Set RTS to let the peer send some data
789 //
790 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) | B_UART_MCR_RTS));
791 }
792
793 return FALSE;
794}
795
806RETURN_STATUS
807EFIAPI
809 IN UINT32 Control
810 )
811{
812 UINTN SerialRegisterBase;
813 UINT8 Mcr;
814
815 //
816 // First determine the parameter is invalid.
817 //
818 if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
819 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0)
820 {
821 return RETURN_UNSUPPORTED;
822 }
823
824 SerialRegisterBase = GetSerialRegisterBase ();
825 if (SerialRegisterBase == 0) {
826 return RETURN_UNSUPPORTED;
827 }
828
829 //
830 // Read the Modem Control Register.
831 //
832 Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
833 Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));
834
835 if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
836 Mcr |= B_UART_MCR_DTRC;
837 }
838
839 if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
840 Mcr |= B_UART_MCR_RTS;
841 }
842
843 //
844 // Write the Modem Control Register.
845 //
846 SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);
847
848 return RETURN_SUCCESS;
849}
850
861RETURN_STATUS
862EFIAPI
864 OUT UINT32 *Control
865 )
866{
867 UINTN SerialRegisterBase;
868 UINT8 Msr;
869 UINT8 Mcr;
870 UINT8 Lsr;
871
872 SerialRegisterBase = GetSerialRegisterBase ();
873 if (SerialRegisterBase == 0) {
874 return RETURN_UNSUPPORTED;
875 }
876
877 *Control = 0;
878
879 //
880 // Read the Modem Status Register.
881 //
882 Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR);
883
884 if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {
885 *Control |= EFI_SERIAL_CLEAR_TO_SEND;
886 }
887
888 if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {
889 *Control |= EFI_SERIAL_DATA_SET_READY;
890 }
891
892 if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {
893 *Control |= EFI_SERIAL_RING_INDICATE;
894 }
895
896 if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {
897 *Control |= EFI_SERIAL_CARRIER_DETECT;
898 }
899
900 //
901 // Read the Modem Control Register.
902 //
903 Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);
904
905 if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {
906 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
907 }
908
909 if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {
910 *Control |= EFI_SERIAL_REQUEST_TO_SEND;
911 }
912
913 if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
914 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
915 }
916
917 //
918 // Read the Line Status Register.
919 //
920 Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR);
921
922 if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {
923 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
924 }
925
926 if ((Lsr & B_UART_LSR_RXRDY) == 0) {
927 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
928 }
929
930 return RETURN_SUCCESS;
931}
932
966RETURN_STATUS
967EFIAPI
969 IN OUT UINT64 *BaudRate,
970 IN OUT UINT32 *ReceiveFifoDepth,
971 IN OUT UINT32 *Timeout,
972 IN OUT EFI_PARITY_TYPE *Parity,
973 IN OUT UINT8 *DataBits,
974 IN OUT EFI_STOP_BITS_TYPE *StopBits
975 )
976{
977 UINTN SerialRegisterBase;
978 UINT32 SerialBaudRate;
979 UINTN Divisor;
980 UINT8 Lcr;
981 UINT8 LcrData;
982 UINT8 LcrParity;
983 UINT8 LcrStop;
984
985 SerialRegisterBase = GetSerialRegisterBase ();
986 if (SerialRegisterBase == 0) {
987 return RETURN_UNSUPPORTED;
988 }
989
990 //
991 // Check for default settings and fill in actual values.
992 //
993 if (*BaudRate == 0) {
994 *BaudRate = PcdGet32 (PcdSerialBaudRate);
995 }
996
997 SerialBaudRate = (UINT32)*BaudRate;
998
999 if (*DataBits == 0) {
1000 LcrData = (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3);
1001 *DataBits = LcrData + 5;
1002 } else {
1003 if ((*DataBits < 5) || (*DataBits > 8)) {
1005 }
1006
1007 //
1008 // Map 5..8 to 0..3
1009 //
1010 LcrData = (UINT8)(*DataBits - (UINT8)5);
1011 }
1012
1013 if (*Parity == DefaultParity) {
1014 LcrParity = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);
1015 switch (LcrParity) {
1016 case 0:
1017 *Parity = NoParity;
1018 break;
1019
1020 case 3:
1021 *Parity = EvenParity;
1022 break;
1023
1024 case 1:
1025 *Parity = OddParity;
1026 break;
1027
1028 case 7:
1029 *Parity = SpaceParity;
1030 break;
1031
1032 case 5:
1033 *Parity = MarkParity;
1034 break;
1035
1036 default:
1037 break;
1038 }
1039 } else {
1040 switch (*Parity) {
1041 case NoParity:
1042 LcrParity = 0;
1043 break;
1044
1045 case EvenParity:
1046 LcrParity = 3;
1047 break;
1048
1049 case OddParity:
1050 LcrParity = 1;
1051 break;
1052
1053 case SpaceParity:
1054 LcrParity = 7;
1055 break;
1056
1057 case MarkParity:
1058 LcrParity = 5;
1059 break;
1060
1061 default:
1063 }
1064 }
1065
1066 if (*StopBits == DefaultStopBits) {
1067 LcrStop = (UINT8)((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);
1068 switch (LcrStop) {
1069 case 0:
1070 *StopBits = OneStopBit;
1071 break;
1072
1073 case 1:
1074 if (*DataBits == 5) {
1075 *StopBits = OneFiveStopBits;
1076 } else {
1077 *StopBits = TwoStopBits;
1078 }
1079
1080 break;
1081
1082 default:
1083 break;
1084 }
1085 } else {
1086 switch (*StopBits) {
1087 case OneStopBit:
1088 LcrStop = 0;
1089 break;
1090
1091 case OneFiveStopBits:
1092 case TwoStopBits:
1093 LcrStop = 1;
1094 break;
1095
1096 default:
1098 }
1099 }
1100
1101 //
1102 // Calculate divisor for baud generator
1103 // Ref_Clk_Rate / Baud_Rate / 16
1104 //
1105 Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16);
1106 if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) {
1107 Divisor++;
1108 }
1109
1110 //
1111 // Configure baud rate
1112 //
1113 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);
1114 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8));
1115 SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff));
1116
1117 //
1118 // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
1119 // Strip reserved bits from line control value
1120 //
1121 Lcr = (UINT8)((LcrParity << 3) | (LcrStop << 2) | LcrData);
1122 SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(Lcr & 0x3F));
1123
1124 return RETURN_SUCCESS;
1125}
1126
1132EFIAPI
1134 VOID
1135 )
1136{
1137 // Nothing to do here. This constructor is added to
1138 // enable the chain of constructor invocation for
1139 // dependent libraries.
1140 return RETURN_SUCCESS;
1141}
UINT64 UINTN
RETURN_STATUS EFIAPI PlatformHookSerialPortInitialize(VOID)
UINT32 SerialPortLibUpdatePciRegister32(UINTN PciAddress, UINT32 Value, UINT32 Mask)
BOOLEAN EFIAPI SerialPortPoll(VOID)
RETURN_STATUS EFIAPI SerialPortSetAttributes(IN OUT UINT64 *BaudRate, IN OUT UINT32 *ReceiveFifoDepth, IN OUT UINT32 *Timeout, IN OUT EFI_PARITY_TYPE *Parity, IN OUT UINT8 *DataBits, IN OUT EFI_STOP_BITS_TYPE *StopBits)
UINT8 SerialPortWriteRegister(UINTN Base, UINTN Offset, UINT8 Value)
UINT8 SerialPortReadRegister(UINTN Base, UINTN Offset)
UINTN EFIAPI SerialPortRead(OUT UINT8 *Buffer, IN UINTN NumberOfBytes)
RETURN_STATUS EFIAPI SerialPortInitialize(VOID)
RETURN_STATUS EFIAPI SerialPortSetControl(IN UINT32 Control)
RETURN_STATUS EFIAPI SerialPortGetControl(OUT UINT32 *Control)
UINTN GetSerialRegisterBase(VOID)
UINT16 SerialPortLibUpdatePciRegister16(UINTN PciAddress, UINT16 Value, UINT16 Mask)
EFI_STATUS EFIAPI BaseSerialPortLib16550(VOID)
UINTN EFIAPI SerialPortWrite(IN UINT8 *Buffer, IN UINTN NumberOfBytes)
BOOLEAN SerialPortWritable(UINTN SerialRegisterBase)
UINT8 EFIAPI IoWrite8(IN UINTN Port, IN UINT8 Value)
Definition: IoLibArmVirt.c:200
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
UINT32 EFIAPI MmioRead32(IN UINTN Address)
Definition: IoLib.c:262
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_DEVICE_ERROR
Definition: Base.h:1104
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
UINT32 EFIAPI PciRead32(IN UINTN Address)
Definition: PciLib.c:739
UINT8 EFIAPI PciRead8(IN UINTN Address)
Definition: PciLib.c:62
#define PCI_LIB_ADDRESS(Bus, Device, Function, Register)
Definition: PciLib.h:34
UINT16 EFIAPI PciAnd16(IN UINTN Address, IN UINT16 AndData)
Definition: PciLib.c:484
UINT32 EFIAPI PciWrite32(IN UINTN Address, IN UINT32 Value)
Definition: PciLib.c:765
UINT16 EFIAPI PciOr16(IN UINTN Address, IN UINT16 OrData)
Definition: PciLib.c:453
UINT16 EFIAPI PciWrite16(IN UINTN Address, IN UINT16 Value)
Definition: PciLib.c:422
UINT16 EFIAPI PciRead16(IN UINTN Address)
Definition: PciLib.c:396
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
#define EFI_PCI_COMMAND_MEMORY_SPACE
0x0002
Definition: Pci22.h:592
#define EFI_PCI_COMMAND_IO_SPACE
0x0001
Definition: Pci22.h:591
EFI_STOP_BITS_TYPE
Definition: SerialIo.h:53
EFI_PARITY_TYPE
Definition: SerialIo.h:41
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29