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