]> git.saurik.com Git - apple/boot.git/blob - i386/libsaio/biosfn.c
boot-111.1.tar.gz
[apple/boot.git] / i386 / libsaio / biosfn.c
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 "bootstruct.h"
30 #include "libsaio.h"
31
32 #define MAX_DRIVES 8
33
34 static biosBuf_t bb;
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 unsigned long getMemoryMap( MemoryRange * rangeArray,
83 unsigned long maxRangeCount,
84 unsigned long * conMemSizePtr,
85 unsigned long * extMemSizePtr )
86 {
87 #define kMemoryMapSignature 'SMAP'
88 #define kDescriptorSizeMin 20
89
90 MemoryRange * range = rangeArray;
91 unsigned long count = 0;
92 unsigned long long conMemSize = 0;
93 unsigned long long extMemTop = 0;
94
95 // The memory pointed by the rangeArray must reside within the
96 // first megabyte.
97 //
98 // Prepare for the INT15 E820h call. Each call returns a single
99 // memory range. A continuation value is returned that must be
100 // provided on a subsequent call to fetch the next range.
101 //
102 // Certain BIOSes (Award 6.00PG) expect the upper word in EAX
103 // to be cleared on entry, otherwise only a single range will
104 // be reported.
105 //
106 // Some BIOSes will simply ignore the value of ECX on entry.
107 // Probably best to keep its value at 20 to avoid surprises.
108
109 bb.ebx.rx = 0; // Initial continuation value must be zero.
110
111 while ( count < maxRangeCount )
112 {
113 bb.intno = 0x15;
114 bb.eax.rx = 0xe820;
115 bb.ecx.rx = kDescriptorSizeMin;
116 bb.edx.rx = kMemoryMapSignature;
117 bb.edi.rr = OFFSET( (unsigned long) range );
118 bb.es = SEGMENT( (unsigned long) range );
119 bios(&bb);
120
121 // Check for errors.
122
123 if ( bb.flags.cf
124 || bb.eax.rx != kMemoryMapSignature
125 || bb.ecx.rx != kDescriptorSizeMin ) break;
126
127 // Tally up the conventional/extended memory sizes.
128
129 if ( range->type == kMemoryRangeUsable ||
130 range->type == kMemoryRangeACPI ||
131 range->type == kMemoryRangeNVS )
132 {
133 // Tally the conventional memory ranges.
134 if ( range->base + range->length <= 0xa0000 )
135 conMemSize += range->length;
136
137 // Record the top of extended memory.
138 if ( range->base >= EXTENDED_ADDR &&
139 range->base >= extMemTop )
140 extMemTop = range->base + range->length;
141 }
142
143 range++;
144 count++;
145
146 // Is this the last address range?
147
148 if ( bb.ebx.rx == 0 ) break;
149 }
150
151 if (extMemTop) extMemTop -= EXTENDED_ADDR; // convert to size
152 *conMemSizePtr = conMemSize / 1024; // size in KB
153 *extMemSizePtr = extMemTop / 1024; // size in KB
154
155 return count;
156 }
157
158 unsigned long getExtendedMemorySize()
159 {
160 // Get extended memory size for large configurations. Not used unless
161 // the INT15, E820H call (Get System Address Map) failed.
162 //
163 // Input:
164 //
165 // AX Function Code E801h
166 //
167 // Outputs:
168 //
169 // CF Carry Flag Carry cleared indicates no error.
170 // AX Extended 1 Number of contiguous KB between 1 and 16 MB,
171 // maximum 0x3C00 = 15 MB.
172 // BX Extended 2 Number of contiguous 64 KB blocks between
173 // 16 MB and 4 GB.
174 // CX Configured 1 Number of contiguous KB between 1 and 16 MB,
175 // maximum 0x3C00 = 15 MB.
176 // DX Configured 2 Number of contiguous 64 KB blocks between
177 // 16 MB and 4 GB.
178
179 bb.intno = 0x15;
180 bb.eax.rx = 0xe801;
181 bios(&bb);
182
183 // Return the size of memory above 1MB (extended memory) in kilobytes.
184
185 if ( bb.flags.cf == 0 ) return (bb.ebx.rr * 64 + bb.eax.rr);
186
187 // Get Extended memory size. Called on last resort since the return
188 // value is limited to 16-bits (a little less than 64MB max). May
189 // not be supported by modern BIOSes.
190 //
191 // Input:
192 //
193 // AX Function Code E801h
194 //
195 // Outputs:
196 //
197 // CF Carry Flag Carry cleared indicates no error.
198 // AX Memory Count Number of contiguous KB above 1MB.
199
200 bb.intno = 0x15;
201 bb.eax.rx = 0x88;
202 bios(&bb);
203
204 // Return the size of memory above 1MB (extended memory) in kilobytes.
205
206 return bb.flags.cf ? 0 : bb.eax.rr;
207 }
208
209 unsigned long getConventionalMemorySize()
210 {
211 bb.intno = 0x12;
212 bios(&bb);
213 return bb.eax.rr; // kilobytes
214 }
215
216 void video_mode(int mode)
217 {
218 bb.intno = 0x10;
219 bb.eax.r.h = 0x00;
220 bb.eax.r.l = mode;
221 bios(&bb);
222 }
223
224 int biosread(int dev, int cyl, int head, int sec, int num)
225 {
226 int i;
227
228 bb.intno = 0x13;
229 sec += 1; /* sector numbers start at 1 */
230
231 for (i=0;;) {
232 bb.ecx.r.h = cyl;
233 bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
234 bb.edx.r.h = head;
235 bb.edx.r.l = dev;
236 bb.eax.r.l = num;
237 bb.ebx.rr = OFFSET(ptov(BIOS_ADDR));
238 bb.es = SEGMENT(ptov(BIOS_ADDR));
239
240 bb.eax.r.h = 0x02;
241 bios(&bb);
242
243 if ((bb.eax.r.h == 0x00) || (i++ >= 5))
244 break;
245
246 /* reset disk subsystem and try again */
247 bb.eax.r.h = 0x00;
248 bios(&bb);
249 }
250 return bb.eax.r.h;
251 }
252
253 int ebiosread(int dev, long sec, int count)
254 {
255 int i;
256 static struct {
257 unsigned char size;
258 unsigned char reserved;
259 unsigned char numblocks;
260 unsigned char reserved2;
261 unsigned short bufferOffset;
262 unsigned short bufferSegment;
263 unsigned long long startblock;
264 } addrpacket = {0};
265 addrpacket.size = sizeof(addrpacket);
266
267 for (i=0;;) {
268 bb.intno = 0x13;
269 bb.eax.r.h = 0x42;
270 bb.edx.r.l = dev;
271 bb.esi.rr = OFFSET((unsigned)&addrpacket);
272 bb.ds = SEGMENT((unsigned)&addrpacket);
273 addrpacket.reserved = addrpacket.reserved2 = 0;
274 addrpacket.numblocks = count;
275 addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
276 addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
277 addrpacket.startblock = sec;
278 bios(&bb);
279 if ((bb.eax.r.h == 0x00) || (i++ >= 5))
280 break;
281
282 /* reset disk subsystem and try again */
283 bb.eax.r.h = 0x00;
284 bios(&bb);
285 }
286 return bb.eax.r.h;
287 }
288
289 void putc(int ch)
290 {
291 bb.intno = 0x10;
292 bb.ebx.r.h = 0x00; /* background black */
293 bb.ebx.r.l = 0x0F; /* foreground white */
294 bb.eax.r.h = 0x0e;
295 bb.eax.r.l = ch;
296 bios(&bb);
297 }
298
299 void putca(int ch, int attr, int repeat)
300 {
301 bb.intno = 0x10;
302 bb.ebx.r.h = 0x00; /* page number */
303 bb.ebx.r.l = attr; /* attribute */
304 bb.eax.r.h = 0x9;
305 bb.eax.r.l = ch;
306 bb.ecx.rx = repeat; /* repeat count */
307 bios(&bb);
308 }
309
310 /* Check to see if the passed-in drive is in El Torito no-emulation mode. */
311 int is_no_emulation(int drive)
312 {
313 struct packet {
314 unsigned char packet_size;
315 unsigned char media_type;
316 unsigned char drive_num;
317 unsigned char ctrlr_index;
318 unsigned long lba;
319 unsigned short device_spec;
320 unsigned short buffer_segment;
321 unsigned short load_segment;
322 unsigned short sector_count;
323 unsigned char cyl_count;
324 unsigned char sec_count;
325 unsigned char head_count;
326 unsigned char reseved;
327 };
328 static struct packet pkt;
329
330 bzero(&pkt, sizeof(pkt));
331 pkt.packet_size = 0x13;
332
333 bb.intno = 0x13;
334 bb.eax.r.h = 0x4b;
335 bb.eax.r.l = 0x01; // subfunc: get info
336 bb.edx.r.l = drive;
337 bb.esi.rr = OFFSET((unsigned)&pkt);
338 bb.ds = SEGMENT((unsigned)&pkt);
339
340 bios(&bb);
341 #if DEBUG
342 printf("el_torito info drive %x\n", drive);
343
344 printf("--> cf %x, eax %x\n", bb.flags.cf, bb.eax.rr);
345
346 printf("pkt_size: %x\n", pkt.packet_size);
347 printf("media_type: %x\n", pkt.media_type);
348 printf("drive_num: %x\n", pkt.drive_num);
349 printf("device_spec: %x\n", pkt.device_spec);
350 printf("press a key->\n");getc();
351 #endif
352
353 /* Some BIOSes erroneously return cf = 1 */
354 /* Just check to see if the drive number is the same. */
355 if (pkt.drive_num == drive) {
356 if ((pkt.media_type & 0x0F) == 0) {
357 /* We are in no-emulation mode. */
358 return 1;
359 }
360 }
361
362 return 0;
363 }
364
365 #if DEBUG
366 /*
367 * BIOS drive information.
368 */
369 void print_drive_info(boot_drive_info_t *dp)
370 {
371 // printf("buf_size = %x\n", dp->params.buf_size);
372 printf("info_flags = %x\n", dp->params.info_flags);
373 printf(" phys_cyls = %lx\n", dp->params. phys_cyls);
374 printf(" phys_heads = %lx\n", dp->params. phys_heads);
375 printf(" phys_spt = %lx\n", dp->params. phys_spt);
376 printf("phys_sectors = %lx%lx\n", ((unsigned long *)(&dp->params.phys_sectors))[1],
377 ((unsigned long *)(&dp->params.phys_sectors))[0]);
378 printf("phys_nbps = %x\n", dp->params.phys_nbps);
379 // printf("dpte_offset = %x\n", dp->params.dpte_offset);
380 // printf("dpte_segment = %x\n", dp->params.dpte_segment);
381 // printf("key = %x\n", dp->params.key);
382 // printf("path_len = %x\n", dp->params. path_len);
383 // printf("reserved1 = %x\n", dp->params. reserved1);
384 // printf("reserved2 = %x\n", dp->params.reserved2);
385 //printf("bus_type[4] = %x\n", dp->params. bus_type[4]);
386 //printf("interface_type[8] = %x\n", dp->params. interface_type[8]);
387 //printf("interface_path[8] = %x\n", dp->params. interface_path[8]);
388 //printf("dev_path[8] = %x\n", dp->params. dev_path[8]);
389 // printf("reserved3 = %x\n", dp->params. reserved3);
390 // printf("checksum = %x\n", dp->params. checksum);
391
392 printf(" io_port_base = %x\n", dp->dpte.io_port_base);
393 printf(" control_port_base = %x\n", dp->dpte.control_port_base);
394 printf(" head_flags = %x\n", dp->dpte. head_flags);
395 printf(" vendor_info = %x\n", dp->dpte. vendor_info);
396 printf(" irq = %x\n", dp->dpte. irq);
397 // printf(" irq_unused = %x\n", dp->dpte. irq_unused);
398 printf(" block_count = %x\n", dp->dpte. block_count);
399 printf(" dma_channe = %x\n", dp->dpte. dma_channel);
400 printf(" dma_type = %x\n", dp->dpte. dma_type);
401 printf(" pio_type = %x\n", dp->dpte. pio_type);
402 printf(" pio_unused = %x\n", dp->dpte. pio_unused);
403 printf(" option_flags = %x\n", dp->dpte.option_flags);
404 // printf(" reserved = %x\n", dp->dpte.reserved);
405 printf(" revision = %x\n", dp->dpte. revision);
406 // printf(" checksum = %x\n", dp->dpte. checksum);
407 }
408
409 #endif
410
411 int get_drive_info(int drive, struct driveInfo *dp)
412 {
413 boot_drive_info_t *di = &dp->di;
414 int ret = 0;
415
416 #if 0
417 if (maxhd == 0) {
418 bb.intno = 0x13;
419 bb.eax.r.h = 0x08;
420 bb.edx.r.l = 0x80;
421 bios(&bb);
422 if (bb.flags.cf == 0)
423 maxhd = 0x7f + bb.edx.r.l;
424 };
425
426 if (drive > maxhd)
427 return 0;
428 #endif
429
430 bzero(dp, sizeof(struct driveInfo));
431 dp->biosdev = drive;
432
433 /* Check for El Torito no-emulation mode. */
434 dp->no_emulation = is_no_emulation(drive);
435
436 /* Check drive for EBIOS support. */
437 bb.intno = 0x13;
438 bb.eax.r.h = 0x41;
439 bb.edx.r.l = drive;
440 bb.ebx.rr = 0x55aa;
441 bios(&bb);
442 if((bb.ebx.rr == 0xaa55) && (bb.flags.cf == 0)) {
443 /* Get flags for supported operations. */
444 dp->uses_ebios = bb.ecx.r.l;
445 }
446
447 if (dp->uses_ebios & (EBIOS_ENHANCED_DRIVE_INFO | EBIOS_LOCKING_ACCESS | EBIOS_FIXED_DISK_ACCESS)) {
448 /* Get EBIOS drive info. */
449 static struct drive_params params;
450
451 params.buf_size = sizeof(params);
452 bb.intno = 0x13;
453 bb.eax.r.h = 0x48;
454 bb.edx.r.l = drive;
455 bb.esi.rr = OFFSET((unsigned)&params);
456 bb.ds = SEGMENT((unsigned)&params);
457 bios(&bb);
458 if(bb.flags.cf != 0 /* || params.phys_sectors < 2097152 */) {
459 dp->uses_ebios = 0;
460 di->params.buf_size = 1;
461 } else {
462 bcopy(&params, &di->params, sizeof(params));
463
464 if (drive >= BASE_HD_DRIVE &&
465 (dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) &&
466 di->params.buf_size >= 30 &&
467 !(di->params.dpte_offset == 0xFFFF && di->params.dpte_segment == 0xFFFF)) {
468 void *ptr = (void *)(di->params.dpte_offset + ((unsigned int)di->params.dpte_segment << 4));
469 bcopy(ptr, &di->dpte, sizeof(di->dpte));
470 }
471 }
472 }
473
474 if (di->params.phys_heads == 0 || di->params.phys_spt == 0) {
475 /* Either it's not EBIOS, or EBIOS didn't tell us. */
476 bb.intno = 0x13;
477 bb.eax.r.h = 0x08;
478 bb.edx.r.l = drive;
479 bios(&bb);
480 if (bb.flags.cf == 0 && bb.eax.r.h == 0) {
481 unsigned long cyl;
482 unsigned long sec;
483 unsigned long hds;
484
485 hds = bb.edx.r.h;
486 sec = bb.ecx.r.l & 0x3F;
487 if((dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) && (sec != 0)) {
488 cyl = (di->params.phys_sectors / ((hds + 1) * sec)) - 1;
489 }
490 else {
491 cyl = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
492 }
493 di->params.phys_heads = hds;
494 di->params.phys_spt = sec;
495 di->params.phys_cyls = cyl;
496 } else {
497 ret = -1;
498 }
499 }
500
501 if (dp->no_emulation) {
502 /* Some BIOSes give us erroneous EBIOS support information.
503 * Assume that if you're on a CD, then you can use
504 * EBIOS disk calls.
505 */
506 dp->uses_ebios |= EBIOS_FIXED_DISK_ACCESS;
507 }
508 #if DEBUG
509 print_drive_info(di);
510 printf("uses_ebios = 0x%x\n", dp->uses_ebios);
511 printf("press a key->\n");getc();
512 #endif
513
514 if (ret == 0) {
515 dp->valid = 1;
516 }
517 return ret;
518 }
519
520 void setCursorPosition(int x, int y, int page)
521 {
522 bb.intno = 0x10;
523 bb.eax.r.h = 0x02;
524 bb.ebx.r.h = page; /* page 0 for graphics */
525 bb.edx.r.l = x;
526 bb.edx.r.h = y;
527 bios(&bb);
528 }
529
530 void setCursorType(int type)
531 {
532 bb.intno = 0x10;
533 bb.eax.r.h = 0x01;
534 bb.ecx.rr = type;
535 bios(&bb);
536 }
537
538 void getCursorPositionAndType(int * x, int * y, int * type)
539 {
540 bb.intno = 0x10;
541 bb.eax.r.h = 0x03;
542 bios(&bb);
543 *x = bb.edx.r.l;
544 *y = bb.edx.r.h;
545 *type = bb.ecx.rr;
546 }
547
548 void scollPage(int x1, int y1, int x2, int y2, int attr, int rows, int dir)
549 {
550 bb.intno = 0x10;
551 bb.eax.r.h = (dir > 0) ? 0x06 : 0x07;
552 bb.eax.r.l = rows;
553 bb.ebx.r.h = attr;
554 bb.ecx.r.h = y1;
555 bb.ecx.r.l = x1;
556 bb.edx.r.h = y2;
557 bb.edx.r.l = x2;
558 bios(&bb);
559 }
560
561 void clearScreenRows( int y1, int y2 )
562 {
563 scollPage( 0, y1, 80 - 1, y2, 0x07, y2 - y1 + 1, 1 );
564 }
565
566 void setActiveDisplayPage( int page )
567 {
568 bb.intno = 0x10;
569 bb.eax.r.h = 5;
570 bb.eax.r.l = page;
571 bios(&bb);
572 }
573
574 #if DEBUG
575
576 int terminateDiskEmulation()
577 {
578 static char cd_spec[0x13];
579
580 bb.intno = 0x13;
581 bb.eax.r.h = 0x4b;
582 bb.eax.r.l = 0; // subfunc: terminate emulation
583 bb.esi.rr = OFFSET((unsigned)&cd_spec);
584 bb.ds = SEGMENT((unsigned)&cd_spec);
585 bios(&bb);
586 return bb.eax.r.h;
587 }
588
589 int readDriveParameters(int drive, struct driveParameters *dp)
590 {
591 bb.intno = 0x13;
592 bb.edx.r.l = drive;
593 bb.eax.r.h = 0x08;
594 bios(&bb);
595 if (bb.eax.r.h == 0) {
596 dp->heads = bb.edx.r.h;
597 dp->sectors = bb.ecx.r.l & 0x3F;
598 dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
599 dp->totalDrives = bb.edx.r.l;
600 } else {
601 bzero(dp, sizeof(*dp));
602 }
603 return bb.eax.r.h;
604
605 }
606 #endif
607
608 #define APM_INTNO 0x15
609 #define APM_INTCODE 0x53
610
611 int
612 APMPresent(void)
613 {
614 bb.intno = APM_INTNO;
615 bb.eax.r.h = APM_INTCODE;
616 bb.eax.r.l = 0x00;
617 bb.ebx.rr = 0x0000;
618 bios(&bb);
619 if ((bb.flags.cf == 0) &&
620 (bb.ebx.r.h == 'P') &&
621 (bb.ebx.r.l == 'M')) {
622 /* Success */
623 bootArgs->apmConfig.major_vers = bb.eax.r.h;
624 bootArgs->apmConfig.minor_vers = bb.eax.r.l;
625 bootArgs->apmConfig.flags.data = bb.ecx.rr;
626 return 1;
627 }
628 return 0;
629 }
630
631 int
632 APMConnect32(void)
633 {
634 bb.intno = APM_INTNO;
635 bb.eax.r.h = APM_INTCODE;
636 bb.eax.r.l = 0x03;
637 bb.ebx.rr = 0x0000;
638 bios(&bb);
639 if (bb.flags.cf == 0) {
640 /* Success */
641 bootArgs->apmConfig.cs32_base = (bb.eax.rr) << 4;
642 bootArgs->apmConfig.entry_offset = bb.ebx.rx;
643 bootArgs->apmConfig.cs16_base = (bb.ecx.rr) << 4;
644 bootArgs->apmConfig.ds_base = (bb.edx.rr) << 4;
645 if (bootArgs->apmConfig.major_vers >= 1 &&
646 bootArgs->apmConfig.minor_vers >= 1) {
647 bootArgs->apmConfig.cs_length = bb.esi.rr;
648 bootArgs->apmConfig.ds_length = bb.edi.rr;
649 } else {
650 bootArgs->apmConfig.cs_length =
651 bootArgs->apmConfig.ds_length = 64 * 1024;
652 }
653 bootArgs->apmConfig.connected = 1;
654 return 1;
655 }
656 return 0;
657 }
658
659 #ifdef EISA_SUPPORT
660 BOOL
661 eisa_present(
662 void
663 )
664 {
665 static BOOL checked;
666 static BOOL isEISA;
667
668 if (!checked) {
669 if (strncmp((char *)0xfffd9, "EISA", 4) == 0)
670 isEISA = TRUE;
671
672 checked = TRUE;
673 }
674
675 return (isEISA);
676 }
677
678 int
679 ReadEISASlotInfo(EISA_slot_info_t *ep, int slot)
680 {
681 union {
682 struct {
683 unsigned char char2h :2;
684 unsigned char char1 :5;
685 unsigned char char3 :5;
686 unsigned char char2l :3;
687 unsigned char d2 :4;
688 unsigned char d1 :4;
689 unsigned char d4 :4;
690 unsigned char d3 :4;
691 } s;
692 unsigned char data[4];
693 } u;
694 static char hex[0x10] = "0123456789ABCDEF";
695
696
697 bb.intno = 0x15;
698 bb.eax.r.h = 0xd8;
699 bb.eax.r.l = 0x00;
700 bb.ecx.r.l = slot;
701 bios(&bb);
702 if (bb.flags.cf)
703 return bb.eax.r.h;
704 ep->u_ID.d = bb.eax.r.l;
705 ep->configMajor = bb.ebx.r.h;
706 ep->configMinor = bb.ebx.r.l;
707 ep->checksum = bb.ecx.rr;
708 ep->numFunctions = bb.edx.r.h;
709 ep->u_resources.d = bb.edx.r.l;
710 u.data[0] = bb.edi.r.l;
711 u.data[1] = bb.edi.r.h;
712 u.data[2] = bb.esi.r.l;
713 u.data[3] = bb.esi.r.h;
714 ep->id[0] = u.s.char1 + ('A' - 1);
715 ep->id[1] = (u.s.char2l | (u.s.char2h << 3)) + ('A' - 1);
716 ep->id[2] = u.s.char3 + ('A' - 1);
717 ep->id[3] = hex[u.s.d1];
718 ep->id[4] = hex[u.s.d2];
719 ep->id[5] = hex[u.s.d3];
720 ep->id[6] = hex[u.s.d4];
721 ep->id[7] = 0;
722 return 0;
723 }
724
725 /*
726 * Note: ep must point to an address below 64k.
727 */
728
729 int
730 ReadEISAFuncInfo(EISA_func_info_t *ep, int slot, int function)
731 {
732 bb.intno = 0x15;
733 bb.eax.r.h = 0xd8;
734 bb.eax.r.l = 0x01;
735 bb.ecx.r.l = slot;
736 bb.ecx.r.h = function;
737 bb.esi.rr = (unsigned int)ep->data;
738 bios(&bb);
739 if (bb.eax.r.h == 0) {
740 ep->slot = slot;
741 ep->function = function;
742 }
743 return bb.eax.r.h;
744 }
745 #endif /* EISA_SUPPORT */
746
747 #define PCI_SIGNATURE 0x20494350 /* "PCI " */
748
749 int
750 ReadPCIBusInfo(PCI_bus_info_t *pp)
751 {
752 bb.intno = 0x1a;
753 bb.eax.r.h = 0xb1;
754 bb.eax.r.l = 0x01;
755 bios(&bb);
756 if ((bb.eax.r.h == 0) && (bb.edx.rx == PCI_SIGNATURE)) {
757 pp->BIOSPresent = 1;
758 pp->u_bus.d = bb.eax.r.l;
759 pp->majorVersion = bb.ebx.r.h;
760 pp->minorVersion = bb.ebx.r.l;
761 pp->maxBusNum = bb.ecx.r.l;
762 return 0;
763 }
764 return -1;
765 }
766
767 void sleep(int n)
768 {
769 unsigned int endtime = (time18() + 18*n);
770 while (time18() < endtime);
771 }
772
773 void delay(int ms)
774 {
775 bb.intno = 0x15;
776 bb.eax.r.h = 0x86;
777 bb.ecx.rr = ms >> 16;
778 bb.edx.rr = ms & 0xFFFF;
779 bios(&bb);
780 }