Chameleon

Chameleon Svn Source Tree

Root/branches/zenith432/i386/libsaio/biosfn.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 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 2.0 (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/* Copyright 2007 David Elliott
30 2007-12-30 dfe
31 - Enhanced code to normalize segment/offset to huge pointers so that any
32 linear address within the first MB of memory can be passed to BIOS
33 functions. This allows some of the __DATA sections to span into the
34 next segment and also allows stack variables to be used whereas the
35 old code could only operate on static data in the first 64k.
36 NOTE: Requires bios.s change to respect DS.
37 */
38/* Copyright 2007 VMware Inc.
39 2007-12-29 dfe
40 - Added ebiosEjectMedia
41 */
42
43#include "bootstruct.h"
44#include "libsaio.h"
45
46
47#ifndef MEMRANGE
48#define MEMRANGE 0
49#endif
50
51#if MEMRANGE
52#define DBG(x...)printf(x)
53#else
54#define DBG(x...)msglog(x)
55#endif
56
57#define MAX_DRIVES 8
58
59static biosBuf_t bb;
60
61
62//==============================================================================
63
64int bgetc(void)
65{
66#if 0
67/* Poll for the next character. Most real BIOS do not need this as the
68 INT 16h,AH=0h function will block until one is received.
69 Unfortunately, Apple's EFI CSM will never wake up. This idea is lifted
70 from the grub-a20.patch to GRUB's stage2/asm.S file.
71*/
72while(!readKeyboardStatus());
73// Apple's EFI CSM???? Who cares - Zenith432
74#endif
75
76bb.intno = 0x16;
77bb.eax.r.h = 0x00;
78bios(&bb);
79
80return bb.eax.rr;
81}
82
83
84//==============================================================================
85
86int readKeyboardStatus(void)
87{
88bb.intno = 0x16;
89bb.eax.r.h = 0x01;
90bios(&bb);
91
92if (bb.flags.zf) {
93return 0;
94} else {
95return bb.eax.rr;
96}
97}
98
99int readKeyboardShiftFlags(void)
100{
101#if 0
102bb.intno = 0x16;
103bb.eax.r.h = 0x02;
104bios(&bb);
105return bb.eax.r.l;
106#else
107return *(uint8_t const volatile*) 0x417U;
108#endif
109}
110
111
112//==============================================================================
113
114unsigned int time18(void)
115{
116#if 0
117union {
118struct {
119unsigned int low:16;
120unsigned int high:16;
121} s;
122
123unsigned int i;
124} time;
125
126bb.intno = 0x1a;
127bb.eax.r.h = 0x00;
128bios(&bb);
129time.s.low = bb.edx.rr;
130time.s.high = bb.ecx.rr;
131
132return time.i;
133#else
134(void) __sync_lock_test_and_set((uint8_t volatile*) 0x470U, (uint8_t) 0U);
135return *(uint32_t const volatile*) 0x46CU;
136#endif
137}
138
139#if MEMRANGE
140
141static unsigned long rerangeMemoryMap(unsigned long count);
142static unsigned long rerangeMemoryMap(unsigned long count)
143{
144int i, still_changing, newcount = count;
145
146MemoryRange * range = (MemoryRange *)BIOS_ADDR;
147struct MemoryRange change_tmp;
148
149/* sort map list by memory addresses (low -> high) */
150still_changing = 1;
151while (still_changing) {
152still_changing = 0;
153for (i=1; i<count; i++) {
154/* if <current_addr> > <last_addr>, swap */
155if (range[i].base < range[i-1].base) {
156change_tmp.base = range[i].base;
157change_tmp.length = range[i].length;
158change_tmp.type = range[i].type;
159
160range[i].base = range[i-1].base;
161range[i].length = range[i-1].length;
162range[i].type = range[i-1].type;
163
164range[i-1].base = change_tmp.base;
165range[i-1].length = change_tmp.length;
166range[i-1].type = change_tmp.type;
167
168still_changing=1;
169}
170}
171}
172
173/* clear overlaps */
174/* linux's arch/i386/kern/setup.c may have better algorithm */
175for (i=1; i<count; i++) {
176if ( range[i-1].base + range[i-1].length > range[i].base ) {
177range[newcount].base = range[i].base + range[i].length;
178range[newcount].length = range[i-1].base + range[i-1].length - range[newcount].base;
179range[newcount].type = range[i-1].type;
180newcount++;
181
182range[i-1].length = range[i].base - range[i-1].base;
183}
184}
185
186/*
187 * 0xb0000000 : 0x10000000 NG
188 * 0xc0000400 NG
189 * 0xf2000000 NG
190 */
191range[newcount].base = 0xb0000000;
192range[newcount].length = 0x0f000000;
193range[newcount].type = kMemoryRangeUsable;
194newcount++;
195
196return newcount;
197}
198#endif
199
200unsigned long getMemoryMap( MemoryRange * rangeArray,
201 unsigned long maxRangeCount,
202 unsigned long * conMemSizePtr,
203 unsigned long * extMemSizePtr )
204{
205#define kMemoryMapSignature 'SMAP'
206#define kDescriptorSizeMin 20
207
208MemoryRange *range = (MemoryRange *)BIOS_ADDR;
209unsigned longcount = 0;
210#if MEMRANGE
211unsigned longrerangedCount;
212#endif
213unsigned long longconMemSize = 0;
214unsigned long longextMemSize = 0;
215
216// Prepare for the INT15 E820h call. Each call returns a single
217// memory range. A continuation value is returned that must be
218// provided on a subsequent call to fetch the next range.
219//
220// Certain BIOSes (Award 6.00PG) expect the upper word in EAX
221// to be cleared on entry, otherwise only a single range will
222// be reported.
223//
224// Some BIOSes will simply ignore the value of ECX on entry.
225// Probably best to keep its value at 20 to avoid surprises.
226
227//printf("Get memory map 0x%x, %d\n", rangeArray); getchar();
228if (maxRangeCount > (BIOS_LEN / sizeof(MemoryRange))) {
229maxRangeCount = (BIOS_LEN / sizeof(MemoryRange));
230}
231bb.ebx.rx = 0; // Initial continuation value must be zero.
232
233while (count < maxRangeCount)
234{
235bb.intno = 0x15;
236bb.eax.rx = 0xe820;
237bb.ecx.rx = kDescriptorSizeMin;
238bb.edx.rx = kMemoryMapSignature;
239bb.edi.rr = NORMALIZED_OFFSET( (unsigned long) range );
240bb.es = NORMALIZED_SEGMENT( (unsigned long) range );
241bios(&bb);
242
243// Check for errors.
244
245if ( bb.flags.cf || bb.eax.rx != kMemoryMapSignature || bb.ecx.rx != kDescriptorSizeMin )
246{
247//printf("Got an error %x %x %x\n", bb.flags.cf,
248// bb.eax.rx, bb.ecx.rx);
249break;
250}
251
252// Tally up the conventional/extended memory sizes.
253
254if ( range->type == kMemoryRangeUsable || range->type == kMemoryRangeACPI || range->type == kMemoryRangeNVS ) {
255// Tally the conventional memory ranges.
256if ( range->base + range->length <= 0xa0000 )
257{
258conMemSize += range->length;
259}
260
261// Record the top of extended memory.
262if (range->base >= EXTENDED_ADDR)
263{
264extMemSize += range->length;
265}
266}
267
268range++;
269count++;
270
271// Is this the last address range?
272
273if ( bb.ebx.rx == 0 )
274{
275//printf("last range\n");
276break;
277}
278}
279
280*conMemSizePtr = (conMemSize / 1024); // size in KB
281*extMemSizePtr = (extMemSize / 1024); // size in KB
282
283#if MEMRANGE
284rerangedCount = rerangeMemoryMap(count);
285range += rerangedCount - count;
286#endif
287
288// Copy out data
289bcopy((char *)BIOS_ADDR, rangeArray, ((char *)range - (char *)BIOS_ADDR));
290
291#if DEBUG
292{
293int i;
294 printf("%d total ranges\n", count);
295
296getchar();
297
298for (i = 0, range = rangeArray; i<count; i++, range++)
299{
300printf("range: type %d, base 0x%x, length 0x%x\n",
301range->type, (unsigned int)range->base, (unsigned int)range->length);
302getchar();
303}
304}
305#endif
306
307return count;
308}
309
310
311//==============================================================================
312
313
314unsigned long getExtendedMemorySize()
315{
316// Get extended memory size for large configurations. Not used unless
317// the INT15, E820H call (Get System Address Map) failed.
318//
319// Input:
320//
321// AX Function Code E801h
322//
323// Outputs:
324//
325// CF Carry Flag Carry cleared indicates no error.
326// AX Extended 1 Number of contiguous KB between 1 and 16 MB,
327// maximum 0x3C00 = 15 MB.
328// BX Extended 2 Number of contiguous 64 KB blocks between
329// 16 MB and 4 GB.
330// CX Configured 1 Number of contiguous KB between 1 and 16 MB,
331// maximum 0x3C00 = 15 MB.
332// DX Configured 2 Number of contiguous 64 KB blocks between
333// 16 MB and 4 GB.
334
335bb.intno = 0x15;
336bb.eax.rx = 0xe801;
337bios(&bb);
338
339// Return the size of memory above 1MB (extended memory) in kilobytes.
340
341if (bb.flags.cf == 0)
342{
343return (bb.ebx.rr * 64 + bb.eax.rr);
344}
345
346// Get Extended memory size. Called on last resort since the return
347// value is limited to 16-bits (a little less than 64MB max). May
348// not be supported by modern BIOSes.
349//
350// Input:
351//
352// AX Function Code E801h
353//
354// Outputs:
355//
356// CF Carry Flag Carry cleared indicates no error.
357// AX Memory Count Number of contiguous KB above 1MB.
358
359bb.intno = 0x15;
360bb.eax.rx = 0x88;
361bios(&bb);
362
363// Return the size of memory above 1MB (extended memory) in kilobytes.
364
365return bb.flags.cf ? 0 : bb.eax.rr;
366}
367
368
369//==============================================================================
370
371
372unsigned long getConventionalMemorySize()
373{
374bb.intno = 0x12;
375bios(&bb);
376
377return bb.eax.rr; // kilobytes
378}
379
380
381//==============================================================================
382
383
384void video_mode(int mode)
385{
386bb.intno = 0x10;
387bb.eax.r.h = 0x00;
388bb.eax.r.l = mode;
389bios(&bb);
390}
391
392
393//==============================================================================
394
395int biosread(int dev, int cyl, int head, int sec, int num)
396{
397int i;
398
399bb.intno = 0x13;
400sec += 1; // sector numbers start at 1.
401
402for (i = 0; ;)
403{
404bb.ecx.r.h = cyl;
405bb.ecx.r.l = ((cyl & 0x300) >> 2) | (sec & 0x3F);
406bb.edx.r.h = head;
407bb.edx.r.l = dev;
408bb.eax.r.l = num;
409bb.ebx.rr = OFFSET(ptov(BIOS_ADDR));
410bb.es = SEGMENT(ptov(BIOS_ADDR));
411
412bb.eax.r.h = 0x02;
413bios(&bb);
414
415// In case of a successful call, make sure we set AH (return code) to zero.
416if (bb.flags.cf == 0)
417{
418bb.eax.r.h = 0;
419}
420
421// Now we can really check for the return code (AH) value.
422if ((bb.eax.r.h == 0x00) || (i++ >= 5))
423{
424break;
425}
426
427 // Reset disk subsystem and try again.
428bb.eax.r.h = 0x00;
429bios(&bb);
430}
431
432return bb.eax.r.h;
433}
434
435
436//==============================================================================
437
438int ebiosread(int dev, unsigned long long sec, int count)
439{
440int i;
441
442static struct
443{
444unsigned char size;
445unsigned char reserved;
446unsigned char numblocks;
447unsigned char reserved2;
448unsigned short bufferOffset;
449unsigned short bufferSegment;
450unsigned long long startblock;
451} addrpacket __attribute__((aligned(16))) = {0};
452addrpacket.size = sizeof(addrpacket);
453
454for (i = 0; ;)
455{
456bb.intno = 0x13;
457bb.eax.r.h = 0x42;
458bb.edx.r.l = dev;
459bb.esi.rr = NORMALIZED_OFFSET((unsigned)&addrpacket);
460bb.ds = NORMALIZED_SEGMENT((unsigned)&addrpacket);
461addrpacket.reserved = addrpacket.reserved2 = 0;
462addrpacket.numblocks = count;
463addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
464addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
465addrpacket.startblock = sec;
466bios(&bb);
467
468// In case of a successful call, make sure we set AH (return code) to zero.
469if (bb.flags.cf == 0)
470{
471bb.eax.r.h = 0;
472}
473
474// Now we can really check for the return code (AH) value.
475if ((bb.eax.r.h == 0x00) || (i++ >= 5))
476{
477break;
478}
479
480// Reset disk subsystem and try again.
481bb.eax.r.h = 0x00;
482bios(&bb);
483}
484
485return bb.eax.r.h;
486}
487
488//==============================================================================
489
490int ebioswrite(int dev, long sec, int count)
491{
492int i;
493static struct {
494unsigned char size;
495unsigned char reserved;
496unsigned char numblocks;
497unsigned char reserved2;
498unsigned short bufferOffset;
499unsigned short bufferSegment;
500unsigned long long startblock;
501} addrpacket __attribute__((aligned(16))) = {0};
502addrpacket.size = sizeof(addrpacket);
503
504for (i=0;;) {
505bb.intno = 0x13;
506bb.eax.r.l = 0; /* Don't verify */
507bb.eax.r.h = 0x43;
508bb.edx.r.l = dev;
509bb.esi.rr = NORMALIZED_OFFSET((unsigned)&addrpacket);
510bb.ds = NORMALIZED_SEGMENT((unsigned)&addrpacket);
511addrpacket.reserved = addrpacket.reserved2 = 0;
512addrpacket.numblocks = count;
513addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
514addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
515addrpacket.startblock = sec;
516bios(&bb);
517
518/* In case of a successful call, make sure we set AH (return code) to zero. */
519if (bb.flags.cf == 0)
520bb.eax.r.h = 0;
521
522/* Now we can really check for the return code (AH) value. */
523if ((bb.eax.r.h == 0x00) || (i++ >= 5))
524break;
525
526/* reset disk subsystem and try again */
527bb.eax.r.h = 0x00;
528bios(&bb);
529}
530return bb.eax.r.h;
531}
532
533void bios_putchar(int ch)
534{
535bb.intno= 0x10;
536bb.ebx.r.h= 0x00; /* background black */
537bb.ebx.r.l= 0x0F; /* foreground white */
538bb.eax.r.h= 0x0e;
539bb.eax.r.l= ch;
540bios(&bb);
541}
542
543
544//==============================================================================
545
546void putca(int ch, int attr, int repeat)
547{
548bb.intno = 0x10;
549bb.ebx.r.h = 0x00; /* page number */
550bb.ebx.r.l = attr; /* attribute */
551bb.eax.r.h = 0x9;
552bb.eax.r.l = ch;
553bb.ecx.rx = repeat; /* repeat count */
554bios(&bb);
555}
556
557
558//==============================================================================
559// Check to see if the passed-in drive is in El Torito no-emulation mode.
560
561int is_no_emulation(int drive)
562{
563struct packet
564{
565unsigned char packet_size;
566unsigned char media_type;
567unsigned char drive_num;
568unsigned char ctrlr_index;
569unsigned long lba;
570unsigned short device_spec;
571unsigned short buffer_segment;
572unsigned short load_segment;
573unsigned short sector_count;
574unsigned char cyl_count;
575unsigned char sec_count;
576unsigned char head_count;
577unsigned char reseved;
578} __attribute__((packed));
579static struct packet pkt;
580
581bzero(&pkt, sizeof(pkt));
582pkt.packet_size = 0x13;
583
584bb.intno = 0x13;
585bb.eax.r.h = 0x4b;
586bb.eax.r.l = 0x01; // subfunc: get info
587bb.edx.r.l = drive;
588bb.esi.rr = NORMALIZED_OFFSET((unsigned)&pkt);
589bb.ds = NORMALIZED_SEGMENT((unsigned)&pkt);
590
591bios(&bb);
592
593#if DEBUG
594printf("el_torito info drive %x\n", drive);
595printf("--> cf %x, eax %x\n", bb.flags.cf, bb.eax.rr);
596printf("pkt_size: %x\n", pkt.packet_size);
597printf("media_type: %x\n", pkt.media_type);
598printf("drive_num: %x\n", pkt.drive_num);
599printf("device_spec: %x\n", pkt.device_spec);
600
601pause();
602#endif
603
604/* Some BIOSes erroneously return cf = 1 */
605/* Just check to see if the drive number is the same. */
606if (pkt.drive_num == drive && (pkt.media_type & 0x0F) == 0)
607{
608return 1; // We are in no-emulation mode.
609}
610
611return 0;
612}
613
614#if DEBUG
615/*
616 * BIOS drive information.
617 */
618static void print_drive_info(boot_drive_info_t *dp)
619{
620//printf("buf_size = %x\n", dp->params.buf_size);
621printf("info_flags = %x\n", dp->params.info_flags);
622printf("phys_cyls = %lx\n", dp->params. phys_cyls);
623printf("phys_heads = %lx\n", dp->params. phys_heads);
624printf("phys_spt = %lx\n", dp->params. phys_spt);
625printf("phys_sectors = %lx%lx\n", ((unsigned long *)(&dp->params.phys_sectors))[1],
626 ((unsigned long *)(&dp->params.phys_sectors))[0]);
627printf("phys_nbps = %x\n", dp->params.phys_nbps);
628//printf("dpte_offset = %x\n", dp->params.dpte_offset);
629//printf("dpte_segment = %x\n", dp->params.dpte_segment);
630//printf("key = %x\n", dp->params.key);
631//printf("path_len = %x\n", dp->params. path_len);
632//printf("reserved1 = %x\n", dp->params. reserved1);
633//printf("reserved2 = %x\n", dp->params.reserved2);
634//printf("bus_type[4] = %x\n", dp->params. bus_type[4]);
635//printf("interface_type[8] = %x\n", dp->params. interface_type[8]);
636//printf("interface_path[8] = %x\n", dp->params. interface_path[8]);
637//printf("dev_path[16] = %x\n", dp->params. dev_path[16]);
638//printf("reserved3 = %x\n", dp->params. reserved3);
639//printf("checksum = %x\n", dp->params. checksum);
640printf("io_port_base = %x\n", dp->dpte.io_port_base);
641printf("control_port_base = %x\n", dp->dpte.control_port_base);
642printf("head_flags = %x\n", dp->dpte. head_flags);
643printf("vendor_info = %x\n", dp->dpte. vendor_info);
644printf("irq = %x\n", dp->dpte. irq);
645//printf("irq_unused = %x\n", dp->dpte. irq_unused);
646printf("block_count = %x\n", dp->dpte. block_count);
647printf("dma_channe = %x\n", dp->dpte. dma_channel);
648printf("dma_type = %x\n", dp->dpte. dma_type);
649printf("pio_type = %x\n", dp->dpte. pio_type);
650printf("pio_unused = %x\n", dp->dpte. pio_unused);
651printf("option_flags = %x\n", dp->dpte.option_flags);
652//printf("reserved = %x\n", dp->dpte.reserved);
653printf("revision = %x\n", dp->dpte. revision);
654//printf("checksum = %x\n", dp->dpte. checksum);
655}
656
657#endif
658
659//==============================================================================
660
661int get_drive_info(int drive, struct driveInfo *dp)
662{
663int ret = 0;
664
665boot_drive_info_t *di = &dp->di;
666
667#if UNUSED
668if (maxhd == 0) {
669bb.intno = 0x13;
670bb.eax.r.h = 0x08;
671bb.edx.r.l = 0x80;
672bios(&bb);
673
674if (bb.flags.cf == 0) {
675maxhd = 0x7f + bb.edx.r.l;
676}
677};
678
679if (drive > maxhd) {
680return 0;
681}
682#endif
683
684bzero(dp, sizeof(struct driveInfo));
685dp->biosdev = drive;
686
687/* Check for El Torito no-emulation mode. */
688dp->no_emulation = is_no_emulation(drive);
689
690/* Check drive for EBIOS support. */
691bb.intno = 0x13;
692bb.eax.r.h = 0x41;
693bb.edx.r.l = drive;
694bb.ebx.rr = 0x55aa;
695bios(&bb);
696
697if ((bb.ebx.rr == 0xaa55) && (bb.flags.cf == 0))
698{
699/* Get flags for supported operations. */
700dp->uses_ebios = bb.ecx.r.l;
701}
702
703if (dp->uses_ebios & (EBIOS_ENHANCED_DRIVE_INFO | EBIOS_LOCKING_ACCESS | EBIOS_FIXED_DISK_ACCESS))
704{
705/* Get EBIOS drive info. */
706static struct drive_params params;
707
708params.buf_size = sizeof(params);
709bb.intno = 0x13;
710bb.eax.r.h = 0x48;
711bb.edx.r.l = drive;
712bb.esi.rr = NORMALIZED_OFFSET((unsigned)&params);
713bb.ds = NORMALIZED_SEGMENT((unsigned)&params);
714bios(&bb);
715
716if (bb.flags.cf != 0 /* || params.phys_sectors < 2097152 */)
717{
718dp->uses_ebios = 0;
719di->params.buf_size = 1;
720}
721else
722{
723bcopy(&params, &di->params, sizeof(params));
724
725if (drive >= BASE_HD_DRIVE &&
726(dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) &&
727di->params.buf_size >= 30 &&
728!(di->params.dpte_offset == 0xFFFF && di->params.dpte_segment == 0xFFFF))
729{
730void *ptr = (void *)(di->params.dpte_offset + ((unsigned int)di->params.dpte_segment << 4));
731bcopy(ptr, &di->dpte, sizeof(di->dpte));
732}
733}
734}
735
736/*
737 * zef: This code will fail on recent JMicron and Intel option ROMs
738 */
739//if (di->params.phys_heads == 0 || di->params.phys_spt == 0) {
740///* Either it's not EBIOS, or EBIOS didn't tell us. */
741//bb.intno = 0x13;
742//bb.eax.r.h = 0x08;
743//bb.edx.r.l = drive;
744//bios(&bb);
745//if (bb.flags.cf == 0 && bb.eax.r.h == 0) {
746//unsigned long cyl;
747//unsigned long sec;
748//unsigned long hds;
749//
750//hds = bb.edx.r.h;
751//sec = bb.ecx.r.l & 0x3F;
752//if ((dp->uses_ebios & EBIOS_ENHANCED_DRIVE_INFO) && (sec != 0)) {
753//cyl = (di->params.phys_sectors / ((hds + 1) * sec)) - 1;
754//} else {
755//cyl = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
756//}
757//di->params.phys_heads = hds;
758//di->params.phys_spt = sec;
759//di->params.phys_cyls = cyl;
760//} else {
761//ret = -1;
762//}
763//}
764
765if (dp->no_emulation)
766{
767/* Some BIOSes give us erroneous EBIOS support information.
768 * Assume that if you're on a CD, then you can use
769 * EBIOS disk calls.
770 */
771dp->uses_ebios |= EBIOS_FIXED_DISK_ACCESS;
772}
773#if DEBUG
774print_drive_info(di);
775printf("uses_ebios = 0x%x\n", dp->uses_ebios);
776printf("result %d\n", ret);
777pause();
778#endif
779
780if (ret == 0)
781{
782dp->valid = 1;
783}
784return ret;
785}
786
787//==============================================================================
788
789#if UNUSED
790int ebiosEjectMedia(int biosdev)
791{
792bb.intno = 0x13;
793bb.eax.r.h = 0x46;
794bb.eax.r.l = 0;
795bb.edx.rx = biosdev;
796bios(&bb);
797return bb.eax.r.h;
798}
799#endif
800
801void setCursorPosition(int x, int y, int page)
802{
803bb.intno = 0x10;
804bb.eax.r.h = 0x02;
805bb.ebx.r.h = page; /* page 0 for graphics */
806bb.edx.r.l = x;
807bb.edx.r.h = y;
808bios(&bb);
809}
810
811void setCursorType(int type)
812{
813bb.intno = 0x10;
814bb.eax.r.h = 0x01;
815bb.ecx.rr = type;
816bios(&bb);
817}
818
819void getCursorPositionAndType(int * x, int * y, int * type)
820{
821bb.intno = 0x10;
822bb.eax.r.h = 0x03;
823bios(&bb);
824*x = bb.edx.r.l;
825*y = bb.edx.r.h;
826*type = bb.ecx.rr;
827}
828
829void scollPage(int x1, int y1, int x2, int y2, int attr, int rows, int dir)
830{
831bb.intno = 0x10;
832bb.eax.r.h = (dir > 0) ? 0x06 : 0x07;
833bb.eax.r.l = rows;
834bb.ebx.r.h = attr;
835bb.ecx.r.h = y1;
836bb.ecx.r.l = x1;
837bb.edx.r.h = y2;
838bb.edx.r.l = x2;
839bios(&bb);
840}
841
842void clearScreenRows( int y1, int y2 )
843{
844scollPage( 0, y1, 80 - 1, y2, 0x07, y2 - y1 + 1, 1 );
845}
846
847void setActiveDisplayPage( int page )
848{
849bb.intno = 0x10;
850bb.eax.r.h = 5;
851bb.eax.r.l = page;
852bios(&bb);
853}
854
855#if DEBUG
856
857static int terminateDiskEmulation()
858{
859static char cd_spec[0x13];
860
861bb.intno = 0x13;
862bb.eax.r.h = 0x4b;
863bb.eax.r.l = 0; // subfunc: terminate emulation
864bb.esi.rr = NORMALIZED_OFFSET((unsigned)&cd_spec);
865bb.ds = NORMALIZED_SEGMENT((unsigned)&cd_spec);
866bios(&bb);
867return bb.eax.r.h;
868}
869
870static int readDriveParameters(int drive, struct driveParameters *dp)
871{
872bb.intno = 0x13;
873bb.edx.r.l = drive;
874bb.eax.r.h = 0x08;
875bios(&bb);
876if (bb.eax.r.h == 0) {
877dp->heads = bb.edx.r.h;
878dp->sectors = bb.ecx.r.l & 0x3F;
879dp->cylinders = bb.ecx.r.h | ((bb.ecx.r.l & 0xC0) << 2);
880dp->totalDrives = bb.edx.r.l;
881} else {
882bzero(dp, sizeof(*dp));
883}
884return bb.eax.r.h;
885}
886#endif
887
888#ifdef APM_SUPPORT
889
890#define APM_INTNO 0x15
891#define APM_INTCODE 0x53
892
893int
894APMPresent(void)
895{
896bb.intno = APM_INTNO;
897bb.eax.r.h = APM_INTCODE;
898bb.eax.r.l = 0x00;
899bb.ebx.rr = 0x0000;
900bios(&bb);
901if ((bb.flags.cf == 0) && (bb.ebx.r.h == 'P') && (bb.ebx.r.l == 'M')) {
902/* Success */
903bootArgs->apmConfig.major_vers = bb.eax.r.h;
904bootArgs->apmConfig.minor_vers = bb.eax.r.l;
905bootArgs->apmConfig.flags.data = bb.ecx.rr;
906return 1;
907}
908return 0;
909}
910
911int
912APMConnect32(void)
913{
914bb.intno = APM_INTNO;
915bb.eax.r.h = APM_INTCODE;
916bb.eax.r.l = 0x03;
917bb.ebx.rr = 0x0000;
918bios(&bb);
919if (bb.flags.cf == 0) {
920/* Success */
921bootArgs->apmConfig.cs32_base = (bb.eax.rr) << 4;
922bootArgs->apmConfig.entry_offset = bb.ebx.rx;
923bootArgs->apmConfig.cs16_base = (bb.ecx.rr) << 4;
924bootArgs->apmConfig.ds_base = (bb.edx.rr) << 4;
925if (bootArgs->apmConfig.major_vers >= 1 && bootArgs->apmConfig.minor_vers >= 1) {
926bootArgs->apmConfig.cs_length = bb.esi.rr;
927bootArgs->apmConfig.ds_length = bb.edi.rr;
928} else {
929bootArgs->apmConfig.cs_length =
930bootArgs->apmConfig.ds_length = 64 * 1024;
931}
932bootArgs->apmConfig.connected = 1;
933return 1;
934}
935return 0;
936}
937
938#endif /* APM_SUPPORT */
939
940#ifdef EISA_SUPPORT
941bool eisa_present(void)
942{
943static bool checked = false;
944static bool isEISA;
945
946if (!checked) {
947if (strncmp((char *)0xfffd9, "EISA", 4) == 0) {
948isEISA = true;
949}
950checked = true;
951}
952return (isEISA);
953}
954
955int
956ReadEISASlotInfo(EISA_slot_info_t *ep, int slot)
957{
958union
959{
960struct
961{
962unsigned char char2h :2;
963unsigned char char1 :5;
964unsigned char char3 :5;
965unsigned char char2l :3;
966unsigned char d2 :4;
967unsigned char d1 :4;
968unsigned char d4 :4;
969unsigned char d3 :4;
970} s;
971unsigned char data[4];
972} u;
973static char hex[0x10] = "0123456789ABCDEF";
974
975
976bb.intno = 0x15;
977bb.eax.r.h = 0xd8;
978bb.eax.r.l = 0x00;
979bb.ecx.r.l = slot;
980bios(&bb);
981if (bb.flags.cf)
982return bb.eax.r.h;
983ep->u_ID.d = bb.eax.r.l;
984ep->configMajor = bb.ebx.r.h;
985ep->configMinor = bb.ebx.r.l;
986ep->checksum = bb.ecx.rr;
987ep->numFunctions = bb.edx.r.h;
988ep->u_resources.d = bb.edx.r.l;
989u.data[0] = bb.edi.r.l;
990u.data[1] = bb.edi.r.h;
991u.data[2] = bb.esi.r.l;
992u.data[3] = bb.esi.r.h;
993ep->id[0] = u.s.char1 + ('A' - 1);
994ep->id[1] = (u.s.char2l | (u.s.char2h << 3)) + ('A' - 1);
995ep->id[2] = u.s.char3 + ('A' - 1);
996ep->id[3] = hex[u.s.d1];
997ep->id[4] = hex[u.s.d2];
998ep->id[5] = hex[u.s.d3];
999ep->id[6] = hex[u.s.d4];
1000ep->id[7] = 0;
1001return 0;
1002}
1003
1004/*
1005 * Note: ep must point to an address below 64k.
1006 */
1007
1008int
1009ReadEISAFuncInfo(EISA_func_info_t *ep, int slot, int function)
1010{
1011bb.intno = 0x15;
1012bb.eax.r.h = 0xd8;
1013bb.eax.r.l = 0x01;
1014bb.ecx.r.l = slot;
1015bb.ecx.r.h = function;
1016bb.esi.rr = (unsigned int)ep->data;
1017bios(&bb);
1018if (bb.eax.r.h == 0)
1019{
1020ep->slot = slot;
1021ep->function = function;
1022}
1023return bb.eax.r.h;
1024}
1025#endif /* EISA_SUPPORT */
1026
1027#if UNUSED
1028#define PCI_SIGNATURE 0x20494350 /* "PCI " */
1029
1030int
1031ReadPCIBusInfo(PCI_bus_info_t *pp)
1032{
1033bb.intno = 0x1a;
1034bb.eax.r.h = 0xb1;
1035bb.eax.r.l = 0x01;
1036bios(&bb);
1037if ((bb.eax.r.h == 0) && (bb.edx.rx == PCI_SIGNATURE))
1038{
1039pp->BIOSPresent = 1;
1040pp->u_bus.d = bb.eax.r.l;
1041pp->majorVersion = bb.ebx.r.h;
1042pp->minorVersion = bb.ebx.r.l;
1043pp->maxBusNum = bb.ecx.r.l;
1044return 0;
1045}
1046return -1;
1047}
1048#endif
1049
1050void sleep(int n)
1051{
1052while (n >= 2048)
1053{
1054delay(2048000000);
1055n -= 2048;
1056}
1057if (n > 0)
1058{
1059delay(n * 1000000);
1060}
1061}
1062
1063
1064//==============================================================================
1065
1066void delay(int us)
1067{
1068 bb.intno = 0x15;
1069 bb.eax.r.h = 0x86;
1070 bb.ecx.rr = us >> 16;
1071 bb.edx.rr = us & 0xFFFF;
1072 bios(&bb);
1073}
1074/* // reverted from commit 2602
1075void enableA20(void)
1076{
1077 bzero(&bb, sizeof bb); // Note: may be called before BSS section is initialized
1078 bb.intno = 0x15;
1079 bb.eax.rr = 0x2401;
1080 bios(&bb);
1081}
1082*/
1083

Archive Download this file

Revision: 2805