mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 21:44:31 +00:00
76 lines
2.2 KiB
C
76 lines
2.2 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: Serial port driver
|
|
* FILE: drivers/bus/serial/legacy.c
|
|
* PURPOSE: Legacy serial port enumeration
|
|
*
|
|
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
|
* Mark Junker (mjscod@gmx.de)
|
|
*/
|
|
|
|
#include "serial.h"
|
|
|
|
#include <debug.h>
|
|
|
|
UART_TYPE
|
|
SerialDetectUartType(
|
|
IN PUCHAR BaseAddress)
|
|
{
|
|
UCHAR Lcr, TestLcr;
|
|
UCHAR OldScr, Scr5A, ScrA5;
|
|
BOOLEAN FifoEnabled;
|
|
UCHAR NewFifoStatus;
|
|
|
|
Lcr = READ_PORT_UCHAR(SER_LCR(BaseAddress));
|
|
WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr ^ 0xFF);
|
|
TestLcr = READ_PORT_UCHAR(SER_LCR(BaseAddress)) ^ 0xFF;
|
|
WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr);
|
|
|
|
/* Accessing the LCR must work for a usable serial port */
|
|
if (TestLcr != Lcr)
|
|
return UartUnknown;
|
|
|
|
/* Ensure that all following accesses are done as required */
|
|
READ_PORT_UCHAR(SER_RBR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_IER(BaseAddress));
|
|
READ_PORT_UCHAR(SER_IIR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_LCR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_MCR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_LSR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_MSR(BaseAddress));
|
|
READ_PORT_UCHAR(SER_SCR(BaseAddress));
|
|
|
|
/* Test scratch pad */
|
|
OldScr = READ_PORT_UCHAR(SER_SCR(BaseAddress));
|
|
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0x5A);
|
|
Scr5A = READ_PORT_UCHAR(SER_SCR(BaseAddress));
|
|
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0xA5);
|
|
ScrA5 = READ_PORT_UCHAR(SER_SCR(BaseAddress));
|
|
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), OldScr);
|
|
|
|
/* When non-functional, we have a 8250 */
|
|
if (Scr5A != 0x5A || ScrA5 != 0xA5)
|
|
return Uart8250;
|
|
|
|
/* Test FIFO type */
|
|
FifoEnabled = (READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0x80) != 0;
|
|
WRITE_PORT_UCHAR(SER_FCR(BaseAddress), SR_FCR_ENABLE_FIFO);
|
|
NewFifoStatus = READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0xC0;
|
|
if (!FifoEnabled)
|
|
WRITE_PORT_UCHAR(SER_FCR(BaseAddress), 0);
|
|
switch (NewFifoStatus)
|
|
{
|
|
case 0x00:
|
|
return Uart16450;
|
|
case 0x40:
|
|
case 0x80:
|
|
/* Not sure about this but the documentation says that 0x40
|
|
* indicates an unusable FIFO but my tests only worked
|
|
* with 0x80 */
|
|
return Uart16550;
|
|
}
|
|
|
|
/* FIFO is only functional for 16550A+ */
|
|
return Uart16550A;
|
|
}
|