/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
+ * Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
* All rights reserved.
*/
+#include "bootstruct.h"
#include "libsaio.h"
-#include "memory.h"
-#include "kernBootStruct.h"
+
+#define MAX_DRIVES 8
static biosBuf_t bb;
-unsigned char uses_ebios[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int bgetc(void)
{
bb.eax.r.h = 0x01;
bios(&bb);
if (bb.flags.zf) {
- return 0;
+ return 0;
} else {
- return bb.eax.rr;
+ return bb.eax.rr;
}
}
unsigned int time18(void)
{
union {
- struct {
- unsigned int low:16;
- unsigned int high:16;
- } s;
- unsigned int i;
+ struct {
+ unsigned int low:16;
+ unsigned int high:16;
+ } s;
+ unsigned int i;
} time;
bb.intno = 0x1a;
return time.i;
}
-int memsize(int which)
+unsigned long getMemoryMap( MemoryRange * rangeArray,
+ unsigned long maxRangeCount,
+ unsigned long * conMemSizePtr,
+ unsigned long * extMemSizePtr )
{
- if (which) {
- get_memsize(&bb);
- return (bb.edx.rr << 16) | bb.eax.rr;
+ #define kMemoryMapSignature 'SMAP'
+ #define kDescriptorSizeMin 20
+
+ MemoryRange * range = (MemoryRange *)BIOS_ADDR;
+ unsigned long count = 0;
+ unsigned long long conMemSize = 0;
+ unsigned long long extMemSize = 0;
+
+ // Prepare for the INT15 E820h call. Each call returns a single
+ // memory range. A continuation value is returned that must be
+ // provided on a subsequent call to fetch the next range.
+ //
+ // Certain BIOSes (Award 6.00PG) expect the upper word in EAX
+ // to be cleared on entry, otherwise only a single range will
+ // be reported.
+ //
+ // Some BIOSes will simply ignore the value of ECX on entry.
+ // Probably best to keep its value at 20 to avoid surprises.
+
+ //printf("Get memory map 0x%x, %d\n", rangeArray);getc();
+ if (maxRangeCount > (BIOS_LEN / sizeof(MemoryRange))) {
+ maxRangeCount = (BIOS_LEN / sizeof(MemoryRange));
}
- else {
- /* conventional memory */
- bb.intno = 0x12;
+ bb.ebx.rx = 0; // Initial continuation value must be zero.
+
+ while ( count < maxRangeCount )
+ {
+ bb.intno = 0x15;
+ bb.eax.rx = 0xe820;
+ bb.ecx.rx = kDescriptorSizeMin;
+ bb.edx.rx = kMemoryMapSignature;
+ bb.edi.rr = OFFSET( (unsigned long) range );
+ bb.es = SEGMENT( (unsigned long) range );
bios(&bb);
- return bb.eax.rr;
+
+ // Check for errors.
+
+ if ( bb.flags.cf
+ || bb.eax.rx != kMemoryMapSignature
+ || bb.ecx.rx != kDescriptorSizeMin ) {
+ //printf("Got an error %x %x %x\n", bb.flags.cf,
+ // bb.eax.rx, bb.ecx.rx);
+ break;
+ }
+
+ // Tally up the conventional/extended memory sizes.
+
+ if ( range->type == kMemoryRangeUsable ||
+ range->type == kMemoryRangeACPI ||
+ range->type == kMemoryRangeNVS )
+ {
+ // Tally the conventional memory ranges.
+ if ( range->base + range->length <= 0xa0000 ) {
+ conMemSize += range->length;
+ }
+
+ // Record the top of extended memory.
+ if ( range->base >= EXTENDED_ADDR ) {
+ extMemSize += range->length;
+ }
+ }
+
+ range++;
+ count++;
+
+ // Is this the last address range?
+
+ if ( bb.ebx.rx == 0 ) {
+ //printf("last range\n");
+ break;
+ }
+ }
+ *conMemSizePtr = conMemSize / 1024; // size in KB
+ *extMemSizePtr = extMemSize / 1024; // size in KB
+
+ // Copy out data
+ bcopy((char *)BIOS_ADDR, rangeArray, ((char *)range - (char *)BIOS_ADDR));
+
+#if DEBUG
+ {
+ int i;
+ printf("%d total ranges\n", count);getc();
+ for (i=0, range = rangeArray; i<count; i++, range++) {
+ printf("range: type %d, base 0x%x, length 0x%x\n",
+ range->type, (unsigned int)range->base, (unsigned int)range->length); getc();
+ }
}
+#endif
+
+ return count;
+}
+
+unsigned long getExtendedMemorySize()
+{
+ // Get extended memory size for large configurations. Not used unless
+ // the INT15, E820H call (Get System Address Map) failed.
+ //
+ // Input:
+ //
+ // AX Function Code E801h
+ //
+ // Outputs:
+ //
+ // CF Carry Flag Carry cleared indicates no error.
+ // AX Extended 1 Number of contiguous KB between 1 and 16 MB,
+ // maximum 0x3C00 = 15 MB.
+ // BX Extended 2 Number of contiguous 64 KB blocks between
+ // 16 MB and 4 GB.
+ // CX Configured 1 Number of contiguous KB between 1 and 16 MB,
+ // maximum 0x3C00 = 15 MB.
+ // DX Configured 2 Number of contiguous 64 KB blocks between
+ // 16 MB and 4 GB.
+
+ bb.intno = 0x15;
+ bb.eax.rx = 0xe801;
+ bios(&bb);
+
+ // Return the size of memory above 1MB (extended memory) in kilobytes.
+
+ if ( bb.flags.cf == 0 ) return (bb.ebx.rr * 64 + bb.eax.rr);
+
+ // Get Extended memory size. Called on last resort since the return
+ // value is limited to 16-bits (a little less than 64MB max). May
+ // not be supported by modern BIOSes.
+ //
+ // Input:
+ //
+ // AX Function Code E801h
+ //
+ // Outputs:
+ //
+ // CF Carry Flag Carry cleared indicates no error.
+ // AX Memory Count Number of contiguous KB above 1MB.
+
+ bb.intno = 0x15;
+ bb.eax.rx = 0x88;
+ bios(&bb);
+
+ // Return the size of memory above 1MB (extended memory) in kilobytes.
+
+ return bb.flags.cf ? 0 : bb.eax.rr;
+}
+
+unsigned long getConventionalMemorySize()
+{
+ bb.intno = 0x12;
+ bios(&bb);
+ return bb.eax.rr; // kilobytes
}
void video_mode(int mode)
int i;
bb.intno = 0x13;
- sec += 1; /* sector numbers start at 1 */
+ sec += 1; /* sector numbers start at 1 */
for (i=0;;) {
- bb.ecx.r.h = cyl;
- bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
- bb.edx.r.h = head;
- bb.edx.r.l = dev;
- bb.eax.r.l = num;
- bb.ebx.rr = ptov(BIOS_ADDR);
- bb.es = ((unsigned long)&i & 0xffff0000) >> 4;
-
- bb.eax.r.h = 0x02;
- bios(&bb);
+ bb.ecx.r.h = cyl;
+ bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
+ bb.edx.r.h = head;
+ bb.edx.r.l = dev;
+ bb.eax.r.l = num;
+ bb.ebx.rr = OFFSET(ptov(BIOS_ADDR));
+ bb.es = SEGMENT(ptov(BIOS_ADDR));
+
+ bb.eax.r.h = 0x02;
+ bios(&bb);
- if ((bb.eax.r.h == 0x00) || (i++ >= 5))
- break;
+ if ((bb.eax.r.h == 0x00) || (i++ >= 5))
+ break;
- /* reset disk subsystem and try again */
- bb.eax.r.h = 0x00;
- bios(&bb);
+ /* reset disk subsystem and try again */
+ bb.eax.r.h = 0x00;
+ bios(&bb);
}
return bb.eax.r.h;
}
int ebiosread(int dev, long sec, int count)
{
int i;
- struct {
- unsigned char size;
- unsigned char reserved;
- unsigned char numblocks;
- unsigned char reserved2;
- unsigned int buffer;
- unsigned long long startblock;
- } addrpacket = {0};
+ static struct {
+ unsigned char size;
+ unsigned char reserved;
+ unsigned char numblocks;
+ unsigned char reserved2;
+ unsigned short bufferOffset;
+ unsigned short bufferSegment;
+ unsigned long long startblock;
+ } addrpacket __attribute__((aligned(16))) = {0};
addrpacket.size = sizeof(addrpacket);
for (i=0;;) {
- bb.intno = 0x13;
+ bb.intno = 0x13;
bb.eax.r.h = 0x42;
bb.edx.r.l = dev;
- bb.esi.rr = ((unsigned)&addrpacket & 0xffff);
- addrpacket.numblocks = count;
- addrpacket.buffer = ptov(BIOS_ADDR);
- addrpacket.startblock = sec;
+ bb.esi.rr = OFFSET((unsigned)&addrpacket);
+ bb.ds = SEGMENT((unsigned)&addrpacket);
+ addrpacket.reserved = addrpacket.reserved2 = 0;
+ addrpacket.numblocks = count;
+ addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
+ addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
+ addrpacket.startblock = sec;
+ bios(&bb);
+ if ((bb.eax.r.h == 0x00) || (i++ >= 5))
+ break;
+
+ /* reset disk subsystem and try again */
+ bb.eax.r.h = 0x00;
+ bios(&bb);
+ }
+ return bb.eax.r.h;
+}
+
+int ebioswrite(int dev, long sec, int count)
+{
+ int i;
+ static struct {
+ unsigned char size;
+ unsigned char reserved;
+ unsigned char numblocks;
+ unsigned char reserved2;
+ unsigned short bufferOffset;
+ unsigned short bufferSegment;
+ unsigned long long startblock;
+ } addrpacket __attribute__((aligned(16))) = {0};
+ addrpacket.size = sizeof(addrpacket);
+
+ for (i=0;;) {
+ bb.intno = 0x13;
+ bb.eax.r.l = 0; /* Don't verify */
+ bb.eax.r.h = 0x43;
+ bb.edx.r.l = dev;
+ bb.esi.rr = OFFSET((unsigned)&addrpacket);
+ bb.ds = SEGMENT((unsigned)&addrpacket);
+ addrpacket.reserved = addrpacket.reserved2 = 0;
+ addrpacket.numblocks = count;
+ addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
+ addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
+ addrpacket.startblock = sec;
bios(&bb);
if ((bb.eax.r.h == 0x00) || (i++ >= 5))
break;
void putc(int ch)
{
bb.intno = 0x10;
- bb.ebx.r.h = 0x00; /* background black */
- bb.ebx.r.l = 0x0F; /* foreground white */
+ bb.ebx.r.h = 0x00; /* background black */
+ bb.ebx.r.l = 0x0F; /* foreground white */
bb.eax.r.h = 0x0e;
bb.eax.r.l = ch;
bios(&bb);
}
-unsigned int get_diskinfo(int drive)
+void putca(int ch, int attr, int repeat)
{
- struct {
- unsigned short size;
- unsigned short flags;
- unsigned long cylinders;
- unsigned long heads;
- unsigned long sectors;
- unsigned long long total_sectors;
- unsigned short bps;
- unsigned long params_p;
- } ebios = {0};
- unsigned char useEbios = 0;
+ bb.intno = 0x10;
+ bb.ebx.r.h = 0x00; /* page number */
+ bb.ebx.r.l = attr; /* attribute */
+ bb.eax.r.h = 0x9;
+ bb.eax.r.l = ch;
+ bb.ecx.rx = repeat; /* repeat count */
+ bios(&bb);
+}
- union {
- compact_diskinfo_t di;
- unsigned int ui;
- } ret;
- static int maxhd = 0;
+/* Check to see if the passed-in drive is in El Torito no-emulation mode. */
+int is_no_emulation(int drive)
+{
+ struct packet {
+ unsigned char packet_size;
+ unsigned char media_type;
+ unsigned char drive_num;
+ unsigned char ctrlr_index;
+ unsigned long lba;
+ unsigned short device_spec;
+ unsigned short buffer_segment;
+ unsigned short load_segment;
+ unsigned short sector_count;
+ unsigned char cyl_count;
+ unsigned char sec_count;
+ unsigned char head_count;
+ unsigned char reseved;
+ } __attribute__((packed));
+ static struct packet pkt;
+
+ bzero(&pkt, sizeof(pkt));
+ pkt.packet_size = 0x13;
+
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x4b;
+ bb.eax.r.l = 0x01; // subfunc: get info
+ bb.edx.r.l = drive;
+ bb.esi.rr = OFFSET((unsigned)&pkt);
+ bb.ds = SEGMENT((unsigned)&pkt);
+
+ bios(&bb);
+#if DEBUG
+ printf("el_torito info drive %x\n", drive);
+
+ printf("--> cf %x, eax %x\n", bb.flags.cf, bb.eax.rr);
+
+ printf("pkt_size: %x\n", pkt.packet_size);
+ printf("media_type: %x\n", pkt.media_type);
+ printf("drive_num: %x\n", pkt.drive_num);
+ printf("device_spec: %x\n", pkt.device_spec);
+ printf("press a key->\n");getc();
+#endif
+
+ /* Some BIOSes erroneously return cf = 1 */
+ /* Just check to see if the drive number is the same. */
+ if (pkt.drive_num == drive) {
+ if ((pkt.media_type & 0x0F) == 0) {
+ /* We are in no-emulation mode. */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#if DEBUG
+/*
+ * BIOS drive information.
+ */
+void print_drive_info(boot_drive_info_t *dp)
+{
+ // printf("buf_size = %x\n", dp->params.buf_size);
+ printf("info_flags = %x\n", dp->params.info_flags);
+ printf(" phys_cyls = %lx\n", dp->params. phys_cyls);
+ printf(" phys_heads = %lx\n", dp->params. phys_heads);
+ printf(" phys_spt = %lx\n", dp->params. phys_spt);
+ printf("phys_sectors = %lx%lx\n", ((unsigned long *)(&dp->params.phys_sectors))[1],
+ ((unsigned long *)(&dp->params.phys_sectors))[0]);
+ printf("phys_nbps = %x\n", dp->params.phys_nbps);
+ // printf("dpte_offset = %x\n", dp->params.dpte_offset);
+ // printf("dpte_segment = %x\n", dp->params.dpte_segment);
+ // printf("key = %x\n", dp->params.key);
+ // printf("path_len = %x\n", dp->params. path_len);
+ // printf("reserved1 = %x\n", dp->params. reserved1);
+ // printf("reserved2 = %x\n", dp->params.reserved2);
+ //printf("bus_type[4] = %x\n", dp->params. bus_type[4]);
+ //printf("interface_type[8] = %x\n", dp->params. interface_type[8]);
+ //printf("interface_path[8] = %x\n", dp->params. interface_path[8]);
+ //printf("dev_path[8] = %x\n", dp->params. dev_path[8]);
+ // printf("reserved3 = %x\n", dp->params. reserved3);
+ // printf("checksum = %x\n", dp->params. checksum);
+
+ printf(" io_port_base = %x\n", dp->dpte.io_port_base);
+ printf(" control_port_base = %x\n", dp->dpte.control_port_base);
+ printf(" head_flags = %x\n", dp->dpte. head_flags);
+ printf(" vendor_info = %x\n", dp->dpte. vendor_info);
+ printf(" irq = %x\n", dp->dpte. irq);
+ // printf(" irq_unused = %x\n", dp->dpte. irq_unused);
+ printf(" block_count = %x\n", dp->dpte. block_count);
+ printf(" dma_channe = %x\n", dp->dpte. dma_channel);
+ printf(" dma_type = %x\n", dp->dpte. dma_type);
+ printf(" pio_type = %x\n", dp->dpte. pio_type);
+ printf(" pio_unused = %x\n", dp->dpte. pio_unused);
+ printf(" option_flags = %x\n", dp->dpte.option_flags);
+ // printf(" reserved = %x\n", dp->dpte.reserved);
+ printf(" revision = %x\n", dp->dpte. revision);
+ // printf(" checksum = %x\n", dp->dpte. checksum);
+}
+
+#endif
- ret.ui = 0;
+int get_drive_info(int drive, struct driveInfo *dp)
+{
+ boot_drive_info_t *di = &dp->di;
+ int ret = 0;
+
+#if UNUSED
if (maxhd == 0) {
- bb.intno = 0x13;
- bb.eax.r.h = 0x08;
- bb.edx.r.l = 0x80;
- bios(&bb);
- if (bb.flags.cf == 0)
- maxhd = 0x7f + bb.edx.r.l;
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x08;
+ bb.edx.r.l = 0x80;
+ bios(&bb);
+ if (bb.flags.cf == 0)
+ maxhd = 0x7f + bb.edx.r.l;
};
if (drive > maxhd)
- return 0;
+ return 0;
+#endif
+
+ bzero(dp, sizeof(struct driveInfo));
+ dp->biosdev = drive;
+
+ /* Check for El Torito no-emulation mode. */
+ dp->no_emulation = is_no_emulation(drive);
/* Check drive for EBIOS support. */
bb.intno = 0x13;
bb.edx.r.l = drive;
bb.ebx.rr = 0x55aa;
bios(&bb);
- if(bb.ebx.rr == 0xaa55 && bb.flags.cf == 0) {
+ if((bb.ebx.rr == 0xaa55) && (bb.flags.cf == 0)) {
+ /* Get flags for supported operations. */
+ dp->uses_ebios = bb.ecx.r.l;
+ }
+ if (dp->uses_ebios & (EBIOS_ENHANCED_DRIVE_INFO | EBIOS_LOCKING_ACCESS | EBIOS_FIXED_DISK_ACCESS)) {
/* Get EBIOS drive info. */
- ebios.size = 26;
+ static struct drive_params params;
+
+ params.buf_size = sizeof(params);
bb.intno = 0x13;
bb.eax.r.h = 0x48;
bb.edx.r.l = drive;
- bb.esi.rr = ((unsigned)&ebios & 0xffff);
+ bb.esi.rr = OFFSET((unsigned)¶ms);
+ bb.ds = SEGMENT((unsigned)¶ms);
bios(&bb);
- if(bb.flags.cf == 0 && ebios.cylinders != 0) {
- useEbios = 1;
- }
+ if(bb.flags.cf != 0 /* || params.phys_sectors < 2097152 */) {
+ dp->uses_ebios = 0;
+ di->params.buf_size = 1;
+ } else {
+ bcopy(¶ms, &di->params, sizeof(params));
+
+ if (drive >= BASE_HD_DRIVE &&
+ (dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) &&
+ di->params.buf_size >= 30 &&
+ !(di->params.dpte_offset == 0xFFFF && di->params.dpte_segment == 0xFFFF)) {
+ void *ptr = (void *)(di->params.dpte_offset + ((unsigned int)di->params.dpte_segment << 4));
+ bcopy(ptr, &di->dpte, sizeof(di->dpte));
+ }
+ }
}
- bb.intno = 0x13;
- bb.eax.r.h = 0x08;
- bb.edx.r.l = drive;
- bios(&bb);
- if (bb.flags.cf == 0 && bb.eax.r.h == 0) {
- unsigned long cyl;
- unsigned long sec;
- unsigned long hds;
-
- hds = bb.edx.r.h;
- sec = bb.ecx.r.l & 0x3F;
- if(useEbios) {
- cyl = (ebios.total_sectors / ((hds + 1) * sec)) - 1;
- }
- else {
- cyl = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
- }
- ret.di.heads = hds;
- ret.di.sectors = sec;
- ret.di.cylinders = cyl;
+ if (di->params.phys_heads == 0 || di->params.phys_spt == 0) {
+ /* Either it's not EBIOS, or EBIOS didn't tell us. */
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x08;
+ bb.edx.r.l = drive;
+ bios(&bb);
+ if (bb.flags.cf == 0 && bb.eax.r.h == 0) {
+ unsigned long cyl;
+ unsigned long sec;
+ unsigned long hds;
+
+ hds = bb.edx.r.h;
+ sec = bb.ecx.r.l & 0x3F;
+ if((dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) && (sec != 0)) {
+ cyl = (di->params.phys_sectors / ((hds + 1) * sec)) - 1;
+ }
+ else {
+ cyl = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
+ }
+ di->params.phys_heads = hds;
+ di->params.phys_spt = sec;
+ di->params.phys_cyls = cyl;
+ } else {
+ ret = -1;
+ }
}
- if(drive >= 0x80) uses_ebios[drive - 0x80] = useEbios;
- return ret.ui;
+
+ if (dp->no_emulation) {
+ /* Some BIOSes give us erroneous EBIOS support information.
+ * Assume that if you're on a CD, then you can use
+ * EBIOS disk calls.
+ */
+ dp->uses_ebios |= EBIOS_FIXED_DISK_ACCESS;
+ }
+#if DEBUG
+ print_drive_info(di);
+ printf("uses_ebios = 0x%x\n", dp->uses_ebios);
+ printf("result %d\n", ret);
+ printf("press a key->\n");getc();
+#endif
+
+ if (ret == 0) {
+ dp->valid = 1;
+ }
+ return ret;
}
-void setCursorPosition(int x, int y)
+void setCursorPosition(int x, int y, int page)
{
bb.intno = 0x10;
bb.eax.r.h = 0x02;
- bb.ebx.r.h = 0x00; /* page 0 for graphics */
+ bb.ebx.r.h = page; /* page 0 for graphics */
bb.edx.r.l = x;
bb.edx.r.h = y;
bios(&bb);
}
+void setCursorType(int type)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 0x01;
+ bb.ecx.rr = type;
+ bios(&bb);
+}
+
+void getCursorPositionAndType(int * x, int * y, int * type)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 0x03;
+ bios(&bb);
+ *x = bb.edx.r.l;
+ *y = bb.edx.r.h;
+ *type = bb.ecx.rr;
+}
+
+void scollPage(int x1, int y1, int x2, int y2, int attr, int rows, int dir)
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = (dir > 0) ? 0x06 : 0x07;
+ bb.eax.r.l = rows;
+ bb.ebx.r.h = attr;
+ bb.ecx.r.h = y1;
+ bb.ecx.r.l = x1;
+ bb.edx.r.h = y2;
+ bb.edx.r.l = x2;
+ bios(&bb);
+}
+
+void clearScreenRows( int y1, int y2 )
+{
+ scollPage( 0, y1, 80 - 1, y2, 0x07, y2 - y1 + 1, 1 );
+}
+
+void setActiveDisplayPage( int page )
+{
+ bb.intno = 0x10;
+ bb.eax.r.h = 5;
+ bb.eax.r.l = page;
+ bios(&bb);
+}
+
#if DEBUG
+int terminateDiskEmulation()
+{
+ static char cd_spec[0x13];
+
+ bb.intno = 0x13;
+ bb.eax.r.h = 0x4b;
+ bb.eax.r.l = 0; // subfunc: terminate emulation
+ bb.esi.rr = OFFSET((unsigned)&cd_spec);
+ bb.ds = SEGMENT((unsigned)&cd_spec);
+ bios(&bb);
+ return bb.eax.r.h;
+}
+
int readDriveParameters(int drive, struct driveParameters *dp)
{
bb.intno = 0x13;
bb.eax.r.h = 0x08;
bios(&bb);
if (bb.eax.r.h == 0) {
- dp->heads = bb.edx.r.h;
- dp->sectors = bb.ecx.r.l & 0x3F;
- dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
- dp->totalDrives = bb.edx.r.l;
+ dp->heads = bb.edx.r.h;
+ dp->sectors = bb.ecx.r.l & 0x3F;
+ dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
+ dp->totalDrives = bb.edx.r.l;
} else {
- bzero(dp, sizeof(*dp));
+ bzero(dp, sizeof(*dp));
}
return bb.eax.r.h;
}
#endif
-#define APM_INTNO 0x15
-#define APM_INTCODE 0x53
+#ifdef APM_SUPPORT
+
+#define APM_INTNO 0x15
+#define APM_INTCODE 0x53
int
APMPresent(void)
{
- KERNBOOTSTRUCT *kbp = kernBootStruct;
-
bb.intno = APM_INTNO;
bb.eax.r.h = APM_INTCODE;
bb.eax.r.l = 0x00;
bb.ebx.rr = 0x0000;
bios(&bb);
if ((bb.flags.cf == 0) &&
- (bb.ebx.r.h == 'P') &&
- (bb.ebx.r.l == 'M')) {
- /* Success */
- kbp->apm_config.major_vers = bb.eax.r.h;
- kbp->apm_config.minor_vers = bb.eax.r.l;
- kbp->apm_config.flags.data = bb.ecx.rr;
- return 1;
+ (bb.ebx.r.h == 'P') &&
+ (bb.ebx.r.l == 'M')) {
+ /* Success */
+ bootArgs->apmConfig.major_vers = bb.eax.r.h;
+ bootArgs->apmConfig.minor_vers = bb.eax.r.l;
+ bootArgs->apmConfig.flags.data = bb.ecx.rr;
+ return 1;
}
return 0;
}
int
APMConnect32(void)
{
- KERNBOOTSTRUCT *kbp = kernBootStruct;
-
bb.intno = APM_INTNO;
bb.eax.r.h = APM_INTCODE;
bb.eax.r.l = 0x03;
bb.ebx.rr = 0x0000;
bios(&bb);
if (bb.flags.cf == 0) {
- /* Success */
- kbp->apm_config.cs32_base = (bb.eax.rr) << 4;
- kbp->apm_config.entry_offset = bb.ebx.rx;
- kbp->apm_config.cs16_base = (bb.ecx.rr) << 4;
- kbp->apm_config.ds_base = (bb.edx.rr) << 4;
- if (kbp->apm_config.major_vers >= 1 &&
- kbp->apm_config.minor_vers >= 1) {
- kbp->apm_config.cs_length = bb.esi.rr;
- kbp->apm_config.ds_length = bb.edi.rr;
- } else {
- kbp->apm_config.cs_length =
- kbp->apm_config.ds_length = 64 * 1024;
- }
- kbp->apm_config.connected = 1;
- return 1;
+ /* Success */
+ bootArgs->apmConfig.cs32_base = (bb.eax.rr) << 4;
+ bootArgs->apmConfig.entry_offset = bb.ebx.rx;
+ bootArgs->apmConfig.cs16_base = (bb.ecx.rr) << 4;
+ bootArgs->apmConfig.ds_base = (bb.edx.rr) << 4;
+ if (bootArgs->apmConfig.major_vers >= 1 &&
+ bootArgs->apmConfig.minor_vers >= 1) {
+ bootArgs->apmConfig.cs_length = bb.esi.rr;
+ bootArgs->apmConfig.ds_length = bb.edi.rr;
+ } else {
+ bootArgs->apmConfig.cs_length =
+ bootArgs->apmConfig.ds_length = 64 * 1024;
+ }
+ bootArgs->apmConfig.connected = 1;
+ return 1;
}
return 0;
}
-#ifdef EISA_SUPPORT // turn off for now since there isn't enough room
+#endif /* APM_SUPPORT */
+
+#ifdef EISA_SUPPORT
BOOL
eisa_present(
void
)
{
- static BOOL checked;
- static BOOL isEISA;
+ static BOOL checked;
+ static BOOL isEISA;
if (!checked) {
- if (strncmp((char *)0xfffd9, "EISA", 4) == 0)
- isEISA = TRUE;
-
- checked = TRUE;
+ if (strncmp((char *)0xfffd9, "EISA", 4) == 0)
+ isEISA = TRUE;
+
+ checked = TRUE;
}
return (isEISA);
ReadEISASlotInfo(EISA_slot_info_t *ep, int slot)
{
union {
- struct {
- unsigned char char2h :2;
- unsigned char char1 :5;
- unsigned char char3 :5;
- unsigned char char2l :3;
- unsigned char d2 :4;
- unsigned char d1 :4;
- unsigned char d4 :4;
- unsigned char d3 :4;
- } s;
- unsigned char data[4];
+ struct {
+ unsigned char char2h :2;
+ unsigned char char1 :5;
+ unsigned char char3 :5;
+ unsigned char char2l :3;
+ unsigned char d2 :4;
+ unsigned char d1 :4;
+ unsigned char d4 :4;
+ unsigned char d3 :4;
+ } s;
+ unsigned char data[4];
} u;
static char hex[0x10] = "0123456789ABCDEF";
-
+
bb.intno = 0x15;
bb.eax.r.h = 0xd8;
bb.ecx.r.l = slot;
bios(&bb);
if (bb.flags.cf)
- return bb.eax.r.h;
+ return bb.eax.r.h;
ep->u_ID.d = bb.eax.r.l;
ep->configMajor = bb.ebx.r.h;
ep->configMinor = bb.ebx.r.l;
bb.esi.rr = (unsigned int)ep->data;
bios(&bb);
if (bb.eax.r.h == 0) {
- ep->slot = slot;
- ep->function = function;
+ ep->slot = slot;
+ ep->function = function;
}
return bb.eax.r.h;
}
-#endif
+#endif /* EISA_SUPPORT */
#define PCI_SIGNATURE 0x20494350 /* "PCI " */
bb.eax.r.l = 0x01;
bios(&bb);
if ((bb.eax.r.h == 0) && (bb.edx.rx == PCI_SIGNATURE)) {
- pp->BIOSPresent = 1;
- pp->u_bus.d = bb.eax.r.l;
- pp->majorVersion = bb.ebx.r.h;
- pp->minorVersion = bb.ebx.r.l;
- pp->maxBusNum = bb.ecx.r.l;
- return 0;
+ pp->BIOSPresent = 1;
+ pp->u_bus.d = bb.eax.r.l;
+ pp->majorVersion = bb.ebx.r.h;
+ pp->minorVersion = bb.ebx.r.l;
+ pp->maxBusNum = bb.ecx.r.l;
+ return 0;
}
return -1;
}
+
+void sleep(int n)
+{
+ unsigned int endtime = (time18() + 18*n);
+ while (time18() < endtime);
+}
+
+void delay(int ms)
+{
+ bb.intno = 0x15;
+ bb.eax.r.h = 0x86;
+ bb.ecx.rr = ms >> 16;
+ bb.edx.rr = ms & 0xFFFF;
+ bios(&bb);
+}
+