- Create another branch for networking fixes
[reactos.git] / boot / freeldr / freeldr / comm / rs232.c
1 /*
2 * FreeLoader
3 * Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2001 Eric Kohl
5 * Copyright (C) 2001 Emanuele Aliberti
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <freeldr.h>
23
24 /* MACROS *******************************************************************/
25
26 #if DBG
27
28 #define DEFAULT_BAUD_RATE 19200
29
30 #define SER_RBR(x) ((x)+0)
31 #define SER_THR(x) ((x)+0)
32 #define SER_DLL(x) ((x)+0)
33 #define SER_IER(x) ((x)+1)
34 #define SER_DLM(x) ((x)+1)
35 #define SER_IIR(x) ((x)+2)
36 #define SER_LCR(x) ((x)+3)
37 #define SR_LCR_CS5 0x00
38 #define SR_LCR_CS6 0x01
39 #define SR_LCR_CS7 0x02
40 #define SR_LCR_CS8 0x03
41 #define SR_LCR_ST1 0x00
42 #define SR_LCR_ST2 0x04
43 #define SR_LCR_PNO 0x00
44 #define SR_LCR_POD 0x08
45 #define SR_LCR_PEV 0x18
46 #define SR_LCR_PMK 0x28
47 #define SR_LCR_PSP 0x38
48 #define SR_LCR_BRK 0x40
49 #define SR_LCR_DLAB 0x80
50 #define SER_MCR(x) ((x)+4)
51 #define SR_MCR_DTR 0x01
52 #define SR_MCR_RTS 0x02
53 #define SER_LSR(x) ((x)+5)
54 #define SR_LSR_DR 0x01
55 #define SR_LSR_TBE 0x20
56 #define SER_MSR(x) ((x)+6)
57 #define SR_MSR_CTS 0x10
58 #define SR_MSR_DSR 0x20
59 #define SER_SCR(x) ((x)+7)
60
61 /* STATIC VARIABLES *********************************************************/
62
63 static ULONG Rs232ComPort = 0;
64 static ULONG Rs232BaudRate = 0;
65 static PUCHAR Rs232PortBase = (PUCHAR)0;
66
67 /* The com port must only be initialized once! */
68 static BOOLEAN PortInitialized = FALSE;
69
70 /* STATIC FUNCTIONS *********************************************************/
71
72 static BOOLEAN Rs232DoesComPortExist(PUCHAR BaseAddress)
73 {
74 BOOLEAN found;
75 UCHAR mcr;
76 UCHAR msr;
77
78 found = FALSE;
79
80 /* save Modem Control Register (MCR) */
81 mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress));
82
83 /* enable loop mode (set Bit 4 of the MCR) */
84 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
85
86 /* clear all modem output bits */
87 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
88
89 /* read the Modem Status Register */
90 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
91
92 /*
93 * the upper nibble of the MSR (modem output bits) must be
94 * equal to the lower nibble of the MCR (modem input bits)
95 */
96 if ((msr & 0xF0) == 0x00)
97 {
98 /* set all modem output bits */
99 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F);
100
101 /* read the Modem Status Register */
102 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
103
104 /*
105 * the upper nibble of the MSR (modem output bits) must be
106 * equal to the lower nibble of the MCR (modem input bits)
107 */
108 if ((msr & 0xF0) == 0xF0)
109 found = TRUE;
110 }
111
112 /* restore MCR */
113 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr);
114
115 return (found);
116 }
117
118 /* FUNCTIONS *********************************************************/
119
120 BOOLEAN Rs232PortInitialize(ULONG ComPort, ULONG BaudRate)
121 {
122 ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
123 //char buffer[80];
124 ULONG divisor;
125 UCHAR lcr;
126
127 if (PortInitialized == FALSE)
128 {
129 if (BaudRate != 0)
130 {
131 Rs232BaudRate = BaudRate;
132 }
133 else
134 {
135 Rs232BaudRate = DEFAULT_BAUD_RATE;
136 }
137
138 if (ComPort == 0)
139 {
140 if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[2]))
141 {
142 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[2];
143 Rs232ComPort = 2;
144 /*#ifndef NDEBUG
145 sprintf (buffer,
146 "\nSerial port COM%ld found at 0x%lx\n",
147 ComPort,
148 (ULONG)PortBase);
149 HalDisplayString (buffer);
150 #endif*/ /* NDEBUG */
151 }
152 else if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[1]))
153 {
154 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[1];
155 Rs232ComPort = 1;
156 /*#ifndef NDEBUG
157 sprintf (buffer,
158 "\nSerial port COM%ld found at 0x%lx\n",
159 ComPort,
160 (ULONG)PortBase);
161 HalDisplayString (buffer);
162 #endif*/ /* NDEBUG */
163 }
164 else
165 {
166 /*sprintf (buffer,
167 "\nKernel Debugger: No COM port found!!!\n\n");
168 HalDisplayString (buffer);*/
169 return FALSE;
170 }
171 }
172 else
173 {
174 if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[ComPort]))
175 {
176 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[ComPort];
177 Rs232ComPort = ComPort;
178 /*#ifndef NDEBUG
179 sprintf (buffer,
180 "\nSerial port COM%ld found at 0x%lx\n",
181 ComPort,
182 (ULONG)PortBase);
183 HalDisplayString (buffer);
184 #endif*/ /* NDEBUG */
185 }
186 else
187 {
188 /*sprintf (buffer,
189 "\nKernel Debugger: No serial port found!!!\n\n");
190 HalDisplayString (buffer);*/
191 return FALSE;
192 }
193 }
194
195 PortInitialized = TRUE;
196 }
197
198 /*
199 * set baud rate and data format (8N1)
200 */
201
202 /* turn on DTR and RTS */
203 WRITE_PORT_UCHAR (SER_MCR(Rs232PortBase), SR_MCR_DTR | SR_MCR_RTS);
204
205 /* set DLAB */
206 lcr = READ_PORT_UCHAR (SER_LCR(Rs232PortBase)) | SR_LCR_DLAB;
207 WRITE_PORT_UCHAR (SER_LCR(Rs232PortBase), lcr);
208
209 /* set baud rate */
210 divisor = 115200 / BaudRate;
211 WRITE_PORT_UCHAR (SER_DLL(Rs232PortBase), divisor & 0xff);
212 WRITE_PORT_UCHAR (SER_DLM(Rs232PortBase), (divisor >> 8) & 0xff);
213
214 /* reset DLAB and set 8N1 format */
215 WRITE_PORT_UCHAR (SER_LCR(Rs232PortBase),
216 SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
217
218 /* read junk out of the RBR */
219 lcr = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
220
221 /*
222 * set global info
223 */
224 //KdComPortInUse = (ULONG)PortBase;
225
226 /*
227 * print message to blue screen
228 */
229 /*sprintf (buffer,
230 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
231 ComPort,
232 (ULONG)PortBase,
233 BaudRate);
234
235 HalDisplayString (buffer);*/
236
237 return TRUE;
238 }
239
240 BOOLEAN Rs232PortGetByte(PUCHAR ByteRecieved)
241 {
242 if (PortInitialized == FALSE)
243 return FALSE;
244
245 if ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_DR))
246 {
247 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
248 return TRUE;
249 }
250
251 return FALSE;
252 }
253
254 BOOLEAN Rs232PortPollByte(PUCHAR ByteRecieved)
255 {
256 if (PortInitialized == FALSE)
257 return FALSE;
258
259 while ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_DR) == 0)
260 ;
261
262 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
263
264 return TRUE;
265 }
266
267 VOID Rs232PortPutByte(UCHAR ByteToSend)
268 {
269 if (PortInitialized == FALSE)
270 return;
271
272 while ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_TBE) == 0)
273 ;
274
275 WRITE_PORT_UCHAR (SER_THR(Rs232PortBase), ByteToSend);
276 }
277
278 #endif /* DBG */
279
280 BOOLEAN Rs232PortInUse(ULONG Base)
281 {
282 #if DBG
283 return PortInitialized && Rs232PortBase == (PUCHAR)(ULONG_PTR)Base ? TRUE : FALSE;
284 #else
285 return FALSE;
286 #endif
287 }