Chameleon

Chameleon Svn Source Tree

Root/tags/2.3/i386/libsaio/biosfn.c

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

Archive Download this file

Revision: 2862