]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/sl.subproj/display.c
BootX-59.1.1.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / display.c
CommitLineData
04fee52e
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
db839b1d 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
04fee52e 7 *
db839b1d
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
04fee52e
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
db839b1d
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
04fee52e
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
366defd1 26 * display.c - Functions to manage and find display.
04fee52e 27 *
366defd1 28 * Copyright (c) 1998-2002 Apple Computer, Inc.
04fee52e
A
29 *
30 * DRI: Josh de Cesare
31 */
32
33#include <sl.h>
34
35#include "clut.h"
366defd1
A
36#include "appleboot.h"
37#include "failedboot.h"
38#include "netboot.h"
04fee52e
A
39
40struct DisplayInfo {
41 CICell screenPH;
42 CICell screenIH;
43 CICell address;
44 CICell width;
45 CICell height;
46 CICell depth;
47 CICell linebytes;
853f9ac3 48 CICell triedToOpen;
04fee52e
A
49};
50
51typedef struct DisplayInfo DisplayInfo, *DisplayInfoPtr;
52
04fee52e
A
53
54static long FindDisplays(void);
55static long OpenDisplays(void);
04fee52e
A
56static long OpenDisplay(long displayNum);
57static long InitDisplay(long displayNum);
04fee52e
A
58static long LookUpCLUTIndex(long index, long depth);
59
60static long gNumDisplays;
61static long gMainDisplayNum;
62static DisplayInfo gDisplays[16];
63
366defd1
A
64static unsigned char *gAppleBoot;
65static unsigned char *gNetBoot;
66static unsigned char *gFailedBoot;
67
04fee52e
A
68// Public Functions
69
70long InitDisplays(void)
71{
72 FindDisplays();
73 OpenDisplays();
74
75 return 0;
76}
77
78
366defd1 79long DrawSplashScreen(long stage)
04fee52e
A
80{
81 DisplayInfoPtr display;
366defd1
A
82 short *appleBoot16, *netBoot16;
83 long *appleBoot32, *netBoot32;
04fee52e
A
84 long cnt, x, y, pixelSize;
85
86 if (gMainDisplayNum == -1) return 0;
87
88 display = &gDisplays[gMainDisplayNum];
89
366defd1
A
90 switch (stage) {
91 case 0 :
92 // Make sure the boot display is marked.
93 SetProp(display->screenPH, "AAPL,boot-display", NULL, 0);
04fee52e
A
94
95 switch (display->depth) {
96 case 16 :
366defd1
A
97 appleBoot16 =
98 AllocateBootXMemory(kAppleBootWidth * kAppleBootHeight * 2);
99 for (cnt = 0; cnt < (kAppleBootWidth * kAppleBootHeight); cnt++)
100 appleBoot16[cnt] = LookUpCLUTIndex(gAppleBootPict[cnt], 16);
101 gAppleBoot = (char *)appleBoot16;
04fee52e
A
102 break;
103
104 case 32 :
366defd1
A
105 appleBoot32 =
106 AllocateBootXMemory(kAppleBootWidth * kAppleBootHeight * 4);
107 for (cnt = 0; cnt < (kAppleBootWidth * kAppleBootHeight); cnt++)
108 appleBoot32[cnt] = LookUpCLUTIndex(gAppleBootPict[cnt], 32);
109 gAppleBoot = (char *)appleBoot32;
04fee52e
A
110 break;
111
112 default :
366defd1 113 gAppleBoot = (unsigned char *)gAppleBootPict;
04fee52e
A
114 break;
115 }
116
366defd1
A
117 x = (display->width - kAppleBootWidth) / 2;
118 y = (display->height - kAppleBootHeight) / 2 + kAppleBootOffset;
119
120 CallMethod(5, 0, display->screenIH, "draw-rectangle", (long)gAppleBoot,
121 x, y, kAppleBootWidth, kAppleBootHeight);
122
123 if (gBootFileType != kNetworkDeviceType) {
124 SpinInit(0, 0, NULL, 0, 0, 0, 0, 0, 0, 0);
125 } else {
126 switch (display->depth) {
127 case 16 :
128 pixelSize = 2;
129 netBoot16 =
130 AllocateBootXMemory(kNetBootWidth * kNetBootHeight * kNetBootFrames * 2);
131 for (cnt = 0; cnt < (kNetBootWidth * kNetBootHeight * kNetBootFrames); cnt++)
132 netBoot16[cnt] = LookUpCLUTIndex(gNetBootPict[cnt], 16);
133 gNetBoot = (char *)netBoot16;
134 break;
135
136 case 32 :
137 pixelSize = 4;
138 netBoot32 =
139 AllocateBootXMemory(kNetBootWidth * kNetBootHeight * kNetBootFrames * 4);
140 for (cnt = 0; cnt < (kNetBootWidth * kNetBootHeight * kNetBootFrames); cnt++)
141 netBoot32[cnt] = LookUpCLUTIndex(gNetBootPict[cnt], 32);
142 gNetBoot = (char *)netBoot32;
143 break;
144
145 default :
146 pixelSize = 1;
147 gNetBoot = (unsigned char *)gNetBootPict;
148 break;
149 }
04fee52e 150
366defd1
A
151 x = (display->width - kNetBootWidth) / 2;
152 y = (display->height - kNetBootHeight) / 2 + kNetBootOffset;
04fee52e 153
366defd1
A
154 CallMethod(5, 0, display->screenIH, "draw-rectangle", (long)gNetBoot,
155 x, y, kNetBootWidth, kNetBootHeight);
04fee52e 156
366defd1
A
157 // Set up the spin cursor.
158 SpinInit(display->screenIH, gNetBoot,
159 x, y,
160 kNetBootWidth, kNetBootHeight,
161 kNetBootFrames, kNetBootFPS, pixelSize, 0);
162 }
163 break;
164
165 case 1 :
166 x = (display->width - kAppleBootWidth) / 2;
167 y = (display->height - kAppleBootHeight) / 2 + kAppleBootOffset;
168
169 CallMethod(5, 0, display->screenIH, "draw-rectangle", (long)gAppleBoot,
170 x, y, kAppleBootWidth, kAppleBootHeight);
171
172 if (gBootFileType == kNetworkDeviceType) {
173 x = (display->width - kNetBootWidth) / 2;
174 y = (display->height - kNetBootHeight) / 2 + kNetBootOffset;
04fee52e 175
366defd1
A
176 // Erase the netboot picture with 75% grey.
177 CallMethod(5, 0, display->screenIH, "fill-rectangle",
178 LookUpCLUTIndex(0x01, display->depth),
179 x, y, kNetBootWidth, kNetBootHeight);
04fee52e 180 }
366defd1 181 break;
04fee52e 182
366defd1
A
183 default :
184 return -1;
185 break;
04fee52e 186 }
04fee52e
A
187
188 return 0;
189}
190
191
366defd1 192long DrawFailedBootPicture(void)
04fee52e
A
193{
194 long cnt;
366defd1
A
195 short *failedBoot16;
196 long *failedBoot32, posX, posY;
04fee52e
A
197 DisplayInfoPtr display = &gDisplays[gMainDisplayNum];
198
04fee52e
A
199 switch (display->depth) {
200 case 16 :
366defd1 201 failedBoot16 = AllocateBootXMemory(32 * 32 * 2);
04fee52e 202 for (cnt = 0; cnt < (32 * 32); cnt++)
366defd1
A
203 failedBoot16[cnt] = LookUpCLUTIndex(gFailedBootPict[cnt], 16);
204 gFailedBoot = (char *)failedBoot16;
04fee52e
A
205 break;
206
207 case 32 :
366defd1 208 failedBoot32 = AllocateBootXMemory(32 * 32 * 4);
04fee52e 209 for (cnt = 0; cnt < (32 * 32); cnt++)
366defd1
A
210 failedBoot32[cnt] = LookUpCLUTIndex(gFailedBootPict[cnt], 32);
211 gFailedBoot = (char *)failedBoot32;
04fee52e
A
212 break;
213
214 default :
366defd1 215 gFailedBoot = (unsigned char *)gFailedBootPict;
04fee52e
A
216 break;
217 }
218
366defd1
A
219 // Erase the newboot picture with 75% grey.
220 posX = (display->width - kNetBootWidth) / 2;
221 posY = (display->height - kNetBootHeight) / 2 + kNetBootOffset;
222 CallMethod(5, 0, display->screenIH, "fill-rectangle",
223 LookUpCLUTIndex(0x01, display->depth),
224 posX, posY, kNetBootWidth, kNetBootHeight);
225
226 // Draw the failed boot picture.
227 posX = (display->width - kFailedBootWidth) / 2;
228 posY = ((display->height - kFailedBootHeight)) / 2 + kFailedBootOffset;
229 CallMethod(5, 0, display->screenIH, "draw-rectangle",
230 (long)gFailedBoot, posX, posY,
231 kFailedBootWidth, kFailedBootHeight);
04fee52e
A
232
233 return 0;
234}
235
236
237void GetMainScreenPH(Boot_Video_Ptr video)
238{
239 DisplayInfoPtr display;
366defd1 240 long address, size;
04fee52e
A
241
242 if (gMainDisplayNum == -1) {
243 // No display, set it to zero.
244 video->v_baseAddr = 0;
245 video->v_rowBytes = 0;
246 video->v_width = 0;
247 video->v_height = 0;
248 video->v_depth = 0;
249 } else {
250 display = &gDisplays[gMainDisplayNum];
251
252 video->v_baseAddr = display->address;
253 video->v_rowBytes = display->linebytes;
254 video->v_width = display->width;
255 video->v_height = display->height;
256 video->v_depth = display->depth;
257 }
366defd1
A
258
259 // Allocate memory and a range for the CLUT.
260 size = 256 * 3;
261 address = AllocateKernelMemory(size);
262 AllocateMemoryRange("BootCLUT", address, size);
263 bcopy((char *)gClut, (char *)address, size);
264
265 // Allocate memory and a range for the failed boot picture.
266 size = 32 + kFailedBootWidth * kFailedBootHeight;
267 address = AllocateKernelMemory(size);
268 AllocateMemoryRange("Pict-FailedBoot", address, size);
269 ((long *)address)[0] = kFailedBootWidth;
270 ((long *)address)[1] = kFailedBootHeight;
271 ((long *)address)[2] = kFailedBootOffset;
272 bcopy((char *)gFailedBootPict, (char *)(address + 32), size - 32);
04fee52e
A
273}
274
366defd1 275
04fee52e
A
276// Private Functions
277
278static long FindDisplays(void)
279{
280 CICell screenPH, controlPH;
281 long cnt;
282
283 // Find all the screens in the system.
284 screenPH = 0;
285 while (1) {
286 screenPH = SearchForNode(screenPH, 1, "device_type", "display");
287 if (screenPH != 0) gDisplays[gNumDisplays++].screenPH = screenPH;
288 else break;
289 }
290
291 // Find /chaos/control, and
292 // invalidate gStdOutPH if equal (since new OF was downloaded).
293 controlPH = FindDevice("/chaos/control");
294 if (gStdOutPH == controlPH) gStdOutPH = 0;
295
296 // Find the main screen using the screen alias or chaos/control.
297 gMainDisplayNum = -1;
298 screenPH = FindDevice("screen");
299 if (screenPH == -1) screenPH = controlPH;
300 for (cnt = 0; cnt < gNumDisplays; cnt++)
301 if (gDisplays[cnt].screenPH == screenPH) gMainDisplayNum = cnt;
302
303 return 0;
304}
305
306
307static long OpenDisplays(void)
308{
309 long cnt;
310
311 // Open the main screen or
312 // look for a main screen if we don't have one.
313 if ((gMainDisplayNum == -1) || !OpenDisplay(gMainDisplayNum)) {
314 gMainDisplayNum = -1;
315 for (cnt = 0; cnt < gNumDisplays; cnt++) {
316 if (OpenDisplay(cnt)) {
317 gMainDisplayNum = cnt;
318 break;
319 }
320 }
321 }
322
853f9ac3
A
323 // Open the rest of the displays
324 if (gOFVersion >= kOFVersion3x) {
325 for (cnt = 0; cnt < gNumDisplays; cnt++) {
326 OpenDisplay(cnt);
327 }
328 }
329
04fee52e
A
330 return 0;
331}
332
04fee52e
A
333
334static long OpenDisplay(long displayNum)
335{
366defd1
A
336 char screenPath[258], displayType[32];
337 CICell screenPH, screenIH;
338 long ret, size;
04fee52e 339
853f9ac3
A
340 // Only try to open a screen once.
341 if (gDisplays[displayNum].triedToOpen) {
342 return gDisplays[displayNum].screenIH != 0;
343 } else {
344 gDisplays[displayNum].triedToOpen = -1;
345 }
346
366defd1
A
347 screenPH = gDisplays[displayNum].screenPH;
348
04fee52e 349 // Try to use mac-boot's ihandle.
366defd1
A
350 Interpret(0, 1, "\" _screen-ihandle\" $find if execute else 0 then",
351 &screenIH);
352 if ((screenIH != 0) && (InstanceToPackage(screenIH) != screenPH)) {
853f9ac3
A
353 screenIH = 0;
354 }
04fee52e
A
355
356 // Try to use stdout as the screen's ihandle
366defd1 357 if ((screenIH == 0) && (gStdOutPH == screenPH)) {
853f9ac3
A
358 screenIH = gStdOutIH;
359 }
04fee52e
A
360
361 // Try to open the display.
362 if (screenIH == 0) {
363 screenPath[255] = '\0';
366defd1 364 ret = PackageToPath(screenPH, screenPath, 255);
04fee52e 365 if (ret != -1) {
853f9ac3 366 strcat(screenPath, ":0");
04fee52e
A
367 screenIH = Open(screenPath);
368 }
369 }
370
366defd1
A
371 // Find out what type of display is attached.
372 size = GetProp(screenPH, "display-type", displayType, 31);
373 if (size != -1) {
374 displayType[size] = '\0';
375 // If the display-type is NONE, don't use the display.
376 if (!strcmp(displayType, "NONE")) screenIH = 0;
377 }
378
04fee52e
A
379 // Save the ihandle for later use.
380 gDisplays[displayNum].screenIH = screenIH;
381
382 // Initialize the display.
383 if (screenIH != 0) InitDisplay(displayNum);
384
385 return screenIH != 0;
386}
387
388
389static long InitDisplay(long displayNum)
390{
391 DisplayInfoPtr display = &gDisplays[displayNum];
392 CICell screenPH = display->screenPH;
393 CICell screenIH = display->screenIH;
394
395 // Get the vital info for this screen.
396 GetProp(screenPH, "address", (char *)&(display->address), 4);
397 GetProp(screenPH, "width", (char *)&(display->width), 4);
398 GetProp(screenPH, "height", (char *)&(display->height), 4);
399 GetProp(screenPH, "depth", (char *)&(display->depth), 4);
400 GetProp(screenPH, "linebytes", (char *)&(display->linebytes), 4);
401
402 // Replace some of the drivers words.
366defd1 403 Interpret(3, 1,
04fee52e 404 " value depthbytes"
366defd1
A
405 " value rowbytes"
406 " to active-package"
853f9ac3 407 " frame-buffer-adr value this-frame-buffer-adr"
04fee52e
A
408
409 " : rect-setup" // ( adr|index x y w h -- w adr|index xy-adr h )
853f9ac3 410 " >r >r rowbytes * swap depthbytes * + this-frame-buffer-adr +"
04fee52e
A
411 " r> depthbytes * -rot r>"
412 " ;"
413
414 " : DRAW-RECTANGLE" // ( adr x y w h -- )
415 " rect-setup" // ( w adr xy-adr h )
416 " 0 ?do" // ( w adr xy-adr )
417 " 2dup 4 pick move"
418 " 2 pick rowbytes d+"
419 " loop"
420 " 3drop"
421 " ;"
422
423 " : FILL-RECTANGLE" // ( index x y w h -- )
424 " rect-setup rot depthbytes case"
425 " 1 of dup 8 << or dup 10 << or endof"
426 " 2 of dup 10 << or endof"
427 " endcase -rot 0 ?do"
428 " dup 3 pick 3 pick filll"
429 " rowbytes +"
430 " loop"
431 " 3drop"
432 " ;"
433
434 " : READ-RECTANGLE" // ( adr x y w h -- )
435 " rect-setup >r swap r> 0 ?do"
436 " 2dup 4 pick move"
437 " rowbytes 3 pick d+"
438 " loop"
439 " 3drop"
440 " ;"
441
853f9ac3 442 " this-frame-buffer-adr"
04fee52e
A
443 " 0 to active-package"
444 , display->screenPH, display->linebytes,
445 display->depth / 8, &display->address);
446
366defd1 447 // Set the CLUT for 8 bit displays.
04fee52e 448 if (display->depth == 8) {
366defd1 449 CallMethod(3, 0, screenIH, "set-colors", (long)gClut, 0, 256);
04fee52e
A
450 }
451
366defd1
A
452 // Set the screen to 75% grey.
453 CallMethod(5, 0, screenIH, "fill-rectangle",
454 LookUpCLUTIndex(0x01, display->depth),
455 0, 0, display->width, display->height);
04fee52e
A
456
457 return 0;
458}
459
460
461static long LookUpCLUTIndex(long index, long depth)
462{
463 long result, red, green, blue;
464
465 red = gClut[index * 3 + 0];
466 green = gClut[index * 3 + 1];
467 blue = gClut[index * 3 + 2];
468
469 switch (depth) {
470 case 16 :
471 result = ((red & 0xF8) << 7)|((green & 0xF8) << 2)|((blue & 0xF8) >> 3);
472 break;
473
474 case 32 :
475 result = (red << 16) | (green << 8) | blue;
476 break;
477
478 default :
479 result = index;
480 break;
481 }
482
483 return result;
484}
853f9ac3 485
366defd1 486
853f9ac3 487#if 0
366defd1
A
488static void DumpDisplaysInfo(void);
489
490static void DumpDisplaysInfo(void)
853f9ac3 491{
366defd1
A
492 long cnt, length;
493 char tmpStr[512];
853f9ac3 494
366defd1
A
495 printf("gNumDisplays: %x, gMainDisplayNum: %x\n",
496 gNumDisplays, gMainDisplayNum);
497
498 for (cnt = 0; cnt < gNumDisplays; cnt++) {
499 printf("Display: %x, screenPH: %x, screenIH: %x\n",
500 cnt, gDisplays[cnt].screenPH, gDisplays[cnt].screenIH);
853f9ac3 501
366defd1
A
502 if (gDisplays[cnt].screenPH) {
503 length = PackageToPath(gDisplays[cnt].screenPH, tmpStr, 511);
504 tmpStr[length] = '\0';
505 printf("PHandle Path: %s\n", tmpStr);
506 }
853f9ac3 507
366defd1
A
508 if (gDisplays[cnt].screenIH) {
509 length = InstanceToPath(gDisplays[cnt].screenIH, tmpStr, 511);
510 tmpStr[length] = '\0';
511 printf("IHandle Path: %s\n", tmpStr);
512 }
853f9ac3 513
366defd1
A
514 printf("address = %x\n", gDisplays[cnt].address);
515 printf("linebytes = %x\n", gDisplays[cnt].linebytes);
516 printf("width = %x\n", gDisplays[cnt].width);
517 printf("height = %x\n", gDisplays[cnt].height);
518 printf("depth = %x\n", gDisplays[cnt].depth);
519 printf("\n");
853f9ac3 520 }
853f9ac3
A
521}
522#endif