1 /* $Id: serial.c,v 1.10 2002/10/06 13:16:26 robd Exp $
4 * Written by Jason Filby (jasonfilby@yahoo.com)
5 * For ReactOS (www.reactos.com)
10 //#include <internal/mmhal.h>
11 //#include "../../../ntoskrnl/include/internal/i386/io.h"
12 //#include "../../../ntoskrnl/include/internal/io.h"
14 #define outb_p(a,p) WRITE_PORT_UCHAR((PUCHAR)a,p)
15 #define outw_p(a,p) WRITE_PORT_USHORT((PUSHORT)a,p)
16 #define inb_p(p) READ_PORT_UCHAR((PUCHAR)p)
27 #define UART_BAUDRATE 96 // 1200 BPS
28 #define UART_LCRVAL 0x1b // 0x1b for 8e1
29 #define UARY_FCRVAL 0x7
31 int uart_detect(unsigned base
)
33 // Returns 0 if no UART detected
35 int olddata
=inb_p(base
+4);
37 if ((inb_p(base
+6) & 0xf0)) return 0;
41 int irq_setup(unsigned base
)
43 // Returns -1 if not found -- otherwise returns interrupt level
45 char ier
, mcr
, imrm
, imrs
, maskm
, masks
, irqm
, irqs
;
47 __asm("cli"); // disable all CPU interrupts
48 ier
= inb_p(base
+1); // read IER
49 outb_p(base
+1,0); // disable all UART ints
50 while (!(inb_p(base
+5)&0x20)); // wait for the THR to be empty
51 mcr
= inb_p(base
+4); // read MCR
52 outb_p(base
+4,0x0F); // connect UART to irq line
53 imrm
= inb_p(0x21); // read contents of master ICU mask register
54 imrs
= inb_p(0xA1); // read contents of slave ICU mask register
55 outb_p(0xA0,0x0A); // next read access to 0xA0 reads out IRR
56 outb_p(0x20,0x0A); // next read access to 0x20 reads out IRR
57 outb_p(base
+1,2); // let's generate interrupts...
58 maskm
= inb_p(0x20); // this clears all bits except for the one
59 masks
= inb_p(0xA0); // that corresponds to the int
60 outb_p(base
+1,0); // drop the int line
61 maskm
&= ~inb_p(0x20); // this clears all bits except for the one
62 masks
&= ~inb_p(0xA0); // that corresponds to the int
63 outb_p(base
+1,2); // and raise it again just to be sure...
64 maskm
&= inb_p(0x20); // this clears all bits except for the one
65 masks
&= inb_p(0xA0); // that corresponds to the int
66 outb_p(0xA1,~masks
); // now let us unmask this interrupt only
68 outb_p(0xA0,0x0C); // enter polled mode
69 outb_p(0x20,0x0C); // that order is important with Pentium/PCI systems
70 irqs
= inb_p(0xA0); // and accept the interrupt
72 inb_p(base
+2); // reset transmitter interrupt in UART
73 outb_p(base
+4,mcr
); // restore old value of MCR
74 outb_p(base
+1,ier
); // restore old value of IER
75 if (masks
) outb_p(0xA0,0x20); // send an EOI to slave
76 if (maskm
) outb_p(0x20,0x20); // send an EOI to master
77 outb_p(0x21,imrm
); // restore old mask register contents
80 if (irqs
&0x80) // slave interrupt occured
82 if (irqm
&0x80) // master interrupt occured
87 void uart_init(unsigned uart_base
)
89 // Initialize the UART
90 outb_p(uart_base
+3, 0x80);
91 outw_p(uart_base
, UART_BAUDRATE
);
92 outb_p(uart_base
+3, UART_LCRVAL
);
93 outb_p(uart_base
+4, 0);
96 unsigned uart_getchar(unsigned uart_base
)
100 x
=(inb_p(uart_base
+5) & 0x9f) << 8;
101 if(x
& 0x100) x
|=((unsigned)inb_p(uart_base
)) & 0xff;
105 void InitializeSerial(void)
107 unsigned comports
[4] = { COM1
, COM2
, COM3
, COM4
};
108 char *comname
[4] = { "COM1", "COM2", "COM3", "COM4" };
113 if(uart_detect(comports
[i
])==0)
115 DbgPrint("%s not detected\n", comname
[i
]);
117 uart_init(comports
[i
]);
118 irq_level
=irq_setup(comports
[i
]);
121 DbgPrint("Warning: IRQ not detected!\n");
123 DbgPrint("%s hooked to interrupt level %d\n", comname
[i
], irq_level
);
129 // For testing purposes
130 void testserial(void)
140 DbgPrint("Testing serial input...\n");
143 x
.val
=uart_getchar(COM1
);
144 // if(!x.val) continue;
149 // DbgPrint("(%x-%c) %c\n", x.val, x.character, testc);
154 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
156 DbgPrint("Serial Driver 0.0.2\n");
157 // InitializeSerial();
159 return(STATUS_SUCCESS
);