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