b23b4a0f5f63b6ed0b10263d76f9c0509b67ccbc
[reactos.git] / reactos / hal / halx86 / display.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: display.c,v 1.18 2004/10/31 19:45:16 ekohl Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/hal/x86/display.c
24 * PURPOSE: Blue screen display
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
26 * UPDATE HISTORY:
27 * Created 08/10/99
28 */
29
30 /*
31 * Portions of this code are from the XFree86 Project and available from the
32 * following license:
33 *
34 * Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
35 *
36 * Permission is hereby granted, free of charge, to any person obtaining a copy
37 * of this software and associated documentation files (the "Software"), to
38 * deal in the Software without restriction, including without limitation the
39 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
40 * sell copies of the Software, and to permit persons to whom the Software is
41 * furnished to do so, subject to the following conditions:
42 *
43 * The above copyright notice and this permission notice shall be included in
44 * all copies or substantial portions of the Software.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49 * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
50 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
51 * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 *
53 * Except as contained in this notice, the name of the XFree86 Project shall
54 * not be used in advertising or otherwise to promote the sale, use or other
55 * dealings in this Software without prior written authorization from the
56 * XFree86 Project.
57 */
58
59 /* DISPLAY OWNERSHIP
60 *
61 * So, who owns the physical display and is allowed to write to it?
62 *
63 * In MS NT, upon boot HAL owns the display. Somewhere in the boot
64 * sequence (haven't figured out exactly where or by who), some
65 * component calls HalAcquireDisplayOwnership. From that moment on,
66 * the display is owned by that component and is switched to graphics
67 * mode. The display is not supposed to return to text mode, except
68 * in case of a bug check. The bug check will call HalDisplayString
69 * to output a string to the text screen. HAL will notice that it
70 * currently doesn't own the display and will re-take ownership, by
71 * calling the callback function passed to HalAcquireDisplayOwnership.
72 * After the bugcheck, execution is halted. So, under NT, the only
73 * possible sequence of display modes is text mode -> graphics mode ->
74 * text mode (the latter hopefully happening very infrequently).
75 *
76 * Things are a little bit different in the current state of ReactOS.
77 * We want to have a functional interactive text mode. We should be
78 * able to switch from text mode to graphics mode when a GUI app is
79 * started and switch back to text mode when it's finished. Then, when
80 * another GUI app is started, another switch to and from graphics mode
81 * is possible. Also, when the system bugchecks in graphics mode we want
82 * to switch back to text mode to show the registers and stack trace.
83 * Last but not least, HalDisplayString is used a lot more in ReactOS,
84 * e.g. to print debug messages when the /DEBUGPORT=SCREEN boot option
85 * is present.
86 * 3 Components are involved in Reactos: HAL, BLUE.SYS and VIDEOPRT.SYS.
87 * As in NT, on boot HAL owns the display. When entering the text mode
88 * command interpreter, BLUE.SYS kicks in. It will write directly to the
89 * screen, more or less behind HALs back.
90 * When a GUI app is started, WIN32K.SYS will open the DISPLAY device.
91 * This open call will end up in VIDEOPRT.SYS. That component will then
92 * take ownership of the display by calling HalAcquireDisplayOwnership.
93 * When the GUI app terminates (WIN32K.SYS will close the DISPLAY device),
94 * we want to give ownership of the display back to HAL. Using the
95 * standard exported HAL functions, that's a bit of a problem, because
96 * there is no function defined to do that. In NT, this is handled by
97 * HalDisplayString, but that solution isn't satisfactory in ReactOS,
98 * because HalDisplayString is (in some cases) also used to output debug
99 * messages. If we do it the NT way, the first debug message output while
100 * in graphics mode would switch the display back to text mode.
101 * So, instead, if HalDisplayString detects that HAL doesn't have ownership
102 * of the display, it doesn't do anything.
103 * To return ownership to HAL, a new function is exported,
104 * HalReleaseDisplayOwnership. This function is called by the DISPLAY
105 * device Close routine in VIDEOPRT.SYS. It is also called at the beginning
106 * of a bug check, so HalDisplayString is activated again.
107 * Now, while the display is in graphics mode (not owned by HAL), BLUE.SYS
108 * should also refrain from writing to the screen buffer. The text mode
109 * screen buffer might overlap the graphics mode screen buffer, so changing
110 * something in the text mode buffer might mess up the graphics screen. To
111 * allow BLUE.SYS to detect if HAL owns the display, another new function is
112 * exported, HalQueryDisplayOwnership. BLUE.SYS will call this function to
113 * check if it's allowed to touch the text mode buffer.
114 *
115 * In an ideal world, when HAL takes ownership of the display, it should set
116 * up the CRT using real-mode (actually V86 mode, but who cares) INT 0x10
117 * calls. Unfortunately, this will require HAL to setup a real-mode interrupt
118 * table etc. So, we chickened out of that by having the loader set up the
119 * display before switching to protected mode. If HAL is given back ownership
120 * after a GUI app terminates, the INT 0x10 calls are made by VIDEOPRT.SYS,
121 * since there is already support for them via the VideoPortInt10 routine.
122 */
123
124 #include <ddk/ntddk.h>
125 #include <hal.h>
126
127 #define SCREEN_SYNCHRONIZATION
128
129 #define VGA_AC_INDEX 0x3c0
130 #define VGA_AC_READ 0x3c1
131 #define VGA_AC_WRITE 0x3c0
132
133 #define VGA_MISC_WRITE 0x3c2
134
135 #define VGA_SEQ_INDEX 0x3c4
136 #define VGA_SEQ_DATA 0x3c5
137
138 #define VGA_DAC_MASK 0x3c6
139 #define VGA_DAC_READ_INDEX 0x3c7
140 #define VGA_DAC_WRITE_INDEX 0x3c8
141 #define VGA_DAC_DATA 0x3c9
142 #define VGA_FEATURE_READ 0x3ca
143 #define VGA_MISC_READ 0x3cc
144
145 #define VGA_GC_INDEX 0x3ce
146 #define VGA_GC_DATA 0x3cf
147
148 #define VGA_CRTC_INDEX 0x3d4
149 #define VGA_CRTC_DATA 0x3d5
150
151 #define VGA_INSTAT_READ 0x3da
152
153 #define VGA_SEQ_NUM_REGISTERS 5
154 #define VGA_CRTC_NUM_REGISTERS 25
155 #define VGA_GC_NUM_REGISTERS 9
156 #define VGA_AC_NUM_REGISTERS 21
157
158 #define CRTC_COLUMNS 0x01
159 #define CRTC_OVERFLOW 0x07
160 #define CRTC_ROWS 0x12
161 #define CRTC_SCANLINES 0x09
162
163 #define CRTC_CURHI 0x0e
164 #define CRTC_CURLO 0x0f
165
166
167 #define CHAR_ATTRIBUTE_BLACK 0x00 /* black on black */
168 #define CHAR_ATTRIBUTE 0x17 /* grey on blue */
169
170 #define FONT_AMOUNT (8*8192)
171
172 /* VARIABLES ****************************************************************/
173
174 static ULONG CursorX = 0; /* Cursor Position */
175 static ULONG CursorY = 0;
176 static ULONG SizeX = 80; /* Display size */
177 static ULONG SizeY = 25;
178
179 static BOOLEAN DisplayInitialized = FALSE;
180 static BOOLEAN HalOwnsDisplay = TRUE;
181
182 static PUSHORT VideoBuffer = NULL;
183 static PUCHAR GraphVideoBuffer = NULL;
184
185 static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
186
187 static UCHAR SavedTextPalette[768];
188 static UCHAR SavedTextMiscOutReg;
189 static UCHAR SavedTextCrtcReg[VGA_CRTC_NUM_REGISTERS];
190 static UCHAR SavedTextAcReg[VGA_AC_NUM_REGISTERS];
191 static UCHAR SavedTextGcReg[VGA_GC_NUM_REGISTERS];
192 static UCHAR SavedTextSeqReg[VGA_SEQ_NUM_REGISTERS];
193 static UCHAR SavedTextFont[2][FONT_AMOUNT];
194 static BOOLEAN TextPaletteEnabled = FALSE;
195
196 /* PRIVATE FUNCTIONS *********************************************************/
197
198 VOID FASTCALL
199 HalClearDisplay (UCHAR CharAttribute)
200 {
201 WORD *ptr = (WORD*)VideoBuffer;
202 ULONG i;
203
204 for (i = 0; i < SizeX * SizeY; i++, ptr++)
205 *ptr = ((CharAttribute << 8) + ' ');
206
207 CursorX = 0;
208 CursorY = 0;
209 }
210
211
212 /* STATIC FUNCTIONS *********************************************************/
213
214 VOID STATIC
215 HalScrollDisplay (VOID)
216 {
217 PUSHORT ptr;
218 int i;
219
220 ptr = VideoBuffer + SizeX;
221 RtlMoveMemory(VideoBuffer,
222 ptr,
223 SizeX * (SizeY - 1) * 2);
224
225 ptr = VideoBuffer + (SizeX * (SizeY - 1));
226 for (i = 0; i < (int)SizeX; i++, ptr++)
227 {
228 *ptr = (CHAR_ATTRIBUTE << 8) + ' ';
229 }
230 }
231
232 VOID STATIC FASTCALL
233 HalPutCharacter (CHAR Character)
234 {
235 PUSHORT ptr;
236
237 ptr = VideoBuffer + ((CursorY * SizeX) + CursorX);
238 *ptr = (CHAR_ATTRIBUTE << 8) + Character;
239 }
240
241 VOID STATIC
242 HalDisablePalette(VOID)
243 {
244 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
245 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x20);
246 TextPaletteEnabled = FALSE;
247 }
248
249 VOID STATIC
250 HalEnablePalette(VOID)
251 {
252 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
253 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x00);
254 TextPaletteEnabled = TRUE;
255 }
256
257 UCHAR STATIC FASTCALL
258 HalReadGc(ULONG Index)
259 {
260 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
261 return(READ_PORT_UCHAR((PUCHAR)VGA_GC_DATA));
262 }
263
264 VOID STATIC FASTCALL
265 HalWriteGc(ULONG Index, UCHAR Value)
266 {
267 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
268 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_DATA, Value);
269 }
270
271 UCHAR STATIC FASTCALL
272 HalReadSeq(ULONG Index)
273 {
274 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
275 return(READ_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA));
276 }
277
278 VOID STATIC FASTCALL
279 HalWriteSeq(ULONG Index, UCHAR Value)
280 {
281 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
282 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA, Value);
283 }
284
285 VOID STATIC FASTCALL
286 HalWriteAc(ULONG Index, UCHAR Value)
287 {
288 if (TextPaletteEnabled)
289 {
290 Index &= ~0x20;
291 }
292 else
293 {
294 Index |= 0x20;
295 }
296 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
297 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
298 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_WRITE, Value);
299 }
300
301 UCHAR STATIC FASTCALL
302 HalReadAc(ULONG Index)
303 {
304 if (TextPaletteEnabled)
305 {
306 Index &= ~0x20;
307 }
308 else
309 {
310 Index |= 0x20;
311 }
312 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
313 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
314 return(READ_PORT_UCHAR((PUCHAR)VGA_AC_READ));
315 }
316
317 VOID STATIC FASTCALL
318 HalWriteCrtc(ULONG Index, UCHAR Value)
319 {
320 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
321 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, Value);
322 }
323
324 UCHAR STATIC FASTCALL
325 HalReadCrtc(ULONG Index)
326 {
327 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
328 return(READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA));
329 }
330
331 VOID STATIC FASTCALL
332 HalResetSeq(BOOLEAN Start)
333 {
334 if (Start)
335 {
336 HalWriteSeq(0x00, 0x01);
337 }
338 else
339 {
340 HalWriteSeq(0x00, 0x03);
341 }
342 }
343
344 VOID STATIC FASTCALL
345 HalBlankScreen(BOOLEAN On)
346 {
347 UCHAR Scrn;
348
349 Scrn = HalReadSeq(0x01);
350
351 if (On)
352 {
353 Scrn &= ~0x20;
354 }
355 else
356 {
357 Scrn |= 0x20;
358 }
359
360 HalResetSeq(TRUE);
361 HalWriteSeq(0x01, Scrn);
362 HalResetSeq(FALSE);
363 }
364
365 VOID STATIC
366 HalSaveFont(VOID)
367 {
368 UCHAR Attr10;
369 UCHAR MiscOut, Gc4, Gc5, Gc6, Seq2, Seq4;
370 ULONG i;
371
372 /* Check if we are already in graphics mode. */
373 Attr10 = HalReadAc(0x10);
374 if (Attr10 & 0x01)
375 {
376 return;
377 }
378
379 /* Save registers. */
380 MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
381 Gc4 = HalReadGc(0x04);
382 Gc5 = HalReadGc(0x05);
383 Gc6 = HalReadGc(0x06);
384 Seq2 = HalReadSeq(0x02);
385 Seq4 = HalReadSeq(0x04);
386
387 /* Force colour mode. */
388 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x01));
389
390 HalBlankScreen(FALSE);
391
392 for (i = 0; i < 2; i++)
393 {
394 /* Save font 1 */
395 HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
396 HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
397 HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
398 HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0 */
399 HalWriteGc(0x06, 0x05); /* Set graphics. */
400 memcpy(SavedTextFont[i], GraphVideoBuffer, FONT_AMOUNT);
401 }
402
403 /* Restore registers. */
404 HalWriteAc(0x10, Attr10);
405 HalWriteSeq(0x02, Seq2);
406 HalWriteSeq(0x04, Seq4);
407 HalWriteGc(0x04, Gc4);
408 HalWriteGc(0x05, Gc5);
409 HalWriteGc(0x06, Gc6);
410 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
411
412 HalBlankScreen(TRUE);
413 }
414
415 VOID STATIC
416 HalSaveMode(VOID)
417 {
418 ULONG i;
419
420 SavedTextMiscOutReg = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
421
422 for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
423 {
424 SavedTextCrtcReg[i] = HalReadCrtc(i);
425 }
426
427 HalEnablePalette();
428 for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
429 {
430 SavedTextAcReg[i] = HalReadAc(i);
431 }
432 HalDisablePalette();
433
434 for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
435 {
436 SavedTextGcReg[i] = HalReadGc(i);
437 }
438
439 for (i = 0; i < VGA_SEQ_NUM_REGISTERS; i++)
440 {
441 SavedTextSeqReg[i] = HalReadSeq(i);
442 }
443 }
444
445 VOID STATIC
446 HalDacDelay(VOID)
447 {
448 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
449 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
450 }
451
452 VOID STATIC
453 HalSavePalette(VOID)
454 {
455 ULONG i;
456 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
457 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_READ_INDEX, 0x00);
458 for (i = 0; i < 768; i++)
459 {
460 SavedTextPalette[i] = READ_PORT_UCHAR((PUCHAR)VGA_DAC_DATA);
461 HalDacDelay();
462 }
463 }
464
465 VOID STATIC
466 HalRestoreFont(VOID)
467 {
468 UCHAR MiscOut, Attr10, Gc1, Gc3, Gc4, Gc5, Gc6, Gc8;
469 UCHAR Seq2, Seq4;
470 ULONG i;
471
472 /* Save registers. */
473 MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
474 Attr10 = HalReadAc(0x10);
475 Gc1 = HalReadGc(0x01);
476 Gc3 = HalReadGc(0x03);
477 Gc4 = HalReadGc(0x04);
478 Gc5 = HalReadGc(0x05);
479 Gc6 = HalReadGc(0x06);
480 Gc8 = HalReadGc(0x08);
481 Seq2 = HalReadSeq(0x02);
482 Seq4 = HalReadSeq(0x04);
483
484 /* Force into colour mode. */
485 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x10));
486
487 HalBlankScreen(FALSE);
488
489 HalWriteGc(0x03, 0x00); /* Don't rotate; write unmodified. */
490 HalWriteGc(0x08, 0xFF); /* Write all bits. */
491 HalWriteGc(0x01, 0x00); /* All planes from CPU. */
492
493 for (i = 0; i < 2; i++)
494 {
495 HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
496 HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
497 HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
498 HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0. */
499 HalWriteGc(0x06, 0x05); /* Set graphics. */
500 memcpy(GraphVideoBuffer, SavedTextFont[i], FONT_AMOUNT);
501 }
502
503 HalBlankScreen(TRUE);
504
505 /* Restore registers. */
506 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
507 HalWriteAc(0x10, Attr10);
508 HalWriteGc(0x01, Gc1);
509 HalWriteGc(0x03, Gc3);
510 HalWriteGc(0x04, Gc4);
511 HalWriteGc(0x05, Gc5);
512 HalWriteGc(0x06, Gc6);
513 HalWriteGc(0x08, Gc8);
514 HalWriteSeq(0x02, Seq2);
515 HalWriteSeq(0x04, Seq4);
516 }
517
518 VOID STATIC
519 HalRestoreMode(VOID)
520 {
521 ULONG i;
522
523 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, SavedTextMiscOutReg);
524
525 for (i = 1; i < VGA_SEQ_NUM_REGISTERS; i++)
526 {
527 HalWriteSeq(i, SavedTextSeqReg[i]);
528 }
529
530 /* Unlock CRTC registers 0-7 */
531 HalWriteCrtc(17, (UCHAR)(SavedTextCrtcReg[17] & ~0x80));
532
533 for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
534 {
535 HalWriteCrtc(i, SavedTextCrtcReg[i]);
536 }
537
538 for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
539 {
540 HalWriteGc(i, SavedTextGcReg[i]);
541 }
542
543 HalEnablePalette();
544 for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
545 {
546 HalWriteAc(i, SavedTextAcReg[i]);
547 }
548 HalDisablePalette();
549 }
550
551 VOID STATIC
552 HalRestorePalette(VOID)
553 {
554 ULONG i;
555 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
556 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_WRITE_INDEX, 0x00);
557 for (i = 0; i < 768; i++)
558 {
559 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_DATA, SavedTextPalette[i]);
560 HalDacDelay();
561 }
562 HalDisablePalette();
563 }
564
565 /* PRIVATE FUNCTIONS ********************************************************/
566
567 VOID FASTCALL
568 HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock)
569 /*
570 * FUNCTION: Initalize the display
571 * ARGUMENTS:
572 * InitParameters = Parameters setup by the boot loader
573 */
574 {
575 if (DisplayInitialized == FALSE)
576 {
577 ULONG ScanLines;
578 ULONG Data;
579
580 VideoBuffer = (PUSHORT)(0xff3b8000);
581 GraphVideoBuffer = (PUCHAR)(0xff3a0000);
582
583 /* Set cursor position */
584 // CursorX = LoaderBlock->cursorx;
585 // CursorY = LoaderBlock->cursory;
586 CursorX = 0;
587 CursorY = 0;
588
589 /* read screen size from the crtc */
590 /* FIXME: screen size should be read from the boot parameters */
591 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_COLUMNS);
592 SizeX = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) + 1;
593 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_ROWS);
594 SizeY = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
595 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_OVERFLOW);
596 Data = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
597 SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3));
598 SizeY++;
599 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_SCANLINES);
600 ScanLines = (READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) & 0x1F) + 1;
601 SizeY = SizeY / ScanLines;
602
603 #ifdef BOCHS_30ROWS
604 SizeY=30;
605 #endif
606 HalClearDisplay(CHAR_ATTRIBUTE_BLACK);
607
608 DisplayInitialized = TRUE;
609
610 /*
611 Save the VGA state at this point so we can restore it on a bugcheck.
612 */
613 HalSavePalette();
614 HalSaveMode();
615 HalSaveFont();
616 }
617 }
618
619
620 /* PUBLIC FUNCTIONS *********************************************************/
621
622 VOID STDCALL
623 HalReleaseDisplayOwnership(VOID)
624 /*
625 * FUNCTION: Release ownership of display back to HAL
626 */
627 {
628 if (HalResetDisplayParameters == NULL)
629 return;
630
631 if (HalOwnsDisplay == TRUE)
632 return;
633
634 if (!HalResetDisplayParameters(SizeX, SizeY))
635 {
636 HalRestoreMode();
637 HalRestoreFont();
638 HalRestorePalette();
639 }
640 HalOwnsDisplay = TRUE;
641 HalClearDisplay(CHAR_ATTRIBUTE);
642 }
643
644
645 VOID STDCALL
646 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
647 /*
648 * FUNCTION:
649 * ARGUMENTS:
650 * ResetDisplayParameters = Pointer to a driver specific
651 * reset routine.
652 */
653 {
654 HalOwnsDisplay = FALSE;
655 HalResetDisplayParameters = ResetDisplayParameters;
656 }
657
658 VOID STDCALL
659 HalDisplayString(IN PCH String)
660 /*
661 * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
662 * already and displays a string
663 * ARGUMENT:
664 * string = ASCII string to display
665 * NOTE: Use with care because there is no support for returning from BSOD
666 * mode
667 */
668 {
669 PCH pch;
670 #ifdef SCREEN_SYNCHRONIZATION
671 int offset;
672 #endif
673 static KSPIN_LOCK Lock;
674 KIRQL OldIrql;
675 ULONG Flags;
676
677 /* See comment at top of file */
678 if (!HalOwnsDisplay)
679 {
680 return;
681 }
682
683 pch = String;
684
685 OldIrql = KfRaiseIrql(HIGH_LEVEL);
686 KiAcquireSpinLock(&Lock);
687
688 Ki386SaveFlags(Flags);
689 Ki386DisableInterrupts();
690
691
692 #if 0
693 if (HalOwnsDisplay == FALSE)
694 {
695 HalReleaseDisplayOwnership();
696 }
697 #endif
698
699 #ifdef SCREEN_SYNCHRONIZATION
700 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
701 offset = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA)<<8;
702 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
703 offset += READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
704
705 CursorY = offset / SizeX;
706 CursorX = offset % SizeX;
707 #endif
708
709 while (*pch != 0)
710 {
711 if (*pch == '\n')
712 {
713 CursorY++;
714 CursorX = 0;
715 }
716 else if (*pch == '\b')
717 {
718 if (CursorX > 0)
719 {
720 CursorX--;
721 }
722 }
723 else if (*pch != '\r')
724 {
725 HalPutCharacter (*pch);
726 CursorX++;
727
728 if (CursorX >= SizeX)
729 {
730 CursorY++;
731 CursorX = 0;
732 }
733 }
734
735 if (CursorY >= SizeY)
736 {
737 HalScrollDisplay ();
738 CursorY = SizeY - 1;
739 }
740
741 pch++;
742 }
743
744 #ifdef SCREEN_SYNCHRONIZATION
745 offset = (CursorY * SizeX) + CursorX;
746
747 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
748 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)(offset & 0xff));
749 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
750 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)((offset >> 8) & 0xff));
751 #endif
752 Ki386RestoreFlags(Flags);
753
754 KiReleaseSpinLock(&Lock);
755 KfLowerIrql(OldIrql);
756 }
757
758 VOID STDCALL
759 HalQueryDisplayParameters(OUT PULONG DispSizeX,
760 OUT PULONG DispSizeY,
761 OUT PULONG CursorPosX,
762 OUT PULONG CursorPosY)
763 {
764 if (DispSizeX)
765 *DispSizeX = SizeX;
766 if (DispSizeY)
767 *DispSizeY = SizeY;
768 if (CursorPosX)
769 *CursorPosX = CursorX;
770 if (CursorPosY)
771 *CursorPosY = CursorY;
772 }
773
774
775 VOID STDCALL
776 HalSetDisplayParameters(IN ULONG CursorPosX,
777 IN ULONG CursorPosY)
778 {
779 CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
780 CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
781 }
782
783
784 BOOLEAN STDCALL
785 HalQueryDisplayOwnership(VOID)
786 {
787 return !HalOwnsDisplay;
788 }
789
790 /* EOF */