]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/sl.subproj/display.c
BootX-34.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 *
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.
11 *
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * display.c - Functions to manage and find displays.
24 *
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30#include <sl.h>
31
32#include "clut.h"
33
34#include "bad_system.h"
35
36#if kMacOSXServer
37#include "images.h"
38#else
39#include "happy_mac.h"
40#include "happy_foot.h"
41#endif
42
43struct DisplayInfo {
44 CICell screenPH;
45 CICell screenIH;
46 CICell address;
47 CICell width;
48 CICell height;
49 CICell depth;
50 CICell linebytes;
51};
52
53typedef struct DisplayInfo DisplayInfo, *DisplayInfoPtr;
54
55// The Driver Description
56enum {
57 kInitialDriverDescriptor = 0,
58 kVersionOneDriverDescriptor = 1,
59 kTheDescriptionSignature = 'mtej',
60 kDriverDescriptionSignature = 'pdes'
61};
62
63struct DriverType {
64 unsigned char nameInfoStr[32]; // Driver Name/Info String
65 unsigned long version; // Driver Version Number - really NumVersion
66};
67typedef struct DriverType DriverType;
68
69struct DriverDescription {
70 unsigned long driverDescSignature; // Signature field of this structure
71 unsigned long driverDescVersion; // Version of this data structure
72 DriverType driverType; // Type of Driver
73 char otherStuff[512];
74};
75typedef struct DriverDescription DriverDescription;
76
77#define kNumNetDrivers (7)
78
79char *gNetDriverFileNames[kNumNetDrivers] = {
80 "ATYRagePro_ndrv",
81 "Spinnaker_ndrv",
82 "ATYLT-G_ndrv",
83 "ATYLTPro_ndrv",
84 "chips65550_ndrv",
85 "control_ndrv",
86 "ATYRage_ndrv"
87};
88
89char *gNetDriverMatchNames[kNumNetDrivers] = {
90 "ATY,mach64_3DUPro",
91 "ATY,mach64",
92 "ATY,264LT-G",
93 "ATY,RageLTPro",
94 "chips65550",
95 "control",
96 "ATY,mach64_3DU"
97};
98
99static long FindDisplays(void);
100static long OpenDisplays(void);
101static void DumpDisplaysInfo(void);
102static long OpenDisplay(long displayNum);
103static long InitDisplay(long displayNum);
104static long NetLoadDrivers(void);
105static long DiskLoadDrivers(void);
106static long LoadDisplayDriver(char *fileSpec);
107static long LookUpCLUTIndex(long index, long depth);
108
109static long gNumDisplays;
110static long gMainDisplayNum;
111static DisplayInfo gDisplays[16];
112
113// Public Functions
114
115long InitDisplays(void)
116{
117 FindDisplays();
118 OpenDisplays();
119
120 return 0;
121}
122
123
124long LoadDisplayDrivers(void)
125{
126 long ret;
127
128 // Don't bother if there are no displays.
129 if (gNumDisplays == 0) return 0;
130
131 ret = NetLoadDrivers();
132
133#if 0
134 switch (gBootFileType) {
135 case kNetworkDeviceType :
136 ret = NetLoadDrivers();
137 break;
138
139 case kBlockDeviceType :
140 ret = DiskLoadDrivers();
141 break;
142
143 case kUnknownDeviceType :
144 ret = 0;
145 }
146#endif
147
148 return ret;
149}
150
151
152long DrawSplashScreen(void)
153{
154 DisplayInfoPtr display;
155 unsigned char *happyMac, *happyFoot;
156 short *happyMac16, *happyFoot16;
157 long *happyMac32, *happyFoot32;
158 long cnt, x, y, pixelSize;
159
160 if (gMainDisplayNum == -1) return 0;
161
162 display = &gDisplays[gMainDisplayNum];
163
164 // Make sure the boot display is marked.
165 SetProp(display->screenPH, "AAPL,boot-display", NULL, 0);
166
167#if kMacOSXServer
168 x = (display->width - BIG_WIDTH) / 2;
169 y = ((display->height - BIG_HEIGHT)) / 2 + BIG_DY;
170
171 CallMethod_5_0(display->screenIH, "draw-rectangle", (long)bigImage,
172 x, y, BIG_WIDTH, BIG_HEIGHT);
173
174 x = (display->width - SPIN_WIDTH) / 2;
175 y = ((display->height - SPIN_WIDTH) / 2) + 28;
176
177 // Set up the spin cursor.
178 SpinInit(0, display->screenIH, waitCursors,
179 x, y, SPIN_WIDTH, SPIN_WIDTH);
180
181 // Do a spin to start things off.
182 Spin();
183
184#else
185
186 switch (display->depth) {
187 case 16 :
188 happyMac16 = malloc(kHappyMacWidth * kHappyMacHeight * 2);
189 for (cnt = 0; cnt < (kHappyMacWidth * kHappyMacHeight); cnt++)
190 happyMac16[cnt] = LookUpCLUTIndex(gHappyMacIcon[cnt], 16);
191 happyMac = (char *)happyMac16;
192 break;
193
194 case 32 :
195 happyMac32 = malloc(kHappyMacWidth * kHappyMacHeight * 4);
196 for (cnt = 0; cnt < (kHappyMacWidth * kHappyMacHeight); cnt++)
197 happyMac32[cnt] = LookUpCLUTIndex(gHappyMacIcon[cnt], 32);
198 happyMac = (char *)happyMac32;
199 break;
200
201 default :
202 happyMac = gHappyMacIcon;
203 break;
204 }
205
206 x = (display->width - kHappyMacWidth) / 2;
207 y = (display->height - kHappyMacHeight) / 2;
208
209 CallMethod_5_0(display->screenIH, "draw-rectangle", (long)happyMac,
210 x, y, kHappyMacWidth, kHappyMacHeight);
211
212 if (gBootFileType != kNetworkDeviceType) {
213 SpinInit(0, 0, NULL, 0, 0, 0, 0, 0);
214 } else {
215 Interpret_1_0("ms", 1000);
216
217 switch (display->depth) {
218 case 16 :
219 pixelSize = 2;
220 happyFoot16 = malloc(kHappyFootWidth * kHappyFootHeight * 2);
221 for (cnt = 0; cnt < (kHappyFootWidth * kHappyFootHeight); cnt++)
222 happyFoot16[cnt] = LookUpCLUTIndex(gHappyFootPict[cnt], 16);
223 happyFoot = (char *)happyFoot16;
224 break;
225
226 case 32 :
227 pixelSize = 4;
228 happyFoot32 = malloc(kHappyFootWidth * kHappyFootHeight * 4);
229 for (cnt = 0; cnt < (kHappyFootWidth * kHappyFootHeight); cnt++)
230 happyFoot32[cnt] = LookUpCLUTIndex(gHappyFootPict[cnt], 32);
231 happyFoot = (char *)happyFoot32;
232 break;
233
234 default :
235 pixelSize = 1;
236 happyFoot = gHappyFootPict;
237 break;
238 }
239
240 for (cnt = 0; cnt < kHappyFootHeight - 1; cnt++) {
241
242 CallMethod_5_0(display->screenIH, "draw-rectangle", (long)happyMac,
243 x, y - cnt, kHappyMacWidth, kHappyMacHeight);
244
245 CallMethod_5_0(display->screenIH, "draw-rectangle",
246 (long)happyFoot + pixelSize *
247 kHappyFootWidth * (kHappyFootHeight - cnt - 1),
248 x + 6, y + kHappyMacHeight - 1 - cnt,
249 kHappyFootWidth, cnt + 1);
250
251 CallMethod_5_0(display->screenIH, "draw-rectangle",
252 (long)happyFoot + pixelSize *
253 kHappyFootWidth * (kHappyFootHeight - cnt - 1),
254 x + 15, y + kHappyMacHeight - 1 - cnt,
255 kHappyFootWidth, cnt + 1);
256
257 Interpret_1_0("ms", 75);
258 }
259
260 // Set up the spin cursor.
261 SpinInit(1, display->screenIH, happyFoot,
262 x + 15, y + kHappyMacHeight - kHappyFootHeight + 1,
263 kHappyFootWidth, kHappyFootHeight, pixelSize);
264 }
265#endif
266
267 return 0;
268}
269
270
271long DrawBrokenSystemFolder(void)
272{
273 long cnt;
274 unsigned char *iconPtr, tmpIcon[1024];
275 short *icon16;
276 long *icon32;
277 DisplayInfoPtr display = &gDisplays[gMainDisplayNum];
278
279 long x, y;
280
281#if kMacOSXServer
282 // Set the screen to Medium Blue
283 CallMethod_5_0(display->screenIH, "fill-rectangle", 128, 0, 0,
284 display->width, display->height);
285
286 // Use the default icon.
287 iconPtr = gBrokenSystemFolderIcon;
288#else
289 // Set the screen to Medium Grey
290 CallMethod_5_0(display->screenIH, "fill-rectangle",
291 LookUpCLUTIndex(0xF9, display->depth),
292 0, 0, display->width, display->height);
293
294 // Convert the default icon.
295 for (cnt = 0; cnt < 1024; cnt++) {
296 tmpIcon[cnt] = gBrokenSystemFolderIcon[cnt];
297 if (tmpIcon[cnt] == 0x80) tmpIcon[cnt] = 0xF9;
298 }
299 iconPtr = tmpIcon;
300#endif
301
302 switch (display->depth) {
303 case 16 :
304 icon16 = malloc(32 * 32 * 2);
305 for (cnt = 0; cnt < (32 * 32); cnt++)
306 icon16[cnt] = LookUpCLUTIndex(iconPtr[cnt], 16);
307 iconPtr = (char *)icon16;
308 break;
309
310 case 32 :
311 icon32 = malloc(32 * 32 * 4);
312 for (cnt = 0; cnt < (32 * 32); cnt++)
313 icon32[cnt] = LookUpCLUTIndex(iconPtr[cnt], 32);
314 iconPtr = (char *)icon32;
315 break;
316
317 default :
318 break;
319 }
320
321 // Draw the broken system folder.
322 x = (display->width - 32) / 2;
323 y = ((display->height - 32)) / 2;
324 CallMethod_5_0(display->screenIH, "draw-rectangle",
325 (long)iconPtr, x, y, 32, 32);
326
327 return 0;
328}
329
330
331void GetMainScreenPH(Boot_Video_Ptr video)
332{
333 DisplayInfoPtr display;
334
335 if (gMainDisplayNum == -1) {
336 // No display, set it to zero.
337 video->v_baseAddr = 0;
338 video->v_rowBytes = 0;
339 video->v_width = 0;
340 video->v_height = 0;
341 video->v_depth = 0;
342 } else {
343 display = &gDisplays[gMainDisplayNum];
344
345 video->v_baseAddr = display->address;
346 video->v_rowBytes = display->linebytes;
347 video->v_width = display->width;
348 video->v_height = display->height;
349 video->v_depth = display->depth;
350 }
351}
352
353// Private Functions
354
355static long FindDisplays(void)
356{
357 CICell screenPH, controlPH;
358 long cnt;
359
360 // Find all the screens in the system.
361 screenPH = 0;
362 while (1) {
363 screenPH = SearchForNode(screenPH, 1, "device_type", "display");
364 if (screenPH != 0) gDisplays[gNumDisplays++].screenPH = screenPH;
365 else break;
366 }
367
368 // Find /chaos/control, and
369 // invalidate gStdOutPH if equal (since new OF was downloaded).
370 controlPH = FindDevice("/chaos/control");
371 if (gStdOutPH == controlPH) gStdOutPH = 0;
372
373 // Find the main screen using the screen alias or chaos/control.
374 gMainDisplayNum = -1;
375 screenPH = FindDevice("screen");
376 if (screenPH == -1) screenPH = controlPH;
377 for (cnt = 0; cnt < gNumDisplays; cnt++)
378 if (gDisplays[cnt].screenPH == screenPH) gMainDisplayNum = cnt;
379
380 return 0;
381}
382
383
384static long OpenDisplays(void)
385{
386 long cnt;
387
388 // Open the main screen or
389 // look for a main screen if we don't have one.
390 if ((gMainDisplayNum == -1) || !OpenDisplay(gMainDisplayNum)) {
391 gMainDisplayNum = -1;
392 for (cnt = 0; cnt < gNumDisplays; cnt++) {
393 if (OpenDisplay(cnt)) {
394 gMainDisplayNum = cnt;
395 break;
396 }
397 }
398 }
399
400 return 0;
401}
402
403static void DumpDisplaysInfo(void)
404{
405 long cnt, length;
406 char tmpStr[512];
407
408 printf("gNumDisplays: %x, gMainDisplayNum: %x\n",
409 gNumDisplays, gMainDisplayNum);
410
411 for (cnt = 0; cnt < gNumDisplays; cnt++) {
412 printf("Display: %x, screenPH: %x, screenIH: %x\n",
413 cnt, gDisplays[cnt].screenPH, gDisplays[cnt].screenIH);
414
415 if (gDisplays[cnt].screenPH) {
416 length = PackageToPath(gDisplays[cnt].screenPH, tmpStr, 511);
417 tmpStr[length] = '\0';
418 printf("PHandle Path: %s\n", tmpStr);
419 }
420
421 if (gDisplays[cnt].screenIH) {
422 length = InstanceToPath(gDisplays[cnt].screenIH, tmpStr, 511);
423 tmpStr[length] = '\0';
424 printf("IHandle Path: %s\n", tmpStr);
425 }
426
427 printf("address = %x\n", gDisplays[cnt].address);
428 printf("linebytes = %x\n", gDisplays[cnt].linebytes);
429 printf("width = %x\n", gDisplays[cnt].width);
430 printf("height = %x\n", gDisplays[cnt].height);
431 printf("depth = %x\n", gDisplays[cnt].depth);
432 printf("\n");
433 }
434}
435
436
437static long OpenDisplay(long displayNum)
438{
439 char screenPath[256];
440 CICell screenIH;
441 long ret;
442
443 // Try to use mac-boot's ihandle.
444 Interpret_0_1("\" _screen-ihandle\" $find if execute else 0 then",
445 &screenIH);
446
447 // Try to use stdout as the screen's ihandle
448 if (gStdOutPH == gDisplays[displayNum].screenPH) screenIH = gStdOutIH;
449
450 // Try to open the display.
451 if (screenIH == 0) {
452 screenPath[255] = '\0';
453 ret = PackageToPath(gDisplays[displayNum].screenPH, screenPath, 255);
454 if (ret != -1) {
455 screenIH = Open(screenPath);
456 }
457 }
458
459 // Save the ihandle for later use.
460 gDisplays[displayNum].screenIH = screenIH;
461
462 // Initialize the display.
463 if (screenIH != 0) InitDisplay(displayNum);
464
465 return screenIH != 0;
466}
467
468
469static long InitDisplay(long displayNum)
470{
471 DisplayInfoPtr display = &gDisplays[displayNum];
472 CICell screenPH = display->screenPH;
473 CICell screenIH = display->screenIH;
474
475 // Get the vital info for this screen.
476 GetProp(screenPH, "address", (char *)&(display->address), 4);
477 GetProp(screenPH, "width", (char *)&(display->width), 4);
478 GetProp(screenPH, "height", (char *)&(display->height), 4);
479 GetProp(screenPH, "depth", (char *)&(display->depth), 4);
480 GetProp(screenPH, "linebytes", (char *)&(display->linebytes), 4);
481
482 // Replace some of the drivers words.
483 Interpret_3_1(
484 " to active-package"
485 " value rowbytes"
486 " value depthbytes"
487
488 " : rect-setup" // ( adr|index x y w h -- w adr|index xy-adr h )
489 " >r >r rowbytes * swap depthbytes * + frame-buffer-adr +"
490 " r> depthbytes * -rot r>"
491 " ;"
492
493 " : DRAW-RECTANGLE" // ( adr x y w h -- )
494 " rect-setup" // ( w adr xy-adr h )
495 " 0 ?do" // ( w adr xy-adr )
496 " 2dup 4 pick move"
497 " 2 pick rowbytes d+"
498 " loop"
499 " 3drop"
500 " ;"
501
502 " : FILL-RECTANGLE" // ( index x y w h -- )
503 " rect-setup rot depthbytes case"
504 " 1 of dup 8 << or dup 10 << or endof"
505 " 2 of dup 10 << or endof"
506 " endcase -rot 0 ?do"
507 " dup 3 pick 3 pick filll"
508 " rowbytes +"
509 " loop"
510 " 3drop"
511 " ;"
512
513 " : READ-RECTANGLE" // ( adr x y w h -- )
514 " rect-setup >r swap r> 0 ?do"
515 " 2dup 4 pick move"
516 " rowbytes 3 pick d+"
517 " loop"
518 " 3drop"
519 " ;"
520
521 " frame-buffer-adr"
522 " 0 to active-package"
523 , display->screenPH, display->linebytes,
524 display->depth / 8, &display->address);
525
526 // Set the CLUT for 8 bit displays
527 if (display->depth == 8) {
528 CallMethod_3_0(screenIH, "set-colors", (long)gClut, 0, 256);
529 }
530
531#if kMacOSXServer
532 // Set the screen to Medium Blue
533 CallMethod_5_0(screenIH, "fill-rectangle", 128, 0, 0,
534 display->width, display->height);
535#else
536 // Set the screen to Medium Grey
537 CallMethod_5_0(screenIH, "fill-rectangle",
538 LookUpCLUTIndex(0xF9, display->depth),
539 0, 0, display->width, display->height);
540#endif
541
542 return 0;
543}
544
545
546static long NetLoadDrivers(void)
547{
548 long ret, cnt, curDisplay;
549 CICell screenPH;
550 char fileSpec[512];
551
552 for (cnt = 0; cnt < kNumNetDrivers; cnt++) {
553
554 // See if there is a display for this driver.
555 for (curDisplay = 0; curDisplay < gNumDisplays; curDisplay++) {
556 screenPH = gDisplays[curDisplay].screenPH;
557 if (MatchThis(screenPH, gNetDriverMatchNames[cnt]) == 0) break;
558 }
559
560 if (curDisplay == gNumDisplays) continue;
561
562 sprintf(fileSpec, "%s%sDrivers\\ppc\\IONDRV.config\\%s",
563 gRootDir,
564 (gBootFileType == kNetworkDeviceType) ? "" : "private\\",
565 gNetDriverFileNames[cnt]);
566
567 ret = LoadDisplayDriver(fileSpec);
568 }
569
570 return 0;
571}
572
573static long DiskLoadDrivers(void)
574{
575 long ret, flags, index, time;
576 char dirSpec[512], *name;
577
578 index = 0;
579 while (1) {
580 sprintf(dirSpec, "%sprivate\\Drivers\\ppc\\IONDRV.config\\", gRootDir);
581
582 ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
583 if (ret == -1) break;
584
585 if (flags != kFlatFileType) continue;
586
587 strcat(dirSpec, name);
588 ret = LoadDisplayDriver(dirSpec);
589
590 if (ret == -1) return -1;
591 }
592
593 return 0;
594}
595
596static long LoadDisplayDriver(char *fileSpec)
597{
598 char *pef, *currentPef, *buffer;
599 long pefLen, currentPefLen, ndrvUsed;
600 long curDisplay;
601 char descripName[] = " TheDriverDescription";
602 long err;
603 DriverDescription descrip;
604 DriverDescription curDesc;
605 char matchName[40];
606 unsigned long newVersion;
607 unsigned long curVersion;
608 CICell screenPH;
609
610 pefLen = LoadFile(fileSpec);
611 if (pefLen == -1) return -1;
612 if (pefLen == 0) return 0;
613
614 pef = (char *)kLoadAddr;
615
616 descripName[0] = strlen(descripName + 1);
617 err = GetSymbolFromPEF(descripName, pef, &descrip, sizeof(descrip));
618 if(err != 0) {
619 printf("\nGetSymbolFromPEF returns %d\n",err);
620 return -1;
621 }
622 if((descrip.driverDescSignature != kTheDescriptionSignature) ||
623 (descrip.driverDescVersion != kInitialDriverDescriptor))
624 return 0;
625
626 strncpy(matchName, descrip.driverType.nameInfoStr + 1,
627 descrip.driverType.nameInfoStr[0]);
628 newVersion = descrip.driverType.version;
629
630 if((newVersion & 0xffff) == 0x8000) // final stage, release rev
631 newVersion |= 0xff;
632
633 ndrvUsed = 0;
634 buffer = (char *)malloc(pefLen);
635 if (buffer == NULL) {
636 printf("No space for the NDRV\n");
637 return -1;
638 }
639 bcopy(pef, buffer, pefLen);
640
641 for (curDisplay = 0; curDisplay < gNumDisplays; curDisplay++) {
642 screenPH = gDisplays[curDisplay].screenPH;
643
644 if (MatchThis(screenPH, matchName) != 0) continue;
645
646 err = GetPackageProperty(screenPH, "driver,AAPL,MacOS,PowerPC",
647 &currentPef, &currentPefLen);
648
649 if (err == 0) {
650 err = GetSymbolFromPEF(descripName,currentPef,&curDesc,sizeof(curDesc));
651 if (err != 0) {
652 if((curDesc.driverDescSignature == kTheDescriptionSignature) &&
653 (curDesc.driverDescVersion == kInitialDriverDescriptor)) {
654 curVersion = curDesc.driverType.version;
655 if((curVersion & 0xffff) == 0x8000) // final stage, release rev
656 curVersion |= 0xff;
657
658 if( newVersion <= curVersion)
659 pefLen = 0;
660 }
661 }
662 }
663
664 if(pefLen == 0) continue;
665
666 printf("Installing patch driver\n");
667
668 SetProp(screenPH, "driver,AAPL,MacOS,PowerPC", buffer, pefLen);
669 ndrvUsed = 1;
670 }
671
672 if (ndrvUsed == 0) free(buffer);
673
674 return 0;
675}
676
677
678static long LookUpCLUTIndex(long index, long depth)
679{
680 long result, red, green, blue;
681
682 red = gClut[index * 3 + 0];
683 green = gClut[index * 3 + 1];
684 blue = gClut[index * 3 + 2];
685
686 switch (depth) {
687 case 16 :
688 result = ((red & 0xF8) << 7)|((green & 0xF8) << 2)|((blue & 0xF8) >> 3);
689 break;
690
691 case 32 :
692 result = (red << 16) | (green << 8) | blue;
693 break;
694
695 default :
696 result = index;
697 break;
698 }
699
700 return result;
701}