]> git.saurik.com Git - apple/xnu.git/blob - pexpert/i386/pe_init.c
a483e72f6ee4349a8bc865c4ad84097aec217a3e
[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/debug.h>
34
35 #include "fakePPCStructs.h"
36 #include "fakePPCDeviceTree.h"
37
38 /* extern references */
39 extern void pe_identify_machine(void * args);
40 extern void initialize_screen(void *, unsigned int);
41
42 /* Local references */
43 static vm_offset_t mapframebuffer(caddr_t,int);
44 static vm_offset_t PE_fb_vaddr = 0;
45 static int PE_fb_mode = TEXT_MODE;
46
47 /* private globals */
48 PE_state_t PE_state;
49
50 /* Clock Frequency Info */
51 clock_frequency_info_t gPEClockFrequencyInfo;
52
53 int PE_initialize_console( PE_Video * info, int op )
54 {
55 static int last_console = -1;
56 Boot_Video bootInfo;
57 Boot_Video * bInfo;
58
59 /*
60 * Refuse changes from outside pexpert.
61 * The video mode setup by the booter cannot be changed.
62 */
63 if ( info && (info == &PE_state.video) )
64 {
65 bootInfo.v_baseAddr = PE_fb_vaddr;
66 bootInfo.v_rowBytes = info->v_rowBytes;
67 bootInfo.v_width = info->v_width;
68 bootInfo.v_height = info->v_height;
69 bootInfo.v_depth = info->v_depth;
70 bootInfo.v_display = PE_fb_mode;
71 bInfo = &bootInfo;
72 }
73 else
74 bInfo = 0;
75
76 switch ( op ) {
77
78 case kPEDisableScreen:
79 initialize_screen((void *) bInfo, op);
80 #ifdef FIXME
81 last_console = switch_to_serial_console();
82 #endif
83 kprintf("kPEDisableScreen %d\n", last_console);
84 break;
85
86 case kPEEnableScreen:
87 initialize_screen((void *) bInfo, op);
88 kprintf("kPEEnableScreen %d\n", last_console);
89 #ifdef FIXME
90 if( last_console != -1)
91 switch_to_old_console( last_console);
92 #endif
93 break;
94
95 default:
96 initialize_screen((void *) bInfo, op);
97 break;
98 }
99
100 return 0;
101 }
102
103 void PE_init_iokit(void)
104 {
105 long * dt;
106 void * desc;
107 unsigned char * data;
108 unsigned char * clut;
109
110 dt = (long *) createdt(
111 fakePPCDeviceTree,
112 &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength);
113
114 /* Setup powermac_info and powermac_machine_info structures */
115
116 ((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeP = (unsigned long *) dt;
117 ((boot_args*)PE_state.fakePPCBootArgs)->topOfKernelData = (unsigned int) kalloc(0x2000);
118
119 /*
120 * Setup the OpenFirmware Device Tree routines
121 * so the console can be found and the right I/O space
122 * can be used..
123 */
124 DTInit(dt);
125
126 /*
127 * Initialize the spinning wheel (progress indicator).
128 */
129 clut = appleClut8;
130 desc = &default_progress;
131 data = default_progress_data;
132
133 vc_progress_initialize( desc, data, clut );
134
135 PE_initialize_console( (PE_Video *) 0, kPEAcquireScreen );
136
137 (void) StartIOKit( (void*)dt, (void*)PE_state.fakePPCBootArgs, 0, 0);
138 }
139
140 void PE_init_platform(boolean_t vm_initialized, void * args)
141 {
142 if (PE_state.initialized == FALSE)
143 {
144 extern unsigned int halt_in_debugger, disableDebugOuput;
145 unsigned int debug_arg;
146
147 PE_state.initialized = TRUE;
148 PE_state.bootArgs = args;
149 PE_state.video.v_baseAddr = ((KERNBOOTSTRUCT *)args)->video.v_baseAddr;
150 PE_state.video.v_rowBytes = ((KERNBOOTSTRUCT *)args)->video.v_rowBytes;
151 PE_state.video.v_height = ((KERNBOOTSTRUCT *)args)->video.v_height;
152 PE_state.video.v_width = ((KERNBOOTSTRUCT *)args)->video.v_width;
153 PE_state.video.v_depth = ((KERNBOOTSTRUCT *)args)->video.v_depth;
154 PE_state.video.v_display = ((KERNBOOTSTRUCT *)args)->video.v_display;
155 PE_fb_mode = ((KERNBOOTSTRUCT *)args)->graphicsMode;
156 PE_state.fakePPCBootArgs = (boot_args *)&fakePPCBootArgs;
157 ((boot_args *)PE_state.fakePPCBootArgs)->machineType = 386;
158
159 if (PE_fb_mode == TEXT_MODE)
160 {
161 /* Force a text display if the booter did not setup a
162 * VESA frame buffer.
163 */
164 PE_state.video.v_display = 0;
165 }
166
167 /*
168 * If DB_HALT flag is set, then cause a breakpoint to the debugger
169 * immediately after the kernel debugger has been initialized.
170 *
171 * If DB_PRT flag is set, then enable debugger printf.
172 */
173 disableDebugOuput = TRUE; /* FIXME: override osfmk/i386/AT386/model_dep.c */
174
175 if (PE_parse_boot_arg("debug", &debug_arg)) {
176 if (debug_arg & DB_HALT) halt_in_debugger = 1;
177 if (debug_arg & DB_PRT) disableDebugOuput = FALSE;
178 }
179 }
180
181 if (!vm_initialized)
182 {
183 /* Hack! FIXME.. */
184 outb(0x21, 0xff); /* Maskout all interrupts Pic1 */
185 outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */
186
187 pe_identify_machine(args);
188 }
189 else
190 {
191 pe_init_debug();
192
193 PE_create_console();
194 }
195 }
196
197 void PE_create_console( void )
198 {
199 if ( (PE_fb_vaddr == 0) && (PE_state.video.v_baseAddr != 0) )
200 {
201 PE_fb_vaddr = mapframebuffer((caddr_t) PE_state.video.v_baseAddr,
202 (PE_fb_mode == TEXT_MODE) ?
203 /* text mode */ PE_state.video.v_rowBytes :
204 /* grfx mode */ PE_state.video.v_rowBytes *
205 PE_state.video.v_height);
206 }
207
208 if (PE_state.video.v_display)
209 PE_initialize_console( &PE_state.video, kPEGraphicsMode );
210 else
211 PE_initialize_console( &PE_state.video, kPETextMode );
212 }
213
214 int PE_current_console( PE_Video * info )
215 {
216 *info = PE_state.video;
217
218 if ( PE_fb_mode == TEXT_MODE )
219 {
220 /*
221 * FIXME: Prevent the IOBootFrameBuffer from starting up
222 * when we are in Text mode.
223 */
224 info->v_baseAddr = 0;
225 }
226
227 return (0);
228 }
229
230 void PE_display_icon( unsigned int flags,
231 const char * name )
232 {
233 }
234
235 extern boolean_t PE_get_hotkey( unsigned char key )
236 {
237 return (FALSE);
238 }
239
240 static timebase_callback_func gTimebaseCallback;
241
242 void PE_register_timebase_callback(timebase_callback_func callback)
243 {
244 gTimebaseCallback = callback;
245
246 PE_call_timebase_callback();
247 }
248
249 void PE_call_timebase_callback(void)
250 {
251 struct timebase_freq_t timebase_freq;
252 unsigned long num, den, cnt;
253
254 num = gPEClockFrequencyInfo.bus_clock_rate_num * gPEClockFrequencyInfo.bus_to_dec_rate_num;
255 den = gPEClockFrequencyInfo.bus_clock_rate_den * gPEClockFrequencyInfo.bus_to_dec_rate_den;
256
257 cnt = 2;
258 while (cnt <= den) {
259 if ((num % cnt) || (den % cnt)) {
260 cnt++;
261 continue;
262 }
263
264 num /= cnt;
265 den /= cnt;
266 }
267
268 timebase_freq.timebase_num = num;
269 timebase_freq.timebase_den = den;
270
271 if (gTimebaseCallback) gTimebaseCallback(&timebase_freq);
272 }
273
274 /*
275 * map the framebuffer into kernel vm and return the (virtual)
276 * address.
277 */
278 static vm_offset_t
279 mapframebuffer( caddr_t physaddr, /* start of framebuffer */
280 int length) /* num bytes to map */
281 {
282 vm_offset_t vmaddr;
283
284 if (physaddr != (caddr_t)trunc_page(physaddr))
285 panic("Framebuffer not on page boundary");
286
287 vmaddr = io_map((vm_offset_t)physaddr, length);
288 if (vmaddr == 0)
289 panic("can't alloc VM for framebuffer");
290
291 return vmaddr;
292 }