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