]> git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/pe_init.c
xnu-344.tar.gz
[apple/xnu.git] / pexpert / i386 / pe_init.c
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 * file: pe_init.c
24 * i386 platform expert initialization.
25 */
26 #include <sys/types.h>
27 #include <mach/vm_param.h>
28 #include <pexpert/protos.h>
29 #include <pexpert/pexpert.h>
30 #include <pexpert/boot.h>
31 #include <pexpert/device_tree.h>
32 #include <pexpert/pe_images.h>
33 #include <kern/sched_prim.h>
34
35 #include "fakePPCStructs.h"
36 #include "fakePPCDeviceTree.h"
37 #include "boot_images.h"
38
39 /* extern references */
40 extern void pe_identify_machine(void * args);
41 extern void initialize_screen(void *, unsigned int);
42
43 /* Local references */
44 static vm_offset_t mapframebuffer(caddr_t,int);
45 static vm_offset_t PE_fb_vaddr = 0;
46 static int PE_fb_mode = TEXT_MODE;
47 static KERNBOOTSTRUCT * PE_kbp = 0;
48
49 /* private globals */
50 PE_state_t PE_state;
51 dt_data gMemoryMapNode;
52 dt_data gDriversProp;
53
54 /* Clock Frequency Info */
55 clock_frequency_info_t gPEClockFrequencyInfo;
56
57 int PE_initialize_console( PE_Video * info, int op )
58 {
59 static int last_console = -1;
60 Boot_Video bootInfo;
61 Boot_Video * bInfo;
62
63 /*
64 * Refuse changes from outside pexpert.
65 * The video mode setup by the booter cannot be changed.
66 */
67 if ( info && (info == &PE_state.video) )
68 {
69 bootInfo.v_baseAddr = PE_fb_vaddr;
70 bootInfo.v_rowBytes = info->v_rowBytes;
71 bootInfo.v_width = info->v_width;
72 bootInfo.v_height = info->v_height;
73 bootInfo.v_depth = info->v_depth;
74 bootInfo.v_display = PE_fb_mode;
75 bInfo = &bootInfo;
76 }
77 else
78 bInfo = 0;
79
80 switch ( op ) {
81
82 case kPEDisableScreen:
83 initialize_screen((void *) bInfo, op);
84 #ifdef FIXME
85 last_console = switch_to_serial_console();
86 #endif
87 kprintf("kPEDisableScreen %d\n", last_console);
88 break;
89
90 case kPEEnableScreen:
91 initialize_screen((void *) bInfo, op);
92 kprintf("kPEEnableScreen %d\n", last_console);
93 #ifdef FIXME
94 if( last_console != -1)
95 switch_to_old_console( last_console);
96 #endif
97 break;
98
99 default:
100 initialize_screen((void *) bInfo, op);
101 break;
102 }
103
104 return 0;
105 }
106
107 void PE_init_iokit(void)
108 {
109 long * dt;
110 int i;
111
112 typedef struct {
113 char name[32];
114 unsigned long length;
115 unsigned long value[2];
116 } DriversPackageProp;
117
118 /*
119 * Update the fake device tree with the driver information provided by
120 * the booter.
121 */
122
123 gDriversProp.length = PE_kbp->numBootDrivers * sizeof(DriversPackageProp);
124 gMemoryMapNode.length = 2 * sizeof(long);
125
126 dt = (long *) createdt( fakePPCDeviceTree,
127 &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength );
128
129 if ( dt )
130 {
131 DriversPackageProp * prop = (DriversPackageProp *) gDriversProp.address;
132
133 /* Copy driver info in kernBootStruct to fake device tree */
134
135 for ( i = 0; i < PE_kbp->numBootDrivers; i++, prop++ )
136 {
137 switch ( PE_kbp->driverConfig[i].type )
138 {
139 case kBootDriverTypeKEXT:
140 sprintf(prop->name, "Driver-%lx", PE_kbp->driverConfig[i].address);
141 break;
142
143 case kBootDriverTypeMKEXT:
144 sprintf(prop->name, "DriversPackage-%lx", PE_kbp->driverConfig[i].address);
145 break;
146
147 default:
148 sprintf(prop->name, "DriverBogus-%lx", PE_kbp->driverConfig[i].address);
149 break;
150 }
151 prop->length = sizeof(prop->value);
152 prop->value[0] = PE_kbp->driverConfig[i].address;
153 prop->value[1] = PE_kbp->driverConfig[i].size;
154 }
155
156 *gMemoryMapNode.address = PE_kbp->numBootDrivers + 1;
157 }
158
159 /* Setup powermac_info and powermac_machine_info structures */
160
161 ((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeP = (unsigned long *) dt;
162 ((boot_args*)PE_state.fakePPCBootArgs)->topOfKernelData = (unsigned int) kalloc(0x2000);
163
164 /*
165 * Setup the OpenFirmware Device Tree routines
166 * so the console can be found and the right I/O space
167 * can be used..
168 */
169 DTInit(dt);
170
171 /*
172 * Fetch the CLUT and the noroot image.
173 */
174 bcopy( bootClut, appleClut8, sizeof(appleClut8) );
175
176 default_noroot.width = kFailedBootWidth;
177 default_noroot.height = kFailedBootHeight;
178 default_noroot.dx = 0;
179 default_noroot.dy = kFailedBootOffset;
180 default_noroot_data = failedBootPict;
181
182 /*
183 * Initialize the spinning wheel (progress indicator).
184 */
185 vc_progress_initialize( &default_progress, default_progress_data,
186 (unsigned char *) appleClut8 );
187
188 PE_initialize_console( (PE_Video *) 0, kPEAcquireScreen );
189
190 (void) StartIOKit( (void*)dt, (void*)PE_state.fakePPCBootArgs, 0, 0);
191 }
192
193 void PE_init_platform(boolean_t vm_initialized, void * args)
194 {
195 if (PE_state.initialized == FALSE)
196 {
197 PE_kbp = (KERNBOOTSTRUCT *) args;
198
199 PE_state.initialized = TRUE;
200 PE_state.bootArgs = args;
201 PE_state.video.v_baseAddr = PE_kbp->video.v_baseAddr;
202 PE_state.video.v_rowBytes = PE_kbp->video.v_rowBytes;
203 PE_state.video.v_height = PE_kbp->video.v_height;
204 PE_state.video.v_width = PE_kbp->video.v_width;
205 PE_state.video.v_depth = PE_kbp->video.v_depth;
206 PE_state.video.v_display = PE_kbp->video.v_display;
207 PE_fb_mode = PE_kbp->graphicsMode;
208 PE_state.fakePPCBootArgs = (boot_args *)&fakePPCBootArgs;
209 ((boot_args *)PE_state.fakePPCBootArgs)->machineType = 386;
210
211 if (PE_fb_mode == TEXT_MODE)
212 {
213 /* Force a text display if the booter did not setup a
214 * VESA frame buffer.
215 */
216 PE_state.video.v_display = 0;
217 }
218 }
219
220 if (!vm_initialized)
221 {
222 /* Hack! FIXME.. */
223 outb(0x21, 0xff); /* Maskout all interrupts Pic1 */
224 outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */
225
226 pe_identify_machine(args);
227 }
228 else
229 {
230 pe_init_debug();
231
232 PE_create_console();
233 }
234 }
235
236 void PE_create_console( void )
237 {
238 if ( (PE_fb_vaddr == 0) && (PE_state.video.v_baseAddr != 0) )
239 {
240 PE_fb_vaddr = mapframebuffer((caddr_t) PE_state.video.v_baseAddr,
241 (PE_fb_mode == TEXT_MODE) ?
242 /* text mode */ PE_state.video.v_rowBytes :
243 /* grfx mode */ PE_state.video.v_rowBytes *
244 PE_state.video.v_height);
245 }
246
247 if (PE_state.video.v_display)
248 PE_initialize_console( &PE_state.video, kPEGraphicsMode );
249 else
250 PE_initialize_console( &PE_state.video, kPETextMode );
251 }
252
253 int PE_current_console( PE_Video * info )
254 {
255 *info = PE_state.video;
256
257 if ( PE_fb_mode == TEXT_MODE )
258 {
259 /*
260 * FIXME: Prevent the IOBootFrameBuffer from starting up
261 * when we are in Text mode.
262 */
263 info->v_baseAddr = 0;
264
265 /*
266 * Scale the size of the text screen from characters
267 * to pixels.
268 */
269 info->v_width *= 8; // CHARWIDTH
270 info->v_height *= 16; // CHARHEIGHT
271 }
272
273 return (0);
274 }
275
276 void PE_display_icon( unsigned int flags, const char * name )
277 {
278 if ( default_noroot_data )
279 vc_display_icon( &default_noroot, default_noroot_data );
280 }
281
282 extern boolean_t PE_get_hotkey( unsigned char key )
283 {
284 return (FALSE);
285 }
286
287 static timebase_callback_func gTimebaseCallback;
288
289 void PE_register_timebase_callback(timebase_callback_func callback)
290 {
291 gTimebaseCallback = callback;
292
293 PE_call_timebase_callback();
294 }
295
296 void PE_call_timebase_callback(void)
297 {
298 struct timebase_freq_t timebase_freq;
299 unsigned long num, den, cnt;
300
301 num = gPEClockFrequencyInfo.bus_clock_rate_num * gPEClockFrequencyInfo.bus_to_dec_rate_num;
302 den = gPEClockFrequencyInfo.bus_clock_rate_den * gPEClockFrequencyInfo.bus_to_dec_rate_den;
303
304 cnt = 2;
305 while (cnt <= den) {
306 if ((num % cnt) || (den % cnt)) {
307 cnt++;
308 continue;
309 }
310
311 num /= cnt;
312 den /= cnt;
313 }
314
315 timebase_freq.timebase_num = num;
316 timebase_freq.timebase_den = den;
317
318 if (gTimebaseCallback) gTimebaseCallback(&timebase_freq);
319 }
320
321 /*
322 * map the framebuffer into kernel vm and return the (virtual)
323 * address.
324 */
325 static vm_offset_t
326 mapframebuffer( caddr_t physaddr, /* start of framebuffer */
327 int length) /* num bytes to map */
328 {
329 vm_offset_t vmaddr;
330
331 if (physaddr != (caddr_t)trunc_page(physaddr))
332 panic("Framebuffer not on page boundary");
333
334 vmaddr = io_map((vm_offset_t)physaddr, length);
335 if (vmaddr == 0)
336 panic("can't alloc VM for framebuffer");
337
338 return vmaddr;
339 }
340
341 /*
342 * The default (non-functional) PE_poll_input handler.
343 */
344 static int
345 PE_stub_poll_input(unsigned int options, char * c)
346 {
347 *c = 0xff;
348 return 1; /* 0 for success, 1 for unsupported */
349 }
350
351 /*
352 * Called by the kernel debugger to poll for keyboard input.
353 * Keyboard drivers may replace the default stub function
354 * with their polled-mode input function.
355 */
356 int (*PE_poll_input)(unsigned int options, char * c)
357 = PE_stub_poll_input;