sync trunk HEAD (r50626)
[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 #ifndef _M_ARM
23
24 #include <freeldr.h>
25
26 /* MACROS *******************************************************************/
27
28 #if DBG
29
30 #define DEFAULT_BAUD_RATE 19200
31
32 #define SER_RBR(x) ((x)+0)
33 #define SER_THR(x) ((x)+0)
34 #define SER_DLL(x) ((x)+0)
35 #define SER_IER(x) ((x)+1)
36 #define SER_DLM(x) ((x)+1)
37 #define SER_IIR(x) ((x)+2)
38 #define SER_LCR(x) ((x)+3)
39 #define SR_LCR_CS5 0x00
40 #define SR_LCR_CS6 0x01
41 #define SR_LCR_CS7 0x02
42 #define SR_LCR_CS8 0x03
43 #define SR_LCR_ST1 0x00
44 #define SR_LCR_ST2 0x04
45 #define SR_LCR_PNO 0x00
46 #define SR_LCR_POD 0x08
47 #define SR_LCR_PEV 0x18
48 #define SR_LCR_PMK 0x28
49 #define SR_LCR_PSP 0x38
50 #define SR_LCR_BRK 0x40
51 #define SR_LCR_DLAB 0x80
52 #define SER_MCR(x) ((x)+4)
53 #define SR_MCR_DTR 0x01
54 #define SR_MCR_RTS 0x02
55 #define SER_LSR(x) ((x)+5)
56 #define SR_LSR_DR 0x01
57 #define SR_LSR_TBE 0x20
58 #define SER_MSR(x) ((x)+6)
59 #define SR_MSR_CTS 0x10
60 #define SR_MSR_DSR 0x20
61 #define SER_SCR(x) ((x)+7)
62
63 /* STATIC VARIABLES *********************************************************/
64
65 static ULONG Rs232ComPort = 0;
66 static ULONG Rs232BaudRate = 0;
67 static PUCHAR Rs232PortBase = (PUCHAR)0;
68
69 /* The com port must only be initialized once! */
70 static BOOLEAN PortInitialized = FALSE;
71
72 /* STATIC FUNCTIONS *********************************************************/
73
74 static BOOLEAN Rs232DoesComPortExist(PUCHAR BaseAddress)
75 {
76 BOOLEAN found;
77 UCHAR mcr;
78 UCHAR msr;
79
80 found = FALSE;
81
82 /* save Modem Control Register (MCR) */
83 mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress));
84
85 /* enable loop mode (set Bit 4 of the MCR) */
86 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
87
88 /* clear all modem output bits */
89 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
90
91 /* read the Modem Status Register */
92 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
93
94 /*
95 * the upper nibble of the MSR (modem output bits) must be
96 * equal to the lower nibble of the MCR (modem input bits)
97 */
98 if ((msr & 0xF0) == 0x00)
99 {
100 /* set all modem output bits */
101 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F);
102
103 /* read the Modem Status Register */
104 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
105
106 /*
107 * the upper nibble of the MSR (modem output bits) must be
108 * equal to the lower nibble of the MCR (modem input bits)
109 */
110 if ((msr & 0xF0) == 0xF0)
111 found = TRUE;
112 }
113
114 /* restore MCR */
115 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr);
116
117 return (found);
118 }
119
120 /* FUNCTIONS *********************************************************/
121
122 BOOLEAN Rs232PortInitialize(ULONG ComPort, ULONG BaudRate)
123 {
124 ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
125 //char buffer[80];
126 ULONG divisor;
127 UCHAR lcr;
128
129 if (PortInitialized == FALSE)
130 {
131 if (BaudRate != 0)
132 {
133 Rs232BaudRate = BaudRate;
134 }
135 else
136 {
137 Rs232BaudRate = DEFAULT_BAUD_RATE;
138 }
139
140 if (ComPort == 0)
141 {
142 if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[2]))
143 {
144 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[2];
145 Rs232ComPort = 2;
146 /*#ifndef NDEBUG
147 sprintf (buffer,
148 "\nSerial port COM%ld found at 0x%lx\n",
149 ComPort,
150 (ULONG)PortBase);
151 HalDisplayString (buffer);
152 #endif*/ /* NDEBUG */
153 }
154 else if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[1]))
155 {
156 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[1];
157 Rs232ComPort = 1;
158 /*#ifndef NDEBUG
159 sprintf (buffer,
160 "\nSerial port COM%ld found at 0x%lx\n",
161 ComPort,
162 (ULONG)PortBase);
163 HalDisplayString (buffer);
164 #endif*/ /* NDEBUG */
165 }
166 else
167 {
168 /*sprintf (buffer,
169 "\nKernel Debugger: No COM port found!!!\n\n");
170 HalDisplayString (buffer);*/
171 return FALSE;
172 }
173 }
174 else
175 {
176 if (Rs232DoesComPortExist ((PUCHAR)(ULONG_PTR)BaseArray[ComPort]))
177 {
178 Rs232PortBase = (PUCHAR)(ULONG_PTR)BaseArray[ComPort];
179 Rs232ComPort = ComPort;
180 /*#ifndef NDEBUG
181 sprintf (buffer,
182 "\nSerial port COM%ld found at 0x%lx\n",
183 ComPort,
184 (ULONG)PortBase);
185 HalDisplayString (buffer);
186 #endif*/ /* NDEBUG */
187 }
188 else
189 {
190 /*sprintf (buffer,
191 "\nKernel Debugger: No serial port found!!!\n\n");
192 HalDisplayString (buffer);*/
193 return FALSE;
194 }
195 }
196
197 PortInitialized = TRUE;
198 }
199
200 /*
201 * set baud rate and data format (8N1)
202 */
203
204 /* turn on DTR and RTS */
205 WRITE_PORT_UCHAR (SER_MCR(Rs232PortBase), SR_MCR_DTR | SR_MCR_RTS);
206
207 /* set DLAB */
208 lcr = READ_PORT_UCHAR (SER_LCR(Rs232PortBase)) | SR_LCR_DLAB;
209 WRITE_PORT_UCHAR (SER_LCR(Rs232PortBase), lcr);
210
211 /* set baud rate */
212 divisor = 115200 / BaudRate;
213 WRITE_PORT_UCHAR (SER_DLL(Rs232PortBase), divisor & 0xff);
214 WRITE_PORT_UCHAR (SER_DLM(Rs232PortBase), (divisor >> 8) & 0xff);
215
216 /* reset DLAB and set 8N1 format */
217 WRITE_PORT_UCHAR (SER_LCR(Rs232PortBase),
218 SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
219
220 /* read junk out of the RBR */
221 lcr = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
222
223 /*
224 * set global info
225 */
226 //KdComPortInUse = (ULONG)PortBase;
227
228 /*
229 * print message to blue screen
230 */
231 /*sprintf (buffer,
232 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
233 ComPort,
234 (ULONG)PortBase,
235 BaudRate);
236
237 HalDisplayString (buffer);*/
238
239 return TRUE;
240 }
241
242 BOOLEAN Rs232PortGetByte(PUCHAR ByteRecieved)
243 {
244 if (PortInitialized == FALSE)
245 return FALSE;
246
247 if ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_DR))
248 {
249 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
250 return TRUE;
251 }
252
253 return FALSE;
254 }
255
256 BOOLEAN Rs232PortPollByte(PUCHAR ByteRecieved)
257 {
258 if (PortInitialized == FALSE)
259 return FALSE;
260
261 while ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_DR) == 0)
262 ;
263
264 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(Rs232PortBase));
265
266 return TRUE;
267 }
268
269 VOID Rs232PortPutByte(UCHAR ByteToSend)
270 {
271 if (PortInitialized == FALSE)
272 return;
273
274 while ((READ_PORT_UCHAR (SER_LSR(Rs232PortBase)) & SR_LSR_TBE) == 0)
275 ;
276
277 WRITE_PORT_UCHAR (SER_THR(Rs232PortBase), ByteToSend);
278 }
279
280 #endif /* DBG */
281
282 BOOLEAN Rs232PortInUse(ULONG Base)
283 {
284 #if DBG
285 return PortInitialized && Rs232PortBase == (PUCHAR)(ULONG_PTR)Base ? TRUE : FALSE;
286 #else
287 return FALSE;
288 #endif
289 }
290
291 #endif /* not _M_ARM */