:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 #include <ddk/ntddk.h>
31 #include <mps.h>
32
33 #define SCREEN_SYNCHRONIZATION
34
35
36 #define CRTC_COMMAND       0x3d4
37 #define CRTC_DATA          0x3d5
38
39 #define CRTC_COLUMNS       0x01
40 #define CRTC_OVERFLOW      0x07
41 #define CRTC_ROWS          0x12
42 #define CRTC_SCANLINES     0x09
43
44 #define CRTC_CURHI         0x0e
45 #define CRTC_CURLO         0x0f
46
47
48 #define CHAR_ATTRIBUTE     0x17  /* grey on blue */
49
50
51 /* VARIABLES ****************************************************************/
52
53 static ULONG CursorX = 0;      /* Cursor Position */
54 static ULONG CursorY = 0;
55 static ULONG SizeX = 80;       /* Display size */
56 static ULONG SizeY = 25;
57
58 static BOOLEAN DisplayInitialized = FALSE;
59 static BOOLEAN HalOwnsDisplay = TRUE;
60
61 static WORD *VideoBuffer = NULL;
62
63 static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
64
65
66 /* STATIC FUNCTIONS *********************************************************/
67
68 static VOID
69 HalClearDisplay (VOID)
70 {
71    WORD *ptr = (WORD*)VideoBuffer;
72    ULONG i;
73
74   for (i = 0; i < SizeX * SizeY; i++, ptr++)
75     *ptr = ((CHAR_ATTRIBUTE << 8) + ' ');
76
77   CursorX = 0;
78   CursorY = 0;
79 }
80
81
82 VOID
83 HalScrollDisplay (VOID)
84 {
85   WORD *ptr;
86   int i;
87
88   ptr = VideoBuffer + SizeX;
89   RtlMoveMemory(VideoBuffer,
90                 ptr,
91                 SizeX * (SizeY - 1) * 2);
92
93   ptr = VideoBuffer  + (SizeX * (SizeY - 1));
94   for (i = 0; i < SizeX; i++, ptr++)
95     {
96       *ptr = (CHAR_ATTRIBUTE << 8) + ' ';
97     }
98 }
99
100
101 static VOID
102 HalPutCharacter (CHAR Character)
103 {
104   WORD *ptr;
105
106   ptr = VideoBuffer + ((CursorY * SizeX) + CursorX);
107   *ptr = (CHAR_ATTRIBUTE << 8) + Character;
108 }
109
110
111 /* PRIVATE FUNCTIONS ********************************************************/
112
113 VOID
114 HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock)
115 /*
116  * FUNCTION: Initalize the display
117  * ARGUMENTS:
118  *         InitParameters = Parameters setup by the boot loader
119  */
120 {
121   if (DisplayInitialized == FALSE)
122     {
123       ULONG ScanLines;
124       ULONG Data;
125
126       VideoBuffer = (WORD *)(0xd0000000 + 0xb8000);
127 //      VideoBuffer = HalMapPhysicalMemory (0xb8000, 2);
128
129       /* Set cursor position */
130 //      CursorX = LoaderBlock->cursorx;
131 //      CursorY = LoaderBlock->cursory;
132       CursorX = 0;
133       CursorY = 0;
134
135       /* read screen size from the crtc */
136       /* FIXME: screen size should be read from the boot parameters */
137       WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_COLUMNS);
138       SizeX = READ_PORT_UCHAR((PUCHAR)CRTC_DATA) + 1;
139       WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_ROWS);
140       SizeY = READ_PORT_UCHAR((PUCHAR)CRTC_DATA);
141       WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_OVERFLOW);
142       Data = READ_PORT_UCHAR((PUCHAR)CRTC_DATA);
143       SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3));
144       SizeY++;
145       WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_SCANLINES);
146       ScanLines = (READ_PORT_UCHAR((PUCHAR)CRTC_DATA) & 0x1F) + 1;
147       SizeY = SizeY / ScanLines;
148
149 #ifdef BOCHS_30ROWS
150       SizeY=30;
151 #endif
152       HalClearDisplay();
153
154       DisplayInitialized = TRUE;
155     }
156 }
157
158
159 VOID
160 HalResetDisplay(VOID)
161 /*
162  * FUNCTION: Reset the display
163  * ARGUMENTS:
164  *         None
165  */
166 {
167   if (HalResetDisplayParameters == NULL)
168     return;
169
170   if (HalOwnsDisplay == TRUE)
171     return;
172
173   if (HalResetDisplayParameters(SizeX, SizeY) == TRUE)
174     {
175       HalOwnsDisplay = TRUE;
176       HalClearDisplay();
177     }
178 }
179
180
181 /* PUBLIC FUNCTIONS *********************************************************/
182
183 VOID STDCALL
184 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
185 /*
186  * FUNCTION: 
187  * ARGUMENTS:
188  *         ResetDisplayParameters = Pointer to a driver specific
189  *         reset routine.
190  */
191 {
192   HalOwnsDisplay = FALSE;
193   HalResetDisplayParameters = ResetDisplayParameters;
194 }
195
196
197 VOID STDCALL
198 HalDisplayString(IN PCH String)
199 /*
200  * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
201  * already and displays a string
202  * ARGUMENT:
203  *        string = ASCII string to display
204  * NOTE: Use with care because there is no support for returning from BSOD
205  * mode
206  */
207 {
208   PCH pch;
209 #ifdef SCREEN_SYNCHRONIZATION
210   int offset;
211 #endif
212   static KSPIN_LOCK Lock;
213   ULONG Flags;
214
215   pch = String;
216
217   pushfl(Flags);
218   __asm__ ("cli\n\t");
219   KeAcquireSpinLockAtDpcLevel(&Lock);
220   
221   if (HalOwnsDisplay == FALSE)
222     {
223       HalResetDisplay ();
224     }
225   
226 #ifdef SCREEN_SYNCHRONIZATION
227   WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
228   offset = READ_PORT_UCHAR((PUCHAR)CRTC_DATA)<<8;
229   WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
230   offset += READ_PORT_UCHAR((PUCHAR)CRTC_DATA);
231   
232   CursorY = offset / SizeX;
233   CursorX = offset % SizeX;
234 #endif
235   
236   while (*pch != 0)
237     {
238       if (*pch == '\n')
239         {
240           CursorY++;
241           CursorX = 0;
242         }
243       else if (*pch != '\r')
244         {
245           HalPutCharacter (*pch);
246           CursorX++;
247           
248           if (CursorX >= SizeX)
249             {
250               CursorY++;
251               CursorX = 0;
252             }
253         }
254   
255       if (CursorY >= SizeY)
256         {
257           HalScrollDisplay ();
258           CursorY = SizeY - 1;
259         }
260   
261       pch++;
262     }
263   
264 #ifdef SCREEN_SYNCHRONIZATION
265   offset = (CursorY * SizeX) + CursorX;
266   
267   WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO);
268   WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, offset & 0xff);
269   WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI);
270   WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, (offset >> 8) & 0xff);
271 #endif
272   KeReleaseSpinLockFromDpcLevel(&Lock);
273   popfl(Flags);
274 }
275
276
277 VOID STDCALL
278 HalQueryDisplayParameters(OUT PULONG DispSizeX,
279                           OUT PULONG DispSizeY,
280                           OUT PULONG CursorPosX,
281                           OUT PULONG CursorPosY)
282 {
283   if (DispSizeX)
284     *DispSizeX = SizeX;
285   if (DispSizeY)
286     *DispSizeY = SizeY;
287   if (CursorPosX)
288     *CursorPosX = CursorX;
289   if (CursorPosY)
290     *CursorPosY = CursorY;
291 }
292
293
294 VOID STDCALL
295 HalSetDisplayParameters(IN ULONG CursorPosX,
296                         IN ULONG CursorPosY)
297 {
298   CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
299   CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
300 }
301
302 /* EOF */