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