2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * display.c - Functions to manage and find displays.
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
34 #include "bad_system.h"
39 #include "happy_mac.h"
40 #include "happy_foot.h"
54 typedef struct DisplayInfo DisplayInfo
, *DisplayInfoPtr
;
56 // The Driver Description
58 kInitialDriverDescriptor
= 0,
59 kVersionOneDriverDescriptor
= 1,
60 kTheDescriptionSignature
= 'mtej',
61 kDriverDescriptionSignature
= 'pdes'
65 unsigned char nameInfoStr
[32]; // Driver Name/Info String
66 unsigned long version
; // Driver Version Number - really NumVersion
68 typedef struct DriverType DriverType
;
70 struct DriverDescription
{
71 unsigned long driverDescSignature
; // Signature field of this structure
72 unsigned long driverDescVersion
; // Version of this data structure
73 DriverType driverType
; // Type of Driver
76 typedef struct DriverDescription DriverDescription
;
78 #define kNumNetDrivers (7)
80 char *gNetDriverFileNames
[kNumNetDrivers
] = {
90 char *gNetDriverMatchNames
[kNumNetDrivers
] = {
100 static long FindDisplays(void);
101 static long OpenDisplays(void);
102 static void DumpDisplaysInfo(void);
103 static long OpenDisplay(long displayNum
);
104 static long InitDisplay(long displayNum
);
105 static long NetLoadDrivers(void);
106 static long LoadDisplayDriver(char *fileSpec
);
107 static long LookUpCLUTIndex(long index
, long depth
);
110 static long DiskLoadDrivers(void);
113 static long gNumDisplays
;
114 static long gMainDisplayNum
;
115 static DisplayInfo gDisplays
[16];
119 long InitDisplays(void)
128 long LoadDisplayDrivers(void)
132 // Don't bother if there are no displays.
133 if (gNumDisplays
== 0) return 0;
135 ret
= NetLoadDrivers();
138 switch (gBootFileType
) {
139 case kNetworkDeviceType
:
140 ret
= NetLoadDrivers();
143 case kBlockDeviceType
:
144 ret
= DiskLoadDrivers();
147 case kUnknownDeviceType
:
156 long DrawSplashScreen(void)
158 DisplayInfoPtr display
;
159 unsigned char *happyMac
, *happyFoot
;
160 short *happyMac16
, *happyFoot16
;
161 long *happyMac32
, *happyFoot32
;
162 long cnt
, x
, y
, pixelSize
;
164 if (gMainDisplayNum
== -1) return 0;
166 display
= &gDisplays
[gMainDisplayNum
];
168 // Make sure the boot display is marked.
169 SetProp(display
->screenPH
, "AAPL,boot-display", NULL
, 0);
172 x
= (display
->width
- BIG_WIDTH
) / 2;
173 y
= ((display
->height
- BIG_HEIGHT
)) / 2 + BIG_DY
;
175 CallMethod_5_0(display
->screenIH
, "draw-rectangle", (long)bigImage
,
176 x
, y
, BIG_WIDTH
, BIG_HEIGHT
);
178 x
= (display
->width
- SPIN_WIDTH
) / 2;
179 y
= ((display
->height
- SPIN_WIDTH
) / 2) + 28;
181 // Set up the spin cursor.
182 SpinInit(0, display
->screenIH
, waitCursors
,
183 x
, y
, SPIN_WIDTH
, SPIN_WIDTH
);
185 // Do a spin to start things off.
190 switch (display
->depth
) {
192 happyMac16
= malloc(kHappyMacWidth
* kHappyMacHeight
* 2);
193 for (cnt
= 0; cnt
< (kHappyMacWidth
* kHappyMacHeight
); cnt
++)
194 happyMac16
[cnt
] = LookUpCLUTIndex(gHappyMacIcon
[cnt
], 16);
195 happyMac
= (char *)happyMac16
;
199 happyMac32
= malloc(kHappyMacWidth
* kHappyMacHeight
* 4);
200 for (cnt
= 0; cnt
< (kHappyMacWidth
* kHappyMacHeight
); cnt
++)
201 happyMac32
[cnt
] = LookUpCLUTIndex(gHappyMacIcon
[cnt
], 32);
202 happyMac
= (char *)happyMac32
;
206 happyMac
= gHappyMacIcon
;
210 x
= (display
->width
- kHappyMacWidth
) / 2;
211 y
= (display
->height
- kHappyMacHeight
) / 2;
213 CallMethod_5_0(display
->screenIH
, "draw-rectangle", (long)happyMac
,
214 x
, y
, kHappyMacWidth
, kHappyMacHeight
);
216 if (gBootFileType
!= kNetworkDeviceType
) {
217 SpinInit(0, 0, NULL
, 0, 0, 0, 0, 0);
219 Interpret_1_0("ms", 1000);
221 switch (display
->depth
) {
224 happyFoot16
= malloc(kHappyFootWidth
* kHappyFootHeight
* 2);
225 for (cnt
= 0; cnt
< (kHappyFootWidth
* kHappyFootHeight
); cnt
++)
226 happyFoot16
[cnt
] = LookUpCLUTIndex(gHappyFootPict
[cnt
], 16);
227 happyFoot
= (char *)happyFoot16
;
232 happyFoot32
= malloc(kHappyFootWidth
* kHappyFootHeight
* 4);
233 for (cnt
= 0; cnt
< (kHappyFootWidth
* kHappyFootHeight
); cnt
++)
234 happyFoot32
[cnt
] = LookUpCLUTIndex(gHappyFootPict
[cnt
], 32);
235 happyFoot
= (char *)happyFoot32
;
240 happyFoot
= gHappyFootPict
;
244 for (cnt
= 0; cnt
< kHappyFootHeight
- 1; cnt
++) {
246 CallMethod_5_0(display
->screenIH
, "draw-rectangle", (long)happyMac
,
247 x
, y
- cnt
, kHappyMacWidth
, kHappyMacHeight
);
249 CallMethod_5_0(display
->screenIH
, "draw-rectangle",
250 (long)happyFoot
+ pixelSize
*
251 kHappyFootWidth
* (kHappyFootHeight
- cnt
- 1),
252 x
+ 6, y
+ kHappyMacHeight
- 1 - cnt
,
253 kHappyFootWidth
, cnt
+ 1);
255 CallMethod_5_0(display
->screenIH
, "draw-rectangle",
256 (long)happyFoot
+ pixelSize
*
257 kHappyFootWidth
* (kHappyFootHeight
- cnt
- 1),
258 x
+ 15, y
+ kHappyMacHeight
- 1 - cnt
,
259 kHappyFootWidth
, cnt
+ 1);
261 Interpret_1_0("ms", 75);
264 // Set up the spin cursor.
265 SpinInit(1, display
->screenIH
, happyFoot
,
266 x
+ 15, y
+ kHappyMacHeight
- kHappyFootHeight
+ 1,
267 kHappyFootWidth
, kHappyFootHeight
, pixelSize
);
275 long DrawBrokenSystemFolder(void)
278 unsigned char *iconPtr
, tmpIcon
[1024];
281 DisplayInfoPtr display
= &gDisplays
[gMainDisplayNum
];
286 // Set the screen to Medium Blue
287 CallMethod_5_0(display
->screenIH
, "fill-rectangle", 128, 0, 0,
288 display
->width
, display
->height
);
290 // Use the default icon.
291 iconPtr
= gBrokenSystemFolderIcon
;
293 // Set the screen to Medium Grey
294 CallMethod_5_0(display
->screenIH
, "fill-rectangle",
295 LookUpCLUTIndex(0xF9, display
->depth
),
296 0, 0, display
->width
, display
->height
);
298 // Convert the default icon.
299 for (cnt
= 0; cnt
< 1024; cnt
++) {
300 tmpIcon
[cnt
] = gBrokenSystemFolderIcon
[cnt
];
301 if (tmpIcon
[cnt
] == 0x80) tmpIcon
[cnt
] = 0xF9;
306 switch (display
->depth
) {
308 icon16
= malloc(32 * 32 * 2);
309 for (cnt
= 0; cnt
< (32 * 32); cnt
++)
310 icon16
[cnt
] = LookUpCLUTIndex(iconPtr
[cnt
], 16);
311 iconPtr
= (char *)icon16
;
315 icon32
= malloc(32 * 32 * 4);
316 for (cnt
= 0; cnt
< (32 * 32); cnt
++)
317 icon32
[cnt
] = LookUpCLUTIndex(iconPtr
[cnt
], 32);
318 iconPtr
= (char *)icon32
;
325 // Draw the broken system folder.
326 x
= (display
->width
- 32) / 2;
327 y
= ((display
->height
- 32)) / 2;
328 CallMethod_5_0(display
->screenIH
, "draw-rectangle",
329 (long)iconPtr
, x
, y
, 32, 32);
335 void GetMainScreenPH(Boot_Video_Ptr video
)
337 DisplayInfoPtr display
;
339 if (gMainDisplayNum
== -1) {
340 // No display, set it to zero.
341 video
->v_baseAddr
= 0;
342 video
->v_rowBytes
= 0;
347 display
= &gDisplays
[gMainDisplayNum
];
349 video
->v_baseAddr
= display
->address
;
350 video
->v_rowBytes
= display
->linebytes
;
351 video
->v_width
= display
->width
;
352 video
->v_height
= display
->height
;
353 video
->v_depth
= display
->depth
;
359 static long FindDisplays(void)
361 CICell screenPH
, controlPH
;
364 // Find all the screens in the system.
367 screenPH
= SearchForNode(screenPH
, 1, "device_type", "display");
368 if (screenPH
!= 0) gDisplays
[gNumDisplays
++].screenPH
= screenPH
;
372 // Find /chaos/control, and
373 // invalidate gStdOutPH if equal (since new OF was downloaded).
374 controlPH
= FindDevice("/chaos/control");
375 if (gStdOutPH
== controlPH
) gStdOutPH
= 0;
377 // Find the main screen using the screen alias or chaos/control.
378 gMainDisplayNum
= -1;
379 screenPH
= FindDevice("screen");
380 if (screenPH
== -1) screenPH
= controlPH
;
381 for (cnt
= 0; cnt
< gNumDisplays
; cnt
++)
382 if (gDisplays
[cnt
].screenPH
== screenPH
) gMainDisplayNum
= cnt
;
388 static long OpenDisplays(void)
392 // Open the main screen or
393 // look for a main screen if we don't have one.
394 if ((gMainDisplayNum
== -1) || !OpenDisplay(gMainDisplayNum
)) {
395 gMainDisplayNum
= -1;
396 for (cnt
= 0; cnt
< gNumDisplays
; cnt
++) {
397 if (OpenDisplay(cnt
)) {
398 gMainDisplayNum
= cnt
;
404 // Open the rest of the displays
405 if (gOFVersion
>= kOFVersion3x
) {
406 for (cnt
= 0; cnt
< gNumDisplays
; cnt
++) {
414 static void DumpDisplaysInfo(void)
419 printf("gNumDisplays: %x, gMainDisplayNum: %x\n",
420 gNumDisplays
, gMainDisplayNum
);
422 for (cnt
= 0; cnt
< gNumDisplays
; cnt
++) {
423 printf("Display: %x, screenPH: %x, screenIH: %x\n",
424 cnt
, gDisplays
[cnt
].screenPH
, gDisplays
[cnt
].screenIH
);
426 if (gDisplays
[cnt
].screenPH
) {
427 length
= PackageToPath(gDisplays
[cnt
].screenPH
, tmpStr
, 511);
428 tmpStr
[length
] = '\0';
429 printf("PHandle Path: %s\n", tmpStr
);
432 if (gDisplays
[cnt
].screenIH
) {
433 length
= InstanceToPath(gDisplays
[cnt
].screenIH
, tmpStr
, 511);
434 tmpStr
[length
] = '\0';
435 printf("IHandle Path: %s\n", tmpStr
);
438 printf("address = %x\n", gDisplays
[cnt
].address
);
439 printf("linebytes = %x\n", gDisplays
[cnt
].linebytes
);
440 printf("width = %x\n", gDisplays
[cnt
].width
);
441 printf("height = %x\n", gDisplays
[cnt
].height
);
442 printf("depth = %x\n", gDisplays
[cnt
].depth
);
448 static long OpenDisplay(long displayNum
)
450 char screenPath
[258];
454 // Only try to open a screen once.
455 if (gDisplays
[displayNum
].triedToOpen
) {
456 return gDisplays
[displayNum
].screenIH
!= 0;
458 gDisplays
[displayNum
].triedToOpen
= -1;
461 // Try to use mac-boot's ihandle.
462 Interpret_0_1("\" _screen-ihandle\" $find if execute else 0 then",
464 if ((screenIH
!= 0) &&
465 (InstanceToPackage(screenIH
) != gDisplays
[displayNum
].screenPH
)) {
469 // Try to use stdout as the screen's ihandle
470 if ((screenIH
== 0) && (gStdOutPH
== gDisplays
[displayNum
].screenPH
)) {
471 screenIH
= gStdOutIH
;
474 // Try to open the display.
476 screenPath
[255] = '\0';
477 ret
= PackageToPath(gDisplays
[displayNum
].screenPH
, screenPath
, 255);
479 strcat(screenPath
, ":0");
480 screenIH
= Open(screenPath
);
484 // Save the ihandle for later use.
485 gDisplays
[displayNum
].screenIH
= screenIH
;
487 // Initialize the display.
488 if (screenIH
!= 0) InitDisplay(displayNum
);
490 return screenIH
!= 0;
494 static long InitDisplay(long displayNum
)
496 DisplayInfoPtr display
= &gDisplays
[displayNum
];
497 CICell screenPH
= display
->screenPH
;
498 CICell screenIH
= display
->screenIH
;
500 // Get the vital info for this screen.
501 GetProp(screenPH
, "address", (char *)&(display
->address
), 4);
502 GetProp(screenPH
, "width", (char *)&(display
->width
), 4);
503 GetProp(screenPH
, "height", (char *)&(display
->height
), 4);
504 GetProp(screenPH
, "depth", (char *)&(display
->depth
), 4);
505 GetProp(screenPH
, "linebytes", (char *)&(display
->linebytes
), 4);
507 // Replace some of the drivers words.
512 " frame-buffer-adr value this-frame-buffer-adr"
514 " : rect-setup" // ( adr|index x y w h -- w adr|index xy-adr h )
515 " >r >r rowbytes * swap depthbytes * + this-frame-buffer-adr +"
516 " r> depthbytes * -rot r>"
519 " : DRAW-RECTANGLE" // ( adr x y w h -- )
520 " rect-setup" // ( w adr xy-adr h )
521 " 0 ?do" // ( w adr xy-adr )
523 " 2 pick rowbytes d+"
528 " : FILL-RECTANGLE" // ( index x y w h -- )
529 " rect-setup rot depthbytes case"
530 " 1 of dup 8 << or dup 10 << or endof"
531 " 2 of dup 10 << or endof"
532 " endcase -rot 0 ?do"
533 " dup 3 pick 3 pick filll"
539 " : READ-RECTANGLE" // ( adr x y w h -- )
540 " rect-setup >r swap r> 0 ?do"
542 " rowbytes 3 pick d+"
547 " this-frame-buffer-adr"
548 " 0 to active-package"
549 , display
->screenPH
, display
->linebytes
,
550 display
->depth
/ 8, &display
->address
);
552 // Set the CLUT for 8 bit displays
553 if (display
->depth
== 8) {
554 CallMethod_3_0(screenIH
, "set-colors", (long)gClut
, 0, 256);
558 // Set the screen to Medium Blue
559 CallMethod_5_0(screenIH
, "fill-rectangle", 128, 0, 0,
560 display
->width
, display
->height
);
562 // Set the screen to Medium Grey
563 CallMethod_5_0(screenIH
, "fill-rectangle",
564 LookUpCLUTIndex(0xF9, display
->depth
),
565 0, 0, display
->width
, display
->height
);
572 static long NetLoadDrivers(void)
574 long ret
, cnt
, curDisplay
;
578 for (cnt
= 0; cnt
< kNumNetDrivers
; cnt
++) {
580 // See if there is a display for this driver.
581 for (curDisplay
= 0; curDisplay
< gNumDisplays
; curDisplay
++) {
582 screenPH
= gDisplays
[curDisplay
].screenPH
;
583 if (MatchThis(screenPH
, gNetDriverMatchNames
[cnt
]) == 0) break;
586 if (curDisplay
== gNumDisplays
) continue;
588 sprintf(fileSpec
, "%s%sDrivers\\ppc\\IONDRV.config\\%s",
590 (gBootFileType
== kNetworkDeviceType
) ? "" : "private\\",
591 gNetDriverFileNames
[cnt
]);
593 ret
= LoadDisplayDriver(fileSpec
);
599 static long LoadDisplayDriver(char *fileSpec
)
601 char *pef
, *currentPef
, *buffer
;
602 long pefLen
, currentPefLen
, ndrvUsed
;
604 char descripName
[] = " TheDriverDescription";
606 DriverDescription descrip
;
607 DriverDescription curDesc
;
609 unsigned long newVersion
;
610 unsigned long curVersion
;
613 pefLen
= LoadFile(fileSpec
);
614 if (pefLen
== -1) return -1;
615 if (pefLen
== 0) return 0;
617 pef
= (char *)kLoadAddr
;
619 descripName
[0] = strlen(descripName
+ 1);
620 err
= GetSymbolFromPEF(descripName
, pef
, &descrip
, sizeof(descrip
));
622 printf("\nGetSymbolFromPEF returns %d\n",err
);
625 if((descrip
.driverDescSignature
!= kTheDescriptionSignature
) ||
626 (descrip
.driverDescVersion
!= kInitialDriverDescriptor
))
629 strncpy(matchName
, descrip
.driverType
.nameInfoStr
+ 1,
630 descrip
.driverType
.nameInfoStr
[0]);
631 newVersion
= descrip
.driverType
.version
;
633 if((newVersion
& 0xffff) == 0x8000) // final stage, release rev
637 buffer
= (char *)malloc(pefLen
);
638 if (buffer
== NULL
) {
639 printf("No space for the NDRV\n");
642 bcopy(pef
, buffer
, pefLen
);
644 for (curDisplay
= 0; curDisplay
< gNumDisplays
; curDisplay
++) {
645 screenPH
= gDisplays
[curDisplay
].screenPH
;
647 if (MatchThis(screenPH
, matchName
) != 0) continue;
649 err
= GetPackageProperty(screenPH
, "driver,AAPL,MacOS,PowerPC",
650 ¤tPef
, ¤tPefLen
);
653 err
= GetSymbolFromPEF(descripName
,currentPef
,&curDesc
,sizeof(curDesc
));
655 if((curDesc
.driverDescSignature
== kTheDescriptionSignature
) &&
656 (curDesc
.driverDescVersion
== kInitialDriverDescriptor
)) {
657 curVersion
= curDesc
.driverType
.version
;
658 if((curVersion
& 0xffff) == 0x8000) // final stage, release rev
661 if( newVersion
<= curVersion
)
667 if(pefLen
== 0) continue;
669 printf("Installing patch driver\n");
671 SetProp(screenPH
, "driver,AAPL,MacOS,PowerPC", buffer
, pefLen
);
675 if (ndrvUsed
== 0) free(buffer
);
681 static long LookUpCLUTIndex(long index
, long depth
)
683 long result
, red
, green
, blue
;
685 red
= gClut
[index
* 3 + 0];
686 green
= gClut
[index
* 3 + 1];
687 blue
= gClut
[index
* 3 + 2];
691 result
= ((red
& 0xF8) << 7)|((green
& 0xF8) << 2)|((blue
& 0xF8) >> 3);
695 result
= (red
<< 16) | (green
<< 8) | blue
;
707 static long DiskLoadDrivers(void)
709 long ret
, flags
, index
, time
;
710 char dirSpec
[512], *name
;
714 sprintf(dirSpec
, "%sprivate\\Drivers\\ppc\\IONDRV.config\\", gRootDir
);
716 ret
= GetDirEntry(dirSpec
, &index
, &name
, &flags
, &time
);
717 if (ret
== -1) break;
719 if (flags
!= kFlatFileType
) continue;
721 strcat(dirSpec
, name
);
722 ret
= LoadDisplayDriver(dirSpec
);
724 if (ret
== -1) return -1;