9d82553bdc3f31699624cb4307aecf7e01e080ee
[reactos.git] / reactos / hal / halppc / 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* $Id: display.c 23907 2006-09-04 05:52:23Z arty $
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
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 #include <ppcboot.h>
126 #include <ppcdebug.h>
127
128 #define NDEBUG
129 #include <debug.h>
130
131 boot_infos_t PpcEarlybootInfo;
132
133 #define SCREEN_SYNCHRONIZATION
134
135 /* VARIABLES ****************************************************************/
136
137 static ULONG CursorX = 0; /* Cursor Position */
138 static ULONG CursorY = 0;
139 static ULONG SizeX = 80; /* Display size */
140 static ULONG SizeY = 25;
141
142 static BOOLEAN DisplayInitialized = FALSE;
143 static BOOLEAN HalOwnsDisplay = TRUE;
144 static ULONG GraphVideoBuffer = 0;
145 static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
146
147 extern UCHAR XboxFont8x16[];
148 extern void SetPhys( ULONG Addr, ULONG Data );
149 extern ULONG GetPhys( ULONG Addr );
150 extern void SetPhysByte( ULONG Addr, ULONG Data );
151
152 /* PRIVATE FUNCTIONS *********************************************************/
153
154 VOID FASTCALL
155 HalClearDisplay (UCHAR CharAttribute)
156 {
157 ULONG i;
158 ULONG deviceSize =
159 PpcEarlybootInfo.dispDeviceRowBytes *
160 PpcEarlybootInfo.dispDeviceRect[3];
161 for(i = 0; i < deviceSize; i += sizeof(int) )
162 SetPhys(GraphVideoBuffer + i, CharAttribute);
163
164 CursorX = 0;
165 CursorY = 0;
166 }
167
168
169 /* STATIC FUNCTIONS *********************************************************/
170
171 VOID STATIC
172 HalScrollDisplay (VOID)
173 {
174 ULONG i, deviceSize =
175 PpcEarlybootInfo.dispDeviceRowBytes *
176 PpcEarlybootInfo.dispDeviceRect[3];
177 ULONG Dest = (ULONG)GraphVideoBuffer,
178 Src = (ULONG)(GraphVideoBuffer + (16 * PpcEarlybootInfo.dispDeviceRowBytes));
179 ULONG End = (ULONG)
180 GraphVideoBuffer +
181 (PpcEarlybootInfo.dispDeviceRowBytes *
182 (PpcEarlybootInfo.dispDeviceRect[3]-16));
183
184 while( Src < End )
185 {
186 SetPhys((ULONG)Dest, GetPhys(Src));
187 Src += 4; Dest += 4;
188 }
189
190 /* Clear the bottom row */
191 for(i = End; i < deviceSize; i += sizeof(int) )
192 SetPhys(GraphVideoBuffer + i, 1);
193 }
194
195 VOID STATIC FASTCALL
196 HalPutCharacter (CHAR Character)
197 {
198 WRITE_PORT_UCHAR((PVOID)0x3f8, Character);
199 #if 0
200 int i,j,k;
201 ULONG Dest =
202 (GraphVideoBuffer +
203 (16 * PpcEarlybootInfo.dispDeviceRowBytes * CursorY) +
204 (8 * (PpcEarlybootInfo.dispDeviceDepth / 8) * CursorX)), RowDest;
205 UCHAR ByteToPlace;
206
207 for( i = 0; i < 16; i++ ) {
208 RowDest = Dest;
209 for( j = 0; j < 8; j++ ) {
210 ByteToPlace = ((128 >> j) & (XboxFont8x16[(16 * Character) + i])) ? 0xff : 1;
211 for( k = 0; k < PpcEarlybootInfo.dispDeviceDepth / 8; k++, RowDest++ ) {
212 SetPhysByte(RowDest, ByteToPlace);
213 }
214 }
215 Dest += PpcEarlybootInfo.dispDeviceRowBytes;
216 }
217 #endif
218 }
219
220 /* PRIVATE FUNCTIONS ********************************************************/
221
222 VOID FASTCALL
223 HalInitializeDisplay (PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
224 /*
225 * FUNCTION: Initalize the display
226 * ARGUMENTS:
227 * InitParameters = Parameters setup by the boot loader
228 */
229 {
230 if (! DisplayInitialized)
231 {
232 boot_infos_t *XBootInfo = (boot_infos_t *)LoaderBlock->ArchExtra;
233 GraphVideoBuffer = (ULONG)XBootInfo->dispDeviceBase;
234 memcpy(&PpcEarlybootInfo, XBootInfo, sizeof(*XBootInfo));
235
236 /* Set cursor position */
237 CursorX = 0;
238 CursorY = 0;
239
240 SizeX = XBootInfo->dispDeviceRowBytes / XBootInfo->dispDeviceDepth;
241 SizeY = XBootInfo->dispDeviceRect[3] / 16;
242
243 HalClearDisplay(1);
244
245 DisplayInitialized = TRUE;
246 }
247 }
248
249
250 /* PUBLIC FUNCTIONS *********************************************************/
251
252 VOID NTAPI
253 HalReleaseDisplayOwnership(VOID)
254 /*
255 * FUNCTION: Release ownership of display back to HAL
256 */
257 {
258 if (HalResetDisplayParameters == NULL)
259 return;
260
261 if (HalOwnsDisplay == TRUE)
262 return;
263
264 HalOwnsDisplay = TRUE;
265 HalClearDisplay(0);
266 }
267
268
269 VOID NTAPI
270 HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
271 /*
272 * FUNCTION:
273 * ARGUMENTS:
274 * ResetDisplayParameters = Pointer to a driver specific
275 * reset routine.
276 */
277 {
278 HalOwnsDisplay = FALSE;
279 HalResetDisplayParameters = ResetDisplayParameters;
280 }
281
282 VOID NTAPI
283 HalDisplayString(IN PCH String)
284 /*
285 * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
286 * already and displays a string
287 * ARGUMENT:
288 * string = ASCII string to display
289 * NOTE: Use with care because there is no support for returning from BSOD
290 * mode
291 */
292 {
293 PCH pch;
294 //static KSPIN_LOCK Lock;
295 KIRQL OldIrql;
296 BOOLEAN InterruptsEnabled = __readmsr();
297
298 /* See comment at top of file */
299 if (! HalOwnsDisplay || ! DisplayInitialized)
300 {
301 return;
302 }
303
304 pch = String;
305
306 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
307 //KiAcquireSpinLock(&Lock);
308
309 _disable();
310
311 while (*pch != 0)
312 {
313 if (*pch == '\n')
314 {
315 CursorY++;
316 CursorX = 0;
317 }
318 else if (*pch == '\b')
319 {
320 if (CursorX > 0)
321 {
322 CursorX--;
323 }
324 }
325 else if (*pch != '\r')
326 {
327 HalPutCharacter (*pch);
328 CursorX++;
329
330 if (CursorX >= SizeX)
331 {
332 CursorY++;
333 CursorX = 0;
334 }
335 }
336
337 if (CursorY >= SizeY)
338 {
339 HalScrollDisplay ();
340 CursorY = SizeY - 1;
341 }
342
343 pch++;
344 }
345
346 __writemsr(InterruptsEnabled);
347
348 //KiReleaseSpinLock(&Lock);
349 KeLowerIrql(OldIrql);
350 }
351
352 VOID NTAPI
353 HalQueryDisplayParameters(OUT PULONG DispSizeX,
354 OUT PULONG DispSizeY,
355 OUT PULONG CursorPosX,
356 OUT PULONG CursorPosY)
357 {
358 if (DispSizeX)
359 *DispSizeX = SizeX;
360 if (DispSizeY)
361 *DispSizeY = SizeY;
362 if (CursorPosX)
363 *CursorPosX = CursorX;
364 if (CursorPosY)
365 *CursorPosY = CursorY;
366 }
367
368
369 VOID NTAPI
370 HalSetDisplayParameters(IN ULONG CursorPosX,
371 IN ULONG CursorPosY)
372 {
373 CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
374 CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
375 }
376
377
378 BOOLEAN NTAPI
379 HalQueryDisplayOwnership(VOID)
380 {
381 return !HalOwnsDisplay;
382 }
383
384 /* EOF */