update for HEAD-2003091401
[reactos.git] / 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$
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 <mps.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 WORD *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 BOOL 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   WORD *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 < SizeX; i++, ptr++)
227     {
228       *ptr = (CHAR_ATTRIBUTE << 8) + ' ';
229     }
230 }
231
232 VOID STATIC FASTCALL
233 HalPutCharacter (CHAR Character)
234 {
235   WORD *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, 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, 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, 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, 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, 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, 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, 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, Index);
328   return(READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA));
329 }
330
331 VOID STATIC FASTCALL
332 HalResetSeq(BOOL 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(BOOL 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, MiscOut | 0x01);
389
390   HalBlankScreen(FALSE);
391
392   for (i = 0; i < 2; i++)
393     {
394       /* Save font 1 */
395       HalWriteSeq(0x02, 0x04 << i); /* Write to plane 2 or 3 */
396       HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
397       HalWriteGc(0x04, 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, 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, 0x04 << i); /* Write to plane 2 or 3 */
496       HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
497       HalWriteGc(0x04, 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, 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 = (WORD *)(0xd0000000 + 0xb8000);
581       GraphVideoBuffer = (PUCHAR)(0xd0000000 + 0xa0000);
582 //      VideoBuffer = HalMapPhysicalMemory (0xb8000, 2);
583
584       /* Set cursor position */
585 //      CursorX = LoaderBlock->cursorx;
586 //      CursorY = LoaderBlock->cursory;
587       CursorX = 0;
588       CursorY = 0;
589
590       /* read screen size from the crtc */
591       /* FIXME: screen size should be read from the boot parameters */
592       WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_COLUMNS);
593       SizeX = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) + 1;
594       WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_ROWS);
595       SizeY = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
596       WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_OVERFLOW);
597       Data = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
598       SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3));
599       SizeY++;
600       WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_SCANLINES);
601       ScanLines = (READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) & 0x1F) + 1;
602       SizeY = SizeY / ScanLines;
603
604 #ifdef BOCHS_30ROWS
605       SizeY=30;
606 #endif
607       HalClearDisplay(CHAR_ATTRIBUTE_BLACK);
608
609       DisplayInitialized = TRUE;
610
611       /* 
612          Save the VGA state at this point so we can restore it on a bugcheck.
613       */
614       HalSavePalette();
615       HalSaveMode();
616       HalSaveFont();
617     }
618 }
619
620
621 /* PUBLIC FUNCTIONS *********************************************************/
622
623 VOID STDCALL
624 HalReleaseDisplayOwnership()
625 /*
626  * FUNCTION: Release ownership of display back to HAL
627  */
628 {
629   if (HalResetDisplayParameters == NULL)
630     return;
631
632   if (HalOwnsDisplay == TRUE)
633     return;
634
635   if (!HalResetDisplayParameters(SizeX, SizeY))
636     {
637       HalRestoreMode();
638       HalRestoreFont();
639       HalRestorePalette();
640     }
641   HalOwnsDisplay = TRUE;
642   HalClearDisplay(CHAR_ATTRIBUTE);
643 }
644
645
646 VOID STDCALL
647 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
648 /*
649  * FUNCTION: 
650  * ARGUMENTS:
651  *         ResetDisplayParameters = Pointer to a driver specific
652  *         reset routine.
653  */
654 {
655   HalOwnsDisplay = FALSE;
656   HalResetDisplayParameters = ResetDisplayParameters;
657 }
658
659 VOID STDCALL
660 HalDisplayString(IN PCH String)
661 /*
662  * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
663  * already and displays a string
664  * ARGUMENT:
665  *        string = ASCII string to display
666  * NOTE: Use with care because there is no support for returning from BSOD
667  * mode
668  */
669 {
670   PCH pch;
671 #ifdef SCREEN_SYNCHRONIZATION
672   int offset;
673 #endif
674   static KSPIN_LOCK Lock;
675   ULONG Flags;
676
677   /* See comment at top of file */
678   if (! HalOwnsDisplay)
679     {
680       return;
681     }
682
683   pch = String;
684
685   pushfl(Flags);
686   __asm__ ("cli\n\t");
687   KeAcquireSpinLockAtDpcLevel(&Lock);
688
689 #if 0  
690   if (HalOwnsDisplay == FALSE)
691     {
692       HalReleaseDisplayOwnership();
693     }
694 #endif
695   
696 #ifdef SCREEN_SYNCHRONIZATION
697   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
698   offset = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA)<<8;
699   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
700   offset += READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
701   
702   CursorY = offset / SizeX;
703   CursorX = offset % SizeX;
704 #endif
705   
706   while (*pch != 0)
707     {
708       if (*pch == '\n')
709         {
710           CursorY++;
711           CursorX = 0;
712         }
713       else if (*pch == '\b')
714         {
715           if (CursorX > 0)
716             {
717               CursorX--;
718             }
719         }
720       else if (*pch != '\r')
721         {
722           HalPutCharacter (*pch);
723           CursorX++;
724           
725           if (CursorX >= SizeX)
726             {
727               CursorY++;
728               CursorX = 0;
729             }
730         }
731   
732       if (CursorY >= SizeY)
733         {
734           HalScrollDisplay ();
735           CursorY = SizeY - 1;
736         }
737   
738       pch++;
739     }
740   
741 #ifdef SCREEN_SYNCHRONIZATION
742   offset = (CursorY * SizeX) + CursorX;
743   
744   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
745   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, offset & 0xff);
746   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
747   WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (offset >> 8) & 0xff);
748 #endif
749   KeReleaseSpinLockFromDpcLevel(&Lock);
750   popfl(Flags);
751 }
752
753 VOID STDCALL
754 HalQueryDisplayParameters(OUT PULONG DispSizeX,
755                           OUT PULONG DispSizeY,
756                           OUT PULONG CursorPosX,
757                           OUT PULONG CursorPosY)
758 {
759   if (DispSizeX)
760     *DispSizeX = SizeX;
761   if (DispSizeY)
762     *DispSizeY = SizeY;
763   if (CursorPosX)
764     *CursorPosX = CursorX;
765   if (CursorPosY)
766     *CursorPosY = CursorY;
767 }
768
769
770 VOID STDCALL
771 HalSetDisplayParameters(IN ULONG CursorPosX,
772                         IN ULONG CursorPosY)
773 {
774   CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
775   CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
776 }
777
778 BOOLEAN STDCALL
779 HalQueryDisplayOwnership()
780 {
781   return ! HalOwnsDisplay;
782 }
783
784 /* EOF */