]> git.saurik.com Git - apple/boot.git/blame - i386/libsaio/biosfn.c
boot-80.1.tar.gz
[apple/boot.git] / i386 / libsaio / biosfn.c
CommitLineData
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
33static biosBuf_t bb;
34unsigned char uses_ebios[8] = {0, 0, 0, 0, 0, 0, 0, 0};
35
36int bgetc(void)
37{
38 bb.intno = 0x16;
39 bb.eax.r.h = 0x00;
40 bios(&bb);
41 return bb.eax.rr;
42}
43
44int 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
56int readKeyboardShiftFlags(void)
57{
58 bb.intno = 0x16;
59 bb.eax.r.h = 0x02;
60 bios(&bb);
61 return bb.eax.r.l;
62}
63
64unsigned 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
82int 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
96void 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
104int 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
133int 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
165void 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
175unsigned 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
253void 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
265int 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
287int
288APMPresent(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
309int
310APMConnect32(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
340BOOL
341eisa_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
358int
359ReadEISASlotInfo(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
409int
410ReadEISAFuncInfo(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
429int
430ReadPCIBusInfo(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}