+\r
+/**\r
+ Sets the control bits on a serial device.\r
+\r
+ @param Control Sets the bits of Control that are settable.\r
+\r
+ @retval RETURN_SUCCESS The new control bits were set on the serial device.\r
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+SerialPortSetControl (\r
+ IN UINT32 Control\r
+ )\r
+{\r
+ UINTN SerialRegisterBase;\r
+ UINT8 Mcr;\r
+\r
+ //\r
+ // First determine the parameter is invalid.\r
+ //\r
+ if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
+ EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ SerialRegisterBase = GetSerialRegisterBase ();\r
+ if (SerialRegisterBase ==0) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Read the Modem Control Register.\r
+ //\r
+ Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);\r
+ Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS));\r
+\r
+ if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {\r
+ Mcr |= B_UART_MCR_DTRC;\r
+ }\r
+\r
+ if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {\r
+ Mcr |= B_UART_MCR_RTS;\r
+ }\r
+\r
+ //\r
+ // Write the Modem Control Register.\r
+ //\r
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr);\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Retrieve the status of the control bits on a serial device.\r
+\r
+ @param Control A pointer to return the current control signals from the serial device.\r
+\r
+ @retval RETURN_SUCCESS The control bits were read from the serial device.\r
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+SerialPortGetControl (\r
+ OUT UINT32 *Control\r
+ )\r
+{\r
+ UINTN SerialRegisterBase;\r
+ UINT8 Msr;\r
+ UINT8 Mcr;\r
+ UINT8 Lsr;\r
+\r
+ SerialRegisterBase = GetSerialRegisterBase ();\r
+ if (SerialRegisterBase ==0) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ *Control = 0;\r
+\r
+ //\r
+ // Read the Modem Status Register.\r
+ //\r
+ Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR);\r
+\r
+ if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) {\r
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;\r
+ }\r
+\r
+ if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) {\r
+ *Control |= EFI_SERIAL_DATA_SET_READY;\r
+ }\r
+\r
+ if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) {\r
+ *Control |= EFI_SERIAL_RING_INDICATE;\r
+ }\r
+\r
+ if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) {\r
+ *Control |= EFI_SERIAL_CARRIER_DETECT;\r
+ }\r
+\r
+ //\r
+ // Read the Modem Control Register.\r
+ //\r
+ Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR);\r
+\r
+ if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) {\r
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
+ }\r
+\r
+ if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) {\r
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
+ }\r
+\r
+ if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {\r
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+ }\r
+\r
+ //\r
+ // Read the Line Status Register.\r
+ //\r
+ Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR);\r
+\r
+ if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) {\r
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;\r
+ }\r
+\r
+ if ((Lsr & B_UART_LSR_RXRDY) == 0) {\r
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,\r
+ data bits, and stop bits on a serial device.\r
+\r
+ @param BaudRate The requested baud rate. A BaudRate value of 0 will use the\r
+ device's default interface speed.\r
+ On output, the value actually set.\r
+ @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the\r
+ serial interface. A ReceiveFifoDepth value of 0 will use\r
+ the device's default FIFO depth.\r
+ On output, the value actually set.\r
+ @param Timeout The requested time out for a single character in microseconds.\r
+ This timeout applies to both the transmit and receive side of the\r
+ interface. A Timeout value of 0 will use the device's default time\r
+ out value.\r
+ On output, the value actually set.\r
+ @param Parity The type of parity to use on this serial device. A Parity value of\r
+ DefaultParity will use the device's default parity value.\r
+ On output, the value actually set.\r
+ @param DataBits The number of data bits to use on the serial device. A DataBits\r
+ vaule of 0 will use the device's default data bit setting.\r
+ On output, the value actually set.\r
+ @param StopBits The number of stop bits to use on this serial device. A StopBits\r
+ value of DefaultStopBits will use the device's default number of\r
+ stop bits.\r
+ On output, the value actually set.\r
+\r
+ @retval RETURN_SUCCESS The new attributes were set on the serial device.\r
+ @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
+ @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.\r
+ @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+SerialPortSetAttributes (\r
+ IN OUT UINT64 *BaudRate,\r
+ IN OUT UINT32 *ReceiveFifoDepth,\r
+ IN OUT UINT32 *Timeout,\r
+ IN OUT EFI_PARITY_TYPE *Parity,\r
+ IN OUT UINT8 *DataBits,\r
+ IN OUT EFI_STOP_BITS_TYPE *StopBits\r
+ )\r
+{\r
+ UINTN SerialRegisterBase;\r
+ UINT32 SerialBaudRate;\r
+ UINTN Divisor;\r
+ UINT8 Lcr;\r
+ UINT8 LcrData;\r
+ UINT8 LcrParity;\r
+ UINT8 LcrStop;\r
+\r
+ SerialRegisterBase = GetSerialRegisterBase ();\r
+ if (SerialRegisterBase ==0) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check for default settings and fill in actual values.\r
+ //\r
+ if (*BaudRate == 0) {\r
+ *BaudRate = PcdGet32 (PcdSerialBaudRate);\r
+ }\r
+ SerialBaudRate = (UINT32) *BaudRate;\r
+\r
+ if (*DataBits == 0) {\r
+ LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3);\r
+ *DataBits = LcrData + 5;\r
+ } else {\r
+ if ((*DataBits < 5) || (*DataBits > 8)) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Map 5..8 to 0..3\r
+ //\r
+ LcrData = (UINT8) (*DataBits - (UINT8) 5);\r
+ }\r
+\r
+ if (*Parity == DefaultParity) {\r
+ LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7);\r
+ switch (LcrParity) {\r
+ case 0:\r
+ *Parity = NoParity;\r
+ break;\r
+\r
+ case 3:\r
+ *Parity = EvenParity;\r
+ break;\r
+\r
+ case 1:\r
+ *Parity = OddParity;\r
+ break;\r
+\r
+ case 7:\r
+ *Parity = SpaceParity;\r
+ break;\r
+\r
+ case 5:\r
+ *Parity = MarkParity;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ switch (*Parity) {\r
+ case NoParity:\r
+ LcrParity = 0;\r
+ break;\r
+\r
+ case EvenParity:\r
+ LcrParity = 3;\r
+ break;\r
+\r
+ case OddParity:\r
+ LcrParity = 1;\r
+ break;\r
+\r
+ case SpaceParity:\r
+ LcrParity = 7;\r
+ break;\r
+\r
+ case MarkParity:\r
+ LcrParity = 5;\r
+ break;\r
+\r
+ default:\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (*StopBits == DefaultStopBits) {\r
+ LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1);\r
+ switch (LcrStop) {\r
+ case 0:\r
+ *StopBits = OneStopBit;\r
+ break;\r
+\r
+ case 1:\r
+ if (*DataBits == 5) {\r
+ *StopBits = OneFiveStopBits;\r
+ } else {\r
+ *StopBits = TwoStopBits;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ switch (*StopBits) {\r
+ case OneStopBit:\r
+ LcrStop = 0;\r
+ break;\r
+\r
+ case OneFiveStopBits:\r
+ case TwoStopBits:\r
+ LcrStop = 1;\r
+ break;\r
+\r
+ default:\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Calculate divisor for baud generator\r
+ // Ref_Clk_Rate / Baud_Rate / 16\r
+ //\r
+ Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16);\r
+ if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) {\r
+ Divisor++;\r
+ }\r
+\r
+ //\r
+ // Configure baud rate\r
+ //\r
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB);\r
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8));\r
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff));\r
+\r
+ //\r
+ // Clear DLAB and configure Data Bits, Parity, and Stop Bits.\r
+ // Strip reserved bits from line control value\r
+ //\r
+ Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData);\r
+ SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F));\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r