]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.1 (the "License"). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Copyright 1993 NeXT Computer, Inc. | |
26 | * All rights reserved. | |
27 | */ | |
28 | ||
29 | #include "libsaio.h" | |
30 | #include "memory.h" | |
31 | #include "kernBootStruct.h" | |
32 | ||
33 | static biosBuf_t bb; | |
34 | unsigned char uses_ebios[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | |
35 | ||
36 | int bgetc(void) | |
37 | { | |
38 | bb.intno = 0x16; | |
39 | bb.eax.r.h = 0x00; | |
40 | bios(&bb); | |
41 | return bb.eax.rr; | |
42 | } | |
43 | ||
44 | int readKeyboardStatus(void) | |
45 | { | |
46 | bb.intno = 0x16; | |
47 | bb.eax.r.h = 0x01; | |
48 | bios(&bb); | |
49 | if (bb.flags.zf) { | |
50 | return 0; | |
51 | } else { | |
52 | return bb.eax.rr; | |
53 | } | |
54 | } | |
55 | ||
56 | int readKeyboardShiftFlags(void) | |
57 | { | |
58 | bb.intno = 0x16; | |
59 | bb.eax.r.h = 0x02; | |
60 | bios(&bb); | |
61 | return bb.eax.r.l; | |
62 | } | |
63 | ||
64 | unsigned int time18(void) | |
65 | { | |
66 | union { | |
67 | struct { | |
68 | unsigned int low:16; | |
69 | unsigned int high:16; | |
70 | } s; | |
71 | unsigned int i; | |
72 | } time; | |
73 | ||
74 | bb.intno = 0x1a; | |
75 | bb.eax.r.h = 0x00; | |
76 | bios(&bb); | |
77 | time.s.low = bb.edx.rr; | |
78 | time.s.high = bb.ecx.rr; | |
79 | return time.i; | |
80 | } | |
81 | ||
82 | int memsize(int which) | |
83 | { | |
84 | if (which) { | |
85 | get_memsize(&bb); | |
86 | return (bb.edx.rr << 16) | bb.eax.rr; | |
87 | } | |
88 | else { | |
89 | /* conventional memory */ | |
90 | bb.intno = 0x12; | |
91 | bios(&bb); | |
92 | return bb.eax.rr; | |
93 | } | |
94 | } | |
95 | ||
96 | void video_mode(int mode) | |
97 | { | |
98 | bb.intno = 0x10; | |
99 | bb.eax.r.h = 0x00; | |
100 | bb.eax.r.l = mode; | |
101 | bios(&bb); | |
102 | } | |
103 | ||
104 | int biosread(int dev, int cyl, int head, int sec, int num) | |
105 | { | |
106 | int i; | |
107 | ||
108 | bb.intno = 0x13; | |
109 | sec += 1; /* sector numbers start at 1 */ | |
110 | ||
111 | for (i=0;;) { | |
112 | bb.ecx.r.h = cyl; | |
113 | bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F); | |
114 | bb.edx.r.h = head; | |
115 | bb.edx.r.l = dev; | |
116 | bb.eax.r.l = num; | |
117 | bb.ebx.rr = ptov(BIOS_ADDR); | |
118 | bb.es = ((unsigned long)&i & 0xffff0000) >> 4; | |
119 | ||
120 | bb.eax.r.h = 0x02; | |
121 | bios(&bb); | |
122 | ||
123 | if ((bb.eax.r.h == 0x00) || (i++ >= 5)) | |
124 | break; | |
125 | ||
126 | /* reset disk subsystem and try again */ | |
127 | bb.eax.r.h = 0x00; | |
128 | bios(&bb); | |
129 | } | |
130 | return bb.eax.r.h; | |
131 | } | |
132 | ||
133 | int ebiosread(int dev, long sec, int count) | |
134 | { | |
135 | int i; | |
136 | struct { | |
137 | unsigned char size; | |
138 | unsigned char reserved; | |
139 | unsigned char numblocks; | |
140 | unsigned char reserved2; | |
141 | unsigned int buffer; | |
142 | unsigned long long startblock; | |
143 | } addrpacket = {0}; | |
144 | addrpacket.size = sizeof(addrpacket); | |
145 | ||
146 | for (i=0;;) { | |
147 | bb.intno = 0x13; | |
148 | bb.eax.r.h = 0x42; | |
149 | bb.edx.r.l = dev; | |
150 | bb.esi.rr = ((unsigned)&addrpacket & 0xffff); | |
151 | addrpacket.numblocks = count; | |
152 | addrpacket.buffer = ptov(BIOS_ADDR); | |
153 | addrpacket.startblock = sec; | |
154 | bios(&bb); | |
155 | if ((bb.eax.r.h == 0x00) || (i++ >= 5)) | |
156 | break; | |
157 | ||
158 | /* reset disk subsystem and try again */ | |
159 | bb.eax.r.h = 0x00; | |
160 | bios(&bb); | |
161 | } | |
162 | return bb.eax.r.h; | |
163 | } | |
164 | ||
165 | void putc(int ch) | |
166 | { | |
167 | bb.intno = 0x10; | |
168 | bb.ebx.r.h = 0x00; /* background black */ | |
169 | bb.ebx.r.l = 0x0F; /* foreground white */ | |
170 | bb.eax.r.h = 0x0e; | |
171 | bb.eax.r.l = ch; | |
172 | bios(&bb); | |
173 | } | |
174 | ||
175 | unsigned int get_diskinfo(int drive) | |
176 | { | |
177 | struct { | |
178 | unsigned short size; | |
179 | unsigned short flags; | |
180 | unsigned long cylinders; | |
181 | unsigned long heads; | |
182 | unsigned long sectors; | |
183 | unsigned long long total_sectors; | |
184 | unsigned short bps; | |
185 | unsigned long params_p; | |
186 | } ebios = {0}; | |
187 | unsigned char useEbios = 0; | |
188 | ||
189 | union { | |
190 | compact_diskinfo_t di; | |
191 | unsigned int ui; | |
192 | } ret; | |
193 | static int maxhd = 0; | |
194 | ||
195 | ret.ui = 0; | |
196 | if (maxhd == 0) { | |
197 | bb.intno = 0x13; | |
198 | bb.eax.r.h = 0x08; | |
199 | bb.edx.r.l = 0x80; | |
200 | bios(&bb); | |
201 | if (bb.flags.cf == 0) | |
202 | maxhd = 0x7f + bb.edx.r.l; | |
203 | }; | |
204 | ||
205 | if (drive > maxhd) | |
206 | return 0; | |
207 | ||
208 | /* Check drive for EBIOS support. */ | |
209 | bb.intno = 0x13; | |
210 | bb.eax.r.h = 0x41; | |
211 | bb.edx.r.l = drive; | |
212 | bb.ebx.rr = 0x55aa; | |
213 | bios(&bb); | |
214 | if(bb.ebx.rr == 0xaa55 && bb.flags.cf == 0) { | |
215 | ||
216 | /* Get EBIOS drive info. */ | |
217 | ebios.size = 26; | |
218 | bb.intno = 0x13; | |
219 | bb.eax.r.h = 0x48; | |
220 | bb.edx.r.l = drive; | |
221 | bb.esi.rr = ((unsigned)&ebios & 0xffff); | |
222 | bios(&bb); | |
223 | if(bb.flags.cf == 0 && ebios.cylinders != 0) { | |
224 | useEbios = 1; | |
225 | } | |
226 | } | |
227 | ||
228 | bb.intno = 0x13; | |
229 | bb.eax.r.h = 0x08; | |
230 | bb.edx.r.l = drive; | |
231 | bios(&bb); | |
232 | if (bb.flags.cf == 0 && bb.eax.r.h == 0) { | |
233 | unsigned long cyl; | |
234 | unsigned long sec; | |
235 | unsigned long hds; | |
236 | ||
237 | hds = bb.edx.r.h; | |
238 | sec = bb.ecx.r.l & 0x3F; | |
239 | if(useEbios) { | |
240 | cyl = (ebios.total_sectors / ((hds + 1) * sec)) - 1; | |
241 | } | |
242 | else { | |
243 | cyl = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2); | |
244 | } | |
245 | ret.di.heads = hds; | |
246 | ret.di.sectors = sec; | |
247 | ret.di.cylinders = cyl; | |
248 | } | |
249 | if(drive >= 0x80) uses_ebios[drive - 0x80] = useEbios; | |
250 | return ret.ui; | |
251 | } | |
252 | ||
253 | void setCursorPosition(int x, int y) | |
254 | { | |
255 | bb.intno = 0x10; | |
256 | bb.eax.r.h = 0x02; | |
257 | bb.ebx.r.h = 0x00; /* page 0 for graphics */ | |
258 | bb.edx.r.l = x; | |
259 | bb.edx.r.h = y; | |
260 | bios(&bb); | |
261 | } | |
262 | ||
263 | #if DEBUG | |
264 | ||
265 | int readDriveParameters(int drive, struct driveParameters *dp) | |
266 | { | |
267 | bb.intno = 0x13; | |
268 | bb.edx.r.l = drive; | |
269 | bb.eax.r.h = 0x08; | |
270 | bios(&bb); | |
271 | if (bb.eax.r.h == 0) { | |
272 | dp->heads = bb.edx.r.h; | |
273 | dp->sectors = bb.ecx.r.l & 0x3F; | |
274 | dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2); | |
275 | dp->totalDrives = bb.edx.r.l; | |
276 | } else { | |
277 | bzero(dp, sizeof(*dp)); | |
278 | } | |
279 | return bb.eax.r.h; | |
280 | ||
281 | } | |
282 | #endif | |
283 | ||
284 | #define APM_INTNO 0x15 | |
285 | #define APM_INTCODE 0x53 | |
286 | ||
287 | int | |
288 | APMPresent(void) | |
289 | { | |
290 | KERNBOOTSTRUCT *kbp = kernBootStruct; | |
291 | ||
292 | bb.intno = APM_INTNO; | |
293 | bb.eax.r.h = APM_INTCODE; | |
294 | bb.eax.r.l = 0x00; | |
295 | bb.ebx.rr = 0x0000; | |
296 | bios(&bb); | |
297 | if ((bb.flags.cf == 0) && | |
298 | (bb.ebx.r.h == 'P') && | |
299 | (bb.ebx.r.l == 'M')) { | |
300 | /* Success */ | |
301 | kbp->apm_config.major_vers = bb.eax.r.h; | |
302 | kbp->apm_config.minor_vers = bb.eax.r.l; | |
303 | kbp->apm_config.flags.data = bb.ecx.rr; | |
304 | return 1; | |
305 | } | |
306 | return 0; | |
307 | } | |
308 | ||
309 | int | |
310 | APMConnect32(void) | |
311 | { | |
312 | KERNBOOTSTRUCT *kbp = kernBootStruct; | |
313 | ||
314 | bb.intno = APM_INTNO; | |
315 | bb.eax.r.h = APM_INTCODE; | |
316 | bb.eax.r.l = 0x03; | |
317 | bb.ebx.rr = 0x0000; | |
318 | bios(&bb); | |
319 | if (bb.flags.cf == 0) { | |
320 | /* Success */ | |
321 | kbp->apm_config.cs32_base = (bb.eax.rr) << 4; | |
322 | kbp->apm_config.entry_offset = bb.ebx.rx; | |
323 | kbp->apm_config.cs16_base = (bb.ecx.rr) << 4; | |
324 | kbp->apm_config.ds_base = (bb.edx.rr) << 4; | |
325 | if (kbp->apm_config.major_vers >= 1 && | |
326 | kbp->apm_config.minor_vers >= 1) { | |
327 | kbp->apm_config.cs_length = bb.esi.rr; | |
328 | kbp->apm_config.ds_length = bb.edi.rr; | |
329 | } else { | |
330 | kbp->apm_config.cs_length = | |
331 | kbp->apm_config.ds_length = 64 * 1024; | |
332 | } | |
333 | kbp->apm_config.connected = 1; | |
334 | return 1; | |
335 | } | |
336 | return 0; | |
337 | } | |
338 | ||
339 | #ifdef EISA_SUPPORT // turn off for now since there isn't enough room | |
340 | BOOL | |
341 | eisa_present( | |
342 | void | |
343 | ) | |
344 | { | |
345 | static BOOL checked; | |
346 | static BOOL isEISA; | |
347 | ||
348 | if (!checked) { | |
349 | if (strncmp((char *)0xfffd9, "EISA", 4) == 0) | |
350 | isEISA = TRUE; | |
351 | ||
352 | checked = TRUE; | |
353 | } | |
354 | ||
355 | return (isEISA); | |
356 | } | |
357 | ||
358 | int | |
359 | ReadEISASlotInfo(EISA_slot_info_t *ep, int slot) | |
360 | { | |
361 | union { | |
362 | struct { | |
363 | unsigned char char2h :2; | |
364 | unsigned char char1 :5; | |
365 | unsigned char char3 :5; | |
366 | unsigned char char2l :3; | |
367 | unsigned char d2 :4; | |
368 | unsigned char d1 :4; | |
369 | unsigned char d4 :4; | |
370 | unsigned char d3 :4; | |
371 | } s; | |
372 | unsigned char data[4]; | |
373 | } u; | |
374 | static char hex[0x10] = "0123456789ABCDEF"; | |
375 | ||
376 | ||
377 | bb.intno = 0x15; | |
378 | bb.eax.r.h = 0xd8; | |
379 | bb.eax.r.l = 0x00; | |
380 | bb.ecx.r.l = slot; | |
381 | bios(&bb); | |
382 | if (bb.flags.cf) | |
383 | return bb.eax.r.h; | |
384 | ep->u_ID.d = bb.eax.r.l; | |
385 | ep->configMajor = bb.ebx.r.h; | |
386 | ep->configMinor = bb.ebx.r.l; | |
387 | ep->checksum = bb.ecx.rr; | |
388 | ep->numFunctions = bb.edx.r.h; | |
389 | ep->u_resources.d = bb.edx.r.l; | |
390 | u.data[0] = bb.edi.r.l; | |
391 | u.data[1] = bb.edi.r.h; | |
392 | u.data[2] = bb.esi.r.l; | |
393 | u.data[3] = bb.esi.r.h; | |
394 | ep->id[0] = u.s.char1 + ('A' - 1); | |
395 | ep->id[1] = (u.s.char2l | (u.s.char2h << 3)) + ('A' - 1); | |
396 | ep->id[2] = u.s.char3 + ('A' - 1); | |
397 | ep->id[3] = hex[u.s.d1]; | |
398 | ep->id[4] = hex[u.s.d2]; | |
399 | ep->id[5] = hex[u.s.d3]; | |
400 | ep->id[6] = hex[u.s.d4]; | |
401 | ep->id[7] = 0; | |
402 | return 0; | |
403 | } | |
404 | ||
405 | /* | |
406 | * Note: ep must point to an address below 64k. | |
407 | */ | |
408 | ||
409 | int | |
410 | ReadEISAFuncInfo(EISA_func_info_t *ep, int slot, int function) | |
411 | { | |
412 | bb.intno = 0x15; | |
413 | bb.eax.r.h = 0xd8; | |
414 | bb.eax.r.l = 0x01; | |
415 | bb.ecx.r.l = slot; | |
416 | bb.ecx.r.h = function; | |
417 | bb.esi.rr = (unsigned int)ep->data; | |
418 | bios(&bb); | |
419 | if (bb.eax.r.h == 0) { | |
420 | ep->slot = slot; | |
421 | ep->function = function; | |
422 | } | |
423 | return bb.eax.r.h; | |
424 | } | |
425 | #endif | |
426 | ||
427 | #define PCI_SIGNATURE 0x20494350 /* "PCI " */ | |
428 | ||
429 | int | |
430 | ReadPCIBusInfo(PCI_bus_info_t *pp) | |
431 | { | |
432 | bb.intno = 0x1a; | |
433 | bb.eax.r.h = 0xb1; | |
434 | bb.eax.r.l = 0x01; | |
435 | bios(&bb); | |
436 | if ((bb.eax.r.h == 0) && (bb.edx.rx == PCI_SIGNATURE)) { | |
437 | pp->BIOSPresent = 1; | |
438 | pp->u_bus.d = bb.eax.r.l; | |
439 | pp->majorVersion = bb.ebx.r.h; | |
440 | pp->minorVersion = bb.ebx.r.l; | |
441 | pp->maxBusNum = bb.ecx.r.l; | |
442 | return 0; | |
443 | } | |
444 | return -1; | |
445 | } |