Fixed bug
[reactos.git] / reactos / ntoskrnl / hal / x86 / printk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/printk.c
5 * PURPOSE: Writing to the console
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * ??/??/??: Created
9 * 05/06/98: Implemented BSOD
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <internal/ntoskrnl.h>
15 #include <internal/string.h>
16 #include <internal/mmhal.h>
17 #include <internal/halio.h>
18
19 //#define BOCHS_DEBUGGING 1
20 //#define SERIAL_DEBUGGING
21 #define SERIAL_PORT 0x03f8
22 #define SERIAL_BAUD_RATE 19200
23 #define SERIAL_LINE_CONTROL (SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO)
24
25 #define NDEBUG
26 #include <internal/debug.h>
27
28 /* GLOBALS ******************************************************************/
29
30 #ifdef BOCHS_DEBUGGING
31 #define BOCHS_LOGGER_PORT (0x3ed)
32 #endif
33
34 #ifdef SERIAL_DEBUGGING
35 #define SER_RBR SERIAL_PORT + 0
36 #define SER_THR SERIAL_PORT + 0
37 #define SER_DLL SERIAL_PORT + 0
38 #define SER_IER SERIAL_PORT + 1
39 #define SER_DLM SERIAL_PORT + 1
40 #define SER_IIR SERIAL_PORT + 2
41 #define SER_LCR SERIAL_PORT + 3
42 #define SR_LCR_CS5 0x00
43 #define SR_LCR_CS6 0x01
44 #define SR_LCR_CS7 0x02
45 #define SR_LCR_CS8 0x03
46 #define SR_LCR_ST1 0x00
47 #define SR_LCR_ST2 0x04
48 #define SR_LCR_PNO 0x00
49 #define SR_LCR_POD 0x08
50 #define SR_LCR_PEV 0x18
51 #define SR_LCR_PMK 0x28
52 #define SR_LCR_PSP 0x38
53 #define SR_LCR_BRK 0x40
54 #define SR_LCR_DLAB 0x80
55 #define SER_MCR SERIAL_PORT + 4
56 #define SR_MCR_DTR 0x01
57 #define SR_MCR_RTS 0x02
58 #define SER_LSR SERIAL_PORT + 5
59 #define SR_LSR_TBE 0x20
60 #define SER_MSR SERIAL_PORT + 6
61 #endif
62
63 /*
64 * PURPOSE: Current cursor position
65 */
66 static unsigned int cursorx=0, cursory=0;
67 static unsigned int lines_seen = 0;
68 static unsigned char CharAttribute = 0x17;
69
70 //#define NR_ROWS 25
71 #define NR_ROWS 50
72 #define NR_COLUMNS 80
73 #define VIDMEM_BASE 0xb8000
74
75 /*
76 * PURPOSE: Points to the base of text mode video memory
77 */
78 static char* vidmem = (char *)(VIDMEM_BASE + IDMAP_BASE);
79
80 #define CRTC_COMMAND 0x3d4
81 #define CRTC_DATA 0x3d5
82 #define CRTC_CURLO 0x0f
83 #define CRTC_CURHI 0x0e
84
85 /*
86 * PURPOSE: This flag is set to true if the system is in HAL managed
87 * console mode. This is initially true then once the graphics drivers
88 * initialize, it is turned off, HAL console mode is reentered if a fatal
89 * error occurs or on system shutdown
90 */
91 static unsigned int in_hal_console = 1;
92
93 /*
94 * PURPOSE: Defines the hal console video mode
95 */
96 static unsigned char mode03[] = {0x67,0x00,0x03,0x00,0x03,0x00,0x02,
97 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,
98 0x1f,0x00,0x4f,0x0e,0x0f,0x00,0x00,
99 0x00,0x00,0x9c,0x0e,0x8f,0x28,0x01,
100 0x96,0xb9,0xa3,0xff,0x00,0x00,0x00,
101 0x00,0x00,0x10,0x0e,0x00,0xff,0x00,
102 0x00,0x01,0x02,0x03,0x04,0x05,0x06,
103 0x07,0x10,0x11,0x12,0x13,0x14,0x15,
104 0x16,0x17,0x0c,0x00,0x0f,0x08,0x00};
105
106 /* FUNCTIONS ***************************************************************/
107
108
109 void HalSwitchToBlueScreen(void)
110 /*
111 * FUNCTION: Switches the monitor to text mode and writes a blue background
112 * NOTE: This function is entirely self contained and can be used from any
113 * graphics mode.
114 */
115 {
116 /*
117 * Sanity check
118 */
119 if (in_hal_console)
120 {
121 return;
122 }
123
124 /*
125 * Reset the cursor position
126 */
127 cursorx=0;
128 cursory=0;
129
130 /*
131 * This code section is taken from the sample routines by
132 * Jeff Morgan (kinfira@hotmail.com)
133 */
134
135 }
136
137
138 NTSTATUS STDCALL NtDisplayString(IN PUNICODE_STRING DisplayString)
139 {
140 // DbgPrint("DisplayString %x\n",DisplayString);
141 DbgPrint("%s",DisplayString);
142 // DbgPrint("Returning from NtDisplayString()\n");
143 return(STATUS_SUCCESS);
144 }
145
146 void HalDisplayString(char* string)
147 /*
148 * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
149 * already and displays a string
150 * ARGUMENT:
151 * string = ASCII string to display
152 * NOTE: Use with care because there is no support for returning from BSOD
153 * mode
154 */
155 {
156 if (!in_hal_console)
157 {
158 HalSwitchToBlueScreen();
159 }
160 printk("%s",string);
161 }
162
163 static void putchar(char c)
164 /*
165 * FUNCTION: Writes a character to the console and updates the cursor position
166 * ARGUMENTS:
167 * c = the character to write
168 * NOTE: This function handles newlines as well
169 */
170 {
171 char* address;
172 int offset;
173 int i;
174
175 #ifdef BOCHS_DEBUGGING
176 outb_p(BOCHS_LOGGER_PORT,c);
177 #endif
178
179 #ifdef SERIAL_DEBUGGING
180 while ((inb_p(SER_LSR) & SR_LSR_TBE) == 0)
181 ;
182 outb_p(SER_THR, c);
183 #endif
184
185 switch(c)
186 {
187 case '\n':
188 cursory++;
189 cursorx = 0;
190 lines_seen++;
191 break;
192
193 default:
194 vidmem[(cursorx * 2) + (cursory * 80 * 2)] = c;
195 vidmem[(cursorx * 2) + (cursory * 80 * 2) + 1] = CharAttribute;
196 cursorx++;
197 if (cursorx >= NR_COLUMNS)
198 {
199 cursory++;
200 lines_seen++;
201 cursorx = 0;
202 }
203 }
204
205 #if 0
206 if (lines_seen == 24)
207 {
208 char str[] = "--- press escape to continue";
209
210 lines_seen = 0;
211 for (i = 0; str[i] != 0; i++)
212 {
213 vidmem[NR_COLUMNS*(NR_ROWS-1)*2+i*2] = str[i];
214 vidmem[NR_COLUMNS*(NR_ROWS-1)*2+i*2+1] = CharAttribute;
215 }
216
217 while (inb_p(0x60)!=0x81);
218 memset(&vidmem[NR_COLUMNS*(NR_ROWS-1)*2],0,NR_COLUMNS*2);
219 }
220 #endif
221
222 if (cursory >= NR_ROWS)
223 {
224 unsigned short *LinePtr;
225
226 memcpy(vidmem,
227 &vidmem[NR_COLUMNS * 2],
228 NR_COLUMNS * (NR_ROWS - 1) * 2);
229 LinePtr = (unsigned short *) &vidmem[NR_COLUMNS * (NR_ROWS - 1) * 2];
230 for (i = 0; i < NR_COLUMNS; i++)
231 {
232 LinePtr[i] = CharAttribute << 8;
233 }
234 cursory = NR_ROWS - 1;
235 }
236
237 /*
238 * Set the cursor position
239 */
240
241 offset = cursory * NR_COLUMNS;
242 offset = offset + cursorx;
243
244 outb_p(CRTC_COMMAND, CRTC_CURLO);
245 outb_p(CRTC_DATA, offset);
246 outb_p(CRTC_COMMAND, CRTC_CURHI);
247 offset >>= 8;
248 outb_p(CRTC_DATA, offset);
249
250 }
251
252 asmlinkage void printk(const char* fmt, ...)
253 /*
254 * FUNCTION: Print a formatted string to the hal console
255 * ARGUMENTS: As for printf
256 * NOTE: So it can used from irq handlers this function disables interrupts
257 * during its execution, they are restored to the previous state on return
258 */
259 {
260 char buffer[256];
261 char* str=buffer;
262 va_list ap;
263 unsigned int eflags;
264
265 /*
266 * Because this is used by alomost every subsystem including irqs it
267 * must be atomic. The following code sequence disables interrupts after
268 * saving the previous state of the interrupt flag
269 */
270 __asm__("pushf\n\tpop %0\n\tcli\n\t"
271 : "=m" (eflags)
272 : /* */);
273
274 /*
275 * Process the format string into a fixed length buffer using the
276 * standard C RTL function
277 */
278 va_start(ap,fmt);
279 vsprintf(buffer,fmt,ap);
280 va_end(ap);
281
282 while ((*str)!=0)
283 {
284 putchar(*str);
285 str++;
286 }
287
288 /*
289 * Restore the interrupt flag
290 */
291 __asm__("push %0\n\tpopf\n\t"
292 :
293 : "m" (eflags));
294 }
295
296 int bad_user_access_length(void)
297 {
298 printk("Bad user access length\n");
299 }
300
301 ULONG DbgPrint(PCH Format, ...)
302 {
303 char buffer[256];
304 char* str=buffer;
305 va_list ap;
306 unsigned int eflags;
307
308 /*
309 * Because this is used by alomost every subsystem including irqs it
310 * must be atomic. The following code sequence disables interrupts after
311 * saving the previous state of the interrupt flag
312 */
313 __asm__("pushf\n\tpop %0\n\tcli\n\t"
314 : "=m" (eflags)
315 : /* */);
316
317 /*
318 * Process the format string into a fixed length buffer using the
319 * standard C RTL function
320 */
321 va_start(ap,Format);
322 vsprintf(buffer,Format,ap);
323 va_end(ap);
324
325 while ((*str)!=0)
326 {
327 putchar(*str);
328 str++;
329 }
330
331 /*
332 * Restore the interrupt flag
333 */
334 __asm__("push %0\n\tpopf\n\t"
335 :
336 : "m" (eflags));
337 }
338
339 void HalInitConsole(boot_param* bp)
340 /*
341 * FUNCTION: Initalize the console
342 * ARGUMENTS:
343 * bp = Parameters setup by the boot loader
344 */
345 {
346
347 #ifdef SERIAL_DEBUGGING
348 /* turn on DTR and RTS */
349 outb_p(SER_MCR, SR_MCR_DTR | SR_MCR_RTS);
350 /* set baud rate, line control */
351 outb_p(SER_LCR, SERIAL_LINE_CONTROL | SR_LCR_DLAB);
352 outb_p(SER_DLL, (115200 / SERIAL_BAUD_RATE) & 0xff);
353 outb_p(SER_DLM, ((115200 / SERIAL_BAUD_RATE) >> 8) & 0xff);
354 outb_p(SER_LCR, SERIAL_LINE_CONTROL);
355 #endif
356
357 cursorx=bp->cursorx;
358 cursory=bp->cursory;
359 }