- Update to r53061
[reactos.git] / drivers / serial / serial / legacy.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Serial port driver
4 * FILE: drivers/bus/serial/legacy.c
5 * PURPOSE: Legacy serial port enumeration
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 * Mark Junker (mjscod@gmx.de)
9 */
10
11 #include "serial.h"
12
13 UART_TYPE
14 SerialDetectUartType(
15 IN PUCHAR BaseAddress)
16 {
17 UCHAR Lcr, TestLcr;
18 UCHAR OldScr, Scr5A, ScrA5;
19 BOOLEAN FifoEnabled;
20 UCHAR NewFifoStatus;
21
22 Lcr = READ_PORT_UCHAR(SER_LCR(BaseAddress));
23 WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr ^ 0xFF);
24 TestLcr = READ_PORT_UCHAR(SER_LCR(BaseAddress)) ^ 0xFF;
25 WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr);
26
27 /* Accessing the LCR must work for a usable serial port */
28 if (TestLcr != Lcr)
29 return UartUnknown;
30
31 /* Ensure that all following accesses are done as required */
32 READ_PORT_UCHAR(SER_RBR(BaseAddress));
33 READ_PORT_UCHAR(SER_IER(BaseAddress));
34 READ_PORT_UCHAR(SER_IIR(BaseAddress));
35 READ_PORT_UCHAR(SER_LCR(BaseAddress));
36 READ_PORT_UCHAR(SER_MCR(BaseAddress));
37 READ_PORT_UCHAR(SER_LSR(BaseAddress));
38 READ_PORT_UCHAR(SER_MSR(BaseAddress));
39 READ_PORT_UCHAR(SER_SCR(BaseAddress));
40
41 /* Test scratch pad */
42 OldScr = READ_PORT_UCHAR(SER_SCR(BaseAddress));
43 WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0x5A);
44 Scr5A = READ_PORT_UCHAR(SER_SCR(BaseAddress));
45 WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0xA5);
46 ScrA5 = READ_PORT_UCHAR(SER_SCR(BaseAddress));
47 WRITE_PORT_UCHAR(SER_SCR(BaseAddress), OldScr);
48
49 /* When non-functional, we have a 8250 */
50 if (Scr5A != 0x5A || ScrA5 != 0xA5)
51 return Uart8250;
52
53 /* Test FIFO type */
54 FifoEnabled = (READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0x80) != 0;
55 WRITE_PORT_UCHAR(SER_FCR(BaseAddress), SR_FCR_ENABLE_FIFO);
56 NewFifoStatus = READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0xC0;
57 if (!FifoEnabled)
58 WRITE_PORT_UCHAR(SER_FCR(BaseAddress), 0);
59 switch (NewFifoStatus)
60 {
61 case 0x00:
62 return Uart16450;
63 case 0x40:
64 case 0x80:
65 /* Not sure about this but the documentation says that 0x40
66 * indicates an unusable FIFO but my tests only worked
67 * with 0x80 */
68 return Uart16550;
69 }
70
71 /* FIFO is only functional for 16550A+ */
72 return Uart16550A;
73 }