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
36 if ((inb_p(base
+6) & 0xf0)) return 0;
40 int irq_setup(unsigned base
)
42 // Returns -1 if not found -- otherwise returns interrupt level
44 char ier
, mcr
, imrm
, imrs
, maskm
, masks
, irqm
, irqs
;
46 __asm("cli"); // disable all CPU interrupts
47 ier
= inb_p(base
+1); // read IER
48 outb_p(base
+1,0); // disable all UART ints
49 while (!(inb_p(base
+5)&0x20)); // wait for the THR to be empty
50 mcr
= inb_p(base
+4); // read MCR
51 outb_p(base
+4,0x0F); // connect UART to irq line
52 imrm
= inb_p(0x21); // read contents of master ICU mask register
53 imrs
= inb_p(0xA1); // read contents of slave ICU mask register
54 outb_p(0xA0,0x0A); // next read access to 0xA0 reads out IRR
55 outb_p(0x20,0x0A); // next read access to 0x20 reads out IRR
56 outb_p(base
+1,2); // let's generate interrupts...
57 maskm
= inb_p(0x20); // this clears all bits except for the one
58 masks
= inb_p(0xA0); // that corresponds to the int
59 outb_p(base
+1,0); // drop the int line
60 maskm
&= ~inb_p(0x20); // this clears all bits except for the one
61 masks
&= ~inb_p(0xA0); // that corresponds to the int
62 outb_p(base
+1,2); // and raise it again just to be sure...
63 maskm
&= inb_p(0x20); // this clears all bits except for the one
64 masks
&= inb_p(0xA0); // that corresponds to the int
65 outb_p(0xA1,~masks
); // now let us unmask this interrupt only
67 outb_p(0xA0,0x0C); // enter polled mode
68 outb_p(0x20,0x0C); // that order is important with Pentium/PCI systems
69 irqs
= inb_p(0xA0); // and accept the interrupt
71 inb_p(base
+2); // reset transmitter interrupt in UART
72 outb_p(base
+4,mcr
); // restore old value of MCR
73 outb_p(base
+1,ier
); // restore old value of IER
74 if (masks
) outb_p(0xA0,0x20); // send an EOI to slave
75 if (maskm
) outb_p(0x20,0x20); // send an EOI to master
76 outb_p(0x21,imrm
); // restore old mask register contents
79 if (irqs
&0x80) // slave interrupt occured
81 if (irqm
&0x80) // master interrupt occured
86 void uart_init(unsigned uart_base
)
88 // Initialize the UART
89 outb_p(uart_base
+3, 0x80);
90 outw_p(uart_base
, UART_BAUDRATE
);
91 outb_p(uart_base
+3, UART_LCRVAL
);
92 outb_p(uart_base
+4, 0);
95 unsigned uart_getchar(unsigned uart_base
)
99 x
=(inb_p(uart_base
+5) & 0x9f) << 8;
100 if(x
& 0x100) x
|=((unsigned)inb_p(uart_base
)) & 0xff;
104 void InitializeSerial(void)
106 unsigned comports
[4] = { COM1
, COM2
, COM3
, COM4
};
107 char *comname
[4] = { "COM1", "COM2", "COM3", "COM4" };
112 if(uart_detect(comports
[i
])==0)
114 DbgPrint("%s not detected\n", comname
[i
]);
116 uart_init(comports
[i
]);
117 irq_level
=irq_setup(comports
[i
]);
120 DbgPrint("Warning: IRQ not detected!\n");
122 DbgPrint("%s hooked to interrupt level %d\n", comname
[i
], irq_level
);
128 // For testing purposes
129 void testserial(void)
139 DbgPrint("Testing serial input...\n");
142 x
.val
=uart_getchar(COM1
);
143 // if(!x.val) continue;
148 // DbgPrint("(%x-%c) %c\n", x.val, x.character, testc);
153 DriverEntry(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
155 DbgPrint("Serial Driver 0.0.2\n");
156 // InitializeSerial();
158 return(STATUS_SUCCESS
);