bf89c63e6c4fad4a79bd995655c28d20f9c04099
[reactos.git] / reactos / hal / halx86 / generic / 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$
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 <hal.h>
125 #define NDEBUG
126 #include <debug.h>
127
128
129 #define SCREEN_SYNCHRONIZATION
130
131 #define VGA_GRAPH_MEM 0xa0000
132 #define VGA_CHAR_MEM 0xb8000
133 #define VGA_END_MEM 0xbffff
134
135 #define VGA_AC_INDEX 0x3c0
136 #define VGA_AC_READ 0x3c1
137 #define VGA_AC_WRITE 0x3c0
138
139 #define VGA_MISC_WRITE 0x3c2
140
141 #define VGA_SEQ_INDEX 0x3c4
142 #define VGA_SEQ_DATA 0x3c5
143
144 #define VGA_DAC_MASK 0x3c6
145 #define VGA_DAC_READ_INDEX 0x3c7
146 #define VGA_DAC_WRITE_INDEX 0x3c8
147 #define VGA_DAC_DATA 0x3c9
148 #define VGA_FEATURE_READ 0x3ca
149 #define VGA_MISC_READ 0x3cc
150
151 #define VGA_GC_INDEX 0x3ce
152 #define VGA_GC_DATA 0x3cf
153
154 #define VGA_CRTC_INDEX 0x3d4
155 #define VGA_CRTC_DATA 0x3d5
156
157 #define VGA_INSTAT_READ 0x3da
158
159 #define VGA_SEQ_NUM_REGISTERS 5
160 #define VGA_CRTC_NUM_REGISTERS 25
161 #define VGA_GC_NUM_REGISTERS 9
162 #define VGA_AC_NUM_REGISTERS 21
163
164 #define CRTC_COLUMNS 0x01
165 #define CRTC_OVERFLOW 0x07
166 #define CRTC_ROWS 0x12
167 #define CRTC_SCANLINES 0x09
168
169 #define CRTC_CURHI 0x0e
170 #define CRTC_CURLO 0x0f
171
172
173 #define CHAR_ATTRIBUTE_BLACK 0x00 /* black on black */
174 #define CHAR_ATTRIBUTE 0x07 /* grey on black */
175
176 #define FONT_AMOUNT (8*8192)
177
178 /* VARIABLES ****************************************************************/
179
180 static ULONG CursorX = 0; /* Cursor Position */
181 static ULONG CursorY = 0;
182 static ULONG SizeX = 80; /* Display size */
183 static ULONG SizeY = 25;
184
185 static BOOLEAN DisplayInitialized = FALSE;
186 static BOOLEAN HalOwnsDisplay = TRUE;
187
188 static PUSHORT VideoBuffer = NULL;
189 static PUCHAR GraphVideoBuffer = NULL;
190
191 static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
192
193 static UCHAR SavedTextPalette[768];
194 static UCHAR SavedTextMiscOutReg;
195 static UCHAR SavedTextCrtcReg[VGA_CRTC_NUM_REGISTERS];
196 static UCHAR SavedTextAcReg[VGA_AC_NUM_REGISTERS];
197 static UCHAR SavedTextGcReg[VGA_GC_NUM_REGISTERS];
198 static UCHAR SavedTextSeqReg[VGA_SEQ_NUM_REGISTERS];
199 static UCHAR SavedTextFont[2][FONT_AMOUNT];
200 static BOOLEAN TextPaletteEnabled = FALSE;
201
202 /* PRIVATE FUNCTIONS *********************************************************/
203
204 VOID FASTCALL
205 HalClearDisplay (UCHAR CharAttribute)
206 {
207 WORD *ptr = (WORD*)VideoBuffer;
208 ULONG i;
209
210 for (i = 0; i < SizeX * SizeY; i++, ptr++)
211 *ptr = ((CharAttribute << 8) + ' ');
212
213 CursorX = 0;
214 CursorY = 0;
215 }
216
217
218 /* STATIC FUNCTIONS *********************************************************/
219
220 VOID STATIC
221 HalScrollDisplay (VOID)
222 {
223 PUSHORT ptr;
224 int i;
225
226 ptr = VideoBuffer + SizeX;
227 RtlMoveMemory(VideoBuffer,
228 ptr,
229 SizeX * (SizeY - 1) * 2);
230
231 ptr = VideoBuffer + (SizeX * (SizeY - 1));
232 for (i = 0; i < (int)SizeX; i++, ptr++)
233 {
234 *ptr = (CHAR_ATTRIBUTE << 8) + ' ';
235 }
236 }
237
238 VOID STATIC FASTCALL
239 HalPutCharacter (CHAR Character)
240 {
241 PUSHORT ptr;
242
243 ptr = VideoBuffer + ((CursorY * SizeX) + CursorX);
244 *ptr = (CHAR_ATTRIBUTE << 8) + Character;
245 }
246
247 VOID STATIC
248 HalDisablePalette(VOID)
249 {
250 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
251 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x20);
252 TextPaletteEnabled = FALSE;
253 }
254
255 VOID STATIC
256 HalEnablePalette(VOID)
257 {
258 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
259 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x00);
260 TextPaletteEnabled = TRUE;
261 }
262
263 UCHAR STATIC FASTCALL
264 HalReadGc(ULONG Index)
265 {
266 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
267 return(READ_PORT_UCHAR((PUCHAR)VGA_GC_DATA));
268 }
269
270 VOID STATIC FASTCALL
271 HalWriteGc(ULONG Index, UCHAR Value)
272 {
273 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
274 WRITE_PORT_UCHAR((PUCHAR)VGA_GC_DATA, Value);
275 }
276
277 UCHAR STATIC FASTCALL
278 HalReadSeq(ULONG Index)
279 {
280 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
281 return(READ_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA));
282 }
283
284 VOID STATIC FASTCALL
285 HalWriteSeq(ULONG Index, UCHAR Value)
286 {
287 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
288 WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA, Value);
289 }
290
291 VOID STATIC FASTCALL
292 HalWriteAc(ULONG Index, UCHAR Value)
293 {
294 if (TextPaletteEnabled)
295 {
296 Index &= ~0x20;
297 }
298 else
299 {
300 Index |= 0x20;
301 }
302 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
303 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
304 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_WRITE, Value);
305 }
306
307 UCHAR STATIC FASTCALL
308 HalReadAc(ULONG Index)
309 {
310 if (TextPaletteEnabled)
311 {
312 Index &= ~0x20;
313 }
314 else
315 {
316 Index |= 0x20;
317 }
318 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
319 WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
320 return(READ_PORT_UCHAR((PUCHAR)VGA_AC_READ));
321 }
322
323 VOID STATIC FASTCALL
324 HalWriteCrtc(ULONG Index, UCHAR Value)
325 {
326 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
327 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, Value);
328 }
329
330 UCHAR STATIC FASTCALL
331 HalReadCrtc(ULONG Index)
332 {
333 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
334 return(READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA));
335 }
336
337 VOID STATIC FASTCALL
338 HalResetSeq(BOOLEAN Start)
339 {
340 if (Start)
341 {
342 HalWriteSeq(0x00, 0x01);
343 }
344 else
345 {
346 HalWriteSeq(0x00, 0x03);
347 }
348 }
349
350 VOID STATIC FASTCALL
351 HalBlankScreen(BOOLEAN On)
352 {
353 UCHAR Scrn;
354
355 Scrn = HalReadSeq(0x01);
356
357 if (On)
358 {
359 Scrn &= ~0x20;
360 }
361 else
362 {
363 Scrn |= 0x20;
364 }
365
366 HalResetSeq(TRUE);
367 HalWriteSeq(0x01, Scrn);
368 HalResetSeq(FALSE);
369 }
370
371 VOID STATIC
372 HalSaveFont(VOID)
373 {
374 UCHAR Attr10;
375 UCHAR MiscOut, Gc4, Gc5, Gc6, Seq2, Seq4;
376 ULONG i;
377
378 /* Check if we are already in graphics mode. */
379 Attr10 = HalReadAc(0x10);
380 if (Attr10 & 0x01)
381 {
382 return;
383 }
384
385 /* Save registers. */
386 MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
387 Gc4 = HalReadGc(0x04);
388 Gc5 = HalReadGc(0x05);
389 Gc6 = HalReadGc(0x06);
390 Seq2 = HalReadSeq(0x02);
391 Seq4 = HalReadSeq(0x04);
392
393 /* Force colour mode. */
394 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x01));
395
396 HalBlankScreen(FALSE);
397
398 for (i = 0; i < 2; i++)
399 {
400 /* Save font 1 */
401 HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
402 HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
403 HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
404 HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0 */
405 HalWriteGc(0x06, 0x05); /* Set graphics. */
406 memcpy(SavedTextFont[i], GraphVideoBuffer, FONT_AMOUNT);
407 }
408
409 /* Restore registers. */
410 HalWriteAc(0x10, Attr10);
411 HalWriteSeq(0x02, Seq2);
412 HalWriteSeq(0x04, Seq4);
413 HalWriteGc(0x04, Gc4);
414 HalWriteGc(0x05, Gc5);
415 HalWriteGc(0x06, Gc6);
416 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
417
418 HalBlankScreen(TRUE);
419 }
420
421 VOID STATIC
422 HalSaveMode(VOID)
423 {
424 ULONG i;
425
426 SavedTextMiscOutReg = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
427
428 for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
429 {
430 SavedTextCrtcReg[i] = HalReadCrtc(i);
431 }
432
433 HalEnablePalette();
434 for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
435 {
436 SavedTextAcReg[i] = HalReadAc(i);
437 }
438 HalDisablePalette();
439
440 for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
441 {
442 SavedTextGcReg[i] = HalReadGc(i);
443 }
444
445 for (i = 0; i < VGA_SEQ_NUM_REGISTERS; i++)
446 {
447 SavedTextSeqReg[i] = HalReadSeq(i);
448 }
449 }
450
451 VOID STATIC
452 HalDacDelay(VOID)
453 {
454 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
455 (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
456 }
457
458 VOID STATIC
459 HalSavePalette(VOID)
460 {
461 ULONG i;
462 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
463 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_READ_INDEX, 0x00);
464 for (i = 0; i < 768; i++)
465 {
466 SavedTextPalette[i] = READ_PORT_UCHAR((PUCHAR)VGA_DAC_DATA);
467 HalDacDelay();
468 }
469 }
470
471 VOID STATIC
472 HalRestoreFont(VOID)
473 {
474 UCHAR MiscOut, Attr10, Gc1, Gc3, Gc4, Gc5, Gc6, Gc8;
475 UCHAR Seq2, Seq4;
476 ULONG i;
477
478 /* Save registers. */
479 MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
480 Attr10 = HalReadAc(0x10);
481 Gc1 = HalReadGc(0x01);
482 Gc3 = HalReadGc(0x03);
483 Gc4 = HalReadGc(0x04);
484 Gc5 = HalReadGc(0x05);
485 Gc6 = HalReadGc(0x06);
486 Gc8 = HalReadGc(0x08);
487 Seq2 = HalReadSeq(0x02);
488 Seq4 = HalReadSeq(0x04);
489
490 /* Force into colour mode. */
491 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x10));
492
493 HalBlankScreen(FALSE);
494
495 HalWriteGc(0x03, 0x00); /* Don't rotate; write unmodified. */
496 HalWriteGc(0x08, 0xFF); /* Write all bits. */
497 HalWriteGc(0x01, 0x00); /* All planes from CPU. */
498
499 for (i = 0; i < 2; i++)
500 {
501 HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
502 HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
503 HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
504 HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0. */
505 HalWriteGc(0x06, 0x05); /* Set graphics. */
506 memcpy(GraphVideoBuffer, SavedTextFont[i], FONT_AMOUNT);
507 }
508
509 HalBlankScreen(TRUE);
510
511 /* Restore registers. */
512 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
513 HalWriteAc(0x10, Attr10);
514 HalWriteGc(0x01, Gc1);
515 HalWriteGc(0x03, Gc3);
516 HalWriteGc(0x04, Gc4);
517 HalWriteGc(0x05, Gc5);
518 HalWriteGc(0x06, Gc6);
519 HalWriteGc(0x08, Gc8);
520 HalWriteSeq(0x02, Seq2);
521 HalWriteSeq(0x04, Seq4);
522 }
523
524 VOID STATIC
525 HalRestoreMode(VOID)
526 {
527 ULONG i;
528
529 WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, SavedTextMiscOutReg);
530
531 for (i = 1; i < VGA_SEQ_NUM_REGISTERS; i++)
532 {
533 HalWriteSeq(i, SavedTextSeqReg[i]);
534 }
535
536 /* Unlock CRTC registers 0-7 */
537 HalWriteCrtc(17, (UCHAR)(SavedTextCrtcReg[17] & ~0x80));
538
539 for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
540 {
541 HalWriteCrtc(i, SavedTextCrtcReg[i]);
542 }
543
544 for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
545 {
546 HalWriteGc(i, SavedTextGcReg[i]);
547 }
548
549 HalEnablePalette();
550 for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
551 {
552 HalWriteAc(i, SavedTextAcReg[i]);
553 }
554 HalDisablePalette();
555 }
556
557 VOID STATIC
558 HalRestorePalette(VOID)
559 {
560 ULONG i;
561 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
562 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_WRITE_INDEX, 0x00);
563 for (i = 0; i < 768; i++)
564 {
565 WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_DATA, SavedTextPalette[i]);
566 HalDacDelay();
567 }
568 HalDisablePalette();
569 }
570
571 /* PRIVATE FUNCTIONS ********************************************************/
572
573 VOID FASTCALL
574 HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock)
575 /*
576 * FUNCTION: Initalize the display
577 * ARGUMENTS:
578 * InitParameters = Parameters setup by the boot loader
579 */
580 {
581 PHYSICAL_ADDRESS PhysBuffer;
582
583 if (! DisplayInitialized)
584 {
585 ULONG ScanLines;
586 ULONG Data;
587
588 PhysBuffer.u.HighPart = 0;
589 PhysBuffer.u.LowPart = VGA_GRAPH_MEM;
590 GraphVideoBuffer = MmMapIoSpace(PhysBuffer, VGA_END_MEM - VGA_GRAPH_MEM + 1, MmNonCached);
591 if (NULL == GraphVideoBuffer)
592 {
593 return;
594 }
595 VideoBuffer = (PUSHORT) (GraphVideoBuffer + (VGA_CHAR_MEM - VGA_GRAPH_MEM));
596
597 /* Set cursor position */
598 // CursorX = LoaderBlock->cursorx;
599 // CursorY = LoaderBlock->cursory;
600 CursorX = 0;
601 CursorY = 0;
602
603 /* read screen size from the crtc */
604 /* FIXME: screen size should be read from the boot parameters */
605 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_COLUMNS);
606 SizeX = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) + 1;
607 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_ROWS);
608 SizeY = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
609 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_OVERFLOW);
610 Data = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
611 SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3));
612 SizeY++;
613 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_SCANLINES);
614 ScanLines = (READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) & 0x1F) + 1;
615 SizeY = SizeY / ScanLines;
616
617 #ifdef BOCHS_30ROWS
618 SizeY=30;
619 #endif
620 HalClearDisplay(CHAR_ATTRIBUTE_BLACK);
621
622 DisplayInitialized = TRUE;
623
624 /*
625 Save the VGA state at this point so we can restore it on a bugcheck.
626 */
627 HalSavePalette();
628 HalSaveMode();
629 HalSaveFont();
630 }
631 }
632
633
634 /* PUBLIC FUNCTIONS *********************************************************/
635
636 VOID STDCALL
637 HalReleaseDisplayOwnership(VOID)
638 /*
639 * FUNCTION: Release ownership of display back to HAL
640 */
641 {
642 if (HalResetDisplayParameters == NULL)
643 return;
644
645 if (HalOwnsDisplay == TRUE)
646 return;
647
648 if (!HalResetDisplayParameters(SizeX, SizeY))
649 {
650 HalRestoreMode();
651 HalRestoreFont();
652 HalRestorePalette();
653 }
654 HalOwnsDisplay = TRUE;
655 HalClearDisplay(CHAR_ATTRIBUTE);
656 }
657
658
659 VOID STDCALL
660 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
661 /*
662 * FUNCTION:
663 * ARGUMENTS:
664 * ResetDisplayParameters = Pointer to a driver specific
665 * reset routine.
666 */
667 {
668 HalOwnsDisplay = FALSE;
669 HalResetDisplayParameters = ResetDisplayParameters;
670 }
671
672 VOID STDCALL
673 HalDisplayString(IN PCH String)
674 /*
675 * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
676 * already and displays a string
677 * ARGUMENT:
678 * string = ASCII string to display
679 * NOTE: Use with care because there is no support for returning from BSOD
680 * mode
681 */
682 {
683 PCH pch;
684 #ifdef SCREEN_SYNCHRONIZATION
685 int offset;
686 #endif
687 static KSPIN_LOCK Lock;
688 KIRQL OldIrql;
689 ULONG Flags;
690
691 /* See comment at top of file */
692 if (! HalOwnsDisplay || ! DisplayInitialized)
693 {
694 return;
695 }
696
697 pch = String;
698
699 OldIrql = KfRaiseIrql(HIGH_LEVEL);
700 KiAcquireSpinLock(&Lock);
701
702 Ki386SaveFlags(Flags);
703 Ki386DisableInterrupts();
704
705 #ifdef SCREEN_SYNCHRONIZATION
706 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
707 offset = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA)<<8;
708 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
709 offset += READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
710
711 CursorY = offset / SizeX;
712 CursorX = offset % SizeX;
713 #endif
714
715 while (*pch != 0)
716 {
717 if (*pch == '\n')
718 {
719 CursorY++;
720 CursorX = 0;
721 }
722 else if (*pch == '\b')
723 {
724 if (CursorX > 0)
725 {
726 CursorX--;
727 }
728 }
729 else if (*pch != '\r')
730 {
731 HalPutCharacter (*pch);
732 CursorX++;
733
734 if (CursorX >= SizeX)
735 {
736 CursorY++;
737 CursorX = 0;
738 }
739 }
740
741 if (CursorY >= SizeY)
742 {
743 HalScrollDisplay ();
744 CursorY = SizeY - 1;
745 }
746
747 pch++;
748 }
749
750 #ifdef SCREEN_SYNCHRONIZATION
751 offset = (CursorY * SizeX) + CursorX;
752
753 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
754 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)(offset & 0xff));
755 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
756 WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)((offset >> 8) & 0xff));
757 #endif
758 Ki386RestoreFlags(Flags);
759
760 KiReleaseSpinLock(&Lock);
761 KfLowerIrql(OldIrql);
762 }
763
764 VOID STDCALL
765 HalQueryDisplayParameters(OUT PULONG DispSizeX,
766 OUT PULONG DispSizeY,
767 OUT PULONG CursorPosX,
768 OUT PULONG CursorPosY)
769 {
770 if (DispSizeX)
771 *DispSizeX = SizeX;
772 if (DispSizeY)
773 *DispSizeY = SizeY;
774 if (CursorPosX)
775 *CursorPosX = CursorX;
776 if (CursorPosY)
777 *CursorPosY = CursorY;
778 }
779
780
781 VOID STDCALL
782 HalSetDisplayParameters(IN ULONG CursorPosX,
783 IN ULONG CursorPosY)
784 {
785 CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
786 CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
787 }
788
789
790 BOOLEAN STDCALL
791 HalQueryDisplayOwnership(VOID)
792 {
793 return !HalOwnsDisplay;
794 }
795
796 /* EOF */